DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

DPH-1121 /

DPH-1121/dsh-usage-stats

Verified

DeepSeek Harness token-usage report with a grow-only per-session ledger: deleting a session no longer deletes its usage

★ 1 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@b25d582b

dsh-usage-stats

在 DeepSeek Harness 的界面里看这台 harness 花了多少 token:按 Today / 近 7 天 / 近 30 天 / 全部统计,并拆出服务方上报的四个桶(未缓存输入 / 输出 / 缓存读取 / 缓存写入)。

它的重点是「删了也不丢」:用量按会话逐个备份进一份只增不减的台账, 所以删除会话(dsh-session-cleanup、手删目录、归档清理)不会把它那部分用量从统计里抹掉。

适配 dsh 0.1.6-alpha.1 ~ 0.2.1-rc.2(含桌面版 0.2.1-rc.2):会话日志的代际 (0.1.6 写 v3、0.1.7 写 v4,升级后两代可以并存)在磁盘上按代际识别,而不是写死一个文件名; 页脚会写出这次到底读到了哪几代。逐条实测见 docs/compatibility.md。

只读会话日志、不持有凭据、不联系 provider、不改模型路由;除了自己那份台账,不写任何东西。


一、这个插件解决什么问题

DSH 已经在 $DSH_HOME/sessions/ 下为每个会话精确记录了服务方上报的 token 用量, 但那是一个每会话累计值 —— 它回答不了「我今天花了多少」。本插件折叠那些日志, 把它变成按天、按供应商、按模型的报告。

而会话日志是可以被删掉的(dsh-session-cleanup 就是 rm -rf 会话目录)。 日志一没,按日志现场折叠出来的统计就跟着少一块 —— 用户清理一次侧边栏, 历史用量就凭空下降一次,这种数字没法用来做判断。

所以 0.3.0 起:每次扫描折叠出来的结果会按会话备份到

$DSH_HOME/storages/dsh-usage-stats/usage-ledger.json

规则只有两条:

规则 含义
只增不减 同一个会话、同一个 (天, 供应商, 模型) 格子,取「台账里记的」与「日志现在说的」中较大的一份。日志被压缩、截断、改写,都不能把已经计过费的数字降下来
从不删除 记录写进去就只被向上更新。没有淘汰、没有 TTL、没有上限。想清空统计就删掉那个目录,下次扫描以当前日志为基线重新开始

后台每 30 秒巡检一次(只对 mtime/size 变过的日志重新折叠), 所以不需要有人打开设置页,用量也会被记下来:会话建了又删、中间没人看过页面,同样不丢。


二、安装

项 值
包名 dsh-usage-stats
版本 0.4.1
dsh 基线 0.1.6-alpha.1 ~ 0.2.1-rc.2(engines.dsh 按 0.1.6 / 0.1.7 / 0.2.0 / 0.2.1 四条已测发布线声明)
源码 与分发 本仓库(github.com/HaydenSmith1121/dsh-usage-stats)

方式 A(推荐,也是以后的默认路径):装一次插件市场面板(dsh-plugins-market), 在左侧「插件市场」里点安装。市场里的这一条就是本仓库的 github: 规格 —— 不经过任何中间产物仓库(dsh-plugin-collection 已停止维护、将被丢弃)。

方式 B(手动,等价):直接从本仓库安装:

dsh plugin --profile web add github:HaydenSmith1121/dsh-usage-stats        # dsh web
dsh plugin --profile desktop add github:HaydenSmith1121/dsh-usage-stats    # 桌面版

profile 选哪个:dsh web 用 web,桌面版(DeepSeek Harness 应用)用 desktop —— 桌面版的 profile 里带着 @deepseek-ai/dsh-web-app 与它自己的 bundle 清单 ($DSH_HOME/profiles/desktop/package.json),插件装错 profile 就不会被加载。 不确定时看一眼 $DSH_HOME/profiles/ 下有哪些目录。

lib/(构建产物)是提交进仓库的,所以 git 安装不需要跑任何构建脚本 —— 本包也故意没有 prepare:有它的话 pnpm 10+ 会以 ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED 拦下安装,逼每个用户手改 allowBuilds (0.3.1 修的就是这个)。要自己从源码打包:npm run pack。

方式 C(离线 tarball):npm run pack 自己打一个,或从可信副本取 —— 装法同上, 把参数换成 .tgz 的绝对路径。

装完重启(dsh web,或直接退出再打开桌面版):设置页是客户端半,重启后立刻出现; 读会话日志并维护台账的路由由宿主半注册,只在启动时加载 —— 重启之前页面会明说这一点, 而不是给一个裸 404。


三、配置

