deepseek-harness
deepseek-ai
DeepSeek Harness: Everything is a Plugin.
PROJECT TOPICS
PROJECT README
Keeps the harness's own opencode-go provider route on the model list opencode Go actually serves — no second provider, no settings.yaml edits, no credential handling, and no shipped model overwritten.
opencode-go route lists 27 models (pi-ai's shipped snapshot)deepseek-v4.1-flash, kimi-k2.5, grok-4.5, glm-5, qwen3.5-plus, mimo-v2-pro/omni, minimax-m2.5, deepseek-flash, hy3-preview, union-alphaWhen opencode ships a model the harness snapshot predates (for example deepseek-v4.1-flash), the route cannot serve it, and adding it by configuration fails:
llm-pi-ai: provider "opencode-go" model "deepseek-v4.1-flash" needs an api; the installed
catalog does not describe it, so set the route's api to the wire protocol its endpoint speaks
Every configuration path has a cost — see discussion #6464:
| Path | Cost |
|---|---|
providers.opencode-go.models |
replaces the route's whole catalog (all 27 shipped models), and every entry must restate api/baseURL |
modelOverrides |
only reshapes ids the catalog already describes; a new id is refused |
| a custom route | is not the built-in opencode-go, so balance/cost/session plugins no longer recognize it |
This plugin takes the third path: it contributes into the catalog itself, so a new model becomes a shipped model.
opencode-go catalog object (MODELS['opencode-go']), which is exactly what dsh-llm-pi-ai reads while resolving the route (getBuiltinModels('opencode-go')). Settings surfaces, model validation, and request resolution therefore treat them as built-ins.getModels is wrapped so a route that already resolved still sees entries that arrive later. A background refresh lands in the model picker and the request path without a restart.$DSH_HOME/cache/opencode-go-model-list/catalog.json, adopted synchronously on the next boot, and refreshed in the background. Offline hosts keep the last good list.| Source | Role |
|---|---|
GET https://opencode.ai/zen/go/v1/models |
which models the plan serves (public, no auth; 38 at the time of writing) |
GET https://models.dev/api.json, opencode-go slice |
context/output limits, modalities, cost, reasoning options, family (37 records) |
| the shipped catalog | api, baseUrl, compat (vendor wire dialect), thinking-level spellings |
Each field is resolved on its own evidence:
family shipped model → the SDK the provider itself declares (provider.npm) → the vendor's majority protocol → the route's majority protocol → defaultApisupportsStore:false), extended by a same-family model's own dialect (deepseek's thinkingFormat: deepseek) — never guessed across vendorshy3-preview): cloned from the nearest sibling by id prefix, named from the idFidelity regression against the shipped catalog itself (test/fidelity.test.mjs, each entry rebuilt with the model removed from the shipped set): reasoning/input/contextWindow/maxTokens match 27/27, api 26/27, name 26/27, cost 22/27, compat/thinkingLevelMap 21/27. The gaps are curated facts no listing endpoint discloses (price revisions, vendor dialects).
dsh plugin commandcd E:\path\to\dsh-opencode-go-model-list-fix
dsh plugin --profile web add . # link: dependency; node_modules points here
# or a packed, self-contained copy:
dsh plugin --profile web add file:E:\path\to\dsh-opencode-go-model-list-fix
dsh plugin forwards its arguments to pnpm inside the profile directory and then reconciles dsh.profile.bundles against installed state: any dependency whose package declares dsh.bundle.patch joins the profile layer stack. This package declares it, so one command covers dependency, node_modules, and bundle registration. Verified in an isolated home: both link: and file: registered the bundle and booted to 38 models. pnpm must be on PATH (11.17.0 here).
link:: the profile's node_modules points at this checkout — edits apply immediately, but the directory must stay put.file:: pnpm packs a copy honoring files, self-contained; re-run add to update.dsh plugin --profile web install re-registers it from installed state.install.ps1 (no pnpm needed)powershell -ExecutionPolicy Bypass -File .\install.ps1 # profile: web (default)
powershell -ExecutionPolicy Bypass -File .\install.ps1 -Profile tui
The script does exactly two things: copies the package to $DSH_HOME/profiles/<profile>/node_modules/dsh-opencode-go-model-list, and appends the package name to that profile's dsh.profile.bundles. It never writes into the dsh installation, settings.yaml, or the credential store. Verified that pnpm install / pnpm add do not prune such a copy (it sits outside pnpm's dependency graph, which is also why update will not upgrade it).
After a restart, expect:
[opencode-go-model-list] mounted: route=opencode-go gateway=https://opencode.ai/zen/go/v1/models ...
[opencode-go-model-list] route "opencode-go" resolved against the installed catalog: 27 shipped models, ...
[opencode-go-model-list] gateway=38, catalog=37 → 11 contributed (27 already served) in 2641ms
Uninstall with uninstall.ps1 (add -RemoveCache to drop the cache). Nothing on disk in the installation was ever modified, so removal restores the previous list exactly.
powershell -ExecutionPolicy Bypass -File .\scripts\verify-in-isolated-home.ps1 -Proxy http://127.0.0.1:7897
It builds an isolated harness home under .verify/dsh-home, initializes a throwaway headless profile, links this package and a probe plugin into it, and boots dsh twice — with and without the plugin — while the probe asks the harness's own LLM service (ctx.llm.listModels('opencode-go'), resolveModelInfo) for the route's models. Observed output:
===== without the plugin (shipped catalog) =====
[probe] count 27 after 24.5s
[probe] has-target deepseek-v4.1-flash=false kimi-k2.5=false
===== with the plugin (live catalog) =====
[probe] count 38 after 0.5s
[probe] has-target deepseek-v4.1-flash=true kimi-k2.5=true
[probe] resolve deepseek-v4.1-flash {"provider":"opencode-go","id":"deepseek-v4.1-flash","name":"DeepSeek V4.1 Flash",
"inputModalities":["text","image"],"context":{"contextWindow":1000000},
"reasoning":{"efforts":[{"id":"off",...},{"id":"low",...},{"id":"high",...},{"id":"max",...}]}}
- id: opencode-go-model-list
name: 'dsh-opencode-go-model-list'
config:
provider: opencode-go # the route to extend (the built-in one by default)
gatewayUrl: https://opencode.ai/zen/go/v1/models # what the plan serves
catalogUrl: https://models.dev/api.json # metadata; empty means gateway + siblings only
refreshIntervalMs: 21600000 # 6h; 0 fetches once per process start
timeoutMs: 15000
offline: false # cache only, no network
includeDeprecated: true
defaultApi: openai-completions
updateExisting: false # true rewrites shipped entries with live metadata
patchCollection: true # the live view that makes a refresh need no restart
cachePath: '' # default: $DSH_HOME/cache/opencode-go-model-list/catalog.json
extraModelIds: []
models: # per-model overrides, keyed by id
deepseek-v4.1-flash:
name: DeepSeek V4.1 Flash
contextWindow: 1000000
some-id:
skip: true
verbose: false
llm.registerAdapter and registers no provider. opencode-go stays the catalog provider dsh-llm-pi-ai reuses — same API implementations, same ambient credential discovery, same apiKeyEnv.x-opencode-session and friends by route name plus URL host (opencode.ai). Contributed models use the same route and base URL, so session headers keep flowing.cost (from models.dev). Whether its own price table covers a new model is that plugin's data question.updateExisting: true; unmounting withdraws exactly the contributed ids and restores the original collection method.compat are inferred from the shipped catalog. If opencode ever puts a new model on a protocol none of its siblings use, name it explicitly with the per-model api override.opencode.ai and models.dev, through the process proxy environment the harness launcher already installs (@deepseek-ai/dsh-http-proxy) — no extra configuration here. When both fail, the shipped catalog is served unchanged.lib/index.js plugin entry (cordis: name / inject / apply, plus a testable mount)
lib/config.js configuration normalization and defaults
lib/sources.js the two upstreams, fetched and parsed leniently
lib/mapping.js upstream facts -> pi-ai catalog entries (every inference rule lives here)
lib/pi-ai.js pi-ai module location, catalog contribute/withdraw, collection patch
lib/cache.js cache read (sync) and write (atomic)
test/ unit, catalog integration, fidelity, end-to-end (35 cases)
scripts/ isolated-home verification script and its probe plugin
npm test # standard node --test (spawns workers)
npm run test:in-process # every suite in one process (works under a restricted sandbox) CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: 无有效分类标签。