dsh-plugin-token-report
已验证dsh-plugin-token-report · v0.9.0 · MIT · Web 界面
DSH 插件:无人值守地把 token 用量实时上报到部门服务端,另提供 token_usage 工具、ctx.tokenReport 服务与界面用量面板。
安装
dsh plugin add dsh-plugin-token-report 用 dsh --profile default --dump-config 确认 layer 已生效 —— 参见安装指南。
源码
标签
作者
说明文档
dsh-plugin-token-report
在 DeepSeek Harness(DSH) 里直接查看本机 token 用量:输入框上方一条用量条,点开就是趋势图、 模型排行与自定义日期范围;要往部门看板汇总时,再填「服务端地址 + appKey」开始上报。
不填就不发:未署名 / 未配 appKey 时,插件只读本机日志 —— 不采集上报事件,也不上报。
- 📊 界面用量面板 —— 输入框上方的用量条(0.3.0 起是默认位置)或会话标题栏右上角的胶囊,共用同一个详情面板
- 🧮 只展示真值 —— 计费总量 = 未缓存输入 + 输出 + 缓存读 + 缓存写;
cacheRead不是input的一部分 - 💰 费用(估算) —— 按本机单价快照现算;未计价的用量写「未计价」而不是
¥0.00,金额绝不跨币种相加 - 🔗 多套 DSH 并集 —— 命令行版与 DSH Desktop 的会话日志一起统计;互为镜像的会话按
event_id去重,只算一次 - 🔌 本机客户端全覆盖 —— DSH / Codex / Claude Code / Trae(国际版与国内版)/ WorkBuddy 缺省就一起统计、也一起上报;装了哪个就有哪个,不用配置
- 📤 实时上报 + 历史补报 —— 异步批量、磁盘 outbox、断网续传;服务端按事件 ID 去重,重复投递无害
- 🤖 Agent 可查询 ——
token_usage/token_usage_diagnostics工具,以及供其它插件调用的ctx.tokenReport服务 - 🔒 不采集对话内容 —— 只取 token 数值、模型名、工作目录与轮次等统计字段
快速开始
dsh plugin --profile web add dsh-plugin-token-report@latest
- 重启 ——
dsh --profile web --no-open,用终端打印的完整地址打开浏览器 - 看用量 —— 选择工作区,输入框上方出现用量条。想汇总到部门看板,点面板右上角齿轮「配置」填服务端地址 + appKey,保存即生效,不必重启
不需要改任何 profile 配置:0.9.0 起本插件不再注册 sessionTelemetry 服务(那个名字由官方 OTel 后端占用),改为订阅宿主会话事件流 —— 因此与官方 session-telemetry-otel 可以同时开着,各记各的。桌面端(DSH Desktop)的安装见「在 DSH Desktop(桌面端)上安装」。
环境要求
| 项 | 要求 |
|---|---|
| DSH 宿主 | 0.1.7-rc.2 或更高、0.3.0 之前(本插件已在 0.1.7-rc.2 与 0.2.0-rc.2 上实测启动) |
| 宿主模块 | 与宿主同代(@deepseek-ai/cordis ~4.0.4)。插件只吃宿主的会话事件流(@deepseek-ai/dsh-session)—— 0.9.0 起不再依赖 @deepseek-ai/dsh-session-telemetry |
| Node.js | ≥ 22.15.0 |
| profile | 需要 web profile(界面面板与 /api 数据通道在那里;headless profile 下只有上报与工具) |
上面那个版本窗口是兼容窗口,不是精确版本:宿主启动时逐个 peer 判定,任一不满足就跳过整个 bundle —— 现象是「面板不见了 + 一条也不上报」,启动日志只有一行
skipping profile bundle …, 不是报错。排查看下方「升级与常见问题」的排查表。
实际使用截图
以下截图来自 2026-09-25 本机运行的 DSH Web 与真实会话日志,仅截取插件区域。数值是该机器当时的用量,不是模拟数据,也不代表性能基准。
用量概览与模型明细
点击输入框上方 TOKEN 用量 条里的「详情」,即可查看计费总量、未缓存输入、输出、缓存读、缓存命中率、调用数和会话数。趋势支持切换 Token 总量、调用数与命中率,明细支持模型、服务商、项目和会话分组,点击行可展开,超过 10 行可翻页。

