dsh-usage-board
No description
- Stars
- 0
- Language
- TypeScript
- Created
- Aug 27, 2026
- Updated
- Aug 27, 2026
Introduction
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:
- 挂载点(宿主 slot 注入,共三个):
conversation.view—— 会话页 "Usage" Tab(该会话树根聚合:KPI、五桶构成、模型占比、step 耗时瀑布);sidebar.footer.action—— 侧栏底栏图标按钮,开合大盘;shell.overlay—— 全屏大盘(余额卡 + 可烧天数、异常与反事实、84 天热力图、byModel、24 小时剖面、最近会话、详情表 + Export CSV)。
- 数据层(
src/client/store/,纯函数、node --test 直测):手动刷新、无自动轮询——快照?rev=条件请求(unchanged应答不重渲染),?refresh=1强制余额出网;turns 懒加载(?limit=&session_id=&root_session_id=,CSV 同端点);投影形选择器把真实帧投影成组件消费形状。 - 开发工作流:
开发态改npm run build # tsdown 双产物:lib/index.js(node 半)+ lib/client.js(浏览器半) npm run dev # tsdown --watch(配合宿主 client-hmr 热替换) dsh plugin --profile web add "$(pwd)" # 安装到 web profile(pnpm link + bundle 清单登记) dsh --profile web --port 3099 # 起宿主;UI 打开 http://127.0.0.1:3099src/client/**→ watch 重编lib/client.js→ 宿主 stat-poll 触发clientModules.rebuilt→ SSE 推浏览器热替换;生产态dsh web按 rev(bundle sha256 前 12 位)服务/plugins/<id>/client.js?rev=,内容变更即换址免缓存。
余额查询配置
大盘的余额卡读取 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 永远不要删。