feat: model + thinking control — the stats bar's picker, on pi-ai's catalog

The model-control wave (user-decided design, 2026-09-12): ONE controller
for the conversation agents (prober/teacher are functionally one agent);
background sub-agents stay config-pinned. pi-ai owns the registry — the
shipped 366-model OpenRouter catalog (cost, context, modality,
thinkingLevelMap), getSupportedThinkingLevels/clampThinkingLevel for the
per-model thinking truth, and streamSimple's automatic clamp. No second
registry to drift out of sync.

Seams:
- config.ts: ReasoningEffort retired for pi's ThinkingLevel
  (off|minimal|low|medium|high|xhigh|max). GLM roles go honest at "low" —
  pi's catalog says GLM-5.3-flash accepts exactly low|high|max, and the old
  "minimal" was silently clamped to low by streamSimple since the swap;
  nothing changes behaviorally. visualMaker → qwen/qwen3.8-flash (fixes
  the dead qwen/qwen3.8-max slug — the catalog only ships -0902; also the
  user's cost pick, 0.15/0.47 per-1M).
- src/agent/models.ts: piEngineFor(role, settings?) — provider+id resolved
  from the catalog, thinking level from settings ?? config, CLAMPED to the
  model's supported list (a settings change between models can never send
  an invalid level). PiEngine gains `level` (observability/tests).
- ChatRecord.settings {model?: {provider, id}, thinkingLevel?} — written
  by PUT /api/chats/[id]/settings (replace-whole, no updatedAt churn),
  read by chat-handler at turn composition: agents are stateless per turn,
  so the change is next-turn-effective by construction. The turns log
  still records the ACTUAL billed model (the honest witness).
- GET /api/models: the configured-provider catalog as client-safe DTOs
  (core/contracts/models.ts) + config defaults; a second provider joins
  the picker by registering it in piModels() — nothing else changes.
- PUT settings validation gate (src/server/model-catalog.ts): unknown
  provider/model or unsupported level → 400 carrying the supported list,
  never a silent clamp.
- scripts/sync-pricing.ts: regenerated PRICES/CONTEXT_LIMITS from pi-ai's
  shipped openrouter.json (offline; same source as the engine + picker).
  All 366 models priced; glm's stale 0.15/0.5 → pi's 0.075/0.25, limit
  1310720 → 1048576 — cost is inferred at read time, so history re-prices.
- UI (components/model-picker.tsx): stats-bar right side becomes model +
  thinking buttons; menus open ABOVE; fuzzy search over "provider id
  name" (core/fuzzy.ts — pi's /model pattern); model rows show name/id/
  price/context; the thinking menu lists exactly the chosen model's
  supported levels (GLM: low|high|max — no dead options, no "off").
  Model switch drops an incompatible pinned level (falls back to config,
  which clamps honestly) rather than carrying a 400.

Tests (350/350, +15): catalog projection + defaults, the settings gate,
pi thinking truth pinned against upgrades (glm low|high|max; minimal→low;
off→low — GLM cannot disable thinking), the engine factory's
override/fallback/clamp/throw matrix, fuzzy ranking, store round-trip,
and the re-priced folds (usage, stats bar, activity dock).

