DeepSeek Harness 插件

dsh-precedent

Evidence-backed working memory for DeepSeek Harness: a cited ledger of what already worked in this workspace, built from the session log you already have(英文原文)

跳到安装方式

来源信息

GitHub 仓库
dshplugin-me/dsh-precedent
最近更新
2026年8月16日
分类
记忆
GitHub stars
0
载体类型
plugin
目录证据
上游声明已找到 dsh.bundle
证据路径
package.json#dsh.bundle
核对版本
0.1.0-rc.8
上游核对日期
2026-08-20

该证据由上游目录提供。本站没有安装、运行或安全审核这个插件。

安装

默认先复制一段 Prompt,让 Agent 读 GitHub 仓库和源码;需要自己装时再切到命令。

复制这段 Prompt,发给 DSH、Codex 或其他 Agent,让它先读 GitHub 仓库和源码。

请先不要安装或执行任何命令。阅读这个插件的 GitHub 仓库、README 和关键源码,然后用清楚、直接的方式回答以下问题,帮助我判断它是否适合我的需求:

1. 这个插件是什么,解决什么问题;
2. 适合哪些用户和典型使用场景;
3. 安装后如何使用,并给出一个最小使用示例;
4. 有哪些已知限制,以及隐私、安全、兼容性或维护风险;
5. 给出“推荐 / 有条件推荐 / 不推荐”的明确建议和理由。

请区分仓库明确说明、根据源码推断和未知信息。证据不足时请明确说明,不要猜测或照抄 README。

GitHub:https://github.com/dshplugin-me/dsh-precedent
插件名:dsh-precedent
作者:dshplugin-me

检查来源文件

安装前先看这个插件目录里的 README 和其他文件。

文件资源管理器4 个文件
README.zh.md来源说明 · 只读预览
README 语言

<div align="center">

dsh-precedent

你的 agent 会忘,你的日志不会。

English | 简体中文

