DeepSeek Harness Plugin Hub

发布与管理完整 Harness Profiles,发现适合你的插件。

探索

插件目录环境预设文档中心动态

社区

发布插件联系我们报告问题

相关链接

Plugin Hub GitHubDeepSeek Harness 官方项目系统状态隐私说明
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

独立、非官方社区项目,与 DeepSeek 官方无隶属、授权或背书关系。

Plan Spend — DeepSeek Harness 插件(DSH Plugin)
DeepSeek Harness Plugin Hub
ProfilesPlugins分类动态文档登录管理 Profiles
ProfilesPlugins分类动态文档登录
← Plugins
P

@chi-hong22/dsh-plan-spend

Plan Spend

DSH Web GUI 套餐用量弹窗:显示已配置提供商的套餐用量——DeepSeek 官方余额以及 OpenCode Go 的 5 小时/每周/每月配额——作为一个树外 DeepSeek Harness 插件包

插件会安装到这里;不确定时保持 web。

npx -y @deepseek-ai/dsh plugin --profile web add github:Chi-hong22/dsh-plan-spend#3f2cf0d3533e4444b6f6632cce1b20b44b5bdb50
README兼容性版本

兼容性与来源证明

Plan Spend 以 @chi-hong22/dsh-plan-spend 发布,当前版本为 0.3.0。Plugin Hub 会校验它的 manifest,并保存精确安装来源,便于复现安装结果。

DSH 兼容范围
*
运行环境
web
发布来源
github
Registry 更新时间
2026/10/14

版本

0.3.0stable
2026/10/14
0.2.0stable
2026/10/14
0.1.0stable
2026/10/8

相关插件

正在加载相关插件…

最新版
0.3.0
DSH
*
HMR
重启进程
Tree shaking
未声明可安全裁剪
解包体积
未提供
文件数
未提供
Surface
web
许可证
MIT
发布源
github
GitHub
★ 0
周下载
0
最近提交
2026/10/14
查看源码 ↗
README Badge

点击下方 Badge 复制 Markdown,粘贴到 README 即可。

这是你的 Plugin?认领权益 · 优先安全扫描

验证 package.json 声明的 GitHub 仓库,即可管理这个公开页面。认领后,Hub 会优先安排当前版本的安全扫描,并在通过后公开展示结果。

认领这个 Plugin →
报告问题

相关插件

继续浏览 models-usage 分类下经过校验的插件。

Whale Widgetdsh-whale-widgetDSH Web 界面右下角的 DeepSeek 余额小鲸鱼挂件:余额/今日已用/峰谷定价、自定义泡泡点击序列(文本/余额/今日/峰谷/图片/随机语句与并列加权选择)、逐行样式与字体、悬浮快捷编辑、音效与每轮消耗、自定义角色/动图/音效、吸附与翻转自定义Usage@linxin666/dsh-usage用于 dsh Web GUI 的使用统计插件:检测各提供商的余额和编程套餐配额,并实时记录令牌使用情况;侧边栏 Settings 行上方显示紧凑的价格概览卡片Client Ui Model Capabilities@linxin666/dsh-client-ui-model-capabilities为自定义 pi-ai 提供商声明每个模型的能力(图像输入和推理力度),可直接在 Models 设置卡片中编辑;写入官方 llm-pi-ai 设置命名空间,不更改 DSH 源代码。Cost Meterdsh-cost-meterDeepSeek Harness 会话费用统计插件:本会话成本、当日费用、历史记录与官方价格同步,支持多厂商多模型价格计费(内置 170+ 模型 ID 价格目录与自动匹配)、主流 Coding Plan 订阅额度查询与显示(13 家,含 OpenDesign 工作区查询、含小米 MiMo Token Plan 控制台 Cookie 查询、SCNet Token Plan 本地 Credits 计量与火山方舟 Volcano Ark Coding Plan AK/SK 签名查询)、自定义 Provider

README

@chi-hong22/dsh-plan-spend

A usage popup for the DSH Web GUI: one "Usage" chip in the frame-wide overlay opens a panel showing the plan spend of the configured providers.

What it shows

