DeepSeek Harness Plugin Hub

Publish and manage complete Harness Profiles. Discover Plugins for your next setup.

Explore

PluginsPresetsDocsNews

Community

Publish a pluginContactReport an issue

Resources

Plugin Hub on GitHubDeepSeek HarnessSystem statusPrivacy notice
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

Independent and unofficial. Not affiliated with, authorized by, or endorsed by DeepSeek.

Todo Assistant — DSH Plugin for DeepSeek Harness
← Plugins
T

todo-assistant

Todo Assistant

DSH plugin: A cross-session workspace for side tasks—turn things you decide not to do yet but do not want to forget into cards, then handle them in separate sessions.

The plugin will be installed here. Keep web if you are unsure.

npx -y @deepseek-ai/dsh plugin --profile web add github:zangoose335/dsh-todo-assistant#cc59cf4229eebd7703810337b9d49735732a2f25
READMECompatibilityVersions

Description

A DSH plugin: A cross-session workspace for side tasks found during a session. Turn tasks you decide not to do yet but do not want to forget into cards, then handle them in separate sessions.

Compatibility and provenance

Todo Assistant is published as todo-assistant and currently resolves to version 0.1.0. The Hub verifies its manifest and preserves the exact installation source for reproducible installs.

DSH compatibility
*
Runtime surfaces
web
Release source
github
Registry updated
10/17/2026

Versions

0.1.0stable
10/17/2026

Related plugins

Loading related plugins…

Latest
0.1.0
DSH
*
HMR
Process restart
Tree shaking
Safe tree shaking not declared
Unpacked size
Unavailable
Files
Unavailable
Surface
web
License
MIT
Source
github
GitHub
★ 0
Weekly downloads
0
Last push
10/19/2026
View source ↗
README badge

Click the badge to copy Markdown for your README.

Do you maintain this Plugin?Claim benefit · Priority security scan

Verify the GitHub repository declared in package.json to manage this listing. After you claim it, Hub will prioritize a security scan of the current version and publish the result when it passes.

Claim this Plugin →
Report an issue
DeepSeek Harness Plugin Hub
ProfilesPluginsCategoriesNewsDocsSign inManage Profiles
ProfilesPluginsCategoriesNewsDocsSign in

Related plugins

More verified plugins in productivity-workflow.

Acp App@deepseek-ai/dsh-acp-appThe dsh ACP profile bundle: automation-only JSON-RPC stdio and process lifecycle over dsh-baseExperimental Schedule Bundle@deepseek-ai/dsh-experimental-schedule-bundleOptional bundle that adds Schedule, its task page, and time context to the Web compositionWeb All@linxin666/dsh-web-allDSH Web UI 全家桶聚合插件:一键安装全部功能插件(task-board / git-graph / pet / remote-web-ui / web-ui-settings / skin-center / community-plugins / compat shim)。compat 桥接层已并入本包(src/client),无需独立 compat npm 包。Ab Ocrdsh-ab-ocr--- description: "The out-of-tree ocr tool: recognizes a scanned PDF or image page by page, merges the pages in order only after the last one, and saves one Markdown document with the heading levels the model decided." kind: "package-reference" ---

README

中文 | English

待办助理 (todo-assistant)

跨会话的旁支任务工作台:把会话里"先不做但别忘"的事记成卡片,之后单独开会话处理。 设计见 docs/DESIGN.md。安装见 安装,许可见 LICENSE(MIT)。

当前功能:

  • 右栏 tab:五个视图(未完成 / 待修复 / 待添加 / 已完成 / 全部)、卡片 CRUD、详情展开、按工作区范围过滤(跟随当前会话);
  • 捕获:todo_add(完整 schema + git 坐标 + mustRead/park + 开发者原话 + 路径归一化)、去重拦截、 #DB … #/db / #MEMO … #/memo 标记、AI 回复上的「记录待办」段落面板、输入框 #db 补全与 # 引用框;
  • 读取:todo_read / todo_note / todo_status / todo_list / todo_recall(两段式原文回读);
  • 提醒:每步零模型的路径相关性检测 + 下一步一行提醒 + 右栏「相关」角标;
  • 交接:卡片「开始任务」→ 新会话以卡片开场 / 插入当前会话;工作区级通用规则随新会话带上。

结构