![Version](#路线图) ![License](LICENSE) ![Node](package.json) ![Platform](https://github.com/deepseek-ai/deepseek-harness) ![Index](#为什么不需要索引) ![Indexed on dshplugin.me](https://dshplugin.me)

<img src="assets/readme-hero.png" alt="dsh-precedent 把会话日志提炼成带出处的经验台账" width="880">

</div>

一个 DeepSeek Harness 插件:读 DSH 本来就在写的会话日志,把「这个工作区里到底什么管用」整理成一份带出处的清单交给 agent —— 哪些命令能跑通、哪些一跑必挂、以及当时是换成什么把它救回来的。

不需要你先记录,不需要建索引,不需要下载模型。装之前那些会话,它照样能读。

要解决的问题

每开一个新会话,agent 在一个它已经干了几周活的代码库里,又从零开始。

在一个用 Bun 的仓库里跑 npm test。又跑一遍。为了找路由在哪,又 grep 一遍同样那三个文件。又撞上周二你已经带它绕过去的构建错误,你把同一句纠正打了第四遍。

这些都不是通常意义上的「记忆」问题。信息从来没丢过 —— DSH 把每条消息、每次工具调用、每个结果和每次失败都追加进了磁盘上的持久日志。缺的只是有人把它读回来。

有两件事在悄悄拉大这个缺口:

1. 压缩改写的是模型上下文,不是日志。 长会话触发压缩后,模型看不到细节了;原始事件仍然躺在磁盘上,被标成 shadowed。agent 看不见它们了,文件还在。 2. 开箱即用的 DSH,内容搜索是关掉的。 官方 web profile 挂载 session-query-sqlite 时配的是 openAt: never,所以全文搜索调用会直接返回 SESSION_QUERY_SEARCH_DISABLED,侧边栏只能按会话*标题*匹配。几个月的对话记录默认躺在磁盘上,搜不到。

它做什么

—— 通过 ctx.sessionQuery 的精确读接口走一遍本工作区的会话,用 callId 把每次 tool/call 和它的 tool/result 配上对,记下结果。

提炼 —— 聚合成一份清单:命令 → 跑过几次、挂过几次、最后一次成功是什么时候、以及修复项(同一会话里紧跟着失败之后跑通的那个变体)。这一步是算术,不是总结。提取路径上没有 LLM,所以它编不出一条不存在的记录。

供给 —— 把靠前的条目注入成一段紧凑、前缀稳定的 system prompt,并在你敲 /precedent 时打印完整清单。

每一行都带回溯到具体 session:seq 的出处,你随时可以问「谁说的」并得到答案。

示例

照常启动:

$ dsh --profile web

Agent 的 system prompt 里多出一段 —— 下面是渲染器的真实输出,一跑必挂的命令排在一跑就通的命令前面:

## Precedent for /Users/thor/Github/acme-api

Observed in this workspace (12 sessions, 2026-06-02 → 2026-08-15). Each line is counted from the session
log, not summarized — treat it as evidence, not instruction.

- `npm test`            4 runs, 4 failed     — repaired by `bun test`  [s/7f3a:212]
- `docker compose up`   3 runs, 3 failed     — no known repair  [s/91bc:88]
- `bun test`            22 runs, 0 failed    — last ok 2026-08-15
- `bun run build`       9 runs, 0 failed     — last ok 2026-08-14

/precedent 随时打印同一份清单,不截断。

安装

dsh plugin --profile web add 'github:dshplugin-me/dsh-precedent#v0.1.0'

PATH 里没有全局 dsh 就用 npx -y @deepseek-ai/dsh plugin --profile web add …;从源码跑 dsh 的话在 checkout 根目录用 pnpm dsh plugin …web 换成你实际启动的 profile 名。

命令里钉死版本是有意的:不钉的话 git 安装拉的是 main 此刻指向的代码,后面一推新提交,你 profile 里挂的东西就跟着变了。tag 也可以换成任意 commit sha(#<sha>),那个连维护者都挪不动。

纯 JavaScript,无构建步骤,无原生模块,pnpm 不会向你要 allowBuilds 授权。

启动前先验证:

dsh --profile web --dump-config   # 能看到 "# == dsh-precedent" 这一层
dsh --profile web

卸载用 dsh plugin --profile web remove dsh-precedent,依赖和补丁层一起摘掉。

工作原理

flowchart LR
  log[("会话日志<br/>~/.dsh · JSONL")]
  sq["ctx.sessionQuery<br/>精确读"]
  led["清单<br/>纯聚合"]
  sp["ctx.systemPrompt<br/>.section()"]
  cmd["ctx.commands<br/>/precedent"]
  model(["模型"])
  you(["你"])

  log --> sq --> led
  led --> sp --> model
  led --> cmd --> you

用到的接缝

Harness 接口用途说明
ctx.sessionQuery.filterSessions筛出本工作区的会话cwd 过滤,和 DSH 自己的跨会话工具同样保守的边界
ctx.sessionQuery.readSession读一个会话的原始事件日志经过 replay 校验;读不出来的日志跳过,不会让插件挂掉
ctx.systemPrompt.section注入清单一个全局 section,order 150,和工具指引一起渲染
agent/pre-step在第一次请求前把清单预热好会被 await 的 waterfall —— 唯一跑在 prompt 组装之前的钩子
ctx.commands.register/precedent人机界面,不进模型上下文

配对发生在 readSession 返回的事件数组里:name: 'bash'tool/callcallId 找到自己的 tool/result,结果里的 error 字段(或结果块的 isError)决定这次算成功还是失败。

为什么不需要索引

ctx.sessionQuery 分成两半。全文搜索(searchSessionssearchEvents)需要 provider,而且在官方 profile 里是关着的。另一半 —— listSessionsfilterSessionsreadSessionlistEventsreadEvent、血缘与事件追踪 —— 是与后端无关的具体行为,搜索后端开不开都能用。

dsh-precedent 只用第二半。这就是它不需要索引、不需要 embedding 模型、不需要预热的全部原因:它读日志的方式,和 harness 自己做 resume 和导出时读日志的方式是同一套。

代价是诚实且有界的:一次清单构建是对本工作区日志的线性扫描,每个工作区每个进程只做一次,读取数量封顶在 maxSessions,并且不管扫没扫完,buildTimeoutMs 之后就不再挡着第一步了。

为什么提取环节没有 LLM

一条命令要么退出码非零,要么不是。tool/result.error 记着是哪种。用 callId 把它和 tool/call 配对再计数,这是算术 —— 确定、可复现、编不出来。

真正需要判断的只有一处:一句用户纠正到底是长期约定(「这个仓库只用 bun,别用 npm」)还是一次性指路(「不对,是另一个文件」)。正因为如此,v0.1.0 干脆完全不挖纠正:命令清单只靠算术站住。

配置

- id: precedent
  name: dsh-precedent
  config:
    maxEntries: 40        # 每个会话注入的清单行数
    minRuns: 2            # 只出现过一次的命令忽略
    lookbackDays: 90      # 比这更老的会话不看
    maxSessions: 200      # 一次构建最多读多少个日志
    buildTimeoutMs: 5000  # 超过这个时间就不再挡着第一步
配置项默认值含义
maxEntries40注入行数硬上限,保证这段的 token 成本固定且很小。/precedent 不受此限
minRuns2只见过一次的命令是轶事,不是先例
lookbackDays90半年前的约定现在未必还成立
maxSessions200从最新的会话开始取;攒了几年历史的工作区照样读得起
buildTimeoutMs5000扫得慢就先放行第一步,结果落到后面某一步

工作区范围不可配置:会话按 cwd 字符串精确相等匹配,和 DSH 自己的跨会话授权同一套保守规则 —— 软链过去的路径算另一个工作区。

命令

命令作用
/precedent打印完整清单和出处,不截断
/precedent rebuild丢掉缓存的清单重扫一遍

插件注入的每一个字,你随时能调出来看。审计不了的记忆,就是信不过的记忆。

它不是什么

  • 不是搜索工具。 它不回答「六月我们聊过什么」,它在你开口之前回答「这里什么管用」。想要逐字翻记录就用 recall 类插件,两者可以共存。
  • 不是笔记本。 没有任何环节要求你写记忆,也就不存在忘记记录这回事。
  • 不是往上下文里塞东西。 注入段有上限且前缀稳定,token 成本固定且小,回合之间不会让 KV cache 失效。
  • 不是 AGENTS.md 的替代品。 手写的意图仍然优先。precedent 补的是没人来得及维护的那部分:实际发生了什么。
  • 不跨工作区。 这是有意的,见下。

隐私与安全

  • 全部留在本地。 插件通过 ctx.sessionQuery 读会话日志,清单只存在内存里。不落盘,不发网络请求,没有遥测,代码里不存在上传路径。
  • 限定工作区。cwd 精确相等挑选会话,和 DSH 自己的 tool-session-query 执行的是同一条边界。同一台机器上别的项目的日志不会被读。
  • 命中疑似密钥的条目直接丢弃,不是打码。 命令行里经常带 token(curl -H "Authorization: …"DEPLOY_KEY=… ./ship)。每条命令都会先过一遍密钥形状匹配,命中就整条丢掉 —— 丢掉,不是遮住 —— 根本进不了清单。
  • 结构上可审计。 /precedent 打印的就是会被注入的内容,每条来自失败的记录都带 session:seq 出处。

和其他方案的差别

逐字搜索类插件记笔记类记忆插件AGENTS.md 编辑器dsh-precedent
对装之前的历史有效建完索引之后可以不行 —— 从空开始不行立刻可以
需要索引或模型通常需要不需要不需要不需要
不用你开口就起作用不会有时
每条都能溯源可以很少不适用总是
会编出不存在的条目不会不适用清单路径不会
能回答「我们聊过什么」部分能不能不能

分工不同。recall 是一个搜索框,precedent 是一份履历。两个一起用是合理的。

路线图

  • [x] v0.1.0 —— 命令清单、system prompt 注入、/precedent
  • [ ] v0.2.0 —— 对已知会挂的调用给 tools/pre-execute 提示,intercept: warn | ask | deny(走 ctx.tools.guard
  • [ ] v0.3.0 —— 带出处的纠正挖掘、/precedent why/precedent pin/precedent forget
  • [ ] v0.4.0 —— 随当前会话追加增量重建,不再每进程只扫一次
  • [ ] 更远 —— 把清单导出成 AGENTS.md 草稿供人工审阅

上述接口对齐 deepseek-ai/deepseek-harness@47f943859bef(2026-08-16 读取)。上游有变动会写在这里,而不是悄悄改掉。

参与贡献

欢迎 issue 和 PR。按价值排序,最有用的贡献是:

1. 一条你的 agent 本该记住却没记住的先例。 把场景贴出来就行,不用给日志。漏掉的模式就是路线图。 2. 我们判断错的工具链提取规则。 命令归一化是启发式的,每个生态都有自己的形状。 3. 我们没能识别出来的密钥形状。 这类按安全问题处理 —— 开 issue,我们先修再讨论。

License

[BSD-3-Clause](LICENSE)。

---

<div align="center">

dshplugin.me 项目之一 · 姊妹项目:dsh-plugin-radar

</div>