Skip to content
dsh.fish
Bundle

dsh-provider-billing

DeepSeek Harness plugin: provider account balance inside each Models settings row, queried through a loopback-pinned RPC channel with the stored API key kept on the host

Source
ZeroingIn
stars
2 stars
License
MIT
Updated
Updated 10 days ago

Readme

# dsh-provider-billing

English | [中文](README.zh.md)

[![npm version](https://img.shields.io/npm/v/dsh-provider-billing?logo=npm)](https://www.npmjs.com/package/dsh-provider-billing)

A DeepSeek Harness plugin (maintained outside the official repository) that shows the account balance behind each configured provider route's stored API key — one balance line inside each provider row of the **Models** settings page, with a refresh control per route. The key never leaves the host: the browser sends only the route id, and the host resolves the endpoint and credential from the configuration plane before asking the provider's OpenAI-compatible `/user/balance` endpoint.

**Host requirement**: the plugin renders inside the Models page's `settings.models.row` contribution hole, which only newer harness builds declare. Older harness builds are **not supported**: the plugin reports a clear load failure instead of degrading silently. Do not install it on an unsupported harness.

## Install

Any of the three equivalent routes:

### 1. npm

```sh
dsh plugin --profile web add dsh-provider-billing
```

Published on npm as [`dsh-provider-billing`](https://www.npmjs.com/package/dsh-provider-billing) — the simplest route: the tarball ships the built `lib/` and `cordis.patch.yml`, so no build step runs on install.

### 2. GitHub

```sh
dsh plugin --profile web add github:ZeroingIn/dsh-provider-billing
```

A GitHub install fetches **sources**: pnpm runs the package's `prepare` script (`tsdown`, fully self-contained — no sibling checkout, no npm resolution of `@deepseek-ai/*`) during install. pnpm ≥ 10 refuses to run a git dependency's build script until it is allowlisted — copy the exact package key pnpm prints into the profile's `pnpm-workspace.yaml`:

```yaml
allowBuilds:
  dsh-provider-billing: true
```

Allowlisting means *permission to execute this package's code on your machine at install time*. For a locked build, append a commit sha: `github:ZeroingIn/dsh-provider-billing#<sha>`.

### 3. tarball

```sh
pnpm pack        # produces dsh-provider-billing-0.1.1.tgz
dsh plugin --profile web add ./dsh-provider-billing-0.1.1.tgz
```

### Local development

```sh
dsh plugin --profile web add link:/absolute/path/to/dsh-provider-billing
```

`link:` points the profile at this directory: edit → `pnpm build` → restart `dsh web` for host-half changes, or just refresh the browser for client-only changes (the client bundle is served live at `/plugins/dsh-provider-billing/client.js`). Switch to npm/GitHub distribution once stable.

## Config

```yaml
- id: provider-billing
  name: dsh-provider-billing
  config:
    providers: [deepseek-official]
```

`providers` names the configurable-provider routes this deployment may check; a route absent from the directory never appears. The UI is fixed to the Models-row form (`settings.models.row`) — there is no other form and no compatibility fallback.

## How it works

- **Host half** (`src/index.ts`): one plugin row registers a loopback-pinned generic RPC channel (`/provider-billing`, endpoints `list` and `query`) through `ctx.connection.rpc.handle(..., { authority: 'loopback' })`, with the loopback fence enforced by the Connection layer — the same fence that pins the privileged `/api` methods. `query` resolves the route's stored key and endpoint (profile → `<ROUTE>_API_KEY` derivation → adapter default, each through the credential seam then the trusted environment, first hit wins) and fetches `/user/balance`.
- **Browser half** (`src/client/`): registers into the Models page's `settings.models.row` hole and renders the balance card (bilingual copy, `余额` / `Balance`). Without the hole it prints an explicit load-failure error.

## Development

```sh
pnpm install     # toolchain only — @deepseek-ai/* peers come from the installing harness
pnpm typecheck   # needs tsconfig.local.json (below)
pnpm test        # vitest: channel/query + the row card
pnpm build       # tsdown + tsc declarations → lib/{index,invariant,client}.js + lib/types
pnpm pack        # tarball
```

**Local harness checkout**: the published `@deepseek-ai/*` rc packages on npm have a broken dependency tree, so this package declares them as peerDependencies (satisfied by the installing harness) and resolves their types and test runtime from a local harness checkout. Create `tsconfig.local.json` (gitignored; `pnpm typecheck`, `pnpm test` and `pnpm build` read it) by extending `tsconfig.json` with declaration emit for `lib/types` plus a `paths` block pointing every `@deepseek-ai/*` specifier at the checkout's built types:

```jsonc
{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "noEmit": false,
    "declaration": true,
    "emitDeclarationOnly": true,
    "outDir": "lib/types",
    "paths": {
      "@deepseek-ai/cordis": ["<HARNESS_CHECKOUT>/vendor/cordis/lib/types"],
      "@deepseek-ai/dsh-llm": ["<HARNESS_CHECKOUT>/packages/llm/llm/lib/types"],
      "@deepseek-ai/dsh-settings": ["<HARNESS_CHECKOUT>/packages/settings/settings/lib/types"],
      "@deepseek-ai/dsh-credentials": ["<HARNESS_CHECKOUT>/packages/credentials/credentials/lib/types"],
      "@deepseek-ai/dsh-launch-environment": ["<HARNESS_CHECKOUT>/packages/util/launch-environment/lib/types"],
      "@deepseek-ai/dsh-host-apiproxy": ["<HARNESS_CHECKOUT>/packages/host/apiproxy/lib/types"],
      "@deepseek-ai/dsh-host-apiproxy/api": ["<HARNESS_CHECKOUT>/packages/host/apiproxy/lib/types/api"],
      "@deepseek-ai/dsh-invariants": ["<HARNESS_CHECKOUT>/packages/runtime-diagnostics/invariants/lib/types"],
      "@deepseek-ai/dsh-client-connection": ["<HARNESS_CHECKOUT>/packages/client/connection/lib/types"],
      "@deepseek-ai/dsh-client-connection/client": ["<HARNESS_CHECKOUT>/packages/client/connection/lib/types/client"],
      "@deepseek-ai/dsh-client-locale/client": ["<HARNESS_CHECKOUT>/packages/client/locale/lib/types/client"],
      "@deepseek-ai/dsh-client-runtime/client": ["<HARNESS_CHECKOUT>/packages/client/runtime/lib/types/client"],
      "@deepseek-ai/dsh-client-test-runtime": ["<HARNESS_CHECKOUT>/packages/test-support/client-runtime/lib/types"],
      "@deepseek-ai/dsh-client-ui-settings/client": ["<HARNESS_CHECKOUT>/packages/client/ui-settings/lib/types/client"],
      "@deepseek-ai/dsh-client-ui-settings-models/client": ["<HARNESS_CHECKOUT>/packages/client/ui-settings-models/lib/types/client"],
      "@deepseek-ai/dsh-client-ui-slots": ["<HARNESS_CHECKOUT>/packages/client/ui-slots/lib/types"],
      "@deepseek-ai/dsh-host-webserver": ["<HARNESS_CHECKOUT>/packages/host/webserver/lib/types"]
    }
  },
  "include": ["src"]
}
```

The tests derive their runtime aliases from the same file by rebasing `/lib/types` onto `/src`.

## Known limitations

- Only the `/user/balance` convention is served (the DeepSeek official shape); a provider with a different balance API reports its own error through the card.
- Endpoint errors ride the closed wire taxonomy's `internal` branch (with descriptive messages).
- npm tarballs do not include `lib/types` unless `pnpm build` ran on the publishing machine first (runtime is unaffected).
- The `row` UI requires the `settings.models.row` hole; unsupported harness builds fail loud.

## License

[MIT](LICENSE)

Install

dsh plugin --profile web add github:ZeroingIn/dsh-provider-billing

Profile: web

  • This package builds from source on install. pnpm will ask you to allow its build script — that is permission to run the package’s code on your machine, outside the agent sandbox. Only allow sources you trust.
  • This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.
Source