自定义日期范围
除了今天、昨天、本周、最近 7 天、本月、近 30 天和今年,还可以通过双月日历选择开始与结束日期。开始与结束日期既可以点日历选,也可以直接敲进输入框(2026-09-21、2026/9/21、2026年9月21日 都认,失焦后统一成 2026-09-21);格式不对、日期不存在或开始晚于结束时,标题右侧会说明原因,「应用范围」只在区间可用时才可点。范围按本地时区计算,包含起止两天,点击「应用范围」后更新统计;生效期间按钮上直接显示所选区间(如 09-12 – 10-06)。

安装最新稳定版
前置要求(宿主版本窗口、Node 版本)见上方「环境要求」。安装本身只有一条命令:
dsh plugin --profile web add dsh-plugin-token-report@latest
dsh plugin add 会自动在 ~/.dsh/profiles/web/package.json 的 dsh.profile.bundles 中登记发布包。检查它只出现一次,且没有 0.9.0 之前的旧仓内源码包名 @ai-token-report/dsh-plugin(那个名字现在只用于清理历史装机);不要再手动 insert 插件。正常列表例如:
{
"dsh": {
"profile": {
"bundles": [
"@deepseek-ai/dsh-base",
"@deepseek-ai/dsh-web-app",
"dsh-plugin-token-report"
]
}
}
}
不需要额外改 cordis.patch.yml:0.9.0 起本插件不注册 sessionTelemetry 服务,所以官方 session-telemetry-otel 可以继续开着 —— 它只在你主动提交反馈时上传,本插件只看 token 数值与模型名。
⚠️ 0.8.x 及更早是互斥的:那一版把自己注册成第二个 telemetry 后端(cordis 同名服务只能注册一个),所以必须在同一个
cordis.patch.yml里合并- id: session-telemetry-otel与disabled: true,否则 DSH 启动会失败并只报一行service "sessionTelemetry" has been registered at <OpenTelemetrySessionBackend>。 升级到 0.9.0 之后那一行可以删掉(留着也无害 —— 只是官方后端不再工作)。
随后重启 DSH,用终端打印的完整地址打开浏览器:
dsh --profile web --no-open
选择工作区后,输入框上方会出现用量条(0.3.0 起这是默认位置)。想让面板改到会话标题栏右上角、或两个位置都要,见下方「调整面板位置」。安装后无需单独启动本地统计网页。
dsh plugin内部调用宿主自己的包管理器。上面的安装命令用于 DSH profile;本仓开发、构建与发布使用 Bun。
在 DSH Desktop(桌面端)上安装
桌面端与命令行版走的是同一条装配路,只是 home 与 profile 换成了 Desktop 自己那套; 但桌面端的图形入口装不了本插件,所以下面给的是命令行步骤。
同一套步骤的交付版在仓库的
docs/桌面端安装交付清单.md(逐条命令 + 核对 + 回滚, 文件不在 npm 包里,所以这里只写路径);本节是它的说明版。
为什么不能用桌面端的插件界面装
| 入口 | 能不能装 | 原因 |
|---|---|---|
侧边栏「插件」(社区插件市场 dshmarket) |
❌ | 市场只允许安装 awesome-dsh-plugin 精选列表内的来源,其它一律拒绝(其 README 明写)。实测该目录 plugins.json(约 5 MB)里 token-report 0 命中 |
上游「插件」管理页(@deepseek-ai/dsh-plugin-manager) |
⚠️ 未实测 | 它接受 npm 包名 / 本地路径 / tarball / git,但在 Desktop 上包操作归 Desktop shell 所有,会走下面的 generation 管线 |
想让同事在界面里一键装,唯一途径是把包 PR 进 awesome-dsh-plugin 精选列表。
桌面端与命令行版的四个差别
| 命令行版 | DSH Desktop | |
|---|---|---|
| DSH home | ~/.dsh(或 $DSH_HOME) |
%APPDATA%\dsh-desktop\harness(macOS:~/Library/Application Support/dsh-desktop/harness) |
| profile | 任意 | 只有 web —— Desktop 只暴露这一个,别的名字直接抛错 |
| 宿主 | 你自己装的 dsh |
Desktop 自带一整套 harness,在 <安装目录>\resources\app.asar.unpacked\node_modules\ 下(本机实测 @deepseek-ai/dsh = 0.1.7-rc.2、@deepseek-ai/cordis = 4.0.4、随包 Node v24.9.0) |
| 包操作 | 你调 dsh plugin … |
Desktop 启动时会做 profile maintenance:把非市场来源的插件迁成不可变 generation(.generations/live/<...>,一次 rename 上线),并写 dsh.desktop.generationProjection 与 pnpm.overrides;迁移失败会写 profiles/web/.generations-deferred.json 并冻结该迁移 |
其余一律相同:数据目录仍是 ~/.ai-token-report,与命令行版共用(身份 / appKey 填一次两边都生效,见上方「多套 DSH 并存」);会话日志按本机全部 DSH 的并集统计。
步骤
① 退出 DSH Desktop(要写 profile 与 node_modules)。
② 打开一个 PowerShell,把 home、宿主入口与 Desktop 自己的 pnpm 都指过去:
# 安装目录按实际替换(本机在 D:\Program Files\DSH Desktop)
$desktopRoot = "D:\Program Files\DSH Desktop"
$desktopDsh = "$desktopRoot\resources\app.asar.unpacked\node_modules\@deepseek-ai\dsh\lib\bin.js"
$env:DSH_HOME = "$env:APPDATA\dsh-desktop\harness"
$env:PATH = "$env:DSH_HOME\.desktop-bin;$env:PATH" # ★ 用 Desktop 的 pnpm,别用系统里那个
PATH这一行不是可有可无:Desktop 的pnpm.cmd会在 pnpm 跑动期间临时排除 generation 投影, 换成另一个 pnpm 就绕开了这层保护。
③ 装包(两种 spec 二选一):
# npm 稳定版
node $desktopDsh plugin --profile web add dsh-plugin-token-report@latest
# 本地 tarball:未发布的版本 / 离线分发。
# ★ 路径用正斜杠,反斜杠会报 ERR_UNSUPPORTED_ESM_URL_SCHEME;下面的版本号按实际 tarball 替换。
node $desktopDsh plugin --profile web add file:D:/path/to/dsh-plugin-token-report-0.9.0.tgz
add 会自动在 profiles/web/package.json 的 dsh.profile.bundles 里登记包名;不要再手动 insert。
④ 官方 OTel 不需要再禁用(0.9.0 起):本插件不注册 sessionTelemetry 服务,两边可以同时开着。0.8.x 才需要在这一步往 profiles/web/cordis.patch.yml 里写 - id: session-telemetry-otel + disabled: true;升级后那两行可以删掉。
⑤ 核对(只读,不起服务):
node $desktopDsh plugin --profile web list # 本机实测:[email protected]
node $desktopDsh --profile web --dump-config | Select-String token-report
⑥ 重启 DSH Desktop。 面板出现即装好(默认输入框上方;位置在面板「配置」里改,保存即生效)。
装好之后
启动日志会打印
UI 用量面板数据通道已挂载 → GET /api/tokenReport.stats(面板位置:…)。桌面端看不到宿主的终端输出(它写进
%APPDATA%\dsh-desktop\logs\harness.log),本次启动的完整地址(含?token=) 就在那行dsh web: http://127.0.0.1:<端口>/?token=…里。想确认界面数据通道真的在跑,就用它取一次配置路由 (/api前面有 Host/Origin 栅栏,所以要带Origin与上一步拿到的 cookie):$url = "http://127.0.0.1:<端口>/?token=<启动日志里那串>" $jar = "$env:TEMP\dsh-cookies.txt" curl.exe -s -o NUL -c $jar $url curl.exe -s -b $jar -H "Origin: http://127.0.0.1:<端口>" "http://127.0.0.1:<端口>/api/tokenReport.config" # 本机实测:200 + {"position":"dock"}首次使用、填服务端与 appKey、看「上报调试」,都与命令行版一致,见「第一次使用」与「开启团队上报」。
三个坑
- 🚨 版本窗口:当前
peerDependencies是>=0.1.7-rc.2 <0.3.0-0,放宽后的窗口从0.7.0起就在 npm 上(0.6.0及更早那一版钉的是精确0.1.7-rc.2)。宿主启动时由dsh-app-boot的evaluatePluginCompatibility逐个 peer 做semver.satisfies(runtime, range, { includePrerelease: true }),任一不满足就跳过整个 bundle —— 日志只有一行skipping profile bundle …,表现是「面板不见了 + 一条也不上报」,不是报错。所以:- Desktop 自带的
0.1.7-rc.2(以及0.2.x)都在窗口内,装@latest即可,不需要为了拿放宽窗口去手工打 tarball(tarball 只在「装未发布版本」时才用得上)。 - 反过来,Desktop 升到
0.3.0及以后会被跳过。那时要么等插件放宽并复验,要么用宿主自己的allow-version … --accept-risk强制放行(自担风险,不等于已验证)。
- Desktop 自带的
- 不要把仓内源码目录装进 Desktop:发布包是构建产物(
index.js/client.js),而仓内目录要先bun run --filter dsh-plugin-token-report build、且依赖写的是workspace:*(指向两个从未发布的私有包)。宿主跑在 Node 上、也不会替你构建,所以桌面端只用发布包或 tarball。 - 升级 / 卸载走同一条路,不要只手改
package.json:一旦 Desktop 的 generation 迁移成功,插件会被搬进不可变的.generations/live/<...>,那时只有重新add才换得了版本(plugin remove会走 Desktop 的 generation 下线流程)。
第一次使用
- 打开「详情」,选择需要查看的周期。首次建立索引可能需要十几秒,后续只增量读取变化的日志。
- 切换趋势指标或明细分组查看用量来源。图表下方「查看图表数据」提供精确值。
- 手动点击刷新即可读取最新数据;页面每 3 秒问一次「有没有新数」(没有就零成本), 有新采集时按宿主缓存节奏(最多 30 秒)自动更新;切回前台标签页会立刻取一次。
仅查看本机统计不需要署名。未署名时,插件不采集上报事件,也不上报。 页面读取的是 DSH 已有的本机会话日志。
多套 DSH 并存(DSH Desktop / 命令行 / 第三方客户端)
一台机器上同时装着多套 DSH 时(命令行版 ~/.dsh、DSH Desktop 的 %APPDATA%\dsh-desktop\harness……),
插件缺省把它们的会话日志一起统计。发现是结构驱动的 —— 候选目录里只有真的有 sessions 子目录
的才算一个根 —— 所以面板上的数字是多套 DSH 的并集,接入新的第三方客户端不需要改配置。
两套 DSH 的会话经常互为镜像(同一份日志被两边各记一份)。镜像按 event_id = <sessionId>:<seq> 去重、
只算一次,所以「并集小于各自相加」是正确结果,不是漏扫。启动日志与 token_usage_diagnostics
会逐一列出这次实际读到的根 —— 「我的数据到底读了哪几处」不会只给一个数字。
署名、连接配置与本地索引库都在同一个「数据目录」里,缺省 ~/.ai-token-report/,它与会话日志根无关,
所以多套 DSH 缺省就共用同一份身份与配置,Desktop 里不会再出现「尚未署名」,不需要任何配置:
<数据目录>/identity.json ← 署名(token 就是 appKey)
<数据目录>/plugin-connection.json ← 面板里填的服务端地址 / appKey / 间隔 / 位置 / 会话日志根
<数据目录>/usage.sqlite ← 本地增量索引库(日志的派生物,可删可重建)
<数据目录>/outbox/ ← 磁盘 outbox(崩溃不丢数据)
只有两种情况才需要动配置:想钉住统计范围(只看其中几处)用 dshHomes ——
面板里就能改(齿轮「配置」→「会话日志根」,保存即生效),也可以用部署配置
dshHomes 或环境变量 DSH_TOKEN_REPORT_DSH_HOMES 统一钉死;
想让某套 DSH 单独用一份身份 / 库用 dataDir(对应环境变量 DSH_TOKEN_REPORT_DATA_DIR,
只能在部署配置 / 环境变量里给 —— 换掉它等于连身份 / 库 / outbox 一起换,会让人「突然变成另一个人」)。
🚨 不要用日志根去达到「分开身份」的目的:
dshHome/dshHomes换掉的是日志来源, 那会让面板少算另一套 DSH 的会话,而实时上报照常工作 —— 这个错误不会以「完全没数据」的形式暴露。
别的 AI 客户端也算(缺省就是全算)
面板、token_usage 工具与上报都覆盖本机全部已注册来源:DSH、Codex、Claude Code、
Trae(国际版 trae / 国内版 trae-cn,两个发行版算两个来源)、WorkBuddy。
没有开关要打开 —— 本机装了哪个客户端,它的用量就进面板、也会进部门看板;
没装的那些自然不会出现(诊断里会逐项报出解析到的根)。
代价必须知情:第一次取数与第一轮历史补报要冷扫这些日志(本机实测 Codex 就有 1,500 个文件 /
2.8 GB,十几秒到几分钟),之后按文件字节数增量,只解析变化过的文件。
嫌慢就把那个客户端的日志目录挪走,或者用它自己的环境开关关掉
(例如 DSH_TOKEN_REPORT_CODEX=0)—— ⚠️ 这一项刻意不在面板里:
「我不想统计 Codex」是一件部署策略级的事,不该和「我的服务端地址」放在同一个表单里。
为什么不再做成「白名单」:少统计一个来源没有任何下游信号 —— 面板数字看着完全正常, 而它与「我在那台客户端上本来就没用量」长得一模一样。采集范围不是性能偏好,是一句会被读成结论的口径。
调整面板位置
面板默认出现在输入框上方。想让它出现在会话标题栏右上角、或两个位置都要, 有两种办法 —— 面板内改(推荐,立刻生效),或在 profile 里改部署配置。
办法一(0.6.0 起):面板右上角齿轮「配置」→ 面板位置 → 验证并保存。 保存后面板就地换地方,不必刷新页面、更不必重启 DSH:
| 取值 | 效果 |
|---|---|
输入框上方(用量条) |
只显示输入框上方的用量条(默认) |
会话标题栏右上角(胶囊) |
只显示标题栏右上角的胶囊;点开就是同一个详情面板 |
两处都显示 |
两处都显示 —— 与 0.2.0 的外观一致 |
这一项与下面「部署配置」写的是同一个东西,只是存在本机
(<数据目录>/plugin-connection.json,缺省即 ~/.ai-token-report/,见上方「多套 DSH 并存」),并且优先于部署配置。
办法二:在 profile 的 cordis.patch.yml 里给插件加一段 ui ——
适合「IT 统一规定全公司都用某个位置」:
- id: token-report
config:
ui:
position: dock # dock(默认,输入框上方) | header(右上角) | both(两处都要)
改完刷新页面即可生效。三种取值共用同一个详情面板,数字口径完全一致。
也可以不改 YAML,用环境变量 DSH_TOKEN_REPORT_UI_POSITION 临时覆盖。
写错的值不会让面板消失:只认上面三个值,其它一律回退 dock,并在 DSH 启动日志里告警。
面板内那一栏同样只提供这三个值,选不出非法值。
开启团队上报
在详情面板右上角点击齿轮「配置」,五个字段:
| 字段 | 说明 |
|---|---|
| 服务端地址 | 部门平台根地址(例如 https://portal.example.com,或本机自建的 http://127.0.0.1:8787)。上报地址由它推导(<地址>/api/v1/token-usage),不需要自己拼路径 |
| appKey | 管理员在平台「appKey 管理」页签发的那一串。已配置时留空 = 只改下面各项偏好,不会重新校验、也不重写身份文件 |
| 上报间隔 | 5 秒 / 10 秒(默认)/ 30 秒 / 1 分钟 / 5 分钟。这个数字直接决定部门服务端的请求密度,所以只给档位 |
| 面板位置 | 见上一节;保存后就地换地方 |
| 会话日志根 | 每行一个 DSH home;留空 = 自动发现。见上方「多套 DSH 并存」 |
点击「验证并保存」后,插件用这个 appKey 向对应服务端的 /api/v1/identity/verify 校验身份,
姓名与分组以服务端返回值为准(面板不再询问姓名 —— 它由 appKey 在服务端绑定的人决定)。
★ 保存后立即生效,不需要重启 DSH。 保存成功后页面会如实回报当前状态 (「已保存并开始上报 → 地址」或「上报仍未启用:原因」),并当场开始补报本机全部历史用量。 已保存的 appKey 不回显。
看「到底上报了什么」(上报调试)
配置页第二个页签 「上报调试」 是排查「部门看板上没有我的数」的地方。 它每 3 秒刷新一次,把下面这些一次说清:
- 在不在上报:状态 + 地址;没在跑时给原因(未署名 / 未配 appKey / 部署关闭了上报)。
- 发了多少:已采集、已投递(含重复与拒收)、内存队列、磁盘待投递(批数 / 条数 / 字节)、 请求数与失败数、最近成功时间。
- 最近上报:每次真实请求的请求体原文(点开可展开)+ 服务端回执 (接收 / 重复 / 拒收)与 HTTP 状态。请求体过大时只显示开头,并明确标注「已截断」。
- 历史补报进度:扫描文件数 / 服务端确认数 / 上次错误。
- 两个按钮:「立即上报一次」(真发)与「预览下一批内容」(只显示,不发送、不消耗队列)。
🚨 页面里看不到 appKey。 调试数据由宿主半的
GET /api/tokenReport.reports提供, 而宿主只保留请求体、不保留请求头 —— appKey 走Authorization: Bearer,天然不在这里。 不要为了「方便排查」把请求头加进去:那会把一个调试页变成凭证泄漏面。
身份与连接保存在数据目录下(缺省 ~/.ai-token-report/;DSH Desktop 与命令行版缺省就共用同一份、不需要任何配置,见上方「多套 DSH 并存」)。插件与本地 Web 共用身份文件。部署侧固定了身份时,页面会提示配置由管理员管理。
启用上报后,插件会在后台扫描上面那些会话日志根(缺省是本机全部 DSH home)以及本机全部已注册来源(Codex / Claude Code / Trae / WorkBuddy)下的全部历史会话,分批补报用量,直到服务器全部确认收到;不需要逐个打开旧会话。实时新用量同时上报,服务端按事件 ID 去重。断网或退出后,下次启动会继续;更换服务端地址或 appKey 后,会向新连接重新全量补报。
历史补报只发送 token 数值、模型和会话归属等统计字段,不发送对话正文。token_usage_diagnostics 会显示历史扫描进度、服务器确认数、重试错误和最近完成时间。对照本地与部门看板时,请选择相同时间范围并筛选 appKey 对应人员。
DSH 升级会保留旧格式日志作为备份;同一会话存在多个规范格式版本时,统计与补报都只读取最高版本,与 DSH 自身一致,避免事件重编号后重复计费。历史补报不会自动删除服务器上的旧数据;已由旧版本重复上报的记录需先对账、备份,再单独修复。
让 Agent 查询
可以在 DSH 会话里要求:
调用 token_usage,查看我今天的 token 用量,按模型分组。
调用 token_usage,查看最近 7 天的用量,按天显示趋势。
调用 token_usage_diagnostics,检查上报是否成功、是否有待发送数据。
工具注册需要宿主提供对应能力并启用 features.tools。查询工具只读本机日志,本身不产生上报。
功能说明
| 能力 | 使用方式 |
|---|---|
| 界面统计 | 用量条与标题栏入口(挂哪几个由 ui.position 决定,默认只挂输入框上方),共用详情面板 |
| 时间分析 | 预设周期、双月日历、自定义范围、趋势切换 |
| 明细分析 | 模型 / 服务商 / 项目 / 会话分组,展开与分页 |
| 费用(估算) | 面板顶部一行「费用(估算)」+ 明细表每行的金额列;token_usage 工具也给出同样一段。金额是本机按 pricing.json 快照(没有就退回内置种子价)现算的估算,与部门看板可能不同 —— 所以那行口径说明(单价来源 / 未计价比例 / 「估算 ≠ 财务账单」)永远与金额一起出现 |
| 多套 DSH 并集 | 缺省统计本机全部 DSH 的会话日志(互为镜像的会话按 event_id 去重,只算一次) |
| 多客户端来源 | 本机全部已注册来源(Codex / Claude Code / Trae / WorkBuddy)缺省就一起统计、也一起上报;装了哪个就有哪个。要收窄只能用各来源自己的环境开关(如 DSH_TOKEN_REPORT_CODEX=0) |
| 本地增量查询 | SQLite 增量索引;库不可用时自动回退日志扫描并提示 |
| 上报连接 | 面板内填服务端地址 + appKey,验证后立即生效(无需重启) |
| 上报偏好 | 面板内选上报间隔、面板位置与会话日志根;只改偏好时不必重填 appKey,保存后即时生效 |
| 实时上报 | 异步批量发送、磁盘 outbox、失败保留、重启重放 |
| 历史补报 | 独立后台线程扫描全部历史,服务器确认后保存进度,失败持续重试 |
| 上报调试 | 配置页「上报调试」页签:状态与原因、计数、最近请求体原文与回执、补报进度、立即上报 / 不发送预览 |
| Agent 与插件集成 | token_usage、token_usage_diagnostics、ctx.tokenReport |
token 数永远只展示真值;金额(估算)在面板与 token_usage 里也会出现,
但未计价的用量写「未计价」而不是 ¥0.00(「没配上价」与「没花钱」是两件事),
金额一律由宿主算好、格式化好再透传给界面 —— 浏览器半不做任何换算。
趋势图刻意没有金额曲线:多币种绝不跨币种相加,那条判定规则的唯一实现留在部门看板。
只采集用量相关字段(包含模型名、工作目录、轮次等),不采集对话内容。上报失败不会阻塞 DSH 的会话循环;服务端按事件 ID 去重。
采集了什么,不采集什么
| 内容 | |
|---|---|
| 采集 | 计费级的四类 token 数(未缓存输入 / 输出 / 缓存读 / 缓存写)、模型名、供应商、工作目录(项目)、会话与轮次标识、事件时间、来源客户端 |
| 不采集 | 对话正文、提示词、模型回复、附件与文件内容 —— 内容开关恒为关,一个字节都不读 |
| 不署名就不采 | 没有身份文件、没有 appKey,或部署侧关掉上报(features.reporting: false)时,不注册上报后端、一个字节都不发,只在启动日志里提示一次「去哪里填」 |
为什么不做 unknown 兜底 |
那等于未授权的数据采集。宁可一条不报,也不替使用者做这个决定 |
上报走 Authorization: Bearer <appKey>,地址由使用者自己填(缺省指向本机自建的
http://127.0.0.1:8787/api/v1/token-usage)。插件不向任何其它地址发送数据。
面板的「上报调试」页签能看到每一次真实请求的请求体原文与回执 —— 采集范围不必只看承诺,可以自己核。
升级与常见问题
从旧版升级时,重新运行上方带 @latest 的安装命令即可安装最新稳定版。若曾源码直挂或手动 insert,先执行下方离线修复,再重启 DSH。
从 0.5.0(或更早)升到 0.6.0 时,数据目录换了位置,需要手动搬一次家 —— 见下方「0.6.0 数据目录位置变更」。 0.5.0 的下一个公开版本就是 0.6.0,中间没有需要单独安装的版本。
各版本都变了什么
| 版本 | 使用者能感知的变动 |
|---|---|
| 0.9.0 | ★ 不再与官方 OTel 后端互斥:插件不再注册 sessionTelemetry 服务(改订阅宿主会话事件流),装了它不必再停用 session-telemetry-otel;cordis.patch.yml 里那两行可以删掉。包名与发布名统一为 dsh-plugin-token-report(旧仓内名 @ai-token-report/dsh-plugin 仍会被修复工具清理)。peer 去掉 @deepseek-ai/dsh-session-telemetry |
| 0.8.0 | ★ 统计与上报范围都改成「本机全部已注册来源」(Codex / Claude Code / Trae / WorkBuddy 缺省就一起算、也一起报);面板里可改「会话日志根」(保存即生效);README 补齐 DSH Desktop 的安装步骤。旧的 extraSources 配置项已废弃(写了会在启动日志里告警) |
| 0.7.0 | peerDependencies 从精确 0.1.7-rc.2 放宽成兼容窗口 >=0.1.7-rc.2 <0.3.0-0 —— 宿主小版本升级不必再等插件跟进 |
| 0.6.0 | ★ 数据目录搬到 ~/.ai-token-report(升级要手动搬一次家,见下一节);面板里可改面板位置;保存即生效,不必重启;面板开始展示费用(估算) |
| 0.4.0 | 随包提供离线修复工具 repair-profile.mjs(清理 duplicate loader entry id;开发期写作 0.3.1,npm 上没有这个版本) |
| 0.3.0 | 面板默认位置改成输入框上方的用量条(ui.position: dock)—— 要保留 0.2.0 的外观就配 both |
🚨 0.6.0 数据目录位置变更:升级必须搬一次家
这是升级到 0.6.0 唯一需要动手的地方。 数据目录(署名 / 连接配置 / 本地索引库 / outbox / 补报水位)
的缺省位置从 <DSH home>/token-report(通常是 ~/.dsh/token-report)改为 ~/.ai-token-report,
旧目录不会被自动迁移,也不会报错:
| 现象 | 原因 |
|---|---|
| 面板回到「尚未署名」、要求重新填 appKey | 署名与连接配置还留在旧目录里 |
| 面板数字变了(历史少了一块) | 新目录里没有索引库;日志仍在,重扫即可恢复 |
| 磁盘 outbox 里没发完的批留在了旧目录 | 待投递数据不会自己搬过来 |
先把该 profile 的 DSH 停掉,再搬(只做移动,不删除任何东西):
# Windows PowerShell —— 换过 DSH_HOME 的话,按实际路径替换 $old
$old = "$env:USERPROFILE\.dsh\token-report"
$new = "$env:USERPROFILE\.ai-token-report"
New-Item -ItemType Directory -Force $new | Out-Null
Get-ChildItem -Force $old | Move-Item -Destination $new -Force
# macOS / Linux
old=~/.dsh/token-report; new=~/.ai-token-report
mkdir -p "$new" && mv "$old"/* "$new"/
若新目录里已经有同名条目(例如升级后已经跑过一次 DSH、新的空 outbox/ 已建),
Move-Item -Force 对已存在的目录仍会报错 —— 那种情况先把新目录里的空 outbox 删掉,
或者只搬 identity.json、plugin-connection.json、state.json、backfill 这几项
(usage.sqlite 可留可删,它是日志的派生物)。
搬完核对:新目录里应当能看到 identity.json 与 plugin-connection.json;重启 DSH 后面板不再要求重新署名。
想确认生效位置,打开「配置」→「上报调试」——诊断文本会同时打印会话日志根与数据目录。
CLI(ai-token-report)与本插件共用同一个数据目录,所以搬一次两边都恢复。
0.3.0 启动报 duplicate loader entry id: token-report
插件树里重复挂载了相同 ID,Loader 在插件代码执行前就会失败。仅升级 JS 文件不能清理旧 profile。离线修复工具从 0.4.0 起随包提供(开发期写作 0.3.1,但 npm 上并没有这个版本 —— 别去装它);先停止该 profile 的 DSH,再在 Windows PowerShell 运行:
node "$env:USERPROFILE/.dsh/profiles/web/node_modules/dsh-plugin-token-report/repair-profile.mjs" --profile web
node "$env:USERPROFILE/.dsh/profiles/web/node_modules/dsh-plugin-token-report/repair-profile.mjs" --profile web --apply
设置过 DSH_HOME 时,把上面的 USERPROFILE/.dsh 路径替换成实际 DSH_HOME。第一条只检查,需修复时退出码为 1;第二条先备份,再修改。工具去掉重复 bundle 和旧源码包依赖,把插件 insert 转成 ID 配置覆盖;保留其它插件、原配置与 !!js 表达式。YAML 注释在原文备份中保留。
终端会打印备份目录(<dataDir>/plugin-backups/repair-*,缺省 ~/.ai-token-report/plugin-backups/repair-*)。遇到配置冲突、其它插件占用 ID,或全局 $DSH_HOME/cordis.patch.yml 仍重复插入时拒绝写入,需人工合并。不要删除整个 profile、身份文件、数据库或 outbox。修复后重新运行 dsh web。
尚未升级时,也可单独复制仓库构建出的 repair-profile.mjs 到故障电脑,用同样参数运行,无需启动 DSH。
0.2.0 → 0.3.0 的行为变更(唯一一处):用量面板的默认位置改成
ui.position: dock—— 默认只出现输入框上方那条用量条, 会话标题栏右侧的胶囊不再默认出现。要保留 0.2.0 的外观(两处都有), 在插件config里加ui: { position: both }。 位置配错(写了别的值)不会让面板消失:一律回退dock并在启动日志里告警。
| 现象 | 处理 |
|---|---|
启动报 service "sessionTelemetry" has been registered at <…> |
只可能出自 0.8.x 及更早的版本(它要独占那个服务名,与官方 OTel 互斥) |
面板不见了,且一条也不上报(启动日志只有 skipping profile bundle …) |
宿主版本落在兼容窗口之外 —— 见上方「环境要求」。这一行不是报错,是整个 bundle 被跳过了 |
| 没有用量入口 | 确认安装在 web profile、bundle 数组包含发布包名,并已重启;features.ui 不能关闭 |
| 桌面端(DSH Desktop)装不上 / 界面里搜不到 | 桌面端的社区市场只收 awesome-dsh-plugin 精选列表内的来源,本插件不在其中 —— 按上方「在 DSH Desktop(桌面端)上安装」走命令行 |
| 401 / 未通过宿主鉴权 | 使用本次 DSH 启动时打印的完整地址重新打开 |
| 首次统计较慢 | 等待首次索引完成;如显示降级,检查 SQLite 权限与宿主 Node 版本 |
| 团队看板没有数据 | 先看配置页「上报调试」页签:它会直接说「未上报及原因」并列出最近请求与回执;再用 token_usage_diagnostics 看补报进度 |
| 改完配置没生效 | 0.6.0 起保存即生效(页面会回报状态)。若显示「需重启 DSH」,说明宿主没提供热生效入口(旧版本宿主),重启即可 |
| 升级后面板要求重新署名 / 数字少了一块 | 数据目录换了位置,旧目录要搬一次家 —— 见上方「0.6.0 数据目录位置变更」 |
源码、开发文档与构建方式见 GitHub 仓库
(0.9.0 起仓内包名与 npm 发布名是同一个:dsh-plugin-token-report —— 插件市场的 npm 映射就是按仓内 package.json 的 name 去找包的)。
单文件离线版(截图以 Base64 内嵌):README.offline.md。