dsh-usage-board
DSH(DeepSeek Harness / Cordis)的用量·成本·诊断面板插件:实时采集 token/耗时/错误指标,冷启动回溯全部历史会话,按 Sub-agent DAG 聚合,需要时按指针回查原文。
- 架构:CQRS——DSH 会话文件是只读的 Write Model,本插件维护的 SQLite 是可重建的 Read Model。
- 双层读模型:暖层 SQLite 物化汇总 + 热层进程内不可变快照,UI 一次 fetch 拿到渲染就绪的全帧。
- 零依赖:零运行时依赖、零 Worker、零本地编译;仅用 Node ≥ 22.5 内置
node:sqlite。
快速上手
npm install # 只装 devDependencies(typescript 与 @types/node)
npm test # node --test,全量测试(无网络、无外部进程)
npm run typecheck
作为库嵌入(结构化 HostContext,无需真实 Cordis 运行时):
import { createEngine } from './src/index.ts'
const engine = createEngine(ctx, { dbPath, sessionsRoot })
await engine.ready // 冷启动回溯完成(已就绪则秒开跳过)
const rollup = engine.query.getRollupBySession(rootSessionId)
const heat = engine.query.getHeatmapData(12)
const fails = engine.query.getTimelineAnomalies(100)
const text = engine.query.loadTurnDetails({ sessionFilePath, turnIndex })
await engine.dispose() // 逆序清理,幂等
双层读模型与快照端点
第二阶段在查询之上加预处理层:
- 暖层:SQLite 物化汇总表
daily_rollups / session_rollups,按脏分区从 turns 整段重算;金额永不落库,由价目表现算。
- 热层:进程内不可变快照主帧(零 Worker),一次
get() 拿到渲染就绪的全部汇总——KPI 总账、84 天热力图、24 小时峰谷剖面、byModel、最近会话、异常计数、计价信息(含 nextSwitchEpochMs 与反事实省额)、余额块。
- revision 条件请求:写入事务原子递增
data_revision;UI 携带旧 revision 轮询,无新数据时端点应答 body 级 unchanged,不触发重渲染。
注入 ctx.webServer 时自动注册端点(回环 same-origin 限定;未注入时引擎作为库完整可用):
| 端点 | 语义 |
|---|
GET /api/usage-dashboard/snapshot?rev=N | rev 命中 → {unchanged:true, revision};否则全量主帧(含 snapshotVersion) |
GET /api/usage-dashboard/snapshot?refresh=1 | 余额透传:旁路 TTL 强制出网一次,必答全量新余额块 |
GET /api/usage-dashboard/turns?limit=N&format=csv | 最近 turn 详情帧(垃圾值/<1 回默认 500、>500 钳到 500);行含 toolMs(按 step 聚合工具时长,无调用为 null)与 delegationDepth(子代理深度);format=csv 出 CSV(列序 = JSON 字段序) |
GET /api/usage-dashboard/turns?session_id=&root_session_id= | 按会话过滤(可选,可同给 = 交集):session_id 精确匹配该会话、root_session_id 匹配整棵会话树;垃圾值视同缺省 → 全库最近 N 条 |
UI 层
浏览器半(src/client/ → lib/client.js)经宿主 slot 系统挂载,只消费上表端点,不碰文件系统与 SQLite:
余额查询配置
大盘的余额卡读取 DeepSeek 官方 GET /user/balance,key 复用宿主凭证:在「设置 → 模型」里配置 DEEPSEEK_API_KEY,或写入 ~/.dsh/.credentials.yaml(文件权限须 0600,顶层 DEEPSEEK_API_KEY: <key>)。未配置时余额块显示占位态,其余功能不受影响(引擎中唯一出网组件就是余额服务,其余一切纯本地)。
数据位置
| 内容 | 路径 |
|---|
| 投影库(Read Model) | ~/.dsh/data/usage.sqlite(0600,WAL) |
| 真相源(Write Model,只读) | ~/.dsh/sessions/<projectKey>/<sessionId>/session.jsonl.zstd |
删库重建
投影库可随时删除(先停用插件,再 rm ~/.dsh/data/usage.sqlite*)。下次启动 backfill 会重扫全部历史会话重建投影;正在进行的活会话由事件总线继续增量补齐。Write Model 永远不要删。
License
MIT