ProviderSourceRendered
DeepSeek officialthe DeepSeek account sign-in: the host half asks ctx.deepseekAccount.resolveToken for the grant and calls GET https://api.deepseek.com/user/balance with x-dsh-auth-token; falls back to the same endpoint with DEEPSEEK_API_KEYrecharge balance (server precision kept), the topped-up split on the fallback card, the sufficiency flag, which route the number came from, and the peak / off-peak window with its next switch
OpenCode GoGET https://opencode.ai/zen/go/v1/usage5-hour / 7-day / monthly used percentage, progress bar, reset countdown

赠金 (granted credit) is not shown. It is promotional and short-lived, so it is not plan balance: the API-key card does not map granted_balance, and the account card reads the recharge wallet (topped_up_balance) alone.

Known limitation: the OpenCode Go usage endpoint returns percentages and reset instants only — no used/limit amounts. That column is therefore percent-only; the exact dollar figures live in the OpenCode console.

Peak and off-peak (DeepSeek official)

DeepSeek bills two rates, and off-peak is half the peak price, so the DeepSeek card carries one more row: whether the current moment is peak or off-peak, and how long until the next switch.

There is no endpoint that reports the current window — the rule lives in a footnote on the pricing page — so this row derives it client-side from the published rule:

  • Peak: Monday–Friday 09:00–12:00 and 14:00–18:00 Beijing time (UTC 01:00–04:00 and 06:00–10:00), excluding Chinese public holidays.
  • Everything else is off-peak: 12:00–14:00, the night, all weekend, and public holidays in full.

How the derivation is pinned down:

  • Weekends are always off-peak, so a make-up workday that lands on a Saturday or Sunday needs no extra modelling — the weekend rule already calls it off-peak.
  • The holiday set is therefore the whole published State Council arrangement (including workdays folded into a holiday, such as 2 January for New Year), not just the 11 statutory days; otherwise peak would reappear mid-holiday.
  • Lookups use UTC date keys: every peak window lies inside UTC 00:00–16:00 and everything outside a window is off-peak, so a UTC-date lookup and a Beijing-date lookup agree.
  • The windows are half-open: 04:00:00 sharp is already off-peak.

The holiday table needs upkeep

The table is UM_CHINA_PUBLIC_HOLIDAYS_UTC in client.body.js (33 days for 2026, from State Council notice 国办发明电〔2025〕7 号); the years it covers are listed in UM_HOLIDAY_YEARS. Each fourth quarter, once the State Council publishes the next year's arrangement, append that year's date keys and the year itself.

When the table does not cover the current year the card says so outright — the holiday table does not cover that year, add the data — because in that state every weekday statutory holiday would be scored as peak, and a wrong number stated silently is worse than a missing one declared. A covered year shows no notice at all.

Install

dsh plugin --profile <profile> add github:Chi-hong22/dsh-plan-spend

The desktop profile is owned by the Electron application: the CLI refuses it with profile "desktop" is managed exclusively by the Electron application. Install through the GUI plugin page instead.

Verify the mount:

dsh --profile <profile> --dump-config | grep usage-meter

Configuration

The plugin has no config. It decides which providers to show from whether their credential is configured; the reference names live in the ADAPTERS table in index.js:

ProviderCredential ref (POSIX environment name)
DeepSeek officialDEEPSEEK_API_KEY
OpenCode GoOPENCODEGO_API_KEY

Credentials resolve through ctx.credentials.resolve(); the source precedence is documented by @deepseek-ai/dsh-credentials-local (launch environment → stored file → project .env → harness home .env). An unconfigured provider issues no request and renders as "no credential configured; skipped".