文件作用
host.jsHost 插件入口:打开 todo_assistant storage domain,注册 /api 路由与 todo_add 工具
domain.js领域声明(zod record schema)与纯逻辑:建卡、捕获校验、改卡、ID、L0 投影
api.js数据操作与线协议:list / create / patch / remove / note.add / note.remove
tool.js六个工具定义:todo_add / todo_read / todo_note / todo_status / todo_list / todo_recall
git.js写卡时的代码坐标:git rev-parse(subprocess)优先,.git 文件读取兜底
detect.js检测规则:工具调用 → 路径 → 卡片匹配 → 提醒行 / 角标集合
recall.jsL2 回读:原始日志 → 目录(seq/轮次/角色/首行/token)→ 指定 slice 的正文
dedupe.js近似重复:同工作区 + 共享触及文件 + 标题相似度
client.js浏览器 half:右栏页签类型 + 卡片 UI(无构建步骤,只用 baseline react)
scripts/verify-domain.mjs无头验证:用安装里的真实 storage 栈打开 domain 并跑完整个线协议

domain.js / api.js 刻意不写任何包导入,测试脚本可以脱离 profile 直接驱动它们; 真实依赖由 index.js 注入 createTodoSpec({ z, defineDomain, domainTable })。

#DB 标记(输入即同意)

在消息里写:

#DB 导出 CSV 时表头重复
第二行也算待办内容
#/db
  • 开始标记 #DB / #db,或英文的 #MEMO / #memo(两者等价,同一捕获链路);结束标记 #/db / #/memo 可省略(省略时到消息结尾),两种结束标记可互换;
  • 跳过围栏代码块与行内代码 —— 否则一条"讲解这个语法"的消息会把自己记成待办;
  • host 在 user/message(只认人打的,source.kind === 'user')上扫描,命中就排进该会话的队列;
  • 下一次装配会注入一条一次性指令:告诉 AI「这段被标了 #DB,标记就是明确同意,用 todo_add 原样记下,不要再问」;
  • 开发者原话(含标记本身)仍会逐字存进卡片的 request。

识别点在 host 侧(agent/inbox/claimed,早于 prompt 装配),所以不依赖 composer 的提交钩子;也不改发送流程。

输入框里有轻量补全:打 #db 会变成 #DB #/DB,打 #memo 会变成 #MEMO #/MEMO,光标停在两个空格之间。实现只用公开的 useInput + inputActions(先插 #/db、再把 #db 替换成 #DB ),不碰编辑器内部与 DOM。

面板内的使用说明

