在输入框与每轮回复尾部显示本轮和对话花费的人民币
28.2/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/3 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add CHIP-PHILO-GH/dsh-turn-cost该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:待复验
是什么
dsh 原生插件 · model
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 46 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
读写/删除本地文件
查看扫描证据(共 8 处,展示前 8 条)
- 读取本地文件lib/pricing.js:56
const raw = JSON.parse(readFileSync(join(home, 'storages', 'cost-meter', 'ledger.json'), 'utf8')) - 读取本地文件test.mjs:16
const read = (file) => readFileSync(join(HERE, file), 'utf8') - 写入本地文件test.mjs:40
mkdirSync(dir, { recursive: true }) - 写入本地文件test.mjs:41
writeFileSync(join(dir, 'ledger.json'), ledgerText, 'utf8') - 删除本地文件递归test.mjs:49
rmSync(home, { recursive: true, force: true }) - 读取本地文件test.mjs:196
statSync(join(HERE, f)) - 读取本地文件test.mjs:242
const walk = (dir) => readdirSync(dir, { withFileTypes: true }).flatMap((entry) => { - 读取本地文件test.mjs:251
const text = readFileSync(file, 'utf8')
扫描于 2026/11/1(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
功能亮点
- 显示本轮花费金额
- 显示对话花费金额
- 只读槽位与用量事件
DSH 插件:在本轮统计与回合尾部显示花费的人民币金额,只读既有槽位与用量事件,不改宿主。
README
由 DeepSeek 最新模型翻译生成dsh-turn-cost —— DSH 轮次花费(人民币)
只想要「照着做一遍」的封装版本(含安装、配置与排错表),见同名技能包 dsh-turn-cost;本仓库是代码本体。
在 DSH 输入框下方、以及每一轮回复的尾部,显示这一轮和整个对话花了多少人民币。
这是什么
一个 DSH 插件,两端一模块:
| 位置 | 文件 | 职责 |
| 宿主端 | lib/index.js | 注册一个只读的会话投影 turnCost,把每次模型调用的 token 桶按轮次折叠成金额 |
| 计价 | lib/pricing.js | 读价格表 / 汇率 / 峰谷规则,把 token 桶换算成人民币 |
| 浏览器端 | lib/client.js | 从投影取值,在 DSH 既有界面上就地加两个元素 |
| 装载行 | cordis.patch.yml | 往 profile 补丁层插一条 loader 条目 |
| 离线测试 | test.mjs | 只覆盖 lib/pricing.js,见「测试」 |
宿主端只做加法:不修改 DSH 任何源码、样式或既有插件。它注册的是会话投影(对持久会话日志的纯 fold),不介入模型调用链。
展开完整文档(README 剩余 1 节)
dsh-turn-cost —— DSH 轮次花费(人民币)
只想要「照着做一遍」的封装版本(含安装、配置与排错表),见同名技能包 dsh-turn-cost;本仓库是代码本体。
在 DSH 输入框下方、以及每一轮回复的尾部,显示这一轮和整个对话花了多少人民币。
这是什么
一个 DSH 插件,两端一模块:
| 位置 | 文件 | 职责 |
| 宿主端 | lib/index.js | 注册一个只读的会话投影 turnCost,把每次模型调用的 token 桶按轮次折叠成金额 |
| 计价 | lib/pricing.js | 读价格表 / 汇率 / 峰谷规则,把 token 桶换算成人民币 |
| 浏览器端 | lib/client.js | 从投影取值,在 DSH 既有界面上就地加两个元素 |
| 装载行 | cordis.patch.yml | 往 profile 补丁层插一条 loader 条目 |
| 离线测试 | test.mjs | 只覆盖 lib/pricing.js,见「测试」 |
宿主端只做加法:不修改 DSH 任何源码、样式或既有插件。它注册的是会话投影(对持久会话日志的纯 fold),不介入模型调用链。
解决什么问题
DSH 界面上本来就有「1 轮 71 步·257 tok/s」「10.7M tok·缓存命中 99%」这类统计,但没有「这一轮花了多少钱」。
本插件把 usage 里的 token 桶按 dsh-cost-meter 账本里的价格换算成人民币(缺省符号 ¥、4 位小数),补上这一格:
- 输入框下方 —— 看整个对话累计花了多少;
- 每轮回复尾部 —— 看这一轮花了多少。
显示在哪、长什么样
两个落点都是「就地加一个元素」,不新开行、不新开面板。
1) 输入框下方的统计药丸
在 DSH 自己那一排统计药丸里追加第三个,文本形如:
本轮 ¥0.42 · 本对话 ¥3.17
本对话累计金额为 0、或投影还没有数据时,这一行什么都不加。
悬停提示按行给分项(金额、四个 token 桶、模型调用次数):
本对话 · 金额 ¥3.17 · 未缓存输入 2.1M tok · 缓存读取 10.4M tok · 缓存写入 0 tok · 输出 186K tok · 模型调用 63 次本轮 · 金额 ¥0.42 · 未缓存输入 320K tok · 缓存读取 1.8M tok · 缓存写入 0 tok · 输出 21.3K tok · 模型调用 9 次
2) 每个回合尾部的徽章
在每个回合的动作条(与复制 / 点赞 / 分叉按钮、「用量 X tok」同排)里加一枚小徽章:
本轮 ¥0.42
它显示的是这条助手消息所属轮次的金额——宿主端维护了「助手消息 id → 轮次号」的映射,徽章靠它定位。
映射找不到、或那一轮金额为 0 时,不渲染任何东西。
样式
自带样式写在插件自己的 标签里,类名统一 dtc- 前缀,颜色一律取全局主题变量(--dsw-alias-label-tertiary 等),不引用、也不修改 DSH 的任何类名与样式表。
药丸复刻邻居药丸的规格(继承行内字号与行高、1px 8px 内边距、24px 圆角、tabular-nums),所以它看起来和旁边两个是同一排的。
数据从哪来
宿主端:turnCost 会话投影
lib/index.js 通过 ctx.inject(['sessionProjections'], …) 注册一个 key 为 turnCost 的会话投影,从会话事件流里读两类用量样本:
| 事件 | 取什么 |
| assistant/chunk,且 chunk.type === 'usage' | chunk.usage,加上 data.turn / data.step |
| assistant/message | data.usage,加上 data.turn / data.step |
usage 的四个桶按字段名映射:inputTokens → 未缓存输入、outputTokens → 输出、 cacheReadTokens → 缓存读取、cacheWriteTokens → 缓存写入;每一项都先夹到 ≥ 0(负数与非数字当 0)。
另外两件事:
- request/header 事件里的 data.header.config.model 决定当前模型 id;取不到时用 default;
- assistant/message 的 data.message.id(或 data.messageId)用来维护「助手消息 id → 轮次号」的映射。
同一轮不会重复计数
流式过程中会先到一个不完整的 usage 样本,回复结束时会再来一个最终样本。投影按 轮次:步 折叠:
- 同一个 轮次:步 的新样本与上一个完全一致 → 直接跳过(这顺带避免了切模型后重复上报同一样本把「模型调用次数」多算一次);
- 不一致 → 先把旧样本减掉,再把新样本加上;
- 只有全新的 轮次:步 才把「模型调用次数」+1。
客户端:只读投影
lib/client.js 用 props.useProjection('turnCost') 取值;取不到(宿主端没加载、或投影尚未建立)时什么都不显示。
宿主端对客户端只暴露显示需要的字段:symbol / decimals / totals / turns / latestTurn / messageTurn。
安装
前提:Node ≥ 18,本机已装 DSH。
运行时的 zod 由 DSH 宿主提供,本包在 package.json 里以 peerDependencies 声明它("zod": "*"), 不把宿主运行时复制进自身依赖树。因而:在 DSH 里装载不需要额外安装;单独 npm install 本包时,
npm 会按 peer 规则自行解析 zod。
git clone https://github.com/CHIP-PHILO-GH/dsh-turn-cost
cd dsh-turn-cost
把这个目录装成名为 dsh-turn-cost 的 DSH 插件——放进 profile 的插件目录,例如 $env:DSH_HOME\profiles\node_modules\dsh-turn-cost(DSH_HOME 未设置时是 ~/.dsh)。
装载行由本包自带的 cordis.patch.yml 提供(package.json 的 dsh.bundle.patch 指向它),内容是往 profile 补丁层插一条 loader 条目:
- insert:
- id: turn-cost
name: 'dsh-turn-cost'
装好后重启 dsh web 生效(宿主端与浏览器端 bundle 都只在启动时加载,本插件不做热重载)。
重启后宿主端会打印一行自检日志,里面的三个值就是本次生效的符号 / 小数位 / 汇率:
[dsh-turn-cost] 已加载,计价:¥ 小数 4 位,汇率 7.2
卸载
1. 从 profile 的 cordis.patch.yml 里删掉 id: turn-cost 那条 loader 条目;
2. 删掉插件目录 …\profiles\node_modules\dsh-turn-cost;
3. 重启 dsh web。
插件自身不写任何文件,也没有自己的配置文件,所以没有残留状态要清理(页面上那两个元素随页面刷新消失)。
配置项
本插件没有自己的配置文件。 价格口径直接沿用 dsh-cost-meter 的账本配置:
<DSH_HOME>\storages\cost-meter\ledger.json → 顶层 "config" 字段
<DSH_HOME> 取环境变量 DSH_HOME,未设置时取 ~/.dsh。
这个文件不存在、读不了或格式不对时,插件不会报错,而是整份退回内置兜底配置(见「计价依据」)。
config 里被读取的字段一共这些,其余字段一律忽略:
| 键 | 类型 | 缺省 | 说明 |
| symbol | string | ¥ | 金额前缀。空串或非字符串时用 ¥ |
| decimals | number | 4 | 显示小数位。先向下取整,再夹到 0–10 |
| exchangeRate | number | 7.2 | 美元 → 人民币汇率。非正数或非数字时用 7.2 |
| peakEnabled | boolean | false | 峰谷计价开关。必须严格等于 true 才启用(字符串 "true" 不算) |
| peakEffectiveAt | string | 无 | 峰谷档生效时刻,交给 Date.parse 解析。该时刻之前的调用一律按基础价 |
| peakWindows | array | [] | 峰时段窗口,单位是 UTC 小时,见下 |
| prices.models | object | {} | 模型 id → 单价记录 |
| prices.default | object | 兜底单价 | 模型没登记时用它 |
单价记录(prices.models.<模型 id> 与 prices.default)的字段:
| 键 | 说明 |
| cacheHit | 缓存命中价(缓存读取与缓存写入都用它) |
| cacheMiss | 未命中输入价 |
| output | 输出价 |
| offPeak | 可选。非峰时段档位,字段同上;缺失时退回基础价 |
| peak | 可选。峰时段档位,字段同上;缺失时退回基础价 |
三条归一化规则:单位一律是美元 / 1M tokens;记录里缺哪个字段,就用兜底单价里的同名字段补; offPeak / peak 里缺的字段再用该记录自身的基础价补。
peakWindows 的每一项是 { start, end },单位是 UTC 小时(0–23):
- start < end:命中区间 [start, end);
- start > end:跨零点环绕,命中 [start, 24) ∪ [0, end);
- 某项的 start / end 不是有限数字 → 该项被忽略。
peakEnabled 为 true 时还有一条容易踩的规则:peakEffectiveAt 必须是能解析成时间的字符串。
- 有效:该时刻之前的调用一律按基础价;之后落在窗口内用 peak 档,其余用 offPeak 档;
- 无效或缺失:落在窗口内仍然用 peak 档,但窗口外一律用基础价——offPeak 档不会被用到 (代码只在「调用时刻 ≥ 生效时刻」时才取 offPeak)。
判定用的是调用发生的时刻(事件自带时间戳,缺失时退回当前时刻),不是「现在」。
⚠️ 配置在插件加载时读一次。改完账本要重启 dsh web 才生效。
计价依据
公式
美元成本 = (未缓存输入 × cacheMiss + 输出 × output + (缓存读取 + 缓存写入) × cacheHit) / 1,000,000 人民币 = 美元成本 × exchangeRate
四个 token 桶都先夹到 ≥ 0。缓存写入按命中价(cacheHit)计费,口径与 dsh-cost-meter 一致。
汇率不是有限正数时按 1 处理。
兜底单价(写死在代码里的那份)
lib/pricing.js 的 FALLBACK_ENTRY,单位 美元 / 1M tokens,代码注释标明对应 DeepSeek 官方 deepseek-flash 档:
| 项 | 单价(美元 / 1M tokens) |
| 缓存命中(cacheHit,含缓存读取与缓存写入) | 0.0028 |
| 未命中输入(cacheMiss) | 0.14 |
| 输出(output) | 0.28 |
兜底配置的其余部分:符号 ¥、小数位 4、汇率 7.2、峰谷开关关闭、prices.models 为空。
按兜底表算几个数(汇率 7.2):
| 用量 | 美元 | 人民币 |
| 1M 未命中输入 | 0.14 | ¥1.008 |
| 1M 输出 | 0.28 | ¥2.016 |
| 1M 缓存读取 | 0.0028 | ¥0.02016 |
| 1M 缓存写入 | 0.0028 | ¥0.02016 |
| 1M 未命中输入 + 1M 输出 + 1M 缓存读取 + 1M 缓存写入 | 0.4256 | ¥3.06432 |
有账本配置时
只要 ledger.json 读得到,用的就是账本里的价格表、汇率、小数位与峰谷规则;内置那份兜底表只在读不到的时候整份顶上(模型级单价缺失时退回 prices.default,default 也缺失时退回兜底单价)。
能力边界与已知限制
它给的是估算,不是账单。 以下是代码层面能确定的口径与边界:
1. 只统计 usage 的四个 token 桶。会话事件流里 usage 之外的任何计费项都不计入。
2. 价格依赖账本。账本读不到时按内置兜底表(DeepSeek 官方 deepseek-flash 档 + 汇率 7.2)算。
你的模型或渠道不在账本里、或账本价格与你的实际合同价不同时,显示值会与实际扣费不一致。
3. 缓存写入按命中价计。这是与 dsh-cost-meter 对齐的口径;渠道对缓存写入另有定价时,这里不会体现。
4. 峰谷档按 UTC 小时判断,且 peakEffectiveAt 之前的调用一律按基础价; peakEnabled 不是布尔 true(例如配置里写成字符串)时峰谷规则完全不生效; peakEffectiveAt 无效或缺失时,窗口外的调用不会走 offPeak 档,而是按基础价。
5. 配置只读一次(插件加载时),改账本要重启 dsh web。
6. 金额是四舍五入后的显示值:按 decimals 位 toFixed 后去掉末尾的 0;金额小于 10^-decimals 时自动多给两位小数(最多 12 位),所以极小金额不会显示成 ¥0。
7. 「本轮」= 轮次号最大的一轮,不是「正在跑的那一轮」。
8. 只有一轮时,两段文案会重复显示同一个金额:输入框下方的文案本意是「只有一轮时不重复两遍」,但那条合并条件比较的是对象引用,而 turns 里的条目和 totals 不是同一个对象,所以一轮时仍会显示「本轮 ¥x · 本对话 ¥x」。这一条是从代码读出来的,没有在浏览器里逐帧实测。
9. 输入框下方的药丸靠 DOM 落位:它选的是带 [data-composer-stats] 标记属性的那个容器。
宿主哪天改掉这个标记,药丸就不再出现(回合尾部的徽章走的是插件槽位,不受影响)。
插件对 DOM 变化挂了 MutationObserver:那一行被会话切换重建、或宿主往末尾追加自己的节点时,会自动把自己插回并挪到最后一个位置,同时认领已存在的同类节点以避免同一行出现两个。
10. 宿主端没起来就什么都不显示:客户端取不到 turnCost 投影时静默不渲染(不报错、不占位)。
测试
node test.mjs
test.mjs 零依赖(只用 Node 内置模块),也不需要 DSH 在运行,更不需要装 react / zod。
它覆盖 lib/pricing.js——本插件里唯一能在离线环境判定的部分,因为它是个纯函数模块,只依赖 node:fs / node:path / node:os。测的内容:
- 兜底单价、符号、小数位、汇率、峰谷开关;
- 从临时 ledger.json 解析配置,含 decimals 夹取、exchangeRate 兜底、peakWindows 跨零点环绕;
- 模型单价查找与回退(模型 → prices.default → 兜底单价);
- 档位选择(峰谷关闭 / 生效前 / 峰时段 / 非峰时段 / 档位缺失);
- 金额公式(四个桶、负值夹 0、汇率非法按 1);
- 发布字段:包名、无 private、engines、repository、files、版本号与 CHANGELOG 一致;
- 改名的三处一致性:package.json 的 name == cordis.patch.yml 里的 name == lib/client.js 里
window.__ModuleLoader__.load({ id }) 的 id(客户端模块按这个 id 注册,对不上会加载失败);
- 文档一致性:每个被读取的配置键都必须在 README.md 与 README.en.md 里出现,且 README 里的兜底单价与汇率与代码一致;
- 仓库里所有文本文件都不含本机路径片段。
CI 跑的就是这一条命令(见 .github/workflows/ci.yml),任何 Node ≥ 18 的机器上都能跑通。
没有覆盖、也没放进 CI 的部分:
| 部分 | 为什么 |
| lib/index.js(宿主端投影) | import { z } from 'zod',且投影要跑在 DSH 的 sessionProjections 上下文里 |
| lib/client.js(浏览器端) | 单文件 bundle,靠 window.__ModuleLoader__ 加载,要真实浏览器 + DSH 页面 |
| 端到端(真的显示出金额) | 需要 DSH 正在运行,并且有一次真实模型调用 |
这三部分只能手动核验:重启 dsh web 后看那行自检日志,再在一次真实回复后看输入框下方有没有多出「本轮 ¥… · 本对话 ¥…」药丸、以及该轮尾巴上有没有徽章。本仓库没有对它们做自动化验证。
许可
MIT。
离线验证
陌生人 clone 后可直接运行:
node test.mjs
该命令只使用 Node 内置模块,实际 import lib/pricing.js,覆盖兜底配置、计价公式、模型/峰谷单价选择、账本解析、边界处理和发布字段一致性。输出会给出“离线可测 N 项 / 需真实环境 M 项”,并明确打印每个 SKIP;React 渲染、DSH runtime 装配、真实用量事件和浏览器页面不在离线覆盖范围内。预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
CHIP-PHILO-GH/dsh-turn-cost
在输入框与每轮回复尾部显示本轮和对话花费的人民币
相关插件 · 模型接入
API 中继安全审计toby-bridges/api-relay-audit
面向 AI API 中转与 LLM 代理的本地安全审计。
★ 897已汉化DSH
69.4
免费搜索插件DDDMUC/dsh-free-search
DeepSeek Harness 免费搜索插件 —— 无需 API key,零成本,多引擎可切换。 一个给…
★ 761已汉化DSH
68.7
免费联网搜索liustack/modsearch
在官方 App 里模型能联网,切到 API 就不能了。ModSearch 把联网补回来:网页搜索、X…
★ 863已汉化DSH
68.5
OpenCode 免费模型FishBottle7/opencode2dsh
在 DSHDeepSeek Harness里原生使用 OpenCode Zen 的免费匿名模型。
★ 379已汉化DSH
67.8
AI 模型网关tingly-dev/tingly-box
Tingly Box Web UI 演示
★ 373已汉化DSH
67.4
WorkBuddy 账号池XDTrees/dsh-xdpool
把你能白嫖的模型额度接进 DSH 同一个池:WorkBuddy 多账号自动容错、十三家扫码登录、76…
★ 359已汉化DSH
67.1