Overview
dsh-freellmapi
auto model that scores each request's complexity and picks the best of 18 catalogued providers -- five enabled by default -- failing over automatically. Unconfigured providers collapse to a single 'add your key' entry instead of dead models, and pinning a specific model is strict -- never silently swapped. Works with zero credentials out of the box.README / EN
Package documentation
Registry summary
auto model that scores each request's complexity and picks the best of 18 catalogued providers -- five enabled by default -- failing over automatically. Unconfigured providers collapse to a single 'add your key' entry instead of dead models, and pinning a specific model is strict -- never silently swapped. Works with zero credentials out of the box.dsh.pub verifies the pinned bundle contract, runtime facts, and distribution semantics. The complete README remains in the source repository.
Read the full README on GitHubLIMITATIONS
Known limitations
Stated plainly, so you know what you are relying on: 1. **The complexity classifier is a heuristic, not understanding.** It counts tokens, fenced code, tool schemas and vocabulary. [When it gets it wrong](#when-it-gets-it-wrong-and-how-to-override-it) shows three real misjudgements from this implementation. When you know better, pin `auto:simple` / `auto:medium` / `auto:complex`, or pin one `provider/model`. 2. **No end-to-end run against real providers.** Every test in this repository runs against in-process mock providers, deliberately, so CI stays offline. The only *real* external calls ever made were the maintainer's keyless probe (five requests, four 200s and one 404 documented in `_lead/live-probe-2026-10-13.md`) plus the credential-free reachability and catalog probes behind the reachability section above (`_lead/research/reachability-v0.7.md`, 2026-10-15). **No completion has ever been requested with a real key**, so everything else — every keyed provider, every quota number, every model id except the ones a public catalog publishes — is **documentation-level evidence**, not measurement. 3. **Only credential-free requests were ever made.** `groq`, `cerebras`, `openrouter`, `mistral`, `nvidia` and the rest were contacted without credentials (status codes and public catalogs only, never a completion), so their `baseURL`s and model ids come from upstream's registry and migrations. Rate-limit numbers are the 2026-04 baseline and will drift. 4. **`zhipu` is the riskiest entry in the pool**, and `volcengine` / `longcat` model ids are inferred — all three ship **disabled** with `confidence: 'speculative'`. Enabling them is you accepting that risk. The `zhipu` hostname in particular differs between the mainland and overseas sites and the keys do not interchange: a wrong hostname is a guaranteed 401. 5. **Free catalogs drift.** The same model id can answer 200 today and `400 model_unavailable` tomorrow. The router treats that as a per-model condition (park + next candidate), so it degrades instead of failing — but it is normal operation, not a bug. 6. **`stream_error` frame shapes are documentation-level.** Upstream does not pin the JSON shape, so the parser recognises the four plausible forms (`type`, `code`, `object`, nested `error`) and treats any error-shaped frame as terminal. 7. **The image path is not verified against a real attachments service.** Bytes are read through `attachments.imageHostPath()`, the only documented way for an adapter to reach them, and inlined as `data:` URLs (up to 20 MB each); if that service differs in your build, each affected image degrades to a placeholder text and the request still succeeds. Only two models in the default pool declare `vision: true`. 8. **`sessionId` / `purpose` from `GenerateOptions` are not mapped** — Chat Completions has no standard field for them. 9. **Health state is not persisted.** Cooldowns live in the process; after a restart a parked provider is retried once. `HealthTracker` can round-trip its state, but nothing writes it to disk. 10. **A failed-over answer comes from a different model than the first choice.** When candidate 1 fails, candidate 2 answers, and they are different models. That is safe (nothing was emitted yet) and fully recorded in the routing record's `attempts`, but the answer is not from the top-ranked model. 11. **`nvidia` needs `parallel_tool_calls: false`.** Several NIM models reject parallel tool calls, so the pool declares the flag and it is applied to the request body. NVIDIA still ships disabled by default (trial-only ToS, minutes-long first token, tight limits). 12. **`routing.weights` / `routing.thresholds` are advanced fields** with no rendered form in the settings page (they are `z.any()` payloads). Edit them in the profile patch. 13. **Still open from the v0.1.0 verification round** (re-checked against this implementation): `maxTokens` a
