wjf1/dsh-commandcode

wjf1/dsh-commandcode

把 Command Code 接入 DSH Desktop 的模型提供商插件:注册 commandcode 路由,带实时模型目录、可配置的请求与流式空闲超时、429/401 自动多账户轮换、按套餐过滤模型、OAuth 登录流程,以及中英双语的用量与计费面板。

模型与账号接入

dsh-commandcode

Enhanced DSH-Desktop LLM provider plugin for Command Code. Feature-parity with dsh-commandcode-provider plus robust catalog sync, configurable retry, multi-credential environments, and refined UI for DSH-Desktop 0.7.1.

English | 中文


Screenshots

The screenshots below come from real runs inside DSH Desktop 0.7.1. After installing the plugin you see the same cards under Settings → Command Code and on the Models page.

ViewWhat it showsAsset
Usage & plan panelAccount chip, plan badge, request / success-rate / cost / token in-out breakdown, monthly · purchased · gifted quotas, 5-hour and weekly window progress barsassets/panel-usage.png
Models page provider cardCommand Code provider group, API key input, quick login, catalog refreshassets/card-models.png
Multi-account settingsAccount list, per-slot API key environment variable, active account switchassets/settings-accounts.png

The assets/ directory is where these images live; how to capture and refresh them is documented in HANDOFF.md. screenshots.json lists the assets the plugin marketplace picks up automatically (currently empty — no screenshot is published yet).


Features

Core Capability (Feature Parity)

  • Provider Route Registration — Registers the commandcode provider route on ctx.llm, making Command Code models selectable in any conversation
  • Models Page Card — A dedicated provider card on the Models settings page with API key input and quick login
  • Live Model Catalog — Real-time model directory fetching from the Command Code Provider API (/provider/v1/models) with on-disk cache
  • Credential Configuration — API key via environment variable (COMMANDCODE_API_KEY), settings page, CLI auth file (~/.commandcode/auth.json), or built-in OAuth login flow
  • Streaming Generation — Full SSE/JSONL streaming with text, reasoning, tool-call, and usage events

Enhancements

  • Stale-While-Revalidate Catalog — Serves cached models instantly, refreshes in the background; ETag conditional requests; circuit breaker prevents hammering a failing endpoint
  • Configurable Timeout & Retry — Per-request timeout (first byte) and stream idle timeout, both adjustable in settings; exponential backoff with jitter for transient failures
  • Multi-Account Rotation — Configure multiple API keys; automatic rotation on 429 rate-limit or 401 invalid-credential; active window probing to revive cooled-down accounts
  • Structured Error Diagnostics — Every error carries a stable code, diagnostic context (status, model, account, request ID), and a user-facing troubleshooting hint
  • Plan-Aware Model Filtering — Hides models above the account's subscription tier (fails open: unknown plan or on-demand credits show everything)
  • Usage & Billing Dashboard — Per-account usage stats, 5-hour/weekly window limits with progress bars, subscription plan info, and credit balance
  • Image Input Support — Vision-capable models accept image attachments via the durable attachment service

UI Optimization

  • Redesigned Settings Page — Clear card-based layout: Connection, Usage & Plan, Multi-Account, Advanced
  • Real-time Form Validation — Invalid API base URL, non-positive timeout, etc. with inline error messages
  • Bilingual Interface — Full Chinese/English localization following the browser language
  • DSH-Desktop 0.7.1 Design — Aligned design tokens (--dsw-alias-*), rounded corners, smooth transitions, focus rings
  • Per-Account Usage Tabs — Switch between accounts to view individual usage and plan status

Version Adaptation

  • DeepSeek Harness 0.1.2-alpha.1 Compatible — Built for DSH Desktop 0.7.x: uses @deepseek-ai/dsh-client-store (replaces the deleted dsh-client-runtime), the reactive SettingsScope snapshot contract, the credentials Remote namespace, and the shared /api exact-Fetch-route registry for the usage/login backends
  • One-Click Install — Add to profile's dsh.profile.bundles and restart; no manual build steps required
  • TypeScript Build — Reproducible build via tsdown with ESM output and type declarations

Installation

Prerequisites

  • DSH-Desktop >= 0.7.0 (DeepSeek Harness 0.1.2-alpha.1)
  • Node.js >= 20 (for development/build only; the desktop app bundles its own runtime)
  • A Command Code account with API key or subscription