没有配置项:没有 API Key、没有设置项、没有环境变量。

唯一的路径约定是台账的位置(由 DSH 主目录推导):

文件 说明
$DSH_HOME/storages/dsh-usage-stats/usage-ledger.json 用量台账(只增不减)
$DSH_HOME/storages/dsh-usage-stats/usage-ledger.json.corrupt.json 台账损坏时被挪到这里的原件

$DSH_HOME 未设置时用 ~/.dsh(与 DSH 自己的解析顺序一致)。


四、页面显示什么

  • 总 tokens,以及构成它的四个桶;
  • 缓存读占比(有缓存的 harness 上它常远超其它桶,只给裸总数会显得吓人);
  • 该范围内的模型调用次数;
  • 页脚老实交代:读到几个会话日志、几个读不到、几个已删除会话的用量是从台账保留的, 以及读到的是哪几代会话日志格式(· 读到的日志格式:v4 × 12)。

最后那一项是 0.4.0 加的:harness 给会话日志的文件名和表头都打了格式代际,而这个代际 在发布线之间会动(0.1.6 是 v3,0.1.7 是 v4)。把读到的代际印出来, 「它在这台机器上到底读懂了没有」才是一个可以自己核对的事实,而不是一句承诺。 表头读不出代际时显示「未标版本 × N」—— 不猜。

范围是含端点的本地日历窗口且以今天结束,所以它们嵌套:7 天的数字必然包含 1 天的。

台账本身的状态也从不暗示,而是直接写出来:

状态 页面怎么写
ok 「删除会话不会丢用量:各会话的用量已逐个备份,只增不减。」
rebuilt 「用量台账曾不可用,已重建(原因)—— 重建之前保留的用量不再计入。」
unavailable 「用量台账 <路径> 写不进去(原因),删除会话会同时删掉它的用量。」并给出该路径

会话目录整体读不到时(临时故障),页面明说「本次读不到会话目录 —— 所有数字都来自备份」, 并且不会把在场会话谎报成「已删除」。


五、数字从哪来(口径)

折叠刻意复刻 DSH 自己的 tokenUsage 投影(@deepseek-ai/dsh-token-meter), 而不是自己发明一套看起来合理的规则 —— 一份和框架对不上的报告,比没有报告更糟。 三个 load-bearing 的细节:

# 细节 不这么做会怎样
1 同一步骤内最后一条样本胜出 一个流式步骤会为同一个 (turn, step) 记录多条 usage 样本,每条替换前一条。朴素求和会把一个流式步骤重复计很多遍
2 一次重试开一个新槽 llm/retry-started 为它自己的 (turn, step) 关闭当前槽,所以被重试的那一次会与它替换掉的那次并存相加 —— 它确实被计费了两次
3 assistant/message 与 assistant/attempt 都带 usage 后者是它内嵌流里最后一条 usage chunk

node scripts/verify-fold.mjs --reference <0.2.0 的 lib/index.js> 会重新推导每个会话的合计, 并与上一个发布的真实产物逐字节比对(npm test 用仓库内冻结的那份参考实现)。

磁盘格式:按代际识别,不按版本号

折叠规则在两条发布线上没变,但读日志这件事会变,所以它是单独一层 (src/usage/format.js),并且只认磁盘上的事实:

代际 文件名 表头 fork 继承切点
0–1 session.jsonl[.zstd] 扁平,带 seedLength 表头里的 seedLength
2、3、4 session.v<N>.jsonl[.zstd] 扁平,只有 isSeeded 最后一条带 inherited: true 的 session/end-seed 事件的 seq

一个会话目录里有多代文件时(升级后就是如此),读数值最高的那一代 —— 与 harness 自己的选择一致。声明了 isSeeded 却找不到继承标记的日志,记为读不到, 而不是猜一个切点:harness 自己的解码器对这种日志同样抛错,而猜错的代价是把父会话的整段 前缀再计一次费。逐条实测见 docs/compatibility.md。

已知统计边界(诚实登记)

