bowenliang123/dsh-context
bowenliang123/dsh-contextDSH 上下文洞察面板:Context 仪表盘 + /context命令 + Context 浏览器,查看 Context的分类组成、内容详情、演进趋势、压缩/注入事件、统计等一站式 Context 全生命周期管理。
在侧边栏底部显示一张卡片:DeepSeek 账号余额(用 DSH 已保存的 API Key 调官方 /user/balance 接口获取),以及当前模型的档单价——输入、缓存读取、输出——取自内置的官方价格表快照。一个圆点标出当前计费时段,旁边是距离切换的倒计时:高峰为北京时间周一至周五 9:00–12:00、14:00–18:00(不含中国法定节假日),其余为空闲时段。档单价与圆点只对 DeepSeek 官方模型显示,其他模型只显示余额。卡片每 30 秒刷新一次,点击或切换模型时立即刷新,并跟随应用主题与 DSH 语言。
A sidebar plugin for the DeepSeek Harness (DSH) Web UI that answers two questions without leaving the app: how much is left on the active provider's account, and what the model costs right now — the second one for official DeepSeek models, whose prices the built-in table and DeepSeek's peak/off-peak windows cover.
¥ / $), or — for subscription plans that publish no balance — the tightest usage window as a percentage (5-hour 23%). The card follows the model you have selected, so switching provider switches the reading.2d 15h, 5h 47m, 23m).deepseek-official / deepseek-account) *and* its model id is in the built-in table. A third-party route that happens to offer a model called deepseek-flash is priced by its own contract, so the built-in table and DeepSeek's peak/off-peak windows do not apply to it — the card then shows the account reading alone, because any figure derived from them would not match your bill. An official model that is newer than this plugin release is also left unpriced until the table catches up.—) rather than a number it does not have yet.Provider (route id) · Kind · Endpoint · Credential reference DeepSeek (deepseek-official, deepseek-account, deepseek) · Balance · GET https://api.deepseek.com/user/balance (honours DEEPSEEK_BASE_URL) · DEEPSEEK_API_KEY Moonshot / Kimi (moonshotai, moonshotai-cn) · Balance · GET /v1/users/me/balance — USD on api.moonshot.ai, CNY on api.moonshot.cn · MOONSHOT_API_KEY Z.ai / GLM (zai, zai-coding-cn) · Balance · GET /api/biz/account/query-customer-account-report — Bearer on api.z.ai, raw key on open.bigmodel.cn · ZAI_API_KEY OpenRouter (openrouter) · Balance · GET /api/v1/key, falling back to GET /api/v1/credits when the key carries no limit · OPENROUTER_API_KEY Kimi For Coding (kimi-coding) · Subscription usage · GET https://api.kimi.com/coding/v1/usages · KIMI_CODING_API_KEY OpenCode (opencode, opencode-go) · Subscription usage · GET https://opencode.ai/zen/go/v1/usage · OPENCODE_API_KEY MiniMax (minimax, minimax-cn) · Subscription usage · GET /v1/token_plan/remains · MINIMAX_API_KEY / MINIMAX_CN_API_KEY Claude Code (anthropic) · OAuth subscription · GET https://api.anthropic.com/api/oauth/usage · DSH_USAGE_CLAUDE_OAUTH_TOKEN OpenAI Codex (openai-codex) · OAuth subscription · GET https://chatgpt.com/backend-api/wham/usage · DSH_USAGE_CODEX_OAUTH_TOKEN + DSH_USAGE_CODEX_ACCOUNT_ID
The reference each provider reads is the one the Models page writes for that route (_API_KEY), then the adapter's own environment name, so a key you typed on the Models page and one you exported in your shell both work. The status page names the references it looked at, so a missing key tells you which one to set.
These two providers publish their subscription usage only to an OAuth token, which DSH never holds for them — the routes authenticate with an API key. Open the plugin's page in Plugins, paste a token, and the card plus the status table start reporting:
claudeAiOauth.accessToken from ~/.claude/.credentials.json (on macOS: the Claude Code-credentials keychain item). A token minted by claude setup-token also works, but it carries only user:inference, so the plugin reads the 5-hour and 7-day windows from the rate-limit response headers instead of the full usage body.tokens.access_token from ~/.codex/auth.json and put tokens.account_id in the account ID field, which is sent as the ChatGPT-Account-Id header.Tokens are stored through DSH's credential service (~/.dsh/.credentials.yaml) and stay on this machine: no response, log line, or page element ever carries one back. Clear removes them again.
The status page lists these with the reason rather than leaving a silent gap:
GetCodingPlanUsage), and DSH's provider directory carries no Ark route to key on.DSH · Plugin version 0.2.x (0.2.0-rc.1 and later) · 0.11.0 and later 0.1.x (0.1.0-rc.6 and later) · 0.10.x, or 0.11.0 and later
dsh --version prints your DSH version. Installing without a version picks the newest compatible release; name an exact version (@dougen/dsh-deepseek-usage@0.10.2) when the newest does not match your DSH.
DEEPSEEK_API_KEY for DeepSeek, and so on.dsh plugin --profile web add @dougen/dsh-deepseek-usagedsh web and open the URL it prints — the card sits at the bottom of the sidebar, below the Cordis panel button.dsh plugin --profile web remove @dougen/dsh-deepseek-usageThen restart dsh web.
The card then shows the reason instead of numbers:
is_available: false.https://api.deepseek.com/user/balance may be unavailable or answer differently; only DeepSeek's official platform is supported.The card never shows an upstream error message verbatim: transport details stay in the host's log, and the card carries a short, actionable line instead.
PRICE_TABLE in lib/pricing.js, a snapshot of the official pricing page. It changes only when a new version of the plugin ships — there is no local price file and no background sync.deepseek-official / deepseek-account) whose id is in the table (deepseek-flash, deepseek-v4-pro, deepseek-chat, deepseek-reasoner and the legacy names). A third-party route offering a model with the same name is priced by its own contract, so the card hides both instead of showing a figure that would not match your bill.HOLIDAY_RANGES in lib/pricing.js. The State Council usually publishes next year's arrangement in November; update it then, together with HOLIDAY_TABLE_THROUGH_YEAR. Until you do, holidays are treated as ordinary workdays and the card shows peak prices during them; the host logs a warning once a day while the table does not cover the current year.Models reached through a third-party gateway (Workbuddy, a relay, a self-hosted endpoint) are billed by that gateway. A vendor API reports your own account at that vendor, which is a different fact: if your DeepSeek key is configured and the active model runs on Workbuddy, the card shows Workbuddy's status — not your DeepSeek balance, and not what the gateway is charging. The status page repeats this note for the same reason.
lib/index.js, lib/accounts.js, lib/pricing.js) registers GET /api/deepseek-usage, GET /api/deepseek-usage/accounts, and POST /api/deepseek-usage/token. Per request it resolves the active model's provider from agentDefaultModel, resolves that provider's credential reference through DSH's credential service, asks the matching endpoint, and answers with the reading plus the price and peak facts. GET /api/deepseek-usage/holidays hands the browser half the same public-holiday table. Readings are cached for 10 seconds and keyed by provider, endpoint, and credential, so a second tab or a click does not repeat the upstream call.lib/client.js) renders that answer into the sidebar.footer.action slot, re-reads it every 30 seconds, and refreshes on click or on a model change. The peak state and the countdown come from the same answer, so the card itself holds no pricing logic. It also renders the query-status table into plugins.detail.section on the plugin's own page, where the OAuth token cards write through POST /api/deepseek-usage/token.Host header must name a loopback address (or the address the server is bound to), cross-site browser requests and foreign Origin headers are refused, and only the documented methods are accepted. A local process on the same machine can still read the route — that is inherent to a local tool.configured facts and writes tokens through the host; no response carries a key, a token, or an upstream error message.一个 DeepSeek Harness(DSH)网页界面的侧边栏插件:不离开 DSH 就能知道当前模型提供商的账号还剩多少钱;当前用的是 DeepSeek 官方模型时,还能看到它现在什么价——内置价格表与官方峰谷时段覆盖的正是这些模型。
¥ / $);订阅制(没有余额接口)则显示最紧窗口的已用百分比(如 5 小时 23%)。读数跟随当前选中的模型,切换提供商即切换读数。2d 15h、5h 47m、23m)。deepseek-official / deepseek-account)提供、且模型 id 在内置表里,卡片才给价。第三方路由上恰好也叫 deepseek-flash 的模型按它自己的合约计费,内置价格表与官方峰谷时段对它不成立,卡片只显示账户读数——据此算出的数字与实际账单不符。比本插件版本更新的官方模型同样不估价,直到价格表更新:插件不会按模型名猜价格。—,而不是一个它并不拥有的数字。提供商(路由 id) · 类型 · 接口 · 密钥引用 DeepSeek(deepseek-official、deepseek-account、deepseek) · 余额 · GET https://api.deepseek.com/user/balance(遵循 DEEPSEEK_BASE_URL) · DEEPSEEK_API_KEY Moonshot / Kimi(moonshotai、moonshotai-cn) · 余额 · GET /v1/users/me/balance——api.moonshot.ai 为 USD、api.moonshot.cn 为 CNY · MOONSHOT_API_KEY 智谱 Z.ai / GLM(zai、zai-coding-cn) · 余额 · GET /api/biz/account/query-customer-account-report——api.z.ai 用 Bearer、open.bigmodel.cn 用裸 Key · ZAI_API_KEY OpenRouter(openrouter) · 余额 · GET /api/v1/key;该 Key 无限额时回落 GET /api/v1/credits · OPENROUTER_API_KEY Kimi For Coding(kimi-coding) · 订阅用量 · GET https://api.kimi.com/coding/v1/usages · KIMI_CODING_API_KEY OpenCode(opencode、opencode-go) · 订阅用量 · GET https://opencode.ai/zen/go/v1/usage · OPENCODE_API_KEY MiniMax(minimax、minimax-cn) · 订阅用量 · GET /v1/token_plan/remains · MINIMAX_API_KEY / MINIMAX_CN_API_KEY Claude Code(anthropic) · OAuth 订阅 · GET https://api.anthropic.com/api/oauth/usage · DSH_USAGE_CLAUDE_OAUTH_TOKEN OpenAI Codex(openai-codex) · OAuth 订阅 · GET https://chatgpt.com/backend-api/wham/usage · DSH_USAGE_CODEX_OAUTH_TOKEN + DSH_USAGE_CODEX_ACCOUNT_ID
每个提供商读取的引用顺序是:模型页为该路由写入的 _API_KEY,然后是适配器自己声明的环境变量名。所以无论密钥是当初在模型页键入的,还是在 shell / .env 里导出的,都能读到。状态页会列出它查过哪些引用,缺密钥时直接告诉你该配哪一个。
这两家的订阅用量只对 OAuth 令牌开放,而 DSH 里这两条路由走的是 API Key,拿不到订阅令牌。打开 Plugins 里本插件的页面,粘贴令牌后卡片与状态表即可显示:
~/.claude/.credentials.json 的 claudeAiOauth.accessToken 复制(macOS 在钥匙串项 Claude Code-credentials 里)。claude setup-token 产生的令牌也能用,但它只带 user:inference 权限,插件改为从推理响应的限流头读取 5 小时与 7 天两个窗口,拿不到完整用量体里的分模型周限额。~/.codex/auth.json 的 tokens.access_token 复制,并把 tokens.account_id 填进账号 ID 一栏(它会作为 ChatGPT-Account-Id 请求头发送)。令牌经 DSH 的凭据服务保存在本机(~/.dsh/.credentials.yaml),不出这台机器:任何响应、日志、页面元素都不会把它带回来。点清除即可删除。
状态页会列出它们并写明原因,不留空档:
GetCodingPlanUsage)后面,且 DSH 的提供商目录里没有方舟路由可对应。DSH · 插件版本 0.2.x(0.2.0-rc.1 起) · 0.11.0 及以后 0.1.x(0.1.0-rc.6 起) · 0.10.x,或 0.11.0 及以后
dsh --version 查看当前 DSH 版本。不带版本号安装会取最新的兼容版本;最新版与你的 DSH 不匹配时,用 @dougen/dsh-deepseek-usage@0.10.2 这样的完整版本号指定。
安装:
DEEPSEEK_API_KEY,其余同理。dsh plugin --profile web add @dougen/dsh-deepseek-usagedsh web,打开它打印的地址:卡片位于侧边栏底部、Cordis 面板按钮下方。卸载:
dsh plugin --profile web remove @dougen/dsh-deepseek-usage然后重启 dsh web。
卡片空白说明账户读数没拿到,此时卡片会写明原因:
is_available 为 false。https://api.deepseek.com/user/balance 可能不可用或返回异常,本插件只支持 DeepSeek 官方平台。卡片不会原样显示上游的错误消息:传输层细节留在宿主日志里,卡片上只放一句简短、能行动的话。
价格与官方不一致时:
lib/pricing.js 的内置表 PRICE_TABLE(官方价格页的快照),只在发布新版本时更新——没有本地价格文件,也没有后台同步。deepseek-official / deepseek-account)提供、且模型 id 在内置表里(deepseek-flash、deepseek-v4-pro、deepseek-chat、deepseek-reasoner 及旧名),卡片才显示档单价与峰谷指示灯;第三方路由上同名模型按它自己的合约计费,没有官方峰谷定价,卡片把这两项都隐藏,而不是显示一个与实际账单不符的数字。lib/pricing.js 的 HOLIDAY_RANGES。国务院办公厅通常在前一年 11 月发布次年安排,届时更新,同时把 HOLIDAY_TABLE_THROUGH_YEAR 往前推一年;未更新前,节假日会按普通工作日处理,白天显示高峰价,宿主日志会每天提醒一次。经第三方网关(Workbuddy、中转、自建端点)访问的模型由网关计费。厂商接口反映的是你自己在该厂商的账户,这是另一件事:配了 DeepSeek Key 而当前模型跑在 Workbuddy 上时,卡片显示的是 Workbuddy 的状态——既不是你的 DeepSeek 余额,也不是网关在扣多少。查询状态页同样写着这句话,理由相同。
lib/index.js、lib/accounts.js、lib/pricing.js)注册 GET /api/deepseek-usage、GET /api/deepseek-usage/accounts 与 POST /api/deepseek-usage/token。每次请求从 agentDefaultModel 解析当前模型的提供商,经 DSH 凭据服务解析该提供商的密钥引用,请求对应接口,返回账户读数与价格、峰谷事实;GET /api/deepseek-usage/holidays 把同一份法定节假日表交给浏览器侧。读数缓存 10 秒,并按"提供商 + 端点 + 凭据"分桶,多标签页或重复点击不会重复打上游。lib/client.js)把这份响应渲染进 sidebar.footer.action 槽位,每 30 秒重新读一次,点击卡片或模型变化时立即刷新;峰谷状态与倒计时同样来自这次响应,界面自身不做计价逻辑。它还把查询状态表渲染进插件页的 plugins.detail.section,令牌卡通过 POST /api/deepseek-usage/token 写回宿主。Host 必须是回环地址(或服务器绑定的地址),跨站浏览器请求与异源 Origin 一律拒绝,且只接受文档声明的方法。同一台机器上的本地进程仍能读到该路由——这是本地工具的固有边界。MIT