@kaguyaluna2333/dsh-token-stats
v0.1.3
Published
Cross-session token consumption statistics for DeepSeek Harness: /token-stats command, a tokenStats remote (Typert), and a Web Settings dashboard
Maintainers
Readme
dsh-token-stats
English | 中文
跨会话 Token 消耗统计插件,为 DeepSeek Harness 提供:
/token-stats斜杠命令 —— 在 Web 聊天输入框键入/token-stats,插件回复一份纯文本统计报告(总量 / 按天 / 按周 / 按月 / 按模型 / 会话排行 / 最近请求、缓存命中率)。tokenStatsTypert Remote —— 宿主编排的TokenStatsGateway在/api/tokenStats/aggregate暴露完整的统计文档,供浏览器或其他调用方复用。- 设置页仪表盘 —— 设置中新增「Token 统计」分区(与通用 / 模型 / 插件 / Agent 预设同层级,自带品牌 Logo):总量卡片、可切换按天 / 按周 / 按月的渐变柱状趋势图(悬停显示明细)、按模型表格、会话排行、缓存命中率与逐请求记录(最新在前,时间/会话/模型/输入/输出/缓存读)。
数据来源
不依赖任何运行中的会话状态:直接解码 dsh-session-persistence-jsonl 落盘的会话日志
($DSH_HOME/sessions/<workspace>/<session-id>/session.jsonl.zstd),因此所有历史会话都计入,包括已关闭的、以及本进程从未加载过的会话。
- 日志是多个完整 zstd frame 拼接的容器(每个持久化追加批次一个 frame),插件自带 frame 边界扫描与逐帧解码(
lib/log-reader.js),零第三方依赖(node:zlib+node:fs)。 - 用量语义与
dsh-token-meter的投影折叠一致:assistant/chunk(usage)提供早期样本,同一(turn, step)的最终assistant/message用量替换而非累加(失败的请求保留其分片样本);推理 token 是输出的细分项,不重复计入。 - 模型归属取最近的
request/context(回退request/header);按天/按周/按月均使用本地时区(周一为一周起点);标题取session/title(回退首条用户消息)。
安装
方式一:npm 发布版(推荐)
包已发布到 npm:@kaguyaluna2333/dsh-token-stats。
Web(浏览器 GUI,dsh web)
- 安装到 profile(等价于在 profile 目录执行
pnpm add):dsh plugin --profile web add @kaguyaluna2333/dsh-token-stats - 在
~/.dsh/profiles/web/cordis.patch.yml追加:
可选配置(默认根为- insert: - id: token-stats name: '@kaguyaluna2333/dsh-token-stats'$DSH_HOME/sessions):config: root: '/path/to/sessions' - 重启
dsh web(loader 树在启动时固定,必须重启才能加载新行)。
桌面端(DSH Desktop)
桌面端使用独立的 desktop profile:
dsh plugin --profile desktop add @kaguyaluna2333/dsh-token-stats把上面的 patch 行加入 ~/.dsh/profiles/desktop/cordis.patch.yml,然后退出并重新打开桌面端应用。
方式二:本地软链(仅开发者)
无需 npm 发布版时(本地开发、离线环境),也可以直接把仓库目录软链进 profile:
# Web
mkdir -p ~/.dsh/profiles/node_modules/@kaguyaluna2333
ln -s <仓库目录> ~/.dsh/profiles/node_modules/@kaguyaluna2333/dsh-token-stats
# 桌面端(模块解析锚定在 profile 自己的 node_modules)
mkdir -p ~/.dsh/profiles/desktop/node_modules/@kaguyaluna2333
ln -s <仓库目录> ~/.dsh/profiles/desktop/node_modules/@kaguyaluna2333/dsh-token-statspatch 行与方式一相同,然后重启对应前端。
使用
- 聊天框输入
/token-stats。 - 或打开 设置 → Token 统计 分区(与通用 / 模型 / 插件 / Agent 预设同层级)。
- 聚合结果在进程内有 15 秒缓存,重复调用不重复解码。
结构
| 文件 | 职责 |
|---|---|
| lib/index.js | cordis 函数插件入口:挂载 gateway、注册 /token-stats 命令 |
| lib/gateway.js | TokenStatsGateway(TypertRemoteService):tokenStats 服务 + Remote 方法 aggregate();手写装饰器协议安装 @Remote 标记 |
| lib/typert.host.js | Typert host-face manifest:声明 tokenStats/aggregate 调用与 zod 线格式 |
| lib/aggregate.js | 纯函数聚合核心(折叠、总量/按天/按模型/会话排行、报告渲染),无 cordis 依赖,可独立测试 |
| lib/log-reader.js | 会话日志枚举、zstd frame 扫描、存储记录解码 |
| lib/client.js | 手写浏览器 bundle(window.__ModuleLoader__.load):设置页「Token 统计」分区(顶层 settings.section),直接以 RPC 信封调用 /api/tokenStats/aggregate |
验证
node test/aggregate.test.mjs—— 对真实会话根做聚合并打印报告。- 临时实例端到端(克隆 profile 到独立
DSH_HOME,dsh --profile web --port <x>):loader 行 active、/api/tokenStats/aggregate返回文档、/plugins/@kaguyaluna2333/dsh-token-stats/client.js200、index.html启动图含本包。
已知限制
- 统计口径是日志口径:被压缩掉的轮次仍计入(与
dsh-session-stats一致)。 cacheWriteTokens在多数提供方上报中为 0;合计(含缓存)数字对提示缓存敏感。- 报告读取的是持久化日志的快照;会话正在运行时的最新请求可能尚未落盘(检查点间隔内)。
品牌 Logo 与外壳补丁
页面 Logo:分区页顶部的品牌头(渐变圆角徽标 + 上升柱 + token 圆点,内联 SVG,随主题变色)位于
lib/client.js,随插件 bundle 分发,无需额外操作。侧边栏图标:设置外壳(
dsh-client-ui-settings-general)的navIcon()对分区 id → 图标是硬编码的(models / agent-presets / plugins 之外一律回退到齿轮)。为了让「Token 统计」分区有自己的图标,scripts/patch-shell.mjs会向两处内置外壳 bundle 注入一个分支(自定义 SVG 图标):~/.npm/_npx/*/node_modules/@deepseek-ai/dsh-client-ui-settings-general/lib/client.js(浏览器 profile 用)/Applications/DSH Desktop.app/Contents/Resources/app.asar.unpacked/...(桌面端用)
幂等:已打过补丁的文件会跳过;CLI / 桌面端升级覆盖外壳后,重跑一次即可:
node scripts/patch-shell.mjs
