packages/dsh-task-board
zhu1090093659/dsh-web侧边栏多列任务看板:卡片交给真实 DSH 智能体会话执行,支持 cron 定时(Host 侧到点执行,关浏览器也生效)。
在输入框上方列出已发送但模型尚未读取的插话消息,可在模型读取前逐条或一次性撤回。
DeepSeek Harness (DSH) 插件:撤回「已发送但尚未被模型读取」的文字消息。
在模型运行中发送文字(插话发送)时,消息会以“待处理”气泡的形式出现在对话尾部——在模型认领(读取)之前,你可以一键撤回,避免把还没想好的话发给模型。
截图占位:可将实际效果截图保存为docs/screenshot.png,并取消上方![screenshot]的注释。
conversation.input.dock 插槽)列出所有已发送但模型尚未读取的插话消息(0.2.x 取 inbox['next-step'] 的用户插话,0.1.x 取 placement === 'steering')。DSH 中“已发送但未读取”的消息 = 仍停留在 Agent inbox(待处理队列)中的消息:0.2.x 是 inbox['next-turn'] / inbox['next-step'] 里的 pending 项,0.1.x 是会话快照 ConversationSnapshot.queue。它有两种 placement:
placement · 含义 · 官方界面现状 queued · 运行中排队等待下一轮 · 官方队列坞已有「删除」按钮 steering · 运行中插话发送,显示为对话尾部待处理气泡 · 没有任何撤回入口 ← 本插件补上
撤回实现分两个版本:
session.updateQueue(itemId, { kind: 'remove' })(与官方队列坞的「删除」同一实现)。Client (撤回按钮)
│ host.call('recall', { sessionId, itemId })
▼
Host harness.handle('recall')
│ agents.get(sessionId).inbox.remove(itemId)
▼
效果 消息从 inbox 移除 → inbox 投影更新 → 气泡与条带同步消失运行时 · 「未读插话」数据源 · 撤回调用 0.2.x(含 desktop profile) · useProjection('inbox')['next-step'] 中 source.kind === 'user' 的行 · sessions.binding(sessionId).session.updateQueue(id, { kind: 'remove' })(失败码带命名空间:session/queue-item-not-found) 0.1.x · 会话快照 session.queue 中 placement === 'steering' 的行 · 同上(失败码 queue-item-not-found)
SessionSnapshot 已移除 queue 字段,本地回显改到 pendingSubmissions;插话被接纳后进入 inbox['next-step'],在模型下一步读取前仍可撤回。next-turn(排队消息,已有删除按钮),next-step(插话)这一格由本插件补齐。Host 端逻辑与官方 session.updateQueue 中 kind: 'remove' 的内部实现一致(agent.inbox.remove)。
dsh-recall-unread/
├── README.md # 本文件
├── LICENSE # MIT 许可证
├── .gitignore # Git 忽略规则
├── package.json # 项目元数据(GitHub 展示用)
├── plugin.json # 插件清单(名称 / ID 前缀 / 代码来源)
├── src/
│ ├── host.js # Host 半端源码(动态版,可直接作为 code.host)
│ └── client.js # Client 半端源码(动态版,可直接作为 code.client)
├── plugin/ # 静态 web profile 插件包(安装后随 DSH 加载,推荐)
│ ├── package.json # 安装包元数据(含 dsh.client 声明)
│ ├── host.js # Host 半端(空实现占位,撤回走客户端官方 RPC)
│ └── client.js # Client bundle(__ModuleLoader__ 注册)
└── docs/ # 截图等附加资源(可选)把 plugin/ 目录安装为 DSH web profile 的静态插件:
plugin/ 整个目录复制到 web profile 的 node_modules 下:~/.dsh/profiles/web/node_modules/dsh-recall-unread/~/.dsh/profiles/web/cordis.patch.yml 末尾追加加载行:- insert:
- id: recall-unread
name: dsh-recall-unread说明:静态版在 Client 端直接调用官方会话 RPC session.updateQueue(itemId, { kind: 'remove' })(与官方队列坞的「删除」同一实现),无需动态 RPC,与官方界面行为完全一致。插件不依赖 Amadeus。本项目也可作为 DSH 动态 Cordis 插件(进程级定义)临时体验:
cordis_define)。idPrefix:recallcode.host:粘贴 src/host.js 的完整内容code.client:粘贴 src/client.js 的完整内容name:Recall Sent Unread Messagespurpose:一句话说明用途pluginId / packageId 调用 cordis_run 激活,并在界面批准运行。注意:动态插件是进程级、临时的——DSH 重启后需要重新定义。长期使用请用方式一的静态安装。
本插件零配置、开箱即用,无需任何设置。如需微调,修改 src/client.js 后重新定义(cordis_define)即可,常用可调项:
项 · 位置 · 说明 条带排序 · slots.register(…, order: 30) · 数字越大越靠后,可调整与输入框的贴近程度 提示停留时长 · ctx.timeout(() => setStatus(null), 2500) · 撤回结果提示自动消失的时间(毫秒)
queued)官方队列坞已提供删除,本插件不重复覆盖。DSH 网页启动是 fail-loud 的:任何一个插件加载失败都会整屏显示 Failed to load plugins,导致进不去 DSH。本插件曾因 bundle 里引用 module.exports 而触发 ReferenceError: module is not defined 锁死启动, 现从三层做了固化:
DSH 的 window.__ModuleLoader__.load 的 factory 只注入 `require`,不注入 `module` / `exports`。plugin/client.js 现在完全不引用 module / exports, factory 直接 return { inject, apply }(返回值就是模块导出)。无论怎么改、 怎么重新包装,都不会再出现 module is not defined。文件头有详细警告注释。
⚠️ 不要删掉 `inject` 里的 `'timer'`:Cordis 的 ctx 是 Proxy,未 inject 的服务属性被访问时会直接抛 cannot get property "timer" without inject,导致 apply 阶段失败。客户端的 timer 服务由核心插件@deepseek-ai/dsh-cordis-client-runner提供(ctx.interval/ctx.timeout
已 mixin 到 Context 原型,随 fiber 自动清理),轮询和提示自动消失都依赖它。
同理 Host 半端保留 inject: ['timer'](Host 端 timer 由@deepseek-ai/cordis-plugin-timer 保证,profile 启动时自动加载)。pwsh -NoProfile -ExecutionPolicy Bypass -File tools/install-hooks.ps1安装后每次 git commit 自动运行 tools/check-client-bundle.ps1:
node --check 校验 plugin/client.js / plugin/host.js 语法;module / exports 引用(即会锁死 DSH 的写法)。校验失败会直接拒绝提交,从源头杜绝回归。手动运行同样可以: pwsh -NoProfile -ExecutionPolicy Bypass -File tools/check-client-bundle.ps1。
如果插件又导致启动红屏,不用改任何配置,禁用它即可正常进入 DSH:
# 禁用撤回插件(自动备份 cordis.patch.yml),然后重启 DSH
pwsh -NoProfile -ExecutionPolicy Bypass -File tools/recall-killswitch.ps1
# 恢复撤回插件,然后重启 DSH
pwsh -NoProfile -ExecutionPolicy Bypass -File tools/recall-killswitch.ps1 -Action enable原理:在 ~/.dsh/profiles/web/cordis.patch.yml 的 recall-unread 条目上加/删 disabled: true(loader 对 disabled 条目直接跳过,不导入该插件)。
修改 plugin/client.js 后记得重新部署到~/.dsh/profiles/web/node_modules/dsh-recall-unread/ 并重启 DSH。useProjection('inbox')['next-step'] 读取(SessionSnapshot.queue 已被官方移除), 保留 0.1.x 的 session.queue 回退;预览文本按官方队列坞口径从 content 块折叠; 失败码兼容 session/queue-item-not-found。
amadeus 轮询,改为启用即生效(插件市场/管理页的启用·停用开关控制加载)。
module/exports 引用(factory 直接 return 导出);?.load 注册守卫;inject 保留 ['slots','timer'] 并加 Proxy 访问警告;新增 git 钩子校验与一键急救开关脚本。