feat: add the DeepSeek platform provider and deepseek-flash #84
No files matched your search
+83
-3
@@ -319,10 +319,90 @@ providers:
|
|||||||
api: openai-speech
|
api: openai-speech
|
||||||
input: [text]
|
input: [text]
|
||||||
|
|
||||||
|
# Vendor cloud, not a fleet host: DeepSeek's own API. The label is the bare
|
||||||
|
# `deepseek` — NOT the house `<api> (<host>)` pattern — because the harness
|
||||||
|
# matches provider names against a built-in service table
|
||||||
|
# (`src/config/model-registry.ts` profiles, `dist/cli.js` `VIn` map), and
|
||||||
|
# `deepseekDirect` lists `providers: ["deepseek"]` with urlMarkers
|
||||||
|
# `["api.deepseek.com"]`. A name like `deepseek (platform)` matches neither
|
||||||
|
# form, and the row loses the direct-DeepSeek behaviour set the catalog ships
|
||||||
|
# for its own built-in provider (see the compat block below). The baseUrl
|
||||||
|
# carries the host the label can't name.
|
||||||
|
"deepseek":
|
||||||
|
baseUrl: https://api.deepseek.com/v1
|
||||||
|
api: openai-completions
|
||||||
|
# Command-backed, like every other credential in this file: the key lives in
|
||||||
|
# ~/.config/secrets/deepseek_api_key (600) and never enters the tracked
|
||||||
|
# tree, where the pre-commit shape gate would read it. Quoted because an
|
||||||
|
# unquoted leading `!` is a YAML tag. The resolved value is cached for the
|
||||||
|
# process lifetime — rotation is: rewrite the file, then restart omp.
|
||||||
|
# Written 2026-10-29 from the key Frank issued; every other workstation that
|
||||||
|
# pulls this repo needs its own copy of the file (nothing here carries it).
|
||||||
|
apiKey: "!cat ~/.config/secrets/deepseek_api_key"
|
||||||
|
models:
|
||||||
|
- id: deepseek-flash
|
||||||
|
name: "deepseek-flash"
|
||||||
|
# Official name (api-docs.deepseek.com): `deepseek-flash` is served by
|
||||||
|
# DeepSeek-V4.1-Flash-1017. The legacy names deepseek-v4-flash and
|
||||||
|
# deepseek-v4-flash-vision-exp are still accepted but retired — the
|
||||||
|
# model card says to use `deepseek-flash`; so does Frank.
|
||||||
|
# The model card states context_window 1M; 262,144 is its `max_tokens ≥
|
||||||
|
# 256K` recommendation. The two are the engine's own pair: any prompt +
|
||||||
|
# budget over 1,048,574 is a refusal, and this row states them together
|
||||||
|
# so the harness clamps before the API has to.
|
||||||
|
contextWindow: 1048576
|
||||||
|
maxTokens: 262144
|
||||||
|
# Natively multimodal (V4.1 = image-text-to-text on the hub), despite
|
||||||
|
# the retired `-vision-exp` alias suggesting otherwise.
|
||||||
|
input: [text, image]
|
||||||
|
# Rate card, per 1M tokens, peak tier ($0.15/$0.60 off-peak is not
|
||||||
|
# modelled — the harness has one field per direction and a session
|
||||||
|
# cannot know which window it is billing into). Overriding these here is
|
||||||
|
# the only way a non-catalog row reports cost at all.
|
||||||
|
cost:
|
||||||
|
input: 0.3
|
||||||
|
output: 1.2
|
||||||
|
cacheRead: 0.006
|
||||||
|
cacheWrite: 0
|
||||||
|
compat:
|
||||||
|
# Copied from the harness's own built-in descriptor for this provider
|
||||||
|
# (`pi-catalog/src/provider-models/openai-compat.ts:7422`), never
|
||||||
|
# simplified — the same law as the WAN rows:
|
||||||
|
# V4 thinking mode rejects the `tool_choice` parameter outright; tool
|
||||||
|
# calls still work and default to auto when tools are present.
|
||||||
|
supportsToolChoice: false
|
||||||
|
# V4 has no `developer` role.
|
||||||
|
supportsDeveloperRole: false
|
||||||
|
# Reasoning arrives in `reasoning_content`; the harness's default for a
|
||||||
|
# direct DeepSeek provider is `zai-thinking-disabled` (an explicit
|
||||||
|
# `thinking: {"type":"disabled"}`), which is what this endpoint
|
||||||
|
# honours — `reasoning_effort: "none"` is not accepted here. Left unset
|
||||||
|
# so the built-in default stays in charge rather than a guess.
|
||||||
|
reasoningContentField: "reasoning_content"
|
||||||
|
# The documented request enables thinking with the `thinking` toggle
|
||||||
|
# AND `reasoning_effort`; when thinking is on, the harness strips the
|
||||||
|
# toggle from extraBody and keeps the effort value, so the request
|
||||||
|
# carries what the endpoint expects.
|
||||||
|
# Card-recommended sampler: temperature 1.0, top_p 1.0 (in thinking
|
||||||
|
# mode the API floors top_p at 0.95 — 1.0 is inside the allowed set).
|
||||||
|
# top_k is not accepted through the OpenAI surface, so it is not sent.
|
||||||
|
# extraBody is merged last and wins, so pinning the trio survives a
|
||||||
|
# server-side sampler edit — same law as the LAN rows.
|
||||||
|
extraBody:
|
||||||
|
thinking:
|
||||||
|
type: enabled
|
||||||
|
temperature: 1.0
|
||||||
|
top_p: 1.0
|
||||||
|
# `max_tokens` is the field this API speaks (not
|
||||||
|
# max_completion_tokens) — set by the built-in default, and this row
|
||||||
|
# cannot mis-name it because it names no override of its own.
|
||||||
|
|
||||||
# ─── WAN door ───────────────────────────────────────────────────────────
|
# ─── WAN door ───────────────────────────────────────────────────────────
|
||||||
# The only block in this file that answers OFF the home network. Every
|
# The fleet's own off-network door. Since 2026-10-29 the `deepseek` block
|
||||||
# provider above is a LAN IP, and `modelRoles` (config.yml) still points at
|
# above is also reachable from anywhere (a vendor URL, not a LAN IP), but it
|
||||||
# those, so away from home you must NAME one of the rows below:
|
# is not this door: this block is the route back to FRANK'S engines. Every
|
||||||
|
# fleet provider here is a LAN address, and `modelRoles` (config.yml) still
|
||||||
|
# points at those, so away from home you must NAME one of the rows below:
|
||||||
# omp --model 'openwebui (franksdank.cloud)/frank-dragoon:medium'
|
# omp --model 'openwebui (franksdank.cloud)/frank-dragoon:medium'
|
||||||
# The door is the OpenWebUI vhost `ai.franksdank.cloud` — Caddy → OWU on
|
# The door is the OpenWebUI vhost `ai.franksdank.cloud` — Caddy → OWU on
|
||||||
# Dankclaw:3005, Anubis-exempt because OWU enforces its own auth, public A
|
# Dankclaw:3005, Anubis-exempt because OWU enforces its own auth, public A
|
||||||
|
|||||||
@@ -0,0 +1,127 @@
|
|||||||
|
---
|
||||||
|
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.
|
||||||
@@ -16,6 +16,7 @@ These files define the structural conventions that govern the agent system itsel
|
|||||||
* [OMP Status Line Customization](statusline.md) — How presets, composer shapes, and segment arrays actually interact; the fleet's tuned bar. (moved from /pi/, 2026-10-19)
|
* [OMP Status Line Customization](statusline.md) — How presets, composer shapes, and segment arrays actually interact; the fleet's tuned bar. (moved from /pi/, 2026-10-19)
|
||||||
* [OMP Subagent Limits & Fan-out Policy](subagent-limits.md) — Live caps: concurrency 2, no nested spawns (the `maxRecursionDepth: 0` trap), per-endpoint in-flight ceilings, isolation policy. (moved from /pi/, 2026-10-19)
|
* [OMP Subagent Limits & Fan-out Policy](subagent-limits.md) — Live caps: concurrency 2, no nested spawns (the `maxRecursionDepth: 0` trap), per-endpoint in-flight ceilings, isolation policy. (moved from /pi/, 2026-10-19)
|
||||||
* [WAN Model Access](wan-model-access.md) — Driving the fleet's models from outside the home network through the OpenWebUI door: the command, the key file and its rotation law, what the door publishes, and the off-network failure modes.
|
* [WAN Model Access](wan-model-access.md) — Driving the fleet's models from outside the home network through the OpenWebUI door: the command, the key file and its rotation law, what the door publishes, and the off-network failure modes.
|
||||||
|
* [DeepSeek Platform Provider](deepseek-provider.md) — The first vendor-cloud row in `agent/models.yml`: why its label is the bare word `deepseek`, the key file, and the window/maxTokens/cost values it declares.
|
||||||
* [OMP Snapcompact — Bitmap-Frame Compaction](snapcompact.md) — What shape frank-archon actually reads, the measured recall/billing table, the `imageCountBudget` knob and the pricing that isn't, and the 85 % trigger law.
|
* [OMP Snapcompact — Bitmap-Frame Compaction](snapcompact.md) — What shape frank-archon actually reads, the measured recall/billing table, the `imageCountBudget` knob and the pricing that isn't, and the 85 % trigger law.
|
||||||
|
|
||||||
**Change log:** the bundle keeps exactly one, one level up — [Bundle Change Log](../log.md). A directory here never has its own.
|
**Change log:** the bundle keeps exactly one, one level up — [Bundle Change Log](../log.md). A directory here never has its own.
|
||||||
@@ -22,6 +22,23 @@ not restated here — entry, then pointer. That is what the 2026-10-21 audit pas
|
|||||||
newest twelve entries: the facts stayed, the duplicates went, `git log --follow` keeps the
|
newest twelve entries: the facts stayed, the duplicates went, `git log --follow` keeps the
|
||||||
long form.
|
long form.
|
||||||
|
|
||||||
|
## 2026-10-29
|
||||||
|
|
||||||
|
### A vendor-cloud provider must be named the way the harness names it
|
||||||
|
|
||||||
|
`deepseek` / `deepseek-flash` joins `agent/models.yml` — Frank's DeepSeek platform
|
||||||
|
key in `~/.config/secrets/deepseek_api_key` (600, `!cat`-backed), a 1M/262K row,
|
||||||
|
the documented compat block. The label breaks the house `<api> (<host>)` pattern on
|
||||||
|
purpose: the catalog's host table (`pi-catalog/src/hosts.ts`) keys the
|
||||||
|
direct-DeepSeek behaviour set off the literal name `deepseek` (or an
|
||||||
|
`api.deepseek.com` URL), so a prettier label silently loses the quirks that make
|
||||||
|
the endpoint answer — the `max_tokens` field, the thinking `extraBody`, and the
|
||||||
|
thinking-disable mode this API takes. Law: **a provider label is a lookup key, not
|
||||||
|
only a display name**; check the table before inventing one, and prove the row with
|
||||||
|
a scratch-HOME call (a poisoned-port control is what separates a real auth success
|
||||||
|
from a cached one). Page: [core/deepseek-provider.md](core/deepseek-provider.md).
|
||||||
|
|
||||||
|
|
||||||
## 2026-10-27
|
## 2026-10-27
|
||||||
|
|
||||||
### Snapcompact audited against frank-archon; the blind frame price is the real limit
|
### Snapcompact audited against frank-archon; the blind frame price is the real limit
|
||||||
|
|||||||
Reference in new issue
Block a user