@alaxrpg/dsh-sensenova-provider
Unofficial DeepSeek Harness (DSH) LLM provider plugin for SenseNova (OpenAI-compatible API). Registers the sensenova provider route with a Models-page card, a live model catalog, and multi-account API-key rotation on a single shared base URL.
> Reference implementation: @mars-sea/dsh-commandcode-provider (MIT). This plugin keeps only the multi-account connection feature; it drops login flows, usage dashboards, plan windows, and command-line tools.
Features
- Registers provider route
sensenova(display name SenseNova). - Live model catalog via
GET {apiBase}/v1/models. - Streaming over both wire protocols:
POST {apiBase}/v1/responses(default, see below) andPOST {apiBase}/v1/chat/completions(SSE; automatic fallback). - Multiple API keys (accounts) on one shared base URL:
429 Too Many Requests→ does not cool down or rotate the key (protects the server-side per-key prompt cache); raisesRATE_LIMITwithproviderRetryAfterMsfor the host retry layer (honorsRetry-After, capped at 60 s; quota-class 429s carry a backoff floor). WithquotaRotationenabled, quota-class 429s stickily switch to the next untried key.401 Unauthorized→ rotate to the next key; the rejected key stays disabled until the stored credential changes.- All keys exhausted → surfaces
RATE_LIMIT/INVALID_CREDENTIAL. - Web settings page (Models-page card + dedicated settings section).
- Default wire protocol is Responses (
automode): used whenever the request can be expressed faithfully, and automatically downgraded to Chat Completions when semantics would be lost (e.g. astopsequence, or a reasoning effort away from the model's Responses default). Notable Responses differences:max_output_tokenscounts reasoning tokens,temperaturedefaults to 0.6 (Chat uses 1), reasoning is replayed as a summary only, andstopis not supported (auto-downgrades to Chat). - Image inputs: outbound images in production depend on a host-side attachment bridge (the
0.1.7-rc.2adapter type surface has no channel for it yet). In this version images are sent as host-generated text placeholders — never silently dropped; the bridge is a follow-up host dependency.
Requirements
- DSH host
>=0.1.2-alpha.3(alpha line). - Node.js
>=22.
> Compatibility note: the runtime import surface is a stable subset of
> @deepseek-ai/dsh-llm present since 0.1.1-rc.2 (LlmAdapter, LlmError,
> ReasoningEffortId, assertUsableApiKey, attributionHeaders, errorChain,
> resolveRetryPolicy); the drifting ToolCallId symbol is defined locally
> (src/brand.ts, identity-backed). Runtime loading on 0.1.1-rc.2 hosts works;
> the declared peer floor >=0.1.2-alpha.3 is the type-level support start
> (the ToolCallId type first appears there).
Install
dsh plugin --profile add dsh-sensenova-provider
Or install from a local path:
dsh plugin --profile add ./dsh-sensenova-provider
Then configure SenseNova in the Models page: the default credential environment variable is SENSENOVA_API_KEY, and the default base URL is https://token.sensenova.cn/v1.
Configuration
The plugin installs a llm-sensenova settings section with these fields:
| Field | Type | Default | Meaning |
|---|---|---|---|
apiBase |
string | https://token.sensenova.cn/v1 |
Shared base URL for all accounts. |
apiKeyEnv |
credential-ref | SENSENOVA_API_KEY |
Default account credential reference. |
accounts[] |
array | [] |
Extra accounts: { id, label, apiKeyEnv }. |
activeAccount |
string | "" |
Preferred account id; empty means auto / first usable. |
wireProtocol |
auto/responses/chat-completions |
auto |
Wire protocol mode: auto prefers Responses and downgrades to Chat when semantics would be lost; forcing responses errors on requests it cannot express; chat-completions is the legacy escape hatch. |
reasoningSummary |
auto/concise/detailed |
auto |
Responses-only: verbosity of the reasoning summary (reasoning.summary). |
API keys are stored through the DSH credentials service; they are never logged and never sent to the model.
Development
pnpm install
pnpm run typecheck
pnpm run build # tsdown → lib/
pnpm test # node --import tsx --test tests/**/*.test.ts
License
MIT