@dsh-external/dsh-deepseek-quota

August 26, 2026 · View on GitHub

一个 DeepSeek Harness bundle 插件:在聊天输入框上方的统计行(1 轮 · 14 步 | LLM … | 缓存命中 …) 正下方,显示一条 DeepSeek 额度行:

峰 | 余额:¥274.70 | 当前会话:¥0.0115 | 本轮对话:¥0.0038 | 子代理:¥0.0011

功能特性

会话额度行

  • 注册在 conversation.composer.dock 插槽(order 1,紧跟在内置统计行下方), 显示五段内容:

    • 峰谷:首列显示当前峰谷阶段(当前为高峰时段显示「峰」,低谷时段 显示「谷」;北京时间,含周末全天低谷规则——自 2026-08-23 00:00 起周六/ 周日全天按低谷价)。悬停打开计费规则卡片:价目表版本、峰谷时段、 周末规则与计价方式;其余明细卡片不再重复显示计费规则。
    • 余额:DeepSeek 账户总剩余额度(5 分钟轮询)。每次刷新后在括号内显示 与上次刷新的变化量余额:¥274.70(-0.05)),余额减少显示红色 -,增加显示绿色 +;悬停打开多标签明细面板每 5 分钟(逐次 刷新变化量)、每 1 小时 / 每 1 天时间阈值固化——距上次记录 满 1 小时/1 天才固化一条,首行"截至当前"随每次 5 分钟刷新实时更新并 显示距上次固化点的变化),每个视图固定 10 行无滚动条,并显示赠金/充值 信息;明细表的变化量拆分为两列:变化量(总)(账户总余额的变化) 与 变化量(当前API)(当前 API 的消耗变化,即该时间窗口内 DSH 所有 会话的 DeepSeek 用量消耗——由宿主端重放全部会话的持久日志、按同一峰谷 价目表计价,同一窗口内 变化量(当前API)变化量(总) 的差额即 其他 API 的消耗与充值等非用量变化)。余额快照、三类历史与全局消耗曲线 持久化在浏览器 localStorage,刷新页面后 即时恢复;
    • 当前会话:整个会话日志累计消耗(跨轮次、跨工具步骤);
    • 本轮对话:最新一轮(含该轮全部步骤)的消耗,流式输出期间实时增长; 新的一轮开启但尚无请求时显示 ,不回放上一轮的最终额度;
    • 子代理:本会话全部持久化后代子代理(含已完成、已冷存的)的累计消耗。
  • 数据来自持久日志而非 API:宿主端重放会话事件,折叠提供方上报的用量桶 (未缓存输入 / 缓存读取 / 缓存写入 / 输出,与 token-meter 投影同一套语义), 并按 DeepSeek 官方峰谷分时价目表计价。会话刷新、重启、翻页、压缩后数字不变 ——用量随会话持久化,金额只是对持久数据的即时视图。

  • 子代理不会重复计费:子代理日志开头的父会话继承前缀(seed)被跳过, 其用量只统计从 seedLength 起的自有事件;非 DeepSeek 模型的子代理不计价。

  • 官方峰谷分时定价(2026-08-17 起生效,北京时间,元/百万 tokens): 自 2026-08-23 00:00(北京时间)起,周末(周六/周日)全天不再区分峰谷, 统一按空闲(低谷)时段价格计费;生效前已产生的历史调用仍按原规则计价。

    模型时段输入(缓存命中)输入(缓存未命中)输出
    deepseek-chat(V4-Flash)高峰(工作日 09:00–12:00 / 14:00–18:00)0.103.009.00
    deepseek-chat(V4-Flash)空闲(其余时间,含周末全天)0.051.504.50
    deepseek-reasoner(V4-Pro)高峰(工作日 09:00–12:00 / 14:00–18:00)0.309.0027.00
    deepseek-reasoner(V4-Pro)空闲(其余时间,含周末全天)0.154.5013.50

    每个请求按请求发生时刻(事件时间戳,换算北京时间)选择高峰/空闲单价; 模型按 id 归入对应档位(*chat*/*flash* → V4-Flash,含 deepseek-v4-flash-vision-exp*reasoner*/*pro* → V4-Pro,未知模型 回退到 deepseek-chat 档)。价格可通过行配置覆盖。

  • 三段分别可悬停查看明细(悬浮面板,随主题样式渲染):

    • 悬停当前会话:首列显示当前峰谷阶段(峰/谷,北京时间、含周末 全天低谷规则),其后按模型(Flash / Pro 等档位)细分的额度消耗—— 输入(未命中)、缓存输入、输出三个计费桶各自的折算金额与合计;
    • 悬停本轮对话:本轮每一个请求(步骤)的时间、模型(超长截断,悬停 显示完整 id)、输入(未命中)、缓存输入、输出三个计费桶各自的折算金额 与合计(最多同时显示 5 行,超过内部滚动;超过 200 条请求截断显示);
    • 悬停子代理:每个子代理的模型、三个计费桶的折算金额与合计;非 DeepSeek 模型的子代理显示 - 占位,不计入总额。
  • 零运行时依赖;额度计算不调用 DeepSeek API(仅余额段需要 API Key)。

