A compact mid-turn steering box for DeepSeek Harness: text + images, read receipts, and unfinished-draft rescue when a turn ends.
AI 声明:本插件主要由 AI(DeepSeek Harness 中的 deepseek-flash)编写,维护者负责需求、审查和真机测试。
AI disclosure: Primarily written by an AI assistant (deepseek-flash in DeepSeek Harness); the maintainer directed, reviewed, and tested it.
npm 状态:尚未发布到 npm。请先用 GitHub 安装:
dsh plugin --profile web add github:hffek/dsh-steer-notenpm status: Not published to npm yet; install from GitHub for now.
在对话输入框上方增加一条插话栏:任务运行时可以随时补充方向,不用把内容塞进主输入框,也不会覆盖主输入框里的草稿,更不会挡住输入框下方的 token 用量和缓存命中显示。
npm 包还没有发布;现在请用下面的 GitHub 方式安装。
从 GitHub 安装:
dsh plugin --profile web add github:hffek/dsh-steer-note本地开发目录安装:
dsh plugin --profile web add link:/absolute/path/to/dsh-steer-noteDesktop 请把 --profile web 换成 --profile desktop。安装后重启 DSH;Host 半侧的 STEER_NOTE 系统提示词需要重启才会生效。
- 当前会话的 Agent 正在运行,或这个会话里还有未发送的插话草稿时,插话栏会出现。
Enter发送,Shift+Enter换行,Esc让输入框失焦。- 文字和图片可以一起发送:点击图片按钮选择文件,或直接粘贴 / 拖入图片。发送时图片排在文字前面,和原生 composer 的顺序一致。
- 支持 PNG、JPEG、WebP、GIF;张数、单张大小、总大小和边长限制读取原生
imageLimits投影。图片需要当前模型支持视觉输入,否则会返回“当前模型不支持图片输入”。 - 发送使用与原生输入框相同的
session.prompt({ mode: 'steer' })通道,消息会作为正常的“插话”进入会话,并在下一步生效。 - 任务结束时如果插话还没发送,草稿会自动搬到主输入框:文字追加到现有草稿(空草稿则直接填入),图片用
conversation.createDrafts转成原生草稿附件。主输入框正在发送或暂时不可用时,草稿留在插话栏,并显示“放入输入框”重试按钮。 - 搬运成功后释放图片预览 URL;搬运失败时保留草稿和图片。
- 插话草稿按会话持久化:文字写入浏览器 localStorage,切换会话或刷新页面后会恢复;图片也会尽量保存(受 localStorage 容量限制,太大时会提示切换后不保留)。空闲会话里如果还有草稿,插话栏仍会显示,并提供“放入输入框”。
- 插话记录/读取状态:每发送一条插话,历史按钮会记录它,并显示
已读取、待读取、已送达、未读取或已取消。已读取来自 Chat 的steering节点,待读取来自inbox.next-step/next-turn;回合结束仍没读到就标为未读取。点历史条目可把文字回填到插话栏(图片不会回填,需要重新添加)。 - 取消插话:还在 inbox 里、尚未被读取的插话,历史条目右侧会显示“取消”;点了会调用原生
updateQueue({ action: { kind: 'remove' } })。已经读取或已经失效的插话会提示无法取消。 - 插话记录和草稿只保存在本机浏览器 localStorage,按会话隔离,不会上传;它们只包含本插件发出的插话,不包含主输入框的历史消息。
- 自定义 steer 语义:Host 半侧注册一个
STEER_NOTE系统提示词小节,告诉模型“中途到达的用户消息是当前任务的航向修正,不要当成新任务/不要重开任务”。消息本身仍然走原生session.prompt,所以 UI、日志、图片附件和读取状态都保持原生行为。 - 系统提示词小节是 Host 半侧改动,需要重启 DSH 才会生效;Client 半侧的 UI 改动可以通过重载插件生效。
- one-shot 子代理会话不显示插话栏。
测试环境:DSH Desktop 2.0.18 / DSH 0.2.1-rc.2(Web profile)。
依赖的客户端插槽接口:
conversation.input.dockslotuseSessionStatus、useSession、useProjection、useInput、useChat、inputActions
依赖的原生 Remote:
ctx.remote.session.prompt({ mode: 'steer' })ctx.remote.session.updateQueue({ action: { kind: 'remove' } })(取消未读取插话)
降级行为:
- 如果
updateQueue不可用,不显示取消按钮。 - 如果
conversation.createDrafts/inputActions.addAttachments不可用,文字仍会搬到主输入框,图片保留在插话栏并提示手动添加。 - 如果
useChat暂时返回空节点或 inbox 投影不可用,历史状态会停留在“已送达”,不会误报“已读取”。 - 历史/草稿只保存在本机 localStorage;清理浏览器数据会丢失。
注意:图片搬家用到客户端内部服务 ctx.get('conversation') 的 createDrafts,不是公开文档 API;DSH 升级后需要回归测试。文本/图片发送、历史、取消都走原生公开接口。
client.js:渲染插话栏、图片预览和插话记录,注册conversation.input.dockslot(输入框上方的全宽区域,排在 todo / goal / queue 之后、最靠近输入框的位置),并通过ctx.remote.session.prompt提交文字和 image content part;任务结束时用inputActions.setDraft/inputActions.addAttachments+ctx.get('conversation').createDrafts把草稿搬到主输入框;历史/读取状态来自 slot 的useChat(legacy.nodes里的steering/usersource.rpcId)和useProjection('inbox')。客户端插件需在inject中声明remote和remote.session,否则 Cordis 会拒绝读取remote.session。index.js:Host 半侧,注册STEER_NOTE系统提示词小节(ctx.systemPrompt.section),定义“中途消息是航向修正”的模型语义;不提供自定义 Host RPC、不改变消息 source。cordis.patch.yml:向当前 profile 插入插件行。locale/*.json:插件管理器显示用的标题和描述。
package.json 的 exports 必须保留 "./package.json": "./package.json"。Desktop 的 client-modules 在 loader.internal 不可用时通过 require.resolve('<包名>/package.json') 定位清单;缺少这个导出会让该包被缓存为“非客户端插件”,直到重启。
