前言¶
在 DSH 里做长任务,常见的协作方式是「模型出计划、人在上面看进度」。这个模式有两个具体问题。
一是计划永远由模型拟定。Harness 自带的任务面板是只读的,数据来自会话投影 todos,你只能看,不能改。二是新会话里根本没有入口:todos 投影为空时,那个组件直接 return null,模型写下第一条任务之前,面板压根不存在。
lmk2215/dsh-todo-editor 就是冲着这两点来的。它把方向反过来——你下清单,模型执行。
这是什么¶
一个给 DeepSeek Harness 客户端装的可编辑任务流程面板,维护者 lmk2215,package.json 版本 0.1.0,许可证 MIT,社区目录里归在「工作流」分类。
它做的事:把清单入口挂到会话头部,你在里面写节点、改状态,点保存后直接把清单写进会话,输入框上方的原生任务面板立刻更新——不产生用户消息,不走模型回合,不消耗 token。之后你正常发材料,模型按清单逐个节点执行。
核心功能¶
以下能力均来自 README。
- 头部按钮加未完成数量角标,空列表也能打开(入口常驻在
conversation.session.header.actionsslot)。 - 逐行改文字、
+追加、×删除。 - 点状态标签在「待处理 → 进行中 → 已完成」之间循环,同时只允许一个进行中,与宿主默认策略一致。
- 保存走宿主命令
/todo-apply,直接写会话,没有模型回合。 - 双端校验:空内容、重复条目、非法状态在进入会话日志之前就被挡掉。
- 降级路径:命令通道缺失时(例如宿主半边没重启),保存自动回退成发一条
[任务流程]消息,功能不中断。
安装与启用¶
环境要求:DeepSeek Harness >= 0.2.0(依赖客户端 slot 注册表和 dsh-commands),需要 @deepseek-ai/dsh-client-ui-conversation 提供的 conversation.session.header.actions slot。插件无需构建——lib/client.js 是手写 bundle,只从宿主模块表取 react 和 react-dom。
方式 A,有 pnpm 的环境用插件管理器:
dsh plugin --profile desktop add dsh-todo-editor
方式 B,手动挂载。DSH 的 profile 就是普通目录,本地包可以手工链进去。
-
把仓库放到固定位置,例如
~/.dsh/local-plugins/dsh-todo-editor。 -
链接进 profile 的
node_modules:
# Windows:junction 不需要管理员权限
cmd /c mklink /J "%USERPROFILE%\.dsh\profiles\desktop\node_modules\dsh-todo-editor" ^
"%USERPROFILE%\.dsh\local-plugins\dsh-todo-editor"
# macOS / Linux
ln -s ~/.dsh/local-plugins/dsh-todo-editor ~/.dsh/profiles/desktop/node_modules/dsh-todo-editor
-
在
~/.dsh/profiles/desktop/package.json里登记:dsh.profile.bundles追加"dsh-todo-editor";dependencies追加"dsh-todo-editor": "link:<本仓库绝对路径>"。 -
重启 Harness。注意刷新页面不够——客户端 bundle 在宿主启动时快照。
上面这一整套也有脚本:
node scripts/install.mjs # 安装 / 修复
node scripts/install.mjs --revert # 卸载
默认值和你的目录结构不匹配时,用 --profile <dir> 或 --dsh <app/dsh 目录> 指定。卸载命令会一并撤销 profile 里的链接、package.json 的两处登记和宿主补丁(从 .bak-todoeditor-* 备份还原),之后同样需要重启。
典型用法¶
- 点会话头部的清单图标。
- 写节点,点状态标签切状态。
- 点保存——输入框上方的任务面板立刻变成你这份清单。
- 把材料发出去,模型按清单逐个节点执行并更新状态。
按钮角标显示还有多少条未完成。
可选:配套宿主补丁¶
@deepseek-ai/dsh-tool-todo 的 todos 投影会在每次 turn/start 清空。这意味着你定好的清单,发出下一句话就会消失,等模型重写一次才回来。
patches/tool-todo-survive-turn-start.md 记录了一行改动:有未完成节点就跨轮保留,全部完成后仍然清空,避免陈旧进度常驻。scripts/install.mjs 会带时间戳备份地应用它,--revert 从备份还原。不打补丁插件照样能用,只是面板会先闪空、等模型重发。
实现结构¶
命令 handler 直接跑在接收 agent 上、不产生模型消息,这是保存即时且静默的原因;recordInput: false 让编码后的载荷不落进会话日志。
| 层 | 位置 | 作用 |
|---|---|---|
| 客户端 | lib/client.js |
注册 slot conversation.session.header.actions(id: todo-editor,order: 5),用 react-dom portal 渲染浮层 |
| 客户端 | getTodosFace |
读 session.projections.faceOf("todos") 并订阅变化 |
| 客户端 | applyTodos |
调 session.command("/todo-apply <encodeURIComponent(JSON)>") |
| 宿主 | lib/index.js |
注册 /todo-apply,handler 执行 agent.session.append("todo/write", { todos }),返回不含 text 的 { kind: "success" } |
| 宿主 | @deepseek-ai/dsh-tool-todo |
持有 todos 投影,面板实际渲染它 |
适用场景与注意¶
适合想把计划权拿在自己手里、任务又能拆成有序节点的场景:先写好清单再让模型执行,模型负责执行和更新状态,而不是替你立项。
已知限制,来自 README:
- 保存不是锁:模型一次
todo_write会整表替换,包括你改过的内容。 - 状态标签在命令路径下按你设定的状态原样写入;只有回退路径才经由提示文本表达。
- 浮层是 fixed 定位的 portal,锚定按钮,容器滚动不重算位置(头部本身不滚动)。
- 不支持拖动排序,行内编辑、末尾追加。
安装前建议做两件事:确认版本与 >= 0.2.0 的宿主匹配;通读源码。插件以当前 dsh 进程的权限运行,能力边界取决于它注册的命令和你的环境。许可证是 MIT。
结尾¶
它的价值很具体:把「计划由谁定」这个问题从模型侧挪回人侧,同时不占用任何模型回合。如果你习惯先列清单再派活,这是目前最贴近这个习惯的做法。