环境要求

  • DeepSeek Harness web profiledsh web)——该 bundle 只在 web profile 挂载。
  • 余额段需要配置 DeepSeek API Key(额度计算不需要):
    • Web 界面「设置 > 模型」页,或
    • ~/.dsh/.credentials.yamlDEEPSEEK_API_KEY),或
    • DEEPSEEK_API_KEY 环境变量。

安装

本插件是 bundle 插件:即 npm 包清单中声明了 dsh.bundle,其 cordis.patch.yml 层会被组合进 profile。

从 Git 仓库安装

dsh plugin --profile web add github:ErrorLst/dsh-deepseek-quota

git+https://github.com/ErrorLst/dsh-deepseek-quota.git 同样有效。)

dsh 0.1.0-rc.7 及以后版本在 dsh plugin add 成功后会自动 reconcile,把声明了 dsh.bundle.patch 的包自动登记进 dsh.profile.bundles,无需手动编辑 profile 的 package.json;仅旧版本 dsh 才需要手动登记。重启 dsh web

本地目录安装(开发调试)

dsh plugin --profile web add link:C:/path/to/dsh-deepseek-quota

本地开发请用 link:(符号链接)而不是 file:file: 会在安装时把插件 拷贝进 profile 的 node_modules,之后对插件目录的修改不会被 Web 服务读到 (表现为主机端新路由 404、界面没有新功能);link:node_modules 直接指向 插件目录,改动即时可见——宿主端改动重启 dsh web 生效,浏览器端改动刷新页面即可。

rc.7 及以后版本同样会自动 reconcile 登记 bundle 层,无需手动编辑;重启 dsh web 即可。

从 npm 安装(发布后)

dsh plugin --profile web add @dsh-external/dsh-deepseek-quota

卸载

dsh plugin --profile web remove @dsh-external/dsh-deepseek-quota

rc.7 及以后版本会自动 reconcile,从 dsh.profile.bundles 中移除该名称,无需手动 编辑 profile 的 package.json;仅旧版本 dsh 才需要手动移除。

使用

打开 Web 界面:额度行位于聊天输入框上方统计行的正下方。悬停 「当前会话 / 本轮对话 / 子代理」查看明细面板;悬停「余额」查看赠金/充值明细。

也可以直接访问接口:

curl http://127.0.0.1:3080/api/deepseek-quota
curl http://127.0.0.1:3080/api/deepseek-quota?refresh=1
curl "http://127.0.0.1:3080/api/deepseek-quota/context?sessionId=<session-id>"
curl "http://127.0.0.1:3080/api/deepseek-quota/spend?boundaries=<ms1>,<ms2>"

HTTP API

GET /api/deepseek-quota(由宿主编通过 webServer 提供)

// 成功
{
  "ok": true,
  "isAvailable": true,
  "balances": [
    { "currency": "CNY", "total": "123.45", "granted": "10.00", "toppedUp": "113.45" }
  ],
  "fetchedAt": 1735689600000
}

// 失败 — code 取值:
//   MISSING_KEY    未配置 API Key
//   AUTH           DeepSeek 拒绝该 Key(HTTP 401)
//   HTTP_<status>  上游其他 HTTP 错误
//   TRANSPORT      网络/超时错误
{ "ok": false, "code": "MISSING_KEY", "message": "DEEPSEEK_API_KEY 未配置:…" }

GET /api/deepseek-quota?refresh=1 绕过 TTL 缓存;非 GET 请求返回 405

GET /api/deepseek-quota/spend?boundaries=<ms1,ms2,…>

所有会话(在线 + 持久化,按 id 去重、子代理种子前缀不重复计费)的 DeepSeek 总消耗曲线:在每一个边界时间戳处返回自全部日志起始的累计消耗 (仅统计 DeepSeek 模型样本;其他提供方的用量永不按 DeepSeek 计价)。任意 窗口 (start, end] 的消耗 = boundaries[end].cost - boundaries[start].cost (用于余额明细表的「变化量(当前API)」列)。结果按 spendCacheTtlMs (默认 60 秒)缓存样本折叠,边界查询本身是 O(样本数 + 边界数);折叠预算 spendTimeoutMs(默认 30 秒,多会话持久化读取较重,别用 context 的 8 秒 预算——超时中断会让漏掉的会话用量在窗口里显示为 0)与 512 会话上限触发时 返回 partial: true(数字偏小但仍有意义,界面会提示)。边界最多 64 个, 非法/重复/负值边界会被丢弃。