Quick Install (Profile Bundle)

Add the plugin to your DSH profile's package.json:

# In your profile directory (e.g. ~/.dsh/profiles/desktop/)
npm install dsh-commandcode

Then add it to dsh.profile.bundles in package.json:

{
  "dsh": {
    "profile": {
      "bundles": [
        "@deepseek-ai/dsh-base",
        "@deepseek-ai/dsh-web-app",
        "dsh-commandcode"
      ]
    }
  }
}

Restart DSH-Desktop. The Command Code provider will appear in the Models page.

Manual Build from Source

git clone https://github.com/wjf1/dsh-commandcode.git
cd dsh-commandcode
npm install
npm run build
# Output in ./lib

This plugin commits its build output (lib/) on purpose, so users can install it without a toolchain. If you change anything under src/, rebuild and commit lib/ as well — CI fails when lib/ is out of sync with src/.

Refreshing vendor/ (offline builds)

Every @deepseek-ai/* dependency is pinned to a local tarball in vendor/ instead of a registry version, so npm install works on a machine with no network access to the DeepSeek registry. package.json refers to them as file:vendor/<name>-<version>.tgz.

After bumping a harness SDK version:

# 1. Pack the new versions into vendor/ (run where the packages are resolvable)
mkdir -p vendor
npm pack @deepseek-ai/dsh-llm@<new-version> --pack-destination vendor

# 2. Point package.json at the new tarball
#    "file:vendor/deepseek-ai-dsh-llm-<new-version>.tgz"

# 3. Reinstall and rebuild
npm install
npm run build

npm run check:vendor verifies that every file:vendor/*.tgz referenced by package.json actually exists and is not empty — a cheap check to run before publishing, and it needs no network.


Configuration

API Key

Three ways to configure, in order of precedence:

  1. Settings Page — Go to Settings → Command Code, paste your API key, click Save
  2. Environment Variable — Export COMMANDCODE_API_KEY in the shell that launches DSH
  3. CLI Auth File — Run command-code login to write ~/.commandcode/auth.json
  4. Built-in Login — Click "Login with Browser" in the settings page for OAuth flow

Settings Reference

FieldTypeDefaultDescription
apiKeyEnvstringCOMMANDCODE_API_KEYEnvironment variable name for the API key
apiBasestringhttps://api.commandcode.aiCommand Code Provider API base URL
workingDirstringprocess.cwd()Working directory reported to the API
modelsCachePathstring~/.commandcode/models-cache.jsonModel catalog cache file path
requestTimeoutMsnumber60000Time to wait for first response byte
streamIdleTimeoutMsnumber300000Max stall allowed during streaming
filterModelsByPlanbooleantrueHide models unavailable on current plan
accountsarray[]Extra accounts for multi-account rotation
activeAccountstring—Manually selected active account slot id
lang'zh' | 'en''zh'Language for the /commandcode terminal command

Multi-Account Configuration

# cordis.patch.yml
- insert:
    - id: llm-commandcode
      name: "dsh-commandcode"
      config:
        apiKeyEnv: COMMANDCODE_API_KEY
        accounts:
          - label: "Work"
            apiKeyEnv: COMMANDCODE_API_KEY_WORK
          - label: "Personal"
            apiKeyEnv: COMMANDCODE_API_KEY_PERSONAL

When a request hits 429 (rate limit) or 401 (invalid key), the plugin automatically switches to the next usable account.


Usage

Selecting a Model

  1. Open any conversation in DSH-Desktop
  2. Click the model selector
  3. Find the "Command Code" group
  4. Select any available model (marked with (CC) suffix)

Viewing Usage

  • Settings Page — Go to Settings → Command Code → Usage & Plan card
  • Terminal Command — Type /commandcode in the DSH terminal to see per-account usage, plan, and credit limits

Login Flow

  1. Go to Settings → Command Code
  2. Click "Login with Browser"
  3. Authorize in the opened browser tab
  4. The API key is saved automatically — no restart needed

Troubleshooting

"No API key" error

Ensure at least one of:

  • COMMANDCODE_API_KEY is set in the environment
  • API key is saved in Settings → Command Code
  • command-code login has been run (creates ~/.commandcode/auth.json)

"429 Rate Limit"

  • The 5-hour usage window is exhausted
  • Wait for the window to reset (shown in the Usage card)
  • Add more accounts for automatic rotation
  • Upgrade your Command Code subscription

"401 Invalid Credential"

  • The API key is expired or revoked
  • Re-run the login flow or paste a new key
  • Check that the environment variable contains the correct key

Models not showing in selector

  • Click "Refresh" in the Usage card to trigger a catalog refresh
  • Check network connectivity to api.commandcode.ai
  • The cached catalog is served even when offline; restart clears in-memory cache

Stream stalls / disconnects

  • Increase streamIdleTimeoutMs in Advanced settings
  • Check network stability
  • Long generations may exceed the idle timeout if the model is slow to respond

Development

Project Structure

dsh-commandcode/
├── src/
│   ├── index.ts            # Plugin entry: provider registration, settings, wiring
│   ├── adapter.ts          # LLM adapter: streaming, model catalog, usage endpoints
│   ├── catalog.ts          # Model catalog: SWR, cache, circuit breaker
│   ├── accounts.ts         # Multi-account pool: rotation, window probing
│   ├── login.ts            # OAuth login flow: loopback callback server
│   ├── login-wire.ts       # Login wire protocol types
│   ├── commands.ts         # /commandcode terminal command
│   ├── command-locales.ts  # Command i18n (zh/en)
│   ├── usage-remote.ts     # Usage Typert Gateway endpoints
│   ├── usage-wire.ts       # Usage wire protocol types
│   ├── errors.ts           # Structured error diagnostics
│   ├── retry.ts            # Retry policy, circuit breaker, backoff
│   └── client/
│       ├── index.ts        # Client entry: CSS, slots, controllers
│       ├── section.tsx     # Settings page React component
│       ├── card.tsx        # Models page provider card
│       ├── settings.ts     # Settings controller (state, validation, persist)
│       ├── login.ts        # Login controller (polling)
│       ├── usage.ts        # Usage controller (fetch, tabs)
│       ├── locales.ts      # Client i18n (zh/en)
│       ├── sessions.ts     # Friendly image-session error wrapper
│       ├── update.ts       # Update check
│       └── version.ts      # Version constants
├── tests/                  # Node test runner test suite
├── assets/                 # Icons and screenshots (see the Screenshots section)
├── lib/                    # Prebuilt ESM output committed on purpose — see below
├── vendor/                 # Vendored 0.1.2-alpha.1 package closure (file: devDependencies)
├── cordis.patch.yml        # Bundle layer definition
├── package.json
├── tsconfig.json
├── tsdown.config.ts / tsdown.config.js
├── screenshots.json        # Assets the marketplace picks up
├── HANDOFF.md              # Cross-session handoff notes
└── README.md / README.zh-CN.md / CHANGELOG.md / LICENSE

Why lib/ Is Committed

pnpm v10+ blocks lifecycle scripts of dependencies by default. A plugin that builds itself in a prepare script therefore fails to install from the marketplace ("build scripts are blocked by pnpm by default"). This repository commits the built lib/ so that installation is a plain file copy with zero scripts. npm run build still exists for local development and CI; remember to run it and commit lib/ whenever src/ changes.

Build Commands

npm install          # Install dependencies
npm run typecheck    # TypeScript type check
npm test             # Run test suite
npm run build        # Build ESM output + type declarations to ./lib

Architecture Notes

  • Host/Client Split: src/index.ts runs in the Node.js host process; src/client/index.ts runs in the browser. The dsh.client.inject field in package.json declares the client bundle's dependencies.
  • Per-Request Resolution: All connection facts (API key, endpoint, timeouts) are resolved fresh per request via thunks, so a settings change reaches the next request without restart.
  • Wire Protocol: The Command Code Provider API uses a custom SSE/JSONL format (/alpha/generate). The adapter parses text-delta, reasoning-*, tool-call, finish, and error events.

Acknowledgments

  • Mars-Sea/dsh-commandcode-provider — The original community plugin that this project enhances. MIT License.
  • The Command Code team for the Provider API and CLI.
  • The DeepSeek Harness team for the plugin architecture and LLM adapter framework.

License

MIT © 2026 dsh-commandcode contributors