Jesse-njx/dsh-polyglot
dsh-polyglot — the model switch for DSH: generic OpenAI-compatible ctx.llm adapter, curated free/cheap DeepSeek presets, automatic provider fallback on rate limits
Listed
3
Model
Bundle verified
What it does
The model switch for DSH: point it at any OpenAI-compatible endpoint, with curated free/cheap DeepSeek provider presets and automatic fallback when a free tier rate-limits you.
Best for
- DSH users who want to switch among multiple OpenAI-compatible model endpoints.
- Cost-sensitive workflows that can fail over from rate-limited free providers to another configured provider.
- Teams that need per-provider token and estimated-cost accounting in the session log.
Not ideal for
- Non-chat modalities, which are explicitly outside the plugin's scope.
- Streams that must recover after content has already been emitted; fallback only switches providers before any content flows.
- Users who cannot supply credentials for any usable provider; entries with missing keys are skipped.
README
dsh-polyglot
The model switch for DSH. Point DeepSeek Harness at any OpenAI-compatible endpoint — with curated presets for free and cheap DeepSeek providers and automatic fallback when a free tier rate-limits you.
What claude-code-router is to Claude Code, dsh-polyglot is to DSH — except
DSH’s ctx.llm is a sanctioned extension seam, so there is no request
interception: the generic adapter and the router are both real LlmAdapter
registrations.
-
One generic adapter. A single OpenAI-compatible
ctx.llmadapter parameterized by{baseUrl, apiKey, model, headers?, quirks?}. Streaming, tool calls, and usage extraction are all handled; per-provider deviations (reasoning field names, strict tool schemas, cache-folded usage) are small declarativequirksflags, never per-provider code. -
A router with fallback. On 429 / quota-exceeded / 5xx (or a missing
key), the failing provider is marked cooling-down (exponential backoff,
honoring
Retry-After) and the request is retried on the next provider in the chain. Free tiers rate-limit constantly — automatic failover is the whole product. -
Provider presets as data.
presets/*.json— community PRs add providers without touching the adapter. Each preset carriesverifiedAtand free-tier notes so rot is visible. -
Usage you can see. Every attempt lands in the append-only session log as
polyglot/served;/polyglot usagetallies per provider with token counts and estimated cost from preset pricing.
Quick start
Install the bundle into a profile (a DSH profile is an ordered stack of plugin-bundle patch layers):
dsh plugin --profile web add @dsh-polyglot/bundle
The bundle’s patch registers the polyglot plugin with the recommended
default chain — “code all day for free until something rate-limits, then
degrade gracefully to cheapest-paid”:
nous-portal → opencode-zen → deepseek-official (5M grant) → kilo
Configure keys through the credentials seam (the web Models page writes them), or export the env names each preset declares:
export NOUS_PORTAL_TOKEN=... # nous-portal (bearer, manual token for v0.1)
export OPENCODE_API_KEY=... # opencode-zen
export DEEPSEEK_API_KEY=... # deepseek-official (new accounts: 5M free tokens, 30 days, no card)
export KILO_API_KEY=... # kilo (paid fallback rung)
Pick the virtual provider polyglot in the model selector. A provider without
a configured key is skipped automatically — the chain degrades, it never
fails hard.
Day-to-day commands
| Command | What it does |
|---|---|
/model |
show chains and the active one |
/model <chain> |
switch the active chain mid-session (logged as polyglot/chain) |
/polyglot |
status: active chain, entries, provider cooldowns |
/polyglot usage |
per-provider tally from the session log: calls, ok/failed, tokens, est. cost |
/polyglot presets |
free-tier posture of the active chain’s presets |
Configuration
Override chains and cooldown from your profile patch:
# your profile's cordis.patch.yml (or --patch overlay)
- patch:
- id: polyglot
config:
chains:
default:
- preset: nous-portal
- preset: opencode-zen
- preset: deepseek-official
model: deepseek-v4-flash
- preset: kilo
paid:
- preset: deepseek-official
model: deepseek-v4-pro
cooldown:
baseMs: 30000 # initial per-provider cooldown after a failure
maxMs: 900000 # ceiling (also honors provider Retry-After)
factor: 2 # exponential growth per consecutive failure
jitterRatio: 0.1 # symmetric jitter around each delay
Per-entry overrides: provider (route name), model, baseUrl, apiKeyEnv,
headers, quirks — the custom preset is the escape hatch for
vLLM/Ollama/SGLang localhost and any other OpenAI-compatible endpoint
(Qwen/GLM/Kimi official APIs included).
Quirks reference
| Flag | Default | Meaning |
|---|---|---|
reasoningField |
'reasoning_content' |
wire delta field carrying reasoning text; null disables reasoning entirely |
maxTokensField |
'max_tokens' |
output-cap wire field (max_completion_tokens for newer hosts) |
usage |
'standard' |
'deepseek' subtracts cache hits folded into prompt_tokens; 'none' when the host reports none |
streamOptions |
true |
send stream_options: {include_usage: true}
|
strictToolSchemas |
false |
add strict: true to tool schemas |
thinkingField |
false |
send thinking: {type} (DeepSeek spelling) |
reasoningEffortField |
true |
send reasoning_effort for high/max efforts |
Preset registry
All figures were re-verified 2026-08-14 against provider docs; these move
weekly — every preset carries verifiedAt, and a CI job pinging each
baseUrl with a 1-token request is the planned trust loop.
| Preset | What you get | Cost / limits | Notes |
|---|---|---|---|
deepseek-official |
V4-Flash, V4-Pro | $0.14/$0.28 per M (Flash); 5M free tokens new accounts, 30 days, no card | Baseline; prices trending up |
opencode-zen |
deepseek-v4-flash-free (+ Qwen 3.6 Plus, MiniMax M3, MiMo…) |
Free, no card, 200k context; rate limits undocumented | Commercial terms unclear — flagged in the preset notes
|
nous-portal |
deepseek/deepseek-v4-flash:free |
Free, OAuth-gated, hard rate ceiling that returns errors | The poster child for fallback; put it first in a chain |
kilo |
V4-Pro, V4-Flash, V3.1 Terminus | Pay-as-you-go at no markup over provider rates | Good paid-fallback rung |
openrouter |
:free DeepSeek variants + everything else |
Free variants throttled; paid at listed rates | Widest catalog, one key |
custom |
anything OpenAI-compatible | — | vLLM/Ollama/SGLang localhost; Qwen/GLM/Kimi official endpoints |
groq / together / fireworks
|
DeepSeek hosting | fast but pricier | Latency upgrades, not savings |
How it works
profile ──> provider route "polyglot" (the router meta-adapter)
│ chain: nous-portal → opencode-zen → deepseek-official → kilo
▼
ctx.llm.stream({provider: "nous-portal", ...})
│ adapter per real route (OpenAiCompatAdapter, one per preset)
▼
POST {baseUrl}/chat/completions (SSE, usage, tools)
The router forwards the first attempt that completes. A fallback-eligible
failure that arrives before any content flowed — the free-tier ceiling
case — swaps to the next provider seamlessly; a failure after content flowed
cannot be unwritten and surfaces as a normal error finish. Which provider
actually served each turn is durable in the session log (polyglot/served),
so /polyglot usage is a pure fold over the log, not plugin-side accounting.
ToS note
Free tiers are often gated for evaluation use (OpenCode Zen’s commercial
terms are undocumented). Preset notes surface this at configure time —
dsh-polyglot does not silently launder usage.
Development
pnpm install
pnpm typecheck # strict TS
pnpm build # tsc → lib/
pnpm test # 56 tests: mock OpenAI-compat server with scripted 429/500/
# stream scenarios, golden wire assertions per quirk, and
# end-to-end cordis mounts proving fallback + session events
Roadmap
- v0.2 — per-role chains (planner → paid V4-Pro, executor/summarizer → free Flash); OAuth device flow for Nous Portal; preset auto-update check; provider benchmark/arena integration.
- Non-goals — proxying non-chat modalities; silent key laundering.
Frequently Asked QuestionsFAQ
Use the verified command dsh plugin --profile default add github:Jesse-njx/dsh-polyglot in a DSH-enabled shell. The command resolves the public package metadata and keeps the plugin attached to the catalog identity shown on this page.
Compatibility follows the bundle and profile status shown above. If a profile is not detected, keep the plugin disabled there and check the repository documentation before enabling it in production.
The GitHub link and activity metadata are the source of truth for releases and maintenance. Revisit this page after a new release to confirm the catalog has observed the latest version.