dsh-failbook
失败账本 — DeepSeek Harness 工具失败记录、签名聚类与失败感知重试拦截(含 Web UI 面板)。Failure ledger for DeepSeek Harness: capture, cluster, persist and learn from failed tool calls, with a failure-aware retry guard and a Web UI panel.
安装
npx -p @deepseek-ai/dsh dsh plugin --profile web add github:G1en-114/dsh-failbook说明文档
阅读完整 README ↗安装到你的 web 配置
dsh plugin --profile web add "github:G1en-114/dsh-failbook#main"
或手动编辑配置目录的 `cordis.patch.yml`:
```yaml
- insert:
- id: failbook
name: dsh-failbook
config:
enabled: true
重启 dsh web 后,打开 设置 → 失败账本 即可看到面板。
配置
| 配置项 | 默认 | 说明 |
|---|---|---|
enabled | true | 总开关 |
retryGuardThreshold | 2 | 近窗口内同一签名失败 ≥N 次触发提醒;0 关闭提醒(只记录) |
reminderCooldownSec | 300 | 同一桶两次提醒的最小间隔(秒),防刷屏 |
reminderLocale | 'zh' | 提醒文案语言:zh / en |
exitFailureMin | 2 | 退出码 ≥ 此值记为失败(1 常是 grep 无匹配等正常负结果) |
recentWindowSec | 86400 | "近窗口"滚动窗口(秒) |
maxArgsChars / maxDetailChars | 160 / 400 | 参数/输出预览截断长度 |
patterns | [] | 额外错误模式,格式 分类:正则,如 build-fail:BUILD FAILED |
excludeTools | ['todo_write'] | 不追踪的工具名(支持 * 通配) |
maxBuckets | 1000 | 账本桶上限,超出按最近使用淘汰 |
示例:把退出码 1 也当失败,并拦截得更激进:
- insert:
- id: failbook
name: dsh-failbook
config:
exitFailureMin: 1
retryGuardThreshold: 1
reminderLocale: 'en'
工作原理
工具调用 ──▶ tools/post-execute 瀑布
│
▼
detectFailure(exec, result) 结构化错误?沙箱拒绝?退出码?错误文本?
│
▼
签名 = tool:category 如 bash:command-not-found
│
▼
ledger.record() ──▶ ctx.storageDomain(跨会话持久化)
│
▼
recentCount ≥ 阈值 且 未静音 且 冷却期外?
│
▼ 是
createUserMessage 注入 additionalContexts
(下一轮请求模型可见,0 额外 token 的提醒)
- 失败检测:
result.isError(结构化错误)→ 沙箱[sandbox: …]标记 → 保守错误文本(command not found/ENOENT/EACCES/npm ERR!/fatal:等)→ 退出码兜底。取消(ABORTED)不计为失败。 - 提醒通道:与官方
repeat-tool-reminder相同的additionalContexts机制——不修改工具结果、不打断管线,模型下轮请求自然看到。 - 安全边界:Web API 仅回环地址可访问;账本只存截断预览,完整命令输出永不离开宿主。
与现有方案对比
| 官方 repeat-tool-reminder | dsh-fail-logger | dsh-failbook | |
|---|---|---|---|
| 检测维度 | 参数完全相同的连续重复 | 失败记录 | 失败签名聚类(换参数也拦) |
| 持久化 | 内存 | skill 文件 | storageDomain 跨会话 |
| 重试拦截 | ✅(仅相同调用) | ❌ | ✅(签名 + 冷却 + 静音) |
| Web UI | ❌ | ❌ | ✅ 设置面板 |
| 跨会话统计 | ❌ | 部分 | ✅ 聚合/趋势 |
Roadmap
- 失败记录 + 签名聚类 + 持久化
- 失败感知重试拦截(阈值/冷却/静音)
- Web UI 面板(Top 签名、静音、清空)
- 会话开场简报:新会话注入本工作区 Top 失败模式
- 失败趋势图(按天/工具)
- 一键导出账本(JSON/CSV)
常见问题
Q: 会不会误报?
默认只认确凿标记:[exit code: N]、[sandbox: …] 是 DSH 自己生成的;文本模式全部带词边界且保守。误报桶可以直接在面板静音,或加进 excludeTools。
Q: 提醒会不会刷屏 / 烧 token? 每个桶默认 5 分钟冷却 + 阈值后才提醒,提醒文本有截断上限,且只在工具调用失败时产生。
Q: headless 模式能用吗?
能。没有 storageDomain 服务的配置会自动降级为进程内账本(重启清空),记录与拦截功能不变。
开发
npm install
npm run typecheck # 类型检查
npm test # 构建 + 27 个单元测试
npm run test:integration # 真机集成验证(见下)
npm run build # tsc(宿主) + esbuild(客户端 bundle)
集成验证(已在本仓库实测通过)
scripts/integration-harness.mjs 用真实 DSH 运行时(cordis + tools 管线 + storage-json + storage-domain)跑完整链路:
- 注册一个固定返回
[exit code: 2]的假工具; - 以 agent 身份连续执行 3 次 → 第 2 次起注入重试拦截提醒(含失败原因与建议);
- 断言账本以签名
fake_fail:exit:2落盘(count=3、remindersSent=2); - 读取存储介质文件验证跨进程持久化——与
dsh web重启后/api/dsh-failbook/ledger读到的是同一份数据。
实测结果(curl /api/dsh-failbook/ledger,服务器重启后):
{"buckets":[{"signature":"fake_fail:exit:2","category":"exit:2","count":3,
"recentCount":3,"remindersSent":2,...}],"storage":"domain"}
仓库结构:
src/
├── index.ts # 宿主入口:post-execute 观察者 + 路由注册
├── signature.ts # 失败检测与签名提取
├── store.ts # 账本(storageDomain / 内存双后端)
├── reminder.ts # 提醒构造与注入
├── routes.ts # /api/dsh-failbook/* 回环 API
├── shared.ts # 宿主/客户端共享类型
└── client/ # 浏览器半:设置面板(React + fetch)
English
dsh-failbook — a failure ledger for DeepSeek Harness: every failed tool call is recorded, clustered by failure signature (not by arguments), and persisted across sessions via ctx.storageDomain. When the same failure mode recurs past a threshold, the failure-aware retry guard injects a short advisory into the agent's next request — catching "same mistake, different arguments" loops that identical-args guards miss.
- Install:
dsh plugin --profile web add "github:/dsh-failbook#main" - UI: Settings → 失败账本 (Failbook) — top failure signatures, counts, mute, clear
- Detection: structured errors, non-zero exits (default ≥2), sandbox denials, conservative error-text signatures; cancellations are never counted
- Safety: loopback-only API; only truncated previews are stored
- License: MIT
License
MIT © 2026 dsh-failbook contributors
配置
| 配置项 | 默认 | 说明 |
|---|---|---|
enabled | true | 总开关 |
retryGuardThreshold | 2 | 近窗口内同一签名失败 ≥N 次触发提醒;0 关闭提醒(只记录) |
reminderCooldownSec | 300 | 同一桶两次提醒的最小间隔(秒),防刷屏 |
reminderLocale | 'zh' | 提醒文案语言:zh / en |
exitFailureMin | 2 | 退出码 ≥ 此值记为失败(1 常是 grep 无匹配等正常负结果) |
recentWindowSec | 86400 | "近窗口"滚动窗口(秒) |
maxArgsChars / maxDetailChars | 160 / 400 | 参数/输出预览截断长度 |
patterns | [] | 额外错误模式,格式 分类:正则,如 build-fail:BUILD FAILED |
excludeTools | ['todo_write'] | 不追踪的工具名(支持 * 通配) |
maxBuckets | 1000 | 账本桶上限,超出按最近使用淘汰 |
示例:把退出码 1 也当失败,并拦截得更激进:
- insert:
- id: failbook
name: dsh-failbook
config:
exitFailureMin: 1
retryGuardThreshold: 1
reminderLocale: 'en'