# dsh-cost-dashboard · DSH 费用看板 [English](README.md) | 中文 装在 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(dsh)里的费用看板插件:汇总本机**全部会话**的模型输入 / 输出 / 缓存命中 token 用量,按价格表(含 DeepSeek 峰谷分时计价)计算费用,在 **设置 → 费用看板** 中以看板形式展示。 ## 你会得到 - **两个入口**:设置 → 费用看板(设置导航图标由 dsh 设置外壳按内置 id 硬编码,无法由插件自定义);侧边栏底部另有**看板图标按钮**(数据网格样式),点击在面板中打开同一看板 - **只用人民币**:所有金额一律按 **CNY(¥)** 显示;美元标价(自动同步的价目表、国外模型)按可配置汇率(`fx.cnyPerUsd`,默认 6.79)折算 - **汇总卡片**:总费用、今日费用、输入(未命中缓存)/ 缓存命中率 / 输出 tokens,以及你**自己发起**的会话数(子代理日志已并入,不单独计数) - **每日趋势图**:ECharts 平滑折线图(带渐变面积与悬浮 tooltip);费用模式为单序列(人民币),Tokens 模式拆为"输入/输出"与"缓存命中"两张图(各自刻度);时间范围可选 **近一周 / 近一月 / 近三月**(默认近一周) - **按模型汇总表**:各模型的 token 用量、费用、占比 - **按会话汇总表**:**每个会话按模型拆行**(一个会话用了多个模型就多行,各自显示模型、tokens 与费用),含标题、项目目录,以及「含 N 个子代理」标记(子代理的 token 与费用已折算进发起它的会话);表头可点,**按费用或最近活跃时间排序**(重复点击反向),截断按会话整体进行,不会把某个会话拆掉一半 - **价格配置**:页面上直接编辑价格表 JSON(含汇率),保存到 `~/.dsh/cost-dashboard.json`,立即生效 - **价目表自动同步**:从 LiteLLM 价目 JSON 自动补齐内置/覆盖里没有的模型(24 小时 TTL + 磁盘缓存,网络失败自动降级),**不覆盖**内置与手工价格 - **实际账单(可选)**:配置供应商只读密钥后,显示 DeepSeek/OpenRouter 真实余额、OpenAI/Anthropic 真实花费,并与估算折线对照;国内云厂商(火山/阿里/腾讯)不接 API,价格走配置文件 - **自动刷新**:看板打开期间每 15 秒拉取一次;宿主侧只增量重扫有变化的日志文件(mtime + size 校验)

费用看板 - 趋势与汇总 费用看板 - 按模型/会话明细

