| 1 | # Model & Provider Metadata Audit |
| 2 | |
| 3 | Audit date: **2026-07-12** · Repo state: `main` @ `3e97b278e` (v0.8.68 lane) |
| 4 | Scope: every provider and model CodeWhale knows about, their characteristics |
| 5 | (context window, max output, reasoning, tools, modalities, pricing, aliases), |
| 6 | where each fact lives in code, how the metadata layers interact, and every |
| 7 | discrepancy found against the live Models.dev catalog. Intended as the working |
| 8 | reference for a future metadata-consolidation pass. |
| 9 | |
| 10 | --- |
| 11 | |
| 12 | ## 1. Executive summary |
| 13 | |
| 14 | 1. **The "gpt-5.6-luna 272K" display is correct by design, not a data bug.** |
| 15 | On the ChatGPT/Codex OAuth route, CodeWhale shows the context window that |
| 16 | OpenAI's account-scoped `/models` endpoint advertises (persisted by the |
| 17 | Codex CLI at `~/.codex/models_cache.json`). That cache on this machine |
| 18 | (fetched 2026-07-13) advertises `context_window: 272000` for **all** |
| 19 | gpt-5.x OAuth models (gpt-5.5, gpt-5.6-sol/terra/luna, gpt-5.4, |
| 20 | gpt-5.4-mini; gpt-5.3-codex-spark is 128000). The public **API** route for |
| 21 | the same model ids is 1,050,000 (922,000 input + 128,000 output). The |
| 22 | deliberate policy — documented in `route_runtime.rs:33-51` and pinned by |
| 23 | the test `same_model_id_uses_route_effective_api_and_oauth_metadata` |
| 24 | (`model_picker.rs:1660-1706`) — is to never let the OAuth route inherit |
| 25 | the API route's bigger window, output cap, or pricing. |
| 26 | **Possible UX follow-up (see §8, A1):** label the value as the OAuth-route |
| 27 | window (e.g. "272K ctx (ChatGPT route)") so it doesn't read as wrong data. |
| 28 | |
| 29 | 2. **Metadata is spread across seven layers** (see §2). The precedence is |
| 30 | well-defined and test-guarded, but the *facts* are duplicated in at least |
| 31 | four hand-maintained places (`models.rs`, `model_catalog.bundled.json`, |
| 32 | `pricing.rs`, `models_dev.bundled.json`), which is where drift creeps in. |
| 33 | |
| 34 | 3. **Real drift found** against the live Models.dev catalog — 14 candidate |
| 35 | mismatches (§7), the most defensible being GLM window (202,752 vs |
| 36 | vendor 200,000), Qwen3.6-27b/35b output caps (we say 262,140; Alibaba says |
| 37 | 65,536), Grok 4.20 window (we say 2M; xAI catalog row says 1M), and |
| 38 | MiniMax-M2 (we say 204,800; catalog says 196,608). |
| 39 | |
| 40 | --- |
| 41 | |
| 42 | ## 2. Metadata architecture — layers and precedence |
| 43 | |
| 44 | Effective precedence for model facts (context/output/reasoning/pricing), |
| 45 | lowest → highest, confirmed from `crates/config/src/catalog.rs:9-18`, |
| 46 | `CatalogCompiler::compile` (`catalog.rs:582-641`) and |
| 47 | `crates/tui/src/provider_lake.rs:54-142`: |
| 48 | |
| 49 | ``` |
| 50 | (5) legacy static completion lists (DEFAULT_* consts) ← only if catalog has zero rows for provider |
| 51 | (4) static code tables crates/tui/src/models.rs ← fallback inside context_window_for_model() |
| 52 | (3) bundled Models.dev seed crates/config/assets/models_dev.bundled.json ("NOT a competing source of truth", #4188) |
| 53 | + bundled TUI catalog crates/tui/assets/model_catalog.bundled.json (31 entries) |
| 54 | (2) live Models.dev catalog https://models.dev/catalog.json → ~/.codewhale/catalog/models-dev-catalog.json (24 h TTL) |
| 55 | (1) user / custom overrides (pinned models, custom endpoints, explicit facts) |
| 56 | (0) SPECIAL: ChatGPT/Codex OAuth roster ~/.codex/models_cache.json — bypasses the catalog entirely |
| 57 | for ApiProvider::OpenaiCodex (provider_lake.rs:131-133, route_runtime.rs:33-51) |
| 58 | ``` |
| 59 | |
| 60 | Key components: |
| 61 | |
| 62 | | Component | File | Role | |
| 63 | |---|---|---| |
| 64 | | `ProviderLake` | `crates/tui/src/provider_lake.rs` | Single facade; merges live-over-bundled keyed on `(provider, wire_model_id)`; legacy fallback at `:138-142` | |
| 65 | | Models.dev live fetch | `crates/tui/src/models_dev_live.rs` | Background refresh, 24 h TTL, 15 s timeout, atomic disk cache; env knobs `CODEWHALE_MODELS_DEV_URL` / `_PATH` / `CODEWHALE_DISABLE_MODELS_DEV_FETCH` | |
| 66 | | Catalog compiler + provenance | `crates/config/src/catalog.rs` | `CatalogSource::{Bundled, Live, UserOverride}`; normalizes Models.dev ids (`moonshotai`→`moonshot`, `togetherai`→`together`, `zhipuai`→`zai`) | |
| 67 | | Models.dev schema | `crates/config/src/models_dev.rs` | Network-free deserialization of `{models, providers}` | |
| 68 | | Static fact tables | `crates/tui/src/models.rs` | `context_window_for_model` / `max_output_tokens_for_model` / `model_supports_reasoning`; catalog checked first, then explicit `_Nk` suffix hint, then vendor heuristics | |
| 69 | | Seeded registry | `crates/tui/src/model_registry.rs` | `ModelMetadata` keyed by id, seeded *from* `models.rs` (drift-guarded by tests); intended future single source | |
| 70 | | Pricing | `crates/tui/src/pricing.rs` | Hand-curated USD (+CNY for DeepSeek) rows; catalog USD pricing used when no explicit row | |
| 71 | | Codex OAuth roster | `crates/tui/src/codex_model_cache.rs` | Read-only parse of `~/.codex/models_cache.json`; trusted only when fresh (<24 h), else conservative fallback with `context_window: None` (compat floor 128,000: `config/models.rs:126`) | |
| 72 | | Agent-crate registry | `crates/agent/src/lib.rs` | 93 `ModelInfo` rows (model×provider), aliases, tools/reasoning flags, resolution fallback chain | |
| 73 | |
| 74 | Fallback heuristics in `models.rs` when nothing above matches: |
| 75 | explicit `_Nk` name suffix (8k–1024k) → DeepSeek family (v4 → 1M, legacy → |
| 76 | 128K) → GPT-5.5/5.6 API → 1.05M → Codex family → 400K → known-model table → |
| 77 | any "claude" → 200K → `None` (compaction default threshold 102,400). |
| 78 | |
| 79 | --- |
| 80 | |
| 81 | ## 3. Provider inventory (33 built-in + 1 legacy alias) |
| 82 | |
| 83 | Source: `crates/config/src/provider.rs` (`PROVIDER_REGISTRY`, 33 descriptors), |
| 84 | `provider_kind.rs`, `provider_defaults.rs`. Dialect = `WireFormat` |
| 85 | (`provider.rs:33`): CC = OpenAI Chat Completions, RESP = OpenAI Responses, |
| 86 | AM = Anthropic Messages. |
| 87 | |
| 88 | | id | Display | Default base URL | Default model | Auth (env vars) | Dialect | |
| 89 | |---|---|---|---|---|---| |
| 90 | | `deepseek` | DeepSeek | `https://api.deepseek.com/beta` | `deepseek-v4-pro` | `DEEPSEEK_API_KEY` | CC | |
| 91 | | `deepseek-anthropic` | DeepSeek (Anthropic-compatible) | `https://api.deepseek.com/anthropic` | `deepseek-v4-pro` | `DEEPSEEK_API_KEY` | AM | |
| 92 | | `deepseek-cn` *(TUI-only legacy alias)* | DeepSeek (legacy alias) | own config table | — | shares `DEEPSEEK_API_KEY` | CC | |
| 93 | | `nvidia-nim` | NVIDIA NIM | `https://integrate.api.nvidia.com/v1` | `deepseek-ai/deepseek-v4-pro` | `NVIDIA_API_KEY`, `NVIDIA_NIM_API_KEY`, `DEEPSEEK_API_KEY` | CC | |
| 94 | | `openai` | OpenAI-compatible | `https://api.openai.com/v1` | `deepseek-v4-pro` | `OPENAI_API_KEY` | CC | |
| 95 | | `openai-codex` | OpenAI Codex (ChatGPT) | `https://chatgpt.com/backend-api` | `gpt-5.5` | OAuth (`~/.codex/auth.json`) or `OPENAI_CODEX_ACCESS_TOKEN`/`CODEX_ACCESS_TOKEN` | RESP | |
| 96 | | `anthropic` | Anthropic | `https://api.anthropic.com` | `claude-sonnet-4-6` | `ANTHROPIC_API_KEY` (no subscription OAuth) | AM | |
| 97 | | `atlascloud` | AtlasCloud | `https://api.atlascloud.ai/v1` | `deepseek-ai/deepseek-v4-flash` | `ATLASCLOUD_API_KEY` | CC | |
| 98 | | `wanjie-ark` | Wanjie Ark | `https://maas-openapi.wanjiedata.com/api/v1` | `deepseek-reasoner` | `WANJIE_ARK_API_KEY`, `WANJIE_API_KEY`, `WANJIE_MAAS_API_KEY` | CC | |
| 99 | | `volcengine` | Volcengine Ark | `https://ark.cn-beijing.volces.com/api/coding/v3` | `DeepSeek-V4-Pro` | `VOLCENGINE_API_KEY`, `VOLCENGINE_ARK_API_KEY`, `ARK_API_KEY` | CC | |
| 100 | | `openrouter` | OpenRouter | `https://openrouter.ai/api/v1` | `deepseek/deepseek-v4-pro` | `OPENROUTER_API_KEY` | CC | |
| 101 | | `xiaomi-mimo` | Xiaomi MiMo | `https://token-plan-sgp.xiaomimimo.com/v1` (regional cn/sgp/ams + PAYG `api.xiaomimimo.com`) | `mimo-v2.5-pro` | `XIAOMI_MIMO_TOKEN_PLAN_API_KEY`, `MIMO_TOKEN_PLAN_API_KEY`, `XIAOMI_MIMO_API_KEY`, `XIAOMI_API_KEY`, `MIMO_API_KEY` | CC | |
| 102 | | `novita` | Novita AI | `https://api.novita.ai/openai/v1` | `deepseek/deepseek-v4-pro` | `NOVITA_API_KEY` | CC | |
| 103 | | `fireworks` | Fireworks AI | `https://api.fireworks.ai/inference/v1` | `accounts/fireworks/models/deepseek-v4-pro` | `FIREWORKS_API_KEY` | CC | |
| 104 | | `siliconflow` | SiliconFlow | `https://api.siliconflow.com/v1` | `deepseek-ai/DeepSeek-V4-Pro` | `SILICONFLOW_API_KEY` | CC | |
| 105 | | `siliconflow-CN` | SiliconFlow (China) | `https://api.siliconflow.cn/v1` | `deepseek-ai/DeepSeek-V4-Pro` | `SILICONFLOW_API_KEY` | CC | |
| 106 | | `arcee` | Arcee AI | `https://api.arcee.ai/api/v1` | `trinity-large-thinking` | `ARCEE_API_KEY` | CC | |
| 107 | | `moonshot` | Moonshot/Kimi | `https://api.moonshot.ai/v1` (Kimi-for-coding: `https://api.kimi.com/coding/v1`) | `kimi-k2.7-code` | `MOONSHOT_API_KEY`, `KIMI_API_KEY`, or Kimi OAuth | CC | |
| 108 | | `sglang` | SGLang (self-hosted) | `http://localhost:30000/v1` | `deepseek-ai/DeepSeek-V4-Pro` | `SGLANG_API_KEY` | CC | |
| 109 | | `vllm` | vLLM (self-hosted) | `http://localhost:8000/v1` | `deepseek-ai/DeepSeek-V4-Pro` | `VLLM_API_KEY` | CC | |
| 110 | | `ollama` | Ollama (local) | `http://localhost:11434/v1` | `deepseek-v4-flash` | `OLLAMA_API_KEY` | CC | |
| 111 | | `huggingface` | Hugging Face | `https://router.huggingface.co/v1` | `deepseek-ai/DeepSeek-V4-Pro` | `HUGGINGFACE_API_KEY`, `HF_TOKEN` | CC | |
| 112 | | `together` | Together AI | `https://api.together.xyz/v1` | `deepseek-ai/DeepSeek-V4-Pro` | `TOGETHER_API_KEY` | CC | |
| 113 | | `qianfan` | Baidu Qianfan | `https://api.baiduqianfan.ai/v1` | `ernie-4.0-turbo-8k` | `QIANFAN_API_KEY`, `BAIDU_QIANFAN_API_KEY` | CC | |
| 114 | | `openmodel` | OpenModel | `https://api.openmodel.ai` | `deepseek-v4-flash` | `OPENMODEL_API_KEY` | AM | |
| 115 | | `zai` | Zhipu AI / Z.ai | `https://api.z.ai/api/coding/paas/v4` | `GLM-5.2` | `ZAI_API_KEY`, `Z_AI_API_KEY`, `ZHIPU_API_KEY`, `GLM_API_KEY` | CC | |
| 116 | | `stepfun` | StepFun / StepFlash | `https://api.stepfun.ai/v1` | `step-3.7-flash` | `STEPFUN_API_KEY`, `STEP_API_KEY` | CC | |
| 117 | | `minimax` | MiniMax | `https://api.minimax.io/v1` | `MiniMax-M3` | `MINIMAX_API_KEY` | CC | |
| 118 | | `deepinfra` | DeepInfra | `https://api.deepinfra.com/v1/openai` | `deepseek-ai/DeepSeek-V4-Pro` | `DEEPINFRA_API_KEY`, `DEEPINFRA_TOKEN` | CC | |
| 119 | | `sakana` | Sakana AI (Fugu) | `https://api.sakana.ai/v1` | `fugu` | `FUGU_API_KEY`, `SAKANA_API_KEY` | CC | |
| 120 | | `longcat` | Meituan LongCat | `https://api.longcat.chat/openai/v1` | `LongCat-2.0` | `LONGCAT_API_KEY` | CC | |
| 121 | | `meta` | Meta Model API | `https://api.meta.ai/v1` | `muse-spark-1.1` | `META_MODEL_API_KEY`, `MODEL_API_KEY` | CC | |
| 122 | | `xai` | xAI | `https://api.x.ai/v1` | `grok-4.5` | `XAI_API_KEY` or Grok OAuth (`~/.grok/auth.json`) | CC | |
| 123 | | `custom` | Custom (OpenAI-compatible) | per `[providers.<name>]` table | per table | per-entry `api_key_env` | CC | |
| 124 | |
| 125 | OAuth routes (token precedence: route OAuth → CLI key → provider/root config |
| 126 | → ambient env; `crates/tui/src/config.rs:3494-3566`): |
| 127 | |
| 128 | - **OpenAI Codex/ChatGPT** — Codex CLI login (`~/.codex/auth.json`); |
| 129 | account-scoped model roster from `~/.codex/models_cache.json`; usage is |
| 130 | subscription-scoped so **no dollar pricing is shown** on this route |
| 131 | (`pricing.rs:127-129, 334-338`). |
| 132 | - **xAI Grok** — `[providers.xai] auth_mode = "oauth"`, reuses `~/.grok/auth.json` |
| 133 | or device-code login. |
| 134 | - **Moonshot/Kimi** — Kimi CLI OAuth for the coding endpoint. |
| 135 | - **No Anthropic/Claude subscription OAuth exists** — API key only. |
| 136 | |
| 137 | --- |
| 138 | |
| 139 | ## 4. First-class model metadata (the curated set) |
| 140 | |
| 141 | Merged view of the four fact sources for the models CodeWhale makes explicit |
| 142 | promises about. Columns: **Ctx** = context window (tokens), **Out** = max |
| 143 | output, **R** = emits reasoning, pricing = USD per 1M tokens as |
| 144 | **cache-hit / input / output** from `pricing.rs` (catalog rows have no |
| 145 | cache-hit discount → hit = input). |
| 146 | |
| 147 | ### 4.1 DeepSeek (first-class) |
| 148 | |
| 149 | | Model | Ctx | Out | R | Pricing (hit/in/out USD) | Notes | |
| 150 | |---|---|---|---|---|---| |
| 151 | | `deepseek-v4-pro` | 1,000,000 | 384,000 | ✓ | 0.003625 / 0.435 / 0.87 (+CNY 0.025/3/6) | post-2026-05-31 adjusted rate is permanent (#2489) | |
| 152 | | `deepseek-v4-flash` | 1,000,000 | 384,000 | ✓ | 0.0028 / 0.14 / 0.28 (+CNY 0.02/1/2) | | |
| 153 | | `deepseek-reasoner`, legacy v3.x, `deepseek-coder*` | 128,000 | — | v4-only | flash rates for non-pro | legacy fallback window (`models.rs:7`) | |
| 154 | | `deepseek-ai/*` (NIM-hosted) | 1,000,000 | 384,000 | ✓ | **intentionally unpriced** | NVIDIA terms ≠ DeepSeek platform pricing (`pricing.rs:133-137`) | |
| 155 | | any id with `-Nk` suffix | N×1000 | — | — | — | vendor-agnostic served-name hint, 8k–1024k | |
| 156 | |
| 157 | ### 4.2 OpenAI |
| 158 | |
| 159 | | Model | Ctx (API route) | Ctx (OAuth route) | Out | R | Pricing (hit/in/out) | Notes | |
| 160 | |---|---|---|---|---|---|---| |
| 161 | | `gpt-5.6` (alias → sol) | 1,050,000 | 272,000¹ | 128,000 | ✓ | 0.50 / 5.00 / 30.00 | Models.dev: input limit 922,000 | |
| 162 | | `gpt-5.6-sol` | 1,050,000 | 272,000¹ | 128,000 | ✓ | 0.50 / 5.00 / 30.00 | efforts low→ultra on OAuth | |
| 163 | | `gpt-5.6-terra` | 1,050,000 | 272,000¹ | 128,000 | ✓ | 0.25 / 2.50 / 15.00 | | |
| 164 | | `gpt-5.6-luna` | 1,050,000 | 272,000¹ | 128,000 | ✓ | 0.10 / 1.00 / 6.00 | cost-efficient tier; **the "272k looks wrong" report — see §6** | |
| 165 | | `gpt-5.5` | 1,050,000 | 272,000¹ | 128,000 | ✓ | 0.50 / 5.00 / 30.00 | date snapshots (`gpt-5.5-YYYY-MM-DD`) too | |
| 166 | | `gpt-5.5-pro` | 1,050,000 | n/a | 128,000 | ✓ | 30.00 / 30.00 / 180.00 | no cached-input discount | |
| 167 | | `gpt-5-codex` | 400,000 | per roster | 128,000 | ✓ | 0.125 / 1.25 / 10.00 | deprecated upstream on OAuth path | |
| 168 | | `gpt-5.3-codex` | 400,000 | per roster | 128,000 | ✓ | 0.175 / 1.75 / 14.00 | | |
| 169 | | other codex ids (`gpt-5.1-codex[-mini/-max]`, `gpt-5.2-codex`, `codex-gpt-5.5`, `chatgpt-gpt-5.5`, `gpt-5.5-codex[-preview]`…) | 400,000 | per roster | 128,000 | ✓ | unpriced | recognized by `is_openai_codex_model` (`models.rs:491-507`) | |
| 170 | | `gpt-5.5-nano` | *unknown* | *unknown* | — | ✗ | — | deliberately unrecognized (`models.rs:788-790`) | |
| 171 | |
| 172 | ¹ OAuth window is whatever `~/.codex/models_cache.json` advertises for the |
| 173 | account; on this machine (2026-07-13) it is 272,000 for all gpt-5.x list |
| 174 | models and 128,000 for `gpt-5.3-codex-spark`. Stale/missing cache → no ctx |
| 175 | shown in picker; runtime compat floor 128,000. OAuth route never shows pricing. |
| 176 | |
| 177 | ### 4.3 Anthropic |
| 178 | |
| 179 | | Model | Ctx | Out | R | Pricing (hit/in/out) | Notes | |
| 180 | |---|---|---|---|---|---| |
| 181 | | `claude-opus-4-8` | 1,000,000 | 128,000 | ✓ | 0.50 / 5.00 / 25.00 | | |
| 182 | | `claude-sonnet-4-6` | 1,000,000 | 128,000 | ✓ | 0.30 / 3.00 / 15.00 | out raised 64K→128K (2026-07-09 audit) | |
| 183 | | `claude-sonnet-5` | 1,000,000 | 128,000 | ✓ | intro 0.20/2.00/10.00 until 2026-08-31, then 0.30/3.00/15.00 | time-aware in `pricing.rs:263-273` | |
| 184 | | `claude-fable-5` | 1,000,000 | 128,000 | ✓ | 1.00 / 10.00 / 50.00 | tokenizer yields ~30% more tokens — raw rate comparisons undercount cost (`pricing.rs:178-182`) | |
| 185 | | `claude-haiku-4-5` | 200,000 | 64,000 | ✗ | 0.10 / 1.00 / 5.00 | | |
| 186 | | any other `claude*` | 200,000 | — | ✗ | — | family fallback | |
| 187 | |
| 188 | ### 4.4 Moonshot / Kimi |
| 189 | |
| 190 | | Model | Ctx | Out | R | Pricing | Notes | |
| 191 | |---|---|---|---|---|---| |
| 192 | | `kimi-k2.7-code` (± `moonshotai/`) | 262,144 | 262,144 | ✓ | 0.19 / 0.95 / 4.00 | | |
| 193 | | `kimi-k2.6` (± prefix, `:free`) | 262,144 | 262,144 | ✓ | 0.16 / 0.95 / 4.00 | | |
| 194 | | `kimi-for-coding` | 262,144 | 262,144 | ✓ | — | stable coding route; rides K2.7 path; **not in agent-crate registry or catalogs** (§7 D-12) | |
| 195 | | any bare `kimi-*` | — | — | ✓ | — | prefix rule: always reasoning (#3016) | |
| 196 | |
| 197 | ### 4.5 Z.ai / GLM |
| 198 | |
| 199 | | Model | Ctx | Out | R | Pricing | Notes | |
| 200 | |---|---|---|---|---|---| |
| 201 | | `glm-5.2` (± `z-ai/`) | 1,000,000 | 131,072 | ✓ | 0.26 / 1.40 / 4.40 | | |
| 202 | | `glm-5.3` (± `z-ai/`) | 1,000,000 | 131,072 | ✓ | | **not released by Z.ai as of 2026-08-03** — registered id only; limits/reasoning inherited wholesale from `glm-5.2` pending official Z.ai release metadata, not measured; no published price | |
| 203 | | `glm-5.1` (± `z-ai/`) | 202,752 | 131,072 | ✓ | 0.26 / 1.40 / 4.40 | vendor page says 200K (§7 D-4) | |
| 204 | | `glm-5-turbo` (± `z-ai/`) | 202,752 | 131,072 | ✓ | 0.24 / 1.20 / 4.00 | fast **text** sibling | |
| 205 | | `glm-5v-turbo` (± `z-ai/`) | 202,752 | — | ✗ | — | **vision** model, distinct from 5-turbo | |
| 206 | |
| 207 | ### 4.6 MiniMax |
| 208 | |
| 209 | | Model | Ctx | Out | R | Pricing | Notes | |
| 210 | |---|---|---|---|---|---| |
| 211 | | `minimax-m3` (± `minimax/`, `MiniMax-M3`) | 1,000,000 | 524,288 | ✓ | 0.06 / 0.30 / 1.20 | catalog says out 128,000 (§7 D-5) | |
| 212 | | `minimax-m2.7` (± prefix, `-highspeed`) | 204,800 | 131,072 (catalog) | ✓ | 0.3 / 0.3 / 1.2 (catalog) | | |
| 213 | | `minimax-m2.5` / `m2.1` (± `-highspeed`) | 204,800 | — | ✓ | — | | |
| 214 | | `minimax-m2` | 204,800 | — | ✓ | — | catalog says 196,608 (§7 D-6) | |
| 215 | |
| 216 | ### 4.7 Qwen (OpenRouter-routed) |
| 217 | |
| 218 | | Model | Ctx | Out | R | Pricing | Notes | |
| 219 | |---|---|---|---|---|---| |
| 220 | | `qwen/qwen3.6-flash` | 1,000,000 | 65,536 | ✓ | 0.1875 / 0.1875 / 1.125 | | |
| 221 | | `qwen/qwen3.6-plus` | 1,000,000 | 65,536 | ✓ | 0.325 / 0.325 / 1.95 | | |
| 222 | | `qwen/qwen3.6-35b-a3b` | 262,144 | 262,140 | ✓ | 0.05 / 0.14 / 1.00 | out cap suspect (§7 D-7) | |
| 223 | | `qwen/qwen3.6-27b` | 262,144 | 262,140 | ✓ | 0.15 / 0.285 / 2.40 | out cap suspect (§7 D-7) | |
| 224 | | `qwen/qwen3.6-max-preview` | 262,144 | 65,536 | ✓ | 1.04 / 1.04 / 6.24 | catalog ctx 245,800 (§7 D-8) | |
| 225 | | `qwen/qwen3.7-plus` | — | — | — | 0.064 / 0.32 / 1.28 | **priced but no ctx/out/reasoning rows** (§7 D-13) | |
| 226 | | `qwen/qwen3.7-max` | — | — | — | 0.25 / 1.25 / 3.75 | in agent registry; same gap (§7 D-13) | |
| 227 | |
| 228 | ### 4.8 Xiaomi MiMo |
| 229 | |
| 230 | | Model | Ctx | Out | R | Pricing | Notes | |
| 231 | |---|---|---|---|---|---| |
| 232 | | `mimo-v2.5-pro` (± `xiaomi/`, `-ultraspeed`) | 1,000,000 | 131,072 | ✓ | intentionally unknown | Token-Plan credit billing, no balance endpoint | |
| 233 | | `mimo-v2.5` (± `xiaomi/`) | 1,000,000 | 131,072 | ✓ | unknown | omni (text+image) | |
| 234 | | `mimo-v2.5-asr` | 8,000 | 2,048 | ✗ | unknown | speech-to-text | |
| 235 | | `mimo-v2.5-tts[-voicedesign/-voiceclone]`, `mimo-v2-tts` | 8,000 | 8,192 | ✗ | unknown | TTS family | |
| 236 | |
| 237 | ### 4.9 xAI / Grok |
| 238 | |
| 239 | | Model | Ctx | Out | R | Pricing | Notes | |
| 240 | |---|---|---|---|---|---| |
| 241 | | `grok-4.5` | 500,000 | — | ✓ | — | | |
| 242 | | `grok-4.3` | 1,000,000 | — | ✓ | — | | |
| 243 | | `grok-build` | 512,000 | — | ✓ | — | not in Models.dev | |
| 244 | | `grok-composer-2.5-fast` | 200,000 | — | ✗ | — | not in Models.dev | |
| 245 | | `grok-4.20-0309-reasoning` / `-non-reasoning` | 2,000,000 | — | ✓/✗ | — | catalog row says 1M (§7 D-9); **no Grok pricing rows at all** (§7 D-14) | |
| 246 | |
| 247 | ### 4.10 Others |
| 248 | |
| 249 | | Model | Provider | Ctx | Out | R | Pricing | Notes | |
| 250 | |---|---|---|---|---|---|---| |
| 251 | | `trinity-large-thinking` (± `arcee-ai/`) | Arcee | 262,144 | 262,144 | ✓ | 0.25 / 0.25 / 0.80 | out=ctx suspect (§7 D-2) | |
| 252 | | `trinity-large-preview` | Arcee | 262,144 | — | ✗ | — | catalog row says 131,000 (§7 D-3) | |
| 253 | | `trinity-mini` | Arcee | 128,000 | 64,000 (bundled) | ✗ | 0.045 / 0.045 / 0.15 | catalog says ctx 131,072 (§7 D-1) | |
| 254 | | `step-3.7-flash` | StepFun | 256,000 | 256,000 | ✗ | 0.2 / 0.2 / 1.15 | third-party sourced (models.dev + AA) | |
| 255 | | `fugu` | Sakana | — | — | ✗ | — | in agent registry only | |
| 256 | | `fugu-ultra` / `fugu-ultra-20260615` | Sakana | 1,000,000 | 131,000 | ✓ | 5.0 / 5.0 / 30.0 | limits third-party sourced (Requesty); Sakana's own >272K price tier confirms ctx > 272K | |
| 257 | | `muse-spark-1.1` | Meta | 1,000,000 | 32,000 | ✓ | 1.25 / 1.25 / 4.25 | | |
| 258 | | `LongCat-2.0` | LongCat | — | — | ✓ | — | agent registry only; no fact rows (§7 D-15) | |
| 259 | | `tencent/hy3-preview` | OpenRouter | 262,144 | — | ✓ | 0.021 / 0.063 / 0.21 | catalog says 256,000 (§7 D-10) | |
| 260 | | `google/gemma-4-31b-it` (± `:free`) | OpenRouter | 262,144 | 16,384 (paid) / 32,768 (free) | ✓ | 0.09 / 0.12 / 0.35 | out cap vs catalog 131,072 (§7 D-11) | |
| 261 | | `google/gemma-4-26b-a4b-it` (± `:free`) | OpenRouter | 262,144 | 32,768 (free) | ✓ | 0.06 / 0.06 / 0.33 | | |
| 262 | | `nvidia/nemotron-3-ultra-550b-a55b` (± `:free`) | OpenRouter | 1,000,000 | 16,384 (paid) / 65,536 (free) | ✓ | 0.10 / 0.50 / 2.20 | catalog out 65,000 (§7 D-11) | |
| 263 | | `nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free` | OpenRouter | 262,144 | 65,536 | ✓ | — | | |
| 264 | | `ernie-4.0-turbo-8k` | Qianfan | 8,000 (via `-8k` hint) | — | ✗ | — | Qianfan default; no explicit rows | |
| 265 | |
| 266 | --- |
| 267 | |
| 268 | ## 5. Bundled TUI catalog (`crates/tui/assets/model_catalog.bundled.json`) |
| 269 | |
| 270 | 31 entries, `fetched_at: 2026-07-06`, effectively-infinite TTL. Adds |
| 271 | modalities and (for some rows) USD pricing on top of §4 facts. Highlights: |
| 272 | |
| 273 | - Modalities `text,image`: gpt-5.6 family, muse-spark-1.1, minimax-m3, mimo-v2.5. |
| 274 | - `text,image,audio`: mimo-v2.5-pro (the only audio-input row). |
| 275 | - `gpt-5.6` carries `provider_model_id: gpt-5.6-sol` (alias resolution). |
| 276 | - Pricing present only for: codex models, kimi-k2.7-code, glm-5.2, |
| 277 | minimax-m2.7, trinity-mini, claude family, step-3.7-flash, fugu-ultra. |
| 278 | - The bundled `models_dev.bundled.json` (config crate) is smaller: 2 models |
| 279 | (deepseek-v4-pro/flash), 14 providers, 42 chat offerings; demoted to |
| 280 | offline-fallback-only by #4188. |
| 281 | |
| 282 | ## 6. The gpt-5.6-luna 272K finding (root cause, resolved) |
| 283 | |
| 284 | - **What you saw:** model picker hint "272K ctx" for gpt-5.6-luna. |
| 285 | - **Where it comes from:** `~/.codex/models_cache.json` — the ChatGPT/Codex |
| 286 | OAuth `/models` roster persisted by the Codex CLI. On this machine every |
| 287 | gpt-5.x OAuth entry advertises `context_window: 272000`. |
| 288 | - **Why CodeWhale shows it:** for `ApiProvider::OpenaiCodex` the picker and |
| 289 | runtime use the OAuth-advertised window **exclusively** — never the API |
| 290 | route's 1,050,000 — because the OAuth offering genuinely has the smaller |
| 291 | window and different (subscription) billing. Precedence code: |
| 292 | `model_picker.rs:1105-1111`; runtime: `route_runtime.rs:33-51`; compaction |
| 293 | consumes it via `effective_context_window` (`compaction.rs:98-104`). |
| 294 | Pinned by tests (`model_picker.rs:1660-1706`, |
| 295 | `commands/groups/debug/tests.rs:96-111`). |
| 296 | - **Is 272,000 plausible?** Yes: 400,000 (codex-class window) − 128,000 |
| 297 | (output) = 272,000 usable input; OpenAI advertises the input budget as the |
| 298 | OAuth "context_window". The same-name API models are 1,050,000 total / |
| 299 | 922,000 input. |
| 300 | - **Verdict:** data is correct per route; the *presentation* invites the |
| 301 | "that looks wrong" reaction. See action A1. |
| 302 | |
| 303 | ## 7. Discrepancies & gaps (vs live Models.dev catalog, fetched 2026-07-12) |
| 304 | |
| 305 | Confidence key: **vendor** = the live row is the vendor's own provider entry |
| 306 | (strong signal); **aggregator** = row from a reseller (Vercel/OpenRouter etc., |
| 307 | weaker — verify against the vendor's docs before changing anything). |
| 308 | |
| 309 | | # | Model | CodeWhale says | Live catalog says | Source | Assessment | |
| 310 | |---|---|---|---|---|---| |
| 311 | | D-1 | `trinity-mini` | ctx 128,000 / out 64,000 (bundled) | 131,072 / 131,072 | aggregator | verify vs Arcee docs | |
| 312 | | D-2 | `trinity-large-thinking` | out 262,144 (= full ctx — suspicious) | ctx 262,100 / out 80,000 | aggregator | out=ctx is a common data-entry smell; verify | |
| 313 | | D-3 | `trinity-large-preview` | ctx 262,144 | 131,000 / 131,000 | aggregator | verify | |
| 314 | | D-4 | `glm-5.1`, `glm-5-turbo`, `glm-5v-turbo` | ctx 202,752 | 200,000 | **vendor (zai)** | 202,752 = 198×1024; likely fine (marketing 200K vs binary), document choice | |
| 315 | | D-5 | `minimax-m3` | out 524,288 | out 128,000 | vendor (coding-plan row) | route-dependent; verify per MiniMax platform docs | |
| 316 | | D-6 | `minimax-m2` | ctx 204,800 | 196,608 | vendor (coding-plan row) | verify | |
| 317 | | D-7 | `qwen3.6-35b-a3b`, `qwen3.6-27b` | out 262,140 | out 65,536 | **vendor (alibaba)** | our 262,140 looks wrong (≈ctx); likely fix to 65,536 | |
| 318 | | D-8 | `qwen3.6-max-preview` | ctx 262,144 | 245,800 | vendor (alibaba-cn) | verify | |
| 319 | | D-9 | `grok-4.20-0309-*` | ctx 2,000,000 | 1,000,000 | vendor (xai) | 2M matches xAI's fast-endpoint marketing; catalog row may be the standard endpoint — verify | |
| 320 | | D-10 | `tencent/hy3-preview` | ctx 262,144 | 256,000 | aggregator | minor; verify | |
| 321 | | D-11 | `gemma-4-31b-it` out 16,384; `nemotron-3-ultra` out 16,384 | 131,072 / 65,000 | aggregator | per-host caps differ; ours were OpenRouter-specific — document as route-scoped | |
| 322 | | D-12 | `kimi-for-coding` | in `models.rs` only | absent from live catalog, agent registry, bundled catalogs | — | add to agent registry + bundled catalog or document as models.rs-only route | |
| 323 | | D-13 | `qwen/qwen3.7-plus`, `qwen/qwen3.7-max` | priced (and 3.7-max in agent registry) but **no ctx/out/reasoning rows** | present upstream | — | add fact rows | |
| 324 | | D-14 | all Grok models | **no pricing rows** | xai: e.g. grok-4.5 $2/$6, grok-4.3 $1.25/$2.5 | vendor | add pricing (catalog passthrough may already cover once live rows resolve — verify `resolved_usd_pricing` path) | |
| 325 | | D-15 | `LongCat-2.0`, `fugu` (base), `ernie-4.0-turbo-8k` | agent-registry/default only; no metadata rows | — | — | add facts or mark best-effort | |
| 326 | | D-16 | `mimo-v2.5*` | ctx 1,000,000 | 1,048,576 | vendor (token-plan) | cosmetic (1M vs 2^20); document choice | |
| 327 | | D-17 | `fugu-ultra` | out 131,000 | sakana row: out 1,000,000 | vendor row suspect (out=ctx) | keep ours (Requesty-sourced) unless Sakana docs say otherwise | |
| 328 | |
| 329 | Structural observations: |
| 330 | |
| 331 | - **Four hand-maintained fact stores** must currently be updated in lockstep: |
| 332 | `models.rs`, `model_catalog.bundled.json`, `pricing.rs`, |
| 333 | `models_dev.bundled.json`. `model_registry.rs` is the intended chokepoint |
| 334 | but is not yet consumed by production call sites (its module docs say so). |
| 335 | - The agent crate's `ModelRegistry` (93 rows) duplicates provider/alias data |
| 336 | with its own `supports_tools`/`supports_reasoning` flags — a fifth store. |
| 337 | - `CurrencyPricing` has no **cache-write** field, so Anthropic (1.25–2× input) |
| 338 | and Qwen 3.7 cache-write rates are silently dropped from cost estimates. |
| 339 | - The bundled TUI catalog cannot carry a cache-read rate, forcing Anthropic |
| 340 | rows to live in `pricing.rs` above the catalog. |
| 341 | |
| 342 | ## 8. Action items (for the implementation pass) |
| 343 | |
| 344 | | ID | Action | Where | |
| 345 | |---|---|---| |
| 346 | | A1 | Label OAuth-route context in the picker (e.g. "272K ctx · ChatGPT route") so account-scoped windows don't read as wrong data; optionally show the API-route window alongside | `model_picker.rs:1187-1192` hint renderer | |
| 347 | | A2 | Fix Qwen3.6-27b/35b output caps (262,140 → 65,536, pending vendor-doc check) | `models.rs:371`, tests | |
| 348 | | A3 | Verify & reconcile D-1/2/3 (Arcee), D-5/6 (MiniMax), D-8 (Qwen max-preview), D-9 (Grok 4.20), D-10 (HY3) against vendor docs | `models.rs`, bundled catalogs | |
| 349 | | A4 | Add fact rows for `qwen3.7-plus/max`, `LongCat-2.0`, Grok pricing | `models.rs`, `pricing.rs` | |
| 350 | | A5 | Register `kimi-for-coding` in the agent-crate registry + bundled catalog | `crates/agent/src/lib.rs`, assets | |
| 351 | | A6 | Add cache-write field to `CurrencyPricing` and to the catalog schema; move Anthropic rows into the catalog once it can carry cache rates | `pricing.rs:97-109`, `catalog.rs` | |
| 352 | | A7 | Complete the #3071/#3073 migration: make production call sites consume `model_registry::lookup` so the fact stores collapse to one | `model_registry.rs` | |
| 353 | | A8 | Consider folding the agent-crate `ModelRegistry` flags into the same chokepoint (or generating them from it) | `crates/agent/src/lib.rs` | |
| 354 | | A9 | Refresh `model_catalog.bundled.json` + `models_dev.bundled.json` from the 2026-07-12 live snapshot as part of each release lane | assets | |
| 355 | |
| 356 | ## Appendix A — agent-crate registry (model × provider, 93 rows) |
| 357 | |
| 358 | Source: `crates/agent/src/lib.rs` `ModelRegistry::default()`. Flags: |
| 359 | T = supports tools, R = supports reasoning. Aliases are case-insensitive. |
| 360 | |
| 361 | | Wire model id | Provider | T | R | Aliases | |
| 362 | |---|---|---|---|---| |
| 363 | | `deepseek-v4-pro` | Deepseek | ✓ | ✓ | — | |
| 364 | | `deepseek-v4-flash` | Deepseek | ✓ | ✓ | deepseek-chat, deepseek-reasoner, deepseek-r1, deepseek-v3, deepseek-v3.2 | |
| 365 | | `deepseek-ai/deepseek-v4-pro` | NvidiaNim | ✓ | ✓ | deepseek-v4-pro, nvidia-deepseek-v4-pro, nim-deepseek-v4-pro | |
| 366 | | `deepseek-ai/deepseek-v4-flash` | NvidiaNim | ✓ | ✓ | deepseek-v4-flash, deepseek-chat, deepseek-reasoner, nvidia-deepseek-v4-flash, nim-deepseek-v4-flash | |
| 367 | | `deepseek-v4-pro` | Openai | ✓ | ✓ | openai-compatible-deepseek-v4-pro | |
| 368 | | `deepseek-v4-flash` | Openai | ✓ | ✓ | openai-compatible-deepseek-v4-flash | |
| 369 | | `gpt-5.6` | Openai | ✓ | ✓ | gpt56 | |
| 370 | | `gpt-5.6-sol` | Openai | ✓ | ✓ | gpt56-sol | |
| 371 | | `gpt-5.6-terra` | Openai | ✓ | ✓ | gpt56-terra | |
| 372 | | `gpt-5.6-luna` | Openai | ✓ | ✓ | gpt56-luna | |
| 373 | | `deepseek-ai/deepseek-v4-flash` | Atlascloud | ✓ | ✓ | deepseek-v4-flash, atlascloud-deepseek-v4-flash | |
| 374 | | `deepseek-ai/deepseek-v4-pro` | Atlascloud | ✓ | ✓ | deepseek-v4-pro, atlascloud-deepseek-v4-pro | |
| 375 | | `deepseek-reasoner` | WanjieArk | ✓ | ✓ | wanjie-deepseek-reasoner, ark-wanjie-deepseek-reasoner | |
| 376 | | `DeepSeek-V4-Pro` | Volcengine | ✓ | ✓ | deepseek-v4-pro, volcengine-deepseek-v4-pro, ark-deepseek-v4-pro | |
| 377 | | `DeepSeek-V4-Flash` | Volcengine | ✓ | ✓ | deepseek-v4-flash, deepseek-chat, volcengine-deepseek-v4-flash, ark-deepseek-v4-flash | |
| 378 | | `trinity-large-thinking` | Arcee | ✓ | ✓ | trinity, arcee-trinity, arcee-trinity-large-thinking | |
| 379 | | `trinity-large-preview` | Arcee | ✓ | ✗ | arcee-trinity-large-preview | |
| 380 | | `deepseek/deepseek-v4-pro` | Openrouter | ✓ | ✓ | deepseek-v4-pro, openrouter-deepseek-v4-pro | |
| 381 | | `deepseek/deepseek-v4-flash` | Openrouter | ✓ | ✓ | deepseek-v4-flash, deepseek-chat, deepseek-reasoner, openrouter-deepseek-v4-flash | |
| 382 | | `arcee-ai/trinity-large-thinking` | Openrouter | ✓ | ✓ | trinity, trinity-large-thinking, arcee-trinity-large-thinking | |
| 383 | | `xiaomi/mimo-v2.5-pro` | Openrouter | ✓ | ✓ | openrouter-mimo-v2.5-pro, openrouter-xiaomi-mimo-v2.5-pro | |
| 384 | | `xiaomi/mimo-v2.5` | Openrouter | ✓ | ✓ | openrouter-mimo-v2.5, openrouter-xiaomi-mimo-v2.5 | |
| 385 | | `qwen/qwen3.6-flash` | Openrouter | ✓ | ✓ | qwen3.6-flash, qwen-3.6-flash | |
| 386 | | `qwen/qwen3.6-35b-a3b` | Openrouter | ✓ | ✓ | qwen3.6-35b-a3b, qwen-3.6-35b-a3b | |
| 387 | | `qwen/qwen3.6-max-preview` | Openrouter | ✓ | ✓ | qwen3.6-max-preview, qwen-3.6-max-preview, qwen-max-preview | |
| 388 | | `qwen/qwen3.6-27b` | Openrouter | ✓ | ✓ | qwen3.6-27b, qwen-3.6-27b | |
| 389 | | `qwen/qwen3.6-plus` | Openrouter | ✓ | ✓ | qwen3.6-plus, qwen-3.6-plus | |
| 390 | | `qwen/qwen3.7-max` | Openrouter | ✓ | ✓ | qwen3.7-max, qwen-3.7-max | |
| 391 | | `moonshotai/kimi-k2.7-code` | Openrouter | ✓ | ✓ | kimi-k2.7-code, openrouter-kimi-k2.7-code | |
| 392 | | `moonshotai/kimi-k2.6` | Openrouter | ✓ | ✓ | openrouter-kimi-k2.6 | |
| 393 | | `minimax/minimax-m3` | Openrouter | ✓ | ✓ | minimax-m3, minimax-m-3, openrouter-minimax-m3 | |
| 394 | | `minimax/minimax-m2.7` | Openrouter | ✓ | ✓ | minimax-2.7, minimax-2-7, openrouter-minimax-2.7 | |
| 395 | | `z-ai/glm-5.1` | Openrouter | ✓ | ✓ | glm-5.1, zai-glm-5.1 | |
| 396 | | `z-ai/glm-5.2` | Openrouter | ✓ | ✓ | glm-5.2, zai-glm-5.2 | |
| 397 | | `z-ai/glm-5.3` | Openrouter | ✓ | ✓ | glm-5.3, zai-glm-5.3 | |
| 398 | | `z-ai/glm-5-turbo` | Openrouter | ✓ | ✓ | glm-5-turbo, zai-glm-5-turbo | |
| 399 | | `tencent/hy3-preview` | Openrouter | ✓ | ✓ | hy3-preview, tencent-hy3-preview | |
| 400 | | `google/gemma-4-31b-it` | Openrouter | ✓ | ✓ | gemma-4-31b, gemma-4-31b-it | |
| 401 | | `google/gemma-4-26b-a4b-it` | Openrouter | ✓ | ✓ | gemma-4-26b-a4b, gemma-4-26b-a4b-it | |
| 402 | | `nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free` | Openrouter | ✓ | ✓ | nemotron-3-nano-omni, nemotron-3-nano-omni-reasoning | |
| 403 | | `nvidia/nemotron-3-ultra-550b-a55b` | Openrouter | ✓ | ✓ | nvidia/nemotron-3-ultra, nemotron-3-ultra, nemotron-3-ultra-550b-a55b, nvidia-nemotron-3-ultra, nvidia-nemotron-3-ultra-550b-a55b | |
| 404 | | `GLM-5.2` | Zai | ✓ | ✓ | glm-5.2, glm-5-2, zai-glm-5.2, zai-glm-5-2 | |
| 405 | | `GLM-5.3` | Zai | ✓ | ✓ | glm-5.3, glm-5-3, zai-glm-5.3, zai-glm-5-3 | |
| 406 | | `GLM-5.1` | Zai | ✓ | ✓ | glm-5.1, glm-5-1, zai-glm-5.1, zai-glm-5-1 | |
| 407 | | `GLM-5-Turbo` | Zai | ✓ | ✓ | glm-5-turbo, glm-5turbo, zai-glm-5-turbo | |
| 408 | | `mimo-v2.5-pro` | XiaomiMimo | ✓ | ✓ | mimo, pro, xiaomi-mimo-v2.5-pro, xiaomi-mimo-v2-5-pro | |
| 409 | | `mimo-v2.5` | XiaomiMimo | ✓ | ✓ | omni, mimo-omni, v2.5-omni, mimo-v2.5-omni, xiaomi-mimo-v2.5, xiaomi-mimo-v2.5-omni | |
| 410 | | `mimo-v2.5-asr` | XiaomiMimo | ✗ | ✗ | asr, speech-to-text, transcribe | |
| 411 | | `mimo-v2.5-tts` | XiaomiMimo | ✗ | ✗ | tts, speech, mimo-tts | |
| 412 | | `mimo-v2.5-tts-voicedesign` | XiaomiMimo | ✗ | ✗ | voicedesign, voice-design, mimo-voice-design | |
| 413 | | `mimo-v2.5-tts-voiceclone` | XiaomiMimo | ✗ | ✗ | voiceclone, voice-clone, mimo-voice-clone | |
| 414 | | `mimo-v2-tts` | XiaomiMimo | ✗ | ✗ | mimo-v2-speech | |
| 415 | | `deepseek/deepseek-v4-pro` | Novita | ✓ | ✓ | deepseek-v4-pro, novita-deepseek-v4-pro | |
| 416 | | `deepseek/deepseek-v4-flash` | Novita | ✓ | ✓ | deepseek-v4-flash, deepseek-chat, deepseek-reasoner, novita-deepseek-v4-flash | |
| 417 | | `accounts/fireworks/models/deepseek-v4-pro` | Fireworks | ✓ | ✓ | deepseek-v4-pro, fireworks-deepseek-v4-pro | |
| 418 | | `deepseek-ai/DeepSeek-V4-Pro` | Siliconflow | ✓ | ✓ | deepseek-v4-pro, deepseek-reasoner, deepseek-r1, siliconflow-deepseek-v4-pro | |
| 419 | | `deepseek-ai/DeepSeek-V4-Flash` | Siliconflow | ✓ | ✓ | deepseek-v4-flash, deepseek-chat, deepseek-v3, siliconflow-deepseek-v4-flash | |
| 420 | | `kimi-k2.7-code` | Moonshot | ✓ | ✓ | kimi, kimi-k2, kimi-k2.7, kimi-code, moonshot-kimi-k2.7-code | |
| 421 | | `kimi-k2.6` | Moonshot | ✓ | ✓ | moonshot-kimi-k2.6 | |
| 422 | | `deepseek-ai/DeepSeek-V4-Pro` | Sglang | ✓ | ✓ | deepseek-v4-pro, sglang-deepseek-v4-pro | |
| 423 | | `deepseek-ai/DeepSeek-V4-Flash` | Sglang | ✓ | ✓ | deepseek-v4-flash, deepseek-chat, deepseek-reasoner, sglang-deepseek-v4-flash | |
| 424 | | `deepseek-ai/DeepSeek-V4-Pro` | Vllm | ✓ | ✓ | deepseek-v4-pro, vllm-deepseek-v4-pro | |
| 425 | | `deepseek-ai/DeepSeek-V4-Flash` | Vllm | ✓ | ✓ | deepseek-v4-flash, deepseek-chat, deepseek-reasoner, vllm-deepseek-v4-flash | |
| 426 | | `deepseek-v4-flash` | Ollama | ✓ | ✓ | — (Ollama also accepts any name as-is) | |
| 427 | | `deepseek-ai/DeepSeek-V4-Pro` | Huggingface | ✓ | ✓ | deepseek-v4-pro, hf-deepseek-v4-pro | |
| 428 | | `deepseek-ai/DeepSeek-V4-Flash` | Huggingface | ✓ | ✓ | deepseek-v4-flash, deepseek-chat, deepseek-reasoner, hf-deepseek-v4-flash | |
| 429 | | `deepseek-ai/DeepSeek-V4-Pro` | Together | ✓ | ✓ | deepseek-v4-pro, together-deepseek-v4-pro | |
| 430 | | `deepseek-ai/DeepSeek-V4-Flash` | Together | ✓ | ✓ | deepseek-v4-flash, deepseek-chat, together-deepseek-v4-flash | |
| 431 | | `gpt-5.5` | OpenaiCodex | ✓ | ✓ | codex-gpt-5.5, chatgpt-gpt-5.5 | |
| 432 | | `claude-opus-4-8` | Anthropic | ✓ | ✓ | opus, claude-opus | |
| 433 | | `claude-sonnet-4-6` | Anthropic | ✓ | ✓ | sonnet, claude-sonnet | |
| 434 | | `claude-haiku-4-5` | Anthropic | ✓ | ✗ | haiku, claude-haiku | |
| 435 | | `deepseek-v4-flash` | Openmodel | ✓ | ✓ | openmodel, openmodel-deepseek | |
| 436 | | `step-3.7-flash` | Stepfun | ✓ | ✗ | stepfun, stepflash | |
| 437 | | `MiniMax-M3` | Minimax | ✓ | ✓ | minimax, minimax-m3, minimax-m-3 | |
| 438 | | `MiniMax-M2.7` | Minimax | ✓ | ✓ | minimax-m2.7, minimax-m2-7, minimax-m-2.7, minimax-m-2-7 | |
| 439 | | `MiniMax-M2.7-highspeed` | Minimax | ✓ | ✓ | minimax-m2.7-highspeed (+ dash variants) | |
| 440 | | `MiniMax-M2.5` | Minimax | ✓ | ✓ | minimax-m2.5 (+ dash variants) | |
| 441 | | `MiniMax-M2.5-highspeed` | Minimax | ✓ | ✓ | minimax-m2.5-highspeed (+ dash variants) | |
| 442 | | `MiniMax-M2.1` | Minimax | ✓ | ✓ | minimax-m2.1 (+ dash variants) | |
| 443 | | `MiniMax-M2.1-highspeed` | Minimax | ✓ | ✓ | minimax-m2.1-highspeed (+ dash variants) | |
| 444 | | `MiniMax-M2` | Minimax | ✓ | ✓ | minimax-m2, minimax-m-2 | |
| 445 | | `deepseek-ai/DeepSeek-V4-Pro` | Deepinfra | ✓ | ✓ | deepseek-v4-pro, di-deepseek-v4-pro | |
| 446 | | `deepseek-ai/DeepSeek-V4-Flash` | Deepinfra | ✓ | ✓ | deepseek-v4-flash, di-deepseek-v4-flash | |
| 447 | | `fugu` | Sakana | ✓ | ✗ | sakana-fugu, sakana/fugu | |
| 448 | | `fugu-ultra-20260615` | Sakana | ✓ | ✓ | fugu-ultra, sakana-fugu-ultra | |
| 449 | | `LongCat-2.0` | LongCat | ✓ | ✓ | longcat, longcat-2.0 | |
| 450 | | `muse-spark-1.1` | Meta | ✓ | ✓ | muse-spark, muse | |
| 451 | | `grok-4.5` | Xai | ✓ | ✓ | grok, xai-grok-4.5 | |
| 452 | | `grok-4.3` | Xai | ✓ | ✓ | xai-grok-4.3 | |
| 453 | | `grok-build` | Xai | ✓ | ✓ | xai-grok-build | |
| 454 | | `grok-composer-2.5-fast` | Xai | ✓ | ✗ | xai-grok-composer | |
| 455 | | `grok-4.20-0309-reasoning` | Xai | ✓ | ✓ | xai-grok-reasoning | |
| 456 | | `grok-4.20-0309-non-reasoning` | Xai | ✓ | ✗ | xai-grok-fast | |
| 457 | |
| 458 | Resolution order (`resolve()` at `lib.rs:987+`): Ollama passes names through |
| 459 | verbatim; a `provider_hint` narrows the search; Atlascloud/Arcee/XiaomiMimo |
| 460 | accept arbitrary ids for their provider; otherwise falls back to the hinted |
| 461 | provider's first model, ultimate default `deepseek-v4-pro`. |
| 462 | |
| 463 | ## 8. Fast-tier derivation contract |
| 464 | |
| 465 | Auto routing and the legacy `model_strength = faster` (now the Scout role) use the provider-scoped family map |
| 466 | in `crates/tui/src/model_routing.rs`. A pair is valid only when the current |
| 467 | provider's catalog has both model ids; model-name similarity alone is not |
| 468 | enough. Current non-DeepSeek pairs are: |
| 469 | |
| 470 | | Provider | Strong family | Fast sibling | |
| 471 | |---|---|---| |
| 472 | | OpenAI / OpenAI Codex | `gpt-5.6`, `gpt-5.6-sol`, `gpt-5.6-terra` | `gpt-5.6-luna` | |
| 473 | | Anthropic | Claude Opus/Sonnet rows listed in §4.3 | `claude-haiku-4-5` | |
| 474 | | OpenRouter | Qwen 3.6, Claude, MiMo, Trinity, Kimi rows | provider-prefixed catalog sibling | |
| 475 | | Xiaomi MiMo | `mimo-v2.5-pro` | `mimo-v2.5` | |
| 476 | | Arcee | `trinity-large-thinking` / `trinity-large-preview` | `trinity-mini` | |
| 477 | | Moonshot | `kimi-k2.7-code` | `kimi-k2.6` | |
| 478 | | MiniMax | `MiniMax-M2.7` | `MiniMax-M2.7-highspeed` | |
| 479 | | OpenCode Go | `kimi-k3` | `kimi-k2.7-code` | |
| 480 | |
| 481 | Already-fast rows and true singles return no further sibling. Local/custom |
| 482 | providers never inherit cloud families. New catalog multi-tier families must |
| 483 | add an explicit same-provider pair and a matrix test before they become an |
| 484 | Auto fast route. |
| 485 | |
| 486 | ## Appendix B — file map (where each fact lives) |
| 487 | |
| 488 | | Fact | Primary file | |
| 489 | |---|---| |
| 490 | | Context window / max output / reasoning (static) | `crates/tui/src/models.rs:239-554` | |
| 491 | | Seeded metadata registry (future chokepoint) | `crates/tui/src/model_registry.rs` | |
| 492 | | Pricing (USD + DeepSeek CNY, time-aware rows) | `crates/tui/src/pricing.rs:112-303` | |
| 493 | | Bundled TUI catalog (31 entries, modalities) | `crates/tui/assets/model_catalog.bundled.json` | |
| 494 | | Bundled Models.dev seed (14 providers / 42 offerings) | `crates/config/assets/models_dev.bundled.json` | |
| 495 | | Live Models.dev cache (disk) | `~/.codewhale/catalog/models-dev-catalog.json` | |
| 496 | | Codex OAuth roster (disk, read-only) | `~/.codex/models_cache.json` | |
| 497 | | Provider descriptors (33) | `crates/config/src/provider.rs` | |
| 498 | | Provider base-URL/model constants | `crates/config/src/provider_defaults.rs` | |
| 499 | | Provider enum + parsing | `crates/config/src/provider_kind.rs`, `crates/tui/src/config.rs:42` | |
| 500 | | Catalog merge/precedence | `crates/config/src/catalog.rs`, `crates/tui/src/provider_lake.rs` | |
| 501 | | Live fetch/TTL/freshness | `crates/tui/src/models_dev_live.rs` | |
| 502 | | OAuth route limit override | `crates/tui/src/route_runtime.rs:33-51`, `crates/tui/src/codex_model_cache.rs` | |
| 503 | | Picker display precedence | `crates/tui/src/tui/model_picker.rs:1105-1155` | |
| 504 | | Agent-crate model×provider registry | `crates/agent/src/lib.rs:69-960` | |
| 505 |