Live smoke (disposable driver, deleted): catalog route 366 + defaults;
glm+minimal → 400 + supported; turn 1 billed qwen/qwen3.8-flash under
the override; mid-session switch flipped turn 2 to glm; clear-overrides
restored the config pin. ALL CHECKS PASS on real OpenRouter.
This commit is contained in:
amosblomqvist
2026-09-12 06:02:40 +03:00
parent 740293c361
commit de0c286311
26 changed files with 1649 additions and 131 deletions
+1
View File
@@ -14,3 +14,4 @@ export * from "./contracts/graph.ts";
export * from "./contracts/chat.ts";
export * from "./contracts/jobs.ts";
export * from "./contracts/probe.ts";
export * from "./contracts/models.ts";
+24
View File
@@ -7,6 +7,7 @@
* of "ai" (safe everywhere: server, client, tests). See docs/vision.md.
*/
import type { UIMessage } from "ai";
import type { ThinkingLevel } from "@earendil-works/pi-agent-core";
import type { Phase3 } from "../phases.ts";
import type { PlanNodeStatus, PlanTree } from "./plan.ts";
import type { EmissionStats } from "./graph.ts";
@@ -38,6 +39,25 @@ export interface ChatRecord {
* spend too. Same parallel-log discipline as `turns` (nothing rides
* inside messages). Keyed by startedAt; idempotent appends. */
extractions?: ExtractionRunUsage[];
/** Per-chat model/thinking overrides for the conversation agents. */
settings?: ChatSettings;
}
/** The conversation agents' runtime model choice (model-control wave,
* 2026-09-12): a per-chat override of config.ts's pinned prober/teacher
* spec. Absent fields fall back to config; written by the model picker
* (PUT /api/chats/[id]/settings) and read at turn composition — the
* agents are stateless per turn, so a change takes effect on the next
* turn by construction. Background sub-agents are NEVER overridden
* (config-pinned: they're infrastructure, not conversation). */
export interface ChatSettings {
/** pi-ai catalog coordinates: the provider that owns the model. Only
* "openrouter" is configured today; the field exists so a second
* provider needs no schema change. */
model?: { provider: string; id: string };
/** pi thinking level — must be in the chosen model's supported list
* (getSupportedThinkingLevels; enforced by the settings route). */
thinkingLevel?: ThinkingLevel;
}
// ─── Background-extraction usage (the money channel, extraction side) ────────
@@ -191,6 +211,10 @@ export interface ChatSummary {
phase: Phase3;
/** An unanswered quiz/ask question is waiting for the learner. */
pendingQuestion: boolean;
/** The record's model-control settings — rides the list payload via the
* summary spread (the picker never needs it from here; the full record
* is its source). */
settings?: ChatSettings;
}
/** The sidebar's session row: a summary + live liveness. The chats list
+39
View File
@@ -0,0 +1,39 @@
/**
* Model-catalog contracts (model-control wave, 2026-09-12) — the client-safe
* shapes of GET /api/models and PUT /api/chats/[id]/settings responses.
* Pure types; the server projection lives in src/server/model-catalog.ts
* (which OWNS these shapes — the contract is defined here only so client
* components never import from the server band).
*/
import type { ThinkingLevel } from "@earendil-works/pi-agent-core";
/** One picker row: everything the UI shows about a model, projected from
* pi-ai's catalog. Costs are USD per 1M tokens (the same catalog, the same
* units core/prices.ts's generated table carries). */
export interface ModelCatalogEntry {
id: string;
name: string;
provider: string;
reasoning: boolean;
input: ("text" | "image")[];
/** The thinking levels this model actually accepts (pi's
* thinkingLevelMap — e.g. GLM-5.3-flash: low|high|max). The thinking
* picker lists exactly these; anything else is a lie. */
supportedLevels: ThinkingLevel[];
cost: { input: number; output: number; cacheRead: number; cacheWrite: number };
contextWindow: number;
maxTokens: number;
}
/** The conversation agents' config pin (config.ts MODELS prober/teacher —
* one controller, so one pin): what a chat without settings runs. */
export interface CatalogDefaults {
model: { provider: string; id: string };
thinkingLevel: ThinkingLevel;
}
/** GET /api/models response. */
export interface ModelCatalogResponse {
models: ModelCatalogEntry[];
defaults: CatalogDefaults;
}
+38
View File
@@ -0,0 +1,38 @@
/**
* Fuzzy search scoring (model-control wave, 2026-09-12) — pi's `/model`
* picker pattern: space-separated tokens, each token must match SOME field
* (case-insensitive substring), ranked so exact field matches beat
* prefixes beat buried substrings. Pure core; the picker sorts by score.
*/
/** Score one candidate, or null when any token matches no field.
* Higher is better; ties break naturally by list order (stable sort).
*
* Per-token points: exact field equality 100 · field startsWith 60 ·
* substring 30 minus a depth penalty (earlier finds win). Whole-query
* contiguity in one field adds +50 (query "glm flash" vs the id
* "z-ai/glm-5.3-flash" loses to a model whose id contains "glm flash"
* verbatim — as it should). */
export function fuzzyScore(query: string, ...fields: string[]): number | null {
const tokens = query.trim().toLowerCase().split(/\s+/).filter(Boolean);
if (tokens.length === 0) return 0;
const hay = fields.map((f) => f.toLowerCase());
let total = 0;
for (const token of tokens) {
let best = -1;
for (const f of hay) {
if (f === token) best = Math.max(best, 100);
else if (f.startsWith(token)) best = Math.max(best, 60);
else {
const at = f.indexOf(token);
if (at !== -1) best = Math.max(best, 30 - Math.min(at, 27));
}
}
if (best < 0) return null;
total += best;
}
const joined = tokens.join(" ");
if (hay.some((f) => f.includes(joined))) total += 50;
return total;
}
+1
View File
@@ -26,3 +26,4 @@ export * from "./math-delims.ts";
export * from "./ui-message.ts";
export * from "./tool-parts.ts";
export * from "./prices.ts";
export * from "./fuzzy.ts";
+4
View File
@@ -12,6 +12,7 @@
import type { UIMessage } from "ai";
import type {
ChatRecord,
ChatSettings,
ChatSummary,
GraphEdge,
GraphNode,
@@ -45,6 +46,9 @@ export interface ChatStore {
appendTurnUsage(id: string, entry: TurnUsage): void;
/** Append one extraction-run usage entry — idempotent per startedAt. */
appendExtractionUsage(id: string, entry: ExtractionRunUsage): void;
/** Persist the per-chat model/thinking settings (the model control).
* Replace-whole: the picker sends the complete settings object. */
saveSettings(id: string, settings: ChatSettings): void;
}
// ─── GraphStore — the append-only evidence ledgers (data/graph) ──────────────
+733 -3
View File
@@ -28,16 +28,746 @@ export interface ModelPrice {
}
/** Token prices, USD per 1M tokens. A missing model makes cost render
* as absent ("—"), never zero. Refresh: npx tsx scripts/sync-pricing.ts */
* as absent ("—"), never zero. Refresh: bump @earendil-works/pi-ai, then
* npx tsx scripts/sync-pricing.ts (reads pi-ai's shipped catalog — the
* same source the engine and the picker use). */
export const PRICES: Record<string, ModelPrice> = {
"z-ai/glm-5.3-flash": { input: 0.15, output: 0.5, cacheRead: 0.03 },
"~anthropic/claude-fable-latest": { input: 10, output: 50, cacheRead: 0.25, cacheWrite: 12.5 },
"~anthropic/claude-haiku-latest": { input: 1, output: 5, cacheRead: 0.1, cacheWrite: 1.25 },
"~anthropic/claude-opus-latest": { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 },
"~anthropic/claude-sonnet-latest": { input: 2, output: 10, cacheRead: 0.2, cacheWrite: 2.5 },
"~deepseek/deepseek-v4-flash-latest": { input: 0.04998, output: 0.09996, cacheRead: 0.009996, cacheWrite: 0 },
"~google/gemini-flash-latest": { input: 0.75, output: 3.75, cacheRead: 0.075, cacheWrite: 0.041667 },
"~google/gemini-pro-latest": { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 0.375 },
"~moonshotai/kimi-latest": { input: 2.55, output: 12.75, cacheRead: 0.256, cacheWrite: 0 },
"~openai/gpt-latest": { input: 2, output: 10, cacheRead: 0.2, cacheWrite: 2.5 },
"~openai/gpt-mini-latest": { input: 0.75, output: 4.5, cacheRead: 0.075, cacheWrite: 0 },
"~x-ai/grok-latest": { input: 2, output: 6, cacheRead: 0.5, cacheWrite: 0 },
"~z-ai/glm-flash-latest": { input: 0.075, output: 0.25, cacheRead: 0.015, cacheWrite: 0 },
"~z-ai/glm-latest": { input: 1.15, output: 3.5, cacheRead: 0.1, cacheWrite: 0 },
"aion-labs/aion-2.0": { input: 0.8, output: 1.6, cacheRead: 0.2, cacheWrite: 0 },
"aion-labs/aion-3.0": { input: 3, output: 6, cacheRead: 0.75, cacheWrite: 0 },
"aion-labs/aion-3.0-mini": { input: 0.7, output: 1.4, cacheRead: 0.18, cacheWrite: 0 },
"amazon/nova-2-lite-v1": { input: 0.3, output: 2.5, cacheRead: 0, cacheWrite: 0 },
"amazon/nova-lite-v1": { input: 0.06, output: 0.24, cacheRead: 0, cacheWrite: 0 },
"amazon/nova-micro-v1": { input: 0.035, output: 0.14, cacheRead: 0, cacheWrite: 0 },
"amazon/nova-premier-v1": { input: 2.5, output: 12.5, cacheRead: 0.625, cacheWrite: 0 },
"amazon/nova-pro-v1": { input: 0.8, output: 3.2, cacheRead: 0, cacheWrite: 0 },
"anthropic/claude-3-haiku": { input: 0.25, output: 1.25, cacheRead: 0.03, cacheWrite: 0.3 },
"anthropic/claude-fable-5": { input: 10, output: 50, cacheRead: 1, cacheWrite: 12.5 },
"anthropic/claude-fable-5:batch": { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 },
"anthropic/claude-fable-5.1": { input: 10, output: 50, cacheRead: 0.25, cacheWrite: 12.5 },
"anthropic/claude-fable-5.1:batch": { input: 5, output: 25, cacheRead: 0.125, cacheWrite: 6.25 },
"anthropic/claude-haiku-4.5": { input: 1, output: 5, cacheRead: 0.1, cacheWrite: 1.25 },
"anthropic/claude-haiku-4.5:batch": { input: 0.5, output: 2.5, cacheRead: 0.05, cacheWrite: 0.625 },
"anthropic/claude-opus-4": { input: 15, output: 75, cacheRead: 1.5, cacheWrite: 18.75 },
"anthropic/claude-opus-4.1": { input: 15, output: 75, cacheRead: 1.5, cacheWrite: 18.75 },
"anthropic/claude-opus-4.1:batch": { input: 7.5, output: 37.5, cacheRead: 0.75, cacheWrite: 9.375 },
"anthropic/claude-opus-4.5": { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 },
"anthropic/claude-opus-4.5:batch": { input: 2.5, output: 12.5, cacheRead: 0.25, cacheWrite: 3.125 },
"anthropic/claude-opus-4.6": { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 },
"anthropic/claude-opus-4.6:batch": { input: 2.5, output: 12.5, cacheRead: 0.25, cacheWrite: 3.125 },
"anthropic/claude-opus-4.7": { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 },
"anthropic/claude-opus-4.7:batch": { input: 2.5, output: 12.5, cacheRead: 0.25, cacheWrite: 3.125 },
"anthropic/claude-opus-4.8": { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 },
"anthropic/claude-opus-4.8:batch": { input: 2.5, output: 12.5, cacheRead: 0.25, cacheWrite: 3.125 },
"anthropic/claude-opus-5": { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 },
"anthropic/claude-opus-5:batch": { input: 2.5, output: 12.5, cacheRead: 0.25, cacheWrite: 3.125 },
"anthropic/claude-sonnet-4": { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
"anthropic/claude-sonnet-4.5": { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
"anthropic/claude-sonnet-4.5:batch": { input: 1.5, output: 7.5, cacheRead: 0.15, cacheWrite: 1.875 },
"anthropic/claude-sonnet-4.6": { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
"anthropic/claude-sonnet-4.6:batch": { input: 1.5, output: 7.5, cacheRead: 0.15, cacheWrite: 1.875 },
"anthropic/claude-sonnet-5": { input: 2, output: 10, cacheRead: 0.2, cacheWrite: 2.5 },
"anthropic/claude-sonnet-5:batch": { input: 1, output: 5, cacheRead: 0.1, cacheWrite: 1.25 },
"arcee-ai/trinity-large-thinking": { input: 0.25, output: 0.8, cacheRead: 0.06, cacheWrite: 0 },
"auto": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
"bytedance-seed/seed-1.6": { input: 0.25, output: 2, cacheRead: 0, cacheWrite: 0 },
"bytedance-seed/seed-1.6-flash": { input: 0.075, output: 0.3, cacheRead: 0, cacheWrite: 0 },
"bytedance-seed/seed-2-1-turbo": { input: 0.5, output: 2.5, cacheRead: 0, cacheWrite: 0 },
"bytedance-seed/seed-2.0-code": { input: 0.5, output: 3, cacheRead: 0, cacheWrite: 0 },
"bytedance-seed/seed-2.0-lite": { input: 0.25, output: 2, cacheRead: 0, cacheWrite: 0 },
"bytedance-seed/seed-2.0-mini": { input: 0.1, output: 0.4, cacheRead: 0, cacheWrite: 0 },
"cohere/command-r-08-2024": { input: 0.15, output: 0.6, cacheRead: 0, cacheWrite: 0 },
"cohere/command-r-plus-08-2024": { input: 2.5, output: 10, cacheRead: 0, cacheWrite: 0 },
"cohere/north-mini-code:free": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
"deepseek/deepseek-chat": { input: 0.32, output: 0.89, cacheRead: 0, cacheWrite: 0 },
"deepseek/deepseek-chat-v3-0324": { input: 0.25, output: 1, cacheRead: 0, cacheWrite: 0 },
"deepseek/deepseek-chat-v3.1": { input: 0.55, output: 1.65, cacheRead: 0.55, cacheWrite: 0 },
"deepseek/deepseek-r1": { input: 0.7, output: 2.5, cacheRead: 0, cacheWrite: 0 },
"deepseek/deepseek-r1-0528": { input: 0.5, output: 2.15, cacheRead: 0.35, cacheWrite: 0 },
"deepseek/deepseek-v3.1-terminus": { input: 0.27, output: 1, cacheRead: 0.135, cacheWrite: 0 },
"deepseek/deepseek-v3.2": { input: 0.269, output: 0.4, cacheRead: 0.1345, cacheWrite: 0 },
"deepseek/deepseek-v3.2-exp": { input: 0.27, output: 0.41, cacheRead: 0, cacheWrite: 0 },
"deepseek/deepseek-v4-flash": { input: 0.08526, output: 0.17052, cacheRead: 0.017052, cacheWrite: 0 },
"deepseek/deepseek-v4-flash-0731": { input: 0.065, output: 0.18, cacheRead: 0.016, cacheWrite: 0 },
"deepseek/deepseek-v4-flash-0731:batch": { input: 0.14, output: 0.28, cacheRead: 0.03, cacheWrite: 0 },
"deepseek/deepseek-v4-flash-vision-exp": { input: 0.22, output: 0.66, cacheRead: 0.007, cacheWrite: 0 },
"deepseek/deepseek-v4-pro": { input: 0.890358, output: 1.780716, cacheRead: 0.074196, cacheWrite: 0 },
"deepseek/deepseek-v4-pro-0813": { input: 1.12068, output: 3.36204, cacheRead: 0.037356, cacheWrite: 0 },
"deepseek/deepseek-v4-pro-0813:batch": { input: 1.32, output: 3.96, cacheRead: 0.13, cacheWrite: 0 },
"dots-studio/dots-3-note-preview:free": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
"google/gemini-2.5-flash": { input: 0.3, output: 2.5, cacheRead: 0.03, cacheWrite: 0.083333 },
"google/gemini-2.5-flash-lite": { input: 0.1, output: 0.4, cacheRead: 0.01, cacheWrite: 0.083333 },
"google/gemini-2.5-flash-lite:batch": { input: 0.05, output: 0.2, cacheRead: 0.01, cacheWrite: 0 },
"google/gemini-2.5-flash:batch": { input: 0.15, output: 1.25, cacheRead: 0.03, cacheWrite: 0 },
"google/gemini-2.5-pro": { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 0.375 },
"google/gemini-2.5-pro-preview": { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 0.375 },
"google/gemini-2.5-pro-preview-05-06": { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 0.375 },
"google/gemini-2.5-pro:batch": { input: 0.625, output: 5, cacheRead: 0.125, cacheWrite: 0 },
"google/gemini-3-flash-preview": { input: 0.5, output: 3, cacheRead: 0.05, cacheWrite: 0.083333 },
"google/gemini-3-flash-preview:batch": { input: 0.25, output: 1.5, cacheRead: 0, cacheWrite: 0 },
"google/gemini-3-pro-image": { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 0.375 },
"google/gemini-3.1-flash-lite": { input: 0.25, output: 1.5, cacheRead: 0.025, cacheWrite: 0.083333 },
"google/gemini-3.1-flash-lite-preview": { input: 0.25, output: 1.5, cacheRead: 0.025, cacheWrite: 0.083333 },
"google/gemini-3.1-flash-lite:batch": { input: 0.125, output: 0.75, cacheRead: 0.0125, cacheWrite: 0 },
"google/gemini-3.1-pro-preview": { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 0.375 },
"google/gemini-3.1-pro-preview-customtools": { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 0.375 },
"google/gemini-3.1-pro-preview:batch": { input: 1, output: 6, cacheRead: 0, cacheWrite: 0 },
"google/gemini-3.5-flash": { input: 1.5, output: 9, cacheRead: 0.15, cacheWrite: 0.083333 },
"google/gemini-3.5-flash-lite": { input: 0.3, output: 2.5, cacheRead: 0.03, cacheWrite: 0.083333 },
"google/gemini-3.5-flash-lite:batch": { input: 0.15, output: 1.25, cacheRead: 0.015, cacheWrite: 0 },
"google/gemini-3.5-flash:batch": { input: 0.75, output: 4.5, cacheRead: 0.075, cacheWrite: 0 },
"google/gemini-3.6-flash": { input: 0.75, output: 3.75, cacheRead: 0.075, cacheWrite: 0.041667 },
"google/gemini-3.6-flash:batch": { input: 0.375, output: 1.875, cacheRead: 0.0375, cacheWrite: 0.041667 },
"google/gemini-3.7-flash": { input: 0.75, output: 3.75, cacheRead: 0.075, cacheWrite: 0.041667 },
"google/gemini-3.7-flash:batch": { input: 0.375, output: 1.875, cacheRead: 0.0375, cacheWrite: 0.041667 },
"google/gemini-3.8-flash": { input: 0.75, output: 3.75, cacheRead: 0.075, cacheWrite: 0.041667 },
"google/gemini-3.8-flash:batch": { input: 0.375, output: 1.875, cacheRead: 0.0375, cacheWrite: 0.041667 },
"google/gemma-3-12b-it": { input: 0.05, output: 0.15, cacheRead: 0, cacheWrite: 0 },
"google/gemma-3-27b-it": { input: 0.08, output: 0.45, cacheRead: 0.04, cacheWrite: 0 },
"google/gemma-4-26b-a4b-it": { input: 0.07, output: 0.34, cacheRead: 0, cacheWrite: 0 },
"google/gemma-4-26b-a4b-it:free": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
"google/gemma-4-31b-it": { input: 0.09, output: 0.34, cacheRead: 0.05, cacheWrite: 0 },
"google/gemma-4-31b-it:batch": { input: 0.39, output: 0.97, cacheRead: 0, cacheWrite: 0 },
"google/gemma-4-31b-it:free": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
"ibm-granite/granite-4.2-8b": { input: 0.1, output: 0.15, cacheRead: 0.05, cacheWrite: 0 },
"inception/mercury-2": { input: 0.25, output: 0.75, cacheRead: 0.025, cacheWrite: 0 },
"inception/mercury-2.5-preview": { input: 0.04, output: 0.15, cacheRead: 0.004, cacheWrite: 0 },
"inclusionai/ling-3.0-flash": { input: 0.021, output: 0.063, cacheRead: 0.0042, cacheWrite: 0 },
"inclusionai/ling-3.0-flash-fin": { input: 0.06, output: 0.18, cacheRead: 0.012, cacheWrite: 0 },
"inclusionai/ling-3.0-flash-fin:free": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
"inclusionai/ling-3.0-flash-sante:free": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
"kwaipilot/kat-coder-pro-v2": { input: 0.3, output: 1.2, cacheRead: 0.06, cacheWrite: 0 },
"kwaipilot/kat-coder-pro-v2.5": { input: 0.74, output: 2.96, cacheRead: 0.15, cacheWrite: 0 },
"liquid/lfm-2.5-2.6b:free": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
"meituan/longcat-2.0": { input: 0.3, output: 1.2, cacheRead: 0.006, cacheWrite: 0 },
"meta-llama/llama-3.1-70b-instruct": { input: 0.4, output: 0.4, cacheRead: 0, cacheWrite: 0 },
"meta-llama/llama-3.1-8b-instruct": { input: 0.05, output: 0.08, cacheRead: 0.025, cacheWrite: 0 },
"meta-llama/llama-3.3-70b-instruct": { input: 0.1, output: 0.32, cacheRead: 0, cacheWrite: 0 },
"meta-llama/llama-4-maverick": { input: 0.2, output: 0.696, cacheRead: 0, cacheWrite: 0 },
"meta-llama/llama-4-scout": { input: 0.1, output: 0.3, cacheRead: 0, cacheWrite: 0 },
"meta/muse-glimmer-30b": { input: 0.3, output: 1.1, cacheRead: 0.04, cacheWrite: 0 },
"meta/muse-glimmer-30b:batch": { input: 0.35, output: 1.5, cacheRead: 0.04, cacheWrite: 0 },
"meta/muse-spark-1.1": { input: 1.25, output: 4.25, cacheRead: 0.15, cacheWrite: 0 },
"meta/muse-spark-1.2": { input: 1.25, output: 4.25, cacheRead: 0.15, cacheWrite: 0 },
"meta/muse-spark-1.2-contributor": { input: 0.1, output: 0.2, cacheRead: 0.002, cacheWrite: 0 },
"meta/muse-spark-1.3": { input: 1.25, output: 4.25, cacheRead: 0.15, cacheWrite: 0 },
"meta/muse-spark-1.3-contributor": { input: 0.1, output: 0.2, cacheRead: 0.002, cacheWrite: 0 },
"minimax/minimax-m1": { input: 0.55, output: 2.2, cacheRead: 0, cacheWrite: 0 },
"minimax/minimax-m2": { input: 0.255, output: 1.02, cacheRead: 0, cacheWrite: 0 },
"minimax/minimax-m2.1": { input: 0.3, output: 1.2, cacheRead: 0.03, cacheWrite: 0 },
"minimax/minimax-m2.5": { input: 0.27, output: 1.08, cacheRead: 0.027, cacheWrite: 0 },
"minimax/minimax-m2.7": { input: 0.3, output: 1.2, cacheRead: 0.06, cacheWrite: 0 },
"minimax/minimax-m2.7:free": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
"minimax/minimax-m3": { input: 0.3, output: 1.2, cacheRead: 0.06, cacheWrite: 0 },
"minimax/minimax-m3:batch": { input: 0.3, output: 1.2, cacheRead: 0.06, cacheWrite: 0 },
"minimax/minimax-m3:free": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
"mistralai/codestral-2508": { input: 0.3, output: 0.9, cacheRead: 0.03, cacheWrite: 0 },
"mistralai/devstral-2512": { input: 0.4, output: 2, cacheRead: 0.04, cacheWrite: 0 },
"mistralai/ministral-14b-2512": { input: 0.2, output: 0.2, cacheRead: 0.02, cacheWrite: 0 },
"mistralai/ministral-3b-2512": { input: 0.1, output: 0.1, cacheRead: 0.01, cacheWrite: 0 },
"mistralai/ministral-8b-2512": { input: 0.15, output: 0.15, cacheRead: 0.015, cacheWrite: 0 },
"mistralai/mistral-large": { input: 2, output: 6, cacheRead: 0.2, cacheWrite: 0 },
"mistralai/mistral-large-2407": { input: 2, output: 6, cacheRead: 0.2, cacheWrite: 0 },
"mistralai/mistral-large-2512": { input: 0.5, output: 1.5, cacheRead: 0.05, cacheWrite: 0 },
"mistralai/mistral-medium-3": { input: 0.4, output: 2, cacheRead: 0.04, cacheWrite: 0 },
"mistralai/mistral-medium-3-5": { input: 1.5, output: 7.5, cacheRead: 0, cacheWrite: 0 },
"mistralai/mistral-medium-3-5:batch": { input: 0.75, output: 3.75, cacheRead: 0, cacheWrite: 0 },
"mistralai/mistral-medium-3.1": { input: 0.4, output: 2, cacheRead: 0.04, cacheWrite: 0 },
"mistralai/mistral-nemo": { input: 0.019, output: 0.03, cacheRead: 0, cacheWrite: 0 },
"mistralai/mistral-saba": { input: 0.2, output: 0.6, cacheRead: 0.02, cacheWrite: 0 },
"mistralai/mistral-small-2603": { input: 0.15, output: 0.6, cacheRead: 0.015, cacheWrite: 0 },
"mistralai/mistral-small-3.2-24b-instruct": { input: 0.075, output: 0.2, cacheRead: 0, cacheWrite: 0 },
"mistralai/mixtral-8x22b-instruct": { input: 2, output: 6, cacheRead: 0.2, cacheWrite: 0 },
"mistralai/voxtral-small-24b-2507": { input: 0.1, output: 0.3, cacheRead: 0.01, cacheWrite: 0 },
"moonshotai/kimi-k2": { input: 0.57, output: 2.3, cacheRead: 0, cacheWrite: 0 },
"moonshotai/kimi-k2-0905": { input: 0.6, output: 2.5, cacheRead: 0, cacheWrite: 0 },
"moonshotai/kimi-k2-thinking": { input: 0.6, output: 2.5, cacheRead: 0.15, cacheWrite: 0 },
"moonshotai/kimi-k2.5": { input: 0.41, output: 2.06, cacheRead: 0.07, cacheWrite: 0 },
"moonshotai/kimi-k2.6": { input: 0.95, output: 4, cacheRead: 0.16, cacheWrite: 0 },
"moonshotai/kimi-k2.7-code": { input: 0.66, output: 3.4, cacheRead: 0.18, cacheWrite: 0 },
"moonshotai/kimi-k3": { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 0 },
"moonshotai/kimi-k3:batch": { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 0 },
"nex-agi/nex-n2-mini": { input: 0.025, output: 0.1, cacheRead: 0.0025, cacheWrite: 0 },
"nex-agi/nex-n2-pro": { input: 0.25, output: 1, cacheRead: 0.025, cacheWrite: 0 },
"nvidia/nemotron-3-nano-30b-a3b": { input: 0.05, output: 0.2, cacheRead: 0.03, cacheWrite: 0 },
"nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
"nvidia/nemotron-3-super-120b-a12b": { input: 0.085, output: 0.4, cacheRead: 0, cacheWrite: 0 },
"nvidia/nemotron-3-super-120b-a12b:free": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
"nvidia/nemotron-3-ultra-550b-a55b": { input: 0.625, output: 3.125, cacheRead: 0.1875, cacheWrite: 0 },
"nvidia/nemotron-3-ultra-550b-a55b:free": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
"nvidia/nemotron-3.5-lightning": { input: 0.08, output: 0.2, cacheRead: 0.04, cacheWrite: 0 },
"nvidia/nemotron-3.5-lightning:free": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
"openai/gpt-3.5-turbo": { input: 0.5, output: 1.5, cacheRead: 0, cacheWrite: 0 },
"openai/gpt-3.5-turbo-0613": { input: 1, output: 2, cacheRead: 0, cacheWrite: 0 },
"openai/gpt-3.5-turbo-16k": { input: 3, output: 4, cacheRead: 0, cacheWrite: 0 },
"openai/gpt-3.5-turbo:batch": { input: 0.25, output: 0.75, cacheRead: 0, cacheWrite: 0 },
"openai/gpt-4": { input: 30, output: 60, cacheRead: 0, cacheWrite: 0 },
"openai/gpt-4-turbo": { input: 10, output: 30, cacheRead: 0, cacheWrite: 0 },
"openai/gpt-4-turbo-preview": { input: 10, output: 30, cacheRead: 0, cacheWrite: 0 },
"openai/gpt-4-turbo:batch": { input: 5, output: 15, cacheRead: 0, cacheWrite: 0 },
"openai/gpt-4.1": { input: 2, output: 8, cacheRead: 0.5, cacheWrite: 0 },
"openai/gpt-4.1-mini": { input: 0.4, output: 1.6, cacheRead: 0.1, cacheWrite: 0 },
"openai/gpt-4.1-mini:batch": { input: 0.2, output: 0.8, cacheRead: 0.05, cacheWrite: 0 },
"openai/gpt-4.1-nano": { input: 0.1, output: 0.4, cacheRead: 0.025, cacheWrite: 0 },
"openai/gpt-4.1-nano:batch": { input: 0.05, output: 0.2, cacheRead: 0.0125, cacheWrite: 0 },
"openai/gpt-4.1:batch": { input: 1, output: 4, cacheRead: 0.25, cacheWrite: 0 },
"openai/gpt-4o": { input: 2.5, output: 10, cacheRead: 1.25, cacheWrite: 0 },
"openai/gpt-4o-2024-05-13": { input: 5, output: 15, cacheRead: 0, cacheWrite: 0 },
"openai/gpt-4o-2024-08-06": { input: 2.5, output: 10, cacheRead: 1.25, cacheWrite: 0 },
"openai/gpt-4o-2024-11-20": { input: 2.5, output: 10, cacheRead: 1.25, cacheWrite: 0 },
"openai/gpt-4o-mini": { input: 0.15, output: 0.6, cacheRead: 0.075, cacheWrite: 0 },
"openai/gpt-4o-mini-2024-07-18": { input: 0.15, output: 0.6, cacheRead: 0.075, cacheWrite: 0 },
"openai/gpt-4o-mini:batch": { input: 0.075, output: 0.3, cacheRead: 0.0375, cacheWrite: 0 },
"openai/gpt-4o:batch": { input: 1.25, output: 5, cacheRead: 0.625, cacheWrite: 0 },
"openai/gpt-5": { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 0 },
"openai/gpt-5-mini": { input: 0.25, output: 2, cacheRead: 0.025, cacheWrite: 0 },
"openai/gpt-5-mini:batch": { input: 0.125, output: 1, cacheRead: 0.0125, cacheWrite: 0 },
"openai/gpt-5-nano": { input: 0.05, output: 0.4, cacheRead: 0.005, cacheWrite: 0 },
"openai/gpt-5-nano:batch": { input: 0.025, output: 0.2, cacheRead: 0.0025, cacheWrite: 0 },
"openai/gpt-5-pro": { input: 15, output: 120, cacheRead: 0, cacheWrite: 0 },
"openai/gpt-5-pro:batch": { input: 7.5, output: 60, cacheRead: 0, cacheWrite: 0 },
"openai/gpt-5:batch": { input: 0.625, output: 5, cacheRead: 0.0625, cacheWrite: 0 },
"openai/gpt-5.1": { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 0 },
"openai/gpt-5.1-codex": { input: 1.25, output: 10, cacheRead: 0.13, cacheWrite: 0 },
"openai/gpt-5.1-codex-max": { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 0 },
"openai/gpt-5.1-codex-mini": { input: 0.25, output: 2, cacheRead: 0.03, cacheWrite: 0 },
"openai/gpt-5.1:batch": { input: 0.625, output: 5, cacheRead: 0.0625, cacheWrite: 0 },
"openai/gpt-5.2": { input: 1.75, output: 14, cacheRead: 0.175, cacheWrite: 0 },
"openai/gpt-5.2-chat": { input: 1.75, output: 14, cacheRead: 0.175, cacheWrite: 0 },
"openai/gpt-5.2-codex": { input: 1.75, output: 14, cacheRead: 0.175, cacheWrite: 0 },
"openai/gpt-5.2-pro": { input: 21, output: 168, cacheRead: 0, cacheWrite: 0 },
"openai/gpt-5.2-pro:batch": { input: 10.5, output: 84, cacheRead: 0, cacheWrite: 0 },
"openai/gpt-5.2:batch": { input: 0.875, output: 7, cacheRead: 0.0875, cacheWrite: 0 },
"openai/gpt-5.3-codex": { input: 1.75, output: 14, cacheRead: 0.175, cacheWrite: 0 },
"openai/gpt-5.4": { input: 2.5, output: 15, cacheRead: 0.25, cacheWrite: 0 },
"openai/gpt-5.4-mini": { input: 0.75, output: 4.5, cacheRead: 0.075, cacheWrite: 0 },
"openai/gpt-5.4-mini:batch": { input: 0.375, output: 2.25, cacheRead: 0.0375, cacheWrite: 0 },
"openai/gpt-5.4-nano": { input: 0.2, output: 1.25, cacheRead: 0.02, cacheWrite: 0 },
"openai/gpt-5.4-nano:batch": { input: 0.1, output: 0.625, cacheRead: 0.01, cacheWrite: 0 },
"openai/gpt-5.4-pro": { input: 30, output: 180, cacheRead: 0, cacheWrite: 0 },
"openai/gpt-5.4-pro:batch": { input: 15, output: 90, cacheRead: 0, cacheWrite: 0 },
"openai/gpt-5.4:batch": { input: 1.25, output: 7.5, cacheRead: 0.125, cacheWrite: 0 },
"openai/gpt-5.5": { input: 5, output: 30, cacheRead: 0.5, cacheWrite: 0 },
"openai/gpt-5.5-pro": { input: 30, output: 180, cacheRead: 0, cacheWrite: 0 },
"openai/gpt-5.5-pro:batch": { input: 15, output: 90, cacheRead: 0, cacheWrite: 0 },
"openai/gpt-5.5:batch": { input: 2.5, output: 15, cacheRead: 0.25, cacheWrite: 0 },
"openai/gpt-5.6-luna": { input: 0.2, output: 1.2, cacheRead: 0.02, cacheWrite: 0.25 },
"openai/gpt-5.6-luna-pro": { input: 0.2, output: 1.2, cacheRead: 0.02, cacheWrite: 0.25 },
"openai/gpt-5.6-luna-pro:batch": { input: 0.1, output: 0.6, cacheRead: 0.01, cacheWrite: 0 },
"openai/gpt-5.6-luna:batch": { input: 0.1, output: 0.6, cacheRead: 0.01, cacheWrite: 0 },
"openai/gpt-5.6-sol": { input: 2, output: 10, cacheRead: 0.2, cacheWrite: 2.5 },
"openai/gpt-5.6-sol-pro": { input: 2, output: 10, cacheRead: 0.2, cacheWrite: 2.5 },
"openai/gpt-5.6-sol-pro:batch": { input: 1, output: 5, cacheRead: 0.1, cacheWrite: 1.25 },
"openai/gpt-5.6-sol:batch": { input: 1, output: 5, cacheRead: 0.1, cacheWrite: 1.25 },
"openai/gpt-5.6-terra": { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 2.5 },
"openai/gpt-5.6-terra-pro": { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 2.5 },
"openai/gpt-5.6-terra-pro:batch": { input: 1, output: 6, cacheRead: 0.1, cacheWrite: 0 },
"openai/gpt-5.6-terra:batch": { input: 1, output: 6, cacheRead: 0.1, cacheWrite: 0 },
"openai/gpt-6-astra": { input: 10, output: 50, cacheRead: 1, cacheWrite: 12.5 },
"openai/gpt-6-astra-pro": { input: 10, output: 50, cacheRead: 1, cacheWrite: 12.5 },
"openai/gpt-6-astra-pro:batch": { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 },
"openai/gpt-6-astra:batch": { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 },
"openai/gpt-audio": { input: 2.5, output: 10, cacheRead: 0, cacheWrite: 0 },
"openai/gpt-audio-mini": { input: 0.6, output: 2.4, cacheRead: 0, cacheWrite: 0 },
"openai/gpt-chat-latest": { input: 5, output: 30, cacheRead: 0.5, cacheWrite: 0 },
"openai/gpt-oss-120b": { input: 0.037, output: 0.17, cacheRead: 0, cacheWrite: 0 },
"openai/gpt-oss-120b:batch": { input: 0.15, output: 0.6, cacheRead: 0, cacheWrite: 0 },
"openai/gpt-oss-20b": { input: 0.03, output: 0.13, cacheRead: 0.03, cacheWrite: 0 },
"openai/gpt-oss-safeguard-20b": { input: 0.075, output: 0.3, cacheRead: 0.0375, cacheWrite: 0 },
"openai/o1": { input: 15, output: 60, cacheRead: 7.5, cacheWrite: 0 },
"openai/o3": { input: 2, output: 8, cacheRead: 0.5, cacheWrite: 0 },
"openai/o3-mini": { input: 1.1, output: 4.4, cacheRead: 0.55, cacheWrite: 0 },
"openai/o3-mini-high": { input: 1.1, output: 4.4, cacheRead: 0.55, cacheWrite: 0 },
"openai/o3-mini:batch": { input: 0.55, output: 2.2, cacheRead: 0.275, cacheWrite: 0 },
"openai/o3-pro": { input: 20, output: 80, cacheRead: 0, cacheWrite: 0 },
"openai/o3:batch": { input: 1, output: 4, cacheRead: 0.25, cacheWrite: 0 },
"openai/o4-mini": { input: 1.1, output: 4.4, cacheRead: 0.275, cacheWrite: 0 },
"openai/o4-mini-high": { input: 1.1, output: 4.4, cacheRead: 0.275, cacheWrite: 0 },
"openai/o4-mini:batch": { input: 0.55, output: 2.2, cacheRead: 0.1375, cacheWrite: 0 },
"openrouter/auto": { input: -1000000, output: -1000000, cacheRead: 0, cacheWrite: 0 },
"openrouter/auto-beta": { input: -1000000, output: -1000000, cacheRead: 0, cacheWrite: 0 },
"openrouter/free": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
"openrouter/fusion": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
"poolside/laguna-s-2.1": { input: 0.09, output: 0.18, cacheRead: 0.009, cacheWrite: 0 },
"poolside/laguna-s-2.1:free": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
"poolside/laguna-xs-2.1": { input: 0.06, output: 0.12, cacheRead: 0.03, cacheWrite: 0 },
"poolside/laguna-xs-2.1:free": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
"qwen/qwen-2.5-72b-instruct": { input: 0.36, output: 0.4, cacheRead: 0, cacheWrite: 0 },
"qwen/qwen-2.5-7b-instruct": { input: 0.1, output: 0.2, cacheRead: 0, cacheWrite: 0 },
"qwen/qwen-plus": { input: 0.26, output: 0.78, cacheRead: 0.052, cacheWrite: 0.325 },
"qwen/qwen-plus-2025-07-28": { input: 0.26, output: 0.78, cacheRead: 0, cacheWrite: 0 },
"qwen/qwen3-14b": { input: 0.12, output: 0.24, cacheRead: 0, cacheWrite: 0 },
"qwen/qwen3-235b-a22b": { input: 0.455, output: 1.82, cacheRead: 0, cacheWrite: 0 },
"qwen/qwen3-235b-a22b-2507": { input: 0.09, output: 0.55, cacheRead: 0, cacheWrite: 0 },
"qwen/qwen3-235b-a22b-thinking-2507": { input: 0.23, output: 2.3, cacheRead: 0, cacheWrite: 0 },
"qwen/qwen3-30b-a3b": { input: 0.12, output: 0.5, cacheRead: 0, cacheWrite: 0 },
"qwen/qwen3-30b-a3b-instruct-2507": { input: 0.04815, output: 0.19305, cacheRead: 0, cacheWrite: 0 },
"qwen/qwen3-30b-a3b-thinking-2507": { input: 0.2, output: 2.4, cacheRead: 0, cacheWrite: 0 },
"qwen/qwen3-32b": { input: 0.08, output: 0.28, cacheRead: 0, cacheWrite: 0 },
"qwen/qwen3-8b": { input: 0.117, output: 0.455, cacheRead: 0, cacheWrite: 0 },
"qwen/qwen3-coder": { input: 0.3, output: 1, cacheRead: 0.1, cacheWrite: 0 },
"qwen/qwen3-coder-30b-a3b-instruct": { input: 0.07, output: 0.28, cacheRead: 0, cacheWrite: 0 },
"qwen/qwen3-coder-flash": { input: 0.195, output: 0.975, cacheRead: 0.039, cacheWrite: 0.24375 },
"qwen/qwen3-coder-next": { input: 0.12, output: 0.8, cacheRead: 0.07, cacheWrite: 0 },
"qwen/qwen3-coder-plus": { input: 0.65, output: 3.25, cacheRead: 0.13, cacheWrite: 0.8125 },
"qwen/qwen3-max": { input: 0.78, output: 3.9, cacheRead: 0.156, cacheWrite: 0.975 },
"qwen/qwen3-max-thinking": { input: 0.78, output: 3.9, cacheRead: 0, cacheWrite: 0 },
"qwen/qwen3-next-80b-a3b-instruct": { input: 0.1, output: 1.1, cacheRead: 0.07, cacheWrite: 0 },
"qwen/qwen3-next-80b-a3b-thinking": { input: 0.15, output: 1.2, cacheRead: 0, cacheWrite: 0 },
"qwen/qwen3-vl-235b-a22b-instruct": { input: 0.21, output: 1.9, cacheRead: 0.1, cacheWrite: 0 },
"qwen/qwen3-vl-235b-a22b-thinking": { input: 0.4, output: 4, cacheRead: 0, cacheWrite: 0 },
"qwen/qwen3-vl-30b-a3b-instruct": { input: 0.15, output: 0.6, cacheRead: 0, cacheWrite: 0 },
"qwen/qwen3-vl-30b-a3b-thinking": { input: 0.2, output: 2.4, cacheRead: 0, cacheWrite: 0 },
"qwen/qwen3-vl-32b-instruct": { input: 0.104, output: 0.416, cacheRead: 0, cacheWrite: 0 },
"qwen/qwen3-vl-8b-instruct": { input: 0.117, output: 0.455, cacheRead: 0, cacheWrite: 0 },
"qwen/qwen3-vl-8b-thinking": { input: 0.18, output: 2.1, cacheRead: 0, cacheWrite: 0 },
"qwen/qwen3.5-122b-a10b": { input: 0.29, output: 2.4, cacheRead: 0, cacheWrite: 0 },
"qwen/qwen3.5-27b": { input: 0.195, output: 1.56, cacheRead: 0, cacheWrite: 0 },
"qwen/qwen3.5-35b-a3b": { input: 0.08, output: 0.75, cacheRead: 0, cacheWrite: 0 },
"qwen/qwen3.5-397b-a17b": { input: 0.55, output: 3.5, cacheRead: 0.225, cacheWrite: 0 },
"qwen/qwen3.5-9b": { input: 0.1, output: 0.15, cacheRead: 0, cacheWrite: 0 },
"qwen/qwen3.5-9b:batch": { input: 0.17, output: 0.25, cacheRead: 0, cacheWrite: 0 },
"qwen/qwen3.5-flash-02-23": { input: 0.065, output: 0.26, cacheRead: 0, cacheWrite: 0 },
"qwen/qwen3.5-plus-02-15": { input: 0.26, output: 1.56, cacheRead: 0, cacheWrite: 0 },
"qwen/qwen3.5-plus-20260420": { input: 0.3, output: 1.8, cacheRead: 0, cacheWrite: 0.375 },
"qwen/qwen3.6-27b": { input: 0.3, output: 2, cacheRead: 0.03, cacheWrite: 0 },
"qwen/qwen3.6-35b-a3b": { input: 0.1, output: 0.9, cacheRead: 0.05, cacheWrite: 0 },
"qwen/qwen3.6-flash": { input: 0.1875, output: 1.125, cacheRead: 0, cacheWrite: 0.234375 },
"qwen/qwen3.6-max-preview": { input: 1.027, output: 6.162, cacheRead: 0, cacheWrite: 1.28375 },
"qwen/qwen3.6-plus": { input: 0.325, output: 1.95, cacheRead: 0, cacheWrite: 0.40625 },
"qwen/qwen3.7-flash": { input: 0.03, output: 0.13, cacheRead: 0.006, cacheWrite: 0.038 },
"qwen/qwen3.7-max": { input: 1.475, output: 4.425, cacheRead: 0.295, cacheWrite: 1.84375 },
"qwen/qwen3.7-plus": { input: 0.32, output: 1.28, cacheRead: 0.064, cacheWrite: 0.4 },
"qwen/qwen3.8-2.4t-a95b": { input: 2, output: 6, cacheRead: 0.25, cacheWrite: 0 },
"qwen/qwen3.8-2.4t-a95b:batch": { input: 2, output: 6, cacheRead: 0.25, cacheWrite: 0 },
"qwen/qwen3.8-27b": { input: 0.42, output: 3, cacheRead: 0.085, cacheWrite: 0 },
"qwen/qwen3.8-flash": { input: 0.15, output: 0.47, cacheRead: 0.016, cacheWrite: 0.2 },
"qwen/qwen3.8-max-0902": { input: 2, output: 6, cacheRead: 0.25, cacheWrite: 2.5 },
"rekaai/reka-edge": { input: 0.1, output: 0.1, cacheRead: 0, cacheWrite: 0 },
"relace/relace-search": { input: 1, output: 3, cacheRead: 0, cacheWrite: 0 },
"sakana/fugu-ultra": { input: 5, output: 30, cacheRead: 0.5, cacheWrite: 0 },
"sakana/sakana-namazu": { input: 0.95, output: 4, cacheRead: 0.15, cacheWrite: 0 },
"sao10k/l3.1-euryale-70b": { input: 0.85, output: 0.85, cacheRead: 0, cacheWrite: 0 },
"stepfun/step-3.5-flash": { input: 0.1, output: 0.3, cacheRead: 0, cacheWrite: 0 },
"stepfun/step-3.7-flash": { input: 0.2, output: 1.15, cacheRead: 0.04, cacheWrite: 0 },
"tencent/hy3": { input: 0.132, output: 0.528, cacheRead: 0.033, cacheWrite: 0 },
"tencent/hy3-preview": { input: 0.18, output: 0.6, cacheRead: 0.06, cacheWrite: 0 },
"tencent/hy4-preview": { input: 0.834, output: 2.501, cacheRead: 0.042, cacheWrite: 0 },
"thedrummer/unslopnemo-12b": { input: 0.4, output: 0.4, cacheRead: 0, cacheWrite: 0 },
"thinkingmachines/inkling": { input: 1, output: 4.05, cacheRead: 0.17, cacheWrite: 0 },
"thinkingmachines/inkling-small": { input: 0.45, output: 1.2, cacheRead: 0.1, cacheWrite: 0 },
"thinkingmachines/inkling-small:batch": { input: 0.5, output: 1.2, cacheRead: 0.1, cacheWrite: 0 },
"thinkingmachines/inkling-small:free": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
"thinkingmachines/inkling:batch": { input: 1, output: 4.05, cacheRead: 0.17, cacheWrite: 0 },
"thinkingmachines/inkling:free": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
"upstage/solar-pro-3": { input: 0.15, output: 0.6, cacheRead: 0.015, cacheWrite: 0 },
"upstage/solar-pro4": { input: 0.03, output: 0.12, cacheRead: 0.006, cacheWrite: 0 },
"x-ai/grok-4.20": { input: 1.25, output: 2.5, cacheRead: 0.2, cacheWrite: 0 },
"x-ai/grok-4.3": { input: 1.25, output: 2.5, cacheRead: 0.2, cacheWrite: 0 },
"x-ai/grok-4.3:batch": { input: 1, output: 2, cacheRead: 0.16, cacheWrite: 0 },
"x-ai/grok-4.5": { input: 2, output: 6, cacheRead: 0.3, cacheWrite: 0 },
"x-ai/grok-4.6": { input: 2, output: 6, cacheRead: 0.5, cacheWrite: 0 },
"x-ai/grok-build-0.1": { input: 1, output: 2, cacheRead: 0.2, cacheWrite: 0 },
"xiaomi/mimo-v2.5": { input: 0.14, output: 0.28, cacheRead: 0.0028, cacheWrite: 0 },
"xiaomi/mimo-v2.5-pro": { input: 0.435, output: 0.87, cacheRead: 0.0036, cacheWrite: 0 },
"z-ai/glm-4.5": { input: 0.6, output: 2.2, cacheRead: 0.11, cacheWrite: 0 },
"z-ai/glm-4.5-air": { input: 0.13, output: 0.85, cacheRead: 0.025, cacheWrite: 0 },
"z-ai/glm-4.5v": { input: 0.6, output: 1.8, cacheRead: 0.11, cacheWrite: 0 },
"z-ai/glm-4.6": { input: 0.55, output: 2.2, cacheRead: 0.11, cacheWrite: 0 },
"z-ai/glm-4.6v": { input: 0.3, output: 0.9, cacheRead: 0.055, cacheWrite: 0 },
"z-ai/glm-4.7": { input: 0.4, output: 1.75, cacheRead: 0.08, cacheWrite: 0 },
"z-ai/glm-4.7-flash": { input: 0.06, output: 0.4, cacheRead: 0.01, cacheWrite: 0 },
"z-ai/glm-5": { input: 0.6, output: 1.9, cacheRead: 0.119, cacheWrite: 0 },
"z-ai/glm-5-turbo": { input: 1.2, output: 4, cacheRead: 0.24, cacheWrite: 0 },
"z-ai/glm-5.1": { input: 0.966, output: 3.036, cacheRead: 0.1794, cacheWrite: 0 },
"z-ai/glm-5.2": { input: 0.966, output: 3.036, cacheRead: 0.1932, cacheWrite: 0 },
"z-ai/glm-5.2:free": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
"z-ai/glm-5.3": { input: 1.4, output: 4.4, cacheRead: 0.14, cacheWrite: 0 },
"z-ai/glm-5.3-flash": { input: 0.075, output: 0.25, cacheRead: 0.015, cacheWrite: 0 },
"z-ai/glm-5.3-flash:batch": { input: 0.15, output: 0.5, cacheRead: 0.03, cacheWrite: 0 },
"z-ai/glm-5v-turbo": { input: 1.2, output: 4, cacheRead: 0.24, cacheWrite: 0 },
};
/** Context-window limits (tokens) per model — generated alongside PRICES. */
export const CONTEXT_LIMITS: Record<string, number> = {
"z-ai/glm-5.3-flash": 1310720,
"~anthropic/claude-fable-latest": 1000000,
"~anthropic/claude-haiku-latest": 200000,
"~anthropic/claude-opus-latest": 1000000,
"~anthropic/claude-sonnet-latest": 1000000,
"~deepseek/deepseek-v4-flash-latest": 1048576,
"~google/gemini-flash-latest": 1048576,
"~google/gemini-pro-latest": 1048576,
"~moonshotai/kimi-latest": 1048576,
"~openai/gpt-latest": 1050000,
"~openai/gpt-mini-latest": 400000,
"~x-ai/grok-latest": 500000,
"~z-ai/glm-flash-latest": 1048576,
"~z-ai/glm-latest": 262144,
"aion-labs/aion-2.0": 131072,
"aion-labs/aion-3.0": 131072,
"aion-labs/aion-3.0-mini": 131072,
"amazon/nova-2-lite-v1": 1000000,
"amazon/nova-lite-v1": 300000,
"amazon/nova-micro-v1": 128000,
"amazon/nova-premier-v1": 1000000,
"amazon/nova-pro-v1": 300000,
"anthropic/claude-3-haiku": 200000,
"anthropic/claude-fable-5": 1000000,
"anthropic/claude-fable-5:batch": 1000000,
"anthropic/claude-fable-5.1": 1000000,
"anthropic/claude-fable-5.1:batch": 1000000,
"anthropic/claude-haiku-4.5": 200000,
"anthropic/claude-haiku-4.5:batch": 200000,
"anthropic/claude-opus-4": 200000,
"anthropic/claude-opus-4.1": 200000,
"anthropic/claude-opus-4.1:batch": 200000,
"anthropic/claude-opus-4.5": 200000,
"anthropic/claude-opus-4.5:batch": 200000,
"anthropic/claude-opus-4.6": 1000000,
"anthropic/claude-opus-4.6:batch": 1000000,
"anthropic/claude-opus-4.7": 1000000,
"anthropic/claude-opus-4.7:batch": 1000000,
"anthropic/claude-opus-4.8": 1000000,
"anthropic/claude-opus-4.8:batch": 1000000,
"anthropic/claude-opus-5": 1000000,
"anthropic/claude-opus-5:batch": 1000000,
"anthropic/claude-sonnet-4": 200000,
"anthropic/claude-sonnet-4.5": 1000000,
"anthropic/claude-sonnet-4.5:batch": 1000000,
"anthropic/claude-sonnet-4.6": 1000000,
"anthropic/claude-sonnet-4.6:batch": 1000000,
"anthropic/claude-sonnet-5": 1000000,
"anthropic/claude-sonnet-5:batch": 1000000,
"arcee-ai/trinity-large-thinking": 262144,
"auto": 2000000,
"bytedance-seed/seed-1.6": 262144,
"bytedance-seed/seed-1.6-flash": 262144,
"bytedance-seed/seed-2-1-turbo": 262144,
"bytedance-seed/seed-2.0-code": 262144,
"bytedance-seed/seed-2.0-lite": 262144,
"bytedance-seed/seed-2.0-mini": 262144,
"cohere/command-r-08-2024": 128000,
"cohere/command-r-plus-08-2024": 128000,
"cohere/north-mini-code:free": 256000,
"deepseek/deepseek-chat": 163840,
"deepseek/deepseek-chat-v3-0324": 163840,
"deepseek/deepseek-chat-v3.1": 161000,
"deepseek/deepseek-r1": 64000,
"deepseek/deepseek-r1-0528": 163840,
"deepseek/deepseek-v3.1-terminus": 131072,
"deepseek/deepseek-v3.2": 163840,
"deepseek/deepseek-v3.2-exp": 163840,
"deepseek/deepseek-v4-flash": 1024000,
"deepseek/deepseek-v4-flash-0731": 1048576,
"deepseek/deepseek-v4-flash-0731:batch": 1048576,
"deepseek/deepseek-v4-flash-vision-exp": 1048576,
"deepseek/deepseek-v4-pro": 1024000,
"deepseek/deepseek-v4-pro-0813": 1024000,
"deepseek/deepseek-v4-pro-0813:batch": 1048576,
"dots-studio/dots-3-note-preview:free": 512000,
"google/gemini-2.5-flash": 1048576,
"google/gemini-2.5-flash-lite": 1048576,
"google/gemini-2.5-flash-lite:batch": 1048576,
"google/gemini-2.5-flash:batch": 1048576,
"google/gemini-2.5-pro": 1048576,
"google/gemini-2.5-pro-preview": 1048576,
"google/gemini-2.5-pro-preview-05-06": 1048576,
"google/gemini-2.5-pro:batch": 1048576,
"google/gemini-3-flash-preview": 1048576,
"google/gemini-3-flash-preview:batch": 1048576,
"google/gemini-3-pro-image": 65536,
"google/gemini-3.1-flash-lite": 1048576,
"google/gemini-3.1-flash-lite-preview": 1048576,
"google/gemini-3.1-flash-lite:batch": 1048576,
"google/gemini-3.1-pro-preview": 1048576,
"google/gemini-3.1-pro-preview-customtools": 1048576,
"google/gemini-3.1-pro-preview:batch": 1048576,
"google/gemini-3.5-flash": 1048576,
"google/gemini-3.5-flash-lite": 1048576,
"google/gemini-3.5-flash-lite:batch": 1048576,
"google/gemini-3.5-flash:batch": 1048576,
"google/gemini-3.6-flash": 1048576,
"google/gemini-3.6-flash:batch": 1048576,
"google/gemini-3.7-flash": 1048576,
"google/gemini-3.7-flash:batch": 1048576,
"google/gemini-3.8-flash": 1048576,
"google/gemini-3.8-flash:batch": 1048576,
"google/gemma-3-12b-it": 131072,
"google/gemma-3-27b-it": 131072,
"google/gemma-4-26b-a4b-it": 262144,
"google/gemma-4-26b-a4b-it:free": 262144,
"google/gemma-4-31b-it": 262144,
"google/gemma-4-31b-it:batch": 262144,
"google/gemma-4-31b-it:free": 262144,
"ibm-granite/granite-4.2-8b": 131072,
"inception/mercury-2": 128000,
"inception/mercury-2.5-preview": 260000,
"inclusionai/ling-3.0-flash": 262144,
"inclusionai/ling-3.0-flash-fin": 262144,
"inclusionai/ling-3.0-flash-fin:free": 262144,
"inclusionai/ling-3.0-flash-sante:free": 262144,
"kwaipilot/kat-coder-pro-v2": 262144,
"kwaipilot/kat-coder-pro-v2.5": 262144,
"liquid/lfm-2.5-2.6b:free": 65536,
"meituan/longcat-2.0": 1048756,
"meta-llama/llama-3.1-70b-instruct": 131072,
"meta-llama/llama-3.1-8b-instruct": 131072,
"meta-llama/llama-3.3-70b-instruct": 131072,
"meta-llama/llama-4-maverick": 128000,
"meta-llama/llama-4-scout": 327680,
"meta/muse-glimmer-30b": 131072,
"meta/muse-glimmer-30b:batch": 131072,
"meta/muse-spark-1.1": 1048576,
"meta/muse-spark-1.2": 1048576,
"meta/muse-spark-1.2-contributor": 1048576,
"meta/muse-spark-1.3": 1048576,
"meta/muse-spark-1.3-contributor": 1048576,
"minimax/minimax-m1": 1000000,
"minimax/minimax-m2": 204800,
"minimax/minimax-m2.1": 204800,
"minimax/minimax-m2.5": 200000,
"minimax/minimax-m2.7": 204800,
"minimax/minimax-m2.7:free": 196608,
"minimax/minimax-m3": 524288,
"minimax/minimax-m3:batch": 524288,
"minimax/minimax-m3:free": 1048576,
"mistralai/codestral-2508": 256000,
"mistralai/devstral-2512": 262144,
"mistralai/ministral-14b-2512": 262144,
"mistralai/ministral-3b-2512": 131072,
"mistralai/ministral-8b-2512": 262144,
"mistralai/mistral-large": 128000,
"mistralai/mistral-large-2407": 131072,
"mistralai/mistral-large-2512": 262144,
"mistralai/mistral-medium-3": 131072,
"mistralai/mistral-medium-3-5": 262144,
"mistralai/mistral-medium-3-5:batch": 32768,
"mistralai/mistral-medium-3.1": 131072,
"mistralai/mistral-nemo": 131072,
"mistralai/mistral-saba": 32768,
"mistralai/mistral-small-2603": 262144,
"mistralai/mistral-small-3.2-24b-instruct": 128000,
"mistralai/mixtral-8x22b-instruct": 65536,
"mistralai/voxtral-small-24b-2507": 32768,
"moonshotai/kimi-k2": 131072,
"moonshotai/kimi-k2-0905": 262144,
"moonshotai/kimi-k2-thinking": 262144,
"moonshotai/kimi-k2.5": 262144,
"moonshotai/kimi-k2.6": 262144,
"moonshotai/kimi-k2.7-code": 262144,
"moonshotai/kimi-k3": 1048576,
"moonshotai/kimi-k3:batch": 1048576,
"nex-agi/nex-n2-mini": 262144,
"nex-agi/nex-n2-pro": 262144,
"nvidia/nemotron-3-nano-30b-a3b": 262144,
"nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free": 256000,
"nvidia/nemotron-3-super-120b-a12b": 262144,
"nvidia/nemotron-3-super-120b-a12b:free": 262144,
"nvidia/nemotron-3-ultra-550b-a55b": 256000,
"nvidia/nemotron-3-ultra-550b-a55b:free": 1000000,
"nvidia/nemotron-3.5-lightning": 262144,
"nvidia/nemotron-3.5-lightning:free": 1000000,
"openai/gpt-3.5-turbo": 16385,
"openai/gpt-3.5-turbo-0613": 4095,
"openai/gpt-3.5-turbo-16k": 16385,
"openai/gpt-3.5-turbo:batch": 16385,
"openai/gpt-4": 8191,
"openai/gpt-4-turbo": 128000,
"openai/gpt-4-turbo-preview": 128000,
"openai/gpt-4-turbo:batch": 128000,
"openai/gpt-4.1": 1047576,
"openai/gpt-4.1-mini": 1047576,
"openai/gpt-4.1-mini:batch": 1047576,
"openai/gpt-4.1-nano": 1047576,
"openai/gpt-4.1-nano:batch": 1047576,
"openai/gpt-4.1:batch": 1047576,
"openai/gpt-4o": 128000,
"openai/gpt-4o-2024-05-13": 128000,
"openai/gpt-4o-2024-08-06": 128000,
"openai/gpt-4o-2024-11-20": 128000,
"openai/gpt-4o-mini": 128000,
"openai/gpt-4o-mini-2024-07-18": 128000,
"openai/gpt-4o-mini:batch": 128000,
"openai/gpt-4o:batch": 128000,
"openai/gpt-5": 400000,
"openai/gpt-5-mini": 400000,
"openai/gpt-5-mini:batch": 400000,
"openai/gpt-5-nano": 400000,
"openai/gpt-5-nano:batch": 400000,
"openai/gpt-5-pro": 400000,
"openai/gpt-5-pro:batch": 400000,
"openai/gpt-5:batch": 400000,
"openai/gpt-5.1": 400000,
"openai/gpt-5.1-codex": 400000,
"openai/gpt-5.1-codex-max": 400000,
"openai/gpt-5.1-codex-mini": 400000,
"openai/gpt-5.1:batch": 400000,
"openai/gpt-5.2": 400000,
"openai/gpt-5.2-chat": 128000,
"openai/gpt-5.2-codex": 400000,
"openai/gpt-5.2-pro": 400000,
"openai/gpt-5.2-pro:batch": 400000,
"openai/gpt-5.2:batch": 400000,
"openai/gpt-5.3-codex": 400000,
"openai/gpt-5.4": 1050000,
"openai/gpt-5.4-mini": 400000,
"openai/gpt-5.4-mini:batch": 400000,
"openai/gpt-5.4-nano": 400000,
"openai/gpt-5.4-nano:batch": 400000,
"openai/gpt-5.4-pro": 1050000,
"openai/gpt-5.4-pro:batch": 1050000,
"openai/gpt-5.4:batch": 1050000,
"openai/gpt-5.5": 1050000,
"openai/gpt-5.5-pro": 1050000,
"openai/gpt-5.5-pro:batch": 1050000,
"openai/gpt-5.5:batch": 1050000,
"openai/gpt-5.6-luna": 1050000,
"openai/gpt-5.6-luna-pro": 1050000,
"openai/gpt-5.6-luna-pro:batch": 1050000,
"openai/gpt-5.6-luna:batch": 1050000,
"openai/gpt-5.6-sol": 1050000,
"openai/gpt-5.6-sol-pro": 1050000,
"openai/gpt-5.6-sol-pro:batch": 1050000,
"openai/gpt-5.6-sol:batch": 1050000,
"openai/gpt-5.6-terra": 1050000,
"openai/gpt-5.6-terra-pro": 1050000,
"openai/gpt-5.6-terra-pro:batch": 1050000,
"openai/gpt-5.6-terra:batch": 1050000,
"openai/gpt-6-astra": 1050000,
"openai/gpt-6-astra-pro": 1050000,
"openai/gpt-6-astra-pro:batch": 1050000,
"openai/gpt-6-astra:batch": 1050000,
"openai/gpt-audio": 128000,
"openai/gpt-audio-mini": 128000,
"openai/gpt-chat-latest": 400000,
"openai/gpt-oss-120b": 131072,
"openai/gpt-oss-120b:batch": 131072,
"openai/gpt-oss-20b": 131072,
"openai/gpt-oss-safeguard-20b": 131072,
"openai/o1": 200000,
"openai/o3": 200000,
"openai/o3-mini": 200000,
"openai/o3-mini-high": 200000,
"openai/o3-mini:batch": 200000,
"openai/o3-pro": 200000,
"openai/o3:batch": 200000,
"openai/o4-mini": 200000,
"openai/o4-mini-high": 200000,
"openai/o4-mini:batch": 200000,
"openrouter/auto": 2000000,
"openrouter/auto-beta": 2000000,
"openrouter/free": 200000,
"openrouter/fusion": 1000000,
"poolside/laguna-s-2.1": 1048576,
"poolside/laguna-s-2.1:free": 262144,
"poolside/laguna-xs-2.1": 262144,
"poolside/laguna-xs-2.1:free": 262144,
"qwen/qwen-2.5-72b-instruct": 32768,
"qwen/qwen-2.5-7b-instruct": 32768,
"qwen/qwen-plus": 1000000,
"qwen/qwen-plus-2025-07-28": 1000000,
"qwen/qwen3-14b": 40960,
"qwen/qwen3-235b-a22b": 131072,
"qwen/qwen3-235b-a22b-2507": 262144,
"qwen/qwen3-235b-a22b-thinking-2507": 131072,
"qwen/qwen3-30b-a3b": 40960,
"qwen/qwen3-30b-a3b-instruct-2507": 128000,
"qwen/qwen3-30b-a3b-thinking-2507": 81920,
"qwen/qwen3-32b": 40960,
"qwen/qwen3-8b": 131072,
"qwen/qwen3-coder": 262144,
"qwen/qwen3-coder-30b-a3b-instruct": 262144,
"qwen/qwen3-coder-flash": 1000000,
"qwen/qwen3-coder-next": 262144,
"qwen/qwen3-coder-plus": 1000000,
"qwen/qwen3-max": 262144,
"qwen/qwen3-max-thinking": 262144,
"qwen/qwen3-next-80b-a3b-instruct": 262144,
"qwen/qwen3-next-80b-a3b-thinking": 131072,
"qwen/qwen3-vl-235b-a22b-instruct": 131072,
"qwen/qwen3-vl-235b-a22b-thinking": 131072,
"qwen/qwen3-vl-30b-a3b-instruct": 262144,
"qwen/qwen3-vl-30b-a3b-thinking": 131072,
"qwen/qwen3-vl-32b-instruct": 131072,
"qwen/qwen3-vl-8b-instruct": 131072,
"qwen/qwen3-vl-8b-thinking": 131072,
"qwen/qwen3.5-122b-a10b": 262144,
"qwen/qwen3.5-27b": 262144,
"qwen/qwen3.5-35b-a3b": 262144,
"qwen/qwen3.5-397b-a17b": 262144,
"qwen/qwen3.5-9b": 262144,
"qwen/qwen3.5-9b:batch": 262144,
"qwen/qwen3.5-flash-02-23": 1000000,
"qwen/qwen3.5-plus-02-15": 1000000,
"qwen/qwen3.5-plus-20260420": 1000000,
"qwen/qwen3.6-27b": 262144,
"qwen/qwen3.6-35b-a3b": 262144,
"qwen/qwen3.6-flash": 1000000,
"qwen/qwen3.6-max-preview": 262144,
"qwen/qwen3.6-plus": 1000000,
"qwen/qwen3.7-flash": 1000000,
"qwen/qwen3.7-max": 1000000,
"qwen/qwen3.7-plus": 1000000,
"qwen/qwen3.8-2.4t-a95b": 1000000,
"qwen/qwen3.8-2.4t-a95b:batch": 1010000,
"qwen/qwen3.8-27b": 1000000,
"qwen/qwen3.8-flash": 1000000,
"qwen/qwen3.8-max-0902": 1000000,
"rekaai/reka-edge": 16384,
"relace/relace-search": 256000,
"sakana/fugu-ultra": 1000000,
"sakana/sakana-namazu": 262144,
"sao10k/l3.1-euryale-70b": 131072,
"stepfun/step-3.5-flash": 262144,
"stepfun/step-3.7-flash": 256000,
"tencent/hy3": 262144,
"tencent/hy3-preview": 262144,
"tencent/hy4-preview": 1048576,
"thedrummer/unslopnemo-12b": 32768,
"thinkingmachines/inkling": 524288,
"thinkingmachines/inkling-small": 524288,
"thinkingmachines/inkling-small:batch": 524288,
"thinkingmachines/inkling-small:free": 1048576,
"thinkingmachines/inkling:batch": 524288,
"thinkingmachines/inkling:free": 1048576,
"upstage/solar-pro-3": 131072,
"upstage/solar-pro4": 524288,
"x-ai/grok-4.20": 2000000,
"x-ai/grok-4.3": 1000000,
"x-ai/grok-4.3:batch": 1000000,
"x-ai/grok-4.5": 500000,
"x-ai/grok-4.6": 500000,
"x-ai/grok-build-0.1": 256000,
"xiaomi/mimo-v2.5": 1048576,
"xiaomi/mimo-v2.5-pro": 1048576,
"z-ai/glm-4.5": 131072,
"z-ai/glm-4.5-air": 131072,
"z-ai/glm-4.5v": 65536,
"z-ai/glm-4.6": 204800,
"z-ai/glm-4.6v": 131072,
"z-ai/glm-4.7": 202752,
"z-ai/glm-4.7-flash": 202752,
"z-ai/glm-5": 198000,
"z-ai/glm-5-turbo": 202752,
"z-ai/glm-5.1": 200000,
"z-ai/glm-5.2": 1048576,
"z-ai/glm-5.2:free": 256000,
"z-ai/glm-5.3": 1048576,
"z-ai/glm-5.3-flash": 1048576,
"z-ai/glm-5.3-flash:batch": 1048575,
"z-ai/glm-5v-turbo": 202752,
};
// ─── Pure helpers (folds + cost inference) ───────────────────────────────────