dsh-failure-ledger: Add failure ledger and token savings panel to DSH sessions

前言

跑 DSH 智能体的时候,多数调试时间花在重复的失败上:同一个工具以同样的参数失败两次、长错误原文把上下文吃光、上一回合失败的提示到下一回合就不见了。dsh-failure-ledger 是 TMrazbw 维护的一个 profile 级 Host + Client 插件,做四件事:把大型工具错误压缩成短摘要、跨会话统计对话异常、每回合结束给一次零 token 的提醒,再把节省下来的 token 折算成估算金额显示在侧栏面板里。

它不新增 session event type,不改 DSH 核心,只用公开事件与服务;规则默认全开、阈值取保守值,面板可逐条关闭或调整。下面按它实际提供的能力介绍。

这是什么

插件名 dsh-failure-ledger,仓库 https://github.com/TMrazbw/dsh-failure-ledger,分类为「工作流」,当前版本 V2.8(package 0.1.2,194 项测试通过,MIT)。它由两部分组成:

  • Host 入口 index.js,负责 post-execute 摘要、failureLedger 会话投影和 failure_inbox 工具。
  • Client 入口 client.js,负责回合尾提醒(conversation.chat.turnTail)、主面板和侧栏图标。

设计目标是全局失败采集:所有 DSH 会话、代理、子代理自动生效,同一套规则和统计。

核心功能

大错误压缩与落盘

长错误原文不进上下文,而是写入 failure-reports 目录(默认 D:\deepseek插件\dsh-failure-ledger\failure-reports),模型只看到短摘要 + 下一步 + 报告路径。只有大错误才替换;小错误或含图片的结果只加一条插件 hint;下游 block 原样保留;同一 callId 不重复注入。

落盘的数据包括 index.jsonl、savings.jsonl、anomalies.jsonl、totals.json、playbook.jsonl,以及 reports\、raw\、handoffs\、INBOX.md。totals.json 单调累计,清理明细不会让它回退;空间策略只有两条:每 200 次写入检查一次,明细总上限 100 MB。

对话异常统计

异常通过 INBOX.md、index.jsonl、reports/<fingerprint>.md 和 failure_inbox 工具暴露。会话级统计由 failureLedger 投影提供(n1/n2/saved/usage),摘要里的 Tokens: 标记让重放也能恢复节省数。子代理按 sessionId 去重聚合。

V2.6 增加上下文归因:面板显示当前 tokens / window、本回合增量、压缩次数、主要来源 Top3 与最近 5 次请求,并引入 contextJump 规则(默认 8000 tokens + 10% 窗口,最多 3 条),近似 ±10%,不压缩、不阻断、不注入模型。

每回合提醒与面板

回合尾提醒默认走 UI(零模型请求),只显示本回合统计(turnN1 / turnSavedTokens);本回合没有失败或节省时不显示。模型可见的提醒是 V1.5 的可选开关,默认关闭。conversation.composer.dock 另有一个会话累计徽标,文本形如 失败 n · 异常 m · 节省 x,无数据时不显示。

打开面板的方式有三种:

  • 输入 /dfl-ui,Client 在命令列表显示左侧 PanelIcon、label DFL-UI,并直接打开面板。输入名仍是平台要求的小写。
  • 直接说「打开对话异常统计」或「打开 DFL-UI 面板」,模型会调用 open_failure_ledger 工具。
  • 点击侧栏的「对话异常统计」图标。

面板包含概览卡片(含「未解决」数量)、错误源、异常明细、最近失败(只列 10 条)、按模型节省与只读估算金额,以及规则与参数表单。规则与参数放在诊断/统计之前且不折叠;Guard 只显示已出现(hits > 0)的,最多 20 条,超出的和未出现的收进折叠区。保存走自有 POST api/failure-ledger.admin + Host settings,只允许 .volatile() 字段,并落 profile 配置。

Guard 观察与防复发

V2.0 起有 13 个默认 Guard,覆盖 edit/read 路径、搜索 asar、路径检查、命令路径、超时、sandbox、stale write、PWSh 启动失败、未知工具、依赖缺失、人工验证、浏览器下载/授权等。失败落盘后写入 guard-hits.jsonl 并累加 guards.json;下一次 agent/pre-step 注入一行防复发提示(≤320 字符),同一 turn 最多一次、60s TTL,不阻断、不创建额外模型请求。Guard 只进入观察与提示,A 模式永不 block。

自愈、固化与自动交接