边界 说明
标题生成不计入 session/title-llm-request 会消耗 token 但不记录 usage 样本,任何折叠都看不见。DSH 自己的投影有同样的盲点
fork 的会话不向父会话重复计费 继承前缀(session/end-seed { inherited: true } 之前的事件)被跳过,因为那些事件保留父会话的时间戳、已经随父会话计过。0.4.0 之前这一条实际上没生效(切点读错了字段),fork 会话的父前缀被重复计费
台账启用之前的删除救不回来 0.3.0 第一次运行之前就被删掉的会话,日志已经没了,任何实现都无法复原。台账从第一次扫描开始积累
删除前最后 ≤30 秒的用量 极端情况下(会话在被折叠之前就被删掉)可能来不及记账。巡检间隔是 30 秒,它决定这个窗口
读失败会被报出来,不会被藏起来 页脚显示读了多少个日志、点名几个读不到;不完整的数字永远不会被当成完整的呈现
未知代际的日志 事件形状没变时照常折叠(并在页脚标出代际);连表头都读不出来时按「未 fork」折叠并标为「未标版本」。没有为将来可能出现的形状变化做预测
同一个会话 id 出现在两个工作区目录下 台账按会话 id 记账(这是「删了也不丢」的前提),所以两处同名目录会被合并成一条记录(格子取较大者),而报告会把两份相加 —— 两者不一致。dsh 自己把这种布局判为损坏(duplicate JSONL session id),本插件不额外处理,也不假装它不会发生

六、卸载 / 回滚

dsh plugin --profile web remove dsh-usage-stats          # dsh web
dsh plugin --profile desktop remove dsh-usage-stats      # 桌面版
# 然后重启(dsh web / 重开桌面版)

卸载不会删掉台账:那是你花掉的用量的记录,删不删由你决定。 想清空统计:删掉 $DSH_HOME/storages/dsh-usage-stats/(整目录或那一个 json), 下次扫描会以当前在场的会话日志为基线重建 —— 报告会随之下降,这是预期行为。

回滚到旧版:dsh plugin --profile <profile> add <上一版的 tarball> 即可 —— 本插件不迁移、不改写任何 DSH 数据,所以降级只是换回旧代码,台账原样留着(旧版不认识它,忽略)。 注意 0.3.1 及更早的版本在 0.1.7 上读不到会话日志(写死了 v3 文件名), 回滚到它们只会看到全 0 —— 需要旧版就在 0.1.6 那侧用。 (dsh-plugin-collection 停止维护后,0.3.0 及更早的 tarball 不再有公开托管点; 需要旧版就 git checkout 0.3.0 的提交 && npm run pack 自己打一个。)

⚠️ 与 dsh-workbuddy-quota 的关系:本包是它的继任者(改名 + 只保留用量统计)。 两者不要同时装 —— 它们注册的设置分区 id 不同(usage-stats / token-usage), 同时装会出现两个 Token 用量页。旧包仍然可用,但不再维护。


七、开发

npm run build                 # src/ → lib/(无打包器:宿主半是拷贝,客户端半加外壳)
npm run build:check           # 校验 lib/ 与 src/ 一致(CI 用)
npm test                      # 六个套件:构建一致 / 折叠一致 / 跨版本格式 / 删除保留 / 宿主路由 / 客户端渲染
npm test -- --sessions <dir>  # 再加上真实会话日志的逐字节比对与代际核对

npm test -- --reference <解包后的 0.2.0 包目录>   # 折叠比对改用真实产物作参考

# 声明面:本包的 peer 范围、客户端 inject、bundle patch 对得上这棵 harness 树吗
node scripts/compat-check.mjs --tree <放着 @deepseek-ai/* 包的目录>

目录:

src/
├─ index.js                 宿主半入口:注册路由 + 启动巡检
├─ shared/buckets.js        桶运算与日历窗口(构建时内联进客户端半,两边不会漂移)
├─ usage/
│  ├─ decode.js             zstd 多帧 + JSONL 解码
│  ├─ format.js             会话日志的磁盘格式:代际文件名 + 表头 + fork 切点
│  ├─ fold.js               折叠算法(复刻 DSH 的 tokenUsage 投影)+ 只增不减的合并
│  ├─ ledger.js             台账:读取 / 校验 / 原子写入 / 损坏隔离
│  ├─ scan.js               扫描会话目录(按代际选日志,按 mtime+size+文件名记忆化)
│  ├─ report.js             合并「在场日志」与「台账」,产出报告(含读到的日志代际)
│  └─ host.js               扫描→对账→落盘→报告,外加那条 HTTP 路由
└─ client.js                客户端半(ModuleLoader 工厂体:设置页)
scripts/                    构建、六个校验套件、声明面审计、打包
test/                       合成会话日志构造器(逐代真实形状)+ 冻结的 0.2.0 折叠参考实现
docs/compatibility.md       harness 版本兼容:实测矩阵与边界
docs/verification.md        验证记录

lib/ 是提交进仓库的:本包也支持 github: 直接安装,而 git 安装不会跑我们的构建步骤; npm run build:check 是保证它与 src/ 不脱节的那道闸门。


八、许可

MIT(见 LICENSE)。作者:HaydenSmith1121。

—/ 5

No ratings yet

Verified DSH bundle

Commit b25d582b7069

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout