🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

用量计费表 faith1688/dsh-usage-meter-harness

DeepSeek Harnessv2.0.39
faith168851 天前有提交已提供中文文档扫描:含敏感能力

在输入框旁实时查看 token 用量、花费与余额

31.7/100
综合分
3
GitHub 星标
270
npm 周下载
—/5
用户评分

数据截至 2026/9/18 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add @faith1688/dsh-usage-meter-harness
npm 源 · @faith1688/dsh-usage-meter-harness 的发布者账号已校验与本仓库一致

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
dsh 原生插件 · other
装得上吗
本站已在 dsh 0.2.1-rc.2 下真实安装成功
非静态推断
L5 · 运行时冒烟等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 51 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查✓ 自动检查通过
展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✓npm 包@faith1688/dsh-usage-meter-harness @ 2.0.39
✓Node 引擎要求 >=22 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/10 15:48:27

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 123 处,展示前 69 条)
  • 写入本地文件
    lib/index.js:136
    mkdirSync(dataRoot(), { recursive: true });
  • 读取本地文件
    lib/index.js:137
    if (existsSync(legacyStatePath()) && !existsSync(configPath())) {
  • 写入本地文件
    lib/index.js:139
    copyFileSync(legacyStatePath(), configPath());
  • 读取本地文件
    lib/index.js:143
    if (existsSync(legacySaltPath()) && !existsSync(saltFilePath())) {
  • 写入本地文件
    lib/index.js:145
    copyFileSync(legacySaltPath(), saltFilePath());
  • 写入本地文件
    lib/index.js:151
    mkdirSync(exportsDir, { recursive: true });
  • 读取本地文件
    lib/index.js:152
    for (const f of readdirSync(dataRoot())) {
  • 读取本地文件
    lib/index.js:155
    if (!existsSync(dst)) {
  • 写入本地文件
    lib/index.js:157
    renameSync(join(dataRoot(), f), dst);
  • 读取本地文件
    lib/index.js:179
    if (existsSync(saltFilePath()))
  • 读取本地文件
    lib/index.js:180
    salt = readFileSync(saltFilePath(), 'utf8');
  • 写入本地文件
    lib/index.js:183
    mkdirSync(dataRoot(), { recursive: true });
  • 删除本地文件
    lib/index.js:899
    rmSync(modelApiKeyPath(safeKey), { force: true });
  • 删除本地文件
    lib/index.js:2433
    rmSync(full, { force: true });
  • 发起网络请求
    lib/client.js:1848
    const res = await fetch("/api/usage-meter/models");
  • 发起网络请求
    lib/client.js:1939
    const res = await fetch("/api/usage-meter/stats");
  • 发起网络请求
    lib/client.js:2602
    const res = await fetch("/api/usage-meter/templates");
  • 发起网络请求
    lib/client.js:2614
    const res = await fetch("/api/usage-meter/config");
  • 发起网络请求
    lib/client.js:2665
    const res = await fetch("/api/usage-meter/models");
  • 发起网络请求
    lib/client.js:2690
    const res = await fetch("/api/usage-meter/config");
  • 执行外部命令固定命令
    scripts/install.mjs:26
    execFileSync('cmd.exe', ['/c', 'npm', ...args], { stdio: 'inherit' });
  • 执行外部命令固定命令
    scripts/install.mjs:28
    execFileSync('npm', args, { stdio: 'inherit' });
  • 发起网络请求
    lib/pricing-page.js:240
    const res = await fetch(url, { signal: ctrl.signal, headers: { 'user-agent': 'dsh-usage-meter/1.0 (pricing sync)' } });
  • 请求外部主机api.deepseek.com
    lib/pricing-page.js:403
    const res = await fetch('https://api.deepseek.com/v1/chat/completions', {
  • 发起网络请求
    lib/pricing-page.js:403
    const res = await fetch('https://api.deepseek.com/v1/chat/completions', {
  • 发起网络请求
    lib/prices.js:138
    const res = signal === undefined ? await fetch(url) : await fetch(url, { signal });
  • 发起网络请求
    lib/prices.js:180
    const res = signal === undefined ? await fetch(url) : await fetch(url, { signal });
  • 请求外部主机api.deepseek.com
    lib/balance.js:29
    ? await fetch('https://api.deepseek.com/user/balance', {
  • 发起网络请求
    lib/balance.js:29
    ? await fetch('https://api.deepseek.com/user/balance', {
  • 请求外部主机api.deepseek.com
    lib/balance.js:33
    : await fetch('https://api.deepseek.com/user/balance', {
  • 发起网络请求
    lib/balance.js:33
    : await fetch('https://api.deepseek.com/user/balance', {
  • 读取本地文件
    scripts/_extract-swatch-colors.mjs:19
    const png = PNG.sync.read(readFileSync(file));
  • 执行外部命令固定命令
    scripts/migrate-provider.mjs:40
    const out = execSync('wmic process where "name=\'node.exe\'" get commandline', { encoding: 'utf8' });
  • 写入本地文件
    scripts/migrate-provider.mjs:48
    mkdirSync(backupDir, { recursive: true });
  • 读取本地文件
    scripts/migrate-provider.mjs:50
    const bak = (p) => { if (existsSync(p)) writeFileSync(join(backupDir, basename(p)), readFileSync(p)); };
  • 写入本地文件
    scripts/migrate-provider.mjs:50
    const bak = (p) => { if (existsSync(p)) writeFileSync(join(backupDir, basename(p)), readFileSync(p)); };
  • 读取本地文件
    scripts/migrate-provider.mjs:50
    const bak = (p) => { if (existsSync(p)) writeFileSync(join(backupDir, basename(p)), readFileSync(p)); };
  • 读取本地文件
    scripts/migrate-provider.mjs:68
    if (existsSync(settingsPath)) {
  • 读取本地文件
    scripts/migrate-provider.mjs:70
    let s = readFileSync(settingsPath, 'utf8');
  • 写入本地文件
    scripts/migrate-provider.mjs:75
    if (s !== before) { writeFileSync(settingsPath, s); changed++; console.log('[OK] settings.yaml 已更新(提供方改名 + apiKeyEnv + 辅助引用)'); }
  • 读取本地文件
    scripts/migrate-provider.mjs:83
    if (existsSync(encPath)) {
  • 读取本地文件
    scripts/migrate-provider.mjs:84
    const salt = readFileSync(join(dataRoot, 'salt'), 'utf8');
  • 写入本地文件
    scripts/migrate-provider.mjs:99
    writeFileSync(credPath, c);
  • 写入本地文件
    scripts/migrate-provider.mjs:112
    writeFileSync(cfgPath, JSON.stringify(deepReplace(cfg), null, 2));
  • 写入本地文件
    scripts/migrate-provider.mjs:122
    writeFileSync(statsPath, JSON.stringify(deepReplace(stats), null, 2));
  • 读取本地文件
    scripts/probe-accounts.mjs:9
    const salt = readFileSync(join(dataRoot, 'salt'), 'utf8');
  • 读取本地文件
    scripts/probe-accounts.mjs:13
    const [iv, dat] = readFileSync(join(dataRoot, f), 'utf8').split(':');
  • 读取本地文件
    scripts/probe-accounts.mjs:19
    const cfg = JSON.parse(readFileSync(join(dataRoot, 'config.json'), 'utf8'));
  • 请求外部主机api.deepseek.com
    scripts/probe-accounts.mjs:33
    const r = await fetch('https://api.deepseek.com/user/balance', { method: 'GET', headers: { Authorization: `Bearer ${apiKey}`, Accept: 'application/jso
  • 发起网络请求
    scripts/probe-accounts.mjs:33
    const r = await fetch('https://api.deepseek.com/user/balance', { method: 'GET', headers: { Authorization: `Bearer ${apiKey}`, Accept: 'application/jso
  • 读取本地文件
    scripts/probe-header-events.mjs:17
    try { entries = readdirSync(dir, { withFileTypes: true }); } catch { return out; }
  • 读取本地文件
    scripts/probe-header-events.mjs:27
    const buf = readFileSync(path);
  • 读取本地文件
    scripts/probe-header-events.mjs:44
    .map((f) => ({ f, mtime: statSync(f).mtimeMs }))
  • 读取本地文件
    scripts/probe-keys.mjs:11
    const salt = readFileSync(saltPath, 'utf8');
  • 读取本地文件
    scripts/probe-keys.mjs:13
    console.log('salt mtime:', statSync(saltPath).mtime.toISOString());
  • 读取本地文件
    scripts/probe-keys.mjs:15
    const files = readdirSync(apikeysDir).filter((f) => f.endsWith('.enc')).sort();
  • 读取本地文件
    scripts/probe-keys.mjs:17
    const st = statSync(join(apikeysDir, f));
  • 读取本地文件
    scripts/probe-keys.mjs:18
    const [ivB64, dataB64] = readFileSync(join(apikeysDir, f), 'utf8').split(':');
  • 读取本地文件
    scripts/probe-wrapper-route.mjs:15
    if (!existsSync(cfgPath)) { console.log(`no config.json at ${cfgPath}`); process.exit(1); }
  • 读取本地文件
    scripts/probe-wrapper-route.mjs:16
    const cfg = JSON.parse(readFileSync(cfgPath, 'utf8'));
  • 读取本地文件
    scripts/probe-wrapper-route.mjs:17
    const stats = existsSync(statsPath) ? JSON.parse(readFileSync(statsPath, 'utf8')) : {};
  • 读取本地文件
    scripts/probe-wrapper-route.mjs:17
    const stats = existsSync(statsPath) ? JSON.parse(readFileSync(statsPath, 'utf8')) : {};
  • 读取本地文件
    scripts/probe-wrapper-route.mjs:18
    const apikeys = existsSync(join(dataRoot, 'apikeys')) ? readdirSync(join(dataRoot, 'apikeys')) : [];
  • 读取本地文件
    scripts/probe-wrapper-route.mjs:18
    const apikeys = existsSync(join(dataRoot, 'apikeys')) ? readdirSync(join(dataRoot, 'apikeys')) : [];
  • 读取本地文件
    scripts/scan-sessions.mjs:19
    try { entries = readdirSync(dir, { withFileTypes: true }); } catch { return out; }
  • 读取本地文件
    scripts/scan-sessions.mjs:31
    const buf = readFileSync(path);
  • 读取本地文件
    scripts/scan-sessions.mjs:48
    .map((f) => ({ f, mtime: statSync(f).mtimeMs }))
  • 读取本地文件
    scripts/test-inject-contract.mjs:70
    src = readFileSync(file, 'utf8');
  • 读取本地文件
    scripts/test-token.mjs:3
    const src = readFileSync(new URL('./migrate-provider.mjs', import.meta.url), 'utf8');
扫描于 2026/11/2(1 天前) · 范围 入口闭包 + 全包扫描 · 来源 npm 发布包
涉及外部主机:api.deepseek.com

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

依赖的 DSH / Cordis 模块
@deepseek-ai/schemastery@deepseek-ai/cordis@deepseek-ai/dsh-client-runtime@deepseek-ai/dsh-client-ui-conversation@deepseek-ai/dsh-client-ui-slots@deepseek-ai/dsh-llm@deepseek-ai/dsh-session@deepseek-ai/dsh-session-projection@deepseek-ai/dsh-settings
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 实时查看token用量
  • 显示花费金额
  • 显示真实余额

专为 DeepSeek API 打造的实时用量 / 费用 / 余额计量插件 —— 在聊天输入框旁直接看到 tokens、花费与真实余额。

v2.0.392026-09-13
· v2.0.39 — 紧急修复:v2.0.38 会让插件在启动时崩溃(Failed to load plugins) v2.0.38 是坏的,请勿使用,直接装 2.0.39。 2.0.38 已在 npm 上被标记为弃用(deprecated)。 · 现象(真机实测) 另一台电脑装完 2.0.38、重启 dsh 后,界面直接报: HARNESS Failed to load plugins @faith1688/dsh-usage-meter-harness failed to apply loader entry 68ef7fc2 (@faith1688/dsh-usage-meter-harness): cannot get property "locale" without inject · 根因:类型转换不是探测 v2.0.38 为了让插件在任何组合下都能挂上,把客户端的 locale 从 inject 里删掉了(cordis 没有"可选依赖":声明了却没人提供,apply 就永远不执行)。但代码里仍然直接读 ctx.locale,只是外面套了一层 TypeScript 的类型转换: const svc = (ctx as unknown as { locale?: … }).locale; // ← 编译期没事,运行时会抛 ctx 在运行时是代理:读一个「已提供但没 inject」的服务名,它会直接抛错。类型转换只能骗过编译器,骗不过宿主。于是插件加载失败——比它想修的问题更糟。 修法:所有可选服务一律走真正的探测(与服务端 webServer/llm 同一套): function readOptionalService(ctx, name) { // 优先用反射助手 ctx.get(name);没有它时退化到带 try/catch 的属性读 } · 新增两道回归防线(这次的教训是"验证没覆盖到就一定会漏") 1. scripts/test-inject-contract.mjs —— 用 TypeScript AST 解析 lib/*.js:凡是 ctx. 的属性访问,必须在同文件的 inject 里;否则 FAIL。已用它跑过坏的 2.0.38 产物,确认能报出 ctx.locale(先证明检查有效,再看它变绿)。 2. scripts/test-client-apply.mjs —— 用一个复刻 cordis 行为的代理 ctx,真的跑一遍 client.tsx 的 apply:读未 inject 的服务会抛错,ctx.get() 不抛。内含元测试先证明这个替身真的会抛,再断言真实 apply 跑通、两个席位都注册、locale 只走探测路径。 · 验证(发布前实跑) · tsc --noEmit、npm run bundle 零报错。 · scripts/test-inject-contract.mjs → ALL PASSED(对坏产物先 FAIL 过,证明有效)。 · scripts/test-client-apply.mjs → ALL PASSED(含两条元测试)。 · 既有回归:test-live-rate / test-usage-accounting / test-shared-balance-lock / sim-live-balance 全 PASS。 · 旧版 DSH 0.1.2 真机:web 组合 5 个端点全 200;headless 组合只出现降级说明、不谎报。 · 注意事项 1. 装完/更新完必须重启 dsh web。 2. 发布后 24 小时内,从插件市场更新可能被 pnpm 冷静期拦下并自动回滚——等 24h,或把包名加入 minimumReleaseAgeExclude,或用 npx -y @faith1688/dsh-usage-meter-harness@latest。 --- · v2.0.39 — English Hotfix: v2.0.38 broke plugin startup (Failed to load plugins). Do not use 2.0.38 — install 2.0.39. 2.0.38 is marked deprecated on npm. Symptom: after installing 2.0.38 and restarting dsh, the harness failed with failed to apply loader entry … cannot get property "locale" without inject. Cause: v2.0.38 removed
v2.0.352026-09-11内容较长已截断
· v2.0.35 — 从 1.0.34 升级:全部新增功能一览 npm 上的上一个发布版本是 1.0.34。本次发布 2.0.35,使用 1.0.34 的用户升级后会一次性获得下面全部更新(v1.0.35 → v2.0.35 一整条线)。 安装/升级命令见文末。 --- · 一、新增功能 · 主题与外观(2.0.x → 2.0.34) · 20 个内置主题:浅色系在前、深色系在后,默认 forest-beach-dawn(林滩晓色)。用量弹窗顶部 ⇄ 直接快切,设置页「主题设置」有完整配色预览。 · 每主题可自定义配色:胶囊色、呼吸光晕色、预警三色(余额足 / 不足 / 透支)、速度三档色(0-50 / 51-100 / 101+ tokens/s);改动即时保存到本机,切换主题不丢。 · 胶囊身份色 = 主题色(2.0.30):峰 / 谷 / 平时态跟随主题 brand 家族渲染,不再是写死的固定色。 · 峰谷胶囊 + 峰谷徽章(2.0.29 / 2.0.31):谷价浅绿、峰价浅红,计费中带柔和呼吸光晕,一眼看出当前是峰价还是谷价。 · 胶囊按余额三档着色(2.0.32):余额足 / 不足 / 透支三色,「余额足」的颜色可在设置页单独调。 · 用量与看板 · 用量展板(1.0.36):弹窗右上角 ▦ 打开,三种视图 —— 全部 / 按供应商 / 按模型;数据来自服务端跨会话累计的 /api/usage-meter/stats。 · 当前会话看板(2.0.x):弹窗默认展开「当前会话」—— 总计 + 分项金额 + 每轮费用明细;坐标标签用 provider · model,同名官方/自定义模型不会混淆。 · 余额预警阈值 + 呼吸色(1.0.36):全局「预算预警 %」与「余额预警下限」;模型与供应商可各自覆盖(其他设置 → 预警)。触发时输入框旁的胶囊呼吸变红。官方模型按实时余额金额比对,其他模型按预算百分比。 · 计费 · 一键同步官方价格(2.0.x):设置页一键抓取 DeepSeek 官网价格页,解析最新单价与峰谷时段并写入覆盖,随时保持官方价最新(需先填全局 API Key)。 · 计费模板导出 / 导入(1.0.35):导出到共享持久目录(默认 $DSH_HOME/usage-meter/exports),支持覆盖 / 重命名 / 复制 / 删除 —— 多机、多 profile 共用同一套计费模板。 · 设置与易用性 · 设置页选项卡化(1.0.36):余额预警 / 主题设置 / 模型后缀识别 / 工作目录设置分区,找设置不用长滚动。 · 视觉包装识别可配(1.0.36):逐行「标记 + 开关」配置模型名前缀 / 后缀,可增行、删行,每行独立生效。 · 中英双语三选项(2.0.x):跟随系统 / 中文 / English,选择自动记住,设置页与弹窗全部即时生效,英文界面完整(389 条英文词条)。1.0.34 只能「中文 / English」二选一,且不记住选择。 · 未保存 / 已保存 状态(2.0.x):模型卡编辑后显示「未保存」,保存后显示「已保存」——不再有含糊的「保存中」。 · DS API Key 守卫(2.0.x):非官方模型绝不会回落使用 DeepSeek 官方全局 key,未设置时明确显示「未配置」。 · 「本对话费用」文案(2.0.x):会话级费用的措辞更明确。 --- · 二、计费准确性修复 · 回合归因(2.0.14 + 2.0.35):会话中途切换模型时,正在进行的回合不再沿用上一回合的模型标签。实测问题:切到 deepseek-flash 后正在跑的第 80 轮仍显示旧模型(ngrok-ollama/Qwen3.8-27B)。现在识别 DSH 官方 model/selection 事件,回合归属 = 本回合第一个真正产生用量的请求,定标后永不改写。 · 回合币种(2.0.35):此前 currency 参数从未真正生效,回合币种恒为 CNY —— 美元定价的回合总额少换算一个汇率。现在以本回合首个计费用量的定价币种定标。 · 退化峰谷窗口(2.0.35):手工或 API 写入的畸形窗口 {start === end} 是空集,此前判定恰好铺满全天 → 全天都按峰价计费。现已视作无窗口。 · 看板统计漏计(2.0.35):统计改用 (turn, step) 基线去重,修复三处漏计 —— 会话中途切模型后该会话看板样本全丢、新 step 首段用量被 clamp 成 0、相邻两步等值样本被误判为重复。 · 统一计费时钟(2.0.35):看板此前按 usage 到达时刻定价,与钱包按 step 起始时刻不一致 —— 11:59(峰)发起、12:01(谷)才收单的请求
v1.0.342026-09-05
v1.0.34:修复请求同时通过 assistant/chunk 和 assistant/message 上报用量时重复计费的问题(issue #1)。 · usageEventOf 的 chunk 分支改为从宿主外层 event.data 读取 turn/step(原先读 chunk.turn ?? 0,得到 (0,0)),这样 chunk 和最终 message 会去重成一次计费。 · 忽略全零的初始化样本(不能覆盖正在运行的基线)。 · 把每个桶的增量钳制到 >= 0(重试或更小的修正样本不会产生负 token/费用)。 · 修正模拟器的 chunk 事件结构(原先也把 turn/step 嵌套在里面),并新增回归阶段 9-11。 · 回归:scripts/sim-live-balance.mjs
数据来自仓库的 GitHub Release,可能与插件实际版本不一致。

README

由 DeepSeek 最新模型翻译生成
dsh-usage-meter-harness DeepSeek Harness(DSH)的实时用量 / 费用 / 余额计量插件。 在聊天输入框旁直接看到 token 用量、消费金额和真实钱包余额——官方 DeepSeek 模型和你注册的任何自定义模型都支持。 设置页截图 安装 前置(方式一、二):DSH CLI 本身基于 pnpm,每台机器装一次即可: npm install -g pnpm(或 corepack enable),用 pnpm --version 验证。 三选一。方式一和方式二需要 pnpm(DSH CLI 本身的一次性前置要求,任意插件都一样): npm install -g pnpm 或 corepack enable。 方式一 —— npm 源(需要 pnpm) dsh plugin --profile web add --verbose @faith1688/dsh-usage-meter-harness@latest (--verbose 显示安装进度,可去掉。@latest 显式请求最新版——请始终这样安装。
展开完整文档(README 剩余 1 节)
dsh-usage-meter-harness

DeepSeek Harness(DSH)的实时用量 / 费用 / 余额计量插件。
在聊天输入框旁直接看到 token 用量、消费金额和真实钱包余额——官方 DeepSeek 模型和你注册的任何自定义模型都支持。

设置页截图

安装

前置(方式一、二):DSH CLI 本身基于 pnpm,每台机器装一次即可:
npm install -g pnpm(或 corepack enable),用 pnpm --version 验证。

三选一。方式一和方式二需要 pnpm(DSH CLI 本身的一次性前置要求,任意插件都一样):
npm install -g pnpm 或 corepack enable。

方式一 —— npm 源(需要 pnpm)

dsh plugin --profile web add --verbose @faith1688/dsh-usage-meter-harness@latest

(--verbose 显示安装进度,可去掉。@latest 显式请求最新版——请始终这样安装。)

方式二 —— GitHub 源(需要 pnpm)

dsh plugin --profile web add --verbose github:faith1688/dsh-usage-meter-harness#main

(--verbose 显示安装进度。)

方式三 —— 一行命令安装,不需要 pnpm(推荐)

npx -y @faith1688/dsh-usage-meter-harness@latest
一条命令:自动装进 DSH web profile 并注册 bundle(幂等)。
(@latest 显式请求最新版——请始终这样安装。)

不想用 npx?仓库里也带了同样的脚本:

Windows(cmd):

curl -fsSL https://raw.githubusercontent.com/faith1688/dsh-usage-meter-harness/main/scripts/install.cmd -o "%TEMP%\um-install.cmd" && "%TEMP%\um-install.cmd"

Linux / macOS:

curl -fsSL https://raw.githubusercontent.com/faith1688/dsh-usage-meter-harness/main/scripts/install.sh | sh

脚本会自动完成全部步骤:进入 DSH web profile → 安装包(可见进度)→ 注册 dsh.profile.bundles(幂等,升级后重跑安全)。

注意:方式三用的是原生 npm,不做 pnpm 协调。如果你的 profile 由 pnpm 管理(dsh plugin 的默认方式),推荐用方式一。

任选一种方式后:重启 dsh web。

更新

分两种情况——请对号入座:

全新安装(从没装过),或使用 npx 方式: 直接跑安装命令即可,永远拉取最新版。

升级已有安装(插件已存在): profile 的 package.json / pnpm-lock.yaml 可能锁在旧版本,不带版本号的 add 会被 pnpm 判定"已满足"而跳过。升级时务必显式指定新版本:

dsh plugin --profile web add @faith1688/dsh-usage-meter-harness@latest

或在 profile 目录(~/.dsh/profiles/web)里执行:

pnpm update @faith1688/dsh-usage-meter-harness

(也可以指定精确版本,如 ...@1.0.28。)

在插件市场里点「更新」失败? 如果提示「更新目标为 vX,但实际安装为 vY;已自动恢复原版本」,那是 pnpm 的新版本冷静期(刚发布的版本约 24 小时内会被跳过),不是你装坏了,配置和余额数据都没动。等 24 小时再点一次即可;想立刻升级就用下面的 npx 方式,或在 profile 的 pnpm-workspace.yaml 里把 minimumReleaseAgeExclude 加上本包名(不带版本号)。

更新后:重启 dsh web(或刷新浏览器页面)。注意:重启本身不会拉取新版本——它只是重新加载 node_modules 里已有的包。

为什么这样更新绝不会产生重复挂载记录、也绝不会动你的配置:

- 挂载记录在插件包内部(cordis.patch.yml,dsh.bundle 机制)。每个版本自带完整的一条挂载记录;DSH 启动时从已安装的包里读取——装上新版本包,自动就带上新版本的正确记录。
- 安装器只改 profile 的 package.json(dsh.profile.bundles,自动去重)和 node_modules。从不写 profile 根目录的 cordis.patch.yml——你在里面自己加的内容(或其他插件的配置)原样保留。
- 重复挂载记录只可能发生在:你手动往 profile 根 cordis.patch.yml 里加了相同的 id——安装器永远不会这样做。

功能一览

对话用量卡(聊天输入框旁)

| 功能 | 说明 |
| 实时费用 | 会话累计费用,CNY / USD 可切换,每步实时更新 |
| Token 明细 | 输入(未命中) / 缓存命中 / 缓存写入 / 输出 分桶统计 |
| 本轮用量面板 | 逐轮小计,单价带峰/谷标记 |
| Token 速度 | 模型输出时实时 tokens/s;输出停止或工具执行时自动清零,不冻结旧值 |
| 缓存命中率 | 会话级缓存命中占比 |
| 账户余额 | DeepSeek 官方真实钱包余额;其他厂商按本地账本估算 |
| 预算与剩余 | 设置预算后显示已用 / 剩余 / 超支 |

计费引擎

| 功能 | 说明 |
| 6 种计费模板 | 基础 · 缓存命中/未命中 · 峰谷分时(DeepSeek 官方时段)· 缓存写入+命中 · 输入+输出合并 · Batch 半价 |
| 自定义单价项 | 最多 4 行自定义行;弹窗与你配置的内容逐格一致 |
| 峰谷分时计费 | 北京时间星期 + 时段窗口,支持跨零点时段;按每次请求的发起时刻计费 |
| 回合归因精确 | 每轮费用记在真正执行它的模型名下——会话中途切模型不会把未结束或已结束的回合重新打标;回合币种在本轮首个计费用量到达时定标,美元定价的回合换算正确 |
| 每模型独立计价 | 每个模型可单独设置币种(CNY/USD)、单价与余额 |
| 共享余额钱包 | 一个供应商下所有模型共用一个钱包,一个复选框开关 |
| 官方价预填 | DeepSeek 官方模型自动预填官方价与官方峰谷时段 |
| 内置价格表 | 内置 19 家厂商 137 个模型价格;可选 LiteLLM 形状的远端价格源 |
| 汇率自动刷新 | USD→CNY 自动获取,超过 24 小时自动更新 |
| 一键同步官方价格 | 设置页一键抓取 DeepSeek 官网价格页,解析最新价格与峰谷时段并写入覆盖(需先填全局 API Key),随时保持官方价最新 |
| 旧数据迁移 | 旧版手动初始余额/充值记录自动迁移为厂商钱包,余额不丢失 |

设置与体验

| 功能 | 说明 |
| 中英双语界面 | 设置页右上角语言切换:跟随系统 / 中文 / English,设置页与弹窗全部即时生效,选择自动记住。只影响显示,绝不改动你保存的数据 |
| 主题 | 20 个内置主题(浅色系在前、深色系在后,默认 forest-beach-dawn)+ 每个主题可自定义胶囊颜色与呼吸颜色——用量弹窗顶部快速切换,设置页完整配色,选择保存在本机 |
| 使用中锁定 | 模型正在生成时锁定其编辑器,保证进行中的轮次价格一致 |
| 弹窗所见即所得 | 用量卡的行名与格子完全抄自你选择的模板 |
| 无侵入 | 标准 DSH cordis 插件;不改动其他插件,不动 DSH 核心文件 |
| 峰谷胶囊 | 谷价时胶囊变浅绿、峰价时变浅红(计费中带柔和呼吸光晕),一眼看清当前是峰价还是谷价 |
| 未保存/已保存 | 模型卡编辑后显示「未保存」,点保存后显示「已保存」——不再有含糊的「保存中」 |
| 当前会话看板 | 弹窗默认直接展开「当前会话」视图(总计 + 分项金额 + 每轮费用);坐标标签用 provider · model,同名官方/自定义模型一眼可分 |
| DS API Key 守卫 | 非官方模型勾选「DS API Key」时提示该选项仅 DeepSeek 模型使用;自定义模型绝不回落官方全局 key,未设置显示「未配置」 |

支持的模型

- DeepSeek 官方模型(deepseek-chat、deepseek-reasoner 等):自动预填官方价,通过 API Key 显示真实钱包余额。
- 任意自定义模型(DSH 注册的 OpenAI 兼容厂商、Ollama、OpenRouter 等):自行填写单价与余额即可,其余功能完全一致。

截图

设置页:

设置页

用量弹窗:

用量弹窗

配置

所有配置都在 usage-meter 设置命名空间,可直接在插件界面里修改:

| 键 | 类型 | 默认 | 说明 |
| currency | string | CNY | 显示币种 |
| budget | number | – | 会话预算;设置后显示「剩余」 |
| priceSourceUrl | string | – | LiteLLM 形状的价格 JSON 地址;可选 |
| refreshIntervalMs | number | 4h | 价格 / 余额 / 汇率刷新周期 |
| deepseekApiKey | secret | – | 仅用于查询 DeepSeek 余额(AES 加密存储;不读取环境变量 DEEPSEEK_API_KEY) |

兼容性

- 需要 Node.js ≥ 22。
- peer 版本跟随所支持的 DSH 版本(见 package.json);DSH 升级不影响本插件,本插件也不会影响你的其他插件。

License

MIT © faith1688

隐私

- 插件无任何遥测、无统计。
- 网络请求全部由你主动发起,共四处可选:① 用你自己配置的 API Key 查询 DeepSeek 官方余额接口; ② 获取公开的 USD→CNY 汇率;③ 一键同步官方价格时抓取 DeepSeek 官网价格页; ④ 仅当价格页规则解析失败时,把该页内容发给 DeepSeek 官方接口(用你的全局 Key)提取。
除此之外没有任何数据离开你的机器。
- 源码 MIT 协议,GitHub 上完全可查。
预览分享卡片长什么样 ↓faith1688/dsh-usage-meter-harness
分享 · DeepSeek Harness Hub
faith1688/dsh-usage-meter-harness

在输入框旁实时查看 token 用量、花费与余额

这是你的仓库?认领条目

回到顶部