后续版本在这个骨架上加了几条机制:

  • V2.5 A:Guard 未命中的新失败自动进入下一步,形如 [未解决失败] tool/category/code: hint,不阻断。
  • V2.5 B:同一 turn、同一 tool,失败后不同参数的成功调用视为自愈,自动 resolve、生成 learned Guard 与回归草案,并清理 pending hint;默认 selfHeal.enabled=true,窗口 180s。
  • V2.6 Step 4 固化:resolve 自动生成/更新 learned-<fingerprint> Guard,写出 regressions/<fingerprint>.md;playbook 记录 guardId / regression,面板显示「固化/未固化」。旧 playbook 不回填,避免把测试证据变成规则。
  • V2.7 Step 1 unstick:同一 session / fingerprint 第 2 次失败时提示一次,记下共同假设、最小 probe、三个不同机制,不第三次变体。
  • V2.7 Step 2 claimWithoutEvidence(观察版):记录 lastEdit / lastVerify / lastClaim,声称完成但最近编辑后没有成功验证则记异常,只进面板与异常计数,不注入 hint。
  • V2.8 换对话自动 handoff:不再提供按钮,由 Agent 判断用户是否表达「换对话 / 新开会话 / 下次继续 / 先到这里」,调用 failure_inbox action=handoff。工具返回已调用功能、写入路径、用户下一步,输出 Goal / Done / Open failures / Open questions / Key facts,只写事实、不做 LLM 语义总结,写入 handoffs/<sessionId>.md。

特别注意 Goal 只取真实用户消息(跳过 runner 注入块与 DFL 通知),Done 只写路径/命令摘要。

Token 估算与花费

lib/savings.js 与 lib/cost.js 按 usage 与官方价格估算。金额估算只计直接压缩节省,不乘后续重发,默认取空闲时段缓存未命中输入价;formatCNY 与 snapshot 的 estimatedCNY 都只保留 2 位小数(分)。

价格口径来自 DeepSeek 官方文档(抓取于 2026-10-22),单位为人民币/百万 tokens:

模型 输入·缓存命中(空闲/高峰) 输入·缓存未命中(空闲/高峰) 输出(空闲/高峰)
deepseek-flash 0.02 / 0.04 元 1.00 / 2.00 元 4.00 / 8.00 元
deepseek-v4-pro 0.15 / 0.30 元 4.50 / 9.00 元 13.50 / 27.00 元

峰值时段为北京时间周一至周五 09:00–12:00、14:00–18:00(法定节假日除外),空闲价为高峰价的一半。未知模型按 flash 回退。预算功能默认关闭,可设本会话/今日 CNY 与预警比例。这些数字只是本地估算,不是账单。

安装与启用

README 给出的安装方式是 plugin_manager install_bundle,指向 GitHub 仓库:

plugin_manager install_bundle
target: https://github.com/TMrazbw/dsh-failure-ledger

本地 desktop profile 已通过该命令安装(application: applied)。按插件维护者的说明,修改 Host 代码后,DSH 的 ESM 模块缓存要求重启应用;Client 代码变化则要求刷新 Web 页面。

典型用法

下面是一套可复现的最小流程。

1、跑一轮包含超大工具错误的会话,让插件把长错误压缩并落盘。错误原文会出现在 failure-reports\reports\,索引在 index.jsonl。

2、输出 /dfl-ui 打开面板,确认概览卡片的未解决数量、错误源和近期失败。若要让 Agent 主动读取,可用 failure_inbox 工具:

failure_inbox action="unresolved"

它返回按 fingerprint 分组的未解决失败;action="playbook" 则返回已解决的修复记录。这些后台读取不依赖 UI。

3、想结束当前对话、把上下文交接出去时直接说「先到这里」,让 Agent 决定是否调用:

failure_inbox action=handoff

工具会写出 handoffs/<sessionId>.md 并返回用户下一步。

适用场景与注意

适合长期跑 DSH 智能体、希望事后复盘失败规律、或想量化大错误压缩带来的 token 节省的开发者。它做的是观察与提示,不是阻断器:默认不调用 LLM,不把统计写入 session log,提醒默认零模型请求。

需要注意三点:

  • 插件以当前 dsh 进程的权限运行,安装前应先阅读源码与 LICENSE(MIT)。
  • 错误原文、报告、日志只保存在本机,采集按工具定制并脱敏;面板写参数前必须确认,且只允许 .volatile() 字段。
  • 金额与节省都是估算值,不得作为计费或对账依据。

结尾

dsh-failure-ledger 的价值在于把「失败」从一次性的上下文噪声变成可累积、可查询、可交接的台账,同时不打断当前对话。目录页在 https://www.skillhub.cn/plugins/TMrazbw/dsh-failure-ledger ,代码与文档在 https://github.com/TMrazbw/dsh-failure-ledger 。

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

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

Xiaoye