The API-key row is the fallback. The DeepSeek card is normally read in this half from the signed-in DeepSeek account: ctx.deepseekAccount.resolveToken hands out the stored grant for the configured inference origin (https://api.deepseek.com), and that token goes to the same /user/balance endpoint as x-dsh-auth-token. No API key is needed, and the grant never reaches the browser. When the account cannot answer (signed out, no account provider in this composition, or the query failed) the API-key card stands in and names its own route; a failed account query is reported on that fallback card, so "signed out" and "the query broke" stay distinguishable.

The account service's own balance query is deliberately not used: it goes to platform.deepseek.com, whose WAF answers non-browser clients with HTTP 429, so it reports a failed balance instead of a number.

A failed or missing API-key read also reports the effective credential's source layer and whether this surface could write it (ctx.credentials.describe), because "I saved a key and it still unauthorised" is almost always a read-only launch-environment value winning over the stored one.

Adding a provider = one row in ADAPTERS plus one reader function.

Placement and sizing

The plugin registers two seats:

  • sidebar.footer.action (id usage-meter): the trigger. That seat is the sidebar's own action row and hands each entry { wide }, so the button follows the collapse/expand rail by itself (icon-only when wide === false).
  • shell.overlay (id usage-meter): the panel. The frame-wide layer sits outside every column, so the panel renders beside the sidebar instead of being clipped by the sidebar's overflow: hidden.

Placement: the panel measures the frame-level column that holds the button (by climbing the DOM to the frame's direct child, never by hashed class name), anchors its left edge 10px past that column's right edge and its bottom at the button's bottom, then grows upward. A sidebar width change re-measures.

One deviation worth knowing: sidebar.settings (the account row) is a single seat already owned by the shipped account/settings UI, so taking it would shadow that UI (replaceRisk: shadows-shipped-ui). .footArea is a column with footerActions above settingsArea, so the button lands in the row above the account row rather than at its right in the same row.

Button styling mirrors the shipped account launcher — padding: 6px, border-radius: 12px, gap: 8px, font-size: 14px/22px, row margin 4px -2px, hover --dsw-alias-interactive-bg-hover; the glyph is 32×32, the avatar's own box; in the rail it becomes a centred 40×40 icon.

Alignment with the account row is measured, not assumed: on mount the row takes the sibling account row, finds its first button, then that button's first sized child (the avatar) and the next sized sibling (its label), and converts both left edges into this row's padding-left and the label's margin-left. Whatever inset that row actually uses, this one follows; with no account row the stylesheet defaults stand. The rail opts out and keeps its own centred box.

Dismissal: the trigger again, the panel's ×, Esc, or a press anywhere outside the panel all close it.

Resizing: the grip sits in the panel's top-right corner — the one farthest from the button — dragging right grows the width and dragging up grows the height. The size is stored under usage-meter.size and is bounded by the panel minimum and the overlay bounds.

To return to the default size, clear usage-meter.size. After editing the source run npm run build to regenerate client.js; that file is a build artifact — do not edit it directly.

The browser picks up a new client.js only after a page refresh: replacing package code is not part of DSH's ordinary start/stop sync.

The client half must export inject

The plugin object returned by client.body.js carries inject: ['slots', 'locale'] so Cordis withholds apply until both services are provided. Without it ctx.get('locale') can read undefined and t silently degrades to echoing the key — the UI then shows button.label, panel.title, window.rolling while the data and layout stay perfectly correct, which reads like an unrelated bug. Every shipped client half (dsh-client-ui-sidebar, dsh-client-ui-cordis) exports inject; do the same.

The host half likewise reads the account service through ctx.get instead of declaring it in inject: a composition that mounts no account provider must still mount the meter, with the API-key card in charge.

Security boundary

  • API keys are used in the host half only and never reach the browser; the browser reads same-origin JSON.
  • GET /usage-meter/snapshot is a named route on the harness web server with no additional authentication. When the web server binds 0.0.0.0, anyone on the same network can read the balance and quota numbers (never the keys). Loopback-only use is unaffected.

Layout

index.js             host half: credential resolution + both upstream calls + 30s cache + route
client.body.js       client half source (bare function body, no imports/JSX)
client.js            build artifact, generated by scripts/build-client.mjs
cordis.patch.yml     bundle patch: inserts one row into a profile
scripts/build-client.mjs
scripts/probe-sources.ps1   one-shot probe: verify both upstreams without the plugin
tests/client-ui.test.mjs    trigger/placement/resize + account-route card tests (npm test)
tests/host-snapshot.test.mjs  host route payload tests (npm test)

License

MIT