右上角的圆形 (i) 按钮展开「待办助理使用说明」:插件定位、为什么值得用(记卡带现场、读卡省 token、主线不断、重复提醒、规则写一次)、按场景的用法(问 AI 记卡 / 事后 #x.y 接着做 / 一次多条 / #db 输入即记录 / # 引用 / 开始任务收尾 / 通用规则),以及 #x.y 编号含义。文案在中英两份 i18n 里,改措辞直接改 client.js 的 help.body。

段落捕获面板

点 AI 回复上的「记录待办」后:

  • 面板列出该条回复的段落,关键词/路径命中的预选;
  • 「插入到对话框」把选中的段落拼成同一条消息放进输入框(不发送),适合一次补多条;
  • 「发送给 AI」直接作为一条用户消息入队,由 Agent 调 todo_add;
  • 面板材质与官方弹层一致(mask + layer-2 + --dsw-radius-panel + --dsw-elevation-prominent)。

开发者原话

todo_add 落卡时,host 会把当前轮里人打的用户消息(source.kind === 'user',跳过文件变更/技能等系统注入)逐字存进卡片的 request.text(上限 8000 字,超了标 truncated),模型完全不参与这段文本。

  • 右栏详情第一块就是「开发者原话」,卡片元信息里也会出现「原话」标记;
  • todo_read 默认输出里带 developer request (verbatim);
  • 新会话的种子把它作为「开发者原话」一节带上,接手会话的 AI 直接看到你的措辞。

如果消息里带了 #DB … #/db,只记对应那一段,标记本身不入库;一条消息里多个标记时按出现顺序各记一段(request.block 记序号)。识别点允许标记紧跟在中文标点后(两条:#db …),但贴在单词里(abc#db)不算。

这样 AI 的理解有偏差时,你能对着原话立刻纠正;它也永远不会被"总结"掉。

工作区通用规则

右栏面板里有一块可折叠的「通用规则」,按工作区保存:

  • 存在 todo_assistant 域的 rules 表里,key = 工作区路径(rules.get / rules.set 两个端点);
  • 点「处理 → 新会话中立即执行」时,会把该卡所在工作区的规则拼进开场种子(放在卡片内容之前);
  • 留空即删除该工作区的规则;
  • 只作用于插件自己创建的新会话;你手动新建的会话不会带上(要全局生效得挂系统提示词,那是另一种取舍)。

完成闭环

  • AI 侧新增 todo_status(id, status):唯一能改状态的工具(open / doing / done / dropped),描述里写死必须先得到开发者确认;
  • 新会话种子与「插入当前会话」的提示词里都带了这句: 「改完后主动问开发者是否把 #x.y 标记为完成,确认后再调 todo_status」;
  • 于是接手一张卡后,AI 会在收尾时问一次,得到肯定回答才落 done,不需要你自己去右栏改。

编号

每张卡有一个短标签 #3.2,与内部 id(td_x7k2)并存:

  • major(点前)= 第几个会话:同一根会话共用一个 major,在该会话第一张卡时分配(全局最大 major + 1);
  • minor(点后)= 会话内第几张:组内最大 minor + 1;
  • 子会话不算新会话:沿 header.parentSession 上溯到根,卡片归到根的组;
  • 没有会话的卡:每张新开一个 major、minor 固定 0(x.0);
  • 创建时定号并写进记录:之后删除不重排;只有删掉组内最高 minor 后,同组下一张才会复用该号(已接受);
  • 老卡片迁移:本方案之前的卡一次性变成 1.<旧编号>(1.1…1.N);迁移后旧会话再进新卡会另开 major —— 历史桶不吸收新卡;
  • 右栏、工具输出、提醒行都用 #x.y;入参接受 3.2、#3.2 和 td_x7k2。

数据落在哪

  • domain 名是 todo_assistant(下划线):storage 层强制 UNIT_NAME_RE = /^[a-z][a-z0-9_]*$/, 连字符会被 defineDomain 直接拒绝。
  • 走 storage-domain 的默认 json backend,所以卡片落在 ~/.dsh/storages/todo_assistant.json(单文件 layout)。
  • workspace 存会话所属工作区的规范化路径;不属于任何仓库的卡放 inbox。

捕获(M2)

todo_add 是表单,不是自由写总结:

  • 参数固定为 title / kind / nextStep / touchedFiles / mustRead(必填)+ symptom / cause / intent / park / symbols(可选);
  • 硬约束在 handler 里二次校验,超限直接报错让模型重写:title ≤40、mustRead ≤3 条且每条 ≤200、park.label ≤30、park.why ≤60;touchedFiles 为空只警告不拦截;
  • 工具描述写死三条行为约束:必须先得到开发者明确同意、只写与本待办相关的部分、已压缩内容不得自行回读;
  • touchedFiles 在写入时归一化:绝对路径按工作区剥成相对路径、去掉 ./ 与目录尾斜杠、反斜杠转正斜杠、去重;工作区之外的绝对路径保持原样。所以模型写 /Users/.../src/a.ts 也能参与路径提醒与去重(两者都按归一化后的形式比较)。
  • origin(sessionId / turn / seqRange / cwd)与 code(commit / branch,来自 git rev-parse,subprocess 不可用时读 .git/HEAD + refs / packed-refs)全部由 host 填,模型不产出;
  • workspace 由 session cwd 经 workspaceRegistry.resolveByPath 归一化,和右栏的工作区过滤对齐。

读取(M3)

  • todo_list(workspace?, status?):只有索引(id / 标题 / 状态 / 类型),默认看本会话工作区里 open+doing 的卡;workspace: '*' 跨工作区。
  • todo_read(id, part?):无参返回卡片本体(core + mustRead 正文 + park 的 label/why + 坐标 + 触及文件 + note 数);part: 'notes' 给补充历史;part: 'park:n' 给该条备查指针(含 where,正文留给 M6 的 recall)。
    • 说明:mustRead 每条本来就 ≤200 字,是"必读材料",所以放在默认返回里;park 只给 label/why,正文按设计不主动加载。
  • todo_note(id, text, kind?):追加,text ≤300 字,kind = supplement / evidence / status;先校验再落库,不重写卡片。

右栏卡片右上角的 ⌄ 展开详情(同一份数据走 POST /api/todo-assistant/detail),可直接删补充。

检测与提醒(M4)

零模型调用,全部在 host 侧算:

  • 信号:session/event 里的 tool/call 参数(read/write/edit/read_image 的 file_path,grep/glob 的 path),按会话 + 轮累积;
  • 范围:只看本会话创建、状态 open/doing 的卡(origin.sessionId 匹配);
  • 命中条件(默认):精确文件路径相同,或共享目录前缀 ≥ 2 段(src/auth/router.ts vs src/auth/token.ts 命中;src/a.ts vs src/b.ts 不命中);
  • 每轮每个卡片最多提醒一次:step/end 触发检测,turn/start 重置本轮预算,已提醒的卡不会在同轮重复;
  • 注入:ctx.systemPrompt.context({ name: 'todo-assistant/reminder', order: 130, text }),在下一次装配(同轮下一步)给一行: A file touched this step (src/auth/router.ts) relates to todo #td_x7k2「…」; call todo_note if there is evidence worth keeping. 装配即消耗,下一轮之前不会再出现;
  • 角标:list 请求带上 sessionId,命中卡在 L0 上带 hit: true,右栏显示「相关」并描边;turn/start 重置。

未接的信号(DESIGN §7 已决定不做):commit 变化、从触及文件反推符号。两者也是零模型调用,问题在质量——卡的 code.symbols 常为空、符号名是通用词易误报、commit 多是陈旧性信号;路径信号已覆盖"同一个地方又动了"这一主场景,漏的是"文件移动/改名、只改符号、按符号 grep"三类。

原文回读(M6)

todo_recall(id, slice?) 是 L2,两段式,最贵的一次读取(正文会永久留在上下文里、每步重复计费):

  1. 不给 slice → 目录:卡片 origin.seqRange 里每条消息的 seq / 轮次 / 角色 / 首行 40 字 / token 估算,外加总量;
  2. 给 slice: [from, to] → 只返回这一段正文(每条消息截 2000 字、整次上限 12000 字,超了标注 truncated)。

数据来自 ctx.sessionQuery.readSession(id) 的原始日志(不是当前 surface),所以即使那段历史已被压缩替换,也能读回原貌;token 估算优先用 ctx.tokenMeter.estimateMessage,没有就按 ~4 字符/token 粗估。

工具描述里写死了硬规矩:不得自行 recall,必须先征得开发者同意;先给目录,再由开发者选段。

这条约束是指令而非强制(没有 UI 审批拦着)。两次行为探针("早期轮次已压缩,需要知道当时为什么排除方案 A")里模型都是先 todo_read、再停下来请求批准,日志里未授权调用为 0;据此决定不加机械审批,真出现一次漏网再加(DESIGN §6.4)。

手工建的卡 origin.seqRange 是 [0,0],没有可回读区间,会返回 unavailable。

去重(M7)

todo_add 落库前先算一遍"这是不是同一张卡"(§6.5):

  • 候选范围:同 workspace、状态 open/doing 的卡;
  • 命中条件:至少 1 个 touchedFiles 精确相同 且 标题相似度 ≥ 0.55(字符 bigram Dice,忽略大小写/空白/标点);
  • 命中时不建新卡,返回 status: 'duplicate' + 候选 id/标题/相似度/共享文件,让模型去问开发者;开发者同意后用 todo_note 把新事实追加到那张卡;
  • touchedFiles 为空的捕获不参与去重(只靠标题太容易误判)。

误判代价是模型多问一句,比"同一件事两张卡"便宜。

处理(M5)

卡片上的「处理」展开两个动作(DESIGN §3.11):

  • 新会话中立即执行(菜单里的第一个动作,原文案「新开会话」):ctx.remote.session.create({ workspaceId | cwd }) → .prompt({ mode: 'queue', content: [{type:'text', text: seed}] }) → ctx.uiWorkspace.openSession(sessionId)。 seed 是卡片的 L1:标题、现象/原因/意图、下一步、触及文件、必读(含正文)、备查 label/why、写卡时的 commit、补充条数。新会话从一开始就知道自己在处理哪张卡。
  • 插入当前会话:用 inputActions.captureInsertion() + insertText() 往当前输入框里插一句 现在切到待办 #1.3「…」:先用 todo_read 读它,再按里面的「下一步」继续;改完后问我是否标记完成。 只预填、不自动发送 —— 不替人发消息,也不打断正在跑的轮次;回车由开发者按。

两种方式都会在卡片上记 handling: { sessionId, at }(POST /api/todo-assistant/handle), 列表与详情都不再显示处理标记(2026-10 移除):会话接手只创建/发送种子,不写 handling。 字段仍保留在数据模型里以兼容旧卡,todo_read 也还能读到,但 UI 不写入、不展示。

关联改动:卡片的状态不再用下拉菜单——编号左侧的 radio 直接标完成/取消,× 菜单给「删除 / 归档 / 取消」, kind 标签移到左下角,× 移到右上角。

与设计的一处偏差:设计里「处理」是卡片上的 [处理 ▾] 菜单;这里同样是点一下展开两个选项, 只是菜单行内展开而不是浮层。

客户端 → Host 写通道

形态:/api 通道上的 exact Fetch 路由。不是 @Remote,不是 rpc.handle,也不是自建 webServer 路由。

  • Host:ctx.connection.fetch.register({ path: '/api/todo-assistant/<endpoint>', methods: ['POST'], requestBody: 'buffered', fetch })。路由挂在 Connection 已有的 /api 前缀下,Host/Origin 信任围栏与浏览器 cookie 鉴权在进入 handler 之前就生效(无 cookie → 401)。
  • Client:同源 fetch('api/todo-assistant/<endpoint>')(document-relative,兼容挂载前缀)。
  • 不用 @Remote:那些 namespace 由 TypeScript 装饰器在构建期生成,再由应用自己的 ctx.remote 装配挂载;纯 JS 插件没有这条构建链。
  • 不用 ctx.connection.rpc.handle():它挂路由时读的是 Connection 服务自己的 fiber (get rpc() 里 const owner = this.ctx),那条 fiber 只 inject 了 webRuntime,必然抛 cannot get property "webServer" without inject。intercept('/api', …) 不碰 webServer,但 /api 的中继已被 API Gateway 独占。

线协议(裸 JSON,不套 Gateway 信封):

POST /api/todo-assistant/<endpoint>
{ ...payload }
→ { "ok": true, "value": ... }
→ { "ok": false, "error": { "code": "todo/title-required", "message": "...", "details": {} } }

验证

离线(不需要启动 GUI,不动 profile):

node scripts/verify-domain.mjs

它用本地 dsh 安装里的真实 storage / storage-json / storage-domain 打开本插件的 domain, 跑完增删改查与 note 追加/删除,最后关闭再重开,确认记录跨重启存活。

安装后(当前 profile):

# 1. 已激活
#    在会话里 cordis_inspect_query → Slots.listSubTree(root: "sidebar.right.pane.tab")
#    应看到 key = "todo-assistant" 的 occupant
# 2. 冒烟调用(需要浏览器 session cookie,见下;无 cookie 应返回 401)
curl -sS -X POST "http://127.0.0.1:3080/api/todo-assistant/list" \
  -H 'content-type: application/json' \
  -H 'Host: 127.0.0.1:3080' -H 'Origin: http://127.0.0.1:3080' \
  -b "$COOKIE" \
  --data '{"all":true}'

cookie 就是浏览器里那份 dsh-auth-*(签名密钥在 ~/.dsh/.credentials.yaml 的 client-connection/browser-session 记录里;签名 key 要先 base64url 解码)。

安装

三种方式,任选一种。都需要在 DSH 里调用 plugin_manager install_bundle(需要审批),装完重启 dsh。

1. 从本地目录(开发用) —— 源码留在这里,不要放进 ~/.dsh:

plugin_manager install_bundle  target = <本仓库绝对路径>

2. 从 GitHub 直接装 —— 不用先 clone:

plugin_manager install_bundle  target = https://github.com/zangoose335/dsh-todo-assistant.git

想锁版本就在地址后加 #<commit>,例如 ...#77215f3。

3. 从 npm(发布后):

plugin_manager install_bundle  target = todo-assistant@0.1.0

install_bundle 要求 PATH 里有 pnpm(本机通过 corepack enable pnpm 提供)。 方式 1 装完后 profile 里是一个符号链接:

~/.dsh/profiles/web/node_modules/todo-assistant -> <本仓库绝对路径>

不同方式装的是同一个包名,切换前先 remove_bundle 掉旧的那份。

必须重启 dsh 才会加载 host half:linked 包的安装内导入(zod、@deepseek-ai/dsh-storage-domain) 依赖启动时建立的 profile 解析表,运行中的进程不会在安装后重建它。之后每次改 host 代码都要重启; 只改 client.js 刷新页面即可。

打开 tab

右栏 → 顶部 +(Add)打开 guide → 点「待办助理」。页签布局按会话记在 localStorage,重开仍在。

许可证

MIT © 2026 黑桃伍