dsh-todo-board
Cross-session TODO board as a draggable floating panel: tasks are grouped by working directory and reorderable by drag, each one carries a run mode (remind only, continue in the current session, or open a new session in the same directory), up to four attached images sent to the model as real image
Install
dsh plugin --profile web add dsh-todo-board
Sandbox test results
| Stage | Result |
|---|---|
| 1 install | ✗ |
| 2 list | — |
| 3 mount | — |
| 4 boot | — |
dsh: initialized profile web at /home/node/.dsh/profiles/webFour stages run in an isolated sandbox: install (network on) → list → mount → boot (last three with no network).
README
dsh-todo-board
给 DeepSeek Harness(DSH)agent 的一块跨会话 TODO 板:一次只派一件事,干完它自己去拿下一件。
A cross-session TODO board for DeepSeek Harness: hand the agent one task at a time, and it picks up the next one by itself.




它解决什么 / Why
让 AI 干完一件事之后,自己去待办板里找同一目录下还没做完的下一件继续干 —— 不用你盯着逐个验收,也不用一次把一堆任务塞给它、结果每件都做得半吊子。
待办按工作目录分组,列表顺序就是执行顺序;每条待办自己带一档执行模式(只提醒 / 自动续跑 / 自动新开会话);AI 干完勾自己的左勾,你验收勾右勾,右勾才真正了结它。
- 面板是一个浮窗(
shell.overlay),拖动、缩放、折叠都在里面,位置和尺寸记在localStorage。 - 板子是全局单文件:
${DSH_HOME}/todo-board/board.json,原子写入。面板内按目录分组显示。
Let the agent finish one thing, then look up the next unfinished task in the same working directory and keep going. Tasks are grouped by directory, list order is execution order, and only your own (round) tick closes one.
功能一览 / What you get
能力 · 一句话
[跨会话自动接续](#三档执行模式--run-modes) · 回合结束时把同目录下一条未完成待办交给当前会话或新会话
[三档执行模式](#三档执行模式--run-modes) · 提醒 / 自动续跑 / 自动新开会话,每条待办独立选
[任务状态](#任务状态--task-states) · 每行都有且只有一个状态标签,从实时会话列表推导,永不落盘
[卡住会自愈](#卡住的行不会静默卡死--a-stranded-row-recovers-itself) · 派发失败记 lostAt 并按退避重试,绝不静默退休
[图片附件](#图片附件--attached-images) · Ctrl+V 粘贴截图,最多 4 张,派发时是真正的图片
[定时执行](#定时执行--scheduled-execution) · 本地时间到点才派发,列表里随时可改
[双勾选](#双勾选--two-checkboxes) · 方形是 AI 自己勾的,圆形是你的验收;右勾才了结
[界面风格](#界面风格--skins) · 蓝白 / 素白 / 紧凑 / 随主题四套,一键循环切换
[开发者日志](#开发者日志--developer-log) · 面板内切页看日志,出错才亮小圆点,默认只记本插件
[长任务先规划](#长任务先规划--plan-a-long-task-first) · 明显分多步时先问你要不要拆,/todo 一键注入模板
[模型工具与审批门](#模型工具--the-todo_board-tool) · AI 改板子走 DSH 原生审批框,不问就执行不了(沙箱已放开完全访问时除外)
安装 / Install
dsh plugin --profile web add dsh-todo-board # 从 npm 安装 / from npm dsh plugin --profile web add <git-url-or-path> # 或从仓库/本地目录 / from a repo or local path
安装后重启 Profile(重新执行 dsh web)才会装载 —— 本插件是 host 组合里的一行,不是运行时热加载。
Restart the profile afterwards: the plugin is a row in the host composition, not a runtime hot-load.
卸载 / Uninstall:dsh plugin --profile web remove dsh-todo-board
DSH 版本要求 / DSH version requirement
本插件 0.11.2 起要求 DSH ≥ 0.1.7-rc.2,并已在 DSH 0.2.1-rc.2(桌面端)上验证。
你的 DSH · 装哪个版本
0.1.7-rc.2 ~ 0.2.1-rc.2 · 当前版本(≥ 0.13.0)
≤ 0.1.6(含 0.1.5-rc.3) · dsh-todo-board@0.6.1(最后一版 v3 兼容版本)
会话格式在这两端都是 v4,所以同一条适配覆盖两者。插件注入的每条消息都带一个生产者自有的 source({ kind: 'plugin:dsh-todo-board', form: 'notice' }):这是 v4 的硬性要求,旧 v3 的写法会被持久化层拒绝,而拒绝会带走整个回合——不只是那条提示。不带这个适配的发布版只有 0.4.1 / 0.5.0 / 0.6.1。
0.2.1-rc.2 的实际核对结论:会话格式仍是 v4(SESSION_FORMAT_VERSION = 4),插件依赖的 14 个 host 服务、4 个 host 事件、shell.overlay slot、以及 useSessions 的 store 形状全部未变。逐项证据见 [docs/report-0.2.1-compat.md](docs/report-0.2.1-compat.md)。
版本门是 peer,不是 engines / The gate is a peer, not an engine
engines.dsh 是一扇哑门:npm 只校验它认识的引擎名(node / npm),自定义引擎名不参与检查 —— 装在 DSH 0.1.5 / 0.1.6 上不会有 EBADENGINE 警告。它因此保留着(把范围也留给了 DSH 自己读),但它只是一个声明,从来不是门。
从 0.13.0 起,包里多了一条真正会拦的 peer 依赖:
"peerDependencies": { "@deepseek-ai/dsh": ">=0.1.7-rc.2" }
peer 由 npm 的解析器执行(includePrerelease: true,所以 0.2.0-rc.2 这类预发布版本能被正确匹配),装错版本在安装那一步就被挡下:
已装的 DSH · 结果
0.2.1-rc.2(当前桌面端) · ✅ compatible
0.2.0-rc.2 · ✅ compatible
0.1.7 / 0.1.7-rc.2 · ✅ compatible
0.1.6 · ⛔ BLOCKED,并告知需要 {"@deepseek-ai/dsh": ">=0.1.7-rc.2"}
为什么没有上界。 这里刻意不写<0.3.0之类的上限。实测(includePrerelease: true,与 npm 解析 peer 时的选项一致):<0.3.0能挡住0.3.0,却挡不住0.3.0-rc.1;要真挡住预发布得写<0.3.0-0,而这会把走 nightly 通道的人直接锁在门外。一个拦不住 next 的上界只是假安慰,代价却是实打实的误伤,所以范围只声明下界。
版本差别是行为差别。0.13.0以前装错版本一路畅通、无声无息,实际表现是运行时报错(原因写进插件日志);0.13.0起它会当场被拦下,而不是等运行时才炸。反过来说,如果你要留在 DSH0.1.6或更早,就得显式装dsh-todo-board@0.12.0或更低 —— 那几版没有这道 peer 约束,但也同样没有这层保护。
快速上手 / Quick start
1. 右上角出现浮窗,输入一条待办,选执行模式,点「添加」。
2. 让 AI 去做这件事。它做完会调用 todo_board action=done 给自己打左勾,然后查同目录下一条。
3. 你验收后点右勾;底部「清理已验收」批量清掉。
三档执行模式 / Run modes
每条待办在新增时选一档(默认「提醒」)。
模式 · 行为
提醒 · 不自动做任何事,等你在浮窗里点 ▶
自动续跑 · 回合结束时,把下一条待办注入当前会话继续跑
自动新会话 · 回合结束时,新建一个同目录会话并执行该待办
「目录」一行决定这条待办归属哪个目录:分组标题、能否在「当前目录」里看到、回合结束后由哪个会话接续,都看它。留空 = 跟随当前会话的工作目录。
派发顺序 = 面板里从上到下的顺序,拖动行首 ⠿ 调整,持久化。选择是按归属而不是按目录:一条待办只被它所属的那个会话接走,同目录的另一个会话不会顺手拿走你的活。
「自动新会话」第一次派发时创建会话并绑定到这条待办,之后复用同一个会话,不会一次运行开一个。绑定会话不在了才会再开;点行上的 会话 … ✕ 解绑可手动换一个。
任务状态 / Task states
状态由 host 从实时会话列表推导(不落盘,避免与实际不一致)。每一行都带且只带一个状态标签——需要靠推断才知道的状态等于看不见:
状态 · 含义
未派发 · 还没交给任何会话;▶ 可点
已派发 · 已交给会话,目标还活着
进行中 · 目标会话此刻正在跑
已完成 · AI 打了左勾,或你打了右勾
目标会话丢失 · 派发时找不到目标会话,悬住了
只有 进行中 和悬住的行显眼。已完成 的划线只跟验收走,所以 AI 勾完但你没验收的行会显示「已完成」而依然清晰可读。
「悬住」的原因不止一种,面板按实际原因显示:目标会话丢失、图片被拒(会话是好的,别冤枉它)、建会话失败、预设解析失败、服务不可用;tooltip 写清原因和出路。
▶ 只能在「未派发」时点击。 重复派发只会产生重复工作。
派发失败不会盖上「已派发」的戳。 那个戳的含义是"已经发出去了",而调度器和钩子都会按它跳过——盖上就等于把这条待办永久退休。取而代之的是记录 lostAt 并按退避重试(首次 1 分钟后翻倍,最多半小时一次)。改模式、换目录、解绑会话都会立刻清掉标记让它重新排队;卡住的待办也不会挡住后面的条目。
图片附件 / Attached images
待办可以带图片(最多 4 张,PNG / JPG / WebP / GIF)。图片存进 DSH 的附件库,派发时作为真正的图片和提示词一起发给模型——不是把文件名写进文字里。
- 在新增框里直接
Ctrl+V粘贴截图即可附图,粘完显示缩略图,点缩略图移除。原来的「📎 图片」选文件按钮已删除。行上的缩略图点击可放大,✕ 移除单张。 - 输入框空着时没有任何常驻提示:能力由 placeholder 里的
Ctrl+V 粘贴截图说明,附图区只在真的附了图之后才出现。 - 纯文本粘贴不受影响:只有剪贴板里真的带图片时才会拦截粘贴。
- 一次粘太多会粘满为止并告知(「只粘贴了前 N 张」),而不是静默丢掉。
- 剪贴板图片有时不带 MIME 类型;这种会按文件名的扩展名补上类型再交给 host(host 对媒体类型是严格校验的)。
- 图片字节由本插件自己的
GET /dsh-todo-board/image?id=…提供:harness 自带的图片读取是会话作用域的,而待办的附件存在板上,所以板自己当权威——没被任何待办引用的 id 一律 404。 - 目标模型必须支持图片:派发前会查模型是否声明了
image,文本模型会得到明确提示而不是适配器抛错。
定时执行 / Scheduled executi
…(truncated)
Rendered from the README published on npm. Formatted only, not edited.
Versions
Published on npm::10,最后更新 2026-10-23