dsh-llm-token-usage
统计运行本插件的 harness 自身的 LLM token 用量与参考费用。不绑定任何特定客户端、不读任何产品的私有数据库——数据来自 harness 官方的会话查询服务 ctx.sessionQuery,因此任何 DSH 部署装上它就能统计自己。
每条模型调用事件(assistant/message)自带 usage 与所属 provider/model,所以按天、按模型、按工作区、按会话的聚合都是逐轮精确的。
English — Token usage and cost analytics for DeepSeek Harness (DSH). It aggregates every model call from
ctx.sessionQuery(provider/model + usage per step), converts tokens to a reference cost with a local price table, and shows the platform account balance next to a locally estimated one. Ships a native dashboard panel (KPIs, daily token/cost charts, model & workspace rankings, sortable detail table with CSV export), a session-cost pill and a status line,/token-usage·/token-balance·/token-usage-dashboard·/token-pricingcommands, and thellm_token_usagetool for the agent. Everything is local and read-only; the only network call is the opt-in price-table sync from this repository.dsh plugin --profile web add dsh-llm-token-usage # from npm (once published) dsh plugin --profile web add --workspace-root file:/path/to/dsh-llm-token-usage-0.5.4.tgz
功能
| 能力 | 入口 |
|---|---|
| 左侧栏图标 → 主面板仪表盘 | 左侧图标栏 Token 用量(与 Plugins / Schedules 并列) |
| 文本报表(按天 / 模型 / 工作区 / 会话) | 斜杠命令 /token-usage |
| 平台账户余额(真实值) | 仪表盘 KPI、会话头部胶囊、状态栏、/token-balance |
| 本会话花费 + 余额(会话头部常驻) | 会话标题栏右侧胶囊(悬停看明细) |
| 状态栏精简显示 | composer 下方状态行:本会话 ¥0.82 · 15.7M tokens · 余 ¥97.25 |
| 钱包余额(估算)查看与设置 | 斜杠命令 /token-balance |
| 查看 / 同步参考价表 | 斜杠命令 /token-pricing、/token-pricing update;插件更新时自动同步 |
| 让 Agent 自己按需取数 / 导出 | 模型工具 llm_token_usage(format: "html" 导出) |
| 可视化仪表盘(KPI + 用量堆叠柱 + 费用折线 + 明细表 + CSV 导出) | 左侧栏图标主面板;设置 → LLM Token 用量(同一份组件) |
| 独立 HTML 仪表盘(自包含单文件) | 仪表盘右上「打开独立仪表盘 / 下载 HTML」;或 /token-usage-dashboard 命令 |
安装
在 DSH 桌面端 / CLI 的插件管理里安装本目录即可(install_bundle 会链接工作区源码并写入 profile 补丁):
# 打包后安装
dsh plugin --profile web add --workspace-root file:/绝对路径/dsh-llm-token-usage-<版本>.tgz
# 上架 npm 后
dsh plugin --profile web add dsh-llm-token-usage
装完重启一次 Harness,命令、工具与设置页入口才会生效。本插件不裸导入任何 harness 包(工具定义在包内构造),因此链接安装与打包安装行为一致。
使用
/token-usage # 近 7 天,按天
/token-usage 30 --by model # 近 30 天,按模型
/token-usage all --by project # 全部历史,按工作区
/token-usage all --by session # 全部历史,按会话
/token-usage --since 2026-09-01 --until 2026-09-15
/token-balance # 查看估算余额
/token-balance --set 100 # 记录期初余额(默认今天起算)
/token-balance --set 100 --as-of 2026-09-01
/token-balance --clear
/token-usage-dashboard # 导出自包含 HTML 仪表盘文件
/token-usage-dashboard --path ./dash.html
/token-pricing # 价表位置、版本、已配置模型
/token-pricing update # 从公开仓库同步最新参考价(Gitee 优先、GitHub 兜底)
也可以直接问 Agent:「用了多少 token」「花了多少钱」「哪个模型最费」「缓存命中率多少」。
仪表盘内容
主面板与设置页共用同一份组件,内容与导出 HTML 对齐:
- 6 张 KPI:合计 Tokens / 参考费用 / 账户余额(未登录时回落估算)/ 模型调用(附未缓存输入与输出)/ 缓存命中率 / 轮次;
- 每日 Token 用量:缓存命中 / 未缓存输入 / 输出三段堆叠柱,带峰值标签、稀疏日期刻度与悬停明细;
- 每日参考费用:折线 + 同色渐变面积,带峰值金额、虚线网格与数据点提示;
- 模型分布 / 工作区分布:横向比例条,显示「合计 · 占比 · 费用」;
- 明细表:按天 / 模型 / 工作区 / 会话四档切换,点表头排序(升/降序),含占比与每行缓存命中率,可一键导出 CSV(含命中率列,UTF-8 BOM,Excel 不乱码);
- 口径说明:价表版本、未配置单价的模型、余额口径与数据覆盖。
面板打开期间每 60 秒静默刷新一次(页面隐藏时跳过);无任何调用记录时显示引导空态,而不是一排 0 和空表。
联动:
- 点「模型分布」里的某一行 → 整个面板只看该模型(KPI、图表、排行、明细一起变),再点一次或点 chip 上的 ✕ 取消;
- 点「工作区分布」同理,按会话所在目录筛选;
- 「自定义…」可填
开始日期 ~ 结束日期,Host 会额外返回一档custom区间;点任一固定档位即回到预设区间; - 筛选与自定义区间都通过查询参数交给 Host 计算(
?model=…、?project=…、?since=…&until=…),余额与数据覆盖始终按全量口径,避免筛选后误读。
余额与每轮花费
余额有两个口径,优先展示平台真实值:
| 口径 | 来源 | 展示位置 |
|---|---|---|
| 账户余额(真值) | ctx.deepseekAccount.getBalance():充值钱包 + 赠金钱包 |
KPI「账户余额」、会话胶囊/状态栏的「余 ¥…」、/token-balance |
| 估算余额 | balance.json 的期初余额 − as_of 起参考费用 |
未登录/查询失败时兜底;/token-balance 同时给出 |
账户查询带 60s 缓存与 4s 超时,失败降级为「未登录 / 超时 / 暂不可用」,不影响任何统计。
当前真实余额显示为 ¥86.51、赠金 ¥3.11(示例值,随账户实时变化)。
原 Qoder 插件 0.5.0 用 hooks 在每轮对话浮出「本会话花费 | 钱包余额」。DSH 版把它落到三个原生位置:
- 状态栏精简显示:composer 下方的环境状态行,单行右对齐
本会话 ¥0.82 · 15.7M tokens · 余 ¥97.25,role="status",悬停看明细。 - 会话头部胶囊:
¥2.61 · 1.8M tok | 余 ¥97.25,悬停显示输入/输出/缓存拆分、调用次数、命中率与余额算式。 - 设置页仪表盘:KPI 卡片多一张「余额(估算)」,页脚给出完整算式。
胶囊与状态行共用同一个会话轮询器(sessionUsageStores):同一会话只发一次请求、每 20 秒刷新,两个挂载点都卸载后自动停止并清理。
估算口径(账户余额不可用时的兜底):
剩余 ≈ 期初余额 − 自 as_of(北京时间 00:00)起的参考费用
配置文件 ${DSH_HOME:-~/.dsh}/llm-token-usage/balance.json:
{ "balance": 100.0, "as_of": "2026-11-01" }
balance 为 null 表示未配置(胶囊不显示余额段,报表不出现余额行);未配置单价的模型只统计 token、不扣减余额。
数据源与口径
- 来源:
ctx.sessionQuery(listSessions→readSession→ 逐条assistant/message.usage;会话标题取readTitle)。插件只调用这个官方服务,不解析任何私有文件、不依赖任何产品的目录布局。 - 字段:未缓存输入
inputTokens、缓存命中cacheReadTokens、缓存写入cacheWriteTokens、输出outputTokens;合计 = 四者之和;缓存命中率 = 命中 /(未缓存输入 + 命中)。 - 计价:未缓存输入×input + (命中 + 写入)×cached + 输出×output;峰谷价按每条记录的时间判定(北京时间周一至周五 9:00-12:00、14:00-18:00 为高峰)。未配置单价的模型只统计 token,费用列显示
—。 - 价表:包内
assets/pricing.json只作种子,首次使用时复制到${DSH_HOME:-~/.dsh}/llm-token-usage/pricing.json;之后直接编辑那份文件,或执行/token-pricing update同步。键支持模型id、provider/模型id、provider/*,值支持 flat(input/output/cached)或峰谷(peak/offpeak),单位元 / 百万 tokens。内置 30 款常用模型(DeepSeek / Kimi / 通义千问 / 智谱 / 豆包 / MiniMax 及 OpenAI / Anthropic / Google / xAI)。 - 自动更新:远端版本不比本地新时不回退(本地
_version较新即保持原样,也不写备份);插件激活时后台检查一次价表——插件版本变化(每次插件更新)立即检查,否则距上次检查满 24 小时才检查;失败后 1 小时重试,不影响任何统计功能。状态写入${DSH_HOME}/llm-token-usage/pricing-sync.json,/token-pricing可查看。关闭方式:环境变量DSH_TOKEN_USAGE_NO_NET=1,或插件行autoUpdatePricing: false。 - 手动更新:
/token-pricing update只允许 https 源、8 秒超时、512 KiB 上限,整表结构校验通过才写入(数值必须是有限数字,null价格条目一律拒绝);写入前自动备份(pricing.json.bak-<时间>.json),本地独有的键保留不删,上游的 Qoder 官方档位 / 自定义模型键会被跳过。
配置
插件行的 config 全部可选:
| 字段 | 默认 | 说明 |
|---|---|---|
pricingPath |
用户数据目录 | 覆盖参考价表位置 |
autoUpdatePricing |
true |
是否在插件激活/更新时自动同步价表 |
pricingSyncIntervalMs |
86400000 |
自动同步的时间节流(毫秒),插件版本变化会绕过它 |
balancePath |
用户数据目录 | 覆盖余额配置文件位置 |
templatePath |
包内模板 | 覆盖 HTML 仪表盘模板 |
cacheTtlMs |
60000 |
采集结果缓存毫秒数 |
maxSessions |
200 |
最多读取多少个最近会话;超出时按最新优先截断并在报表中如实标注 |
口径正确性:和 harness 自己的账对账
插件不是"自己算一套",而是必须复现 harness 自身的记账。测试 tests/analytics-parity.mjs 用真实会话日志的冻结基准(tests/fixtures/session-usage.json)对同一段 seq 区间做逐位比对:
| 字段 | harness 的 tokenUsage 投影 |
本插件聚合 | 差异 |
|---|---|---|---|
| 未缓存输入 | 439,850 | 439,850 | 0 |
| 输出 | 157,704 | 157,704 | 0 |
| 缓存命中 | 31,331,712 | 31,331,712 | 0 |
| 缓存写入 | 0 | 0 | 0 |
| 调用次数 | 196 | 196 | 0 |
基准取自 storages/session_projcache 中该会话的检查点(seq 1097),因此这个对照是与客户端自身账本的比对,不是自证。
主题与可访问性
- 按钮/标签不再使用「品牌色实底 + 白字」:
--dsw-alias-brand-primary在深色主题里接近白、浅色主题里接近黑,实底反白会出现字色与底色相同的隐形按钮。选中态改用「次级底 + 品牌色描边 + 主文字色 + 前置圆点」表达,文字始终落在页面底色上。 - 面板内所有颜色只引用
--dsw-alias-*主题令牌(无硬编码色值),深浅主题与自定义皮肤自动跟随。 - 图表系列色语义化:缓存命中用「成功色」、未缓存输入用「品牌色」、输出用「提醒色」;费用折线用品牌色描边 + 同色渐变面积,坐标标签用次要文字色,深浅主题都不会出现低对比。
- 按钮配色改由组件内的一小段
dtu-前缀样式表驱动,因此有:hover与:focus-visible焦点环(键盘可见),选中态靠「描边 + 圆点 + 加粗」表达。 - 导出的 HTML 仪表盘里,渐变标题在
background-clip: text不可用时自动退回实色,不会变成透明字。
仪表盘在哪里看
- 应用内(默认):左侧栏 Token 用量 图标 → 主栏原生仪表盘;设置页里的「在应用内打开」也是切到这个面板(同一个 React 组件,跟随主题与语言)。
- 导出/分享:主面板里的「在浏览器打开」由 Host 落盘后调系统浏览器(macOS
open/ Linuxxdg-open/ Windowsstart),「下载 HTML」生成自包含单文件;系统唤起失败时会依次回退到新窗口与下载,并如实提示。 - 命令行:
/token-usage-dashboard写入${DSH_HOME:-~/.dsh}/llm-token-usage/dashboard.html。
不把 HTML 塞进 iframe:iframe 拿不到宿主的主题令牌与语言上下文,颜色和深浅模式会跟应用脱节;应用内直接用原生组件渲染同一份数据。
隐私与安全
- 只读:仅通过会话查询服务读取已经落盘/在内存中的会话记录,不写任何会话数据。
- 面板数据路由只接受本机回环直连;带
x-forwarded-*/forwarded头的请求与非回环来源一律 403。 - 默认全程离线:正常使用不联网、不上传任何数据;只有显式执行
/token-pricing update才会从插件公开仓库拉取价表(HTTPS、校验、备份后原子写入)。
与 Qoder 版 token-usage@0.5.0 的对应关系
| 0.5.0 能力 | DSH 版落点 |
|---|---|
读 Qoder 本地 local.db 的 chat_message |
ctx.sessionQuery(官方服务,不碰私有文件) |
| 官方模型 + 自定义模型双通道 | 任意 provider/model;custom_model 换成本地模型 id + provider/* 价 |
| 按天 / 模型 / 项目 / 会话聚合 | 同四维(day / model / project / session) |
| 官网价换算、DeepSeek 峰谷 | 同口径,峰谷按每条记录时间判定 |
| hooks:每轮浮出「本会话花费 | 钱包余额」 | 会话头部常驻胶囊(悬停看明细,20s 刷新) |
| 任意工作区可用的入口 | 左侧栏常驻图标 → 主面板仪表盘(不依赖某个会话/工作区) |
balance.json 期初余额 + as_of |
同一份语义,路径 ${DSH_HOME}/llm-token-usage/balance.json,另有 /token-balance 命令 |
build_dashboard.py 生成 HTML |
renderDashboardHtml + /token-usage-dashboard 落盘 |
| Qoder 内 Canvas 仪表盘 | 无对应物(DSH 无 Canvas 概念);改为设置页仪表盘 + 独立 HTML |
/token-usage、/update-pricing 斜杠命令 |
/token-usage、/token-pricing update,另加 /token-balance、/token-usage-dashboard |
update_pricing.py 双源自动更新 |
/token-pricing update(同一公开仓库,显式触发、结构校验、备份) |
v0.1/v0.2 的历史:v0.1 直接读 Qoder SQLite;v0.2 起改为统计运行本插件的 harness 自身,因此逐轮归因精确、新增工作区维度;v0.3 补回 0.5.0 的余额、会话花费与价表同步。
开发
node tests/analytics.mjs # 聚合 / 计价 / 区间 / 仪表盘(31 项)
node tests/analytics-parity.mjs # 与 harness 自身投影对账(10 项)
node tests/source-contract.mjs # 采集器契约:桩 sessionQuery(11 项)
node tests/client-contract.mjs # Client 半加载契约(78 项,无需浏览器)
node tests/features.mjs # 余额 / 账户余额 / 会话快照 / 工具 schema / 价表同步(70 项)
node tests/host-contract.mjs # Host 端到端:命令、工具、路由、筛选与自定义区间(73 项)
pnpm pack --pack-destination dist
本地开发注意:0.3.0 起 Host 半不再裸导入任何
@deepseek-ai/*包(工具定义在lib/tool.js内构造),因此链接安装与打包安装行为一致。若日后重新引入 harness 包导入,仍需先pnpm pack再用file:<tgz>安装——否则 Node 会从包的真实路径向上解析到另一个安装版本。
许可
MIT。
与工作台的共享面板
本插件在 client bundle 加载时把完整 Dashboard 发布到 window.__DSH_PANEL_REGISTRY__['llm-token-usage'],并导出 panels。
工作台(dsh-workbench)直接渲染它,同一份源码、两处入口。
No comments yet. Be the first to write one.