Files
command-center/omp-docs/core/deepseek-provider.md
Frank 206c9acb46 feat: add the DeepSeek platform provider and deepseek-flash
Refs #83

The first vendor-cloud chat row in agent/models.yml. The provider label is the
bare word `deepseek` because pi-catalog/src/hosts.ts keys the direct-DeepSeek
behaviour set (max_tokens field, thinking extraBody, thinking-disable mode) off
that exact name and off api.deepseek.com; the house `<api> (<host>)` pattern
would not match and the row would lose the quirks the endpoint answers to.

The key is command-backed (`!cat ~/.config/secrets/deepseek_api_key`, 600), so
no sk-… value enters the tracked tree, and the row declares the model card's own
pair: contextWindow 1048576 / maxTokens 262144, input [text, image], with the
October 2026 peak rate card in cost. Docs move to the new
omp-docs/core/deepseek-provider.md, indexed and logged in the same commit.
2026-10-29 14:47:34 -07:00

6.5 KiB
Raw Permalink Blame History

type, title, description, resource, tags, verified, timestamp
type title description resource tags verified timestamp
reference DeepSeek Platform Provider (deepseek/deepseek-flash) The vendor-cloud row added to agent/models.yml on 2026-10-29 — why the provider label is the bare word `deepseek`, where its key lives, and the window/maxTokens/cost values it declares. https://api-docs.deepseek.com/
omp
models-yml
deepseek
providers
2026-10-29 2026-10-29

DeepSeek Platform Provider (deepseek / deepseek-flash)

agent/models.yml gained its first vendor-cloud chat row on 2026-10-29: DeepSeek's own hosted API, added alongside the four fleet endpoints and the OpenWebUI WAN door. Use this page when a deepseek/… selector fails, when the key needs rotating, or before adding another upstream-vendor row.

omp --model 'deepseek/deepseek-flash:off'

Why the label is the bare word deepseek

The house pattern for provider labels is <api> (<host>) — llamacpp (dankclaw), openwebui (franksdank.cloud). This row breaks it deliberately: the harness resolves a provider's behaviour set by matching the label (and the baseUrl) against the catalog's host table, pi-catalog/src/hosts.ts, whose entry reads

/** DeepSeek's first-party API only — gates direct-API quirks (max_tokens field, thinking extraBody). */
deepseekDirect: { providers: ["deepseek"], urlMarkers: ["api.deepseek.com"] },

A label of deepseek (platform) matches neither the provider list nor the URL marker rule for the name, and the row loses the direct-DeepSeek quirks the catalog gates behind that key — the max_tokens field name, the thinking extraBody, and the thinking-disable mode, which on this provider must be zai-thinking-disabled (thinking: {"type":"disabled"}), not the none-effort the LAN rows need. The baseUrl carries the host the label cannot name.

The same table is why the provider's roster is not one row but four. A models.yml entry is an overlay on the built-in catalog, keyed by provider/id (#mergeCustomModels → mergeByModelKey), so omp models deepseek now prints:

Row Source
deepseek-flash the authored row — 1M context, 262K max-out
deepseek-v4-flash built-in catalog row, untouched
deepseek-v4-flash-vision-exp built-in catalog row, untouched
deepseek-v4-pro built-in catalog row, untouched

The other three keep catalog windows and pricing; adding a model to the file does not replace the provider.

What the row declares, and from where

Field Value Authority
baseUrl https://api.deepseek.com/v1 official docs, OpenAI base_url
api openai-completions same
id deepseek-flash official model name — deepseek-v4-flash / deepseek-v4-flash-vision-exp are retired aliases that route to DeepSeek-V4.1-Flash-1017 and bill at the Flash price
contextWindow 1048576 model card (context_window 1M)
maxTokens 262144 model card (max_tokens ≥ 256K)
input [text, image] V4.1 is natively image-text-to-text
cost 0.3 / 1.2 / 0.006 / 0 per 1M (in / out / cache-read / cache-write) October 2026 rate card, peak tier
compat.supportsToolChoice false V4 thinking mode rejects the tool_choice parameter; tool calls still work and default to auto
compat.supportsDeveloperRole false V4 has no developer role
compat.reasoningContentField reasoning_content same field every fleet engine uses
compat.extraBody.thinking {type: enabled} the documented request shape

Laws worth carrying forward:

  • maxTokens and contextWindow are a pair. The serving contract is prompt + max_tokens ≤ contextWindow; the harness clamps max_tokens = min(maxTokens, contextWindow − est − 4096), so a declared pair that exceeds the engine's own contract turns into a 400 rather than a truncation. 1048576 / 262144 is the pair the card itself states, and it is the pair the row declares.
  • Cost rates go on the row or nowhere. cost is optional in the schema, and a custom row that omits it reports $0 in the status line forever. The schema models one rate per direction, so the off-peak tier ($0.15 / $0.60) cannot be expressed — peak is the value.
  • Sampling. The card recommends temperature 1.0 / top_p 1.0; thinking mode floors top_p at 0.95 server-side, and top_k is not accepted through the OpenAI surface. The row pins temperature: 1.0 + top_p: 1.0 anyway — extraBody is merged last and wins, so pinning it survives a server-side sampler edit, exactly as the LAN rows do.
  • A row behind a proxy or a vendor façade copies its direct twin's compat block; this row has no LAN twin, so it copies the harness's own built-in descriptor for the same provider (pi-catalog/src/provider-models/openai-compat.ts, openAiCompletionsDescriptor("deepseek", …)) instead of inventing one.

The key

apiKey: "!cat ~/.config/secrets/deepseek_api_key" — 600-mode file, same convention as gitea, kagi_api_key, hf_token, and openwebui_api_key. The rules are the ones in WAN Model Access: a literal sk-… in the tracked file trips the pre-commit shape gate, and a quoted !cmd value is the only shape that both resolves and stays out of the gate's assignment scan. Rotation is rewrite-then-restart; the resolved value is cached for the process lifetime. Every workstation that pulls this repo needs its own copy — nothing in the repo carries the value.

Verification performed 2026-10-29

  • omp models --no-extensions from a scratch HOME containing the edited models.yml + config.yml: zero validation failed lines, all four fleet providers still listed, deepseek (4) present with deepseek-flash 1M/262K.
  • Live call through the scratch HOME — the only proof that auth came from the new apiKey line and not from ~/.omp/agent/auth.json: omp --model 'deepseek/deepseek-flash:off' … -p 'Reply with exactly the word OK' → OK in 2.6 s. The same scratch tree with the baseUrl port poisoned to :9 hangs instead of answering, which is what rules out a cached or built-in answer.

See also

  • WAN Model Access — the credential law and the off-network route to Frank's own engines; deepseek is reachable from anywhere but is not that door.
  • Core config — the rest of agent/config.yml / models.yml.
  • OMP Subagent Limits — providers.maxInFlightRequests is set per provider id; the deepseek row currently has no cap.