Files
command-center/omp-docs/core/deepseek-provider.md
T
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

128 lines
6.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
type: reference
title: DeepSeek Platform Provider (deepseek/deepseek-flash)
description: 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.
resource: https://api-docs.deepseek.com/
tags:
- omp
- models-yml
- deepseek
- providers
verified: 2026-10-29
timestamp: 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.
```bash
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
```ts
/** 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](/core/wan-model-access.md#the-key): 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](/core/wan-model-access.md) — 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](/core/index.md) — the rest of `agent/config.yml` / `models.yml`.
- [OMP Subagent Limits](/core/subagent-limits.md) — `providers.maxInFlightRequests`
is set per provider id; the `deepseek` row currently has no cap.