diff --git a/apps/cli/src/engine/catalog-metadata.test.ts b/apps/cli/src/engine/catalog-metadata.test.ts index a29ca8fb..788816fd 100644 --- a/apps/cli/src/engine/catalog-metadata.test.ts +++ b/apps/cli/src/engine/catalog-metadata.test.ts @@ -124,8 +124,20 @@ describe('catalog-metadata (ADR-0072 P4 — host projection + seed + install + p it('a reseed CARRIES FORWARD enrichment a refresh had populated — never blanks it (ADR-0072 point 5)', () => { seedShippedCatalog(store, TS); - const shippedId = Object.keys(CATALOG_SNAPSHOT)[0]!; - // A `models refresh --catalog` populated enrichment on a shipped id (the snapshot itself carries none). + // Pick a shipped id the snapshot leaves WITHOUT a `knowledgeCutoff`, so this test exercises the + // carry-forward branch rather than the snapshot-wins one. The snapshot bakes in modalities and a + // description for every model today, but not always a cutoff. + const withoutCutoff = Object.entries(CATALOG_SNAPSHOT).find( + ([, m]) => m.knowledgeCutoff === undefined, + ); + // If a future snapshot stamps a cutoff on EVERY model, this test can no longer reach the branch it + // exists for — say so, rather than dying on an unhelpful undefined-index read. + expect( + withoutCutoff, + 'no shipped model lacks knowledgeCutoff — pick another carry-forward column', + ).toBeDefined(); + const shippedId = withoutCutoff![0]; + // A `models refresh --catalog` populated enrichment on a shipped id. store.updateEnrichment([ { modelId: shippedId, @@ -139,10 +151,13 @@ describe('catalog-metadata (ADR-0072 P4 — host projection + seed + install + p store.upsertMeta({ seededSnapshotSha: 'a-different-sha' }); expect(seedShippedCatalog(store, TS + 1)).toBe(true); // it reseeds const row = store.readAll().find((r) => r.modelId === shippedId)!; - // Money+wire came from the (re-reviewed) snapshot; enrichment SURVIVED the reseed rather than resetting to NULL. + // The column the snapshot leaves empty SURVIVES the reseed rather than resetting to NULL... expect(row.knowledgeCutoff).toBe('2099-01'); - expect(row.inputModalities).toBe(JSON.stringify(['text', 'image'])); - expect(row.description).toBe('fetched'); + // ...while a column the snapshot DOES carry wins over the stale DB value, which is the documented + // `?? prior` precedence: the newly-reviewed snapshot is the more trustworthy source for what it states. + const shipped = CATALOG_SNAPSHOT[shippedId]!; + expect(row.inputModalities).toBe(JSON.stringify(shipped.inputModalities)); + expect(row.description).toBe(shipped.description); }); }); diff --git a/docs/roadmap/current.md b/docs/roadmap/current.md index 7ecc5d59..3f06f6f2 100644 --- a/docs/roadmap/current.md +++ b/docs/roadmap/current.md @@ -337,9 +337,9 @@ unanswered**; the remainder sit inline in their own phase-file bullet. |---|------|----------|----------------| | D1 | 0 | Mark the `ci` job a **required** check (open since Phase 0) | Yes — every CI item here is advisory until it flips | | D2 | 0 | Coverage floor: promote to required, or soften `testing.md`? | Promote, **and implement in the same PR** — a checked-in run already shows 92–97% margin | -| D3 | 0 | Accept the upstream Gemini price rise the ADR-0071 §9 guard is refusing? | Accept and regenerate — a stale floor *under*-prices the cap, the dangerous direction | +| D3 | 0 | Accept the upstream price changes the ADR-0071 §9 guard is refusing? | ✅ **Ruled 2026-07-26: take current prices.** Verified: `gemini-flash-latest` moved $0.30→$1.50 in / $2.50→$9.00 out — the shipped floor under-prices by 5×. **Blocked on D3b below** | | D4 | 0 | Confirm the number reservation (`0013`–`0017`, ADR-0073+) | As listed — one item per number, in landing order | -| D5 | 0 | The binding locale bar: EXIT:6 says five, CLAUDE.md says `en`+`tr` | **Maintainer call.** Either amend EXIT:6 to ship `en`+`tr` with three staged, or keep five and fix the prose. 2.5.5.F assumes the latter | +| D5 | 0 | The binding locale bar | ✅ **Ruled 2026-07-26: ship `en` + `tr`**, catalog architected for n locales, `es`/`fr`/`de` staged. EXIT:6, 2.6.L and 2.5.5.F amended | | D7 | 0 | Publish v0.1.1 as-is, or supersede with v0.2.0? | v0.2.0 — ADR-0067's Node `>=22` bump is breaking for 0.x | | D8 | 1 | Do already-persisted approval previews need a scrub? | Yes — migration 0013, same PR. Deleting `history.db` also destroys provider registrations | | D10 | 1 | `BudgetExceededError`/`BudgetPauseError`: adopt `.code`? | Adopt — must precede Wave 3's `RelaviumError` migration | diff --git a/docs/roadmap/phases/phase-2.5.5-hardening-and-remediation.md b/docs/roadmap/phases/phase-2.5.5-hardening-and-remediation.md index f4bd07de..215ab302 100644 --- a/docs/roadmap/phases/phase-2.5.5-hardening-and-remediation.md +++ b/docs/roadmap/phases/phase-2.5.5-hardening-and-remediation.md @@ -345,7 +345,7 @@ The project's own documentation conventions — cite-not-restate, status banners - **Repo-wide docs link/index hygiene sweep: four broken relative links, three missing ADR cross-reference pointers, and four stale reference-doc index tables.** Superseded ADR-0021 has no in-body amendment pointer forward to the new Node floor decision. ADR-0069's Related line 404s to a renamed file — it links `0047-cli-render-seam-and-framework-free-cores.md` but the real file is `docs/decisions/0047-cli-framework-commander-ink-clack.md`. ADR-0071's `### K7.` header gives no in-header signal that it belongs to a separate numbering track. An independent repo-wide crawl of every relative markdown link under `docs/` found four genuinely broken links — one of which duplicates the ADR-0069→ADR-0047 link above — plus a wrong-subdirectory link in ADR-0062. Separately, `docs/reference/README.md`'s shared-core table lists only 5 of 11 real files; `docs/standards/documentation-style.md` §6's canonical-artifact registry is missing 6 of 11, including the safety-critical `llm-provider-seam.md`; `docs/reference/shared-core/agent-runner.md` is orphaned from both indexes despite being cited by six other docs; the `docs/reference/cli/` index is missing `accessibility.md` and `regression-harness.md`. Regenerate all four index tables from the real file tree, fix the four broken links, and add the three missing ADR pointers in one coordinated sweep; recommend a CI link-checker afterward to prevent recurrence. *(M · docs/decisions/, docs/reference/README.md, docs/standards/documentation-style.md, docs/reference/cli/ · #123, #124, #126, #143, #151, #251, #252, #253)* - **Trim two ADRs and one project-structure.md row that restate content already living verbatim in their own cited canonical doc.** ADR-0031 states "canonical types live in `llm-provider-seam.md`" and then spends roughly 250 lines re-deriving the exact same content that file already carries. ADR-0027's addendum states exact sandbox resource-cap numbers that already live in `expression-sandbox-spec.md`, even after the ADR's own preamble names that spec the single canonical home. `docs/project-structure.md`'s Apps table restates a hand-picked, now-stale CLI subcommand list instead of linking to `docs/reference/cli/commands.md`, which already owns it canonically, and has drifted out of sync as a direct result. All three are the identical CLAUDE.md rule-8 violation — trim each ADR to drivers/tradeoffs plus a citation, and replace the stale restated list with a link. *(M · docs/decisions/0031-*.md, docs/decisions/0027-*.md, docs/project-structure.md · #120, #121, #257)* - **Add three missing rows/notes to `tech-stack.md`, the single source of truth for pinned choices.** `docs/tech-stack.md` omits `smol-toml` and `string-width` as ADR-backed runtime dependencies (both already shipped and in `package.json`), and is missing an MCP SDK shape-tradeoff note that should cross-reference ADR-0034. The Playwright e2e row is the one un-flagged not-yet-applicable row in an otherwise carefully phase-annotated doc. Add the two missing dependency rows, the tradeoff note, and the same Phase-3 flag every other not-yet-applicable row already carries, in one pass. *(S · docs/tech-stack.md · #246, #247, #140)* -- **Rewrite CLAUDE.md's and README.md's shared i18n-status clause: wrong on stage, wrong on language count, repeated in both files.** `CLAUDE.md`'s "What this project is" section lists "settings/theming/`en`+`tr` localization" as in-progress Phase 2.6 scope, reading as already shipping — an exhaustive grep for i18n/locale/translation scaffolding across `apps/cli` finds zero hits; the theme hasn't started at all. The same clause also undercounts scope: `docs/roadmap/phases/phase-2.6-conversational-authoring.md` states the real target three times as `en, es, tr, fr, de`, and `README.md` repeats the same en/tr undercount. One rewrite of the shared clause in both `CLAUDE.md` and `README.md`, stating the correct five-language target with an explicit not-started qualifier, fixes all three. *(S · CLAUDE.md, README.md · #74, #260, #134)* +- **Rewrite CLAUDE.md's and README.md's shared i18n-status clause: wrong on stage, wrong on language count, repeated in both files.** `CLAUDE.md`'s "What this project is" section lists "settings/theming/`en`+`tr` localization" as in-progress Phase 2.6 scope, reading as already shipping — an exhaustive grep for i18n/locale/translation scaffolding across `apps/cli` finds zero hits; the theme hasn't started at all. The language count is now settled by maintainer ruling (2026-07-26): the catalog is architected for n locales but **`en` + `tr` are what ship in Phase 2.6**, with `es`/`fr`/`de` staged — so the existing en/tr wording is correct on scope and wrong only on stage. One rewrite of the shared clause in both `CLAUDE.md` and `README.md`, adding an explicit not-started qualifier and naming the staged locales, fixes all three. *(S · CLAUDE.md, README.md · #74, #260, #134)* - **Add the six load-bearing terms missing from the glossary and refresh its stale "Last updated" header.** `docs/glossary.md` omits `ExecutionHost`, `ToolHost`, `ActionGuard`, `MediaStore`, `WorkflowEngine`, and `BudgetGovernor` — terms that recur across the ADR corpus without a defined home — and its "Last updated" header is over a month stale relative to the file's own content. Bundle both fixes into the same edit. *(S · docs/glossary.md · #135, #137)* - **Swap `docs/architecture/README.md`'s recommended reading order to match both target docs' own stated shipping order.** The recommended order puts `cloud-phase-2.md` before `managed-inference.md`, contradicting both documents' own stated shipping/dependency order (managed inference is Phase 5, cloud execution is Phase 6). Swap the two entries. *(S · docs/architecture/README.md · #157)* - **Add the missing `style` commit type to `commit-style.md`'s enumerated Types list.** `docs/standards/commit-style.md` enumerates `feat`, `fix`, `refactor`, `perf`, `test`, `docs`, `chore`, `build`, `ci` but omits `style`, which real repo history already uses (e.g. `style: prettier the ADR-0072 files`, HEAD-2). Add it to the documented list so the doc matches actual practice. *(S · docs/standards/commit-style.md · #158)* @@ -354,7 +354,7 @@ The project's own documentation conventions — cite-not-restate, status banners - **Correct the doc comment on `urlSourceSchema` that asserts the opposite of the flag's actual current state.** A doc comment attached to `urlSourceSchema` (a security-relevant media feature flag) states the flag's behavior backwards from what the code actually does today. Correct the comment to match the real, current gating. *(S · packages/shared/src/content.ts (or the file defining `urlSourceSchema`) · #238)* - **Sync `agent-runner.md`'s documented `cost:updated` payload with the `priced` boolean field ADR-0070 added.** `docs/reference/shared-core/agent-runner.md` predates ADR-0070 and its documented `cost:updated` event payload is missing the `priced` boolean field ADR-0070 added to `CostUpdatedEventSchema`. Add the field to the documented shape and cite ADR-0070 as the source. *(S · docs/reference/shared-core/agent-runner.md · #145)* -**Acceptance:** no canonical doc names the retired `pricing.ts` `MODEL_PRICING` table as the pricing authority; every reference to an unbuilt surface (desktop, VS Code, `apps/api`/`portal`, `packages/ui`) carries the same not-yet-shipped marker convention already used correctly elsewhere in the corpus, at all twenty flagged sites; every reference-doc index (`docs/reference/README.md`, `docs/reference/shared-core/README.md`, `documentation-style.md` §6, `docs/reference/cli/` index) lists every real file in its directory with zero broken relative links, verified by a link-check pass; `packages/mcp` appears in all five package-inventory tables/diagrams including the reviewer agent's own checklist; every roadmap status banner (`current.md`, `AGENTS.md`, the phase-2.6 and phase-3 banners) matches the state recorded in the file it summarizes, with the 2.6.Q "seven decisions" figure corrected to six; the chat tutorial and onboarding path reflect that `chat.ts` ships today; `node-types.md`'s `merge_strategy`/`human_in_the_loop_config` claims match the schema and engine exactly; the three hardcoded-path skills run correctly from a fresh clone via `` `$(git rev-parse --show-toplevel)` ``; `commit-style.md` lists `style` as a valid type; the glossary defines all six missing terms and its date header is current; CLAUDE.md and README.md state the i18n theme as not-started with the correct five-language (`en, es, tr, fr, de`) target. The two blocked items (`overview.md`'s LLM→Keychain edge, Home's `showCost` wiring) surface as explicit open questions in the phase file rather than being silently resolved by guess. +**Acceptance:** no canonical doc names the retired `pricing.ts` `MODEL_PRICING` table as the pricing authority; every reference to an unbuilt surface (desktop, VS Code, `apps/api`/`portal`, `packages/ui`) carries the same not-yet-shipped marker convention already used correctly elsewhere in the corpus, at all twenty flagged sites; every reference-doc index (`docs/reference/README.md`, `docs/reference/shared-core/README.md`, `documentation-style.md` §6, `docs/reference/cli/` index) lists every real file in its directory with zero broken relative links, verified by a link-check pass; `packages/mcp` appears in all five package-inventory tables/diagrams including the reviewer agent's own checklist; every roadmap status banner (`current.md`, `AGENTS.md`, the phase-2.6 and phase-3 banners) matches the state recorded in the file it summarizes, with the 2.6.Q "seven decisions" figure corrected to six; the chat tutorial and onboarding path reflect that `chat.ts` ships today; `node-types.md`'s `merge_strategy`/`human_in_the_loop_config` claims match the schema and engine exactly; the three hardcoded-path skills run correctly from a fresh clone via `` `$(git rev-parse --show-toplevel)` ``; `commit-style.md` lists `style` as a valid type; the glossary defines all six missing terms and its date header is current; CLAUDE.md and README.md state the i18n theme as not-started, shipping `en` + `tr` with `es`/`fr`/`de` staged (the 2026-07-26 ruling). The two blocked items (`overview.md`'s LLM→Keychain edge, Home's `showCost` wiring) surface as explicit open questions in the phase file rather than being silently resolved by guess. ### 2.5.5.G — Codebase hygiene: naming, duplication & dead code diff --git a/docs/roadmap/phases/phase-2.6-conversational-authoring.md b/docs/roadmap/phases/phase-2.6-conversational-authoring.md index adcc6b08..5b309f26 100644 --- a/docs/roadmap/phases/phase-2.6-conversational-authoring.md +++ b/docs/roadmap/phases/phase-2.6-conversational-authoring.md @@ -52,7 +52,8 @@ Phase 2.6 makes bare `relavium` a **full-screen, Home-centric** product. Key out complex sub-tasks; workflows call workflows via `subworkflow` nodes; standardized I/O contracts; parent-child lineage tracking; auto-cleaned artifacts. - **Settings, theming, localization** — `/settings` over the config-write contract; three built-in - themes (default / high-contrast / colorblind-safe); `en`, `es`, `tr`, `fr`, `de` i18n with CI key-parity. + themes (default / high-contrast / colorblind-safe); i18n shipping **`en` + `tr`** with CI key-parity, the + catalog architected for n locales (`es`, `fr`, `de` staged). - **Onboarding v2** — two auth paths: BYOK (live) + Relavium-account stub (disabled, Phase 5). - **17 workstreams** (2.6.A–Q), substrate-first: 2.6.F (full-screen TUI + Node 22 floor) runs first; agent orchestration is split by safety gradient into 2.6.N (safe mechanism) → 2.6.O (model-generated @@ -89,7 +90,8 @@ and syntax-highlighted rendering** — all without breaking the `--json` / CI / - Run history is **attributed and drillable**: per-node model/agent/cost durable, a bounded secret-free tool trace, gate-resolve TOCTOU closed at the store, crashed runs reconciled, cross-process runs watchable live at node granularity. -- The CLI speaks **`en`, `es`, `tr`, `fr`, `de`** over a string catalog with CI key-parity, and ships a real theme system +- The CLI speaks **`en` and `tr`** over an n-locale string catalog with CI key-parity (`es`, `fr`, `de` + staged behind the same catalog, not shipped this phase), and ships a real theme system (default + high-contrast + colorblind-safe) with the color-free path staying legible. - An agent in a chat session can **autonomously spawn sub-agents and invoke workflows** for complex sub-tasks, with standardized I/O contracts, parent-child lineage tracking, hierarchical cost @@ -780,16 +782,25 @@ and the first localized agentic CLI (a genuine differentiator — competitor i18 No new ADR beyond the ADR-0063 key addition. - **i18n foundation**: an in-house string catalog (data ≠ code — zero conditional logic in translation - data; no runtime dependency expected, else ADR); `[preferences].language`; locales **`en`, `es`, `tr`, - `fr`, `de`** in-phase; a CI **key-parity test** (fails on missing/extra keys across all locales) - + a dead-string lint — landing the deferred i18n standard as a `docs/standards/` entry. The five - in-phase locales are all **Latin-script**, so in-phase rendering needs only accent-safe (valid Unicode, - no special handling) and combining-character-safe layout; full **IME composition** and **wide-character / - bidi** handling are **not** in-phase acceptance gates. The catalog architecture stays CJK/RTL-ready - (data ≠ code, no hardcoded width assumptions) so a future CJK or RTL locale needs no re-architecture — - a deliberate forward-compat posture, not an in-phase deliverable. Pluralization rules for German and - French are handled by a minimal in-house pluralization helper (selecting key variants by count); Spanish - and French accented characters are valid Unicode in the terminal and require no special handling. + data; no runtime dependency expected, else ADR); `[preferences].language`; the catalog is architected for + **n locales** but only **`en` + `tr`** ship in-phase (maintainer ruling, 2026-07-26 — `es`, `fr`, `de` are + staged: their key files may land empty/partial, they are not offered in `/settings` until complete); + a CI **key-parity test** (fails on missing/extra keys across the shipped locales) + + a dead-string lint — landing the deferred i18n standard as a `docs/standards/` entry. Both shipped + locales are **Latin-script**, so in-phase rendering needs only accent-safe (valid Unicode, no special + handling) and combining-character-safe layout; full **IME composition** and **wide-character / bidi** + handling are **not** in-phase acceptance gates. The catalog architecture stays CJK/RTL-ready (data ≠ code, + no hardcoded width assumptions) so a future CJK or RTL locale needs no re-architecture — a deliberate + forward-compat posture, not an in-phase deliverable. + - **`tr` is the locale that actually exercises the seams**, and it is in acceptance scope: Turkish takes + **no plural suffix after a numeral** ("3 çalıştırma", never "3 çalıştırmalar"), so the pluralization + helper must select by locale rule rather than assume the English count-based form; and Turkish's + dotless/dotted `ı`/`i` makes any locale-sensitive `toLowerCase`/`toUpperCase` or `localeCompare` on an + identifier a live defect — the same hazard 2.5.5.G's `compareIdentifiers` sweep (`#258`, `#259`) closes + for sorting. Neither needs new architecture; both need a test. + - **`es`, `fr`, `de` are staged, not acceptance scope.** Their accented characters are valid Unicode and + need no special handling, and German/French plural forms are already expressible in the same + count-variant helper — so completing them later is catalogue work, not a re-design. - **i18n-foundation scope inputs — hand-rolled `Intl` formatting and the cost-locale question** *(review findings, planning inputs for the task above, not separate work):* onboarding and the Home chrome currently hand-roll `toLocaleString('en-US')`/relative-time/pluralization strings (~228 unindirected @@ -808,7 +819,7 @@ safety warning, never `--json` output); themes switch live incl. the accessibility pair; the color-free path stays legible; `NO_COLOR` gating is consistent across every style prop including `bold`, `NO_COLOR=''` is honored as set, every status/warning glyph (including `/doctor`'s) has an ASCII-degrade form, and no pictographic emoji renders unconditionally; interactive surfaces run -fully in all five locales with CI-enforced key parity; diagnostics and `--json` remain English-stable per +fully in the shipped locales (`en`, `tr`) with CI-enforced key parity across every catalog key; diagnostics and `--json` remain English-stable per [ADR-0049](../../decisions/0049-cli-machine-output-contract.md); the machine-output contract is character-for-character unaffected. **Required ADR:** i18n + theming architecture. @@ -1341,7 +1352,7 @@ Once their deps land: | **Browsers** | 2.6.G | F + H + K landed | /workflows, /agents, actionable strip, permissions | | **Orchestration foundation** | 2.6.N | F + H landed | Catalog child-session spawn, standardized I/O, artifact-store port + central root, lineage, cost roll-up, guardrails | | **Chat UX** | 2.6.E | F + L landed | Syntax highlighting, rewind/fork, message queue, /copy, cheat sheet | -| **Theme/i18n** | 2.6.L | F landed | Theme system, /settings, 5-locale catalog | +| **Theme/i18n** | 2.6.L | F landed | Theme system, /settings, n-locale catalog (`en`+`tr` shipped) | | **M render-v2** | 2.6.M (render half) | F landed | Tool-call details view, diff rendering | Final integration (last to land — **phase close**): @@ -1432,7 +1443,7 @@ flowchart LR details, and syntax-highlighted code blocks behind a passed security review. 5. Run history is attributed and drillable (list → run → node with the quintet + tool summaries); the gate TOCTOU is store-closed; crashed runs reconcile; cross-process live watch works. -6. `/settings`, the theme system (incl. the accessibility pair), and **`en`, `es`, `tr`, `fr`, `de`** localization ship with +6. `/settings`, the theme system (incl. the accessibility pair), and **`en` + `tr`** localization ship with CI key-parity. 7. **Orchestration ships across the safety gradient**: (2.6.N) a chat agent spawns a **catalog** sub-agent — `/spawn ` and model-driven — with standardized I/O, full parent lineage in `history.db`, diff --git a/packages/llm/src/catalog/models-dev-schema.test.ts b/packages/llm/src/catalog/models-dev-schema.test.ts index 65521801..ac449a9a 100644 --- a/packages/llm/src/catalog/models-dev-schema.test.ts +++ b/packages/llm/src/catalog/models-dev-schema.test.ts @@ -148,6 +148,24 @@ describe('normalizeCatalog — what we import, and what we refuse to', () => { expect(dropped[0]?.reason).toContain('unpriceable'); }); + it('drops a model whose cost is PRESENT but zero — the same $0 hazard, and the null check misses it', () => { + // Live regression: `lyria-3-*` (music, billed per clip) publishes `{input: 0, output: 0}` rather than + // `cost: null`, so it sailed past the null guard and landed in the shipped snapshot at $0 — where it + // passes the ADR-0028 cap instead of being flagged unpriced. A zero rate on EITHER axis is unpriceable. + for (const cost of [ + { input: 0, output: 0 }, + { input: 0, output: 5 }, + { input: 5, output: 0 }, + ]) { + const raw = ModelsDevPayloadSchema.parse( + payload({ openai: { m: upstreamModel({ id: 'zero-rate', cost }) } }), + ); + const { catalog, dropped } = normalizeCatalog(raw); + expect(catalog['zero-rate'], JSON.stringify(cost)).toBeUndefined(); + expect(dropped[0]?.reason).toContain('unpriceable'); + } + }); + it('THROWS on a real cross-provider id collision rather than letting one price silently win', () => { const raw = ModelsDevPayloadSchema.parse( payload({ diff --git a/packages/llm/src/catalog/models-dev-schema.ts b/packages/llm/src/catalog/models-dev-schema.ts index bbc34988..722ae59c 100644 --- a/packages/llm/src/catalog/models-dev-schema.ts +++ b/packages/llm/src/catalog/models-dev-schema.ts @@ -255,6 +255,13 @@ export function normalizeCatalogModel( ) { return undefined; } + // A PRESENT but zero-rate `cost` is the same hazard as an absent one, and the check above does not catch it: + // `lyria-3-*` (music, billed per clip) publishes `{input: 0, output: 0}`, which would import as a $0 row — + // and a $0 row *passes* the ADR-0028 cost cap instead of flagging the model as unpriced. Treat a non-positive + // input or output rate as unpriceable, on the same reasoning as the null case. + if (raw.cost.input <= 0 || raw.cost.output <= 0) { + return undefined; + } const { cost, limit } = raw; const reasoning = toReasoningControls(raw); const requestCapabilities = toRequestCapabilities(raw); diff --git a/packages/llm/src/catalog/snapshot.ts b/packages/llm/src/catalog/snapshot.ts index dd15c018..3c61170b 100644 --- a/packages/llm/src/catalog/snapshot.ts +++ b/packages/llm/src/catalog/snapshot.ts @@ -1,7 +1,7 @@ // GENERATED FILE — DO NOT EDIT BY HAND. Run `pnpm sync:models`. // // The model-catalog snapshot (ADR-0071). Source: https://models.dev/api.json -// Catalog SHA-256: 4db066a3de7bf27d6f54955958a5cb8f60185826dfe9c77aef7aa0e1a370fdc0 +// Catalog SHA-256: a40975f15ee02a1ecc52383e3636ba9c89fefcf1f0adf7c941107cc5800e1b91 // Models: 80 // // This SHIPS IN THE BINARY on purpose. The cost cap (ADR-0028) is a safety control, and a safety control that @@ -27,6 +27,9 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { cacheWritePerMtokMicrocents: 1250000000, reasoning: { effortValues: ['low', 'medium', 'high', 'xhigh', 'max'] }, requestCapabilities: { temperature: false }, + inputModalities: ['text', 'image', 'pdf'], + outputModalities: ['text'], + description: 'Claude model for creative writing, analysis, and controlled agent workflows', }, 'claude-haiku-4-5': { provider: 'anthropic', @@ -39,6 +42,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { cachedInputPerMtokMicrocents: 10000000, cacheWritePerMtokMicrocents: 125000000, reasoning: { budgetTokens: { min: 1024 } }, + inputModalities: ['text', 'image', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2025-02-28', + description: 'Fast Claude lane for lightweight agents, office tasks, and responsive chat', }, 'claude-haiku-4-5-20251001': { provider: 'anthropic', @@ -51,6 +58,11 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { cachedInputPerMtokMicrocents: 10000000, cacheWritePerMtokMicrocents: 125000000, reasoning: { budgetTokens: { min: 1024 } }, + inputModalities: ['text', 'image', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2025-02-28', + description: + 'Fast Claude model for responsive assistance, classification, and lightweight agents', }, 'claude-opus-4-1': { provider: 'anthropic', @@ -63,6 +75,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { cachedInputPerMtokMicrocents: 150000000, cacheWritePerMtokMicrocents: 1875000000, reasoning: { budgetTokens: { min: 1024 } }, + inputModalities: ['text', 'image', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2025-03-31', + description: 'Flagship Claude model for deep reasoning, coding, and long-horizon agents', }, 'claude-opus-4-1-20250805': { provider: 'anthropic', @@ -75,6 +91,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { cachedInputPerMtokMicrocents: 150000000, cacheWritePerMtokMicrocents: 1875000000, reasoning: { budgetTokens: { min: 1024 } }, + inputModalities: ['text', 'image', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2025-03-31', + description: 'Flagship Claude model for deep reasoning, coding, and long-horizon agents', }, 'claude-opus-4-5': { provider: 'anthropic', @@ -87,6 +107,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { cachedInputPerMtokMicrocents: 50000000, cacheWritePerMtokMicrocents: 625000000, reasoning: { effortValues: ['low', 'medium', 'high'], budgetTokens: { min: 1024 } }, + inputModalities: ['text', 'image', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2025-05', + description: 'Flagship Claude model for deep reasoning, coding, and long-horizon agents', }, 'claude-opus-4-5-20251101': { provider: 'anthropic', @@ -99,6 +123,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { cachedInputPerMtokMicrocents: 50000000, cacheWritePerMtokMicrocents: 625000000, reasoning: { effortValues: ['low', 'medium', 'high'], budgetTokens: { min: 1024 } }, + inputModalities: ['text', 'image', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2025-05', + description: 'Flagship Claude model for deep reasoning, coding, and long-horizon agents', }, 'claude-opus-4-6': { provider: 'anthropic', @@ -111,6 +139,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { cachedInputPerMtokMicrocents: 50000000, cacheWritePerMtokMicrocents: 625000000, reasoning: { effortValues: ['low', 'medium', 'high', 'max'], budgetTokens: { min: 1024 } }, + inputModalities: ['text', 'image', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2025-05-31', + description: 'High-end Claude for difficult coding, planning, and slower expert reasoning', }, 'claude-opus-4-7': { provider: 'anthropic', @@ -124,6 +156,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { cacheWritePerMtokMicrocents: 625000000, reasoning: { effortValues: ['low', 'medium', 'high', 'xhigh', 'max'] }, requestCapabilities: { temperature: false }, + inputModalities: ['text', 'image', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2026-01-31', + description: 'Stronger Opus tier for advanced software work and high-stakes reasoning', }, 'claude-opus-4-8': { provider: 'anthropic', @@ -137,6 +173,27 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { cacheWritePerMtokMicrocents: 625000000, reasoning: { effortValues: ['low', 'medium', 'high', 'xhigh', 'max'] }, requestCapabilities: { temperature: false }, + inputModalities: ['text', 'image', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2026-01', + description: 'Top Claude Opus tier for the hardest reasoning, coding, and long-horizon agents', + }, + 'claude-opus-5': { + provider: 'anthropic', + modelId: 'claude-opus-5', + displayName: 'Claude Opus 5', + contextWindowTokens: 1000000, + maxOutputTokens: 128000, + inputPerMtokMicrocents: 500000000, + outputPerMtokMicrocents: 2500000000, + cachedInputPerMtokMicrocents: 50000000, + cacheWritePerMtokMicrocents: 625000000, + reasoning: { effortValues: ['low', 'medium', 'high', 'xhigh', 'max'] }, + requestCapabilities: { temperature: false }, + inputModalities: ['text', 'image', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2026-05', + description: 'Strongest Claude Opus model for coding, agents, and professional work', }, 'claude-sonnet-4-5': { provider: 'anthropic', @@ -149,6 +206,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { cachedInputPerMtokMicrocents: 30000000, cacheWritePerMtokMicrocents: 375000000, reasoning: { budgetTokens: { min: 1024 } }, + inputModalities: ['text', 'image', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2025-07-31', + description: 'Balanced Claude model for coding, analysis, agent workflows, and cost control', }, 'claude-sonnet-4-5-20250929': { provider: 'anthropic', @@ -161,6 +222,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { cachedInputPerMtokMicrocents: 30000000, cacheWritePerMtokMicrocents: 375000000, reasoning: { budgetTokens: { min: 1024 } }, + inputModalities: ['text', 'image', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2025-07-31', + description: 'Balanced Claude model for coding, analysis, agent workflows, and cost control', }, 'claude-sonnet-4-6': { provider: 'anthropic', @@ -173,6 +238,11 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { cachedInputPerMtokMicrocents: 30000000, cacheWritePerMtokMicrocents: 375000000, reasoning: { effortValues: ['low', 'medium', 'high', 'max'], budgetTokens: { min: 1024 } }, + inputModalities: ['text', 'image', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2025-08-31', + description: + 'Claude workhorse for coding agents, careful analysis, and production cost control', }, 'claude-sonnet-5': { provider: 'anthropic', @@ -186,6 +256,57 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { cacheWritePerMtokMicrocents: 250000000, reasoning: { toggle: true, effortValues: ['low', 'medium', 'high', 'xhigh', 'max'] }, requestCapabilities: { temperature: false }, + inputModalities: ['text', 'image', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2026-01-31', + description: 'Everyday Claude agent model for coding, planning, browsing, and general work', + }, + 'deep-research-max-preview-04-2026': { + provider: 'gemini', + modelId: 'deep-research-max-preview-04-2026', + displayName: 'Deep Research Max Preview (Apr-21-2026)', + contextWindowTokens: 131072, + maxOutputTokens: 65536, + inputPerMtokMicrocents: 200000000, + outputPerMtokMicrocents: 1200000000, + cachedInputPerMtokMicrocents: 20000000, + contextTiers: [ + { + aboveContextTokens: 200000, + inputPerMtokMicrocents: 400000000, + outputPerMtokMicrocents: 1800000000, + cachedInputPerMtokMicrocents: 40000000, + }, + ], + reasoning: {}, + inputModalities: ['text', 'image', 'video', 'audio', 'pdf'], + outputModalities: ['text', 'image'], + knowledgeCutoff: '2025-01', + description: + 'Maximum-comprehensiveness agentic researcher for multi-step investigation, synthesis, and cited reports', + }, + 'deep-research-preview-04-2026': { + provider: 'gemini', + modelId: 'deep-research-preview-04-2026', + displayName: 'Deep Research Preview (Apr-21-2026)', + contextWindowTokens: 131072, + maxOutputTokens: 65536, + inputPerMtokMicrocents: 200000000, + outputPerMtokMicrocents: 1200000000, + cachedInputPerMtokMicrocents: 20000000, + contextTiers: [ + { + aboveContextTokens: 200000, + inputPerMtokMicrocents: 400000000, + outputPerMtokMicrocents: 1800000000, + cachedInputPerMtokMicrocents: 40000000, + }, + ], + reasoning: {}, + inputModalities: ['text', 'image', 'video', 'audio', 'pdf'], + outputModalities: ['text', 'image'], + knowledgeCutoff: '2025-01', + description: 'Agentic model for autonomous multi-step research, synthesis, and cited reports', }, 'deepseek-chat': { provider: 'deepseek', @@ -196,6 +317,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { inputPerMtokMicrocents: 14000000, outputPerMtokMicrocents: 28000000, cachedInputPerMtokMicrocents: 280000, + inputModalities: ['text'], + outputModalities: ['text'], + knowledgeCutoff: '2025-09', + description: 'DeepSeek chat model for instruction following, coding, and analysis', }, 'deepseek-reasoner': { provider: 'deepseek', @@ -207,6 +332,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { outputPerMtokMicrocents: 28000000, cachedInputPerMtokMicrocents: 280000, reasoning: {}, + inputModalities: ['text'], + outputModalities: ['text'], + knowledgeCutoff: '2025-09', + description: 'DeepSeek reasoning model for multi-step analysis, math, coding, and tools', }, 'deepseek-v4-flash': { provider: 'deepseek', @@ -219,6 +348,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { cachedInputPerMtokMicrocents: 280000, reasoning: { toggle: true, effortValues: ['high', 'max'] }, requestCapabilities: { attachment: false }, + inputModalities: ['text'], + outputModalities: ['text'], + knowledgeCutoff: '2025-05', + description: 'Fast DeepSeek V4 lane for economical reasoning, coding, and long-context work', }, 'deepseek-v4-pro': { provider: 'deepseek', @@ -231,6 +364,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { cachedInputPerMtokMicrocents: 362500, reasoning: { toggle: true, effortValues: ['high', 'max'] }, requestCapabilities: { attachment: false }, + inputModalities: ['text'], + outputModalities: ['text'], + knowledgeCutoff: '2025-05', + description: 'Open MoE flagship with million-token context for coding and long agent runs', }, 'gemini-2.0-flash': { provider: 'gemini', @@ -241,6 +378,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { inputPerMtokMicrocents: 10000000, outputPerMtokMicrocents: 40000000, cachedInputPerMtokMicrocents: 2500000, + inputModalities: ['text', 'image', 'audio', 'video', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2024-06', + description: 'Earlier Gemini Flash workhorse for responsive multimodal apps and tool use', }, 'gemini-2.0-flash-lite': { provider: 'gemini', @@ -250,6 +391,31 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { maxOutputTokens: 8192, inputPerMtokMicrocents: 7500000, outputPerMtokMicrocents: 30000000, + inputModalities: ['text', 'image', 'audio', 'video', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2024-06', + description: 'Legacy model retained for compatibility with older integrations', + }, + 'gemini-2.5-computer-use-preview-10-2025': { + provider: 'gemini', + modelId: 'gemini-2.5-computer-use-preview-10-2025', + displayName: 'Gemini 2.5 Computer Use Preview 10-2025', + contextWindowTokens: 131072, + maxOutputTokens: 65536, + inputPerMtokMicrocents: 125000000, + outputPerMtokMicrocents: 1000000000, + contextTiers: [ + { + aboveContextTokens: 200000, + inputPerMtokMicrocents: 250000000, + outputPerMtokMicrocents: 1500000000, + }, + ], + reasoning: {}, + inputModalities: ['text', 'image'], + outputModalities: ['text'], + knowledgeCutoff: '2025-01', + description: 'Specialized Gemini 2.5 model for browser-control agents that automate UI tasks', }, 'gemini-2.5-flash': { provider: 'gemini', @@ -261,6 +427,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { outputPerMtokMicrocents: 250000000, cachedInputPerMtokMicrocents: 3000000, reasoning: { toggle: true, budgetTokens: { min: 0, max: 24576 } }, + inputModalities: ['text', 'image', 'audio', 'video', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2025-01', + description: 'Fast Gemini workhorse for multimodal apps where latency and price matter', }, 'gemini-2.5-flash-lite': { provider: 'gemini', @@ -272,6 +442,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { outputPerMtokMicrocents: 40000000, cachedInputPerMtokMicrocents: 1000000, reasoning: { toggle: true, budgetTokens: { min: 512, max: 24576 } }, + inputModalities: ['text', 'image', 'audio', 'video', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2025-01', + description: 'Lean Gemini 2.5 lane for cheap multimodal traffic and quick agents', }, 'gemini-2.5-pro': { provider: 'gemini', @@ -291,6 +465,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { }, ], reasoning: { budgetTokens: { min: 128, max: 32768 } }, + inputModalities: ['text', 'image', 'audio', 'video', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2025-01', + description: "Google's proven reasoning model for coding, math, and multimodal analysis", }, 'gemini-3-flash-preview': { provider: 'gemini', @@ -302,6 +480,11 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { outputPerMtokMicrocents: 300000000, cachedInputPerMtokMicrocents: 5000000, reasoning: { effortValues: ['minimal', 'low', 'medium', 'high'] }, + inputModalities: ['text', 'image', 'video', 'audio', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2025-01', + description: + 'New Gemini flash lane bringing frontier-style multimodal reasoning to cheaper runs', }, 'gemini-3-pro-preview': { provider: 'gemini', @@ -321,6 +504,11 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { }, ], reasoning: { effortValues: ['low', 'high'] }, + inputModalities: ['text', 'image', 'video', 'audio', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2025-01', + description: + 'Preview Gemini flagship for complex reasoning, coding, and rich multimodal prompts', }, 'gemini-3.1-flash-lite': { provider: 'gemini', @@ -332,6 +520,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { outputPerMtokMicrocents: 150000000, cachedInputPerMtokMicrocents: 2500000, reasoning: { effortValues: ['minimal', 'low', 'medium', 'high'] }, + inputModalities: ['text', 'image', 'video', 'audio', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2025-01', + description: 'Low-latency Gemini model for high-volume multimodal and agent workloads', }, 'gemini-3.1-flash-lite-preview': { provider: 'gemini', @@ -343,6 +535,26 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { outputPerMtokMicrocents: 150000000, cachedInputPerMtokMicrocents: 2500000, reasoning: { effortValues: ['minimal', 'low', 'medium', 'high'] }, + inputModalities: ['text', 'image', 'video', 'audio', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2025-01', + description: 'Legacy model retained for compatibility with older integrations', + }, + 'gemini-3.1-flash-live-preview': { + provider: 'gemini', + modelId: 'gemini-3.1-flash-live-preview', + displayName: 'Gemini 3.1 Flash Live Preview', + contextWindowTokens: 131072, + maxOutputTokens: 65536, + inputPerMtokMicrocents: 75000000, + outputPerMtokMicrocents: 450000000, + reasoning: { effortValues: ['minimal', 'low', 'medium', 'high'] }, + requestCapabilities: { structuredOutput: false }, + inputModalities: ['text', 'image', 'video', 'audio'], + outputModalities: ['text', 'audio'], + knowledgeCutoff: '2025-01', + description: + 'High-quality, low-latency Live API model for real-time dialogue and voice-first AI applications', }, 'gemini-3.1-pro-preview': { provider: 'gemini', @@ -362,6 +574,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { }, ], reasoning: { effortValues: ['low', 'medium', 'high'] }, + inputModalities: ['text', 'image', 'video', 'audio', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2025-01', + description: 'Reasoning-first Gemini preview for agentic coding and complex problem solving', }, 'gemini-3.1-pro-preview-customtools': { provider: 'gemini', @@ -381,6 +597,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { }, ], reasoning: { effortValues: ['low', 'medium', 'high'] }, + inputModalities: ['text', 'image', 'video', 'audio', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2025-01', + description: 'Advanced Gemini model for complex reasoning, coding, and multimodal analysis', }, 'gemini-3.5-flash': { provider: 'gemini', @@ -392,6 +612,55 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { outputPerMtokMicrocents: 900000000, cachedInputPerMtokMicrocents: 15000000, reasoning: { effortValues: ['minimal', 'low', 'medium', 'high'] }, + inputModalities: ['text', 'image', 'video', 'audio', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2025-01', + description: 'Fast Gemini model balancing multimodal reasoning, tool use, and cost', + }, + 'gemini-3.5-flash-lite': { + provider: 'gemini', + modelId: 'gemini-3.5-flash-lite', + displayName: 'Gemini 3.5 Flash Lite', + contextWindowTokens: 1048576, + maxOutputTokens: 65536, + inputPerMtokMicrocents: 30000000, + outputPerMtokMicrocents: 250000000, + cachedInputPerMtokMicrocents: 3000000, + reasoning: { effortValues: ['minimal', 'low', 'medium', 'high'] }, + inputModalities: ['text', 'image', 'video', 'audio', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2026-03', + description: 'Fast Gemini model balancing multimodal reasoning, tool use, and cost', + }, + 'gemini-3.5-live-translate-preview': { + provider: 'gemini', + modelId: 'gemini-3.5-live-translate-preview', + displayName: 'Gemini 3.5 Live Translate Preview', + contextWindowTokens: 16384, + maxOutputTokens: 32768, + inputPerMtokMicrocents: 350000000, + outputPerMtokMicrocents: 2100000000, + requestCapabilities: { toolCall: false, attachment: false }, + inputModalities: ['audio'], + outputModalities: ['audio', 'text'], + knowledgeCutoff: '2025-01', + description: + 'Low-latency audio-to-audio model for real-time speech translation across 70+ languages', + }, + 'gemini-3.6-flash': { + provider: 'gemini', + modelId: 'gemini-3.6-flash', + displayName: 'Gemini 3.6 Flash', + contextWindowTokens: 1048576, + maxOutputTokens: 65536, + inputPerMtokMicrocents: 150000000, + outputPerMtokMicrocents: 750000000, + cachedInputPerMtokMicrocents: 15000000, + reasoning: { effortValues: ['minimal', 'low', 'medium', 'high'] }, + inputModalities: ['text', 'image', 'video', 'audio', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2026-03', + description: 'Fast Gemini model balancing multimodal reasoning, tool use, and cost', }, 'gemini-flash-latest': { provider: 'gemini', @@ -399,10 +668,14 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { displayName: 'Gemini Flash Latest', contextWindowTokens: 1048576, maxOutputTokens: 65536, - inputPerMtokMicrocents: 30000000, - outputPerMtokMicrocents: 250000000, - cachedInputPerMtokMicrocents: 7500000, - reasoning: { toggle: true, budgetTokens: { min: 0, max: 24576 } }, + inputPerMtokMicrocents: 150000000, + outputPerMtokMicrocents: 900000000, + cachedInputPerMtokMicrocents: 15000000, + reasoning: { effortValues: ['minimal', 'low', 'medium', 'high'] }, + inputModalities: ['text', 'image', 'video', 'audio', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2025-01', + description: 'Fast Gemini model balancing multimodal reasoning, tool use, and cost', }, 'gemini-flash-lite-latest': { provider: 'gemini', @@ -410,10 +683,14 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { displayName: 'Gemini Flash-Lite Latest', contextWindowTokens: 1048576, maxOutputTokens: 65536, - inputPerMtokMicrocents: 10000000, - outputPerMtokMicrocents: 40000000, + inputPerMtokMicrocents: 25000000, + outputPerMtokMicrocents: 150000000, cachedInputPerMtokMicrocents: 2500000, - reasoning: { toggle: true, budgetTokens: { min: 512, max: 24576 } }, + reasoning: { effortValues: ['minimal', 'low', 'medium', 'high'] }, + inputModalities: ['text', 'image', 'video', 'audio', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2025-01', + description: 'Low-latency Gemini model for high-volume multimodal and agent workloads', }, 'gemini-omni-flash-preview': { provider: 'gemini', @@ -425,6 +702,25 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { outputPerMtokMicrocents: 1750000000, reasoning: {}, requestCapabilities: { toolCall: false }, + inputModalities: ['text', 'image', 'video'], + outputModalities: ['video'], + description: + 'Video generation and editing model for fast, conversational text- and image-to-video workflows', + }, + 'gemini-robotics-er-1.6-preview': { + provider: 'gemini', + modelId: 'gemini-robotics-er-1.6-preview', + displayName: 'Gemini Robotics-ER 1.6 Preview', + contextWindowTokens: 131072, + maxOutputTokens: 65536, + inputPerMtokMicrocents: 100000000, + outputPerMtokMicrocents: 500000000, + reasoning: { toggle: true, budgetTokens: { min: 0 } }, + inputModalities: ['text', 'image', 'video', 'audio'], + outputModalities: ['text'], + knowledgeCutoff: '2025-01', + description: + 'Vision-language model for embodied reasoning: spatial understanding, task planning, and physical-world agentic robotics', }, 'gpt-3.5-turbo': { provider: 'openai', @@ -436,6 +732,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { outputPerMtokMicrocents: 150000000, cachedInputPerMtokMicrocents: 0, requestCapabilities: { toolCall: false, structuredOutput: false, attachment: false }, + inputModalities: ['text'], + outputModalities: ['text'], + knowledgeCutoff: '2021-09-01', + description: 'Compact GPT model for low-latency assistance and high-volume workloads', }, 'gpt-4': { provider: 'openai', @@ -446,6 +746,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { inputPerMtokMicrocents: 3000000000, outputPerMtokMicrocents: 6000000000, requestCapabilities: { structuredOutput: false }, + inputModalities: ['text'], + outputModalities: ['text'], + knowledgeCutoff: '2023-11', + description: 'GPT model for general reasoning, writing, coding, and tool-assisted tasks', }, 'gpt-4-turbo': { provider: 'openai', @@ -456,6 +760,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { inputPerMtokMicrocents: 1000000000, outputPerMtokMicrocents: 3000000000, requestCapabilities: { structuredOutput: false }, + inputModalities: ['text', 'image'], + outputModalities: ['text'], + knowledgeCutoff: '2023-12', + description: 'Compact GPT model for low-latency assistance and high-volume workloads', }, 'gpt-4.1': { provider: 'openai', @@ -466,6 +774,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { inputPerMtokMicrocents: 200000000, outputPerMtokMicrocents: 800000000, cachedInputPerMtokMicrocents: 50000000, + inputModalities: ['text', 'image', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2024-04', + description: 'Long-lived GPT workhorse for coding, instruction following, and production apps', }, 'gpt-4.1-mini': { provider: 'openai', @@ -476,6 +788,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { inputPerMtokMicrocents: 40000000, outputPerMtokMicrocents: 160000000, cachedInputPerMtokMicrocents: 10000000, + inputModalities: ['text', 'image', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2024-04', + description: 'Affordable GPT-4.1 lane for fast coding help and structured extraction', }, 'gpt-4.1-nano': { provider: 'openai', @@ -486,6 +802,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { inputPerMtokMicrocents: 10000000, outputPerMtokMicrocents: 40000000, cachedInputPerMtokMicrocents: 2500000, + inputModalities: ['text', 'image'], + outputModalities: ['text'], + knowledgeCutoff: '2024-04', + description: 'Tiny GPT-4.1 option for classification, routing, and very high-volume tasks', }, 'gpt-4o': { provider: 'openai', @@ -496,6 +816,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { inputPerMtokMicrocents: 250000000, outputPerMtokMicrocents: 1000000000, cachedInputPerMtokMicrocents: 125000000, + inputModalities: ['text', 'image', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2023-09', + description: 'Omni-era GPT for multimodal chat, practical coding, and general assistants', }, 'gpt-4o-2024-05-13': { provider: 'openai', @@ -505,6 +829,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { maxOutputTokens: 4096, inputPerMtokMicrocents: 500000000, outputPerMtokMicrocents: 1500000000, + inputModalities: ['text', 'image'], + outputModalities: ['text'], + knowledgeCutoff: '2023-09', + description: 'GPT model for general reasoning, writing, coding, and tool-assisted tasks', }, 'gpt-4o-2024-08-06': { provider: 'openai', @@ -515,6 +843,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { inputPerMtokMicrocents: 250000000, outputPerMtokMicrocents: 1000000000, cachedInputPerMtokMicrocents: 125000000, + inputModalities: ['text', 'image'], + outputModalities: ['text'], + knowledgeCutoff: '2023-09', + description: 'GPT model for general reasoning, writing, coding, and tool-assisted tasks', }, 'gpt-4o-2024-11-20': { provider: 'openai', @@ -525,6 +857,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { inputPerMtokMicrocents: 250000000, outputPerMtokMicrocents: 1000000000, cachedInputPerMtokMicrocents: 125000000, + inputModalities: ['text', 'image'], + outputModalities: ['text'], + knowledgeCutoff: '2023-09', + description: 'GPT model for general reasoning, writing, coding, and tool-assisted tasks', }, 'gpt-4o-mini': { provider: 'openai', @@ -535,6 +871,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { inputPerMtokMicrocents: 15000000, outputPerMtokMicrocents: 60000000, cachedInputPerMtokMicrocents: 7500000, + inputModalities: ['text', 'image', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2023-09', + description: 'Small omni GPT for cheap multimodal assistance and production-scale traffic', }, 'gpt-5': { provider: 'openai', @@ -547,30 +887,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { cachedInputPerMtokMicrocents: 12500000, reasoning: { effortValues: ['minimal', 'low', 'medium', 'high'] }, requestCapabilities: { temperature: false }, - }, - 'gpt-5-chat-latest': { - provider: 'openai', - modelId: 'gpt-5-chat-latest', - displayName: 'GPT-5 Chat (latest)', - contextWindowTokens: 400000, - maxOutputTokens: 128000, - inputPerMtokMicrocents: 125000000, - outputPerMtokMicrocents: 1000000000, - cachedInputPerMtokMicrocents: 12500000, - reasoning: {}, - requestCapabilities: { toolCall: false }, - }, - 'gpt-5-codex': { - provider: 'openai', - modelId: 'gpt-5-codex', - displayName: 'GPT-5-Codex', - contextWindowTokens: 400000, - maxOutputTokens: 128000, - inputPerMtokMicrocents: 125000000, - outputPerMtokMicrocents: 1000000000, - cachedInputPerMtokMicrocents: 12500000, - reasoning: { effortValues: ['low', 'medium', 'high'] }, - requestCapabilities: { temperature: false, attachment: false }, + inputModalities: ['text', 'image'], + outputModalities: ['text'], + knowledgeCutoff: '2024-09-30', + description: 'Original GPT-5 workhorse for reasoning, coding, writing, and tool workflows', }, 'gpt-5-mini': { provider: 'openai', @@ -583,6 +903,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { cachedInputPerMtokMicrocents: 2500000, reasoning: { effortValues: ['minimal', 'low', 'medium', 'high'] }, requestCapabilities: { temperature: false }, + inputModalities: ['text', 'image'], + outputModalities: ['text'], + knowledgeCutoff: '2024-05-30', + description: 'Small GPT-5 for responsive agents, coding help, and everyday automation', }, 'gpt-5-nano': { provider: 'openai', @@ -595,6 +919,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { cachedInputPerMtokMicrocents: 500000, reasoning: { effortValues: ['minimal', 'low', 'medium', 'high'] }, requestCapabilities: { temperature: false }, + inputModalities: ['text', 'image'], + outputModalities: ['text'], + knowledgeCutoff: '2024-05-30', + description: 'Tiny GPT-5 lane for routing, extraction, classification, and bulk jobs', }, 'gpt-5-pro': { provider: 'openai', @@ -606,6 +934,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { outputPerMtokMicrocents: 12000000000, reasoning: { effortValues: ['high'] }, requestCapabilities: { temperature: false }, + inputModalities: ['text', 'image'], + outputModalities: ['text'], + knowledgeCutoff: '2024-09-30', + description: 'Higher-accuracy GPT-5 tier for tough analysis, coding reviews, and planning', }, 'gpt-5.1': { provider: 'openai', @@ -618,54 +950,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { cachedInputPerMtokMicrocents: 12500000, reasoning: { effortValues: ['none', 'low', 'medium', 'high'] }, requestCapabilities: { temperature: false }, - }, - 'gpt-5.1-chat-latest': { - provider: 'openai', - modelId: 'gpt-5.1-chat-latest', - displayName: 'GPT-5.1 Chat', - contextWindowTokens: 128000, - maxOutputTokens: 16384, - inputPerMtokMicrocents: 125000000, - outputPerMtokMicrocents: 1000000000, - cachedInputPerMtokMicrocents: 12500000, - reasoning: { effortValues: ['medium'] }, - requestCapabilities: { temperature: false }, - }, - 'gpt-5.1-codex': { - provider: 'openai', - modelId: 'gpt-5.1-codex', - displayName: 'GPT-5.1 Codex', - contextWindowTokens: 400000, - maxOutputTokens: 128000, - inputPerMtokMicrocents: 125000000, - outputPerMtokMicrocents: 1000000000, - cachedInputPerMtokMicrocents: 12500000, - reasoning: { effortValues: ['low', 'medium', 'high'] }, - requestCapabilities: { temperature: false }, - }, - 'gpt-5.1-codex-max': { - provider: 'openai', - modelId: 'gpt-5.1-codex-max', - displayName: 'GPT-5.1 Codex Max', - contextWindowTokens: 400000, - maxOutputTokens: 128000, - inputPerMtokMicrocents: 125000000, - outputPerMtokMicrocents: 1000000000, - cachedInputPerMtokMicrocents: 12500000, - reasoning: { effortValues: ['low', 'medium', 'high', 'xhigh'] }, - requestCapabilities: { temperature: false }, - }, - 'gpt-5.1-codex-mini': { - provider: 'openai', - modelId: 'gpt-5.1-codex-mini', - displayName: 'GPT-5.1 Codex mini', - contextWindowTokens: 400000, - maxOutputTokens: 128000, - inputPerMtokMicrocents: 25000000, - outputPerMtokMicrocents: 200000000, - cachedInputPerMtokMicrocents: 2500000, - reasoning: { effortValues: ['low', 'medium', 'high'] }, - requestCapabilities: { temperature: false }, + inputModalities: ['text', 'image'], + outputModalities: ['text'], + knowledgeCutoff: '2024-09-30', + description: 'Sharper GPT-5 generation for coding, product work, and tool-assisted tasks', }, 'gpt-5.2': { provider: 'openai', @@ -678,6 +966,11 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { cachedInputPerMtokMicrocents: 17500000, reasoning: { effortValues: ['none', 'low', 'medium', 'high', 'xhigh'] }, requestCapabilities: { temperature: false }, + inputModalities: ['text', 'image'], + outputModalities: ['text'], + knowledgeCutoff: '2025-08-31', + description: + 'Reliable GPT generation for broad coding, writing, and tool-assisted product work', }, 'gpt-5.2-chat-latest': { provider: 'openai', @@ -690,18 +983,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { cachedInputPerMtokMicrocents: 17500000, reasoning: { effortValues: ['medium'] }, requestCapabilities: { temperature: false }, - }, - 'gpt-5.2-codex': { - provider: 'openai', - modelId: 'gpt-5.2-codex', - displayName: 'GPT-5.2 Codex', - contextWindowTokens: 400000, - maxOutputTokens: 128000, - inputPerMtokMicrocents: 175000000, - outputPerMtokMicrocents: 1400000000, - cachedInputPerMtokMicrocents: 17500000, - reasoning: { effortValues: ['low', 'medium', 'high', 'xhigh'] }, - requestCapabilities: { temperature: false }, + inputModalities: ['text', 'image'], + outputModalities: ['text'], + knowledgeCutoff: '2025-08-31', + description: 'Chat-tuned GPT model for conversational assistance, writing, and tool workflows', }, 'gpt-5.2-pro': { provider: 'openai', @@ -713,6 +998,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { outputPerMtokMicrocents: 16800000000, reasoning: { effortValues: ['medium', 'high', 'xhigh'] }, requestCapabilities: { temperature: false, structuredOutput: false }, + inputModalities: ['text', 'image'], + outputModalities: ['text'], + knowledgeCutoff: '2025-08-31', + description: 'Higher-accuracy GPT-5.2 variant for tougher reasoning and review workflows', }, 'gpt-5.3-chat-latest': { provider: 'openai', @@ -723,6 +1012,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { inputPerMtokMicrocents: 175000000, outputPerMtokMicrocents: 1400000000, cachedInputPerMtokMicrocents: 17500000, + inputModalities: ['text', 'image'], + outputModalities: ['text'], + knowledgeCutoff: '2025-08-31', + description: 'Chat-tuned GPT model for conversational assistance, writing, and tool workflows', }, 'gpt-5.3-codex': { provider: 'openai', @@ -735,6 +1028,11 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { cachedInputPerMtokMicrocents: 17500000, reasoning: { effortValues: ['none', 'low', 'medium', 'high', 'xhigh'] }, requestCapabilities: { temperature: false }, + inputModalities: ['text', 'image', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2025-08-31', + description: + 'Coding-optimized GPT model for repository edits, reviews, and agentic software work', }, 'gpt-5.3-codex-spark': { provider: 'openai', @@ -747,6 +1045,11 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { cachedInputPerMtokMicrocents: 17500000, reasoning: { effortValues: ['none', 'low', 'medium', 'high', 'xhigh'] }, requestCapabilities: { temperature: false }, + inputModalities: ['text', 'image', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2025-08-31', + description: + 'Coding-optimized GPT model for repository edits, reviews, and agentic software work', }, 'gpt-5.4': { provider: 'openai', @@ -767,6 +1070,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { ], reasoning: { effortValues: ['none', 'low', 'medium', 'high', 'xhigh'] }, requestCapabilities: { temperature: false }, + inputModalities: ['text', 'image', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2025-08-31', + description: 'Agent-ready GPT for coding and computer-use workflows at a lower cost', }, 'gpt-5.4-mini': { provider: 'openai', @@ -779,6 +1086,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { cachedInputPerMtokMicrocents: 7500000, reasoning: { effortValues: ['none', 'low', 'medium', 'high', 'xhigh'] }, requestCapabilities: { temperature: false }, + inputModalities: ['text', 'image'], + outputModalities: ['text'], + knowledgeCutoff: '2025-08-31', + description: 'Strong small GPT for coding subagents, quick tool use, and high-volume work', }, 'gpt-5.4-nano': { provider: 'openai', @@ -791,6 +1102,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { cachedInputPerMtokMicrocents: 2000000, reasoning: { effortValues: ['none', 'low', 'medium', 'high', 'xhigh'] }, requestCapabilities: { temperature: false }, + inputModalities: ['text', 'image'], + outputModalities: ['text'], + knowledgeCutoff: '2025-08-31', + description: 'Cheapest GPT-5.4 lane for simple routing, extraction, and bulk automation', }, 'gpt-5.4-pro': { provider: 'openai', @@ -809,6 +1124,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { ], reasoning: { effortValues: ['medium', 'high', 'xhigh'] }, requestCapabilities: { temperature: false, structuredOutput: false }, + inputModalities: ['text', 'image'], + outputModalities: ['text'], + knowledgeCutoff: '2025-08-31', + description: 'More exact GPT-5.4 tier for demanding professional reasoning and agent tasks', }, 'gpt-5.5': { provider: 'openai', @@ -829,6 +1148,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { ], reasoning: { effortValues: ['none', 'low', 'medium', 'high', 'xhigh'] }, requestCapabilities: { temperature: false }, + inputModalities: ['text', 'image', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2025-12-01', + description: 'Default frontier GPT for coding, computer use, research, and knowledge work', }, 'gpt-5.5-pro': { provider: 'openai', @@ -847,6 +1170,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { ], reasoning: { effortValues: ['medium', 'high', 'xhigh'] }, requestCapabilities: { temperature: false }, + inputModalities: ['text', 'image', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2025-12-01', + description: 'Highest-accuracy GPT-5.5 tier for slower, precision-heavy reasoning and coding', }, 'gpt-5.6': { provider: 'openai', @@ -868,6 +1195,11 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { ], reasoning: { effortValues: ['none', 'low', 'medium', 'high', 'xhigh', 'max'] }, requestCapabilities: { temperature: false }, + inputModalities: ['text', 'image', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2026-02-16', + description: + 'Frontier GPT-5.6 model for complex professional work, coding, and agentic workflows', }, 'gpt-5.6-luna': { provider: 'openai', @@ -889,6 +1221,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { ], reasoning: { effortValues: ['none', 'low', 'medium', 'high', 'xhigh', 'max'] }, requestCapabilities: { temperature: false }, + inputModalities: ['text', 'image', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2026-02-16', + description: 'Cost-efficient GPT-5.6 model for fast, high-volume workloads', }, 'gpt-5.6-sol': { provider: 'openai', @@ -910,6 +1246,11 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { ], reasoning: { effortValues: ['none', 'low', 'medium', 'high', 'xhigh', 'max'] }, requestCapabilities: { temperature: false }, + inputModalities: ['text', 'image', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2026-02-16', + description: + 'Frontier GPT-5.6 model for complex professional work, coding, and agentic workflows', }, 'gpt-5.6-terra': { provider: 'openai', @@ -931,6 +1272,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { ], reasoning: { effortValues: ['none', 'low', 'medium', 'high', 'xhigh', 'max'] }, requestCapabilities: { temperature: false }, + inputModalities: ['text', 'image', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2026-02-16', + description: 'Balanced GPT-5.6 model for capable, cost-efficient everyday work', }, o1: { provider: 'openai', @@ -943,6 +1288,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { cachedInputPerMtokMicrocents: 750000000, reasoning: { effortValues: ['low', 'medium', 'high'] }, requestCapabilities: { temperature: false }, + inputModalities: ['text', 'image', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2023-09', + description: 'O-series reasoning model for hard analysis, math, coding, and planning', }, 'o1-pro': { provider: 'openai', @@ -954,6 +1303,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { outputPerMtokMicrocents: 60000000000, reasoning: { effortValues: ['low', 'medium', 'high'] }, requestCapabilities: { temperature: false }, + inputModalities: ['text', 'image'], + outputModalities: ['text'], + knowledgeCutoff: '2023-09', + description: 'O-series reasoning model for hard analysis, math, coding, and planning', }, o3: { provider: 'openai', @@ -966,18 +1319,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { cachedInputPerMtokMicrocents: 50000000, reasoning: { effortValues: ['low', 'medium', 'high'] }, requestCapabilities: { temperature: false }, - }, - 'o3-deep-research': { - provider: 'openai', - modelId: 'o3-deep-research', - displayName: 'o3-deep-research', - contextWindowTokens: 200000, - maxOutputTokens: 100000, - inputPerMtokMicrocents: 1000000000, - outputPerMtokMicrocents: 4000000000, - cachedInputPerMtokMicrocents: 250000000, - reasoning: { effortValues: ['medium'] }, - requestCapabilities: { temperature: false }, + inputModalities: ['text', 'image', 'pdf'], + outputModalities: ['text'], + knowledgeCutoff: '2024-05', + description: 'Deliberate o-series reasoner for hard math, coding, and multi-step analysis', }, 'o3-mini': { provider: 'openai', @@ -990,6 +1335,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { cachedInputPerMtokMicrocents: 55000000, reasoning: { effortValues: ['low', 'medium', 'high'] }, requestCapabilities: { temperature: false, attachment: false }, + inputModalities: ['text'], + outputModalities: ['text'], + knowledgeCutoff: '2024-05', + description: 'Smaller o-series reasoner for economical coding, math, and planning tasks', }, 'o3-pro': { provider: 'openai', @@ -1001,6 +1350,10 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { outputPerMtokMicrocents: 8000000000, reasoning: { effortValues: ['low', 'medium', 'high'] }, requestCapabilities: { temperature: false }, + inputModalities: ['text', 'image'], + outputModalities: ['text'], + knowledgeCutoff: '2024-05', + description: 'High-effort o3 tier for difficult technical reasoning and careful answers', }, 'o4-mini': { provider: 'openai', @@ -1013,20 +1366,12 @@ export const CATALOG_SNAPSHOT: CatalogSnapshot = { cachedInputPerMtokMicrocents: 27500000, reasoning: { effortValues: ['low', 'medium', 'high'] }, requestCapabilities: { temperature: false }, - }, - 'o4-mini-deep-research': { - provider: 'openai', - modelId: 'o4-mini-deep-research', - displayName: 'o4-mini-deep-research', - contextWindowTokens: 200000, - maxOutputTokens: 100000, - inputPerMtokMicrocents: 200000000, - outputPerMtokMicrocents: 800000000, - cachedInputPerMtokMicrocents: 50000000, - reasoning: { effortValues: ['medium'] }, - requestCapabilities: { temperature: false }, + inputModalities: ['text', 'image'], + outputModalities: ['text'], + knowledgeCutoff: '2024-05', + description: 'Fast o-series model for compact reasoning, coding, and tool use', }, }; /** The SHA-256 of this catalog's own data — changes when, and only when, what we ship changes. */ -export const CATALOG_SHA256 = '4db066a3de7bf27d6f54955958a5cb8f60185826dfe9c77aef7aa0e1a370fdc0'; +export const CATALOG_SHA256 = 'a40975f15ee02a1ecc52383e3636ba9c89fefcf1f0adf7c941107cc5800e1b91';