When a relay's model is not recognized by address, the metadata lookup
falls back to the vendor's entry: first the entry that same-name entries
point at via canonical_model_id, and only if none resolves, an entry
listed under a provider that some canonical id points at.
That last step only checked whether the provider counts as a vendor, not
whether the entry claims to be its own. models.dev has no
deepseek/deepseek-v4.1-flash-1017, so the ~40 entries pointing there all
miss, and thinkingmachines (counted as a vendor for its own models) won
with its LoRA fine-tuning entry DeepSeek-V4.1-Flash-1017:peft:262144,
whose canonical id points back at deepseek. It is text-only with a 262144
window, so picking the model filled every app with text-only input and a
quarter of the real window; Codex additionally turned image input off.
Skip entries whose canonical id names another vendor in that fallback.
Against the current models.dev data, 27 ids stop borrowing from hosts of
other vendors' models (thinkingmachines, NVIDIA, vivgrid, alibaba) and
leave the fields empty instead, and laguna-xs-2.1 now resolves to
poolside's own entry rather than being ambiguous. Skipping ':' variants
instead was rejected: it fixes this id but newly resolves nine
thinkingmachines entries carrying 65K training windows (gpt-oss-120b and
others).
Refs #8765, #8682
models.dev moved OpenCode Zen and Go to /inference/... endpoints, while
presets and existing providers still use /zen/... (both work and bill
the same). The endpoint lookup no longer found them, so models only
listed there, such as deepseek-v4.1-flash, filled nothing. Map the old
normalized addresses to the new ones; this applies to every app's fill.
The 272K GPT cap (v4.0.13) applied to every window the metadata lookup
returned, so platforms that really serve the 1.05M OpenAI API window
(OpenRouter and other providers models.dev recognizes by address) were
capped too. The risk the cap guards against is narrower: a relay that
models.dev does not know falls back to the vendor's own entry, and its
1.05M lands on a model that is often served from a ChatGPT subscription
with a 272K window.
- Same-endpoint presets and the models.dev provider matched by address
keep their own windows; only the window borrowed from the vendor entry
(including when the matched provider lists none) is capped at 272K.
- A window the user types is kept as is. When a GPT model's window is
above 272K, the Codex, Hermes, OpenClaw, OpenCode and Pi forms show a
note under the field: relay GPT usually has the subscription window, and
an oversized one delays compaction until the upstream rejects the turn.
Text added in zh / en / ja / zh-TW.
Existing rows are not migrated. Codex GPT rows saved before v4.0.13 with
an auto-filled 1.05M now take effect since #8385; the note shows when the
form is opened.
models.dev lists the OpenAI API window for GPT models (1.05M for the
GPT-5.6 and GPT-6 families), but many relays serve GPT through ChatGPT
subscriptions, whose Codex backend catalogs these models at 272K. The
base URL cannot tell the two apart. An overstated window keeps clients
from compacting until the upstream rejects the prompt and the turn
fails, while an understated one only compacts earlier.
- Cap every GPT window resolveModelMetadata returns at 272K, whether it
comes from a preset, the recognized models.dev provider or the vendor
fallback; smaller windows such as gpt-4o's are left alone
- Lower the GPT windows in the Hermes, OpenClaw, OpenCode, Pi and Codex
presets to the same cap, with a test guarding every preset source
- Pin the Claude Code ChatGPT subscription preset's context and
auto-compact windows to 272K; the 372K it used was the backend's
mid-2026 value and now sits above the backend's limit
A vendor that also hosts other vendors' models (NVIDIA lists
minimaxai/minimax-m2.7 without a canonical id) was counted as a second
vendor next to the entry relays point at, so the fallback gave up and
models like MiniMax-M2.7, gpt-5.4 and kimi-k2.6 got no metadata through
unrecognized relays. Use the entries relays point at first and only fall
back to a vendor's own entry when nothing points anywhere.
Without a thinking map, Pi shows off..high for a custom model and hides
xhigh and max, even when the upstream supports them. When a fetched
model is picked and has no map yet, fill one:
- Use the reviewed map of the Pi preset at the same endpoint, but only
under the same API and when the compat it relies on does not conflict
with what the user wrote. Missing compat keys are added to the model,
and for openai-completions the thinking format and reasoning_effort
support that Pi detects must match the preset's.
- Otherwise, when Pi sends levels verbatim as reasoning_effort
(openai-responses, or openai-completions detected as the OpenAI
thinking format), derive the map from models.dev effort levels using
Pi's own getEffortThinkingLevelMap rule.
A model with its own baseUrl is now looked up by that address. Update
the Pi design docs accordingly.
A provider's /models endpoint only returns model IDs, so a model picked
from the fetched list left its context window, output limit, reasoning
levels, and modalities empty, while the same model in a preset had them.
When a model is picked in the Codex, OpenClaw, Hermes, OpenCode, or
MiniMax Code form, look up its metadata field by field:
1. the preset model with the same endpoint (hand-verified values);
2. the models.dev provider whose API endpoint matches;
3. the vendor's own models.dev entry, without its price.
Endpoints match only when host and path are equal after dropping a
trailing version segment or request path, so plans that share a host
(z.ai standard vs Coding Plan, OpenCode Zen vs Go) never borrow each
other's values. Models are never matched by name across providers: the
same model ID often has very different context windows per deployment.
Only empty fields are filled, and reasoning or image input is only ever
turned on. models.dev is prefetched once the model list is fetched and
shared with the usage pricing import; when it arrives late the row is
filled again, located by its stable row key. A single toast asks the
user to review what was filled.