前言¶
在 DSH(DeepSeek Harness)里用同一个工作区开多个会话时,上下文默认是断的:新会话不知道上一手做到哪、卡在哪、下一步该接什么。常见做法是手动复制粘贴一段说明,或靠记忆补全,既费事又容易漏关键信息。dsh-handoff 是社区维护的 DSH 插件,按工作区目录维护一份交接文档,会话结束自动压成简短摘要,同目录开新会话时在运行时上下文里读回最近几条。实现为纯插件、零第三方依赖、零外部程序,版本 0.1.0,MIT 许可证。
这是什么¶
插件仓库:wonderandyou/dsh-handoff,维护者 wonderandyou,在 SkillHub 插件目录 分类为「记忆」。一句话定位:每个工作区一份交接文档,会话结束自动写简短摘要,同一工作区开新会话自动读回。
核心行为¶
下面按触发时机说明插件在做什么。
| 时机 | 做什么 |
|---|---|
一轮结束(turn/end) |
等防抖窗口(默认 15 秒),把这一段会话压成一条「标题 / 做了什么 / 结果 / 下次接手」写进该工作区的文档 |
会话销毁(agent/disposed) |
不等防抖,立刻把没落盘的内容写掉 |
| 新会话开头 | 挂一段注入:读该工作区最近 N 条交接塞进运行时上下文,默认只注入一次 |
工具 handoff |
支持 list / read / append / clear / status / flush |
| 设置页「交接」 | 列出所有工作区(无记录标「暂无记录」)、切换查看条目、清空 |
同一工作区、同一会话只占一条记录:会话变长是更新该条,不是追加,避免长会话把文档刷满。
注入只在会话开头来一次¶
默认 injectOnce: true:交接文本只在该会话的第一次模型请求里出现,之后每步返回空。原因是 systemPrompt.context 每步都会重新组装;若每步都塞长文本,多步对话会重复占用上下文,而历史消息里已保留首次注入内容。
默认 injectChars: 10000(约 3100 token)、injectEntries: 20。装不下时会截断并提示还有几条未列出。若需要每步都注入,可设 injectOnce: false,并把 injectChars 调到约 1200。
工作区如何识别¶
按顺序尝试,前一条不行才走下一条:
- DSH 工作区账本
~/.dsh/storages/workspace.json中sessionIds命中(只读,不改写) - 会话
cwd与工作区path相同 - 用
cwd本身作为工作区(未登记目录也可用)
数据存放位置¶
默认目录为 ~/.dsh/handoff(可通过配置 dir 修改):
~/.dsh/handoff/
├── index.json 工作区索引(面板用)
├── stats.json 当日总结次数(预算用)
└── workspaces/
├── 插件-3f2a91cd.json 条目数组(真相源)
└── 插件-3f2a91cd.md 渲染版,便于人工阅读
文件名形如 <目录名>-<路径哈希 8 位>,按规范路径识别;工作区删了再加回,或未登记,交接文件仍可保留。
配置¶
全部在 cordis.patch.yml 中设置,省略项用默认值:
| 键 | 默认 | 说明 |
|---|---|---|
enabled |
true |
总开关 |
dir |
"" |
数据目录;空则 ~/.dsh/handoff |
workspaceFile |
"" |
工作区账本路径;空则 ~/.dsh/storages/workspace.json |
injectOrder |
320 |
交接段在运行时上下文中的排序 |
injectOnce |
true |
每会话只注入一次 |
injectEntries |
20 |
新会话最多读回条数 |
injectChars |
10000 |
读回字符预算 |
maxEntries |
40 |
每工作区最多保留条数 |
autoWrite |
true |
会话结束是否自动写 |
minGapMs |
90000 |
两次总结最小间隔 |
debounceMs |
15000 |
一轮结束后等待再总结 |
maxPerDay |
120 |
每天最多总结次数,0 为不限 |
summarizeModel |
"" |
指定模型;空则自动选较便宜的 flash / mini / lite |
summarizeProvider |
"" |
指定 provider;空则优先官方通道 |
总结失败时(模型不可用、返回非 JSON、拿不到 llm 服务)会回退为「最初需求 + 最后进展」的规则摘要,不会留空条。注入组装失败则返回空,避免拖垮整次模型请求。
安装与启用¶
官方 README 未给出 dsh plugin add 一类命令,安装方式是写入 profile 并链接本地包,改完后重启 DSH。
- 在
~/.dsh/profiles/desktop/package.json的dependencies增加:
"dsh-handoff": "link:<你的路径>/dsh-handoff"
-
同文件
dsh.profile.bundles增加"dsh-handoff"。 -
在
node_modules/dsh-handoff建立 junction 指向插件目录(Windows 示例:New-Item -ItemType Junction)。
DSH 生态是「一切皆插件」;SkillHub 等为社区目录站点,与 DeepSeek / 幻方无官方从属关系。安装前建议阅读仓库源码与 MIT 许可证:插件以当前 DSH 进程权限读写 ~/.dsh/handoff 与会话相关数据。
典型用法¶
工具 handoff¶
在会话中通过 DSH 暴露的 handoff 工具手动 list、read、append、clear、status、flush,与自动写入互补。
把历史会话补进交接¶
插件从安装时刻起才自动记录。可用本机回填脚本(只读会话缓存,不联网):
node _backfill.mjs --dry # 预览将写入内容
node _backfill.mjs # 每工作区补最近 4 个会话
node _backfill.mjs --per=8 # 每工作区多补几条
node _backfill.mjs --all # 含未登记在工作区列表的目录
历史条目只能还原标题和开场需求,结果标为「未判断」。
预览新会话会看到什么¶
不启动 DSH、不改文档,用真实交接数据打印注入文本与长度:
node _preview_inject.mjs # 当前目录
node _preview_inject.mjs D:\软件 # 指定工作区路径
输出包含注入长度、估算 token、条数列表,以及第二次取文本应为 0 字符(验证只注入一次)。
自测¶
仓库内可在无 DSH 进程下跑断言(假 ctx、假 llm、假账本):
node _selftest.mjs # host 侧,71 项断言
node _selftest_client.mjs # 设置页侧,23 项断言
适用场景与注意¶
适合在同一项目目录下频繁开新会话、需要延续「做到哪 / 下次接哪」的开发者。自动总结会调用 LLM,受 minGapMs、maxPerDay、debounceMs 等限制,避免连续对话反复总结。
插件纪律(README 原文要点):只读会话事件,不向会话日志 append;同一会话读回时会排除刚写入的那条,避免循环注入。
结尾¶
dsh-handoff 把交接绑在工作区目录上,用结束时的摘要和新会话开头的一次性注入,减轻换会话时的上下文断裂。目录页:https://www.skillhub.cn/plugins/wonderandyou/dsh-handoff;源码与完整说明:https://github.com/wonderandyou/dsh-handoff。