{
  "ok": true,
  "currency": "CNY",
  "pricingVersion": "deepseek-v4-2026-08-23",
  "sessions": 12,
  "samples": 341,
  "boundaries": [
    { "at": 1755446400000, "cost": 0.01234, "costUncachedInput": 0.0045,
      "costCacheRead": 0.0002, "costCacheWrite": 0, "costOutput": 0.00764,
      "uncachedInputTokens": 3000, "cacheReadTokens": 2000,
      "cacheWriteTokens": 0, "outputTokens": 1500, "steps": 3 }
  ],
  "computedAt": 1755447000000
}

refresh=1 绕过折叠缓存;非 GET 请求返回 405

GET /api/deepseek-quota/context?sessionId=<id>

{
  "ok": true,
  "currency": "CNY",
  "pricingVersion": "deepseek-v4-2026-08-23",
  "currentPeak": false,
  "session": {
    "cost": 0.01145,
    "uncachedInputTokens": 2000,
    "cacheReadTokens": 2000,
    "cacheWriteTokens": 0,
    "outputTokens": 1000,
    "model": "deepseek-chat",
    "provider": "deepseek",
    "tier": "deepseek-chat",
    "steps": 2
  },
  "turn": { "turn": 1, "cost": 0.00375, "uncachedInputTokens": 1000, "cacheReadTokens": 0, "cacheWriteTokens": 0, "outputTokens": 500, "steps": 1 },
  "subagents": {
    "cost": 0.001125,
    "count": 2,
    "children": [
      { "id": "…", "label": "…", "cost": 0.000375, "uncachedInputTokens": 100, "cacheReadTokens": 0, "cacheWriteTokens": 0, "outputTokens": 50, "model": "deepseek-chat", "provider": "deepseek" }
    ]
  },
  "computedAt": 1755446400000
}

// 失败 — code 取值:
//   MISSING_SESSION    缺少 sessionId 查询参数
//   SESSION_NOT_FOUND  会话既不在线也不在持久化存储中
//   INTERNAL           计算过程异常(如子代理枚举超时/持久化读取失败)
{ "ok": false, "code": "MISSING_SESSION", "message": "缺少 sessionId 查询参数" }

说明:

  • session / turn / subagents.* 的金额单位与 currency 一致(默认人民币元)。
  • 金额按当前价目表即时折算;token 桶才是持久化的真实数据,价格调整只会影响 展示金额,不会改变会话日志中的用量。
  • 子代理枚举由 ctx.subagents.listDescendants 提供(持久化优先合并在线会话), 子代理读取失败或超时不会影响主会话数字,仅以 subagents.error 标注。
  • 结果按会话短缓存(contextCacheTtlMs,默认 5 秒),切换会话时额度行秒出; GET /api/deepseek-quota/context?sessionId=<id>&refresh=1 可绕过缓存取最新值。
  • 浏览器端额度行在加载完成前先渲染等高的占位行(),数据到达后原位替换, 因此切换会话不会出现布局跳动;切回已看过的会话会先显示缓存值再刷新。

配置

配置项设置方式默认值
API 地址DEEPSEEK_BASE_URL 环境变量,或行配置 baseURLhttps://api.deepseek.com
缓存 TTL行配置 ttlMs60000
请求超时行配置 timeoutMs15000
额度计算预算行配置 contextTimeoutMs8000
额度路由缓存行配置 contextCacheTtlMs5000
全局消耗折叠缓存行配置 spendCacheTtlMs60000
全局消耗折叠预算行配置 spendTimeoutMs30000
价目表覆盖行配置 pricing官方 DeepSeek-V4 峰谷价目表

行配置写在 profile 的 cordis.patch.yml$DSH_HOME/profiles/web/cordis.patch.yml):

- id: deepseek-quota
  config:
    ttlMs: 30000
    timeoutMs: 10000
    pricing:
      version: my-table-2026-09-01
      tiers:
        deepseek-chat:
          peak:
            cacheHit: 0.12
            cacheMiss: 3.2
            output: 9.5
          offpeak:
            cacheHit: 0.06
            cacheMiss: 1.6
            output: 4.75
      fallbackTier: deepseek-chat

pricing.tiers 按档位名深合并进默认价目表;fallbackTier 决定未知模型按哪档计价。

仓库结构

dsh-deepseek-quota/
├── package.json          # 清单:dsh.bundle.patch + dsh.client (web)
├── cordis.patch.yml      # bundle 层:插入 deepseek-quota 宿主行
├── lib/
│   ├── index.js          # 宿主编:余额路由 + 会话额度路由(持久日志 fold + 峰谷计价)
│   ├── client.js         # 浏览器端:侧边栏余额 + composer 额度行(React.createElement)
│   └── types/            # 手写 .d.ts,描述公开接口
├── test/
│   └── index.test.js     # 宿主编冒烟测试(node:test,零依赖)
├── README.md
├── CHANGELOG.md
└── LICENSE

开发

node test/index.test.js   # 运行宿主编冒烟测试(node:test,零依赖)

客户端 bundle 是纯 JavaScript,由 client-modules 系统原样下发——无需构建步骤。 用本地目录(file: 依赖)加载插件并重启 dsh web 即可生效;浏览器端模块在 刷新页面后热更新。

License

MIT