dsh-followup-todo
给「你」用的待办清单,不是给 agent 用的。每条待办自带一份跨会话交接说明,让新开的对话不用回翻旧聊天就能直接开工。
DeepSeek Harness(dsh)插件。宿主端注册 4 个模型工具 + HTTP 接口,浏览器端在会话头部加一个待办按钮、一个悬浮面板,以及输入框上方的一条待办卡片带。
它和内置 todo_write 有什么区别
这是最容易混淆的一点,也是这个插件存在的理由:
内置 todo_write |
dsh-followup-todo |
|
|---|---|---|
| 清单属于谁 | agent 自己 | 你 |
| 装什么 | agent 拆解当前任务的步骤 | 你让它"先记一下"的事 |
| 生命周期 | 当前对话内 | 跨对话、跨会话 |
| 完成后 | 步骤走完就消失 | 标记完成 → 归档 → 可回查 |
| 存哪 | 会话内 | ~/.dsh/followup-todos-<工作区>.json |
一句话:todo_write 是 agent 的工作台,dsh-followup-todo 是你的交接单。
核心设计:context + inject
每条待办有两个自由文本字段,这不是普通的备注,是刻意设计成"让下一个会话零回查开工"的契约:
context(背景) —— 只写已确定的事实:在讨论什么、已达成了什么结论、关键产物或文件路径、硬约束与边界。不要写过程流水账。inject(要注入的内容) —— 明确指明新方向:目标一句话、下一步具体动作、期望产出、可检验的验收标准。有歧义的地方显式标「待确认」。
两者会拼成一条完整的 prompt。点面板里的「继续」或输入框上方的卡片,这条 prompt 就会被填进输入框,新会话开局即带着全部上下文。
安装
dsh plugin --profile <profile> add github:Tiaoma123/dsh-followup-todo
ℹ️ 本包尚未发布到 npm,所以
add dsh-followup-todo暂时用不了;上面这条从 GitHub 直装,效果相同。
⚠️ 只挂一次。 本包通过
cordis.patch.yml自挂载(dsh.bundle.patch),一个包同时提供宿主半边与浏览器半边,装完即用,不需要在 profile 里再手写挂载行。同一个插件不要重复挂载 —— 重复挂载会注册两次/followup-todos前缀路由,整个插件树会在启动时报「duplicate prefix route」而挂掉。如果你之前手动挂过这个插件的其它形态(例如更早的双包版本),先删掉旧的那条再装。
模型工具
| 工具 | 作用 |
|---|---|
todo_add |
新增一条。title 必填,priority 为 P0–P3(默认 P2),另有 context / inject。 |
todo_list |
读取清单。filter:open(未完成,默认视图)/ done / all / archived。按优先级排序,同级按加入时间。 |
todo_done |
标记完成,条目仍留在清单里。 |
todo_archive |
标记完成并归档,移出所有活动视图(filter=archived 仍可回查)。 |
工作区由当前会话的 cwd 决定,也可以用可选的 workspace 参数显式指定(todo_add 除外,它始终用当前会话工作区)。
浏览器端
- 会话头部按钮 —— 显示未完成数量的角标,点开是悬浮面板(挂在
conversation.session.header.utilities,打开会话后才出现)。 - 悬浮面板 —— 新增 / 勾选 / 归档 / 删除,P0–P3 优先级选择,四个过滤页签(未完成 / 已完成 / 已归档 / 全部)。
- 输入框上方待办条 —— 挂在
conversation.input.dock,折叠时只显示一行「Todos · click to fill the composer」加数量,展开后列出条目;点一条就把它的交接 prompt 填进输入框,直接接着干。待办为空时整条不渲染。
数据存储
每条工作区一个文件:
~/.dsh/followup-todos-<base64url(工作区绝对路径)>.json
例如 /home/me/proj → followup-todos-L2hvbWUvbWUvcHJvag.json。文件是纯 JSON 数组,可以直接读、可以直接备份、删掉就等于清空该工作区的清单。
已知限制与安全说明
- HTTP 接口做浏览器鉴权。
/followup-todos/*由 dsh 的 webServer 注册,路由入口先调用connection.requestRejection(req):未通过鉴权的请求直接返回 401 / 403,不进入任何读写逻辑。已实测:不带会话凭据的裸请求被拒(401 unauthorized),浏览器内的同源请求正常通过。connection服务缺席时(老版本 DSH)退化为不拦截,此时任何能访问到该端口的客户端都能读写任意工作区的待办。默认监听127.0.0.1时风险有限;如果你把 dsh web 暴露到非回环地址,请自行再加一层访问控制。ws参数直接取自 query,但文件名经过 base64url 编码,因此不存在路径穿越。
- 列表靠 3 秒轮询刷新(一个全局轮询覆盖所有已登记的工作区分片),不是实时推送;多窗口同时打开时可能有短暂的显示延迟。
- 界面文案走 dsh 的 locale 服务,内置中英两套字典,跟随客户端语言切换。
- 头部按钮挂在
conversation.session.header.utilities,只在已打开的会话里渲染;空白新会话首页看不到它,这是插槽本身的行为。输入框上方的待办条挂在conversation.input.dock,待办为空时不渲染。 - 仅实现了 web 端界面。headless profile 里工具可用,但没有 UI。
维护状态
个人自用项目,不承诺维护。 我按自己的需要改,不保证响应 issue、PR 或兼容性请求。用 MIT 协议发布,你可以随意 fork 或自行修改,无需知会我。
开发与自测
npm test # 冒烟测试,57 项:宿主 42(工具生命周期/排序/归档/5 个 HTTP 端点/并发写入/浏览器鉴权)+ 浏览器 15(加载/导出/插槽注册/i18n 字典/样式注入)
npm run check # 发布前自检:占位符、凭据、硬编码路径、bundle 清单、重复路由、语法
npm test 全程隔离:它会把 HOME 重定向到一个仓库内的临时目录,所以插件写的 ~/.dsh 数据文件留在仓库里,不会碰你真实的待办数据。测试需要 @deepseek-ai/dsh-tools 可解析 —— 装了 dsh 的环境里直接可跑;独立 clone 的话先 npm i -D @deepseek-ai/dsh-tools。
浏览器半边用 window.__ModuleLoader__ 桩加载,拦的是"加载不进来 / 导出不对 / 插槽名写错"这类硬故障;它不渲染组件、不跑 hooks。真机渲染已在隔离 profile 的 dsh 实例上用 Chromium 实测过:待办条在输入框上方出现、数字角标正确、i18n 跟随语言、无控制台错误;未覆盖的是头部按钮(conversation.session.header.utilities 在空白新会话下不渲染,需要打开一个真实会话才能看到)。
License
English summary
A DSH plugin that gives the human a cross-session todo list — as opposed to the built-in todo_write, which tracks the agent's own task steps within a single conversation.
The distinguishing feature is a structured handoff per item: context (established facts, file paths, hard constraints) and inject (next action, expected output, acceptance criteria). Together they compose a prompt that lets a brand-new session start working without re-reading the original conversation.
Registers four model tools (todo_add / todo_list / todo_done / todo_archive) with P0–P3 priorities and an archive lifecycle, plus a browser half (header button, floating panel, composer-adjacent card strip). State lives in one JSON file per workspace under ~/.dsh/.
Personal project, no maintenance promised. MIT licensed; fork freely.
No comments yet. Be the first to write one.