DSH Plugins Marketplace

DSH Plugins

Plugins

/

Tools & Capabilities

/

dsh-provider-usage

d

dsh-provider-usage

Identified

One collapsible sidebar widget stacking OpenCode GO, Command Code and GLM Code Plan quota windows, with reset countdowns, top-up balances, a settings page and a /provider-usage command.

dsh-multi-provider-usage

A DSH plugin that shows the quotas of OpenCode GO, Command Code and GLM Code Plan in one sidebar widget. It is modelled on @astervolans/dsh-opencode-go-usage — same dual-half package, same-origin proxy, same sidebar slot, same Plugins panel settings page — extended from one provider to three.

The package name is dsh-multi-provider-usage because the unscoped dsh-provider-usage name is already taken on npm by a different plugin. The HTTP routes (/provider-usage/*) and chat command (/provider-usage) stay short and stable.

Sidebar widget with the three stacked providers

Features

  • Three providers, one column. All enabled providers are stacked vertically; each header carries a health dot, the provider's primary percentage and its top-up balance. Click a provider header to collapse/expand that provider's plan windows, quota bars and time bars; the collapse state is remembered locally, so any subset can stay folded.
  • OpenCode GO — 5-hour, weekly and monthly windows (the API calls the 5-hour field rolling). Prefers the live dsh-opencode-go plugin's active account through its opencodeGoUsage host service, then falls back to the official GET /v1/usage endpoint.
  • Command Code — monthly credit pool, 5-hour window and weekly window from the official billing/usage endpoints (/alpha/billing/*, /alpha/usage/summary).
  • GLM Code Plan, international and China — 5-hour token window, weekly token window and monthly MCP tool limit, read from the international Z.ai host (api.z.ai) or the China BigModel host (open.bigmodel.cn) at /api/monitor/usage/quota/limit. auto probes both, the GLM card badges the version that answered (International / China), and the plugin settings can pin one version (or a custom endpoint). When neither version answers, the failure names each version's result instead of only the last probe.
  • Top-up balances — OpenCode GO shows the OpenCode Zen prepaid balance and Command Code shows its purchased + free "Extra Credits" balance, both as a badge next to the account/plan and in the /provider-usage text. The OpenCode console token is auto-discovered from OPENCODE_CONSOLE_TOKEN, the OpenCode CLI auth file, or its local opencode.db; the token never leaves the host. When that token is missing, the balance slot becomes a clickable "Set up" chip that opens the plugin settings, where the OpenCode GO card renders a step-by-step setup guide, instead of silently showing nothing. Command Code's tooltip breaks its amount into purchased + free credits; a credits response without either pool renders a muted No top-up badge.
  • Auto-update — on boot and every configured interval the host checks the npm registry, the npmmirror mirror and the GitHub release feed together and trusts the newest version any of them reports. A local link:/file: checkout is fast-forwarded when it is on main, clean, and a strict fast-forward. An npm / market / tarball copy updates itself: the release tarball is downloaded from the first source that serves it (registry → mirror → GitHub, in turn) and each packaged file (lib/, package.json, cordis.patch.yml, docs/) is written to a temp file and renamed over the target, so pnpm's hardlinked store is never edited in place. Either way the running Host keeps the old module graph, so the widget/settings show "updated — restart DSH". The plugin never restarts DSH by itself.
  • Balance-change animation — the widget polls on its normal interval; when a provider's balance differs from the previous poll, the number counts from the old value to the refreshed one while a red/green delta chip (for example -0.1) floats up and fades away. There is no popup and no turn-event tracking, so the animation may appear up to one poll interval later.
  • Low-balance tone — a balance at or below 5 renders amber and at or below 1 renders red (thresholds are in the currency unit and apply to USD and CNY plans alike), in both the sidebar and the settings page's live-usage sections.
  • Click-to-retry failures — an error line in the widget is itself clickable (and keyboard-activatable) and forces one fresh upstream read.
  • Same-origin proxy — the browser only talks to /provider-usage/usage and /provider-usage/settings; API keys stay in the host process.
  • Failure isolation — one broken provider never hides the other two. The route answers 200 while any provider succeeds and 502 only when all enabled providers fail. Partial endpoint failures keep the provider's numbers but turn its health dot amber and name the failed calls in the tooltip.
  • Settings shortcut — the widget header's Settings button opens this bundle's page in the sidebar Plugins panel, directly on the configuration page below.
  • Bundle settings page — sidebar Plugins panel → this bundle's card: enable/disable each provider, edit credential refs and endpoints, choose the GLM region, and see non-network detection status. Save applies immediately. Each provider card embeds a live usage section — quota windows with percentages, time-to-reset and the top-up balance, from the same canonical snapshot the widget renders. While the page is open it follows the widget: a 30-second poll (when the tab is visible) plus an "Updated HH:MM" stamp, a Refresh usage control forces a re-read, and every save re-reads with refresh=1, so a changed credential ref shows its own numbers immediately. The GLM card also carries the referral link (Z.ai "Invite Friends, Get Credits") as a clickable, copyable row. The URL is a bundle constant: it never goes through the settings route and a settings save cannot overwrite it.
  • /provider-usage chat command — prints every enabled provider's numbers as text.
  • Time bars — under each quota bar, gray is time already elapsed and blue is time remaining, matching the reference widget's geometry. Each window also counts down to its reset on the right; an exhausted window keeps that countdown and gains a small exceeded/rate-limited chip right after the percentage, whose hover title also carries the absolute reset time.
  • x-opencode-session fix — injects the real per-conversation harness session id into OpenCode GO chat requests at runtime, without patching DSH.
  • Chinese and English UI through the DSH locale service.

Install

From npm:

dsh plugin --profile desktop add dsh-multi-provider-usage

or, for the web profile:

dsh plugin --profile web add dsh-multi-provider-usage

From a checkout (for development):

dsh plugin --profile desktop add /path/to/dsh-provider-usage

The package declares dsh.bundle.patch, so the CLI reconciles it into the profile's bundle layer stack automatically. The widget and client bundle are part of the profile's client-modules graph, so restart DSH once after installing (a running host does not rebuild its window.__DSH_BOOT__ manifest for a newly linked package).

For a local link: dependency pnpm prints a peer-dependency warning (@deepseek-ai/schemastery, @deepseek-ai/dsh). That is expected: the linked checkout resolves schemastery from its own node_modules in development; a normal npm install resolves the peers from the DSH runtime.

Credentials

All values are resolved through the DSH credentials domain (the process environment, $DSH_HOME/.credentials.yaml and .env layers). They are never returned by the settings route and never reach the browser.

ProviderDefault refResolution orderFallback source
OpenCode GOOPENCODE_GO_API_KEYopencodeGoApiKeyEnv, the dsh-opencode-go active-account ref (only when that entry is enabled), OPENCODE_GO_API_KEY, OPENCODE_API_KEYGET {baseUrl}/v1/usage
Command CodeCOMMANDCODE_API_KEYcommandCodeApiKeyEnv, COMMANDCODE_API_KEY, then the CLI auth file~/.commandcode/auth.json (apiKey)
GLM Code PlanZAI_API_KEYglmApiKeyEnv, ZAI_CODING_CN_API_KEY, ZAI_API_KEY, ZHIPU_API_KEY, GLM_API_KEY, BIGMODEL_API_KEY—

Set a ref in Plugins → dsh-multi-provider-usage → settings (or in the auto-generated Settings → Plugins → Plugin configuration form). A ref is a name such as OPENCODE_GO_API_KEY; the secret itself lives in DSH's credential store.

OpenCode console balance

The GO quota API does not include the account's prepaid balance. That comes from GET https://opencode.ai/console/api/billing/status, which needs the OpenCode console OAuth token (the GO API key returns 403 there). The host resolves it in this order:

  1. opencodeConsoleApiKeyEnv (OPENCODE_CONSOLE_TOKEN by default), resolved through DSH credentials;
  2. the credential table of ~/.local/share/opencode/opencode.db (read via node:sqlite when available; this is where current OpenCode releases keep the OAuth grant and rotate it);
  3. ~/.local/share/opencode/auth.json ($XDG_DATA_HOME/opencode/auth.json when set), provider opencode — the legacy location kept by older releases.

The database is preferred deliberately: OpenCode migrated its grant there but often leaves the old auth.json behind, and that stale token returns 401. Every usable OAuth candidate is tried in turn (at most four), so one expired store cannot hide the live one. Channel builds (opencode-beta.db, opencode-dev.db, …) and $OPENCODE_DB are discovered too. The billing host comes from the grant's metadata.server (so a self-hosted console works), falling back to the public origin; opencodeConsoleBaseUrl overrides it.

An OpenCode API-key login (oc_sk_…, the service-account method) carries no console session and is never sent to the billing endpoint. Such a login, a missing token, or an expired/revoked grant renders a clickable Set up chip (instead of a mute dash) that opens this bundle's page in the Plugins panel and names the fix: run opencode auth login and choose the OpenCode Console account, or store a console token as OPENCODE_CONSOLE_TOKEN.

When the balance is not configured (or the console login is fixable), the OpenCode GO card in the plugin settings renders a step-by-step setup guide in place of the static hint. The lead-in names the state-specific fix (nothing configured, an API-key login, or an expired sign-in). Step ① shows the opencode auth login CLI command with a Copy command button; step ② offers a Re-check button that re-reads the sign-in state and forces one upstream usage read, so a fresh login shows the balance without restarting DSH (unsaved form edits are never discarded by the re-check). The /provider-usage command gives the same state-specific guidance as text for all three fixable states.

The optional opencodeConsoleAuthFile overrides the auth file (and its directory is used to locate opencode.db), opencodeConsoleOrgId supplies the x-org-id header, and opencodeConsoleEnabled: false turns the whole balance read off. Balance failures never hide the GO quota: the provider stays ok with balance: null and a meta.balanceError (plus meta.balanceSetup when the user can fix it). Any other balance failure renders a muted Balance — badge whose tooltip carries the error.

Command Code balance

Command Code's quota and balance share one API key and one billing family, so they cannot diverge the way OpenCode's do: a missing key (COMMANDCODE_API_KEY or ~/.commandcode/auth.json) fails the whole provider with an explicit no API key message rather than blanking only the balance. Two narrower gaps are reported instead of hidden:

  • when /alpha/billing/credits fails, that request carries every window, so the provider errors as well; its message now includes the underlying interface and status instead of only "no usable quota windows", and meta.balanceError lets the header show a muted Balance — badge carrying the cause;
  • when the credits response succeeds but carries neither purchasedCredits nor freeCredits, balance stays null with meta.balanceMissing: true and the header shows a muted No top-up badge (a real 0 still renders $0.00).

OpenCode GO integration and fallback

When opencodeGoSource is opencode-go (the default), the host probes:

  1. a live loader entry named opencode-go / dsh-opencode-go;
  2. that entry is not disabled;
  3. ctx.get("opencodeGoUsage") exposes read();
  4. read() returns valid rolling / weekly / monthly data;
  5. the active account is read from that entry's apiKeyEnv + accounts[].

If any step fails, the host reads the built-in endpoint and reports a fallback object with one of: not-installed, entry-disabled, service-unavailable, read-failed, invalid-response. The widget shows a Built-in badge with the reason and message in its tooltip. opencodeGoSource: "builtin" pins the HTTP path and never touches the other plugin.

Plan windows

ProviderWindowsWindow length
OpenCode GOrolling, weekly, monthly5 h, 7 d, ~30 d
Command Codefive-hour, weekly, monthly5 h, 7 d, real billing period
GLM Code Planfive-hour, weekly, mcp5 h, 7 d, monthly

Percentages are used percentages and are clamped to [0, 100] for display. Command Code monthly utilization is totalCost / (totalCost + monthlyCredits); purchased and free credits are reported separately in meta.monthly and do not change the plan bar, while their sum is the visible top-up balance (balance.extra). The 5-hour/weekly bars use windowLimits.fiveHour / weekly (used, cap, resetAt, exceeded).

A GLM account without a Coding Plan answers HTTP 200 with { "success": false, "msg": ... }; the adapter surfaces that message and the widget shows the provider in an error state.

Configuration

The loader reads the exported Config schema; every field is .volatile(), so the settings page and the auto-generated form hot-apply.

FieldDefaultMeaning
opencodeGoEnabledtrueShow OpenCode GO
opencodeGoSource"opencode-go"opencode-go or builtin
opencodeGoApiKeyEnv"OPENCODE_GO_API_KEY"Credential ref
opencodeGoBaseUrl"https://opencode.ai/zen/go"Gateway base
opencodeConsoleEnabledtrueRead the Zen prepaid balance
opencodeConsoleApiKeyEnv"OPENCODE_CONSOLE_TOKEN"Console token ref
opencodeConsoleOrgId""Optional x-org-id
opencodeConsoleAuthFile""Optional auth.json path; empty auto-discovers
opencodeConsoleDbFile""Optional opencode.db path; empty derives it
opencodeConsoleBaseUrl"https://opencode.ai"Console origin
commandCodeEnabledtrueShow Command Code
commandCodeApiKeyEnv"COMMANDCODE_API_KEY"Credential ref
commandCodeBaseUrl"https://api.commandcode.ai"API base
commandCodeAuthFile""Empty = ~/.commandcode/auth.json
glmEnabledtrueShow GLM Code Plan
glmApiKeyEnv"ZAI_API_KEY"Credential ref
glmBaseUrl""Optional base override
glmRegion"auto"auto, zai, bigmodel, custom
cacheMs30000Per-provider host cache TTL
updateChecktruenpm update check (24 h)
autoUpdatetrueCheck npm, npmmirror and GitHub together; fast-forward a clean checkout, otherwise replace an installed package from the first source that serves the tarball
autoUpdateCheckHours6Hours between auto-update checks (1–168)
injectSessionHeadertrueOpenCode GO session-header fix
providerOrderall three idsProvider display order in the widget; drag the cards in the plugin settings to reorder

glmRegion: "custom" requires glmBaseUrl; auto probes https://api.z.ai first and then https://open.bigmodel.cn, and the widget badges the version that answered.

HTTP API

GET /provider-usage/usage

?refresh=1 (or ?force=1) bypasses the host cache.

{
  "ok": true,
  "enabled": ["opencode-go", "command-code", "glm"],
  "providerOrder": ["opencode-go", "command-code", "glm"],
  "providers": [
    {
      "id": "opencode-go",
      "name": "OpenCode GO",
      "short": "GO",
      "status": "ok",
      "account": { "ref": "OPENCODE_GO_API_KEY", "id": null, "name": "" },
      "plan": null,
      "source": "builtin",
      "requested": "opencode-go",
      "fallback": {
        "from": "opencode-go",
        "reason": "not-installed",
        "message": "dsh-opencode-go is not installed, or its profile entry is inactive"
      },
      "balance": {
        "amount": 5.01495352,
        "currency": "USD",
        "labelKey": "balance.zen",
        "source": "opencode-db",
        "details": { "billingMode": "prepaid", "mode": "pay-as-you-go" }
      },
      "windows": [
        {
          "key": "rolling",
          "labelKey": "window.five-hour",
          "hintKey": "window.five-hour.hint",
          "percent": 0,
          "status": "ok",
          "resetsAt": "2026-11-05T13:50:46.363Z",
          "windowMs": 18000000
        }
      ],
      "meta": {}
    }
  ],
  "update": { "current": "0.1.0", "available": false, "latest": null },
  "sessionHeader": { "active": true, "count": 0, "diag": {} }
}

Failed providers have "status": "error", code, error and windows: []; their siblings are still returned. A body with providers: [] means no provider is enabled. meta.balanceError carries a tolerated balance failure (the provider still answers ok); meta.balanceSetup (no-credential, api-key or expired) marks a failure the user can fix by signing in again; meta.balanceMissing marks a Command Code credits response without purchased/free pools. meta.errors lists partial Command Code endpoint failures: the numbers stay, the health dot turns amber, and the tooltip names the failed calls. Error cards keep the plan they already resolved.

GET /provider-usage/settings

Returns the settings descriptor (namespace, revision, value, base, user) plus a non-network detection report:

{
  "ok": true,
  "namespace": "dsh-multi-provider-usage",
  "revision": 0,
  "value": { "opencodeGoEnabled": true },
  "detection": {
    "providerOrder": ["opencode-go", "command-code", "glm"],
    "enabled": ["opencode-go", "command-code", "glm"],
    "providers": {
      "opencode-go": { "configured": true, "entryFound": false, "fallback": { "...": "..." } },
      "command-code": { "configured": true, "source": "auth-file" },
      "glm": { "configured": true, "region": "auto" }
    }
  }
}

503 means the host has no settings service or the entry has no volatile fields; the settings page explains how to fix it.

POST /provider-usage/settings

Only the fields in the table above are accepted; anything else is ignored. expectedRevision gets 409 on a concurrent change.

{
  "patch": { "commandCodeEnabled": false, "providerOrder": ["glm", "opencode-go", "command-code"] },
  "expectedRevision": 0
}

Cross-origin writes are refused with 403. The usage route is read-only.

How it is put together

HalfFileRole
host (Node)lib/index.jsConfig schema, routes, command, settings/detection, cache, session fix
host adapterslib/providers.jsCanonical window shape and the three vendor adapters
console balancelib/opencode-console.jsOpenCode console token discovery + billing status
session fixlib/opencode-session.jsglobalThis.fetch wrapper + llm/stream ALS context
browserlib/client.jsHand-authored window.__ModuleLoader__.load({ id, factory }) bundle: widget, settings page, locale dictionaries
bundle patchcordis.patch.ymlInserts the profile entry

The browser bundle is composed by DSH's official client-modules scan from dsh.client + exports["./client"]; it registers into sidebar.footer.action and plugins.bundle.config, exactly like the reference plugin.

The session fix wraps globalThis.fetch once and only adds x-opencode-session when the request URL starts with the gateway base carried by the current llm/stream call. The base comes from llm-pi-ai.providers.<route>.baseURL, falling back to opencodeGoBaseUrl.

Compatibility

  • DSH 0.1.7 and above, including the 0.2.0 line; verified on 0.2.1-rc.5.
  • @deepseek-ai/schemastery ^3.18.4 (volatile fields / settings page).
  • Node.js ≥ 18 (global fetch, AbortSignal.timeout).
  • dsh-opencode-go is optional; its absence is a normal fallback.
  • Command Code's CLI auth file is optional if COMMANDCODE_API_KEY is set.
  • A DSH runtime that does not expose plugins.bundle.config loses only the settings page; the sidebar widget and /provider-usage keep working. Set the config fields in the profile patch or the auto-generated form instead.

Development

npm install
npm test

The tests are hermetic: a fake globalThis.fetch and a stub Cordis context, no network and no real keys. They cover the schema, all three adapters, OpenCode GO service integration/fallback, aggregation and error isolation, caching and forced refresh, settings conflicts/whitelisting, the client bundle contract, top-up balance discovery (credential and local auth.json) and failure isolation, and the session-header injection. 110 tests, all offline.

License

MIT.

Comments

Loading…

Similar plugins

@astervolans/dsh-opencode-go-usage

DSH (DeepSeek Harness) plugin: OpenCode GO plan quota widget in the sidebar, same-origin usage proxy, and a /opencode-go chat command

Tools & CapabilitiesTerminal & ClientsManifest valid

★ 0

dsh plugin --profile web add @astervolans/dsh-opencode-go-usage

Shows OpenCode GO plan quota (rolling 5-hour, weekly, monthly) on a DSH Settings page, reading the official usage API through a same-origin proxy; registers no sidebar widget. A rework of Astervolans/

Tools & CapabilitiesManifest valid

★ 0

dsh plugin --profile web add dsh-opencode-go-quota-settings

Bottom-right 余额 badge for the DSH Web UI: on expand it fetches the currently-selected provider's OpenCode Go plan limits or DeepSeek prepaid balance, plus local token usage and pricing-based spend est

Tools & CapabilitiesModels & ProvidersManifest valid

★ 0

dsh plugin --profile web add dsh-opencode-go-quota

by Jovan1666

Command Code plan quota in your DeepSeek Harness (dsh) sidebar: 5-hour, weekly and monthly credit windows with reset countdowns. Works with Go, GOAT, Pro, Max and Provider plans.

Tools & CapabilitiesDevelopment & InfrastructureTerminal & ClientsManifest valid

★ 1

↓ 353/wk

MIT

JavaScript

Oct 26, 2026

dsh plugin --profile web add dsh-commandcode-quota

Inline Command Code plan usage badge in the DSH composer toolbar beside the model selector: 5h and weekly window usage plus remaining credits, clicking the badge opens an upward detail popover with re

Tools & CapabilitiesTerminal & ClientsModels & ProvidersManifest valid

★ 0

dsh plugin --profile web add dsh-commandcode-usage-inline

by Dogtiti

Provider usage panel for DeepSeek Harness: shows the remaining share of each quota window (GLM Coding Plan today) as a chip beside the model selector, with a detail popover.

Manifest valid

★ 0

JavaScript

Oct 26, 2026

dsh plugin --profile web add dsh-plugin-usage-panel