dsh-context-archive:由模型决定哪些工具结果离开上下文

前言

在 DeepSeek Harness(DSH)里跑智能体时,tool/result 会不断堆进上下文:构建日志、测试输出、大段 JSON 往往一次就上万字符。常见做法是按大小或规则自动剪枝,但剪哪一段并不总是和「模型是否已经读完、后面还要不要引用」一致。

下面介绍社区插件 dsh-context-archive(维护者 kingofpowers,分类:记忆)。它把「可以归档」的决策交给模型:长结果在上下文里带可引用的内联编号,模型调用工具把不再需要的条目写到本会话目录,上下文里只留下可恢复的短存根。

这是什么

dsh-context-archive 是 DSH 的模型驱动工具结果归档插件。长纯文本结果写入上下文时会自动加一行内联编号;模型通过 context_archive 指定编号归档,原文落在 ~/.dsh/sessions/.../archives/,上下文替换为三行存根,需要时仍可按路径读取。

与「按大小自动剪枝」类插件不同,触发权在模型侧:它知道哪份输出已读完、哪份后面还要引用。

内联编号与归档调用

不需要先列清单。每个达到阈值的纯文本结果在写入上下文时,会自动带一行内联编号,例如:

[#a1b2c3d4 · 24810 chars]
npm run build ...

编号是结果正文(去掉该行前缀后)的 sha256 前 8 位,纯函数推导,不依赖映射表。

模型确认某条结果可以离开上下文后,一次调用即可归档多条:

context_archive { ids: ["a1b2c3d4", "9f3e0b21"], note: "已提取所需字段" }

不传 ids 的 context_archive {} 仍可用:返回带工具名和首行预览的清单,用于发现可归档项(例如启用插件之前的历史结果没有内联编号时)。

归档后,该条结果在上下文里变为三行存根,并指向会话目录下的原文文件:

[archived #a1b2c3d4 · bash · 24810 chars / 612 lines]
file: ...\sessions\...\<session-id>\archives\a1b2c3d4.txt
first: npm run build ...

归档位置与行为保证

归档目录由 DSH 的 sessionPersistence.locate() 解析,典型结构如下:

~/.dsh/sessions/<workspace-slug>/<session-id>/archives/
├── a1b2c3d4.txt      # 原文(带 session/seq/tool/时间/note 头)
└── index.json        # 归档索引:编号 → seq / 工具 / 字符数 / note / 时间

拿不到该服务时会回退到 projectKey(cwd) 与会话 id 的等价路径。会话删除时归档随目录一起消失。

插件在资料中承诺的行为包括:

  1. 原文不丢:先写归档文件,再改上下文;写盘失败则不替换。
  2. 只增日志:替换通过 surfaceOp: { op: 'replace' } 追加,原始事件仍在日志中,replay 可复现。
  3. 只改 content:保留 turn/step/message.source 等字段。
  4. 幂等:同一编号再次归档返回 already_archived。
  5. 护栏:最近 keep_turns(默认 3 轮)内的工具结果不可归档;0 表示不设护栏;含图片等非文本块不归档;单次最多 20 条。
  6. 失败放行:单条出错只影响该条,返回逐条状态,不抛异常。

配置

优先级从高到低:单次调用参数 > 运行时文件 > profile 配置。

运行时文件(改完立即生效)

~/.dsh/context-archive.json:

{
  "keepTurns": 3,
  "annotate": true,
  "annotateMinChars": 2000,
  "minChars": 2000,
  "maxAnnotated": 200
}

插件在每次用到配置时重新读取(mtime 缓存),下一条工具结果即按新值处理。删掉该文件则回到 profile 默认值。

profile 配置(需重启 DSH)

在 ~/.dsh/profiles/desktop/cordis.patch.yml 的顶层数组中插入(不要多包一层 config:):

- id: context-archive
  name: dsh-context-archive
  config:
    keepTurns: 3
    annotate: true
    annotateMinChars: 2000
    minChars: 800

常用键(资料中的默认与含义):

键 默认 含义
keepTurns 3 最近多少轮保持不动;0 = 全部可归档
annotate true 是否在长结果前加内联编号
minChars 2000(profile 示例为 800) ≥ 该字符数的结果才带编号、才进清单
nudge true 可归档 ≥5 条时,每 40 个事件最多提醒一次
maxAnnotated 200 同时存在的编号上限;0 = 不限

单次调用可覆盖 keep_turns、min_chars、limit(清单条数,默认 40)、stats(只统计不改动)、note(写入归档头与索引)。

配置非法时插件会明确报错并拒绝装载,不会半加载。

统计面板与阈值建议

安装后若使用 better-sidebar,侧栏会增加「上下文归档」页签:上半部分为分桶统计,下半部分为上述四个阈值,保存后写回 ~/.dsh/context-archive.json。

统计采用增量折叠(订阅 session/event),避免每次全量扫日志;计数落在 ~/.dsh/context-archive-stats.json。需要手动全量重建时:GET /dsh-context-archive/stats?reconcile=1。模型也可执行 context_archive { stats: true } 获取同类数据。

「推荐阈值」来自分桶观测:只有带内联编号的结果才可能被回收,因此回收率分母用「已编号」而非全部 tool/result。

安装与启用

Web profile 安装(资料原文):

dsh plugin --profile web add dsh-context-archive

从源码本地链接开发(改代码后需重启 DSH 才会重新导入模块):

dsh plugin --profile desktop add link:<path-to-this-folder>

资料要求 DSH 0.2.1-rc.1 || 0.2.1-rc.2,Node >=20。插件改动或重装后需重启 DSH(ESM 模块缓存不会随重装自动刷新)。

典型用法小结

  1. 安装插件并确认 minChars / annotate 符合预期(运行时 JSON 或 profile)。
  2. 让智能体在长工具输出上看到 [#xxxxxxxx · N chars] 前缀。
  3. 读完并提取要点后,调用 context_archive 带上 ids 与可选 note。
  4. 上下文变短存根;需要原文时对存根中的 file: 路径做 read 或 grep。
  5. 不确定还有哪些可归档时,先 context_archive {} 看清单。

适用场景与注意

适合:长会话、大量 shell/构建/测试输出,且希望由模型按「已读完、暂不需引用」主动回收,而不是一律按体积剪枝的场景。

注意:

  • 替换后的存根要在下一次模型请求时才会出现在上下文中(本轮请求已发出)。
  • 内联编号只对插件启用之后产生的结果自动添加;更早结果仍可通过空参数清单归档。
  • 插件不联外网,仅在 DSH 回环服务注册 GET /dsh-context-archive/stats 与 GET|POST /dsh-context-archive/config;归档会写盘,内容可能是密钥或隐私,权限与 ~/.dsh 一致,共享机器上需谨慎。
  • 与 dsh-compaction-tool-result-pruner 可同时存在,但以先处理者为准;存根远小于其 8192 字符阈值。
  • 插件以当前 DSH 进程权限运行;安装前请查看源码与 MIT 许可证,确认符合你的安全策略。

社区目录 SkillHub 与 GitHub 仓库由维护者发布,与 DeepSeek / 幻方无官方从属关系;DSH 生态本身是「一切皆插件」,可按需从目录或仓库安装。

结尾

dsh-context-archive 把长 tool/result 的回收交给模型:编号可见、归档可溯、上下文留存根。若你已在 DSH 里被工具输出撑满上下文,可以按上面的安装命令试用,并结合侧栏或 stats 调整 minChars。

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

Xiaoye