dsh-prolong-memory
DeepSeek Harness(DSH) 的程序化记忆插件:harness 把会话中每个 durable 事件追加成工作区里一份结构化 log.txt,agent 用 grep / Python 程序化检索。不引入子代理、不做向量检索。
自诊断内建:写探针(probe)、/prolong 状态命令、权限拒绝计数器 —— 当权限 / 沙箱类插件限制本插件时,能立刻区分是"宿主侧写文件被拦"还是"agent 检索调用被拒"。
目的
长程 agent 会话的细节会被上下文压缩(compaction)丢掉。DSH 自带的摘要器对显式标记为重要的信息很忠实,但没人预先标记的操作细节——确切的命令行、退出码、文件路径、报错文本——会被摘要框架化掉。本插件保留一份逐字、可 grep 的完整记录,并通过一小段系统提示词教会 agent 在"感觉上下文缺失"时主动查阅。
这一点用可复现的 A/B 实验验证过(见 [experiments/compaction-ab](experiments/compaction-ab/README.md)):
| 场景 | 启用插件 | 禁用插件 |
|---|---|---|
| 事实明说"请记住" | 6/6 | 6/6(DSH 摘要已足够,此场景插件冗余) |
| 事实埋在"无关紧要"的命令细节里 | 6/6 | 0/6(agent grep log.txt 找回) |
与 PRO-LONG 的关系
本项目复刻 PRO-LONG(*Programmatic Memory Enables Long-Horizon Reasoning*)的核心思想:
- 保留:由 harness(而非模型)把事件追加成只增的结构化日志;模型按需用普通程序化工具(grep / Python)读回。
- 刻意不移植:PRO-LONG 的子代理和一切向量 / embedding 检索。检索直接复用 DSH Standard/Minimal profile 自带的 bash / 文件工具。
与 DeepSeek Harness 的关系
这是一个 DSH 插件,不是 fork、也不是补丁。组合了三个公开扩展点(全部对照 rc.7 源码核实):
| 能力 | 扩展点 | 说明 |
|---|---|---|
事件 → log.txt | session/event 观察器 | 同步热路径通知;写盘排队异步 flush,绝不阻塞 agent loop |
| PRO-LONG 提示词 | ctx.systemPrompt.section() | order=150(工具指导区间 100–199),约 20 行 |
/prolong status | ctx.commands.register() | 人类命令,不经模型轮次;profile 无 ctx.commands 时自动跳过(ctx.inject 惰性组合) |
| 程序化检索 | 无新增 | 复用 profile 自带的 bash / 文件工具 |
> DSH 处于 developer preview,官方声明会有破坏性变更。升级 DSH 后请运行 npm run test:integration 重新验证扩展点契约(冒烟测试挂载真实的 cordis / dsh-session / dsh-system-prompt / dsh-commands,且永远测仓库源码而非已安装副本)。
安装
dsh plugin --profile web add /path/to/dsh-prolong-memory
# 或直接从 GitHub 安装:
dsh plugin --profile web add github:ycr40/dsh-prolong-memory包内 package.json 声明了 "dsh": { "bundle": "cordis.yml" },安装后自动进入该 profile 的 bundle 层。验证实际组合树:
dsh --profile web --dump-config # 应能看到 id: prolong-memory 条目使用
挂载后无需任何操作——该 profile 的每个会话都会在工作区得到一份 log.txt,首节是写探针。之后可以直接问 agent 早先的操作细节("刚才那条失败的命令原文是什么?"),提示词段会引导它去 grep 日志。
随时检查插件健康状态:
/prolong statusprolong-memory status
log file: log.txt (per-session workspace)
window: full
session 9f3c…
path: /work/demo/log.txt
writable=yes sections=128 lastSeq=341
denied tool calls referencing the log: 0配置(cordis.yml / patch overlay)
| 字段 | 默认 | 含义 |
|---|---|---|
logFile | log.txt | 工作区内的日志文件名(拒绝路径穿越,误配置 fail loud) |
logWindow | 0 | 0=全量;N>0=只保留最近 N 节;-1=禁用(no-log 消融) |
promptOrder | 150 | prompt 段排序 |
registerPrompt / registerCommand | true | 可分别关闭提示词段 / 状态命令 |
denyKeep | 20 | 状态报告中保留的最近被拒调用条数 |
临时调试可用 overlay 而不改 profile:dsh --profile web --patch ./overlay.yml。
自诊断:发现权限 / 沙箱插件的限制
两类限制症状不同:
1. agent 检索被拦(tools/pre-execute 策略)→ 拒绝本身是 durable 的 tool/result 错误事件。deny 计数器按 callId 精确配对 tool/call 与 tool/result(缺失时按 (turn, step) FIFO 兜底),统计引用了 log.txt 的被拒调用,/prolong status 会列出并提示 suspect a tools/pre-execute policy plugin。 2. 宿主侧写 log.txt 失败(ctx.sandbox / fs 策略)→ 否则是静默的。每个会话的首个事件触发探针写入,失败即 writable=NO + logger 警告,/prolong status 提示 suspect a permission/sandbox plugin。
deny 判定语义已对照 rc.7 源码校准:策略拒绝 = message.isError === true 且无 data.error(带 data.error 的是 abort / 工具异常,不计入)。
开发与测试
测试优先开发;核心逻辑(格式化 / 写入器 / 计数器 / 状态报告 / 配置 / 提示词)全部是不依赖 Cordis 的纯模块(src/core/),src/index.js 只做接线:
npm test # node --test,48 个用例,含 mock-Context 接线测试
npm run test:integration # 针对本机真实 DSH 运行时的集成冒烟集成测试的模块定位规则:DSH_MODULES > DSH_HOME/profiles/node_modules > ~/.dsh/profiles/node_modules。
已知限制
logWindow > 0的裁剪基于本进程内观察到的事件重写文件;重启后窗口从空重新累积。后续可加"从 durable 会话日志重建"(DSH 的会话日志本来就是全量的)。assistant/chunk、request/header等非叙事事件不落盘,保持 log.txt 可 grep 的信噪比。- 实验证据是方向性的(每变体每模式 1 轮),不是统计性的。
许可证
MIT — 见 [LICENSE](LICENSE)。