在 DSH 侧边栏「设置」上方显示 Command Code 套餐额度:5 小时、每周、月度三条窗口的已用百分比与重置倒计时,附 /quota 命令与零依赖命令行工具。API key 从你自己的 provider 路由里读取,无需配置,也不依赖其他插件。
安装
# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)
dsh plugin --profile web add github:Jovan1666/dsh-commandcode-quota
装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本——pnpm 默认拦截,所以安装可能停在 ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED 或 ERR_PNPM_IGNORED_BUILDS;dsh 会打印出需要添加的确切键名,把它加进该 profile 的 pnpm-workspace.yaml 的 allowBuilds 下,重跑一次即可装上。放行构建本身就是一次信任判断:请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。
README
Command Code 额度面板(DeepSeek Harness 插件)
5 小时 / 每周 / 月度三条额度窗口,就在侧边栏「设置」上方。
不用开浏览器、不用登录、不用猜这个月还剩多少。
你会得到什么
| 三条窗口一眼看完 | 5 小时 / 每周 / 月度,短的在上——最紧的那条就在你视线第一落点 |
| 百分比优先 | 主值按整数取整,和 Command Code 官方面板一致,卡片和官网不会对不上 |
| 钱只在要紧的地方 | 月度额度给出已用与剩余金额;每一行的精确数字悬停可见 |
| 先出现,再实时 | 重启后约 2ms 卡片就在屏幕上,约 1 秒后换成实时值 |
| 该消失时消失 | 没配 Command Code 的机器上,卡片完全不渲染;只是不想让它占地方,也可以在设置里把开关关掉 |
| 中英双语 | 卡片跟随 DSH 界面语言 |
| 每个模型能调多少次 | 在「设置」里看这个套餐给每个模型多少次数,你配置的模型排在最前 |
卡片上的一切都来自你自己账号的数据——窗口数量、上限、百分比都是接口读出来的,不做假设。GOAT、Pro、Provider、Max、Teams 都适用;接口没上报滚动窗口的套餐,就不画那几行。($1 的 Go 档是例外——它没有 API 权限,卡片在那里没有东西可画。)
先确认 dsh 版本
本插件要求 dsh 0.1.5-rc.1 或更高——是 >=0.1.5-rc.1,不是 ^0.1.5-rc.1。 那个脱字符是个坑:按 semver,^0.1.5 等于 >=0.1.5 <0.2.0,读起来会把本插件今天正在跑的 0.2.x 整个排除掉。已核对版本:0.2.1-rc.3(当前桌面端 nightly,2026-10-26)。低于 0.1.5-rc.1 的话启动会直接崩:
Error: failed to apply loader entry commandcode-quota:
Cannot read properties of undefined (reading 'register')
因为 ctx.connection.fetch 这个 seam 在旧版本里不存在。查一下再装:
dsh --version # 需要 0.1.5-rc.1 或更高;本次核对用的是 0.2.1-rc.3
npm i -g @deepseek-ai/dsh@latest
桌面端不会把 dsh 放进 PATH,版本看应用自己的「关于 / 设置」面板;nightly 通道当前发布的就是 0.2.1-rc.3。npm 上的包会略微滞后(写这份文档时是 0.2.1-rc.2),所以 npm i -g …@latest 与桌面端安装包显示出不同的末位数字是正常的——两者都满足上面的要求。
注意:插件的离线校验跑得过也不需要这个版本——那些校验不启动 dsh。
所以「校验全绿」不代表装上去能用;这份 README 里的散文数字同理,它们来自上面那个版本,不是你的版本。node scripts/check.mjs 会打印它实际跑了多少项。
安装
dsh plugin --profile web add github:Jovan1666/dsh-commandcode-quota
然后重启 dsh web、刷新浏览器页面。设置就这么多——没有配置文件、不用填 API key:只要 Command Code 已经是你 DSH 设置里的一个 provider,插件自己会找到它。
包里声明了 bundle patch(dsh.bundle.patch → 仓库根的 cordis.patch.yml),所以 dsh plugin add 已经替你注册了插件行。不要再把那行追加到 profile 自己的 cordis.patch.yml 里:两层插入同一个 loader id,dsh 会直接拒绝启动,报 duplicate loader entry id: commandcode-quota。那一行属于下面的手动安装方式——那种装法没有 bundle 层。
本地克隆安装
git clone https://github.com/Jovan1666/dsh-commandcode-quota
dsh plugin --profile web add ./dsh-commandcode-quota
不用 pnpm 的手动安装 —— 把目录链接进 profile 的 node_modules,然后自己注册那一行(没人替你注册):
# $DSH_HOME/profiles/web/cordis.patch.yml
- insert:
- id: commandcode-quota
name: "dsh-commandcode-quota"
新建的 profile,这个文件末尾是一个 []。要把 [] 替换掉——在 [] 后面追加序列不是合法 YAML,profile 会加载失败。
# macOS / Linux ($DSH_HOME 默认是 $HOME/.dsh)
ln -s "$PWD/dsh-commandcode-quota" "${DSH_HOME:-$HOME/.dsh}/profiles/web/node_modules/dsh-commandcode-quota"
# Windows ($env:DSH_HOME 默认是 $env:USERPROFILE\.dsh)
$dsh = if ($env:DSH_HOME) { $env:DSH_HOME } else { "$env:USERPROFILE\.dsh" }
New-Item -ItemType Junction -Path "$dsh\profiles\web\node_modules\dsh-commandcode-quota" -Target "$PWD\dsh-commandcode-quota"
卸载:dsh plugin --profile web remove dsh-commandcode-quota——包和注册它的 bundle 层一起没;手动安装的则删掉 cordis.patch.yml 里那一行。两种都要重启 dsh web。想连缓存快照一起清掉,就删 $DSH_HOME/dsh-commandcode-quota/。
桌面端
Electron 桌面端独占管理它自己的 profile:dsh --profile desktop … 会直接拒绝,报 profile "desktop" is managed exclusively by the Electron application。所以那边用不了 dsh plugin,只能手动挂。有两种挂法,应用自己那份 profile 用的是第一种:
写进 profile(不需要 loader 行):把包加进 $dsh\profiles\desktop\package.json —— link: 依赖 + 名字放进 profile 的 bundle 列表,注册交给包自带的 bundle patch:
{
"dependencies": {
"dsh-commandcode-quota": "link:C:/path/to/dsh-commandcode-quota"
},
"dsh": {
"profile": {
"bundles": [
"@deepseek-ai/dsh-base",
"@deepseek-ai/dsh-web-app",
"dsh-commandcode-quota" // ← 注册就是从这里来的
]
}
}
}
同时保证这个目录能通过 node_modules 解析到——profile 要靠它解析 link::
$dsh = if ($env:DSH_HOME) { $env:DSH_HOME } else { "$env:USERPROFILE\.dsh" }
New-Item -ItemType Directory -Force -Path "$dsh\profiles\desktop\node_modules" | Out-Null
New-Item -ItemType Junction `
-Path "$dsh\profiles\desktop\node_modules\dsh-commandcode-quota" `
-Target "C:\path\to\dsh-commandcode-quota"
重启桌面端。不要同时再加 insert 行——bundle 层已经注册过这个 loader id,再来一条就是上面说的 duplicate loader entry id: commandcode-quota。
手动挂 + loader 行:只在包没有被写进 profile 的 bundles 列表时用。那种情况下没有人替它注册,所以这一行是必须的:
# $dsh\profiles\desktop\cordis.patch.yml
- insert:
- id: commandcode-quota
name: "dsh-commandcode-quota"
重启桌面端。如果插件没出现,先确认这一行只出现一次、上面的 junction 存在——loader 只需要这两样。
往这个文件里加的东西只用 ASCII。应用会自己重写 profile:手动加的
insert条目会保留,但条目上的中文注释会被重写成乱码。
为什么卡片不用等
过去首屏要等完一整趟上游往返,而刚重启的 dsh 没有任何缓存——这就是"要过一会儿才出来"的来源。用 node preview/latency.mjs 对线上接口实测:
| 场景 | 耗时 |
|---|---|
| 重启后首个响应(磁盘有快照) | 约 2ms |
| 重启后首个响应(首次运行、无快照) | 约 1.4s |
| 四个端点依次请求 | 约 2.3s |
| 四个端点同时请求 | 约 1.2s |
差距来自两件事:
- 四个端点同时发。
whoami原来是单独await的——为了拿一个个人账号根本不上报的 org id,白等约 590ms。 - 最近一次成功报告留在磁盘上。 冷启动时立刻返回它(变灰,并标注"上次成功多久前"),后台同时在拉实时值。卡片 3 秒后就再问一次,而不是等常规的一分钟——你看完数字的时候它已经是实时的了。
怎么读这张卡片
| 窗口 | 含义 | GOAT 档的值 |
|---|---|---|
| 5 小时 | 滚动突发限制——一次长会话抽不干整月额度 | $14 |
| 每周 | 滚动 7 天限制 | $35 |
| 月度 | 本计费周期的额度总额 | $70 |
每行显示已用百分比(低于 60% 绿、低于 85% 黄、更高红)、同色进度条、以及重置倒计时。倒计时跟着界面语言,而且只留时长,免得把百分比挤出 200px 的行:中文是 59分 / 3时05分 / 6天9时,英文是 59m / 3h 05m / 6d 9h。「后重置」和具体钟点在悬停里。点击卡片展开:月度额度金额、剩余、请求数、token 用量。把侧边栏收成导轨,卡片变成 36px 圆徽,显示最紧的那条窗口的百分比。
数字口径
- 百分比是
已用 ÷(已用 + 剩余),实时从接口算出;preview/e2e-live.mjs可以随时对真实账号断言这个恒等式。 - 主值按整数取整,和官方取整方式一致。这就是为什么官网显示
100%而精确值是99.84%——同一份数据,两种取整。精确值和金额悬停可见。 - 月度总额是两个端点的数字相加得来的。跨计费周期或换套餐那一瞬,这两个数会分属两个周期,相加的结果看着正常、实际能差几十个百分点。套餐名义额度就是校验标尺;没过校验时宿主不给任何百分比,卡片会说明原因,下一次刷新自动校正。
刻意不做的几件事
侧边栏内容宽度只有约 200px,笔记本屏上小字会更小。所以卡片是把一个问题回答好——我用到什么程度了——而不是把接口返回的东西全摆出来:
- 金额只给月度。 5 小时和每周是"能不能用"的闸门,不是预算;这两行的金额对用户没有可执行的信息。悬停时每行的精确数字仍在。
- 不做配速判断、不做消耗速度预测。 "超速"对一个有活要干的人没有意义;预测耗尽时间则假设消耗匀速,而实际从来不是。数据层仍在 JSON 里提供
projection给脚本用。 - 什么都不静默。 某个端点挂掉导致某行消失时,卡片会说出来;完全取不到数据时,给一行能读懂的说明,完整诊断文本放在悬停里。
每个模型能调多少次(设置面板)
卡片回答的是「我现在用得多深」;设置 → 额度与卡片 回答的是另一个问题:「如果我只用这一个模型,这个套餐大概够我调多少次」——还管着这张卡片到底要不要显示。
换用别的模型、想把左下角让出来? 那个栏目第一个面板里就有开关:在侧边栏显示额度卡片。关掉,卡片(以及折叠侧栏时的徽章)立刻从左下角消失,不用刷新、不用重启,这个选择会跨重启记住;想看了再打开。它不改变账号的任何东西,只是一个显示偏好,存在插件自己的目录里($DSH_HOME/dsh-commandcode-quota/settings.json),不会发到任何地方。
表里列出这个套餐能调用的每个模型,给出 5 小时 / 每周 / 每月的次数,你自己在 DSH 里配置的模型排在最前。表格上方是套餐级概览(GOAT · $70 · ~75K requests)—— 那是另一套口径算出来的另一个数,界面上分开标注,永远不会被当成同一个数字读。
这些数字是官方算的,不是我们编的。每个套餐页公布三样东西:该模型在这个套餐下的月度额度、它的每 token 单价、以及估算所用的典型请求形状;页面自己在浏览器里把次数算出来。插件复刻的就是同一套算式,并按官方的方式取整(Number(x.toPrecision(3)))。tests/catalog.test.mjs 用官方页面自己渲染出来的数字逐行校验——四个套餐页的全部模型行,加上定价页的可用性与套餐级表格——而内置基线里存着这些行赖以计算的输入,所以断网也能把算式重算一遍。(这段原来写着一个行数。它已经过期两次,所以现在不写数字了:跑 node scripts/verify.mjs,看 catalog 套件自己报的数。)
只在必要时才去问。 官方文档页忽略条件请求(服务器给了 ETag,收到 If-None-Match 仍回 200,压根没有 304 分支),所以插件自己做这件事:先发一个 HEAD 取该页 ETag(0 字节),只有真的变了才下载正文(约 200 KB,压缩后约 37 KB)。核对时机是「你打开这个设置栏目、且本地副本已超过一天」,或者你点检查更新;侧边栏卡片永远不会触发核对。插件里随包带了一份基线,所以第一次使用、或者机器离线时,表格照样有数字,并标注「内置基线,尚未同步」。
打开这个栏目永远不会等这次核对。 栏目先用本地数据画出来,核对在回答之后跑,期间写「正在后台核对官方数据…」;数字到位后会自己刷新——栏目自己回来取结果,不需要你再按一次按钮。按每次往返 300 ms 模拟实测:面板出字从 1.6 s 降到 0.32 s,卡片轮询的响应从 22 KB 降到 1.06 KB(目录以前每一条回答都捎带,而卡片根本不读它)。核对本身的 HTTP 也从四次往返降到两次——两个页面的探针一起发;一次什么都没查到的核对只花两次 0 字节探针。核对没带来变化时下一次会隔几秒再试(失败一整天的核对也不会每次挂载都重来),所以一直开着的面板不会变成请求循环。
套餐页没给数字的模型,由定价页自己的计算器补上:同一份额度、同一套单价,请求形状也按站点自己的做法从 provider 推导(这些行标注「推算」)。官方免费送的模型显示 Free。
官方没说的地方一个都不猜:两页都没定价的模型显示 — 而不是 0;官方没有专页的档位如实说明,不去借别的档位数字(Ultra 按 Max 展示并标注是推断);核对失败时保留上次的数字并标出它的年龄。
/quota 命令
在对话里输入 /quota,把同一份报告打印成文本:
Command Code · GOAT (active)
5-hour 1.4% used · resets in 3h17m
Weekly 12.8% used · resets in 6d7h
Monthly 99.8% used · $70.11 / $70.23 · $0.11 left · resets in 7d22h
5,000 requests · 100% success · in 210.0M / out 4.20M
它读的正是卡片那份缓存报告,所以多敲一次命令不会多打上游接口——而且和卡片不同,它从不用磁盘快照作答:敲命令就是要当前数字。它的输出是英文,双语的是卡片。
环境要求
- DeepSeek Harness
>=0.1.5-rc.1—— 已在0.2.1-rc.3上核对。插件依赖若干尚未稳定的框架内部接缝,见兼容性。 - web profile。卡片要通过
connection服务挂进浏览器侧边栏,而这个服务只有 web 应用会装配——headless 或 CLI profile 没有地方放它。 - 一个有 API 权限的 Command Code 账号(除 $1 的 Go 档外都包含),见套餐与订阅。
- Node.js 18+ —— 只有可选的命令行工具和开发脚本需要。
套餐与订阅
只要有 API 权限,卡片哪一档都能读。这个插件是照着 GOAT 做的:$10/月,拿到 $70 额度,另有 5 小时 $14、每周 $35 两道闸。
GOAT 是适合 agent 循环的那一档。Command Code 官方对 DeepSeek V4 Flash 的估算是一个月 约 154,000 次请求(5 小时约 30,800 次、每周约 76,900 次)——因为 flash 档的单价大致是每百万 token 输入 $0.15、输出 $0.60、缓存读取 $0.003。写代码的 agent 花的正是这类调用:单次很小、次数很多,上下文大部分从缓存里读。一个月几万轮工具调用是正常工作量,到这个价位先见底的是窗口闸和月度额度,而不是请求条数。
这两个数字有个前提,官方页面上写着:估算按一次典型 agent 请求约 800 个新输入 token、约 50,000 个缓存读取 token、125–200 个输出 token,所以带大仓库上下文的跑法会消耗得更快;DeepSeek 还按时段计价,高峰时段更贵(UTC 周一至周五 01:00–04:00、06:00–10:00)。官方同时声明额度随时可能调整——定价页才是准的,上面的数字是 2026-09-19 读到的。
订阅步骤
登录 commandcode.ai,打开定价页,或者 Studio → Billing。
选 GOAT 下单。信用卡/借记卡走 Stripe;支持支付宝,限美元计价的套餐,并且会签自动续费代扣——第一张账单之前先知道这件事比较好。银联未列出。
在 Studio 的 API keys 页点 Generate。key 长这样
user_…,不是sk-…。交给 dsh。设置 → 模型 里可以交互式添加;改文件就在
$DSH_HOME/settings.yaml里加一条 provider 路由:llm-pi-ai: providers: command-code-goat: apiKeyEnv: COMMAND_CODE_GOAT_API_KEY api: openai-completions baseURL: https://api.commandcode.ai/provider/v1 models: - id: deepseek/deepseek-v4.1-flash contextWindow: 1000000 input: ["text", "image"]key 本身别写进这个文件:放环境变量,或者放
$DSH_HOME/.credentials.yaml的refs.COMMAND_CODE_GOAT_API_KEY。到这里就没了——凭据解析说的就是卡片怎么找到这条同样的路由,所以装插件从不问你要 key。
订阅前须知
- Go($1)没有 API 权限。 四个额度端点全部返回 404,插件会报「此套餐无 API 权限」,不会当成可重试的错误。
- 5 小时和每周两道闸从你第一次请求开始计时,不按日历切;切换套餐会把这两道闸一起清零。卡片显示的是接口报出来的重置时刻,不拿周期起点去推算。
- 一人一号。 条款禁止共享、转售、多账号轮用 key,违规会牵连涉及的每个账号永久封禁。
- 换档不影响这张卡片。 $20 的 Pro($80 额度)结构相同、余量更大,$100 / $200 的 Max 再往上放大。$15 的 Provider 是计量的纯 API 接入、没有滚动窗口,卡片就只显示余额、不显示窗口行。
凭据解析
API key 只留在宿主端,浏览器拿不到。宿主按下面的顺序解析,并会报告最终命中的来源:
- 显式传入的 key(命令行
--key)。 - 从你自己的
$DSH_HOME/settings.yaml里发现——任何baseURL指向commandcode.ai的 provider 路由。插件读该路由的字面apiKey或其apiKeyEnv,再按名字去环境变量和$DSH_HOME/.credentials.yaml里找。主机名会被保留(指向 staging 或代理都行),但只取 origin:额度端点在主机根路径上,不在 provider 的/provider/v1路径下。 - 环境变量:
COMMANDCODE_API_KEY、COMMAND_CODE_API_KEY、CMD_API_KEY,再兜底任何名字里含commandcode的变量。 $DSH_HOME/.credentials.yaml里的同名引用(refs.<NAME>)。~/.commandcode/auth.json——官方command-codeCLI 的登录态。
第 2 步是"别人也能用"的关键:它跟随你自己的 provider 配置,而不是写死某一种命名习惯。
flowchart LR
A["侧边栏卡片<br/>(浏览器半)"] -->|"POST /api/cc-quota/report<br/>同源 + 会话 Cookie"| B["宿主半<br/>(15 秒缓存 + 磁盘快照)"]
B -->|"四个只读 GET,并行"| C["Command Code API<br/>/alpha/*"]
| 端点 | 用途 |
|---|---|
/alpha/whoami |
账号名、org id |
/alpha/usage/summary |
本周期已用额度、请求数、成功率、token |
/alpha/billing/credits |
剩余额度、5 小时与每周窗口 |
/alpha/billing/subscriptions |
套餐 id、状态、计费周期起止 |
四个端点各自独立降级:单个失败记进报告的 failures,在卡片上以一行浅灰说明呈现,其余照常渲染。四个全失败时只抛一个错误并带上最具体的错误码——包括四个都返回 404 时的"当前套餐不含 API 权限"。
兼容性
插件依赖若干尚未成为稳定公开 API 的框架接缝,每一条都对着 dsh 0.2.1-rc.3 的真实实现——当前桌面端 nightly,2026-10-26 重新核对过;这些接缝最初是对着 0.1.5-rc.1 核对的,中间没有一条改动:
| 接缝 | 用途 |
|---|---|
sidebar.footer.action 插槽 |
「设置」上方那个位置,两种侧边栏宽度下都成立 |
ctx.slots.register({ name, id, order, inject }, Component) |
贡献卡片 |
ctx.connection.rpc.call(channel, endpoint, payload, signal) |
浏览器侧的请求 |
ctx.connection.fetch.register({ path, methods, requestBody, fetch }) |
宿主侧的路由 |
ctx.get('commands') + commands.register({ name, description, handler }) |
可选的 /quota 斜杠命令 |
dsh.client 清单 + exports["./client"] |
客户端 bundle 发现,服务于 /plugins/<id>/client.js |
为什么用精确 Fetch 路由而不是
connection.rpc.handle?rpc.handle挂载通道走的是owner.webServer,而owner是 Connection 服务自己的 context——那里永远没注入webServer。任何其他插件调用它都会抛cannot get property "webServer" without inject,调用方 inject 什么都没用。connection.fetch.register只写内部路由表,任何插件 fiber 都能用,而且天然继承共享/api传输的 Host/Origin 校验与浏览器会话 Cookie。(最初是在 0.1.5-rc.1 上观察到的;0.2.1-rc.3 的dsh-client-connection里仍是同一个owner.webServer.register(route)挂载方式,所以精确路由依旧是唯一可行的做法。)
未来 dsh 版本改动其中任何一条,插件会在加载时明确报错,而不是静默渲染空白。
命令行工具(可选)
同一份数据层也打包成零依赖的只读命令行工具——适合无头机器,或想查第二个账号时:
node cli/cli.mjs # 渲染一次
node cli/cli.mjs --watch 60 # 每 60 秒刷新
node cli/cli.mjs --json # 归一化 JSON,给脚本消费
node cli/cli.mjs --help
Command Code · GOAT(individual-goat) · Jovan1666
key: $DSH_HOME/.credentials.yaml → refs.COMMAND_CODE_GOAT_API_KEY
5 小时 ---------------------------- 1.4%
今天 21:55 重置(2 小时 4 分后)
每周 ####------------------------ 12.8%
09-24 01:51 重置(6 天 6 小时后)
月度额度 ############################ 99.8% · $70.11 / $70.23
剩余 $0.11 · 09-25 17:08 重置(7 天 21 小时后)
本周期 5,000 请求 · 成功率 100% · in 210.0M / out 4.20M tokens
这里展示的是 --ascii 模式的输出,是刻意的:默认进度条用的是满行高的块字符,在很多等宽字体里会和紧挨着的那行文字糊在一起——本 README 之前就是这样,每周的进度条和上面 5 小时的重置时间粘成了一块。# 和 - 是普通字形,到哪儿都正常。另外没有分隔线、也没有右对齐列,每一行都自洽,不依赖字符宽度。
参数:--json / --watch [秒] / --ascii / --color / --no-color / --base <url> / --timeout <ms>(默认 30 秒,可用 COMMANDCODE_QUOTA_TIMEOUT_MS 覆盖)/ --key <key>。
命令行工具与卡片同一套取舍:金额只给月度,不做配速判断和消耗预测(那些数字仍在 --json 里);它的人类可读输出是中文,--json 与语言无关,是给脚本用的接口。
排查
| 现象 | 含义与处理 |
|---|---|
| 完全没有卡片 | 这台机器没配 Command Code provider,插件按设计保持不可见。去「设置 → Models」确认。 |
| 设置栏目显示「内置基线,尚未同步」 | 这台机器还没核对过官方:新装、离线、或还没到核对时机。点一次「检查更新」即可;你现在看到的是随插件发布的副本,旁边标着它的核对时间。 |
| 点「检查更新」秒回、数字没变 | 这正是好情况:0 字节的 HEAD 发现该页 ETag 没变,所以一个正文都没下载。状态行会告诉你上次核对是什么时候。 |
| 卡片显示错误 | 卡片会给你能读懂的一句话("连不上 Command Code"、"API key 被拒绝了"),悬停可看完整诊断文本。 |
| 卡片下方出现「N 项数据这次没取到」 | 四个上游读取里有 N 个这次没算数。每个端点有 30 秒(COMMANDCODE_QUOTA_TIMEOUT_MS 可改,单位毫秒,1s–120s);超时就丢掉这次读数,而不是拿旧数字顶上去。最常见的原因是 Command Code 自己慢——2026-09-30 它的 server-timing 头自报 /alpha/usage/summary 花了 14 秒,而同一次读里 /alpha/billing/credits 只要 43 毫秒。悬停能看到是哪个端点失败,下一次轮询会自动重试。同一张卡片上少一行「月度」,通常是同一个原因换了个端点。 |
/plugins/dsh-commandcode-quota/client.js 返回 404 |
客户端 bundle 没被组合。确认 package.json 里有 dsh.client.platform === "web" 和 exports["./client"]。 桌面端上这个探测没有意义:连内置的 dsh-client-ui-sidebar 也是 404,因为桌面端渲染进程不从那个 HTTP 服务取 bundle。 |
改了 client.js 没生效 |
刷新页面即可——bundle 每请求现读磁盘。改的是 index.js 或 quota.mjs 就必须重启 dsh web(Node 会缓存模块)。 |
| 数字变灰 | 宿主返回的是磁盘快照,或某次刷新失败。下面会标出距上次成功多久,下一次刷新自动恢复。 |
全是 — |
该套餐没上报窗口,或者某次读取还在路上。 |
| 移除 Command Code 后面板变空 | 这是对的——插件不会为已经不存在的 provider 展示旧快照。 |
隐私
- API key 只留在宿主端。浏览器拿不到 key,只通过同源
/api传输收到归一化报告,而该传输另外还限制在 loopback 并要求本进程的浏览器会话 Cookie。 - 只和你的 Command Code 账号 API 通信。没有遥测、没有统计、没有第三方端点。
- 本地唯一写入的文件是最近一次报告的快照:
$DSH_HOME/dsh-commandcode-quota/last-report.json。它存的就是卡片上那些数字——不含 key,另外只存 key 的一小段摘要,用来确认这份快照属于当前配置的账号。随时可以删掉,插件会重建。 - 除这个快照外,每次刷新都是对四个只读端点的实时读取。
开发
# 1. React 只有组件测试和预览页需要
mkdir .devdeps && cd .devdeps && npm init -y && npm install react@18 react-dom@18 && cd ..
# 2. 一次跑完全部 —— 一个结论,不碰网络也不读真实凭据
node scripts/check.mjs # 发布检查:静态检查 + 密钥扫描 + 下面全部套件
node scripts/verify.mjs # 加 --live 会额外打真实账号
node scripts/verify.mjs --quiet # 每个套件只打一行汇总
它每个套件打一行——套件名、检查数、耗时——最后给总数;任何套件失败就以非零退出。这里刻意不复制那份输出:数字会随着"每个新行为配一条新检查"不断增长,抄下来的一段在别人加检查的当下就过期了。
| 脚本 | 作用 |
|---|---|
node scripts/check.mjs |
发布检查:所有 JSON 可解析、所有 .js/.mjs 过 node --check、没有凭据或本机专有路径被提交,然后跑下面全部套件 |
node scripts/verify.mjs |
全部套件 + 单一退出码;--live 追加两个读真实账号的套件 |
node scripts/audit.mjs |
提交前扫描凭据特征与本机专有内容 |
node preview/latency.mjs |
首屏时间拆解:各端点耗时 + 冷启动前后对比 |
node preview/build.mjs |
把真实的 client.js 渲染进仿真侧边栏(浅/深色、折叠/展开;加 --with-snapshot 多一列"重启瞬间")供无头截图,不用重启 dsh |
node preview/e2e-live.mjs |
一次真实读取:打印 /quota 文本并断言 已用 + 剩余 = 总额 |
node preview/e2e-watch.mjs 6 20 |
对真实账号采样 6 次,断言数字在变化中依然自洽 |
确定性是靠重复验证的,不是靠读一遍代码:for i in 1 2 3 4 5; do node scripts/verify.mjs --quiet; done 每次都应打出同样的总数。
已知限制
- 轮询而非推送。 面板 60 秒刷新一次(有窗口接近上限时提速到 15 秒,已用尽则不再提速),宿主另有 15 秒缓存。额度变化最多滞后一分钟。
- 没有按模型分配的明细。 Command Code 把月度额度按模型分配,但
/alpha端点不暴露那张表,卡片只能给总额。 - 不记录历史。 每次都是实时快照,本地除了那一份缓存报告不存任何东西。
- 只覆盖 Command Code。 不替代 dsh 自己的本地 token 统计(在
$DSH_HOME/dsh-usage/)。 - 目录一次只跟一个套餐。 一次核对抓的是「你当前套餐的页面」加上那张共用的定价页(它负责 planId → 模型映射,并给出套餐级概览),不是每个档位的页面。换套餐后,下一次核对会跟上新档位。
- Provider 与 Teams 没有 per-model 表。 这两档只显示套餐级数字(Provider 是按量计费,Teams 只公布一个总数)。Ultra 官方没有专页,按 Max 的数据展示并标注为推断。
- 厂商的延迟就是这次读取的截止线。 健康时四个端点都在 1 秒上下返回;每个端点有 30 秒,超过就把这次读数丢掉(
COMMANDCODE_QUOTA_TIMEOUT_MS可覆盖)。丢掉的读数不会用旧数字补上:卡片会说明丢了几个,悬停能看到是哪个。 - 依赖框架内部接缝。 见兼容性,未来的 dsh 版本需要跟着看一眼。
参与
欢迎提 issue 和 PR。开 PR 前先跑 node scripts/check.mjs——它应该是绿的,而且新行为应该带一条"改之前会失败"的检查。
许可
MIT —— 见 LICENSE。
链接
同类插件
bowenliang123/dsh-context★ 4016
DSH 上下文洞察面板:Context 仪表盘 + /context命令 + Context 浏览器,查看 Context的分类组成、内容详情、演进趋势、压缩/注入事件、统计等一站式 Context 全生命周期管理。
Han-1413141/dsh-cost-meter★ 606
会话与当日 API 费用统计、预算图框(已用%)、官方余额、历史看板,支持峰谷计价与官方价格一键同步。
wssfk12138/dsh-damage-pulse★ 283
在 DSH Web 界面追踪 DeepSeek Token 用量、单次与会话费用及账户余额,并显示缓存感知的扣费动画。
zh667/TokenLedger★ 202
侧边栏用量面板:把 Token 归属到实际服务该请求的中转站,站点从已有的 provider 配置中读出,无需额外配置;含今日/本月/累计三窗口、按站点与模型下钻、一年活跃度热力图,以及 New API / Sub2API / DeepSeek 余额。
Ychris12138/dsh-usage-stats★ 188
多供应商用量看板:按供应商/模型统计 Token 与日期下钻,统一展示账户余额,并追踪 OpenCode Go / Z.ai 订阅额度。
PolinniZhong/dsh-personal-center★ 115
DeepSeek Harness 个人中心:跨会话用量统计(按供应商/模型分别统计,自动读取已配置模型)、按模型成本估算、全局自定义指令、数据驱动的桌面宠物(位图/矢量皮肤)与会话状态概览,纯本地离线运行。
社区评论
评论公开保存在 GitHub Discussions。加载评论会连接 GitHub 和 Giscus;发表内容需要 GitHub 账号。