## 安装 ```sh dsh plugin --profile web add ``` `` 支持本地路径 / npm 包名 / GitHub 仓库,例如: ```sh # 本地路径开发安装 dsh plugin --profile web add /path/to/dsh-cost-dashboard # GitHub dsh plugin --profile web add github:mike-lee0120/dsh-cost-dashboard ``` `dsh plugin add` 会在 profile 目录(`~/.dsh/profiles/web`)执行 pnpm 安装,并**自动**把声明了 `dsh.bundle` 的包追加进 `dsh.profile.bundles`(无需手改 profile 配置)。安装后重启 `dsh web` 并**刷新页面**,打开 **设置 → 费用看板**。 卸载:`dsh plugin --profile web remove dsh-cost-dashboard`(自动移出 bundles)。 要求:dsh `0.1.0-rc.7`+,Node ≥ 22.15(`node:zlib` 的 zstd API,宿主本身依赖它写会话日志)。 ## 数据来源与记账规则 - 只读扫描 `$DSH_HOME/sessions/*/*/` 下的当前日志代(`session.jsonl.zstd`、`session.vN.jsonl.zstd` 或明文 `.jsonl`):按版本号取最高的一代,与运行时读取的文件完全一致,因此迁移过的会话不会被旧一代的冻结日志计费。不写入、不改投影。 - 记账语义与官方 `@deepseek-ai/dsh-token-meter` 的 `tokenUsage` 投影一致: - `assistant/chunk {type:'usage'}` 是请求的早期样本(请求后续失败也计数); - `assistant/message` 的 `usage`(或缺省时其 `data.stream` 中最后一个 `usage` chunk)是同 `(turn, step)` 的最终样本,**替换**前者而非重复计数;`llm/retry-started` 会关闭该替换槽,使重试的尝试累加而非覆盖; - `assistant/attempt` 的结算同样计费,即使之后没有生成消息; - 四个不相交桶:输入(未命中缓存,DeepSeek `prompt_tokens` 已扣除缓存命中)、缓存命中、缓存写入、输出。缓存写入仍会被折算并参与 `cacheWrite` 价,但 DeepSeek 全线不产生该桶(实测恒为 0),因此看板与各表格不再展示。 - 模型归属:`assistant/message` 自带 `message.source.provider/model`;仅有 usage chunk(失败请求)时归属最近一条 `request/header` 的模型。 - 会话归属:子代理日志的头部记录了发起它的会话(`parentSession`),其用量会折算进该会话——所以按会话表列的是真实会话,并标出它吸收了几个子代理;若父日志缺失,则保留独立一行并标记为子代理。 - 会话中途切换模型也能正确拆分到各模型。 - 可运行 `node scripts/verify-totals.mjs`:与官方 `session_projcache.json` 逐会话对账(该缓存是某一时刻的快照,晚于它的日志会自动跳过并说明);用官方 token meter 的语义重新折叠当前选中的每个日志并逐会话比对;校验迁移过的会话取到最高格式代;并固定校验 DeepSeek 官方人民币价与「北京时间 + 仅工作日」的峰时窗口(正在写入的活跃会话可能因实时时间差出现微小偏差,属正常)。 ## 价格表 内置 24 个条目 = 21 个模型 + 3 个 DeepSeek 退役模型名(单位:每百万 tokens,核对于 2026-09-24;「命中」= 缓存命中价,「写入」= 缓存写入价,缺省按未命中输入价计)。DeepSeek 采用官方人民币价目表([模型 & 价格](https://api-docs.deepseek.com/zh-cn/quick_start/pricing)),其余条目折算成人民币显示: **人民币标价(CNY)** | 模型 | 输入(未命中) | 输入(命中) | 输出 | 备注 | |---|---|---|---|---| | deepseek-v4-pro | 4.5 | 0.15 | 13.5 | 峰时翻倍:9 / 0.30 / 27 | | deepseek-flash | 1 | 0.02 | 4 | 峰时翻倍:2 / 0.04 / 8 | | deepseek-v4-flash | 1 | 0.02 | 4 | 退役名,实际由 DeepSeek-V4.1-Flash 服务 | | deepseek-v4-flash-vision-exp | 1 | 0.02 | 4 | 退役名,同 Flash 价 | | deepseek-v4.1-flash-expires-on-0910 | 1 | 0.02 | 4 | 已过期实验模型名,同 Flash 价 | | kimi-k3 | 20 | 2 | 100 | 月之暗面国内标价 | | qwen3.8-max | 12 | 1.5 | 36 | 阿里云百炼国内标价 | | doubao-seed-2.1-pro | 6 | — | 30 | 火山方舟 | | hy3 | 1 | 0.25 | 4 | 腾讯混元 | | minimax-m3 | 3.15 | 0.63 | 12.6 | ≤512K 输入五折刊例价 | **美元标价(USD,看板折算成人民币显示)** | 模型 | 输入(未命中) | 输入(命中) | 缓存写入 | 输出 | 备注 | |---|---|---|---|---|---| | gpt-5.6-sol | 5 | 0.5 | — | 30 | | | gpt-5.6-terra | 2 | 0.2 | — | 12 | | | gpt-5.6-luna | 0.20 | 0.02 | — | 1.20 | | | gpt-5.5 | 5 | 0.5 | — | 30 | | | gpt-5.4 | 2.5 | 0.25 | — | 15 | | | gpt-5.1 | 1.25 | 0.125 | — | 10 | | | claude-opus-5 | 5 | 0.5 | 6.25 | 25 | | | claude-sonnet-5 | 2 | 0.2 | 2.5 | 10 | 2026-08-31 前临时价,之后 $3/$15 | | claude-fable-5 | 10 | 1 | 12.5 | 50 | | | gemini-3.6-flash | 1.5 | — | — | 7.5 | | | gemini-3.5-flash-lite | 0.3 | — | — | 2.5 | | | grok-4.6 | 2 | — | — | 6 | | | grok-4.6-fast | 4 | 1 | — | 12 | | | glm-5.3 | 1.40 | — | — | 4.40 | Z.ai 标价,火山方舟渠道请自行覆盖 | - DeepSeek V4 系列自 2026-08-17 起执行峰谷定价(空闲为高峰一半,高峰时段 9:00-12:00、14:00-18:00);每条用量记录带时间戳,看板按宿主本地时区精确分时段计价。 - 未配置价格的模型只统计 tokens、不计费用,页面会提示。 ### 覆盖价格 看板底部 **价格配置** 编辑器直接保存 `~/.dsh/cost-dashboard.json`(按模型名整条覆盖内置价;汇率按 `fx` 覆盖): ```json { "fx": { "cnyPerUsd": 6.79 }, "models": { "glm-5.3": { "currency": "USD", "input": 1.4, "inputHit": 0.14, "output": 4.4 }, "my-local-model": { "currency": "CNY", "input": 2, "output": 6, "peak": { "input": 4, "output": 12 }, "peakHours": [[9, 12], [14, 18]] } } } ``` 字段:`fx.cnyPerUsd`(美元兑人民币,默认 6.79,用于把美元标价折算成人民币显示);每个模型 `currency`(CNY|USD)、`input`(未命中输入价)、`inputHit`(缓存命中价,缺省=input)、`cacheWrite`(缓存写价,缺省=input)、`output`;可选 `peak` 及其窗口 `peakHours`(北京时间小时段)、`peakWeekdays`(0=周日,默认周一至周五)、`peakExcludeDates`(北京时间 `YYYY-MM-DD`,如法定节假日)。命中峰时用 peak 费率,peak 未写的字段回落平价;周末与被排除的日期全天按空闲价计。 ### 价目表自动同步 - 内置价之外,看板会从 [LiteLLM 价目 JSON](https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json) 自动补齐缺失模型(美元价,配合 `fx` 折算成人民币显示)。 - 优先级:**手工覆盖 > 内置价 > 目录价**——目录只填缺口,永不覆盖内置峰谷价或您的手工配置。 - 每 24 小时刷新一次,结果缓存到 `~/.dsh/storages/cost-dashboard-catalog.json`;断网时自动降级为缓存,失败状态在看板页脚可见,可点「刷新价目」手动重试。 ### 实际账单(可选) - 展开「实际账单」区块,配置供应商**只读**密钥后可显示真实余额与花费,与估算折线对照。 - 支持:**DeepSeek** `/user/balance`(余额)、**OpenRouter** `/api/v1/key`(额度)、**OpenAI** Cost API(日花费)、**Anthropic** Cost Report(日花费)。 - 凭证保存到 `~/.dsh/cost-dashboard-credentials.json`(0600 权限),格式: ```json { "providers": { "deepseek": { "apiKey": "sk-..." }, "openrouter": { "apiKey": "sk-or-..." }, "openai": { "adminKey": "sk-admin-..." }, "anthropic": { "adminKey": "sk-ant-admin-..." } } } ``` - 凭证为**只读/账单级**密钥,请勿使用高权限密钥;删除对应条目即可停止拉取。国内云厂商(火山/阿里/腾讯)不接 API,其价格在「价格配置」里维护。 ## 开发 纯 `.mjs` 零构建(host 侧仅 Node 内置模块,client 侧手写 module-loader bundle;图表用仓库内 vendor 的 ECharts 5,Apache-2.0,由 `/cost-dashboard/vendor/echarts` 本地提供,无 CDN 依赖)。改动 host(`index.mjs`/`scan.mjs`/`pricing.mjs`/`routes.mjs`)或 client(`client.mjs`)后重启 `dsh web` 并刷新页面生效。 ## 安全 - GET 数据路由与 dshmarket 等插件的自有路由同等暴露面(仅本机数据、无凭据)。 - 价格写入(POST)仅接受同源请求(Origin==Host 校验)。 - 不上报任何数据;扫描只读。 ## 已知限制 - 费用为按标价的估算,不含套餐/折扣/代金券;峰谷按宿主本地时区判断。 - 会话日志删除后对应历史随之消失(统计完全基于本地日志)。 - 超大日志库(数千会话)冷启动扫描会变慢;增量缓存使日常刷新不受影响。