Token 统计 (token-stats) · V1.0.7
在对话收尾时,读取 WorkBuddy 自动保存的对话记录,从每条助手消息的
providerData 中提取 LLM 调用的真实用量数据,按维度汇总并展示报告。
数据来源
本技能读取 WorkBuddy 自动存盘的对话记录 ~/.workbuddy/projects/<项目>/<sessionId>.jsonl,
从每条助手消息的 providerData 提取 API 真实返回的用量(prompt_tokens / completion_tokens /
prompt_cache_hit_tokens / reasoning_tokens / credit)。除"官方价估算"与"平台积分"两列外,
其余 token 维度均为真实用量,非估算。
何时使用
- 用户明确要求统计 token("统计一下本次对话的token" / "看看花了多少")。
- 每次对话收尾(任务交付、或判断对话将结束)必须主动运行并展示,无需用户显式要求——这就是"对话结束自动显示"的实现方式。
但展示前必须先读取用户偏好开关(见下方「展示偏好开关(持久化)」一节),按偏好决定展示形态或跳过。 - 想了解缓存命中率、推理 token 占比、单次/累计成本时。
展示偏好开关(持久化)
为支持"手动关闭 token 统计 / 只留单轮"等诉求,本技能用持久化偏好文件控制收尾展示形态,
而非依赖每轮口头指令。偏好存于技能目录内 .workbuddy/stats_pref.json(运行时生成、不进安装包)。
偏好的三档取值
| 取值 | 含义 | 收尾展示形态 |
|---|---|---|
full |
完整形态(默认) | 该轮图标 + 历史总量图标(--widget-pair latest) |
single |
仅单轮 | 只展示该轮 token 图标(--widget-turn latest),不展示历史总量 |
off |
完全关闭 | 不展示任何 token 统计,跳过收尾运行 |
收尾判定流程(每次对话收尾时按此执行)
- 读取偏好文件
.workbuddy/stats_pref.json;若文件不存在或字段缺失 → 视为full。 - 按偏好分支:
-off→ 本次收尾不运行统计、不展示,直接结束。
-single→ 运行python token_report.py --widget-turn latest --bare --current-model <当前模型名>。
-full(默认)→ 运行python token_report.py --widget-pair latest --bare --current-model <当前模型名>。 - 若用户当轮显式要求了与偏好不同的形态(如偏好
single但用户说"看看历史总量"),
以当轮用户指令为准(一次性覆盖,不改偏好文件);偏好只影响"默认自动行为"。
用户指令 → 偏好写入
Agent 识别以下自然语言指令,调用脚本子命令写偏好(不要手写 JSON,用脚本自带
--set-pref 保证格式与路径正确),并在当次回复里用一句话告知用户当前生效的偏好:
- 「关闭 token 统计」/「别再显示 token 了」/「关掉 token 统计」→
python token_report.py --set-pref off - 「只显示单轮 token」/「只统计本轮」/「不要历史总量」→
python token_report.py --set-pref single - 「恢复完整 token 统计」/「打开完整统计」/「恢复 token 统计」→
python token_report.py --set-pref full
> 偏好文件与技能目录绑定,换机 / 重装技能后会被重置为 full(符合预期,相当于回到默认)。
> 价格刷新自动化是独立机制,不受此偏好影响;off 仅关闭"收尾展示",不影响价格表刷新任务本身。
调用方式(由 Agent 执行)
技能内置脚本 scripts/token_report.py(纯标准库,无需安装依赖):
# 统计"当前对话"(默认,取 app/sessions.json 中最新会话)
python "<skill_dir>/scripts/token_report.py"
# 统计指定历史会话
python "<skill_dir>/scripts/token_report.py" --session <sessionId>
# 直接指定对话 jsonl 文件
python "<skill_dir>/scripts/token_report.py" --jsonl <path/to/sessionId.jsonl>
# 汇总所有历史会话的总量与成本(来自 session_usage 表)
python "<skill_dir>/scripts/token_report.py" --all
# 汇总某日期之后的历史会话
python "<skill_dir>/scripts/token_report.py" --since 2026-08-01
# 生成 HTML 卡片(而非纯文本),写入文件
python "<skill_dir>/scripts/token_report.py" --html --out token_card.html
python "<skill_dir>/scripts/token_report.py" --all --html --out token_card_all.html
# 生成「单对话」可点击图标控件,写入文件(完整 HTML 页面)
python "<skill_dir>/scripts/token_report.py" --widget-session --out token_widget_session.html
# 【每轮对话结束后的标准形态】一次输出『当前轮次图标 + 历史汇总图标』两个(推荐)
# 内联展示用 --bare:脚本会把 HTML 写入固定中转文件,stdout 输出 [WIDGET_FILE] 标记,
# Agent 读取该文件后原样传入 show_widget,避免超长单行被截断。
# --widget-pair latest 表示取当前最新一轮(不要传固定数字,否则每轮都显示同一个旧轮次)。
python "<skill_dir>/scripts/token_report.py" --widget-pair latest --bare --current-model <当前模型名>
# 只输出『当前轮次』单个图标(该轮 token 使用情况)
python "<skill_dir>/scripts/token_report.py" --widget-turn latest --bare
# 只输出『当前任务历史汇总』单个图标(累计 token 总量)
python "<skill_dir>/scripts/token_report.py" --widget-total-session --bare
# 生成「历史总用量」可点击图标控件,写入文件(完整 HTML 页面)
# 默认统计全部任务(不区分工作区);如需限定可加 --scope workspace / --workspace
python "<skill_dir>/scripts/token_report.py" --widget-total --out token_widget_total.html
# 所有 --widget-*/--html 输出均可用 --bare 生成裸 HTML 片段(供 show_widget 内联)
python "<skill_dir>/scripts/token_report.py" --widget-session --bare
> <skill_dir> 即本技能目录(如 ~/.workbuddy/skills/token-stats)。
> 请使用 WorkBuddy 自带的托管 Python(位于
> ~/.workbuddy/binaries/python/versions/<版本>/python.exe,当前环境为 3.13.12)。
脚本默认输出中文纯文本报告(含输入/输出/总计/缓存命中率/成本/模型分布),
并把机器可读的 JSON 摘要打印到 stderr([json]{...})。
加 --html --out <file.html> 可改为输出 HTML 卡片(浅色圆角、指标块、缓存进度条、成本分块)。
报告维度说明
| 维度 | 含义 | 数据来源 |
|---|---|---|
| 输入 tokens | 发给模型的总 token(含系统提示、上下文、工具结果) | prompt_tokens / inputTokens |
| 输出 tokens | 模型生成的总 token(含文本与工具调用参数) | completion_tokens / outputTokens |
| └ 推理 tokens | 输出中用于思维链(Thinking)的部分 | reasoning_tokens |
| 总计 tokens | 输入 + 输出 | total_tokens |
| 缓存命中率 | 命中缓存的输入 token ÷ 输入 token | prompt_cache_hit_tokens ÷ prompt_tokens |
| 积分消耗 | WorkBuddy 平台积分(非人民币),直接读取,既非官方厂商价算法,也非真实人民币扣费 | session_usage.credit_json(按会话汇总) |
| 官方价估算 | 按各模型厂商官方公开价折算的人民币估算值(含输入/输出/缓存命中折扣),仅供参考、非实际扣费 | prices.json(外挂价格表,每周一自动刷新) |
缓存命中率口径:开启 Prompt Caching 的模型上,每次调用输入中与历史前缀重合的部分记为"缓存命中",
按 命中 ÷ 输入 计算;未开启或未命中时为 0%,属正常。
积分口径:报告里的"积分消耗"读取自 WorkBuddy 的 session_usage.credit_json,单位是平台积分(非人民币、
也非厂商官网价)。它是平台按自身规则把 token 折算成的套餐额度消耗,与厂商官方价、真实人民币扣费均无 1:1 关系;
而输入/输出/缓存等 token 维度均为 API 真实返回。
官方价估算(人民币,仅供参考)
报告中的"💵 官方价估算"列,按技能自带价格表 prices.json(位于技能根目录,按 WorkBuddy 内部模型名建索引,
每条含厂商、官方型号、输入/输出/缓存命中价、来源、更新日期)折算人民币估算值。
价格刷新(首次自动创建,后续仅提醒):用户首次使用本技能统计 token 时,Agent 自动创建一条
「每周一刷新价格表」自动化任务(见下方「价格刷新自动化」一节),每周一联网核对官方价并回写
prices.json 的 input/output/cache_hit/updated/source;后续仅检测,任务不存在时只提醒、不自动重建。
计算口径:成本 = (输入−缓存命中)×输入价 + 缓存命中×缓存命中价 + 输出×输出价
(人民币 / 百万 tokens)。无缓存命中价的模型,命中部分按输入价计。
新模型自动识别与价格表治理:
- 统计时发现价格表未收录的模型(含自定义模型),脚本自动登记占位条目(custom-/local: 前缀标注"无官方价")。
- 收尾展示时若发现新登记且非自定义的模型,立即联网补价并回写,无需等每周一。
- 价格表同步 WorkBuddy 已用模型基准,废弃模型的无价占位自动清理,有价条目即使暂未用也保留。
免责:官方价为估算值,与实际扣费可能不同(受套餐折扣、区域、峰谷时段等影响),与平台"积分"列不可互相换算。
价格刷新自动化(首次自动创建,后续仅提醒)
价格表需要联网核对厂商官方价才能保持准确。为避免"每次触发都强制持久化任务"的越界行为,
本技能采用更克制的策略:
- 首次使用自动创建:当用户首次使用本技能统计 token 时,Agent 自动创建一条
「每周一刷新大模型官方价格表」自动化任务,并写入状态标志文件
.workbuddy/price_automation_initialized(位于技能目录内,运行时生成、不进安装包)。
判定"首次"的依据:该状态标志文件不存在,且automation_update的mode="list"中也查不到
同名的活跃任务。创建参数:
-name:每周一刷新大模型官方价格表
-prompt: 见下方「自动化任务 prompt 模板」
-scheduleType:recurring
-rrule:FREQ=WEEKLY;BYDAY=MO;BYHOUR=0;BYMINUTE=0
-status:ACTIVE
-cwds: 指向本地 token-stats 技能目录(如C:/Users/<用户名>/.workbuddy/skills/token-stats) - 后续仅检测、不强制重建:首次之后,每次触发统计 token 时,Agent 只检查该活跃任务是否存在。
- 存在 → 跳过,不重复创建。
- 不存在(如被用户误删,或换机 / 重装后状态标志丢失)→ 仅用一句话提醒用户
「价格刷新任务已不存在,如需恢复可说『重建价格刷新任务』」,绝不自动重建,
把决定权交还用户。 - 创建(或用户主动要求重建)完成后,在当次回复里用一句话告知用户。
> 自动化任务存于本地 ~/.workbuddy/workbuddy.db,不随 skill 安装包分发。
> 换机 / 重装技能后状态标志丢失,会被当作"首次使用"再次自动创建(符合预期)。
> 此外,对话收尾发现新模型时的"立即补价"机制仍作为即时补充继续生效(发现新模型当次就补,
> 但这同样属于联网行为,见下方注意事项)。
自动化任务 prompt 模板(创建时原样填入 prompt 字段)
更新 token-stats 技能的官方价格表。
步骤:
1. 定位 token-stats 技能目录:标准路径 ~/.workbuddy/skills/token-stats/(Windows 实际为
C:/Users/<用户名>/.workbuddy/skills/token-stats/),读取其中的 prices.json。
2. 用 WebSearch / WebFetch 联网核对以下模型厂商的官方最新 API 价格(单位:人民币 / 百万
tokens,字段 input=输入、output=输出、cache_hit=缓存命中读取),保持 JSON 结构不变:
- 智谱 GLM-5.2 / GLM-5.1 —— https://open.bigmodel.cn/pricing
- 腾讯混元 hy3 —— https://www.cloud.tencent.com/document/buy-guide/1729/97731
(确认 hy3 对应型号;若官方已有 HY 3.0 价格则采用之并在 note 说明)
- DeepSeek V4 Pro / Flash —— https://api-docs.deepseek.com/zh-cn/quick_start/pricing
(2026-08-17 起峰谷计价:记录空闲时段价,peak 字段写高峰价,note 说明高峰翻倍)
- MiniMax M3 —— https://platform.minimaxi.com/docs/guides/pricing-paygo
(永久五折;≤512K 与 >512K 两档)
3. 把查到的价格写回各模型条目的 input/output/cache_hit 字段(float,如 8.0),
updated 改为今天日期,source 改为实际访问链接。
4. 若某模型官方价分段(上下文长度 / 峰谷 / 优先级),在 note 说明取值口径。
5. 完成后一句话回报:更新了哪些模型的哪些价格,或哪些未变动。
约束:只允许更新 prices.json 中各模型条目的 input / output / cache_hit / updated / source
五个字段的数值与日期;**禁止新增、删除任何模型条目;禁止修改 prices.json 的 JSON 结构
(键名、层级、数组顺序);禁止读取或写入 prices.json 之外的任何文件**。务必先 Read 再 Edit。
仅当联网可访问时才更新,失败则跳过并说明。
图标控件(可点击展开)+ 对话结束自动显示
本技能把 token 用量做成可点击的图标控件(原生 <details> 点击展开,零依赖、可交互):
-
每轮双图标控件(每轮对话结束后的标准形态)
- 触发:每一轮对话结束后(含收尾),Agent 主动贴出总共两个图标:- ① 该轮的 token 使用情况图标:
💱 第N轮对话 · X tok,点击展开该轮详情
(轮次/模型/时间 HH:MM:SS/输入/输出/缓存含命中率/推理/官方价小计); - ② 历史对话汇总图标:
📊 历史总量 · 累计 tok · 缓存 xx%,点击展开
(输入/输出/缓存命中/总计/积分/官方价估算)——这是本任务从开始到当前的
全部累计,只放一个,不会每轮重复塞历史。 - 轮次分组(rounds):脚本按"一次用户消息引发的所有调用"归为一轮;
调用次数 = 带 token 数据的记录行数(message/function_call各计一次,
与模型官方口径一致);无 token 的流式分片不算调用、单独标注数量。
单轮详情底部展示『本轮模型调用(按次数降序)』细分各模型调用次数。 - 命令(默认
full偏好):python token_report.py --widget-pair latest --bare --current-model <当前模型名>
(--widget-turn latest单出本轮图标,对应single偏好;--widget-total-session单出历史汇总图标)
--current-model填本对话 agent 使用的模型名(如hy3/mimo-v2.5),用于估算
本次统计自身消耗的 token 及人民币;脚本按该模型单价折算,未知模型仅显示 token 数。
轮次号务必用latest,让脚本自动取当前最新一轮;传固定数字会导致每轮都显示同一个旧轮次。 - ⛔ 展示禁令:widget HTML 一律由脚本生成,Agent 禁止手写/改写任何 widget 代码;
脚本产物用 Read 读出后原样传给show_widget(详见文末「内联展示必须走文件中转」铁律)。 - 偏好优先:收尾展示形态以「展示偏好开关(持久化)」一节读取的
full/single/off
为准;不要每轮硬编码--widget-pair,按偏好选--widget-turn或--widget-pair,off则跳过。
- ① 该轮的 token 使用情况图标:
-
历史总用量图标控件(全部任务累计,可选)
- 作用:展示所有已完成对话任务的累计总用量(会话数、累计 tokens、
累计积分、官方价估算),点击展开明细。默认统计全部任务、不区分工作区;
--scope workspace/--workspace <子目录>可按需限定(高级用法)。
- 命令:python token_report.py --widget-total --bare
- 展示时机(可选):仅在你问"所有对话总共花了多少"时展示;默认对话收尾只贴
单对话框件,不自动贴全局历史控件。
渲染方式(由 Agent 选用,必须用脚本真实输出,禁止手写 HTML):
- ⛔ 强制铁律:widget 必须由脚本生成,禁止 agent 手写或改写 HTML
widget 的 HTML(含 .tk-seq 并排布局、.tk-box 卡片、CSS)完全由
token_report.py 渲染。Agent 绝对禁止自己拼、自己改、自己生成任何
widget HTML 片段——之前曾因 agent 手写丢失 .tk-seq 包裹层,导致显示样式
与脚本产物不一致,已列为错误行为。唯一正确流程:
1. 跑 python token_report.py --widget-pair latest --bare --current-model <当前模型名>。
2. stdout 会输出短标记:[WIDGET_FILE]<path>[/WIDGET_FILE];
同时 stderr [json] 里有 widget_html_file 字段指向同一文件。
3. Agent 必须用 Read 工具读取该文件完整内容(脚本已把 HTML 格式化成
多行,避免单行超 2000 字符被截断),然后原封不动作为 show_widget 的
widget_code 传入。一个字符都不许改、不许增、不许删、不许重写。
4. 若因任何原因读不到该文件,宁可不展示图标,也禁止手写 HTML 兜底。
- 这样对话里看到的内联图标与脚本产物逐字节一致(蓝色数字/灰色标签/chip 高亮)。
- 不要自动 present_files 打开预览面板(用户明确反馈:每次收尾自动弹预览
面板很烦)。收尾只内联展示,不生成/不打开 HTML 文件;仅当用户明确说
"打开看看 / 保存成文件"时才 present_files 或写文件。
注意事项
- 统计功能本身不联网、不上传:数据来自本地存盘 jsonl,纯本地读取 token 用量。
- 价格估算功能会按需联网:① 首次使用自动创建「每周一刷新价格表」任务;
② 发现未收录的新模型时立即联网补价;③ 每周一自动化任务联网核对官方价。
这些联网行为仅用于更新prices.json,不涉及你的对话内容。
若不需要价格估算,可关闭刷新机制(对话中说"关闭 token 统计的价格刷新"),
关闭后统计仍完全本地运行、不再有任何联网。 - 收尾展示可持久化开关:展示形态(
full单轮+总量 /single仅单轮 /off完全关闭)
由技能目录内.workbuddy/stats_pref.json持久保存,通过「关闭 token 统计 / 只显示单轮 /
恢复完整统计」等指令切换,无需每轮口头指定;文件不存在时默认full。该开关只影响
"收尾自动展示",不影响价格表刷新自动化(那是独立机制)。 - 进行中的对话可能尚未写入最新用量,报告以已完成调用为准。
- 调用次数 = 真实 API 调用数:统计所有带 token 数据的记录行
(message/function_call工具调用各计一次),与模型官方平台口径一致;
无 token 的流式中间分片不算调用,单独标注"X 条流式分片"。 - token 汇总只累加带数据的调用;官方平台的数字可与本地核对一致。
- 历史汇总 token 来自各会话 jsonl 真实用量累加,积分取自
session_usage表。 --widget-total默认统计全部任务(不区分工作区);如需限定范围可用
--scope workspace/--workspace <projects 子目录>(高级用法)。- 概念对应:WorkBuddy 里「一个对话界面 = 一个任务 = 一个
<sessionId>.jsonl」;
单对话框件(历史总量 + 逐轮明细)覆盖单个任务内的全部分析,日常无需关心工作区。