diff --git a/.changeset/model-meta-no-prices.md b/.changeset/model-meta-no-prices.md new file mode 100644 index 0000000000..099732387e --- /dev/null +++ b/.changeset/model-meta-no-prices.md @@ -0,0 +1,11 @@ +--- +'@tanstack/ai-anthropic': patch +'@tanstack/ai-gemini': patch +'@tanstack/ai-grok': patch +'@tanstack/ai-groq': patch +'@tanstack/ai-mistral': patch +'@tanstack/ai-openai': patch +'@tanstack/ai-openrouter': patch +--- + +Model metadata no longer carries prices. Nothing read them, and prices change faster than a package release. To price a call, read the live rate card from modelschemas: see the Model Prices guide. diff --git a/.changeset/sync-modelschemas-models.md b/.changeset/sync-modelschemas-models.md new file mode 100644 index 0000000000..2203889dfb --- /dev/null +++ b/.changeset/sync-modelschemas-models.md @@ -0,0 +1,7 @@ +--- +'@tanstack/ai-byteplus': patch +'@tanstack/ai-groq': patch +'@tanstack/ai-mistral': patch +--- + +Add new BytePlus, Groq, and Mistral models from the modelschemas catalog. diff --git a/.github/workflows/sync-models.yml b/.github/workflows/sync-models.yml index 1b45a811ac..54a6cc1e78 100644 --- a/.github/workflows/sync-models.yml +++ b/.github/workflows/sync-models.yml @@ -44,11 +44,15 @@ jobs: id: elevenlabs continue-on-error: true run: pnpm generate:models:elevenlabs + env: + MODELSCHEMAS_API_KEY: ${{ secrets.MODELSCHEMAS_API_KEY }} - name: Sync provider models id: provider continue-on-error: true run: pnpm exec tsx scripts/sync-provider-models.ts + env: + MODELSCHEMAS_API_KEY: ${{ secrets.MODELSCHEMAS_API_KEY }} - name: Format run: pnpm format @@ -87,7 +91,7 @@ jobs: if [ -z "$EXISTING_PR" ] || [ "$EXISTING_PR" = "null" ]; then BODY=$(cat <<'PRBODY' - Automated daily sync of model metadata from OpenRouter, Vercel AI Gateway, Lovable AI Gateway, LLM Gateway, Neon AI Gateway, and modelschemas (ElevenLabs text-to-speech, music, sound effects, and voice design). + Automated daily sync of model metadata from OpenRouter, Vercel AI Gateway, Lovable AI Gateway, LLM Gateway, Neon AI Gateway, and modelschemas (native provider models, plus ElevenLabs text-to-speech, music, sound effects, and voice design). - Fetches the latest model list from OpenRouter (chat + `GET /api/v1/videos/models`) - Fetches the latest model list from Vercel AI Gateway @@ -95,7 +99,7 @@ jobs: - Fetches the latest model list from LLM Gateway (`GET /v1/models`) - Fetches the latest model list from Neon AI Gateway - Converts to the internal adapter format - - Syncs provider-specific model metadata for affected packages + - Inserts new native-provider models from modelschemas (`@modelschemas/client`) - Inserts new ElevenLabs text-to-speech, music, sound-effect, and voice-design models from modelschemas - Creates a patch changeset for all changed packages PRBODY diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a0c9e34a46..ea5dca31c3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -55,18 +55,24 @@ For deeper architecture details (adapter system, isomorphic tools, framework int 1. Fetches OpenRouter, Vercel AI Gateway, Lovable AI Gateway, and Neon AI Gateway catalogs. 2. Regenerates `packages/ai-openrouter/src/model-meta.ts` and the Vercel Gateway and Neon model lists. -3. Inserts **new** native-provider models into `packages/ai-openai`, `ai-anthropic`, `ai-gemini`, and `ai-grok`. -4. Inserts **new** ElevenLabs text-to-speech, music, sound-effect, and voice-design ids from [modelschemas](https://modelschemas.com/v1/schemas/elevenlabs) into `packages/ai-elevenlabs/src/model-meta.ts`. Transcription ids stay hand-maintained. +3. Inserts **new** native-provider models from [modelschemas](https://modelschemas.com) (`@modelschemas/client`) into `ai-openai`, `ai-anthropic`, `ai-gemini`, `ai-grok`, `ai-groq`, `ai-mistral`, and `ai-byteplus`. Ids, activity, limits, modalities, and capabilities come from each provider's own catalog, with no second source. A field the catalog leaves empty stays empty, and a row with no modalities is skipped (the log counts it). Model metadata has no prices: they change faster than a release, so apps read them live (`docs/advanced/model-prices.md`). +4. Inserts **new** ElevenLabs text-to-speech, music, sound-effect, and voice-design ids from [modelschemas](https://modelschemas.com/v1/schemas/elevenlabs) into `packages/ai-elevenlabs/src/model-meta.ts` (`scripts/sync-elevenlabs-models.ts`, also through `@modelschemas/client`). Text-to-speech ids are catalog rows with `providerMetadata.canDoTextToSpeech`. Music, sound-effect, and voice-design ids are the `model_id` enums of their request schemas. Transcription ids stay hand-maintained. 5. Writes a patch changeset for the packages that changed. +The sync stops with an error when modelschemas is down, when a catalog is empty, when no row has a `rawId`, `firstSeenAt`, or `deprecatedAt` key, or when an array or type map it must update is missing from a `model-meta.ts`. + +Reads against modelschemas work without a key (60 req/h per IP). Set `MODELSCHEMAS_API_KEY` on the workflow when you want the higher limit. + Rules the generator follows: - Keep OpenRouter routing aliases (ids that start with `~`) in the OpenRouter catalog. Users can pass `chat({ model: '~anthropic/claude-haiku-latest' })`. The generated constant name maps `~` to `_`. -- Do **not** copy those aliases into native provider files (`ai-openai`, `ai-anthropic`, `ai-gemini`, `ai-grok`). Those adapters only accept the provider's own ids. -- For a new native-provider model, write id, modalities, and pricing. Infer features from OpenRouter `supported_parameters` when that field exists. Do **not** copy another model's tool list (`computer_use`, `google_search`, `x_search`, and similar). -- Anthropic first-party ids use dashes (`claude-fable-5-1`). OpenRouter uses dots (`claude-fable-5.1`). The generator hyphenates Anthropic ids on insert. Do not copy the dotted OpenRouter slug into `ai-anthropic`. +- Do **not** copy those aliases into native provider files (any of the eight packages above). Those adapters only accept the provider's own ids. +- For a new native-provider model, write id, limits, and modalities. Infer features from the catalog capabilities: a map of flags where only `true` counts (an absent key is unknown), or a feature object, as BytePlus sends. Do **not** copy another model's tool list (`computer_use`, `google_search`, `x_search`, and similar). BytePlus inserts never claim `structured_outputs`: that gate is a live-probed list. +- ElevenLabs music and voice-design ids are pinned to SDK unions. An id the ElevenLabs SDK does not know yet fails the type-check, so wait for the SDK. BytePlus video and image duration/size tables stay hand-curated. +- Anthropic first-party ids use dashes (`claude-fable-5-1`). OpenRouter uses dots (`claude-fable-5.1`). The generator takes the modelschemas native id (already hyphenated) and does not copy the dotted OpenRouter slug into `ai-anthropic`. Dated Anthropic snapshots (`claude-haiku-4-5-20251001`) are skipped; the undated alias is the public id. - Write a row in the provider's `*ChatModelToolCapabilitiesByName` map for every new chat model, even when `supports.tools` is still `[]`. Missing that row makes `ResolveToolCapabilities` fall back to `readonly []`. -- For new Anthropic models, infer the provider-options mix from the catalog: no sampling parameters → `AnthropicMaxTokensOptions`; `reasoning.mandatory` → `AnthropicAdaptiveOnlyThinkingOptions` plus `AnthropicOutputConfigOptions`. +- For new Anthropic models, infer the provider-options mix from the catalog: no sampling parameters → `AnthropicMaxTokensOptions`; `reasoning.mandatory` → `AnthropicAdaptiveOnlyThinkingOptions` plus `AnthropicOutputConfigOptions`; reasoning params without sampling → adaptive-or-disabled thinking. Every new Claude model gets `AnthropicCacheControlOptions`. +- `firstSeenAt` is when modelschemas first crawled an id, not its release date. The first sync of a new provider can need a one-off older cutoff in `scripts/.sync-models-last-run`. - Leave curated tools and flags on existing models alone. Edit those by hand after the sync PR opens. Do not rebase or hand-edit `automated/sync-models`. The next scheduled run force-pushes that branch from `main`. Merge generator fixes to `main` first, then let the workflow rebuild the sync PR. diff --git a/docs/advanced/model-prices.md b/docs/advanced/model-prices.md new file mode 100644 index 0000000000..23da43598f --- /dev/null +++ b/docs/advanced/model-prices.md @@ -0,0 +1,155 @@ +--- +title: Model Prices +id: model-prices +description: "Price each model call from its token usage, with live rate cards from modelschemas." +keywords: + - tanstack ai + - model prices + - token cost + - modelschemas + - rate card + - onUsage +--- + +Get a model's rate card from [modelschemas](https://modelschemas.com) with `@modelschemas/client`. Check it with `rateCardSchema`, then price each call with `evaluateCard` from `@modelschemas/rate-card`. Prices change often, so read them live. Do not copy them into your code. + + + +react: @modelschemas/client @modelschemas/rate-card zod +vue: @modelschemas/client @modelschemas/rate-card zod +solid: @modelschemas/client @modelschemas/rate-card zod +svelte: @modelschemas/client @modelschemas/rate-card zod +preact: @modelschemas/client @modelschemas/rate-card zod +angular: @modelschemas/client @modelschemas/rate-card zod +octane: @modelschemas/client @modelschemas/rate-card zod +vanilla: @modelschemas/client @modelschemas/rate-card zod + + + +## Price a chat call + +Price each call in the [`onUsage`](./middleware-advanced#onusage) hook of a middleware, on the server: + +```typescript +import { chat } from "@tanstack/ai"; +import type { ChatMiddleware, TokenUsage } from "@tanstack/ai"; +import { anthropicText } from "@tanstack/ai-anthropic"; +import { createModelschemasClient, getModel } from "@modelschemas/client"; +import { RateCardError, evaluateCard } from "@modelschemas/rate-card/evaluator"; +import type { RateCard } from "@modelschemas/rate-card/evaluator"; +import { rateCardSchema } from "@modelschemas/rate-card/schema"; + +const client = createModelschemasClient({ baseUrl: "https://modelschemas.com" }); + +// Keep each rate card for one hour. +const cards = new Map }>(); + +function rateCard(provider: string, modelId: string) { + const key = `${provider}/${modelId}`; + const hit = cards.get(key); + if (hit && Date.now() - hit.at < 60 * 60 * 1000) return hit.card; + // A model with no rate card, or only a price summary, fails the check. + const card = getModel({ client, path: { provider, modelId } }).then(({ data }) => { + const parsed = rateCardSchema.safeParse(data?.pricing); + return parsed.success ? parsed.data : undefined; + }); + cards.set(key, { at: Date.now(), card }); + return card; +} + +// A rate card counts each kind of input token once. `promptTokens` holds them all. +function cardUsage(usage: TokenUsage) { + const cached = usage.promptTokensDetails?.cachedTokens ?? 0; + const written = usage.promptTokensDetails?.cacheWriteTokens ?? 0; + const written1h = usage.promptTokensDetails?.cacheWrite1hTokens ?? 0; + const cacheCounts = { + cache_read_tokens: cached, + cache_write_tokens: written - written1h, + cache_write_1h_tokens: written1h, + }; + return { + input_tokens: usage.promptTokens - cached - written, + output_tokens: usage.completionTokens, + // A card without a cache price rejects a cache count, even a 0. + ...Object.fromEntries(Object.entries(cacheCounts).filter(([, count]) => count > 0)), + }; +} + +const costLog: ChatMiddleware = { + name: "cost-log", + onUsage: async (ctx, usage) => { + const card = await rateCard("anthropic", ctx.model); + if (!card) return console.log(`${ctx.model}: no price on modelschemas`); + try { + const { amount, currency } = evaluateCard(card, { usage: cardUsage(usage) }); + const price = new Intl.NumberFormat("en", { style: "currency", currency, maximumFractionDigits: 6 }); + console.log(`${ctx.model}: ${price.format(amount)}`); + } catch (error) { + if (!(error instanceof RateCardError)) throw error; + console.log(`${ctx.model}: price not known (${error.message})`); + } + }, +}; + +const stream = chat({ + adapter: anthropicText("claude-sonnet-5-5"), + messages: [{ role: "user", content: "Hello!" }], + threadId: "thread-1", + middleware: [costLog], +}); +``` + +The log shows the cost of each model call, for example `claude-sonnet-5-5: $0.013`. A card uses long-context tiers when the input is long enough. + +## When the price is not known + +The rate card does not guess: + +- `rateCardSchema.safeParse` fails when modelschemas has no rate card for the model. +- `evaluateCard` throws `RateCardError` when the call used tokens that the card has no price for. +- `currency` is the card's own currency, for example `USD` or `CNY`. Do not add amounts in two currencies. + +modelschemas allows 60 calls an hour without a key. With the one-hour cache above, that is one call for each model. For a higher limit, pass `apiKey` to `createModelschemasClient`. + +## Price an image before you make it + +A media card prices the request, so you can show the cost before you call the model: + +```typescript +import { createModelschemasClient, getModel } from "@modelschemas/client"; +import { evaluateCard } from "@modelschemas/rate-card/evaluator"; +import { rateCardSchema } from "@modelschemas/rate-card/schema"; + +const client = createModelschemasClient({ baseUrl: "https://modelschemas.com" }); + +const { data } = await getModel({ + client, + path: { provider: "fal", modelId: "alibaba/qwen-image-3/edit" }, +}); +const parsed = rateCardSchema.safeParse(data?.pricing); +if (parsed.success) { + const { amount, currency } = evaluateCard(parsed.data, { + request: { num_images: 2 }, + }); + console.log(`Two images cost ${amount} ${currency}`); +} +``` + +## Provider ids + +Pass the modelschemas provider id, not the package name: + +| Package | modelschemas provider | +| --- | --- | +| `@tanstack/ai-anthropic` | `anthropic` | +| `@tanstack/ai-openai` | `openai`, or `azure` for Azure OpenAI | +| `@tanstack/ai-gemini` | `gemini` | +| `@tanstack/ai-vertex` | `google-vertex` | +| `@tanstack/ai-grok` | `grok` | +| `@tanstack/ai-groq` | `groq` | +| `@tanstack/ai-mistral` | `mistral` | +| `@tanstack/ai-bedrock` | `amazon-bedrock` | +| `@tanstack/ai-openrouter` | `openrouter` | +| `@tanstack/ai-vercel-gateway` | `vercel` | +| `@tanstack/ai-cloudflare` | `cloudflare-workers-ai` | +| `@tanstack/ai-fal` | `fal` | diff --git a/docs/advanced/prompt-caching.md b/docs/advanced/prompt-caching.md index 13b8006751..b018a6cc64 100644 --- a/docs/advanced/prompt-caching.md +++ b/docs/advanced/prompt-caching.md @@ -76,6 +76,8 @@ const stream = chat({ From the second call of a conversation, most of the input comes from the cache. +To turn this usage into a price, see [Model Prices](./model-prices). + ## How it works - The cache key is the first of these that you set: diff --git a/docs/community-adapters/guide.md b/docs/community-adapters/guide.md index 4eb4ccca9d..189b5ceecd 100644 --- a/docs/community-adapters/guide.md +++ b/docs/community-adapters/guide.md @@ -342,7 +342,7 @@ const EFFORT_NONE_LOW_TO_XHIGH = { const GPT5_2 = { name: 'gpt-5.2', - // ...supports, pricing + // ...supports reasoning: EFFORT_NONE_LOW_TO_XHIGH, } as const diff --git a/docs/config.json b/docs/config.json index 2577af99fb..d35733cceb 100644 --- a/docs/config.json +++ b/docs/config.json @@ -1650,7 +1650,12 @@ "label": "Prompt Caching", "to": "advanced/prompt-caching", "addedAt": "2026-10-09", - "updatedAt": "2026-10-22" + "updatedAt": "2026-10-26" + }, + { + "label": "Model Prices", + "to": "advanced/model-prices", + "addedAt": "2026-10-26" }, { "label": "Mid-Conversation Changes", diff --git a/kiira.config.ts b/kiira.config.ts index 041d9f9633..5bdc19d0b6 100644 --- a/kiira.config.ts +++ b/kiira.config.ts @@ -58,6 +58,8 @@ export default defineConfig({ '@cloudflare/workers-types': '^4.20260317.1', '@decartai/tanstack-ai-adapter': '^0.0.2', '@mynthio/tanstack-ai-adapter': '^0.0.14', + // Live model prices (docs/advanced/model-prices.md) + '@modelschemas/rate-card': '^0.2.1', '@cencori/ai-sdk': '^0.4.0', '@soniox/tanstack-ai-adapter': '^0.1.2', '@upstash/agentkit-tanstack-ai': '^0.1.1', diff --git a/package.json b/package.json index cb31d86c42..2edd3b9fe1 100644 --- a/package.json +++ b/package.json @@ -72,6 +72,7 @@ "@changesets/changelog-github": "^0.7.0", "@changesets/cli": "^2.30.0", "@faker-js/faker": "^10.1.0", + "@modelschemas/client": "^0.2.1", "@stylistic/eslint-plugin": "^5.10.0", "@tanstack/ai": "workspace:*", "@tanstack/ai-grok-build": "workspace:*", diff --git a/packages/ai-anthropic/src/model-meta.ts b/packages/ai-anthropic/src/model-meta.ts index 4009f43a50..7e98c5cde5 100644 --- a/packages/ai-anthropic/src/model-meta.ts +++ b/packages/ai-anthropic/src/model-meta.ts @@ -105,15 +105,6 @@ interface ModelMeta< context_window?: number max_output_tokens?: number knowledge_cutoff?: string - pricing: { - input: { - normal: number - cached?: number - } - output: { - normal: number - } - } /** * Type-level description of which provider options this model supports. */ @@ -138,14 +129,6 @@ const CLAUDE_OPUS_4_6 = { context_window: 200_000, max_output_tokens: 128_000, knowledge_cutoff: '2025-05-01', - pricing: { - input: { - normal: 5, - }, - output: { - normal: 25, - }, - }, supports: { input: ['text', 'image', 'document'], extended_thinking: true, @@ -180,14 +163,6 @@ const CLAUDE_OPUS_4_5 = { context_window: 200_000, max_output_tokens: 32_000, knowledge_cutoff: '2025-11-01', - pricing: { - input: { - normal: 15, - }, - output: { - normal: 75, - }, - }, supports: { input: ['text', 'image', 'document'], extended_thinking: true, @@ -223,14 +198,6 @@ const CLAUDE_SONNET_4_6 = { context_window: 1_000_000, max_output_tokens: 64_000, knowledge_cutoff: '2025-08-01', - pricing: { - input: { - normal: 3, - }, - output: { - normal: 15, - }, - }, supports: { input: ['text', 'image', 'document'], extended_thinking: true, @@ -265,14 +232,6 @@ const CLAUDE_SONNET_4_5 = { context_window: 200_000, max_output_tokens: 64_000, knowledge_cutoff: '2025-09-29', - pricing: { - input: { - normal: 3, - }, - output: { - normal: 15, - }, - }, supports: { input: ['text', 'image', 'document'], extended_thinking: true, @@ -306,14 +265,6 @@ const CLAUDE_HAIKU_4_5 = { context_window: 200_000, max_output_tokens: 64_000, knowledge_cutoff: '2025-10-01', - pricing: { - input: { - normal: 1, - }, - output: { - normal: 5, - }, - }, supports: { input: ['text', 'image', 'document'], extended_thinking: true, @@ -365,15 +316,6 @@ const CLAUDE_OPUS_4_7 = { 'memory', ], }, - pricing: { - input: { - normal: 5, - cached: 0.5, - }, - output: { - normal: 25, - }, - }, reasoning: EFFORT_LOW_TO_MAX, } as const satisfies ModelMeta< AnthropicCacheControlOptions & @@ -411,15 +353,6 @@ const CLAUDE_OPUS_4_8 = { 'memory', ], }, - pricing: { - input: { - normal: 5, - cached: 0.5, - }, - output: { - normal: 25, - }, - }, reasoning: EFFORT_LOW_TO_MAX, } as const satisfies ModelMeta< AnthropicCacheControlOptions & @@ -460,15 +393,6 @@ const CLAUDE_FABLE_5 = { 'memory', ], }, - pricing: { - input: { - normal: 10, - cached: 1, - }, - output: { - normal: 50, - }, - }, reasoning: EFFORT_LOW_TO_MAX, } as const satisfies ModelMeta< AnthropicCacheControlOptions & @@ -486,7 +410,7 @@ const CLAUDE_FABLE_5 = { // runs adaptive); `{type: 'disabled'}` opts out, but the manual // `{type: 'enabled', budget_tokens}` shape and non-default sampling // parameters (`temperature`, `top_p`, `top_k`) are rejected with a 400. -// No Priority Tier. $2/$10 per MTok is the standard price. +// No Priority Tier. const CLAUDE_SONNET_5 = { name: 'claude-sonnet-5', id: 'claude-sonnet-5', @@ -508,15 +432,6 @@ const CLAUDE_SONNET_5 = { 'memory', ], }, - pricing: { - input: { - normal: 2, - cached: 0.2, - }, - output: { - normal: 10, - }, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const satisfies ModelMeta< AnthropicCacheControlOptions & @@ -558,15 +473,6 @@ const CLAUDE_OPUS_5 = { 'memory', ], }, - pricing: { - input: { - normal: 5, - cached: 0.5, - }, - output: { - normal: 25, - }, - }, reasoning: EFFORT_LOW_TO_MAX, } as const satisfies ModelMeta< AnthropicContainerOptions & @@ -600,15 +506,6 @@ const CLAUDE_FABLE_5_1 = { 'memory', ], }, - pricing: { - input: { - normal: 10, - cached: 0.25, - }, - output: { - normal: 50, - }, - }, reasoning: EFFORT_LOW_TO_MAX, } as const satisfies ModelMeta< AnthropicCacheControlOptions & @@ -643,15 +540,6 @@ const CLAUDE_OPUS_5_5 = { 'memory', ], }, - pricing: { - input: { - normal: 4, - cached: 0.2, - }, - output: { - normal: 20, - }, - }, reasoning: EFFORT_LOW_TO_MAX, } as const satisfies ModelMeta< AnthropicCacheControlOptions & @@ -692,15 +580,6 @@ const CLAUDE_SONNET_5_5 = { 'memory', ], }, - pricing: { - input: { - normal: 2, - cached: 0.1, - }, - output: { - normal: 10, - }, - }, reasoning: EFFORT_LOW_TO_MAX, } as const satisfies ModelMeta< AnthropicCacheControlOptions & @@ -715,7 +594,7 @@ const CLAUDE_SONNET_5_5 = { > // Claude Haiku 5.5: `disabled` thinking 400s at xhigh/max (the types cannot -// say so). Pricing is the <=100K-token tier. +// say so). const CLAUDE_HAIKU_5_5 = { name: 'claude-haiku-5-5', id: 'claude-haiku-5-5', @@ -737,15 +616,6 @@ const CLAUDE_HAIKU_5_5 = { 'memory', ], }, - pricing: { - input: { - normal: 0.1, - cached: 0.01, - }, - output: { - normal: 0.5, - }, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const satisfies ModelMeta< AnthropicCacheControlOptions & diff --git a/packages/ai-byteplus/src/model-meta.ts b/packages/ai-byteplus/src/model-meta.ts index ef3fa5cf11..e490b53036 100644 --- a/packages/ai-byteplus/src/model-meta.ts +++ b/packages/ai-byteplus/src/model-meta.ts @@ -1,10 +1,13 @@ /** * BytePlus ModelArk model metadata. * - * Every Ark model id in this file — chat, video and image — was verified live - * against `https://ark.ap-southeast.bytepluses.com/api/v3` on 2026-07-31. The - * two Seed Speech ids are the exception: they live on the voice host, which - * needs a separate key that was not available, so they are docs-derived. + * Every hand-written Ark model id in this file — chat, video and image — was + * verified live against `https://ark.ap-southeast.bytepluses.com/api/v3` on + * 2026-07-31. Two kinds of id are the exception. The two Seed Speech ids live + * on the voice host, which needs a separate key that was not available, so + * they are docs-derived. Chat ids added by `scripts/sync-provider-models.ts` + * come from the modelschemas catalog and were not live-probed; the sync never + * adds them to the structured-output or thinking-summary lists below. * Capability metadata is a mix of probed and docs-derived facts; anything not * confirmed against the live API is annotated as such at its declaration. * BytePlus @@ -53,6 +56,54 @@ const EFFORT_NONE_MINIMAL_TO_HIGH = { budget: false, } as const +const DEEPSEEK_V4_1_FLASH_260910 = { + name: 'deepseek-v4-1-flash-260910', + context_window: 1_048_576, + max_output_tokens: 393_216, + supports: { + input: ['text'], + output: ['text'], + capabilities: ['reasoning', 'tool_calling'], + tools: [] as const, + }, +} as const satisfies ModelMeta + +const DEEPSEEK_V4_FLASH_GA_260731 = { + name: 'deepseek-v4-flash-ga-260731', + context_window: 1_048_576, + max_output_tokens: 393_216, + supports: { + input: ['text'], + output: ['text'], + capabilities: ['reasoning', 'tool_calling'], + tools: [] as const, + }, +} as const satisfies ModelMeta + +const DEEPSEEK_V4_PRO_GA_260813 = { + name: 'deepseek-v4-pro-ga-260813', + context_window: 1_048_576, + max_output_tokens: 393_216, + supports: { + input: ['text'], + output: ['text'], + capabilities: ['reasoning', 'tool_calling'], + tools: [] as const, + }, +} as const satisfies ModelMeta + +const GLM_5_3_FLASH_260828 = { + name: 'glm-5-3-flash-260828', + context_window: 1_048_576, + max_output_tokens: 131_072, + supports: { + input: ['text'], + output: ['text'], + capabilities: ['reasoning', 'tool_calling'], + tools: [] as const, + }, +} as const satisfies ModelMeta + /** * BytePlus exposes no server-side provider tools (no hosted web search, code * interpreter, …) on the international Ark endpoint, so every chat model @@ -355,6 +406,10 @@ const GPT_OSS_120B_250805 = { * All supported BytePlus chat model identifiers. */ export const BYTEPLUS_CHAT_MODELS = [ + DEEPSEEK_V4_1_FLASH_260910.name, + DEEPSEEK_V4_FLASH_GA_260731.name, + DEEPSEEK_V4_PRO_GA_260813.name, + GLM_5_3_FLASH_260828.name, DOLA_SEED_2_1_TURBO.name, SEED_2_0_LITE_260428.name, SEED_2_0_MINI_260428.name, @@ -501,6 +556,10 @@ export type BytePlusModelInputModalitiesByName = { [DEEPSEEK_V4_FLASH_260425.name]: typeof DEEPSEEK_V4_FLASH_260425.supports.input [DEEPSEEK_V3_2_251201.name]: typeof DEEPSEEK_V3_2_251201.supports.input [GPT_OSS_120B_250805.name]: typeof GPT_OSS_120B_250805.supports.input + [DEEPSEEK_V4_1_FLASH_260910.name]: typeof DEEPSEEK_V4_1_FLASH_260910.supports.input + [DEEPSEEK_V4_FLASH_GA_260731.name]: typeof DEEPSEEK_V4_FLASH_GA_260731.supports.input + [DEEPSEEK_V4_PRO_GA_260813.name]: typeof DEEPSEEK_V4_PRO_GA_260813.supports.input + [GLM_5_3_FLASH_260828.name]: typeof GLM_5_3_FLASH_260828.supports.input } /** @@ -530,6 +589,11 @@ export const BYTEPLUS_MODEL_INPUT_MODALITIES: Readonly< [DEEPSEEK_V4_FLASH_260425.name]: DEEPSEEK_V4_FLASH_260425.supports.input, [DEEPSEEK_V3_2_251201.name]: DEEPSEEK_V3_2_251201.supports.input, [GPT_OSS_120B_250805.name]: GPT_OSS_120B_250805.supports.input, + [DEEPSEEK_V4_1_FLASH_260910.name]: DEEPSEEK_V4_1_FLASH_260910.supports.input, + [DEEPSEEK_V4_FLASH_GA_260731.name]: + DEEPSEEK_V4_FLASH_GA_260731.supports.input, + [DEEPSEEK_V4_PRO_GA_260813.name]: DEEPSEEK_V4_PRO_GA_260813.supports.input, + [GLM_5_3_FLASH_260828.name]: GLM_5_3_FLASH_260828.supports.input, } satisfies BytePlusModelInputModalitiesByName /** diff --git a/packages/ai-gemini/src/model-meta.ts b/packages/ai-gemini/src/model-meta.ts index e5493443ad..84176b3ed3 100644 --- a/packages/ai-gemini/src/model-meta.ts +++ b/packages/ai-gemini/src/model-meta.ts @@ -56,15 +56,6 @@ interface ModelMeta { max_input_tokens?: number max_output_tokens?: number knowledge_cutoff?: string - pricing?: { - input: { - normal: number - cached?: number - } - output: { - normal: number - } - } /** * Type-level description of which provider options this model supports. */ @@ -90,14 +81,6 @@ const GEMINI_3_1_PRO = { ], tools: ['code_execution', 'file_search', 'google_search', 'url_context'], }, - pricing: { - input: { - normal: 2.5, - }, - output: { - normal: 15, - }, - }, reasoning: EFFORT_LOW_TO_HIGH, } as const satisfies ModelMeta< GeminiToolConfigOptions & @@ -124,14 +107,6 @@ const GEMINI_3_FLASH = { ], tools: ['code_execution', 'file_search', 'google_search', 'url_context'], }, - pricing: { - input: { - normal: 0.5, - }, - output: { - normal: 3, - }, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const satisfies ModelMeta< GeminiToolConfigOptions & @@ -157,14 +132,6 @@ const GEMINI_3_PRO_IMAGE = { capabilities: ['batch_api', 'structured_output', 'thinking'], tools: ['google_search'], }, - pricing: { - input: { - normal: 2, - }, - output: { - normal: 0.134, - }, - }, } as const satisfies ModelMeta< GeminiToolConfigOptions & GeminiSafetyOptions & @@ -190,14 +157,6 @@ const GEMINI_3_1_FLASH_IMAGE = { capabilities: ['batch_api', 'thinking'], tools: ['google_search'], }, - pricing: { - input: { - normal: 0.5, - }, - output: { - normal: 3, - }, - }, } as const satisfies ModelMeta< GeminiToolConfigOptions & GeminiSafetyOptions & @@ -220,14 +179,6 @@ const GEMINI_3_1_FLASH_LITE_IMAGE = { capabilities: ['batch_api', 'structured_output', 'thinking'], tools: ['google_search'], }, - pricing: { - input: { - normal: 0.25, - }, - output: { - normal: 1.5, - }, - }, } as const satisfies ModelMeta< GeminiToolConfigOptions & GeminiSafetyOptions & @@ -252,14 +203,6 @@ const GEMINI_NANO_BANANA_2_1 = { capabilities: ['batch_api', 'thinking'], tools: ['google_search'], }, - pricing: { - input: { - normal: 1.5, - }, - output: { - normal: 7.5, - }, - }, } as const satisfies ModelMeta< GeminiToolConfigOptions & GeminiSafetyOptions & @@ -284,14 +227,6 @@ const GEMINI_3_1_FLASH_LITE = { ], tools: ['code_execution', 'file_search', 'google_search', 'url_context'], }, - pricing: { - input: { - normal: 0.25, - }, - output: { - normal: 1.5, - }, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const satisfies ModelMeta< GeminiToolConfigOptions & @@ -318,14 +253,6 @@ const GEMINI_3_1_FLASH_LITE_PREVIEW = { ], tools: ['code_execution', 'file_search', 'google_search', 'url_context'], }, - pricing: { - input: { - normal: 0.25, - }, - output: { - normal: 1.5, - }, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const satisfies ModelMeta< GeminiToolConfigOptions & @@ -358,14 +285,6 @@ const GEMINI_2_5_PRO = { 'url_context', ], }, - pricing: { - input: { - normal: 2.5, - }, - output: { - normal: 15, - }, - }, reasoning: BUDGET_MINIMAL_TO_HIGH, } as const satisfies ModelMeta< GeminiToolConfigOptions & @@ -385,14 +304,6 @@ const GEMINI_2_5_PRO_TTS = { output: ['audio'], capabilities: ['audio_generation'], }, - pricing: { - input: { - normal: 2.5, - }, - output: { - normal: 15, - }, - }, } as const satisfies ModelMeta< GeminiToolConfigOptions & GeminiSafetyOptions & @@ -423,14 +334,6 @@ const GEMINI_2_5_FLASH = { 'url_context', ], }, - pricing: { - input: { - normal: 1, - }, - output: { - normal: 2.5, - }, - }, reasoning: BUDGET_OFF_HIGH, } as const satisfies ModelMeta< GeminiToolConfigOptions & @@ -458,15 +361,6 @@ const GEMINI_2_5_FLASH_LIVE = { 'thinking', ], }, - pricing: { - // todo find this info - input: { - normal: 0, - }, - output: { - normal: 0, - }, - }, } as const satisfies ModelMeta< GeminiToolConfigOptions & GeminiSafetyOptions & @@ -484,14 +378,6 @@ const GEMINI_2_5_FLASH_TTS = { output: ['audio'], capabilities: ['audio_generation', 'batch_api'], }, - pricing: { - input: { - normal: 1, - }, - output: { - normal: 2.5, - }, - }, } as const satisfies ModelMeta< GeminiToolConfigOptions & GeminiSafetyOptions & @@ -514,14 +400,6 @@ const GEMINI_3_1_FLASH_TTS = { output: ['audio'], capabilities: ['audio_generation', 'batch_api'], }, - pricing: { - input: { - normal: 0.5, - }, - output: { - normal: 10, - }, - }, } as const satisfies ModelMeta< GeminiToolConfigOptions & GeminiSafetyOptions & @@ -543,14 +421,6 @@ const LYRIA_3_PRO = { output: ['audio'], capabilities: ['audio_generation'], }, - pricing: { - input: { - normal: 0, - }, - output: { - normal: 0, - }, - }, } as const satisfies ModelMeta /** @@ -565,14 +435,6 @@ const LYRIA_3_CLIP = { output: ['audio'], capabilities: ['audio_generation'], }, - pricing: { - input: { - normal: 0, - }, - output: { - normal: 0, - }, - }, } as const satisfies ModelMeta const GEMINI_2_5_FLASH_LITE = { @@ -592,14 +454,6 @@ const GEMINI_2_5_FLASH_LITE = { ], tools: ['code_execution', 'google_maps', 'google_search', 'url_context'], }, - pricing: { - input: { - normal: 0.1, - }, - output: { - normal: 0.4, - }, - }, reasoning: BUDGET_OFF_HIGH, } as const satisfies ModelMeta< GeminiToolConfigOptions & @@ -610,8 +464,7 @@ const GEMINI_2_5_FLASH_LITE = { > /** - * Veo video generation models. Pricing is per second of generated video - * (audio+video rate where the model supports audio). + * Veo video generation models. * @experimental Veo video generation is an experimental feature and may change. */ const VEO_3_1_PREVIEW = { @@ -622,14 +475,6 @@ const VEO_3_1_PREVIEW = { input: ['text', 'image'], output: ['video', 'audio'], }, - pricing: { - input: { - normal: 0, - }, - output: { - normal: 0.4, - }, - }, } as const satisfies ModelMeta< GeminiToolConfigOptions & GeminiSafetyOptions & @@ -645,14 +490,6 @@ const VEO_3_1_FAST_PREVIEW = { input: ['text', 'image'], output: ['video', 'audio'], }, - pricing: { - input: { - normal: 0, - }, - output: { - normal: 0.15, - }, - }, } as const satisfies ModelMeta< GeminiToolConfigOptions & GeminiSafetyOptions & @@ -668,14 +505,6 @@ const VEO_3_1_LITE_PREVIEW = { input: ['text', 'image'], output: ['video', 'audio'], }, - pricing: { - input: { - normal: 0, - }, - output: { - normal: 0.05, - }, - }, } as const satisfies ModelMeta< GeminiToolConfigOptions & GeminiSafetyOptions & @@ -688,8 +517,7 @@ const VEO_3_1_LITE_PREVIEW = { * conversational editing. Serves only the Interactions API * (`generateContent` rejects it), so it routes through the * interactions-based path of the video adapter, not Veo's - * `:predictLongRunning` flow. Pricing is per second of generated video - * ($0.10/sec). 360p / 720p (default) / 1080p / 4k at 24 FPS, 3–10 second + * `:predictLongRunning` flow. 360p / 720p (default) / 1080p / 4k at 24 FPS, 3–10 second * clips (default 10s). * @see https://ai.google.dev/gemini-api/docs/models/gemini-omni-flash * @experimental Omni video generation is an experimental feature and may change. @@ -702,14 +530,6 @@ const GEMINI_OMNI_1_1_FLASH = { input: ['text', 'image', 'video'], output: ['video', 'audio'], }, - pricing: { - input: { - normal: 0, - }, - output: { - normal: 0.1, - }, - }, } as const satisfies ModelMeta< GeminiToolConfigOptions & GeminiSafetyOptions & @@ -742,15 +562,6 @@ const GEMINI_3_8_FLASH = { 'computer_use', ], }, - pricing: { - input: { - normal: 0.75, - cached: 0.075, - }, - output: { - normal: 3.75, - }, - }, reasoning: EFFORT_LOW_TO_HIGH, } as const satisfies ModelMeta< GeminiToolConfigOptions & @@ -785,17 +596,6 @@ const GEMINI_3_7_FLASH = { 'computer_use', ], }, - // Currently 50% off through the end of 2026. - // https://ai.google.dev/gemini-api/docs/pricing#gemini-3.7-flash - pricing: { - input: { - normal: 0.75, - cached: 0.075, - }, - output: { - normal: 3.75, - }, - }, reasoning: EFFORT_LOW_TO_HIGH, } as const satisfies ModelMeta< GeminiToolConfigOptions & @@ -830,15 +630,6 @@ const GEMINI_3_6_FLASH = { 'computer_use', ], }, - pricing: { - input: { - normal: 1.5, - cached: 0.15, - }, - output: { - normal: 7.5, - }, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const satisfies ModelMeta< GeminiToolConfigOptions & @@ -871,15 +662,6 @@ const GEMINI_3_5_FLASH = { 'computer_use', ], }, - pricing: { - input: { - normal: 1.5, - cached: 0.15, - }, - output: { - normal: 9, - }, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const satisfies ModelMeta< GeminiToolConfigOptions & @@ -913,15 +695,6 @@ const GEMINI_3_5_FLASH_LITE = { 'url_context', ], }, - pricing: { - input: { - normal: 0.3, - cached: 0.03, - }, - output: { - normal: 2.5, - }, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const satisfies ModelMeta< GeminiToolConfigOptions & @@ -941,15 +714,6 @@ const GEMINI_4_ARGON = { capabilities: ['function_calling', 'structured_output', 'thinking'], tools: ['code_execution', 'file_search', 'google_search', 'url_context'], }, - pricing: { - input: { - normal: 2, - cached: 0.1, - }, - output: { - normal: 10, - }, - }, } as const satisfies ModelMeta< GeminiToolConfigOptions & GeminiSafetyOptions & diff --git a/packages/ai-grok/src/model-meta.ts b/packages/ai-grok/src/model-meta.ts index 217764cc21..3e5c3152ca 100644 --- a/packages/ai-grok/src/model-meta.ts +++ b/packages/ai-grok/src/model-meta.ts @@ -32,15 +32,6 @@ interface ModelMeta { max_output_tokens?: number context_window?: number knowledge_cutoff?: string - pricing?: { - input: { - normal: number - cached?: number - } - output: { - normal: number - } - } /** The model's data for `chat({ reasoning })`. None: it does not reason. */ reasoning?: ModelReasoning } @@ -54,15 +45,6 @@ const GROK_4_5 = { capabilities: ['reasoning', 'structured_outputs', 'tool_calling'], tools: [], }, - pricing: { - input: { - normal: 2, - cached: 0.3, - }, - output: { - normal: 6, - }, - }, reasoning: EFFORT_LOW_TO_HIGH, } as const satisfies ModelMeta @@ -75,15 +57,6 @@ const GROK_4_6 = { capabilities: ['reasoning', 'structured_outputs', 'tool_calling'], tools: [], }, - pricing: { - input: { - normal: 2, - cached: 0.5, - }, - output: { - normal: 6, - }, - }, reasoning: EFFORT_LOW_TO_XHIGH, } as const satisfies ModelMeta @@ -97,15 +70,6 @@ const GROK_4_7 = { capabilities: ['reasoning', 'structured_outputs', 'tool_calling'], tools: [], }, - pricing: { - input: { - normal: 1.6, - cached: 0.4, - }, - output: { - normal: 4.8, - }, - }, reasoning: EFFORT_LOW_TO_XHIGH, } as const satisfies ModelMeta @@ -122,21 +86,13 @@ const GROK_RESPONSES_TOOLS = [ 'mcp', ] as const satisfies ReadonlyArray -// Imagine API image models. Pricing is per generated image (output only). +// Imagine API image models. const GROK_IMAGINE_IMAGE = { name: 'grok-imagine-image', supports: { input: ['text', 'image'], output: ['image'], }, - pricing: { - input: { - normal: 0, - }, - output: { - normal: 0.02, - }, - }, } as const satisfies ModelMeta const GROK_IMAGINE_IMAGE_QUALITY = { @@ -145,14 +101,6 @@ const GROK_IMAGINE_IMAGE_QUALITY = { input: ['text', 'image'], output: ['image'], }, - pricing: { - input: { - normal: 0, - }, - output: { - normal: 0.05, - }, - }, } as const satisfies ModelMeta // xAI's recommended Imagine image model. Supports the 2.0-only `quality` @@ -163,18 +111,9 @@ const GROK_IMAGINE_IMAGE_2_0 = { input: ['text', 'image'], output: ['image'], }, - pricing: { - input: { - normal: 0, - }, - output: { - normal: 0.04, - }, - }, } as const satisfies ModelMeta -// Imagine API video models. Pricing is per second of generated video -// (output only); generated videos carry an audio track. +// Imagine API video models. Generated videos carry an audio track. // // Both models support text-to-video and image-to-video (a starting-frame // image is optional). grok-imagine-video-1.5 is the documented default: it @@ -189,15 +128,6 @@ const GROK_IMAGINE_VIDEO = { input: ['text', 'image', 'video'], output: ['video', 'audio'], }, - pricing: { - input: { - normal: 0, - }, - output: { - // per second of video - normal: 0.05, - }, - }, } as const satisfies ModelMeta const GROK_IMAGINE_VIDEO_1_5 = { @@ -206,15 +136,6 @@ const GROK_IMAGINE_VIDEO_1_5 = { input: ['text', 'image'], output: ['video', 'audio'], }, - pricing: { - input: { - normal: 0, - }, - output: { - // per second of video - normal: 0.08, - }, - }, } as const satisfies ModelMeta const GROK_4_3 = { @@ -226,15 +147,6 @@ const GROK_4_3 = { capabilities: ['reasoning', 'structured_outputs', 'tool_calling'], tools: GROK_RESPONSES_TOOLS, }, - pricing: { - input: { - normal: 1.25, - cached: 0.2, - }, - output: { - normal: 2.5, - }, - }, reasoning: EFFORT_NONE_LOW_TO_HIGH, } as const satisfies ModelMeta @@ -247,15 +159,6 @@ const GROK_BUILD_0_1 = { capabilities: ['reasoning', 'structured_outputs', 'tool_calling'], tools: GROK_RESPONSES_TOOLS, }, - pricing: { - input: { - normal: 1, - cached: 0.2, - }, - output: { - normal: 2, - }, - }, } as const satisfies ModelMeta // Vertex Model Garden IDs. These are not the xAI API catalog. diff --git a/packages/ai-groq/src/model-meta.ts b/packages/ai-groq/src/model-meta.ts index e34863d571..c38ace3619 100644 --- a/packages/ai-groq/src/model-meta.ts +++ b/packages/ai-groq/src/model-meta.ts @@ -15,16 +15,12 @@ const EFFORT_NONE_LOW_TO_HIGH = { } as const /** - * Internal metadata structure describing a Groq model's capabilities and pricing. + * Internal metadata structure describing a Groq model's capabilities. */ interface ModelMeta { name: string context_window?: number max_completion_tokens?: number - pricing: { - input?: { normal: number; cached?: number } - output?: { normal: number } - } supports: { input: Array<'text' | 'image' | 'audio'> output: Array<'text' | 'audio'> @@ -55,14 +51,6 @@ const LLAMA_PROMPT_GUARD_2_86M = { name: 'meta-llama/llama-prompt-guard-2-86m', context_window: 512, max_completion_tokens: 512, - pricing: { - input: { - normal: 0.04, - }, - output: { - normal: 0.04, - }, - }, supports: { input: ['text'], output: ['text'], @@ -76,14 +64,6 @@ const LLAMA_PROMPT_GUARD_2_22M = { name: 'meta-llama/llama-prompt-guard-2-22m', context_window: 512, max_completion_tokens: 512, - pricing: { - input: { - normal: 0.03, - }, - output: { - normal: 0.03, - }, - }, supports: { input: ['text'], output: ['text'], @@ -97,15 +77,6 @@ const GPT_OSS_120B = { name: 'openai/gpt-oss-120b', context_window: 131_072, max_completion_tokens: 65_536, - pricing: { - input: { - normal: 0.15, - cached: 0.075, - }, - output: { - normal: 0.6, - }, - }, supports: { input: ['text'], output: ['text'], @@ -128,15 +99,6 @@ const GPT_OSS_SAFEGUARD_20B = { name: 'openai/gpt-oss-safeguard-20b', context_window: 131_072, max_completion_tokens: 65_536, - pricing: { - input: { - normal: 0.075, - cached: 0.037, - }, - output: { - normal: 0.3, - }, - }, supports: { input: ['text'], output: ['text'], @@ -160,15 +122,6 @@ const GPT_OSS_20B = { name: 'openai/gpt-oss-20b', context_window: 131_072, max_completion_tokens: 65_536, - pricing: { - input: { - normal: 0.075, - cached: 0.037, - }, - output: { - normal: 0.3, - }, - }, supports: { input: ['text'], output: ['text'], @@ -191,14 +144,6 @@ const QWEN_QWEN3_8_27B = { name: 'qwen/qwen3.8-27b', context_window: 131_072, max_completion_tokens: 16_384, - pricing: { - input: { - normal: 0.8, - }, - output: { - normal: 4, - }, - }, supports: { input: ['text', 'image'], output: ['text'], @@ -349,11 +294,6 @@ export type GroqTranscriptionModel = (typeof GROQ_TRANSCRIPTION_MODELS)[number] const ORPHEUS_V1_ENGLISH = { name: 'canopylabs/orpheus-v1-english', - pricing: { - input: { - normal: 22, - }, - }, supports: { input: ['text'], output: ['audio'], @@ -364,11 +304,6 @@ const ORPHEUS_V1_ENGLISH = { const ORPHEUS_ARABIC_SAUDI = { name: 'canopylabs/orpheus-arabic-saudi', - pricing: { - input: { - normal: 40, - }, - }, supports: { input: ['text'], output: ['audio'], diff --git a/packages/ai-mistral/src/model-meta.ts b/packages/ai-mistral/src/model-meta.ts index 67660d1e30..47a47010de 100644 --- a/packages/ai-mistral/src/model-meta.ts +++ b/packages/ai-mistral/src/model-meta.ts @@ -17,6 +17,229 @@ const EFFORT_OFF_HIGH = { budget: false, } as const +const CODESTRAL_2508 = { + name: 'codestral-2508', + context_window: 256_000, + max_completion_tokens: 204_800, + supports: { + input: ['text', 'image', 'audio'], + output: ['text'], + endpoints: ['chat'], + features: [ + 'streaming', + 'tools', + 'json_object', + 'json_schema', + 'reasoning', + 'vision', + ], + }, +} as const satisfies ModelMeta + +const LABS_LEANSTRAL_1_5 = { + name: 'labs-leanstral-1-5', + context_window: 262_144, + supports: { + input: ['text', 'image', 'audio'], + output: ['text'], + endpoints: ['chat'], + features: [ + 'streaming', + 'tools', + 'json_object', + 'json_schema', + 'reasoning', + 'vision', + ], + }, +} as const satisfies ModelMeta + +const LABS_LEANSTRAL_1_5_1 = { + name: 'labs-leanstral-1-5-1', + context_window: 262_144, + supports: { + input: ['text', 'image', 'audio'], + output: ['text'], + endpoints: ['chat'], + features: [ + 'streaming', + 'tools', + 'json_object', + 'json_schema', + 'reasoning', + 'vision', + ], + }, +} as const satisfies ModelMeta + +const MINISTRAL_14B_2512 = { + name: 'ministral-14b-2512', + context_window: 262_144, + max_completion_tokens: 209_715, + supports: { + input: ['text', 'image', 'audio'], + output: ['text'], + endpoints: ['chat'], + features: [ + 'streaming', + 'tools', + 'json_object', + 'json_schema', + 'reasoning', + 'vision', + ], + }, +} as const satisfies ModelMeta + +const MINISTRAL_14B_LATEST = { + name: 'ministral-14b-latest', + context_window: 262_144, + supports: { + input: ['text', 'image', 'audio'], + output: ['text'], + endpoints: ['chat'], + features: [ + 'streaming', + 'tools', + 'json_object', + 'json_schema', + 'reasoning', + 'vision', + ], + }, +} as const satisfies ModelMeta + +const MINISTRAL_3B_2512 = { + name: 'ministral-3b-2512', + context_window: 131_072, + max_completion_tokens: 104_857, + supports: { + input: ['text', 'image', 'audio'], + output: ['text'], + endpoints: ['chat'], + features: [ + 'streaming', + 'tools', + 'json_object', + 'json_schema', + 'reasoning', + 'vision', + ], + }, +} as const satisfies ModelMeta + +const MINISTRAL_8B_2512 = { + name: 'ministral-8b-2512', + context_window: 262_144, + max_completion_tokens: 209_715, + supports: { + input: ['text', 'image', 'audio'], + output: ['text'], + endpoints: ['chat'], + features: [ + 'streaming', + 'tools', + 'json_object', + 'json_schema', + 'reasoning', + 'vision', + ], + }, +} as const satisfies ModelMeta + +const MISTRAL_LARGE_2512 = { + name: 'mistral-large-2512', + context_window: 262_144, + max_completion_tokens: 209_715, + supports: { + input: ['text', 'image', 'audio'], + output: ['text'], + endpoints: ['chat'], + features: [ + 'streaming', + 'tools', + 'json_object', + 'json_schema', + 'reasoning', + 'vision', + ], + }, +} as const satisfies ModelMeta + +const MISTRAL_MEDIUM = { + name: 'mistral-medium', + context_window: 262_144, + supports: { + input: ['text', 'image', 'audio'], + output: ['text'], + endpoints: ['chat'], + features: [ + 'streaming', + 'tools', + 'json_object', + 'json_schema', + 'reasoning', + 'vision', + ], + }, +} as const satisfies ModelMeta + +const MISTRAL_MEDIUM_2604 = { + name: 'mistral-medium-2604', + context_window: 262_144, + supports: { + input: ['text', 'image', 'audio'], + output: ['text'], + endpoints: ['chat'], + features: [ + 'streaming', + 'tools', + 'json_object', + 'json_schema', + 'reasoning', + 'vision', + ], + }, +} as const satisfies ModelMeta + +const MISTRAL_MEDIUM_3_5 = { + name: 'mistral-medium-3-5', + context_window: 262_144, + max_completion_tokens: 209_715, + supports: { + input: ['text', 'image', 'audio'], + output: ['text'], + endpoints: ['chat'], + features: [ + 'streaming', + 'tools', + 'json_object', + 'json_schema', + 'reasoning', + 'vision', + ], + }, +} as const satisfies ModelMeta + +const MISTRAL_SMALL_2603 = { + name: 'mistral-small-2603', + context_window: 262_144, + max_completion_tokens: 209_715, + supports: { + input: ['text', 'image', 'audio'], + output: ['text'], + endpoints: ['chat'], + features: [ + 'streaming', + 'tools', + 'json_object', + 'json_schema', + 'reasoning', + 'vision', + ], + }, +} as const satisfies ModelMeta + /** Provider options for vision-capable Mistral models. */ export type MistralVisionProviderOptions = MistralTextProviderOptions @@ -24,17 +247,12 @@ export type MistralVisionProviderOptions = MistralTextProviderOptions export type MistralReasoningProviderOptions = MistralTextProviderOptions /** - * Internal metadata structure describing a Mistral model's capabilities - * and approximate pricing (USD per million tokens). + * Internal metadata structure describing a Mistral model's capabilities. */ interface ModelMeta { name: string context_window?: number max_completion_tokens?: number - pricing: { - input?: { normal: number; cached?: number } - output?: { normal: number } - } supports: { input: Array<'text' | 'image' | 'audio' | 'document'> output: Array<'text'> @@ -59,10 +277,6 @@ const MISTRAL_LARGE_LATEST = { name: 'mistral-large-latest', context_window: 131_072, max_completion_tokens: 8_192, - pricing: { - input: { normal: 0.5 }, - output: { normal: 1.5 }, - }, supports: { input: ['text'], output: ['text'], @@ -75,10 +289,6 @@ const MISTRAL_MEDIUM_LATEST = { name: 'mistral-medium-latest', context_window: 131_072, max_completion_tokens: 8_192, - pricing: { - input: { normal: 0.4 }, - output: { normal: 2 }, - }, supports: { input: ['text', 'image', 'document'], output: ['text'], @@ -92,10 +302,6 @@ const MISTRAL_SMALL_LATEST = { name: 'mistral-small-latest', context_window: 131_072, max_completion_tokens: 8_192, - pricing: { - input: { normal: 0.1 }, - output: { normal: 0.3 }, - }, supports: { input: ['text', 'image', 'document'], output: ['text'], @@ -109,10 +315,6 @@ const MINISTRAL_8B_LATEST = { name: 'ministral-8b-latest', context_window: 131_072, max_completion_tokens: 8_192, - pricing: { - input: { normal: 0.1 }, - output: { normal: 0.1 }, - }, supports: { input: ['text'], output: ['text'], @@ -125,10 +327,6 @@ const MINISTRAL_3B_LATEST = { name: 'ministral-3b-latest', context_window: 131_072, max_completion_tokens: 8_192, - pricing: { - input: { normal: 0.04 }, - output: { normal: 0.04 }, - }, supports: { input: ['text'], output: ['text'], @@ -141,10 +339,6 @@ const CODESTRAL_LATEST = { name: 'codestral-latest', context_window: 256_000, max_completion_tokens: 8_192, - pricing: { - input: { normal: 0.3 }, - output: { normal: 0.9 }, - }, supports: { input: ['text'], output: ['text'], @@ -157,10 +351,6 @@ const MAGISTRAL_MEDIUM_LATEST = { name: 'magistral-medium-latest', context_window: 40_000, max_completion_tokens: 40_000, - pricing: { - input: { normal: 2 }, - output: { normal: 5 }, - }, supports: { input: ['text'], output: ['text'], @@ -174,10 +364,6 @@ const MAGISTRAL_SMALL_LATEST = { name: 'magistral-small-latest', context_window: 40_000, max_completion_tokens: 40_000, - pricing: { - input: { normal: 0.5 }, - output: { normal: 1.5 }, - }, supports: { input: ['text'], output: ['text'], @@ -194,10 +380,6 @@ const MISTRAL_MEDIUM_3 = { name: 'mistral-medium-3', context_window: 131_072, max_completion_tokens: 8_192, - pricing: { - input: { normal: 0.4 }, - output: { normal: 2 }, - }, supports: { input: ['text', 'image', 'document'], output: ['text'], @@ -210,10 +392,6 @@ const MISTRAL_SMALL_2503 = { name: 'mistral-small-2503', context_window: 131_072, max_completion_tokens: 8_192, - pricing: { - input: { normal: 0.1 }, - output: { normal: 0.3 }, - }, supports: { input: ['text', 'image', 'document'], output: ['text'], @@ -226,10 +404,6 @@ const CODESTRAL_2 = { name: 'codestral-2', context_window: 131_072, max_completion_tokens: 8_192, - pricing: { - input: { normal: 0.3 }, - output: { normal: 0.9 }, - }, supports: { input: ['text'], output: ['text'], @@ -242,6 +416,18 @@ const CODESTRAL_2 = { * All supported Mistral chat model identifiers. */ export const MISTRAL_CHAT_MODELS = [ + CODESTRAL_2508.name, + LABS_LEANSTRAL_1_5.name, + LABS_LEANSTRAL_1_5_1.name, + MINISTRAL_14B_2512.name, + MINISTRAL_14B_LATEST.name, + MINISTRAL_3B_2512.name, + MINISTRAL_8B_2512.name, + MISTRAL_LARGE_2512.name, + MISTRAL_MEDIUM.name, + MISTRAL_MEDIUM_2604.name, + MISTRAL_MEDIUM_3_5.name, + MISTRAL_SMALL_2603.name, MISTRAL_LARGE_LATEST.name, MISTRAL_MEDIUM_LATEST.name, MISTRAL_SMALL_LATEST.name, @@ -286,6 +472,18 @@ export type MistralModelInputModalitiesByName = { [MISTRAL_MEDIUM_3.name]: typeof MISTRAL_MEDIUM_3.supports.input [MISTRAL_SMALL_2503.name]: typeof MISTRAL_SMALL_2503.supports.input [CODESTRAL_2.name]: typeof CODESTRAL_2.supports.input + [CODESTRAL_2508.name]: typeof CODESTRAL_2508.supports.input + [LABS_LEANSTRAL_1_5.name]: typeof LABS_LEANSTRAL_1_5.supports.input + [LABS_LEANSTRAL_1_5_1.name]: typeof LABS_LEANSTRAL_1_5_1.supports.input + [MINISTRAL_14B_2512.name]: typeof MINISTRAL_14B_2512.supports.input + [MINISTRAL_14B_LATEST.name]: typeof MINISTRAL_14B_LATEST.supports.input + [MINISTRAL_3B_2512.name]: typeof MINISTRAL_3B_2512.supports.input + [MINISTRAL_8B_2512.name]: typeof MINISTRAL_8B_2512.supports.input + [MISTRAL_LARGE_2512.name]: typeof MISTRAL_LARGE_2512.supports.input + [MISTRAL_MEDIUM.name]: typeof MISTRAL_MEDIUM.supports.input + [MISTRAL_MEDIUM_2604.name]: typeof MISTRAL_MEDIUM_2604.supports.input + [MISTRAL_MEDIUM_3_5.name]: typeof MISTRAL_MEDIUM_3_5.supports.input + [MISTRAL_SMALL_2603.name]: typeof MISTRAL_SMALL_2603.supports.input } /** @@ -307,6 +505,18 @@ export const MISTRAL_MODEL_INPUT_MODALITIES: Readonly< [MISTRAL_MEDIUM_3.name]: MISTRAL_MEDIUM_3.supports.input, [MISTRAL_SMALL_2503.name]: MISTRAL_SMALL_2503.supports.input, [CODESTRAL_2.name]: CODESTRAL_2.supports.input, + [CODESTRAL_2508.name]: CODESTRAL_2508.supports.input, + [LABS_LEANSTRAL_1_5.name]: LABS_LEANSTRAL_1_5.supports.input, + [LABS_LEANSTRAL_1_5_1.name]: LABS_LEANSTRAL_1_5_1.supports.input, + [MINISTRAL_14B_2512.name]: MINISTRAL_14B_2512.supports.input, + [MINISTRAL_14B_LATEST.name]: MINISTRAL_14B_LATEST.supports.input, + [MINISTRAL_3B_2512.name]: MINISTRAL_3B_2512.supports.input, + [MINISTRAL_8B_2512.name]: MINISTRAL_8B_2512.supports.input, + [MISTRAL_LARGE_2512.name]: MISTRAL_LARGE_2512.supports.input, + [MISTRAL_MEDIUM.name]: MISTRAL_MEDIUM.supports.input, + [MISTRAL_MEDIUM_2604.name]: MISTRAL_MEDIUM_2604.supports.input, + [MISTRAL_MEDIUM_3_5.name]: MISTRAL_MEDIUM_3_5.supports.input, + [MISTRAL_SMALL_2603.name]: MISTRAL_SMALL_2603.supports.input, } satisfies MistralModelInputModalitiesByName /** @@ -324,6 +534,18 @@ export type MistralChatModelProviderOptionsByName = { [MISTRAL_MEDIUM_3.name]: MistralVisionProviderOptions [MISTRAL_SMALL_2503.name]: MistralVisionProviderOptions [CODESTRAL_2.name]: MistralTextProviderOptions + [CODESTRAL_2508.name]: MistralTextProviderOptions + [LABS_LEANSTRAL_1_5.name]: MistralTextProviderOptions + [LABS_LEANSTRAL_1_5_1.name]: MistralTextProviderOptions + [MINISTRAL_14B_2512.name]: MistralTextProviderOptions + [MINISTRAL_14B_LATEST.name]: MistralTextProviderOptions + [MINISTRAL_3B_2512.name]: MistralTextProviderOptions + [MINISTRAL_8B_2512.name]: MistralTextProviderOptions + [MISTRAL_LARGE_2512.name]: MistralTextProviderOptions + [MISTRAL_MEDIUM.name]: MistralTextProviderOptions + [MISTRAL_MEDIUM_2604.name]: MistralTextProviderOptions + [MISTRAL_MEDIUM_3_5.name]: MistralTextProviderOptions + [MISTRAL_SMALL_2603.name]: MistralTextProviderOptions } /** diff --git a/packages/ai-openai/src/model-meta.ts b/packages/ai-openai/src/model-meta.ts index 86c7247315..f79c2a4092 100644 --- a/packages/ai-openai/src/model-meta.ts +++ b/packages/ai-openai/src/model-meta.ts @@ -117,15 +117,6 @@ interface ModelMeta { context_window?: number max_output_tokens?: number knowledge_cutoff?: string - pricing: { - input: { - normal: number - cached?: number - } - output: { - normal: number - } - } /** * Type-level description of which provider options this model supports. */ @@ -163,15 +154,6 @@ const GPT5_2 = { 'apply_patch', ], }, - pricing: { - input: { - normal: 1.75, - cached: 0.175, - }, - output: { - normal: 14, - }, - }, reasoning: EFFORT_NONE_LOW_TO_XHIGH, } as const satisfies ModelMeta< OpenAIBaseOptions & @@ -204,14 +186,6 @@ const GPT5_2_PRO = { 'apply_patch', ], }, - pricing: { - input: { - normal: 21, - }, - output: { - normal: 168, - }, - }, reasoning: EFFORT_MEDIUM_TO_XHIGH, } as const satisfies ModelMeta< OpenAIBaseOptions & @@ -239,15 +213,6 @@ const GPT5_2_CHAT = { 'mcp', ], }, - pricing: { - input: { - normal: 1.75, - cached: 0.175, - }, - output: { - normal: 14, - }, - }, reasoning: EFFORT_MEDIUM, } as const satisfies ModelMeta< OpenAIBaseOptions & @@ -285,15 +250,6 @@ const GPT5_1 = { 'apply_patch', ], }, - pricing: { - input: { - normal: 1.25, - cached: 0.125, - }, - output: { - normal: 10, - }, - }, reasoning: EFFORT_NONE_LOW_TO_HIGH, } as const satisfies ModelMeta< OpenAIBaseOptions & @@ -322,15 +278,6 @@ const GPT5_1_CODEX = { 'apply_patch', ], }, - pricing: { - input: { - normal: 1.25, - cached: 0.125, - }, - output: { - normal: 10, - }, - }, reasoning: EFFORT_LOW_TO_HIGH, } as const satisfies ModelMeta< OpenAIBaseOptions & @@ -369,15 +316,6 @@ const GPT5 = { 'apply_patch', ], }, - pricing: { - input: { - normal: 1.25, - cached: 0.125, - }, - output: { - normal: 10, - }, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const satisfies ModelMeta< OpenAIBaseOptions & @@ -411,15 +349,6 @@ const GPT5_MINI = { 'apply_patch', ], }, - pricing: { - input: { - normal: 0.25, - cached: 0.025, - }, - output: { - normal: 2, - }, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const satisfies ModelMeta< OpenAIBaseOptions & @@ -434,15 +363,6 @@ const GPT5_NANO = { context_window: 400_000, max_output_tokens: 128_000, knowledge_cutoff: '2024-05-31', - pricing: { - input: { - normal: 0.05, - cached: 0.005, - }, - output: { - normal: 0.4, - }, - }, supports: { input: ['text', 'image', 'document'], output: ['text'], @@ -476,14 +396,6 @@ const GPT5_PRO = { context_window: 400_000, max_output_tokens: 272_000, knowledge_cutoff: '2024-09-30', - pricing: { - input: { - normal: 15, - }, - output: { - normal: 120, - }, - }, supports: { input: ['text', 'image', 'document'], output: ['text'], @@ -517,15 +429,6 @@ const GPT5_CODEX = { context_window: 400_000, max_output_tokens: 128_000, knowledge_cutoff: '2024-09-30', - pricing: { - input: { - normal: 1.25, - cached: 0.125, - }, - output: { - normal: 10, - }, - }, supports: { input: ['text', 'image', 'document'], output: ['text', 'image'], @@ -555,15 +458,6 @@ const GPT5_CODEX = { */ const SORA2 = { name: 'sora-2', - pricing: { - input: { - normal: 0, - }, - output: { - // per second of video - normal: 0.1, - }, - }, supports: { input: ['text', 'image'], output: ['video', 'audio'], @@ -580,15 +474,6 @@ const SORA2 = { */ const SORA2_PRO = { name: 'sora-2-pro', - pricing: { - input: { - normal: 0, - }, - output: { - // per second of video - normal: 0.5, - }, - }, supports: { input: ['text', 'image'], output: ['video', 'audio'], @@ -602,15 +487,6 @@ const SORA2_PRO = { const GPT_IMAGE_1 = { name: 'gpt-image-1', // todo fix for images - pricing: { - input: { - normal: 5, - cached: 1.25, - }, - output: { - normal: 0.1, - }, - }, supports: { input: ['text', 'image'], output: ['image'], @@ -625,15 +501,6 @@ const GPT_IMAGE_1 = { const GPT_IMAGE_1_MINI = { name: 'gpt-image-1-mini', // todo fix for images - pricing: { - input: { - normal: 2, - cached: 0.2, - }, - output: { - normal: 0.03, - }, - }, supports: { input: ['text', 'image'], output: ['image'], @@ -647,15 +514,6 @@ const GPT_IMAGE_1_MINI = { const GPT_IMAGE_2_5_FLARE = { name: 'gpt-image-2.5-flare', - pricing: { - input: { - normal: 5, - cached: 1.25, - }, - output: { - normal: 30, - }, - }, supports: { input: ['text', 'image'], output: ['image'], @@ -668,15 +526,6 @@ const GPT_IMAGE_2_5_FLARE = { const GPT_IMAGE_2_5_SUNBURST = { name: 'gpt-image-2.5-sunburst', - pricing: { - input: { - normal: 5, - cached: 1.25, - }, - output: { - normal: 30, - }, - }, supports: { input: ['text', 'image'], output: ['image'], @@ -690,15 +539,6 @@ const GPT_IMAGE_2_5_SUNBURST = { const GPT_IMAGE_2 = { name: 'gpt-image-2', knowledge_cutoff: '2026-04-21', - pricing: { - input: { - normal: 5, - cached: 1.25, - }, - output: { - normal: 30, - }, - }, supports: { input: ['text', 'image'], output: ['image'], @@ -714,15 +554,6 @@ const O3_DEEP_RESEARCH = { context_window: 200_000, max_output_tokens: 100_000, knowledge_cutoff: '2024-01-01', - pricing: { - input: { - normal: 10, - cached: 2.5, - }, - output: { - normal: 40, - }, - }, supports: { input: ['text', 'image'], output: ['text'], @@ -751,15 +582,6 @@ const O4_MINI_DEEP_RESEARCH = { context_window: 200_000, max_output_tokens: 100_000, knowledge_cutoff: '2024-01-01', - pricing: { - input: { - normal: 2, - cached: 0.5, - }, - output: { - normal: 8, - }, - }, supports: { input: ['text', 'image'], output: ['text'], @@ -788,14 +610,6 @@ const O3_PRO = { context_window: 200_000, max_output_tokens: 100_000, knowledge_cutoff: '2024-01-01', - pricing: { - input: { - normal: 20, - }, - output: { - normal: 80, - }, - }, supports: { input: ['text', 'image', 'document'], output: ['text'], @@ -829,15 +643,6 @@ const GPT_AUDIO = { context_window: 128_000, max_output_tokens: 16_384, knowledge_cutoff: '2023-10-01', - pricing: { - // todo add audio tokens to input output - input: { - normal: 2.5, - }, - output: { - normal: 10, - }, - }, supports: { input: ['text', 'audio'], output: ['text', 'audio'], @@ -857,16 +662,6 @@ const GPT_AUDIO = { context_window: 32_000, max_output_tokens: 4_096, knowledge_cutoff: '2023-10-01', - pricing: { - // todo add audio tokens to input output - input: { - normal: 4, - cached: 0.5, - }, - output: { - normal: 16, - }, - }, supports: { input: ['text', 'audio', 'image'], output: ['text', 'audio'], @@ -885,16 +680,6 @@ const GPT_REALTIME_MINI = { context_window: 32_000, max_output_tokens: 4_096, knowledge_cutoff: '2023-10-01', - pricing: { - // todo add audio and image tokens to input output - input: { - normal: 0.6, - cached: 0.06, - }, - output: { - normal: 2.4, - }, - }, supports: { input: ['text', 'audio', 'image'], output: ['text', 'audio'], @@ -913,15 +698,6 @@ const GPT_AUDIO_MINI = { context_window: 128_000, max_output_tokens: 16_384, knowledge_cutoff: '2023-10-01', - pricing: { - // todo add audio tokens to input output - input: { - normal: 0.6, - }, - output: { - normal: 2.4, - }, - }, supports: { input: ['text', 'audio'], output: ['text', 'audio'], @@ -941,15 +717,6 @@ const O3 = { context_window: 200_000, max_output_tokens: 100_000, knowledge_cutoff: '2024-01-01', - pricing: { - input: { - normal: 2, - cached: 0.5, - }, - output: { - normal: 8, - }, - }, supports: { input: ['text', 'image', 'document'], output: ['text'], @@ -983,15 +750,6 @@ const O4_MINI = { context_window: 200_000, max_output_tokens: 100_000, knowledge_cutoff: '2024-01-01', - pricing: { - input: { - normal: 1.1, - cached: 0.275, - }, - output: { - normal: 4.4, - }, - }, supports: { input: ['text', 'image', 'document'], output: ['text'], @@ -1030,15 +788,6 @@ const GPT4_1 = { context_window: 1_047_576, max_output_tokens: 32_768, knowledge_cutoff: '2024-01-01', - pricing: { - input: { - normal: 2, - cached: 0.5, - }, - output: { - normal: 8, - }, - }, supports: { input: ['text', 'image', 'document'], output: ['text'], @@ -1083,15 +832,6 @@ const GPT4_1_MINI = { context_window: 1_047_576, max_output_tokens: 32_768, knowledge_cutoff: '2024-01-01', - pricing: { - input: { - normal: 0.4, - cached: 0.1, - }, - output: { - normal: 1.6, - }, - }, supports: { input: ['text', 'image', 'document'], output: ['text'], @@ -1135,15 +875,6 @@ const GPT4_1_NANO = { context_window: 1_047_576, max_output_tokens: 32_768, knowledge_cutoff: '2024-01-01', - pricing: { - input: { - normal: 0.1, - cached: 0.025, - }, - output: { - normal: 0.4, - }, - }, supports: { input: ['text', 'image', 'document'], output: ['text'], @@ -1188,14 +919,6 @@ const O1_PRO = { context_window: 200_000, max_output_tokens: 100_000, knowledge_cutoff: '2023-10-01', - pricing: { - input: { - normal: 150, - }, - output: { - normal: 600, - }, - }, supports: { input: ['text', 'image', 'document'], output: ['text'], @@ -1217,14 +940,6 @@ const GPT_4O_MINI_SEARCH_PREVIEW = { context_window: 128_000, max_output_tokens: 16_384, knowledge_cutoff: '2023-10-01', - pricing: { - input: { - normal: 0.15, - }, - output: { - normal: 0.6, - }, - }, supports: { input: ['text'], output: ['text'], @@ -1241,14 +956,6 @@ const GPT_4O_SEARCH_PREVIEW = { context_window: 128_000, max_output_tokens: 16_384, knowledge_cutoff: '2023-10-01', - pricing: { - input: { - normal: 2.5, - }, - output: { - normal: 10, - }, - }, supports: { input: ['text'], output: ['text'], @@ -1265,15 +972,6 @@ const O3_MINI = { context_window: 200_000, max_output_tokens: 100_000, knowledge_cutoff: '2023-10-01', - pricing: { - input: { - normal: 1.1, - cached: 0.55, - }, - output: { - normal: 4.4, - }, - }, supports: { input: ['text'], output: ['text'], @@ -1306,16 +1004,6 @@ const O3_MINI = { context_window: 16_000, max_output_tokens: 4_096, knowledge_cutoff: '2023-10-01', - pricing: { - // todo add audio tokens - input: { - normal: 0.6, - cached: 0.3, - }, - output: { - normal: 2.4, - }, - }, supports: { input: ['text', 'audio'], output: ['text', 'audio'], @@ -1334,15 +1022,6 @@ const O1 = { context_window: 200_000, max_output_tokens: 100_000, knowledge_cutoff: '2023-10-01', - pricing: { - input: { - normal: 15, - cached: 7.5, - }, - output: { - normal: 60, - }, - }, supports: { input: ['text', 'image', 'document'], output: ['text'], @@ -1361,14 +1040,6 @@ const O1 = { /* const OMNI_MODERATION = { name: 'omni-moderation', - pricing: { - input: { - normal: 0, - }, - output: { - normal: 0, - }, - }, supports: { input: ['text', 'image'], output: ['text'], @@ -1384,15 +1055,6 @@ const GPT_4O = { context_window: 128_000, max_output_tokens: 16_384, knowledge_cutoff: '2023-10-01', - pricing: { - input: { - normal: 2.5, - cached: 1.25, - }, - output: { - normal: 10, - }, - }, supports: { input: ['text', 'image', 'document'], output: ['text'], @@ -1432,15 +1094,6 @@ const GPT_4O_MINI = { context_window: 128_000, max_output_tokens: 16_384, knowledge_cutoff: '2023-10-01', - pricing: { - input: { - normal: 0.15, - cached: 0.075, - }, - output: { - normal: 0.6, - }, - }, supports: { input: ['text', 'image', 'document'], output: ['text'], @@ -1479,16 +1132,6 @@ const GPT_4O_MINI = { context_window: 32_000, max_output_tokens: 4_096, knowledge_cutoff: '2023-10-01', - pricing: { - // todo add audio tokens to input output - input: { - normal: 5, - cached: 2.5, - }, - output: { - normal: 20, - }, - }, supports: { input: ['text', 'audio'], output: ['text', 'audio'], @@ -1507,14 +1150,6 @@ const GPT_4_TURBO = { context_window: 128_000, max_output_tokens: 4_096, knowledge_cutoff: '2023-12-01', - pricing: { - input: { - normal: 10, - }, - output: { - normal: 30, - }, - }, supports: { input: ['text', 'image'], output: ['text'], @@ -1534,15 +1169,6 @@ const GPT_5_1_CODEX_MINI = { context_window: 400_000, max_output_tokens: 128_000, knowledge_cutoff: '2024-09-30', - pricing: { - input: { - normal: 0.25, - cached: 0.025, - }, - output: { - normal: 2, - }, - }, supports: { input: ['text', 'image'], output: ['text', 'image'], @@ -1571,14 +1197,6 @@ const GPT_3_5_TURBO = { context_window: 16_385, max_output_tokens: 4_096, knowledge_cutoff: '2021-09-01', - pricing: { - input: { - normal: 0.5, - }, - output: { - normal: 1.5, - }, - }, supports: { input: ['text'], output: ['text'], @@ -1595,14 +1213,6 @@ const GPT_4 = { context_window: 8_192, max_output_tokens: 8_192, knowledge_cutoff: '2023-12-01', - pricing: { - input: { - normal: 30, - }, - output: { - normal: 60, - }, - }, supports: { input: ['text'], output: ['text'], @@ -1625,15 +1235,6 @@ const GPT_4O_MINI_TRANSCRIBE = { context_window: 16_000, max_output_tokens: 2_000, knowledge_cutoff: '2024-01-01', - pricing: { - // todo audio tokens - input: { - normal: 1.25, - }, - output: { - normal: 5, - }, - }, supports: { input: ['audio', 'text'], output: ['text'], @@ -1646,15 +1247,6 @@ const GPT_4O_MINI_TRANSCRIBE = { const GPT_4O_MINI_TTS = { name: 'gpt-4o-mini-tts', - pricing: { - // todo audio tokens - input: { - normal: 0.6, - }, - output: { - normal: 12, - }, - }, supports: { input: ['text'], output: ['audio'], @@ -1670,15 +1262,6 @@ const GPT_4O_TRANSCRIBE = { context_window: 16_000, max_output_tokens: 2_000, knowledge_cutoff: '2024-06-01', - pricing: { - // todo audio tokens - input: { - normal: 2.5, - }, - output: { - normal: 10, - }, - }, supports: { input: ['audio', 'text'], output: ['text'], @@ -1694,15 +1277,6 @@ const GPT_4O_TRANSCRIBE_DIARIZE = { context_window: 16_000, max_output_tokens: 2_000, knowledge_cutoff: '2024-06-01', - pricing: { - // todo audio tokens - input: { - normal: 2.5, - }, - output: { - normal: 10, - }, - }, supports: { input: ['audio', 'text'], output: ['text'], @@ -1718,15 +1292,6 @@ const GPT_5_1_CHAT = { context_window: 128_000, max_output_tokens: 16_384, knowledge_cutoff: '2024-09-30', - pricing: { - input: { - normal: 1.25, - cached: 0.125, - }, - output: { - normal: 10, - }, - }, supports: { input: ['text', 'image'], output: ['text'], @@ -1754,15 +1319,6 @@ const GPT_5_CHAT = { context_window: 128_000, max_output_tokens: 16_384, knowledge_cutoff: '2024-09-30', - pricing: { - input: { - normal: 1.25, - cached: 0.125, - }, - output: { - normal: 10, - }, - }, supports: { input: ['text', 'image'], output: ['text'], @@ -1787,15 +1343,6 @@ const GPT_5_CHAT = { /* const TTS_1 = { name: 'tts-1', - pricing: { - // todo figure out pricing - input: { - normal: 15, - }, - output: { - normal: 15, - }, - }, supports: { input: ['text'], output: ['audio'], @@ -1808,15 +1355,6 @@ const GPT_5_CHAT = { const TTS_1_HD = { name: 'tts-1-hd', - pricing: { - // todo figure out pricing - input: { - normal: 30, - }, - output: { - normal: 30, - }, - }, supports: { input: ['text'], output: ['audio'], @@ -1857,15 +1395,6 @@ const GPT_5_4_MINI = { 'apply_patch', ], }, - pricing: { - input: { - normal: 0.75, - cached: 0.075, - }, - output: { - normal: 4.5, - }, - }, reasoning: EFFORT_NONE_LOW_TO_XHIGH, } as const satisfies ModelMeta< OpenAIBaseOptions & @@ -1903,15 +1432,6 @@ const GPT_5_4_NANO = { 'apply_patch', ], }, - pricing: { - input: { - normal: 0.2, - cached: 0.02, - }, - output: { - normal: 1.25, - }, - }, reasoning: EFFORT_NONE_LOW_TO_XHIGH, } as const satisfies ModelMeta< OpenAIBaseOptions & @@ -1949,15 +1469,6 @@ const GPT_5_4_IMAGE_2 = { 'apply_patch', ], }, - pricing: { - input: { - normal: 8, - cached: 2, - }, - output: { - normal: 15, - }, - }, reasoning: EFFORT_NONE_LOW_TO_XHIGH, } as const satisfies ModelMeta< OpenAIBaseOptions & @@ -1997,15 +1508,6 @@ const GPT_5_6_SOL = { 'apply_patch', ], }, - pricing: { - input: { - normal: 5, - cached: 0.5, - }, - output: { - normal: 30, - }, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const satisfies ModelMeta< OpenAIBaseOptions & @@ -2045,15 +1547,6 @@ const GPT_5_6_TERRA = { 'apply_patch', ], }, - pricing: { - input: { - normal: 2, - cached: 0.2, - }, - output: { - normal: 12, - }, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const satisfies ModelMeta< OpenAIBaseOptions & @@ -2093,15 +1586,6 @@ const GPT_5_6_LUNA = { 'apply_patch', ], }, - pricing: { - input: { - normal: 0.2, - cached: 0.02, - }, - output: { - normal: 1.2, - }, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const satisfies ModelMeta< OpenAIBaseOptions & @@ -2140,15 +1624,6 @@ const GPT_5_5 = { 'apply_patch', ], }, - pricing: { - input: { - normal: 5, - cached: 0.5, - }, - output: { - normal: 30, - }, - }, reasoning: EFFORT_NONE_LOW_TO_XHIGH, } as const satisfies ModelMeta< OpenAIBaseOptions & @@ -2186,14 +1661,6 @@ const GPT_5_5_PRO = { 'apply_patch', ], }, - pricing: { - input: { - normal: 30, - }, - output: { - normal: 180, - }, - }, reasoning: EFFORT_MEDIUM_TO_XHIGH, } as const satisfies ModelMeta< OpenAIBaseOptions & @@ -2231,15 +1698,6 @@ const GPT_CHAT_LATEST = { 'apply_patch', ], }, - pricing: { - input: { - normal: 5, - cached: 0.5, - }, - output: { - normal: 30, - }, - }, reasoning: EFFORT_LOW_TO_HIGH, } as const satisfies ModelMeta< OpenAIBaseOptions & @@ -2260,15 +1718,6 @@ const GPT_5_6_LUNA_PRO = { features: ['streaming', 'function_calling', 'structured_outputs'], tools: [], }, - pricing: { - input: { - normal: 0.2, - cached: 0.02, - }, - output: { - normal: 1.2, - }, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const satisfies ModelMeta< OpenAIBaseOptions & @@ -2289,15 +1738,6 @@ const GPT_5_6_SOL_PRO = { features: ['streaming', 'function_calling', 'structured_outputs'], tools: [], }, - pricing: { - input: { - normal: 2.5, - cached: 0.25, - }, - output: { - normal: 15, - }, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const satisfies ModelMeta< OpenAIBaseOptions & @@ -2318,15 +1758,6 @@ const GPT_5_6_TERRA_PRO = { features: ['streaming', 'function_calling', 'structured_outputs'], tools: [], }, - pricing: { - input: { - normal: 2, - cached: 0.2, - }, - output: { - normal: 12, - }, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const satisfies ModelMeta< OpenAIBaseOptions & @@ -2358,15 +1789,6 @@ const GPT_6_ASTRA = { 'apply_patch', ], }, - pricing: { - input: { - normal: 10, - cached: 1, - }, - output: { - normal: 50, - }, - }, reasoning: EFFORT_LOW_TO_MAX, } as const satisfies ModelMeta< OpenAIBaseOptions & @@ -2387,15 +1809,6 @@ const GPT_6_ASTRA_PRO = { features: ['streaming', 'function_calling', 'structured_outputs'], tools: [], }, - pricing: { - input: { - normal: 10, - cached: 1, - }, - output: { - normal: 50, - }, - }, reasoning: EFFORT_LOW_TO_MAX, } as const satisfies ModelMeta< OpenAIBaseOptions & @@ -2427,15 +1840,6 @@ const GPT_6_LUNA = { 'apply_patch', ], }, - pricing: { - input: { - normal: 0.1, - cached: 0.01, - }, - output: { - normal: 0.5, - }, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const satisfies ModelMeta< OpenAIBaseOptions & @@ -2456,15 +1860,6 @@ const GPT_6_LUNA_PRO = { features: ['streaming', 'function_calling', 'structured_outputs'], tools: [], }, - pricing: { - input: { - normal: 0.1, - cached: 0.01, - }, - output: { - normal: 0.5, - }, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const satisfies ModelMeta< OpenAIBaseOptions & @@ -2496,15 +1891,6 @@ const GPT_6_SOL = { 'apply_patch', ], }, - pricing: { - input: { - normal: 2, - cached: 0.2, - }, - output: { - normal: 10, - }, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const satisfies ModelMeta< OpenAIBaseOptions & @@ -2525,15 +1911,6 @@ const GPT_6_SOL_PRO = { features: ['streaming', 'function_calling', 'structured_outputs'], tools: [], }, - pricing: { - input: { - normal: 2, - cached: 0.2, - }, - output: { - normal: 10, - }, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const satisfies ModelMeta< OpenAIBaseOptions & @@ -2566,15 +1943,6 @@ const GPT_6_1_SOL = { 'apply_patch', ], }, - pricing: { - input: { - normal: 2, - cached: 0.1, - }, - output: { - normal: 10, - }, - }, reasoning: EFFORT_LOW_TO_MAX, } as const satisfies ModelMeta< OpenAIBaseOptions & @@ -2607,15 +1975,6 @@ const GPT_6_1_SOL_PRO = { 'apply_patch', ], }, - pricing: { - input: { - normal: 2, - cached: 0.1, - }, - output: { - normal: 10, - }, - }, reasoning: EFFORT_LOW_TO_MAX, } as const satisfies ModelMeta< OpenAIBaseOptions & diff --git a/packages/ai-openrouter/src/model-meta.ts b/packages/ai-openrouter/src/model-meta.ts index 74d79bedf7..bc00f61311 100644 --- a/packages/ai-openrouter/src/model-meta.ts +++ b/packages/ai-openrouter/src/model-meta.ts @@ -231,18 +231,6 @@ const _ANTHROPIC_CLAUDE_FABLE_LATEST = { }, context_window: 1000000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 10, - cached: 12.75, - }, - output: { - normal: 50, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_MAX, } as const const _ANTHROPIC_CLAUDE_HAIKU_LATEST = { @@ -262,18 +250,6 @@ const _ANTHROPIC_CLAUDE_HAIKU_LATEST = { }, context_window: 1000000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 0.1, - cached: 0.135, - }, - output: { - normal: 0.5, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const _ANTHROPIC_CLAUDE_OPUS_LATEST = { @@ -293,18 +269,6 @@ const _ANTHROPIC_CLAUDE_OPUS_LATEST = { }, context_window: 1000000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 4, - cached: 5.2, - }, - output: { - normal: 20, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_MAX, } as const const _ANTHROPIC_CLAUDE_SONNET_LATEST = { @@ -324,18 +288,6 @@ const _ANTHROPIC_CLAUDE_SONNET_LATEST = { }, context_window: 1000000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 2, - cached: 2.6, - }, - output: { - normal: 10, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_MAX, } as const const _DEEPSEEK_DEEPSEEK_FLASH_LATEST = { @@ -364,18 +316,6 @@ const _DEEPSEEK_DEEPSEEK_FLASH_LATEST = { }, context_window: 1048576, max_output_tokens: 943718, - pricing: { - text: { - input: { - normal: 0.07, - cached: 0.008, - }, - output: { - normal: 0.5, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_HIGH_MAX, } as const const _DEEPSEEK_DEEPSEEK_PRO_LATEST = { @@ -402,18 +342,6 @@ const _DEEPSEEK_DEEPSEEK_PRO_LATEST = { }, context_window: 1048576, max_output_tokens: 393216, - pricing: { - text: { - input: { - normal: 0.2235, - cached: 0.22, - }, - output: { - normal: 8, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_HIGH_MAX, } as const const _DEEPSEEK_DEEPSEEK_V4_FLASH_LATEST = { @@ -441,18 +369,6 @@ const _DEEPSEEK_DEEPSEEK_V4_FLASH_LATEST = { }, context_window: 1048576, max_output_tokens: 943718, - pricing: { - text: { - input: { - normal: 0.0475, - cached: 0.028, - }, - output: { - normal: 0.1568, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_HIGH_MAX, } as const const _GOOGLE_GEMINI_FLASH_LATEST = { @@ -474,18 +390,6 @@ const _GOOGLE_GEMINI_FLASH_LATEST = { }, context_window: 1048576, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0.75, - cached: 0.1166666667, - }, - output: { - normal: 3.75, - }, - }, - image: 7.5e-7, - }, reasoning: EFFORT_LOW_TO_HIGH, } as const const _GOOGLE_GEMINI_PRO_LATEST = { @@ -507,18 +411,6 @@ const _GOOGLE_GEMINI_PRO_LATEST = { }, context_window: 1048576, max_output_tokens: 943718, - pricing: { - text: { - input: { - normal: 2, - cached: 0.2875, - }, - output: { - normal: 10, - }, - }, - image: 0.000002, - }, reasoning: EFFORT_LOW_TO_HIGH, } as const const _MOONSHOTAI_KIMI_LATEST = { @@ -545,18 +437,6 @@ const _MOONSHOTAI_KIMI_LATEST = { }, context_window: 1048576, max_output_tokens: 943718, - pricing: { - text: { - input: { - normal: 0.238, - cached: 0.228, - }, - output: { - normal: 16, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_HIGH_MAX, } as const const _OPENAI_GPT_ASTRA_LATEST = { @@ -576,18 +456,6 @@ const _OPENAI_GPT_ASTRA_LATEST = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 10, - cached: 13.5, - }, - output: { - normal: 50, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_MAX, } as const const _OPENAI_GPT_LUNA_LATEST = { @@ -607,18 +475,6 @@ const _OPENAI_GPT_LUNA_LATEST = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 0.1, - cached: 0.135, - }, - output: { - normal: 0.5, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const const _OPENAI_GPT_MINI_LATEST = { @@ -638,18 +494,6 @@ const _OPENAI_GPT_MINI_LATEST = { }, context_window: 400000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 0.75, - cached: 0.075, - }, - output: { - normal: 4.5, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_XHIGH, } as const const _OPENAI_GPT_SOL_LATEST = { @@ -669,18 +513,6 @@ const _OPENAI_GPT_SOL_LATEST = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 2, - cached: 2.6, - }, - output: { - normal: 10, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_MAX, } as const const _OPENAI_GPT_TERRA_LATEST = { @@ -700,18 +532,6 @@ const _OPENAI_GPT_TERRA_LATEST = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 2, - cached: 2.7, - }, - output: { - normal: 12, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const const _UNBIASED_PARETO_LATEST = { @@ -724,18 +544,6 @@ const _UNBIASED_PARETO_LATEST = { }, context_window: 1048576, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 0.8, - cached: 0.03, - }, - output: { - normal: 3.2, - }, - }, - image: 0, - }, } as const const _X_AI_GROK_LATEST = { id: '~x-ai/grok-latest', @@ -757,18 +565,6 @@ const _X_AI_GROK_LATEST = { }, context_window: 500000, max_output_tokens: 450000, - pricing: { - text: { - input: { - normal: 2, - cached: 0.5, - }, - output: { - normal: 6, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_XHIGH, } as const const _Z_AI_GLM_FLASH_LATEST = { @@ -796,18 +592,6 @@ const _Z_AI_GLM_FLASH_LATEST = { }, context_window: 1048576, max_output_tokens: 943718, - pricing: { - text: { - input: { - normal: 0.0052, - cached: 0.0052, - }, - output: { - normal: 0.1985, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_HIGH_MAX, } as const const _Z_AI_GLM_LATEST = { @@ -835,18 +619,6 @@ const _Z_AI_GLM_LATEST = { }, context_window: 1048576, max_output_tokens: 943718, - pricing: { - text: { - input: { - normal: 0.079, - cached: 0.078, - }, - output: { - normal: 1.4, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_HIGH_MAX, } as const const AION_LABS_AION_2_0 = { @@ -866,18 +638,6 @@ const AION_LABS_AION_2_0 = { }, context_window: 131072, max_output_tokens: 32768, - pricing: { - text: { - input: { - normal: 0.8, - cached: 0.2, - }, - output: { - normal: 1.6, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const AION_LABS_AION_3_0 = { @@ -897,18 +657,6 @@ const AION_LABS_AION_3_0 = { }, context_window: 131072, max_output_tokens: 32768, - pricing: { - text: { - input: { - normal: 3, - cached: 0.75, - }, - output: { - normal: 6, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const AION_LABS_AION_3_0_MINI = { @@ -928,18 +676,6 @@ const AION_LABS_AION_3_0_MINI = { }, context_window: 131072, max_output_tokens: 32768, - pricing: { - text: { - input: { - normal: 0.7, - cached: 0.18, - }, - output: { - normal: 1.4, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const AION_LABS_AION_3_5 = { @@ -959,18 +695,6 @@ const AION_LABS_AION_3_5 = { }, context_window: 262144, max_output_tokens: 32768, - pricing: { - text: { - input: { - normal: 3, - cached: 0.75, - }, - output: { - normal: 6, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_HIGH_MAX, } as const const AION_LABS_AION_3_5_MINI = { @@ -990,18 +714,6 @@ const AION_LABS_AION_3_5_MINI = { }, context_window: 262144, max_output_tokens: 32768, - pricing: { - text: { - input: { - normal: 0.7, - cached: 0.18, - }, - output: { - normal: 1.4, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_HIGH_MAX, } as const const AION_LABS_AION_RP_LLAMA_3_1_8B = { @@ -1014,18 +726,6 @@ const AION_LABS_AION_RP_LLAMA_3_1_8B = { }, context_window: 32768, max_output_tokens: 29491, - pricing: { - text: { - input: { - normal: 0.8, - cached: 0, - }, - output: { - normal: 1.6, - }, - }, - image: 0, - }, } as const const AMAZON_NOVA_2_LITE_V1 = { id: 'amazon/nova-2-lite-v1', @@ -1044,18 +744,6 @@ const AMAZON_NOVA_2_LITE_V1 = { }, context_window: 1000000, max_output_tokens: 65535, - pricing: { - text: { - input: { - normal: 0.3, - cached: 0, - }, - output: { - normal: 2.5, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const AMAZON_NOVA_LITE_V1 = { @@ -1068,18 +756,6 @@ const AMAZON_NOVA_LITE_V1 = { }, context_window: 300000, max_output_tokens: 5120, - pricing: { - text: { - input: { - normal: 0.06, - cached: 0, - }, - output: { - normal: 0.24, - }, - }, - image: 0, - }, } as const const AMAZON_NOVA_MICRO_V1 = { id: 'amazon/nova-micro-v1', @@ -1091,18 +767,6 @@ const AMAZON_NOVA_MICRO_V1 = { }, context_window: 128000, max_output_tokens: 5120, - pricing: { - text: { - input: { - normal: 0.035, - cached: 0, - }, - output: { - normal: 0.14, - }, - }, - image: 0, - }, } as const const AMAZON_NOVA_PREMIER_V1 = { id: 'amazon/nova-premier-v1', @@ -1114,18 +778,6 @@ const AMAZON_NOVA_PREMIER_V1 = { }, context_window: 1000000, max_output_tokens: 32000, - pricing: { - text: { - input: { - normal: 2.5, - cached: 0.625, - }, - output: { - normal: 12.5, - }, - }, - image: 0, - }, } as const const AMAZON_NOVA_PRO_V1 = { id: 'amazon/nova-pro-v1', @@ -1137,18 +789,6 @@ const AMAZON_NOVA_PRO_V1 = { }, context_window: 300000, max_output_tokens: 5120, - pricing: { - text: { - input: { - normal: 0.8, - cached: 0, - }, - output: { - normal: 3.2, - }, - }, - image: 0, - }, } as const const ANTHRACITE_ORG_MAGNUM_V4_72B = { id: 'anthracite-org/magnum-v4-72b', @@ -1172,18 +812,6 @@ const ANTHRACITE_ORG_MAGNUM_V4_72B = { }, context_window: 32768, max_output_tokens: 4096, - pricing: { - text: { - input: { - normal: 2.5, - cached: 0, - }, - output: { - normal: 5, - }, - }, - image: 0, - }, } as const const ANTHROPIC_CLAUDE_FABLE_5 = { id: 'anthropic/claude-fable-5', @@ -1202,18 +830,6 @@ const ANTHROPIC_CLAUDE_FABLE_5 = { }, context_window: 1000000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 10, - cached: 13.5, - }, - output: { - normal: 50, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_MAX, } as const const ANTHROPIC_CLAUDE_FABLE_5_BATCH = { @@ -1232,18 +848,6 @@ const ANTHROPIC_CLAUDE_FABLE_5_BATCH = { }, context_window: 1000000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 5, - cached: 6.75, - }, - output: { - normal: 25, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_MAX, } as const const ANTHROPIC_CLAUDE_FABLE_5_1 = { @@ -1263,18 +867,6 @@ const ANTHROPIC_CLAUDE_FABLE_5_1 = { }, context_window: 1000000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 10, - cached: 12.75, - }, - output: { - normal: 50, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_MAX, } as const const ANTHROPIC_CLAUDE_FABLE_5_1_BATCH = { @@ -1293,18 +885,6 @@ const ANTHROPIC_CLAUDE_FABLE_5_1_BATCH = { }, context_window: 1000000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 5, - cached: 6.375, - }, - output: { - normal: 25, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_MAX, } as const const ANTHROPIC_CLAUDE_HAIKU_4_5 = { @@ -1326,18 +906,6 @@ const ANTHROPIC_CLAUDE_HAIKU_4_5 = { }, context_window: 200000, max_output_tokens: 64000, - pricing: { - text: { - input: { - normal: 1, - cached: 1.35, - }, - output: { - normal: 5, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const ANTHROPIC_CLAUDE_HAIKU_4_5_BATCH = { @@ -1358,18 +926,6 @@ const ANTHROPIC_CLAUDE_HAIKU_4_5_BATCH = { }, context_window: 200000, max_output_tokens: 64000, - pricing: { - text: { - input: { - normal: 0.5, - cached: 0.675, - }, - output: { - normal: 2.5, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_TO_HIGH, } as const const ANTHROPIC_CLAUDE_HAIKU_5_5 = { @@ -1389,18 +945,6 @@ const ANTHROPIC_CLAUDE_HAIKU_5_5 = { }, context_window: 1000000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 0.1, - cached: 0.135, - }, - output: { - normal: 0.5, - }, - }, - image: 0, - }, } as const const ANTHROPIC_CLAUDE_HAIKU_5_5_BATCH = { id: 'anthropic/claude-haiku-5.5:batch', @@ -1418,18 +962,6 @@ const ANTHROPIC_CLAUDE_HAIKU_5_5_BATCH = { }, context_window: 1000000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 0.05, - cached: 0.0675, - }, - output: { - normal: 0.25, - }, - }, - image: 0, - }, } as const const ANTHROPIC_CLAUDE_OPUS_4_1 = { id: 'anthropic/claude-opus-4.1', @@ -1448,18 +980,6 @@ const ANTHROPIC_CLAUDE_OPUS_4_1 = { }, context_window: 200000, max_output_tokens: 32000, - pricing: { - text: { - input: { - normal: 15, - cached: 20.25, - }, - output: { - normal: 75, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const ANTHROPIC_CLAUDE_OPUS_4_1_BATCH = { @@ -1479,18 +999,6 @@ const ANTHROPIC_CLAUDE_OPUS_4_1_BATCH = { }, context_window: 200000, max_output_tokens: 32000, - pricing: { - text: { - input: { - normal: 7.5, - cached: 10.125, - }, - output: { - normal: 37.5, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_TO_HIGH, } as const const ANTHROPIC_CLAUDE_OPUS_4_5 = { @@ -1511,18 +1019,6 @@ const ANTHROPIC_CLAUDE_OPUS_4_5 = { }, context_window: 200000, max_output_tokens: 64000, - pricing: { - text: { - input: { - normal: 5, - cached: 6.75, - }, - output: { - normal: 25, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const ANTHROPIC_CLAUDE_OPUS_4_5_BATCH = { @@ -1542,18 +1038,6 @@ const ANTHROPIC_CLAUDE_OPUS_4_5_BATCH = { }, context_window: 200000, max_output_tokens: 64000, - pricing: { - text: { - input: { - normal: 2.5, - cached: 3.375, - }, - output: { - normal: 12.5, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_TO_HIGH, } as const const ANTHROPIC_CLAUDE_OPUS_4_6 = { @@ -1575,18 +1059,6 @@ const ANTHROPIC_CLAUDE_OPUS_4_6 = { }, context_window: 1000000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 5, - cached: 6.75, - }, - output: { - normal: 25, - }, - }, - image: 0, - }, reasoning: BUDGET_NONE_LOW_TO_HIGH_MAX, } as const const ANTHROPIC_CLAUDE_OPUS_4_6_BATCH = { @@ -1607,18 +1079,6 @@ const ANTHROPIC_CLAUDE_OPUS_4_6_BATCH = { }, context_window: 1000000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 2.5, - cached: 3.375, - }, - output: { - normal: 12.5, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_HIGH_MAX, } as const const ANTHROPIC_CLAUDE_OPUS_4_7 = { @@ -1638,18 +1098,6 @@ const ANTHROPIC_CLAUDE_OPUS_4_7 = { }, context_window: 1000000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 5, - cached: 6.75, - }, - output: { - normal: 25, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const const ANTHROPIC_CLAUDE_OPUS_4_7_BATCH = { @@ -1668,18 +1116,6 @@ const ANTHROPIC_CLAUDE_OPUS_4_7_BATCH = { }, context_window: 1000000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 2.5, - cached: 3.375, - }, - output: { - normal: 12.5, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_MAX, } as const const ANTHROPIC_CLAUDE_OPUS_4_8 = { @@ -1699,18 +1135,6 @@ const ANTHROPIC_CLAUDE_OPUS_4_8 = { }, context_window: 1000000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 5, - cached: 6.75, - }, - output: { - normal: 25, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const const ANTHROPIC_CLAUDE_OPUS_4_8_BATCH = { @@ -1729,18 +1153,6 @@ const ANTHROPIC_CLAUDE_OPUS_4_8_BATCH = { }, context_window: 1000000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 2.5, - cached: 3.375, - }, - output: { - normal: 12.5, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_MAX, } as const const ANTHROPIC_CLAUDE_OPUS_5 = { @@ -1760,18 +1172,6 @@ const ANTHROPIC_CLAUDE_OPUS_5 = { }, context_window: 1000000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 5, - cached: 6.75, - }, - output: { - normal: 25, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const const ANTHROPIC_CLAUDE_OPUS_5_BATCH = { @@ -1790,18 +1190,6 @@ const ANTHROPIC_CLAUDE_OPUS_5_BATCH = { }, context_window: 1000000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 2.5, - cached: 3.375, - }, - output: { - normal: 12.5, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_MAX, } as const const ANTHROPIC_CLAUDE_OPUS_5_5 = { @@ -1821,18 +1209,6 @@ const ANTHROPIC_CLAUDE_OPUS_5_5 = { }, context_window: 1000000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 4, - cached: 5.2, - }, - output: { - normal: 20, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_MAX, } as const const ANTHROPIC_CLAUDE_OPUS_5_5_BATCH = { @@ -1851,18 +1227,6 @@ const ANTHROPIC_CLAUDE_OPUS_5_5_BATCH = { }, context_window: 1000000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 2, - cached: 2.6, - }, - output: { - normal: 10, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_MAX, } as const const ANTHROPIC_CLAUDE_SONNET_4_5 = { @@ -1884,18 +1248,6 @@ const ANTHROPIC_CLAUDE_SONNET_4_5 = { }, context_window: 1000000, max_output_tokens: 64000, - pricing: { - text: { - input: { - normal: 3, - cached: 4.05, - }, - output: { - normal: 15, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const ANTHROPIC_CLAUDE_SONNET_4_5_BATCH = { @@ -1916,18 +1268,6 @@ const ANTHROPIC_CLAUDE_SONNET_4_5_BATCH = { }, context_window: 1000000, max_output_tokens: 64000, - pricing: { - text: { - input: { - normal: 1.5, - cached: 2.025, - }, - output: { - normal: 7.5, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_TO_HIGH, } as const const ANTHROPIC_CLAUDE_SONNET_4_6 = { @@ -1949,18 +1289,6 @@ const ANTHROPIC_CLAUDE_SONNET_4_6 = { }, context_window: 1000000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 3, - cached: 4.05, - }, - output: { - normal: 15, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_HIGH_MAX, } as const const ANTHROPIC_CLAUDE_SONNET_4_6_BATCH = { @@ -1981,18 +1309,6 @@ const ANTHROPIC_CLAUDE_SONNET_4_6_BATCH = { }, context_window: 1000000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 1.5, - cached: 2.025, - }, - output: { - normal: 7.5, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_HIGH_MAX, } as const const ANTHROPIC_CLAUDE_SONNET_5 = { @@ -2012,18 +1328,6 @@ const ANTHROPIC_CLAUDE_SONNET_5 = { }, context_window: 1000000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 2, - cached: 2.7, - }, - output: { - normal: 10, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const const ANTHROPIC_CLAUDE_SONNET_5_BATCH = { @@ -2042,18 +1346,6 @@ const ANTHROPIC_CLAUDE_SONNET_5_BATCH = { }, context_window: 1000000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 1, - cached: 1.35, - }, - output: { - normal: 5, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_MAX, } as const const ANTHROPIC_CLAUDE_SONNET_5_5 = { @@ -2073,18 +1365,6 @@ const ANTHROPIC_CLAUDE_SONNET_5_5 = { }, context_window: 1000000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 2, - cached: 2.6, - }, - output: { - normal: 10, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_MAX, } as const const ANTHROPIC_CLAUDE_SONNET_5_5_BATCH = { @@ -2103,18 +1383,6 @@ const ANTHROPIC_CLAUDE_SONNET_5_5_BATCH = { }, context_window: 1000000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 1, - cached: 1.3, - }, - output: { - normal: 5, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_MAX, } as const const ARCEE_AI_TRINITY_LARGE_THINKING = { @@ -2133,18 +1401,6 @@ const ARCEE_AI_TRINITY_LARGE_THINKING = { }, context_window: 262144, max_output_tokens: 80000, - pricing: { - text: { - input: { - normal: 0.25, - cached: 0.06, - }, - output: { - normal: 0.8, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const BYTEDANCE_SEED_SEED_1_6 = { @@ -2166,18 +1422,6 @@ const BYTEDANCE_SEED_SEED_1_6 = { }, context_window: 262144, max_output_tokens: 32768, - pricing: { - text: { - input: { - normal: 0.25, - cached: 0, - }, - output: { - normal: 2, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const BYTEDANCE_SEED_SEED_1_6_FLASH = { @@ -2199,18 +1443,6 @@ const BYTEDANCE_SEED_SEED_1_6_FLASH = { }, context_window: 262144, max_output_tokens: 32768, - pricing: { - text: { - input: { - normal: 0.075, - cached: 0, - }, - output: { - normal: 0.3, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const BYTEDANCE_SEED_SEED_2_1_TURBO = { @@ -2232,18 +1464,6 @@ const BYTEDANCE_SEED_SEED_2_1_TURBO = { }, context_window: 262144, max_output_tokens: 235929, - pricing: { - text: { - input: { - normal: 0.5, - cached: 0, - }, - output: { - normal: 2.5, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const BYTEDANCE_SEED_SEED_2_0_CODE = { @@ -2265,18 +1485,6 @@ const BYTEDANCE_SEED_SEED_2_0_CODE = { }, context_window: 262144, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 0.5, - cached: 0, - }, - output: { - normal: 3, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_HIGH, } as const const BYTEDANCE_SEED_SEED_2_0_LITE = { @@ -2298,18 +1506,6 @@ const BYTEDANCE_SEED_SEED_2_0_LITE = { }, context_window: 262144, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 0.25, - cached: 0, - }, - output: { - normal: 2, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_MINIMAL_TO_HIGH, } as const const BYTEDANCE_SEED_SEED_2_0_MINI = { @@ -2331,18 +1527,6 @@ const BYTEDANCE_SEED_SEED_2_0_MINI = { }, context_window: 262144, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 0.1, - cached: 0, - }, - output: { - normal: 0.4, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_MINIMAL_TO_HIGH, } as const const BYTEDANCE_UI_TARS_1_5_7B = { @@ -2366,18 +1550,6 @@ const BYTEDANCE_UI_TARS_1_5_7B = { }, context_window: 128000, max_output_tokens: 2048, - pricing: { - text: { - input: { - normal: 0.1, - cached: 0.1, - }, - output: { - normal: 0.2, - }, - }, - image: 0, - }, } as const const COGNITIVECOMPUTATIONS_DOLPHIN_MISTRAL_24B_VENICE_EDITION = { id: 'cognitivecomputations/dolphin-mistral-24b-venice-edition', @@ -2397,18 +1569,6 @@ const COGNITIVECOMPUTATIONS_DOLPHIN_MISTRAL_24B_VENICE_EDITION = { }, context_window: 128000, max_output_tokens: 8192, - pricing: { - text: { - input: { - normal: 0.2, - cached: 0, - }, - output: { - normal: 0.9, - }, - }, - image: 0, - }, } as const const COHERE_COMMAND_A = { id: 'cohere/command-a', @@ -2429,18 +1589,6 @@ const COHERE_COMMAND_A = { }, context_window: 256000, max_output_tokens: 8192, - pricing: { - text: { - input: { - normal: 2.5, - cached: 0, - }, - output: { - normal: 10, - }, - }, - image: 0, - }, } as const const COHERE_COMMAND_A_PLUS = { id: 'cohere/command-a-plus', @@ -2462,18 +1610,6 @@ const COHERE_COMMAND_A_PLUS = { }, context_window: 192000, max_output_tokens: 64000, - pricing: { - text: { - input: { - normal: 0.3, - cached: 0.15, - }, - output: { - normal: 1.5, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const COHERE_COMMAND_R_08_2024 = { @@ -2496,18 +1632,6 @@ const COHERE_COMMAND_R_08_2024 = { }, context_window: 128000, max_output_tokens: 4000, - pricing: { - text: { - input: { - normal: 0.15, - cached: 0, - }, - output: { - normal: 0.6, - }, - }, - image: 0, - }, } as const const COHERE_COMMAND_R_PLUS_08_2024 = { id: 'cohere/command-r-plus-08-2024', @@ -2529,18 +1653,6 @@ const COHERE_COMMAND_R_PLUS_08_2024 = { }, context_window: 128000, max_output_tokens: 4000, - pricing: { - text: { - input: { - normal: 2.5, - cached: 0, - }, - output: { - normal: 10, - }, - }, - image: 0, - }, } as const const COHERE_COMMAND_R7B_12_2024 = { id: 'cohere/command-r7b-12-2024', @@ -2561,18 +1673,6 @@ const COHERE_COMMAND_R7B_12_2024 = { }, context_window: 128000, max_output_tokens: 4000, - pricing: { - text: { - input: { - normal: 0.0375, - cached: 0, - }, - output: { - normal: 0.15, - }, - }, - image: 0, - }, } as const const COHERE_NORTH_MINI_CODE_FREE = { id: 'cohere/north-mini-code:free', @@ -2594,18 +1694,6 @@ const COHERE_NORTH_MINI_CODE_FREE = { }, context_window: 256000, max_output_tokens: 64000, - pricing: { - text: { - input: { - normal: 0, - cached: 0, - }, - output: { - normal: 0, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const DEEPSEEK_DEEPSEEK_CHAT = { @@ -2629,18 +1717,6 @@ const DEEPSEEK_DEEPSEEK_CHAT = { }, context_window: 163840, max_output_tokens: 16000, - pricing: { - text: { - input: { - normal: 0.2574, - cached: 0, - }, - output: { - normal: 1.0287, - }, - }, - image: 0, - }, } as const const DEEPSEEK_DEEPSEEK_CHAT_V3_0324 = { id: 'deepseek/deepseek-chat-v3-0324', @@ -2662,18 +1738,6 @@ const DEEPSEEK_DEEPSEEK_CHAT_V3_0324 = { }, context_window: 163840, max_output_tokens: 115200, - pricing: { - text: { - input: { - normal: 0.29, - cached: 0.11, - }, - output: { - normal: 1.14, - }, - }, - image: 0, - }, } as const const DEEPSEEK_DEEPSEEK_CHAT_V3_1 = { id: 'deepseek/deepseek-chat-v3.1', @@ -2699,18 +1763,6 @@ const DEEPSEEK_DEEPSEEK_CHAT_V3_1 = { }, context_window: 163840, max_output_tokens: 32768, - pricing: { - text: { - input: { - normal: 0.25, - cached: 0.13, - }, - output: { - normal: 0.95, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const DEEPSEEK_DEEPSEEK_R1_0528 = { @@ -2737,18 +1789,6 @@ const DEEPSEEK_DEEPSEEK_R1_0528 = { }, context_window: 163840, max_output_tokens: 32768, - pricing: { - text: { - input: { - normal: 0.5, - cached: 0.35, - }, - output: { - normal: 2.15, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const DEEPSEEK_DEEPSEEK_V3_1_TERMINUS = { @@ -2770,18 +1810,6 @@ const DEEPSEEK_DEEPSEEK_V3_1_TERMINUS = { }, context_window: 163840, max_output_tokens: 147456, - pricing: { - text: { - input: { - normal: 0.27, - cached: 0, - }, - output: { - normal: 1, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const DEEPSEEK_DEEPSEEK_V3_2 = { @@ -2808,18 +1836,6 @@ const DEEPSEEK_DEEPSEEK_V3_2 = { }, context_window: 163840, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0.28, - cached: 0.028, - }, - output: { - normal: 0.42, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const DEEPSEEK_DEEPSEEK_V3_2_EXP = { @@ -2840,18 +1856,6 @@ const DEEPSEEK_DEEPSEEK_V3_2_EXP = { }, context_window: 163840, max_output_tokens: 147456, - pricing: { - text: { - input: { - normal: 0.27, - cached: 0, - }, - output: { - normal: 0.41, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const DEEPSEEK_DEEPSEEK_V4_FLASH = { @@ -2879,18 +1883,6 @@ const DEEPSEEK_DEEPSEEK_V4_FLASH = { }, context_window: 1048576, max_output_tokens: 943717, - pricing: { - text: { - input: { - normal: 0.091, - cached: 0.0182, - }, - output: { - normal: 0.182, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_HIGH_XHIGH, } as const const DEEPSEEK_DEEPSEEK_V4_FLASH_0731 = { @@ -2918,18 +1910,6 @@ const DEEPSEEK_DEEPSEEK_V4_FLASH_0731 = { }, context_window: 1048576, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 0.44, - cached: 0.014, - }, - output: { - normal: 1.32, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_HIGH_MAX, } as const const DEEPSEEK_DEEPSEEK_V4_FLASH_VISION_EXP = { @@ -2956,18 +1936,6 @@ const DEEPSEEK_DEEPSEEK_V4_FLASH_VISION_EXP = { }, context_window: 1048576, max_output_tokens: 262144, - pricing: { - text: { - input: { - normal: 0.2156, - cached: 0.00686, - }, - output: { - normal: 0.6468, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_HIGH_MAX, } as const const DEEPSEEK_DEEPSEEK_V4_PRO = { @@ -2995,18 +1963,6 @@ const DEEPSEEK_DEEPSEEK_V4_PRO = { }, context_window: 1048576, max_output_tokens: 384000, - pricing: { - text: { - input: { - normal: 0.95526, - cached: 0.079605, - }, - output: { - normal: 1.91052, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_HIGH_XHIGH, } as const const DEEPSEEK_DEEPSEEK_V4_PRO_0813 = { @@ -3033,18 +1989,6 @@ const DEEPSEEK_DEEPSEEK_V4_PRO_0813 = { }, context_window: 1048576, max_output_tokens: 393216, - pricing: { - text: { - input: { - normal: 0.66, - cached: 0.022, - }, - output: { - normal: 1.98, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_HIGH_MAX, } as const const DEEPSEEK_DEEPSEEK_V4_1_FLASH = { @@ -3071,18 +2015,6 @@ const DEEPSEEK_DEEPSEEK_V4_1_FLASH = { }, context_window: 1048576, max_output_tokens: 943718, - pricing: { - text: { - input: { - normal: 0.3, - cached: 0.006, - }, - output: { - normal: 1.2, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_HIGH_MAX, } as const const DEEPSEEK_DEEPSEEK_V4_1_FLASH_1017 = { @@ -3111,18 +2043,6 @@ const DEEPSEEK_DEEPSEEK_V4_1_FLASH_1017 = { }, context_window: 1048576, max_output_tokens: 393216, - pricing: { - text: { - input: { - normal: 0.15, - cached: 0.003, - }, - output: { - normal: 0.6, - }, - }, - image: 0, - }, } as const const DEEPSEEK_DEEPSEEK_V4_1_FLASH_BATCH = { id: 'deepseek/deepseek-v4.1-flash:batch', @@ -3148,18 +2068,6 @@ const DEEPSEEK_DEEPSEEK_V4_1_FLASH_BATCH = { }, context_window: 1048576, max_output_tokens: 384000, - pricing: { - text: { - input: { - normal: 0.05, - cached: 0.004, - }, - output: { - normal: 0.15, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_HIGH_MAX, } as const const DOTS_STUDIO_DOTS_3_NOTE_PREVIEW_FREE = { @@ -3179,18 +2087,6 @@ const DOTS_STUDIO_DOTS_3_NOTE_PREVIEW_FREE = { }, context_window: 512000, max_output_tokens: 460800, - pricing: { - text: { - input: { - normal: 0, - cached: 0, - }, - output: { - normal: 0, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const ELORIAN_GLIMPSE = { @@ -3216,18 +2112,6 @@ const ELORIAN_GLIMPSE = { }, context_window: 262144, max_output_tokens: 256000, - pricing: { - text: { - input: { - normal: 0.6, - cached: 0.06, - }, - output: { - normal: 3, - }, - }, - image: 0, - }, } as const const FIREWORKS_EMBER_1 = { id: 'fireworks/ember-1', @@ -3252,18 +2136,6 @@ const FIREWORKS_EMBER_1 = { }, context_window: 1048576, max_output_tokens: 943718, - pricing: { - text: { - input: { - normal: 3, - cached: 0.3, - }, - output: { - normal: 15, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_HIGH_MAX, } as const const GOOGLE_GEMINI_2_5_FLASH = { @@ -3285,18 +2157,6 @@ const GOOGLE_GEMINI_2_5_FLASH = { }, context_window: 1048576, max_output_tokens: 65535, - pricing: { - text: { - input: { - normal: 0.3, - cached: 0.1133333333, - }, - output: { - normal: 2.5, - }, - }, - image: 3e-7, - }, reasoning: EFFORT_OFF_HIGH, } as const const GOOGLE_GEMINI_2_5_FLASH_IMAGE = { @@ -3316,18 +2176,6 @@ const GOOGLE_GEMINI_2_5_FLASH_IMAGE = { }, context_window: 32768, max_output_tokens: 8192, - pricing: { - text: { - input: { - normal: 0.3, - cached: 0.1133333333, - }, - output: { - normal: 2.5, - }, - }, - image: 3e-7, - }, } as const const GOOGLE_GEMINI_2_5_FLASH_LITE = { id: 'google/gemini-2.5-flash-lite', @@ -3348,18 +2196,6 @@ const GOOGLE_GEMINI_2_5_FLASH_LITE = { }, context_window: 1048576, max_output_tokens: 65535, - pricing: { - text: { - input: { - normal: 0.1, - cached: 0.0933333333, - }, - output: { - normal: 0.4, - }, - }, - image: 1e-7, - }, reasoning: EFFORT_OFF_HIGH, } as const const GOOGLE_GEMINI_2_5_PRO = { @@ -3380,18 +2216,6 @@ const GOOGLE_GEMINI_2_5_PRO = { }, context_window: 1048576, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 1.25, - cached: 0.5, - }, - output: { - normal: 10, - }, - }, - image: 0.00000125, - }, reasoning: BUDGET_MINIMAL_TO_HIGH, } as const const GOOGLE_GEMINI_2_5_PRO_PREVIEW = { @@ -3413,18 +2237,6 @@ const GOOGLE_GEMINI_2_5_PRO_PREVIEW = { }, context_window: 1048576, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 1.25, - cached: 0.5, - }, - output: { - normal: 10, - }, - }, - image: 0.00000125, - }, reasoning: BUDGET_MINIMAL_TO_HIGH, } as const const GOOGLE_GEMINI_3_FLASH_PREVIEW = { @@ -3446,18 +2258,6 @@ const GOOGLE_GEMINI_3_FLASH_PREVIEW = { }, context_window: 1048576, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0.5, - cached: 0.13333333330000002, - }, - output: { - normal: 3, - }, - }, - image: 5e-7, - }, reasoning: EFFORT_NONE_MINIMAL_TO_HIGH, } as const const GOOGLE_GEMINI_3_FLASH_PREVIEW_BATCH = { @@ -3479,18 +2279,6 @@ const GOOGLE_GEMINI_3_FLASH_PREVIEW_BATCH = { }, context_window: 1048576, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0.25, - cached: 0, - }, - output: { - normal: 1.5, - }, - }, - image: 2.5e-7, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const GOOGLE_GEMINI_3_PRO_IMAGE = { @@ -3512,18 +2300,6 @@ const GOOGLE_GEMINI_3_PRO_IMAGE = { }, context_window: 131072, max_output_tokens: 32768, - pricing: { - text: { - input: { - normal: 2, - cached: 0.575, - }, - output: { - normal: 12, - }, - }, - image: 0.000002, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const GOOGLE_GEMINI_3_PRO_IMAGE_PREVIEW = { @@ -3544,18 +2320,6 @@ const GOOGLE_GEMINI_3_PRO_IMAGE_PREVIEW = { }, context_window: 65536, max_output_tokens: 32768, - pricing: { - text: { - input: { - normal: 2, - cached: 0.575, - }, - output: { - normal: 12, - }, - }, - image: 0.000002, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const GOOGLE_GEMINI_3_1_FLASH_IMAGE = { @@ -3575,18 +2339,6 @@ const GOOGLE_GEMINI_3_1_FLASH_IMAGE = { }, context_window: 131072, max_output_tokens: 32768, - pricing: { - text: { - input: { - normal: 0.5, - cached: 0, - }, - output: { - normal: 3, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_MINIMAL_HIGH, } as const const GOOGLE_GEMINI_3_1_FLASH_IMAGE_PREVIEW = { @@ -3606,18 +2358,6 @@ const GOOGLE_GEMINI_3_1_FLASH_IMAGE_PREVIEW = { }, context_window: 65536, max_output_tokens: 58982, - pricing: { - text: { - input: { - normal: 0.5, - cached: 0, - }, - output: { - normal: 3, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_MINIMAL_HIGH, } as const const GOOGLE_GEMINI_3_1_FLASH_LITE = { @@ -3639,18 +2379,6 @@ const GOOGLE_GEMINI_3_1_FLASH_LITE = { }, context_window: 1048576, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0.25, - cached: 0.1083333333, - }, - output: { - normal: 1.5, - }, - }, - image: 2.5e-7, - }, reasoning: EFFORT_NONE_MINIMAL_TO_HIGH, } as const const GOOGLE_GEMINI_3_1_FLASH_LITE_IMAGE = { @@ -3670,18 +2398,6 @@ const GOOGLE_GEMINI_3_1_FLASH_LITE_IMAGE = { }, context_window: 65536, max_output_tokens: 58982, - pricing: { - text: { - input: { - normal: 0.25, - cached: 0, - }, - output: { - normal: 1.5, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_MINIMAL_HIGH, } as const const GOOGLE_GEMINI_3_1_FLASH_LITE_PREVIEW = { @@ -3702,18 +2418,6 @@ const GOOGLE_GEMINI_3_1_FLASH_LITE_PREVIEW = { }, context_window: 1048576, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0.25, - cached: 0.1083333333, - }, - output: { - normal: 1.5, - }, - }, - image: 2.5e-7, - }, reasoning: EFFORT_NONE_MINIMAL_TO_HIGH, } as const const GOOGLE_GEMINI_3_1_FLASH_LITE_BATCH = { @@ -3735,18 +2439,6 @@ const GOOGLE_GEMINI_3_1_FLASH_LITE_BATCH = { }, context_window: 1048576, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0.125, - cached: 0.0125, - }, - output: { - normal: 0.75, - }, - }, - image: 1.25e-7, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const GOOGLE_GEMINI_3_1_PRO_PREVIEW = { @@ -3768,18 +2460,6 @@ const GOOGLE_GEMINI_3_1_PRO_PREVIEW = { }, context_window: 1048576, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 2, - cached: 0.575, - }, - output: { - normal: 12, - }, - }, - image: 0.000002, - }, reasoning: EFFORT_LOW_TO_HIGH, } as const const GOOGLE_GEMINI_3_1_PRO_PREVIEW_CUSTOMTOOLS = { @@ -3800,18 +2480,6 @@ const GOOGLE_GEMINI_3_1_PRO_PREVIEW_CUSTOMTOOLS = { }, context_window: 1048576, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 2, - cached: 0.575, - }, - output: { - normal: 12, - }, - }, - image: 0.000002, - }, reasoning: EFFORT_LOW_TO_HIGH, } as const const GOOGLE_GEMINI_3_1_PRO_PREVIEW_BATCH = { @@ -3833,18 +2501,6 @@ const GOOGLE_GEMINI_3_1_PRO_PREVIEW_BATCH = { }, context_window: 1048576, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 1, - cached: 0, - }, - output: { - normal: 6, - }, - }, - image: 0.000001, - }, reasoning: EFFORT_LOW_TO_HIGH, } as const const GOOGLE_GEMINI_3_5_FLASH = { @@ -3866,18 +2522,6 @@ const GOOGLE_GEMINI_3_5_FLASH = { }, context_window: 1048576, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 1.5, - cached: 0.2333333333, - }, - output: { - normal: 9, - }, - }, - image: 0.0000015, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const GOOGLE_GEMINI_3_5_FLASH_LITE = { @@ -3899,18 +2543,6 @@ const GOOGLE_GEMINI_3_5_FLASH_LITE = { }, context_window: 1048576, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0.3, - cached: 0.1133333333, - }, - output: { - normal: 2.5, - }, - }, - image: 3e-7, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const GOOGLE_GEMINI_3_5_FLASH_LITE_BATCH = { @@ -3930,18 +2562,6 @@ const GOOGLE_GEMINI_3_5_FLASH_LITE_BATCH = { }, context_window: 1048576, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0.15, - cached: 0.015, - }, - output: { - normal: 1.25, - }, - }, - image: 1.5e-7, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const GOOGLE_GEMINI_3_5_FLASH_BATCH = { @@ -3963,18 +2583,6 @@ const GOOGLE_GEMINI_3_5_FLASH_BATCH = { }, context_window: 1048576, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0.75, - cached: 0.075, - }, - output: { - normal: 4.5, - }, - }, - image: 7.5e-7, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const GOOGLE_GEMINI_3_6_FLASH = { @@ -3996,18 +2604,6 @@ const GOOGLE_GEMINI_3_6_FLASH = { }, context_window: 1048576, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0.75, - cached: 0.1166666667, - }, - output: { - normal: 3.75, - }, - }, - image: 7.5e-7, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const GOOGLE_GEMINI_3_6_FLASH_BATCH = { @@ -4027,18 +2623,6 @@ const GOOGLE_GEMINI_3_6_FLASH_BATCH = { }, context_window: 1048576, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0.375, - cached: 0.0791666667, - }, - output: { - normal: 1.875, - }, - }, - image: 3.75e-7, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const GOOGLE_GEMINI_3_7_FLASH = { @@ -4060,18 +2644,6 @@ const GOOGLE_GEMINI_3_7_FLASH = { }, context_window: 1048576, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0.75, - cached: 0.1166666667, - }, - output: { - normal: 3.75, - }, - }, - image: 7.5e-7, - }, reasoning: EFFORT_LOW_TO_HIGH, } as const const GOOGLE_GEMINI_3_7_FLASH_BATCH = { @@ -4091,18 +2663,6 @@ const GOOGLE_GEMINI_3_7_FLASH_BATCH = { }, context_window: 1048576, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0.375, - cached: 0.0791666667, - }, - output: { - normal: 1.875, - }, - }, - image: 3.75e-7, - }, reasoning: EFFORT_LOW_TO_HIGH, } as const const GOOGLE_GEMINI_3_8_FLASH = { @@ -4124,18 +2684,6 @@ const GOOGLE_GEMINI_3_8_FLASH = { }, context_window: 1048576, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0.825, - cached: 0.12416666670000001, - }, - output: { - normal: 4.125, - }, - }, - image: 8.25e-7, - }, reasoning: EFFORT_LOW_TO_HIGH, } as const const GOOGLE_GEMINI_3_8_FLASH_BATCH = { @@ -4155,18 +2703,6 @@ const GOOGLE_GEMINI_3_8_FLASH_BATCH = { }, context_window: 1048576, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0.375, - cached: 0.0791666667, - }, - output: { - normal: 1.875, - }, - }, - image: 3.75e-7, - }, reasoning: EFFORT_LOW_TO_HIGH, } as const const GOOGLE_GEMINI_4_ARGON = { @@ -4188,18 +2724,6 @@ const GOOGLE_GEMINI_4_ARGON = { }, context_window: 1048576, max_output_tokens: 943718, - pricing: { - text: { - input: { - normal: 2, - cached: 0.2875, - }, - output: { - normal: 10, - }, - }, - image: 0.000002, - }, } as const const GOOGLE_GEMINI_4_ARGON_BATCH = { id: 'google/gemini-4-argon:batch', @@ -4220,18 +2744,6 @@ const GOOGLE_GEMINI_4_ARGON_BATCH = { }, context_window: 1048576, max_output_tokens: 943718, - pricing: { - text: { - input: { - normal: 1, - cached: 0.2375, - }, - output: { - normal: 5, - }, - }, - image: 0.000001, - }, } as const const GOOGLE_GEMINI_NANO_BANANA_2_1 = { id: 'google/gemini-nano-banana-2.1', @@ -4251,18 +2763,6 @@ const GOOGLE_GEMINI_NANO_BANANA_2_1 = { }, context_window: 65536, max_output_tokens: 58982, - pricing: { - text: { - input: { - normal: 1.5, - cached: 0, - }, - output: { - normal: 7.5, - }, - }, - image: 0, - }, } as const const GOOGLE_GEMMA_2_27B_IT = { id: 'google/gemma-2-27b-it', @@ -4283,18 +2783,6 @@ const GOOGLE_GEMMA_2_27B_IT = { }, context_window: 8192, max_output_tokens: 2048, - pricing: { - text: { - input: { - normal: 0.65, - cached: 0, - }, - output: { - normal: 0.65, - }, - }, - image: 0, - }, } as const const GOOGLE_GEMMA_3_12B_IT = { id: 'google/gemma-3-12b-it', @@ -4317,18 +2805,6 @@ const GOOGLE_GEMMA_3_12B_IT = { }, context_window: 131072, max_output_tokens: 16384, - pricing: { - text: { - input: { - normal: 0.05, - cached: 0, - }, - output: { - normal: 0.15, - }, - }, - image: 0, - }, } as const const GOOGLE_GEMMA_3_27B_IT = { id: 'google/gemma-3-27b-it', @@ -4353,18 +2829,6 @@ const GOOGLE_GEMMA_3_27B_IT = { }, context_window: 131072, max_output_tokens: 117964, - pricing: { - text: { - input: { - normal: 0.08, - cached: 0.04, - }, - output: { - normal: 0.35, - }, - }, - image: 0, - }, } as const const GOOGLE_GEMMA_3_4B_IT = { id: 'google/gemma-3-4b-it', @@ -4388,18 +2852,6 @@ const GOOGLE_GEMMA_3_4B_IT = { }, context_window: 131072, max_output_tokens: 117964, - pricing: { - text: { - input: { - normal: 0.04, - cached: 0.02, - }, - output: { - normal: 0.05, - }, - }, - image: 0, - }, } as const const GOOGLE_GEMMA_4_26B_A4B_IT = { id: 'google/gemma-4-26b-a4b-it', @@ -4425,18 +2877,6 @@ const GOOGLE_GEMMA_4_26B_A4B_IT = { }, context_window: 262144, max_output_tokens: 235929, - pricing: { - text: { - input: { - normal: 0.09, - cached: 0.05, - }, - output: { - normal: 0.3, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const GOOGLE_GEMMA_4_26B_A4B_IT_FREE = { @@ -4457,18 +2897,6 @@ const GOOGLE_GEMMA_4_26B_A4B_IT_FREE = { }, context_window: 262144, max_output_tokens: 32768, - pricing: { - text: { - input: { - normal: 0, - cached: 0, - }, - output: { - normal: 0, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const GOOGLE_GEMMA_4_31B_IT = { @@ -4495,18 +2923,6 @@ const GOOGLE_GEMMA_4_31B_IT = { }, context_window: 262144, max_output_tokens: 16384, - pricing: { - text: { - input: { - normal: 0.2, - cached: 0, - }, - output: { - normal: 0.4, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const GOOGLE_GEMMA_4_31B_IT_FREE = { @@ -4527,18 +2943,6 @@ const GOOGLE_GEMMA_4_31B_IT_FREE = { }, context_window: 262144, max_output_tokens: 32768, - pricing: { - text: { - input: { - normal: 0, - cached: 0, - }, - output: { - normal: 0, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const GOOGLE_LYRIA_3_CLIP_PREVIEW = { @@ -4557,18 +2961,6 @@ const GOOGLE_LYRIA_3_CLIP_PREVIEW = { }, context_window: 1048576, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0, - cached: 0, - }, - output: { - normal: 0, - }, - }, - image: 0, - }, } as const const GOOGLE_LYRIA_3_PRO_PREVIEW = { id: 'google/lyria-3-pro-preview', @@ -4586,18 +2978,6 @@ const GOOGLE_LYRIA_3_PRO_PREVIEW = { }, context_window: 1048576, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0, - cached: 0, - }, - output: { - normal: 0, - }, - }, - image: 0, - }, } as const const GRYPHE_MYTHOMAX_L2_13B = { id: 'gryphe/mythomax-l2-13b', @@ -4621,18 +3001,6 @@ const GRYPHE_MYTHOMAX_L2_13B = { }, context_window: 8192, max_output_tokens: 3686, - pricing: { - text: { - input: { - normal: 0.08, - cached: 0, - }, - output: { - normal: 0.11, - }, - }, - image: 0, - }, } as const const IBM_GRANITE_GRANITE_4_0_H_MICRO = { id: 'ibm-granite/granite-4.0-h-micro', @@ -4656,18 +3024,6 @@ const IBM_GRANITE_GRANITE_4_0_H_MICRO = { }, context_window: 131000, max_output_tokens: 117900, - pricing: { - text: { - input: { - normal: 0.017, - cached: 0, - }, - output: { - normal: 0.112, - }, - }, - image: 0, - }, } as const const IBM_GRANITE_GRANITE_4_2_8B = { id: 'ibm-granite/granite-4.2-8b', @@ -4693,18 +3049,6 @@ const IBM_GRANITE_GRANITE_4_2_8B = { }, context_window: 131072, max_output_tokens: 117964, - pricing: { - text: { - input: { - normal: 0.06, - cached: 0.015, - }, - output: { - normal: 0.25, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_HIGH, } as const const INCEPTION_MERCURY_2 = { @@ -4724,18 +3068,6 @@ const INCEPTION_MERCURY_2 = { }, context_window: 128000, max_output_tokens: 50000, - pricing: { - text: { - input: { - normal: 0.25, - cached: 0.025, - }, - output: { - normal: 0.75, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_HIGH, } as const const INCEPTION_MERCURY_2_5 = { @@ -4755,18 +3087,6 @@ const INCEPTION_MERCURY_2_5 = { }, context_window: 260000, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0.04, - cached: 0.004, - }, - output: { - normal: 0.15, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_HIGH, } as const const INCEPTION_MERCURY_3 = { @@ -4786,18 +3106,6 @@ const INCEPTION_MERCURY_3 = { }, context_window: 1000000, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 0.1, - cached: 0.01, - }, - output: { - normal: 0.35, - }, - }, - image: 0, - }, } as const const INCLUSIONAI_LING_3_0_FLASH = { id: 'inclusionai/ling-3.0-flash', @@ -4823,18 +3131,6 @@ const INCLUSIONAI_LING_3_0_FLASH = { }, context_window: 262144, max_output_tokens: 32768, - pricing: { - text: { - input: { - normal: 0.021, - cached: 0.0042, - }, - output: { - normal: 0.063, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const INCLUSIONAI_LING_3_0_FLASH_VL = { @@ -4859,18 +3155,6 @@ const INCLUSIONAI_LING_3_0_FLASH_VL = { }, context_window: 131072, max_output_tokens: 32768, - pricing: { - text: { - input: { - normal: 0.06, - cached: 0.012, - }, - output: { - normal: 0.18, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const INCLUSIONAI_LING_3_1_FLASH = { @@ -4897,18 +3181,6 @@ const INCLUSIONAI_LING_3_1_FLASH = { }, context_window: 262144, max_output_tokens: 235929, - pricing: { - text: { - input: { - normal: 0.075, - cached: 0.015, - }, - output: { - normal: 0.225, - }, - }, - image: 0, - }, } as const const INFERENCE_NET_SCHEMATRON_V2_SMALL = { id: 'inference-net/schematron-v2-small', @@ -4930,18 +3202,6 @@ const INFERENCE_NET_SCHEMATRON_V2_SMALL = { }, context_window: 128000, max_output_tokens: 4096, - pricing: { - text: { - input: { - normal: 0.05, - cached: 0.05, - }, - output: { - normal: 0.23, - }, - }, - image: 0, - }, } as const const INFERENCE_NET_SCHEMATRON_V2_TURBO = { id: 'inference-net/schematron-v2-turbo', @@ -4963,18 +3223,6 @@ const INFERENCE_NET_SCHEMATRON_V2_TURBO = { }, context_window: 128000, max_output_tokens: 8192, - pricing: { - text: { - input: { - normal: 0.03, - cached: 0.03, - }, - output: { - normal: 0.15, - }, - }, - image: 0, - }, } as const const LIQUID_LFM_2_5_2_6B_FREE = { id: 'liquid/lfm-2.5-2.6b:free', @@ -4999,18 +3247,6 @@ const LIQUID_LFM_2_5_2_6B_FREE = { }, context_window: 65536, max_output_tokens: 8192, - pricing: { - text: { - input: { - normal: 0, - cached: 0, - }, - output: { - normal: 0, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const LIQUID_LFM_2_5_24B_A2B = { @@ -5036,18 +3272,6 @@ const LIQUID_LFM_2_5_24B_A2B = { }, context_window: 128000, max_output_tokens: 8192, - pricing: { - text: { - input: { - normal: 0.05, - cached: 0.025, - }, - output: { - normal: 0.7, - }, - }, - image: 0, - }, } as const const MANCER_WEAVER = { id: 'mancer/weaver', @@ -5071,18 +3295,6 @@ const MANCER_WEAVER = { }, context_window: 8000, max_output_tokens: 6000, - pricing: { - text: { - input: { - normal: 0.4, - cached: 0, - }, - output: { - normal: 0.75, - }, - }, - image: 0, - }, } as const const MEITUAN_LONGCAT_2_0 = { id: 'meituan/longcat-2.0', @@ -5105,18 +3317,6 @@ const MEITUAN_LONGCAT_2_0 = { }, context_window: 1048756, max_output_tokens: 262144, - pricing: { - text: { - input: { - normal: 0.3, - cached: 0.006, - }, - output: { - normal: 1.2, - }, - }, - image: 0, - }, reasoning: BUDGET_OFF_HIGH, } as const const META_LLAMA_LLAMA_3_1_70B_INSTRUCT = { @@ -5140,18 +3340,6 @@ const META_LLAMA_LLAMA_3_1_70B_INSTRUCT = { }, context_window: 131072, max_output_tokens: 16384, - pricing: { - text: { - input: { - normal: 0.4, - cached: 0, - }, - output: { - normal: 0.4, - }, - }, - image: 0, - }, } as const const META_LLAMA_LLAMA_3_1_8B_INSTRUCT = { id: 'meta-llama/llama-3.1-8b-instruct', @@ -5176,18 +3364,6 @@ const META_LLAMA_LLAMA_3_1_8B_INSTRUCT = { }, context_window: 131072, max_output_tokens: 117964, - pricing: { - text: { - input: { - normal: 0.05, - cached: 0.025, - }, - output: { - normal: 0.08, - }, - }, - image: 0, - }, } as const const META_LLAMA_LLAMA_3_2_1B_INSTRUCT = { id: 'meta-llama/llama-3.2-1b-instruct', @@ -5208,18 +3384,6 @@ const META_LLAMA_LLAMA_3_2_1B_INSTRUCT = { }, context_window: 60000, max_output_tokens: 54000, - pricing: { - text: { - input: { - normal: 0.027, - cached: 0, - }, - output: { - normal: 0.201, - }, - }, - image: 0, - }, } as const const META_LLAMA_LLAMA_3_2_3B_INSTRUCT = { id: 'meta-llama/llama-3.2-3b-instruct', @@ -5242,18 +3406,6 @@ const META_LLAMA_LLAMA_3_2_3B_INSTRUCT = { }, context_window: 131072, max_output_tokens: 72000, - pricing: { - text: { - input: { - normal: 0.0509, - cached: 0, - }, - output: { - normal: 0.335, - }, - }, - image: 0, - }, } as const const META_LLAMA_LLAMA_3_3_70B_INSTRUCT = { id: 'meta-llama/llama-3.3-70b-instruct', @@ -5278,18 +3430,6 @@ const META_LLAMA_LLAMA_3_3_70B_INSTRUCT = { }, context_window: 131072, max_output_tokens: 16384, - pricing: { - text: { - input: { - normal: 0.1, - cached: 0, - }, - output: { - normal: 0.32, - }, - }, - image: 0, - }, } as const const META_LLAMA_LLAMA_4_MAVERICK = { id: 'meta-llama/llama-4-maverick', @@ -5314,18 +3454,6 @@ const META_LLAMA_LLAMA_4_MAVERICK = { }, context_window: 524288, max_output_tokens: 16384, - pricing: { - text: { - input: { - normal: 0.1875, - cached: 0.05, - }, - output: { - normal: 0.6525, - }, - }, - image: 0, - }, } as const const META_LLAMA_LLAMA_4_SCOUT = { id: 'meta-llama/llama-4-scout', @@ -5348,18 +3476,6 @@ const META_LLAMA_LLAMA_4_SCOUT = { }, context_window: 1310720, max_output_tokens: 16384, - pricing: { - text: { - input: { - normal: 0.1, - cached: 0, - }, - output: { - normal: 0.3, - }, - }, - image: 0, - }, } as const const META_LLAMA_LLAMA_GUARD_4_12B = { id: 'meta-llama/llama-guard-4-12b', @@ -5380,18 +3496,6 @@ const META_LLAMA_LLAMA_GUARD_4_12B = { }, context_window: 163840, max_output_tokens: 16384, - pricing: { - text: { - input: { - normal: 0.18, - cached: 0, - }, - output: { - normal: 0.18, - }, - }, - image: 0, - }, } as const const META_MUSE_GLIMMER_30B = { id: 'meta/muse-glimmer-30b', @@ -5415,18 +3519,6 @@ const META_MUSE_GLIMMER_30B = { }, context_window: 131072, max_output_tokens: 16384, - pricing: { - text: { - input: { - normal: 0.3, - cached: 0.04, - }, - output: { - normal: 1.2, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_XHIGH, } as const const META_MUSE_SPARK_1_1 = { @@ -5446,18 +3538,6 @@ const META_MUSE_SPARK_1_1 = { }, context_window: 1048576, max_output_tokens: 943718, - pricing: { - text: { - input: { - normal: 1.25, - cached: 0.15, - }, - output: { - normal: 4.25, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_XHIGH, } as const const META_MUSE_SPARK_1_2 = { @@ -5477,18 +3557,6 @@ const META_MUSE_SPARK_1_2 = { }, context_window: 1048576, max_output_tokens: 943718, - pricing: { - text: { - input: { - normal: 1.25, - cached: 0.15, - }, - output: { - normal: 4.25, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_XHIGH, } as const const META_MUSE_SPARK_1_2_CONTRIBUTOR = { @@ -5508,18 +3576,6 @@ const META_MUSE_SPARK_1_2_CONTRIBUTOR = { }, context_window: 1048576, max_output_tokens: 943718, - pricing: { - text: { - input: { - normal: 0.1, - cached: 0.002, - }, - output: { - normal: 0.2, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_XHIGH, } as const const META_MUSE_SPARK_1_3 = { @@ -5539,18 +3595,6 @@ const META_MUSE_SPARK_1_3 = { }, context_window: 1048576, max_output_tokens: 943718, - pricing: { - text: { - input: { - normal: 1.25, - cached: 0.15, - }, - output: { - normal: 4.25, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_MAX, } as const const META_MUSE_SPARK_1_3_CONTRIBUTOR = { @@ -5570,18 +3614,6 @@ const META_MUSE_SPARK_1_3_CONTRIBUTOR = { }, context_window: 1048576, max_output_tokens: 943718, - pricing: { - text: { - input: { - normal: 0.1, - cached: 0.002, - }, - output: { - normal: 0.2, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_MAX, } as const const META_MUSE_SPARK_OPEN = { @@ -5608,18 +3640,6 @@ const META_MUSE_SPARK_OPEN = { }, context_window: 1048576, max_output_tokens: 943718, - pricing: { - text: { - input: { - normal: 1.25, - cached: 0.15, - }, - output: { - normal: 4.25, - }, - }, - image: 0, - }, } as const const META_MUSE_WONDER = { id: 'meta/muse-wonder', @@ -5638,18 +3658,6 @@ const META_MUSE_WONDER = { }, context_window: 1048576, max_output_tokens: 943718, - pricing: { - text: { - input: { - normal: 4, - cached: 0.2, - }, - output: { - normal: 20, - }, - }, - image: 0, - }, } as const const MICROSOFT_PHI_4 = { id: 'microsoft/phi-4', @@ -5671,18 +3679,6 @@ const MICROSOFT_PHI_4 = { }, context_window: 16384, max_output_tokens: 14745, - pricing: { - text: { - input: { - normal: 0.07, - cached: 0, - }, - output: { - normal: 0.14, - }, - }, - image: 0, - }, } as const const MINIMAX_MINIMAX_01 = { id: 'minimax/minimax-01', @@ -5694,18 +3690,6 @@ const MINIMAX_MINIMAX_01 = { }, context_window: 1000192, max_output_tokens: 900172, - pricing: { - text: { - input: { - normal: 0.2, - cached: 0, - }, - output: { - normal: 1.1, - }, - }, - image: 0, - }, } as const const MINIMAX_MINIMAX_M1 = { id: 'minimax/minimax-m1', @@ -5727,18 +3711,6 @@ const MINIMAX_MINIMAX_M1 = { }, context_window: 1000000, max_output_tokens: 40000, - pricing: { - text: { - input: { - normal: 0.55, - cached: 0, - }, - output: { - normal: 2.2, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const MINIMAX_MINIMAX_M2 = { @@ -5764,18 +3736,6 @@ const MINIMAX_MINIMAX_M2 = { }, context_window: 204800, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 0.255, - cached: 0, - }, - output: { - normal: 1.02, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const MINIMAX_MINIMAX_M2_HER = { @@ -5788,18 +3748,6 @@ const MINIMAX_MINIMAX_M2_HER = { }, context_window: 65536, max_output_tokens: 2048, - pricing: { - text: { - input: { - normal: 0.3, - cached: 0.03, - }, - output: { - normal: 1.2, - }, - }, - image: 0, - }, } as const const MINIMAX_MINIMAX_M2_1 = { id: 'minimax/minimax-m2.1', @@ -5818,18 +3766,6 @@ const MINIMAX_MINIMAX_M2_1 = { }, context_window: 204800, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 0.3, - cached: 0.03, - }, - output: { - normal: 1.2, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const MINIMAX_MINIMAX_M2_5 = { @@ -5856,18 +3792,6 @@ const MINIMAX_MINIMAX_M2_5 = { }, context_window: 204800, max_output_tokens: 32768, - pricing: { - text: { - input: { - normal: 0.27, - cached: 0.03, - }, - output: { - normal: 0.95, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const MINIMAX_MINIMAX_M2_7 = { @@ -5892,18 +3816,6 @@ const MINIMAX_MINIMAX_M2_7 = { }, context_window: 204800, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 0.3, - cached: 0.06, - }, - output: { - normal: 1.2, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const MINIMAX_MINIMAX_M3 = { @@ -5930,18 +3842,6 @@ const MINIMAX_MINIMAX_M3 = { }, context_window: 1048576, max_output_tokens: 512000, - pricing: { - text: { - input: { - normal: 0.3, - cached: 0.06, - }, - output: { - normal: 1.2, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const MINIMAX_MINIMAX_M3_1_FLASH_FREE = { @@ -5961,18 +3861,6 @@ const MINIMAX_MINIMAX_M3_1_FLASH_FREE = { }, context_window: 1000000, max_output_tokens: 524288, - pricing: { - text: { - input: { - normal: 0, - cached: 0, - }, - output: { - normal: 0, - }, - }, - image: 0, - }, } as const const MISTRALAI_CODESTRAL_2508 = { id: 'mistralai/codestral-2508', @@ -5994,18 +3882,6 @@ const MISTRALAI_CODESTRAL_2508 = { }, context_window: 256000, max_output_tokens: 204800, - pricing: { - text: { - input: { - normal: 0.3, - cached: 0.03, - }, - output: { - normal: 0.9, - }, - }, - image: 0, - }, } as const const MISTRALAI_CODESTRAL_2508_BATCH = { id: 'mistralai/codestral-2508:batch', @@ -6027,18 +3903,6 @@ const MISTRALAI_CODESTRAL_2508_BATCH = { }, context_window: 256000, max_output_tokens: 204800, - pricing: { - text: { - input: { - normal: 0.15, - cached: 0.015, - }, - output: { - normal: 0.45, - }, - }, - image: 0, - }, } as const const MISTRALAI_DEVSTRAL_2512 = { id: 'mistralai/devstral-2512', @@ -6060,18 +3924,6 @@ const MISTRALAI_DEVSTRAL_2512 = { }, context_window: 262144, max_output_tokens: 209715, - pricing: { - text: { - input: { - normal: 0.4, - cached: 0.04, - }, - output: { - normal: 2, - }, - }, - image: 0, - }, } as const const MISTRALAI_MINISTRAL_14B_2512 = { id: 'mistralai/ministral-14b-2512', @@ -6093,18 +3945,6 @@ const MISTRALAI_MINISTRAL_14B_2512 = { }, context_window: 262144, max_output_tokens: 209715, - pricing: { - text: { - input: { - normal: 0.2, - cached: 0.02, - }, - output: { - normal: 0.2, - }, - }, - image: 0, - }, } as const const MISTRALAI_MINISTRAL_3B_2512 = { id: 'mistralai/ministral-3b-2512', @@ -6126,18 +3966,6 @@ const MISTRALAI_MINISTRAL_3B_2512 = { }, context_window: 131072, max_output_tokens: 104857, - pricing: { - text: { - input: { - normal: 0.1, - cached: 0.01, - }, - output: { - normal: 0.1, - }, - }, - image: 0, - }, } as const const MISTRALAI_MINISTRAL_8B_2512 = { id: 'mistralai/ministral-8b-2512', @@ -6159,18 +3987,6 @@ const MISTRALAI_MINISTRAL_8B_2512 = { }, context_window: 262144, max_output_tokens: 209715, - pricing: { - text: { - input: { - normal: 0.15, - cached: 0.015, - }, - output: { - normal: 0.15, - }, - }, - image: 0, - }, } as const const MISTRALAI_MINISTRAL_8B_2512_BATCH = { id: 'mistralai/ministral-8b-2512:batch', @@ -6192,18 +4008,6 @@ const MISTRALAI_MINISTRAL_8B_2512_BATCH = { }, context_window: 262144, max_output_tokens: 209715, - pricing: { - text: { - input: { - normal: 0.075, - cached: 0.0075, - }, - output: { - normal: 0.075, - }, - }, - image: 0, - }, } as const const MISTRALAI_MISTRAL_LARGE = { id: 'mistralai/mistral-large', @@ -6225,18 +4029,6 @@ const MISTRALAI_MISTRAL_LARGE = { }, context_window: 128000, max_output_tokens: 102400, - pricing: { - text: { - input: { - normal: 2, - cached: 0.2, - }, - output: { - normal: 6, - }, - }, - image: 0, - }, } as const const MISTRALAI_MISTRAL_LARGE_2407 = { id: 'mistralai/mistral-large-2407', @@ -6258,18 +4050,6 @@ const MISTRALAI_MISTRAL_LARGE_2407 = { }, context_window: 131072, max_output_tokens: 104857, - pricing: { - text: { - input: { - normal: 2, - cached: 0.2, - }, - output: { - normal: 6, - }, - }, - image: 0, - }, } as const const MISTRALAI_MISTRAL_LARGE_2512 = { id: 'mistralai/mistral-large-2512', @@ -6291,18 +4071,6 @@ const MISTRALAI_MISTRAL_LARGE_2512 = { }, context_window: 262144, max_output_tokens: 209715, - pricing: { - text: { - input: { - normal: 0.5, - cached: 0.05, - }, - output: { - normal: 1.5, - }, - }, - image: 0, - }, } as const const MISTRALAI_MISTRAL_LARGE_2512_BATCH = { id: 'mistralai/mistral-large-2512:batch', @@ -6324,18 +4092,6 @@ const MISTRALAI_MISTRAL_LARGE_2512_BATCH = { }, context_window: 262144, max_output_tokens: 209715, - pricing: { - text: { - input: { - normal: 0.25, - cached: 0.025, - }, - output: { - normal: 0.75, - }, - }, - image: 0, - }, } as const const MISTRALAI_MISTRAL_LARGE_4_0 = { id: 'mistralai/mistral-large-4-0', @@ -6360,18 +4116,6 @@ const MISTRALAI_MISTRAL_LARGE_4_0 = { }, context_window: 1048576, max_output_tokens: 262144, - pricing: { - text: { - input: { - normal: 1.36, - cached: 0.14, - }, - output: { - normal: 4.18, - }, - }, - image: 0, - }, } as const const MISTRALAI_MISTRAL_MEDIUM_3 = { id: 'mistralai/mistral-medium-3', @@ -6393,18 +4137,6 @@ const MISTRALAI_MISTRAL_MEDIUM_3 = { }, context_window: 131072, max_output_tokens: 104857, - pricing: { - text: { - input: { - normal: 0.4, - cached: 0.04, - }, - output: { - normal: 2, - }, - }, - image: 0, - }, } as const const MISTRALAI_MISTRAL_MEDIUM_3_5 = { id: 'mistralai/mistral-medium-3-5', @@ -6427,18 +4159,6 @@ const MISTRALAI_MISTRAL_MEDIUM_3_5 = { }, context_window: 262144, max_output_tokens: 209715, - pricing: { - text: { - input: { - normal: 1.5, - cached: 0, - }, - output: { - normal: 7.5, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_HIGH, } as const const MISTRALAI_MISTRAL_MEDIUM_3_5_BATCH = { @@ -6462,18 +4182,6 @@ const MISTRALAI_MISTRAL_MEDIUM_3_5_BATCH = { }, context_window: 262144, max_output_tokens: 209715, - pricing: { - text: { - input: { - normal: 0.75, - cached: 0, - }, - output: { - normal: 3.75, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_HIGH, } as const const MISTRALAI_MISTRAL_MEDIUM_3_1 = { @@ -6496,18 +4204,6 @@ const MISTRALAI_MISTRAL_MEDIUM_3_1 = { }, context_window: 131072, max_output_tokens: 104857, - pricing: { - text: { - input: { - normal: 0.4, - cached: 0.04, - }, - output: { - normal: 2, - }, - }, - image: 0, - }, } as const const MISTRALAI_MISTRAL_MEDIUM_3_1_BATCH = { id: 'mistralai/mistral-medium-3.1:batch', @@ -6529,18 +4225,6 @@ const MISTRALAI_MISTRAL_MEDIUM_3_1_BATCH = { }, context_window: 131072, max_output_tokens: 104857, - pricing: { - text: { - input: { - normal: 0.2, - cached: 0.02, - }, - output: { - normal: 1, - }, - }, - image: 0, - }, } as const const MISTRALAI_MISTRAL_NEMO = { id: 'mistralai/mistral-nemo', @@ -6565,18 +4249,6 @@ const MISTRALAI_MISTRAL_NEMO = { }, context_window: 131072, max_output_tokens: 16384, - pricing: { - text: { - input: { - normal: 0.029, - cached: 0, - }, - output: { - normal: 0.03, - }, - }, - image: 0, - }, } as const const MISTRALAI_MISTRAL_SABA = { id: 'mistralai/mistral-saba', @@ -6598,18 +4270,6 @@ const MISTRALAI_MISTRAL_SABA = { }, context_window: 32768, max_output_tokens: 26214, - pricing: { - text: { - input: { - normal: 0.2, - cached: 0.02, - }, - output: { - normal: 0.6, - }, - }, - image: 0, - }, } as const const MISTRALAI_MISTRAL_SMALL_24B_INSTRUCT_2501 = { id: 'mistralai/mistral-small-24b-instruct-2501', @@ -6631,18 +4291,6 @@ const MISTRALAI_MISTRAL_SMALL_24B_INSTRUCT_2501 = { }, context_window: 32768, max_output_tokens: 16384, - pricing: { - text: { - input: { - normal: 0.05, - cached: 0, - }, - output: { - normal: 0.08, - }, - }, - image: 0, - }, } as const const MISTRALAI_MISTRAL_SMALL_2603 = { id: 'mistralai/mistral-small-2603', @@ -6665,18 +4313,6 @@ const MISTRALAI_MISTRAL_SMALL_2603 = { }, context_window: 262144, max_output_tokens: 209715, - pricing: { - text: { - input: { - normal: 0.15, - cached: 0.015, - }, - output: { - normal: 0.6, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_HIGH, } as const const MISTRALAI_MISTRAL_SMALL_2603_BATCH = { @@ -6700,18 +4336,6 @@ const MISTRALAI_MISTRAL_SMALL_2603_BATCH = { }, context_window: 262144, max_output_tokens: 209715, - pricing: { - text: { - input: { - normal: 0.075, - cached: 0.0075, - }, - output: { - normal: 0.3, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_HIGH, } as const const MISTRALAI_MISTRAL_SMALL_3_1_24B_INSTRUCT = { @@ -6736,18 +4360,6 @@ const MISTRALAI_MISTRAL_SMALL_3_1_24B_INSTRUCT = { }, context_window: 128000, max_output_tokens: 102400, - pricing: { - text: { - input: { - normal: 0.351, - cached: 0, - }, - output: { - normal: 0.555, - }, - }, - image: 0, - }, } as const const MISTRALAI_MISTRAL_SMALL_3_2_24B_INSTRUCT = { id: 'mistralai/mistral-small-3.2-24b-instruct', @@ -6772,18 +4384,6 @@ const MISTRALAI_MISTRAL_SMALL_3_2_24B_INSTRUCT = { }, context_window: 256000, max_output_tokens: 16384, - pricing: { - text: { - input: { - normal: 0.09375, - cached: 0, - }, - output: { - normal: 0.25, - }, - }, - image: 0, - }, } as const const MISTRALAI_MIXTRAL_8X22B_INSTRUCT = { id: 'mistralai/mixtral-8x22b-instruct', @@ -6805,18 +4405,6 @@ const MISTRALAI_MIXTRAL_8X22B_INSTRUCT = { }, context_window: 65536, max_output_tokens: 52428, - pricing: { - text: { - input: { - normal: 2, - cached: 0.2, - }, - output: { - normal: 6, - }, - }, - image: 0, - }, } as const const MISTRALAI_VOXTRAL_SMALL_24B_2507 = { id: 'mistralai/voxtral-small-24b-2507', @@ -6838,18 +4426,6 @@ const MISTRALAI_VOXTRAL_SMALL_24B_2507 = { }, context_window: 32768, max_output_tokens: 26214, - pricing: { - text: { - input: { - normal: 0.1, - cached: 0.01, - }, - output: { - normal: 0.3, - }, - }, - image: 0, - }, } as const const MOONDREAM_MOONDREAM3_PREVIEW = { id: 'moondream/moondream3-preview', @@ -6867,18 +4443,6 @@ const MOONDREAM_MOONDREAM3_PREVIEW = { }, context_window: 32000, max_output_tokens: 4096, - pricing: { - text: { - input: { - normal: 0.3, - cached: 0, - }, - output: { - normal: 2.5, - }, - }, - image: 0, - }, } as const const MOONDREAM_MOONDREAM3_1_9B_A2B = { id: 'moondream/moondream3.1-9b-a2b', @@ -6896,18 +4460,6 @@ const MOONDREAM_MOONDREAM3_1_9B_A2B = { }, context_window: 32000, max_output_tokens: 4096, - pricing: { - text: { - input: { - normal: 0.3, - cached: 0, - }, - output: { - normal: 2.5, - }, - }, - image: 0, - }, } as const const MOONSHOTAI_KIMI_K2 = { id: 'moonshotai/kimi-k2', @@ -6928,18 +4480,6 @@ const MOONSHOTAI_KIMI_K2 = { }, context_window: 131072, max_output_tokens: 98304, - pricing: { - text: { - input: { - normal: 0.57, - cached: 0, - }, - output: { - normal: 2.3, - }, - }, - image: 0, - }, } as const const MOONSHOTAI_KIMI_K2_0905 = { id: 'moonshotai/kimi-k2-0905', @@ -6961,18 +4501,6 @@ const MOONSHOTAI_KIMI_K2_0905 = { }, context_window: 262144, max_output_tokens: 98304, - pricing: { - text: { - input: { - normal: 0.6, - cached: 0, - }, - output: { - normal: 2.5, - }, - }, - image: 0, - }, } as const const MOONSHOTAI_KIMI_K2_THINKING = { id: 'moonshotai/kimi-k2-thinking', @@ -6997,18 +4525,6 @@ const MOONSHOTAI_KIMI_K2_THINKING = { }, context_window: 262144, max_output_tokens: 98304, - pricing: { - text: { - input: { - normal: 0.6, - cached: 0.15, - }, - output: { - normal: 2.5, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const MOONSHOTAI_KIMI_K2_5 = { @@ -7035,18 +4551,6 @@ const MOONSHOTAI_KIMI_K2_5 = { }, context_window: 262144, max_output_tokens: 235929, - pricing: { - text: { - input: { - normal: 0.5, - cached: 0.15, - }, - output: { - normal: 2.5, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const MOONSHOTAI_KIMI_K2_6 = { @@ -7074,18 +4578,6 @@ const MOONSHOTAI_KIMI_K2_6 = { }, context_window: 262144, max_output_tokens: 235929, - pricing: { - text: { - input: { - normal: 0.65, - cached: 0.15, - }, - output: { - normal: 3.41, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const MOONSHOTAI_KIMI_K2_7_CODE = { @@ -7113,18 +4605,6 @@ const MOONSHOTAI_KIMI_K2_7_CODE = { }, context_window: 262144, max_output_tokens: 235929, - pricing: { - text: { - input: { - normal: 0.6712, - cached: 0.18, - }, - output: { - normal: 3.35, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const MOONSHOTAI_KIMI_K3 = { @@ -7151,18 +4631,6 @@ const MOONSHOTAI_KIMI_K3 = { }, context_window: 1048576, max_output_tokens: 943718, - pricing: { - text: { - input: { - normal: 0.239, - cached: 0.21, - }, - output: { - normal: 11.936, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_HIGH_MAX, } as const const MOONSHOTAI_KIMI_K3_BATCH = { @@ -7187,18 +4655,6 @@ const MOONSHOTAI_KIMI_K3_BATCH = { }, context_window: 1048576, max_output_tokens: 16384, - pricing: { - text: { - input: { - normal: 2.28, - cached: 0.228, - }, - output: { - normal: 11.4, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_HIGH_MAX, } as const const MORPH_MORPH_V3_FAST = { @@ -7218,18 +4674,6 @@ const MORPH_MORPH_V3_FAST = { }, context_window: 262144, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 0.8, - cached: 0, - }, - output: { - normal: 1.2, - }, - }, - image: 0, - }, } as const const MORPH_MORPH_V3_LARGE = { id: 'morph/morph-v3-large', @@ -7248,18 +4692,6 @@ const MORPH_MORPH_V3_LARGE = { }, context_window: 262144, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 0.9, - cached: 0, - }, - output: { - normal: 1.9, - }, - }, - image: 0, - }, } as const const NEX_AGI_NEX_N2_5_MINI = { id: 'nex-agi/nex-n2.5-mini', @@ -7278,18 +4710,6 @@ const NEX_AGI_NEX_N2_5_MINI = { }, context_window: 262144, max_output_tokens: 235929, - pricing: { - text: { - input: { - normal: 0.025, - cached: 0.0025, - }, - output: { - normal: 0.1, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_MEDIUM_HIGH, } as const const NEX_AGI_NEX_N2_5_PRO = { @@ -7310,18 +4730,6 @@ const NEX_AGI_NEX_N2_5_PRO = { }, context_window: 262144, max_output_tokens: 235929, - pricing: { - text: { - input: { - normal: 0.075, - cached: 0.015, - }, - output: { - normal: 0.25, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_MEDIUM_HIGH, } as const const NOUSRESEARCH_HERMES_3_LLAMA_3_1_405B = { @@ -7344,18 +4752,6 @@ const NOUSRESEARCH_HERMES_3_LLAMA_3_1_405B = { }, context_window: 131072, max_output_tokens: 16384, - pricing: { - text: { - input: { - normal: 1, - cached: 0, - }, - output: { - normal: 1, - }, - }, - image: 0, - }, } as const const NOUSRESEARCH_HERMES_3_LLAMA_3_1_70B = { id: 'nousresearch/hermes-3-llama-3.1-70b', @@ -7376,18 +4772,6 @@ const NOUSRESEARCH_HERMES_3_LLAMA_3_1_70B = { }, context_window: 131072, max_output_tokens: 16384, - pricing: { - text: { - input: { - normal: 0.7, - cached: 0, - }, - output: { - normal: 0.7, - }, - }, - image: 0, - }, } as const const NOUSRESEARCH_HERMES_4_405B = { id: 'nousresearch/hermes-4-405b', @@ -7409,18 +4793,6 @@ const NOUSRESEARCH_HERMES_4_405B = { }, context_window: 131072, max_output_tokens: 117964, - pricing: { - text: { - input: { - normal: 1, - cached: 0, - }, - output: { - normal: 3, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const NVIDIA_NEMOTRON_3_NANO_30B_A3B = { @@ -7447,18 +4819,6 @@ const NVIDIA_NEMOTRON_3_NANO_30B_A3B = { }, context_window: 262144, max_output_tokens: 235929, - pricing: { - text: { - input: { - normal: 0.06, - cached: 0, - }, - output: { - normal: 0.24, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const NVIDIA_NEMOTRON_3_NANO_OMNI_30B_A3B_REASONING_FREE = { @@ -7478,18 +4838,6 @@ const NVIDIA_NEMOTRON_3_NANO_OMNI_30B_A3B_REASONING_FREE = { }, context_window: 256000, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0, - cached: 0, - }, - output: { - normal: 0, - }, - }, - image: 0, - }, reasoning: BUDGET_OFF_HIGH, } as const const NVIDIA_NEMOTRON_3_SUPER_120B_A12B = { @@ -7516,18 +4864,6 @@ const NVIDIA_NEMOTRON_3_SUPER_120B_A12B = { }, context_window: 262144, max_output_tokens: 235929, - pricing: { - text: { - input: { - normal: 0.3, - cached: 0.15, - }, - output: { - normal: 2.4, - }, - }, - image: 0, - }, reasoning: BUDGET_NONE_LOW_MEDIUM, } as const const NVIDIA_NEMOTRON_3_SUPER_120B_A12B_FREE = { @@ -7548,18 +4884,6 @@ const NVIDIA_NEMOTRON_3_SUPER_120B_A12B_FREE = { }, context_window: 262144, max_output_tokens: 235929, - pricing: { - text: { - input: { - normal: 0, - cached: 0, - }, - output: { - normal: 0, - }, - }, - image: 0, - }, reasoning: BUDGET_NONE_LOW_MEDIUM, } as const const NVIDIA_NEMOTRON_3_ULTRA_550B_A55B = { @@ -7584,18 +4908,6 @@ const NVIDIA_NEMOTRON_3_ULTRA_550B_A55B = { }, context_window: 262144, max_output_tokens: 182520, - pricing: { - text: { - input: { - normal: 0.6, - cached: 0.12, - }, - output: { - normal: 2.4, - }, - }, - image: 0, - }, reasoning: BUDGET_NONE_MEDIUM_HIGH, } as const const NVIDIA_NEMOTRON_3_ULTRA_550B_A55B_FREE = { @@ -7615,18 +4927,6 @@ const NVIDIA_NEMOTRON_3_ULTRA_550B_A55B_FREE = { }, context_window: 1000000, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0, - cached: 0, - }, - output: { - normal: 0, - }, - }, - image: 0, - }, reasoning: BUDGET_NONE_MEDIUM_HIGH, } as const const NVIDIA_NEMOTRON_3_5_CONTENT_SAFETY = { @@ -7649,18 +4949,6 @@ const NVIDIA_NEMOTRON_3_5_CONTENT_SAFETY = { }, context_window: 131072, max_output_tokens: 117964, - pricing: { - text: { - input: { - normal: 0.2, - cached: 0, - }, - output: { - normal: 0.2, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const NVIDIA_NEMOTRON_3_5_CONTENT_SAFETY_FREE = { @@ -7679,18 +4967,6 @@ const NVIDIA_NEMOTRON_3_5_CONTENT_SAFETY_FREE = { }, context_window: 128000, max_output_tokens: 8192, - pricing: { - text: { - input: { - normal: 0, - cached: 0, - }, - output: { - normal: 0, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const NVIDIA_NEMOTRON_3_5_LIGHTNING = { @@ -7717,18 +4993,6 @@ const NVIDIA_NEMOTRON_3_5_LIGHTNING = { }, context_window: 262144, max_output_tokens: 235929, - pricing: { - text: { - input: { - normal: 0.07, - cached: 0.04, - }, - output: { - normal: 0.2, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const NVIDIA_NEMOTRON_3_5_LIGHTNING_FREE = { @@ -7748,18 +5012,6 @@ const NVIDIA_NEMOTRON_3_5_LIGHTNING_FREE = { }, context_window: 1000000, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0, - cached: 0, - }, - output: { - normal: 0, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const NVIDIA_NEMOTRON_3_5_SUPER_VL = { @@ -7786,18 +5038,6 @@ const NVIDIA_NEMOTRON_3_5_SUPER_VL = { }, context_window: 1048576, max_output_tokens: 235929, - pricing: { - text: { - input: { - normal: 0.15, - cached: 0.02, - }, - output: { - normal: 0.5, - }, - }, - image: 0, - }, } as const const NVIDIA_NEMOTRON_3_5_SUPER_VL_FREE = { id: 'nvidia/nemotron-3.5-super-vl:free', @@ -7817,18 +5057,6 @@ const NVIDIA_NEMOTRON_3_5_SUPER_VL_FREE = { }, context_window: 1000000, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 0, - cached: 0, - }, - output: { - normal: 0, - }, - }, - image: 0, - }, } as const const OPENAI_GPT_3_5_TURBO = { id: 'openai/gpt-3.5-turbo', @@ -7853,18 +5081,6 @@ const OPENAI_GPT_3_5_TURBO = { }, context_window: 16385, max_output_tokens: 4096, - pricing: { - text: { - input: { - normal: 0.5, - cached: 0, - }, - output: { - normal: 1.5, - }, - }, - image: 0, - }, } as const const OPENAI_GPT_3_5_TURBO_0613 = { id: 'openai/gpt-3.5-turbo-0613', @@ -7889,18 +5105,6 @@ const OPENAI_GPT_3_5_TURBO_0613 = { }, context_window: 4095, max_output_tokens: 3685, - pricing: { - text: { - input: { - normal: 1, - cached: 0, - }, - output: { - normal: 2, - }, - }, - image: 0, - }, } as const const OPENAI_GPT_3_5_TURBO_16K = { id: 'openai/gpt-3.5-turbo-16k', @@ -7926,18 +5130,6 @@ const OPENAI_GPT_3_5_TURBO_16K = { }, context_window: 16385, max_output_tokens: 4096, - pricing: { - text: { - input: { - normal: 3, - cached: 0, - }, - output: { - normal: 4, - }, - }, - image: 0, - }, } as const const OPENAI_GPT_3_5_TURBO_INSTRUCT = { id: 'openai/gpt-3.5-turbo-instruct', @@ -7961,18 +5153,6 @@ const OPENAI_GPT_3_5_TURBO_INSTRUCT = { }, context_window: 4095, max_output_tokens: 3685, - pricing: { - text: { - input: { - normal: 1.5, - cached: 0, - }, - output: { - normal: 2, - }, - }, - image: 0, - }, } as const const OPENAI_GPT_3_5_TURBO_BATCH = { id: 'openai/gpt-3.5-turbo:batch', @@ -7997,18 +5177,6 @@ const OPENAI_GPT_3_5_TURBO_BATCH = { }, context_window: 16385, max_output_tokens: 4096, - pricing: { - text: { - input: { - normal: 0.25, - cached: 0, - }, - output: { - normal: 0.75, - }, - }, - image: 0, - }, } as const const OPENAI_GPT_4 = { id: 'openai/gpt-4', @@ -8034,18 +5202,6 @@ const OPENAI_GPT_4 = { }, context_window: 8191, max_output_tokens: 4096, - pricing: { - text: { - input: { - normal: 30, - cached: 0, - }, - output: { - normal: 60, - }, - }, - image: 0, - }, } as const const OPENAI_GPT_4_TURBO = { id: 'openai/gpt-4-turbo', @@ -8070,18 +5226,6 @@ const OPENAI_GPT_4_TURBO = { }, context_window: 128000, max_output_tokens: 4096, - pricing: { - text: { - input: { - normal: 10, - cached: 0, - }, - output: { - normal: 30, - }, - }, - image: 0, - }, } as const const OPENAI_GPT_4_TURBO_BATCH = { id: 'openai/gpt-4-turbo:batch', @@ -8106,18 +5250,6 @@ const OPENAI_GPT_4_TURBO_BATCH = { }, context_window: 128000, max_output_tokens: 4096, - pricing: { - text: { - input: { - normal: 5, - cached: 0, - }, - output: { - normal: 15, - }, - }, - image: 0, - }, } as const const OPENAI_GPT_4_1 = { id: 'openai/gpt-4.1', @@ -8137,18 +5269,6 @@ const OPENAI_GPT_4_1 = { }, context_window: 1047576, max_output_tokens: 32768, - pricing: { - text: { - input: { - normal: 2, - cached: 0.5, - }, - output: { - normal: 8, - }, - }, - image: 0, - }, } as const const OPENAI_GPT_4_1_MINI = { id: 'openai/gpt-4.1-mini', @@ -8168,18 +5288,6 @@ const OPENAI_GPT_4_1_MINI = { }, context_window: 1047576, max_output_tokens: 32768, - pricing: { - text: { - input: { - normal: 0.4, - cached: 0.1, - }, - output: { - normal: 1.6, - }, - }, - image: 0, - }, } as const const OPENAI_GPT_4_1_MINI_BATCH = { id: 'openai/gpt-4.1-mini:batch', @@ -8198,18 +5306,6 @@ const OPENAI_GPT_4_1_MINI_BATCH = { }, context_window: 1047576, max_output_tokens: 32768, - pricing: { - text: { - input: { - normal: 0.2, - cached: 0.05, - }, - output: { - normal: 0.8, - }, - }, - image: 0, - }, } as const const OPENAI_GPT_4_1_NANO = { id: 'openai/gpt-4.1-nano', @@ -8229,18 +5325,6 @@ const OPENAI_GPT_4_1_NANO = { }, context_window: 1047576, max_output_tokens: 32768, - pricing: { - text: { - input: { - normal: 0.1, - cached: 0.025, - }, - output: { - normal: 0.4, - }, - }, - image: 0, - }, } as const const OPENAI_GPT_4_1_NANO_BATCH = { id: 'openai/gpt-4.1-nano:batch', @@ -8259,18 +5343,6 @@ const OPENAI_GPT_4_1_NANO_BATCH = { }, context_window: 1047576, max_output_tokens: 32768, - pricing: { - text: { - input: { - normal: 0.05, - cached: 0.0125, - }, - output: { - normal: 0.2, - }, - }, - image: 0, - }, } as const const OPENAI_GPT_4_1_BATCH = { id: 'openai/gpt-4.1:batch', @@ -8289,18 +5361,6 @@ const OPENAI_GPT_4_1_BATCH = { }, context_window: 1047576, max_output_tokens: 32768, - pricing: { - text: { - input: { - normal: 1, - cached: 0.25, - }, - output: { - normal: 4, - }, - }, - image: 0, - }, } as const const OPENAI_GPT_4O = { id: 'openai/gpt-4o', @@ -8326,18 +5386,6 @@ const OPENAI_GPT_4O = { }, context_window: 128000, max_output_tokens: 16384, - pricing: { - text: { - input: { - normal: 2.5, - cached: 1.25, - }, - output: { - normal: 10, - }, - }, - image: 0, - }, } as const const OPENAI_GPT_4O_2024_05_13 = { id: 'openai/gpt-4o-2024-05-13', @@ -8363,18 +5411,6 @@ const OPENAI_GPT_4O_2024_05_13 = { }, context_window: 128000, max_output_tokens: 4096, - pricing: { - text: { - input: { - normal: 5, - cached: 0, - }, - output: { - normal: 15, - }, - }, - image: 0, - }, } as const const OPENAI_GPT_4O_2024_08_06 = { id: 'openai/gpt-4o-2024-08-06', @@ -8400,18 +5436,6 @@ const OPENAI_GPT_4O_2024_08_06 = { }, context_window: 128000, max_output_tokens: 16384, - pricing: { - text: { - input: { - normal: 2.5, - cached: 1.25, - }, - output: { - normal: 10, - }, - }, - image: 0, - }, } as const const OPENAI_GPT_4O_2024_11_20 = { id: 'openai/gpt-4o-2024-11-20', @@ -8436,18 +5460,6 @@ const OPENAI_GPT_4O_2024_11_20 = { }, context_window: 128000, max_output_tokens: 16384, - pricing: { - text: { - input: { - normal: 2.5, - cached: 1.25, - }, - output: { - normal: 10, - }, - }, - image: 0, - }, } as const const OPENAI_GPT_4O_MINI = { id: 'openai/gpt-4o-mini', @@ -8473,18 +5485,6 @@ const OPENAI_GPT_4O_MINI = { }, context_window: 128000, max_output_tokens: 16384, - pricing: { - text: { - input: { - normal: 0.15, - cached: 0.075, - }, - output: { - normal: 0.6, - }, - }, - image: 0, - }, } as const const OPENAI_GPT_4O_MINI_2024_07_18 = { id: 'openai/gpt-4o-mini-2024-07-18', @@ -8509,18 +5509,6 @@ const OPENAI_GPT_4O_MINI_2024_07_18 = { }, context_window: 128000, max_output_tokens: 16384, - pricing: { - text: { - input: { - normal: 0.15, - cached: 0.075, - }, - output: { - normal: 0.6, - }, - }, - image: 0, - }, } as const const OPENAI_GPT_4O_MINI_BATCH = { id: 'openai/gpt-4o-mini:batch', @@ -8545,18 +5533,6 @@ const OPENAI_GPT_4O_MINI_BATCH = { }, context_window: 128000, max_output_tokens: 16384, - pricing: { - text: { - input: { - normal: 0.075, - cached: 0.0375, - }, - output: { - normal: 0.3, - }, - }, - image: 0, - }, } as const const OPENAI_GPT_4O_BATCH = { id: 'openai/gpt-4o:batch', @@ -8581,18 +5557,6 @@ const OPENAI_GPT_4O_BATCH = { }, context_window: 128000, max_output_tokens: 16384, - pricing: { - text: { - input: { - normal: 1.25, - cached: 0.625, - }, - output: { - normal: 5, - }, - }, - image: 0, - }, } as const const OPENAI_GPT_5 = { id: 'openai/gpt-5', @@ -8611,18 +5575,6 @@ const OPENAI_GPT_5 = { }, context_window: 400000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 1.25, - cached: 0.125, - }, - output: { - normal: 10, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const OPENAI_GPT_5_IMAGE = { @@ -8644,18 +5596,6 @@ const OPENAI_GPT_5_IMAGE = { }, context_window: 400000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 10, - cached: 1.25, - }, - output: { - normal: 10, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const OPENAI_GPT_5_IMAGE_MINI = { @@ -8677,18 +5617,6 @@ const OPENAI_GPT_5_IMAGE_MINI = { }, context_window: 400000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 2.5, - cached: 0.25, - }, - output: { - normal: 2, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const OPENAI_GPT_5_MINI = { @@ -8708,18 +5636,6 @@ const OPENAI_GPT_5_MINI = { }, context_window: 400000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 0.25, - cached: 0.025, - }, - output: { - normal: 2, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const OPENAI_GPT_5_MINI_BATCH = { @@ -8738,18 +5654,6 @@ const OPENAI_GPT_5_MINI_BATCH = { }, context_window: 400000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 0.125, - cached: 0.0125, - }, - output: { - normal: 1, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const OPENAI_GPT_5_NANO = { @@ -8769,18 +5673,6 @@ const OPENAI_GPT_5_NANO = { }, context_window: 400000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 0.05, - cached: 0.005, - }, - output: { - normal: 0.4, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const OPENAI_GPT_5_NANO_BATCH = { @@ -8799,18 +5691,6 @@ const OPENAI_GPT_5_NANO_BATCH = { }, context_window: 400000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 0.025, - cached: 0.0025, - }, - output: { - normal: 0.2, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const OPENAI_GPT_5_PRO = { @@ -8829,18 +5709,6 @@ const OPENAI_GPT_5_PRO = { }, context_window: 400000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 15, - cached: 0, - }, - output: { - normal: 120, - }, - }, - image: 0, - }, reasoning: EFFORT_HIGH, } as const const OPENAI_GPT_5_PRO_BATCH = { @@ -8859,18 +5727,6 @@ const OPENAI_GPT_5_PRO_BATCH = { }, context_window: 400000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 7.5, - cached: 0, - }, - output: { - normal: 60, - }, - }, - image: 0, - }, reasoning: EFFORT_HIGH, } as const const OPENAI_GPT_5_BATCH = { @@ -8889,18 +5745,6 @@ const OPENAI_GPT_5_BATCH = { }, context_window: 400000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 0.625, - cached: 0.0625, - }, - output: { - normal: 5, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const OPENAI_GPT_5_1 = { @@ -8920,18 +5764,6 @@ const OPENAI_GPT_5_1 = { }, context_window: 400000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 1.25, - cached: 0.125, - }, - output: { - normal: 10, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_HIGH, } as const const OPENAI_GPT_5_1_CODEX = { @@ -8950,18 +5782,6 @@ const OPENAI_GPT_5_1_CODEX = { }, context_window: 400000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 1.25, - cached: 0.13, - }, - output: { - normal: 10, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_HIGH, } as const const OPENAI_GPT_5_1_CODEX_MAX = { @@ -8980,18 +5800,6 @@ const OPENAI_GPT_5_1_CODEX_MAX = { }, context_window: 400000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 1.25, - cached: 0.125, - }, - output: { - normal: 10, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_XHIGH, } as const const OPENAI_GPT_5_1_CODEX_MINI = { @@ -9010,18 +5818,6 @@ const OPENAI_GPT_5_1_CODEX_MINI = { }, context_window: 400000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 0.25, - cached: 0.03, - }, - output: { - normal: 2, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_HIGH, } as const const OPENAI_GPT_5_1_BATCH = { @@ -9040,18 +5836,6 @@ const OPENAI_GPT_5_1_BATCH = { }, context_window: 400000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 0.625, - cached: 0.0625, - }, - output: { - normal: 5, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_HIGH, } as const const OPENAI_GPT_5_2 = { @@ -9071,18 +5855,6 @@ const OPENAI_GPT_5_2 = { }, context_window: 400000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 1.75, - cached: 0.175, - }, - output: { - normal: 14, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_XHIGH, } as const const OPENAI_GPT_5_2_CHAT = { @@ -9095,18 +5867,6 @@ const OPENAI_GPT_5_2_CHAT = { }, context_window: 128000, max_output_tokens: 32000, - pricing: { - text: { - input: { - normal: 1.75, - cached: 0.175, - }, - output: { - normal: 14, - }, - }, - image: 0, - }, } as const const OPENAI_GPT_5_2_CODEX = { id: 'openai/gpt-5.2-codex', @@ -9124,18 +5884,6 @@ const OPENAI_GPT_5_2_CODEX = { }, context_window: 400000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 1.75, - cached: 0.175, - }, - output: { - normal: 14, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_XHIGH, } as const const OPENAI_GPT_5_2_PRO = { @@ -9154,18 +5902,6 @@ const OPENAI_GPT_5_2_PRO = { }, context_window: 400000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 21, - cached: 0, - }, - output: { - normal: 168, - }, - }, - image: 0, - }, reasoning: EFFORT_MEDIUM_TO_XHIGH, } as const const OPENAI_GPT_5_2_PRO_BATCH = { @@ -9184,18 +5920,6 @@ const OPENAI_GPT_5_2_PRO_BATCH = { }, context_window: 400000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 10.5, - cached: 0, - }, - output: { - normal: 84, - }, - }, - image: 0, - }, reasoning: EFFORT_MEDIUM_TO_XHIGH, } as const const OPENAI_GPT_5_2_BATCH = { @@ -9214,18 +5938,6 @@ const OPENAI_GPT_5_2_BATCH = { }, context_window: 400000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 0.875, - cached: 0.0875, - }, - output: { - normal: 7, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_XHIGH, } as const const OPENAI_GPT_5_3_CODEX = { @@ -9245,18 +5957,6 @@ const OPENAI_GPT_5_3_CODEX = { }, context_window: 400000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 1.75, - cached: 0.175, - }, - output: { - normal: 14, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_XHIGH, } as const const OPENAI_GPT_5_4 = { @@ -9276,18 +5976,6 @@ const OPENAI_GPT_5_4 = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 2.5, - cached: 0.25, - }, - output: { - normal: 15, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_XHIGH, } as const const OPENAI_GPT_5_4_IMAGE_2 = { @@ -9307,18 +5995,6 @@ const OPENAI_GPT_5_4_IMAGE_2 = { }, context_window: 272000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 8, - cached: 2, - }, - output: { - normal: 15, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_XHIGH, } as const const OPENAI_GPT_5_4_MINI = { @@ -9338,18 +6014,6 @@ const OPENAI_GPT_5_4_MINI = { }, context_window: 400000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 0.75, - cached: 0.075, - }, - output: { - normal: 4.5, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_XHIGH, } as const const OPENAI_GPT_5_4_MINI_BATCH = { @@ -9368,18 +6032,6 @@ const OPENAI_GPT_5_4_MINI_BATCH = { }, context_window: 400000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 0.375, - cached: 0.0375, - }, - output: { - normal: 2.25, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_XHIGH, } as const const OPENAI_GPT_5_4_NANO = { @@ -9399,18 +6051,6 @@ const OPENAI_GPT_5_4_NANO = { }, context_window: 400000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 0.2, - cached: 0.02, - }, - output: { - normal: 1.25, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_XHIGH, } as const const OPENAI_GPT_5_4_NANO_BATCH = { @@ -9429,18 +6069,6 @@ const OPENAI_GPT_5_4_NANO_BATCH = { }, context_window: 400000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 0.1, - cached: 0.01, - }, - output: { - normal: 0.625, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_XHIGH, } as const const OPENAI_GPT_5_4_PRO = { @@ -9460,18 +6088,6 @@ const OPENAI_GPT_5_4_PRO = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 30, - cached: 0, - }, - output: { - normal: 180, - }, - }, - image: 0, - }, reasoning: EFFORT_MEDIUM_TO_XHIGH, } as const const OPENAI_GPT_5_4_PRO_BATCH = { @@ -9490,18 +6106,6 @@ const OPENAI_GPT_5_4_PRO_BATCH = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 15, - cached: 0, - }, - output: { - normal: 90, - }, - }, - image: 0, - }, reasoning: EFFORT_MEDIUM_TO_XHIGH, } as const const OPENAI_GPT_5_4_BATCH = { @@ -9520,18 +6124,6 @@ const OPENAI_GPT_5_4_BATCH = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 1.25, - cached: 0.125, - }, - output: { - normal: 7.5, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_XHIGH, } as const const OPENAI_GPT_5_5 = { @@ -9551,18 +6143,6 @@ const OPENAI_GPT_5_5 = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 5, - cached: 0.5, - }, - output: { - normal: 30, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_XHIGH, } as const const OPENAI_GPT_5_5_PRO = { @@ -9581,18 +6161,6 @@ const OPENAI_GPT_5_5_PRO = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 30, - cached: 0, - }, - output: { - normal: 180, - }, - }, - image: 0, - }, reasoning: EFFORT_MEDIUM_TO_XHIGH, } as const const OPENAI_GPT_5_5_PRO_BATCH = { @@ -9611,18 +6179,6 @@ const OPENAI_GPT_5_5_PRO_BATCH = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 15, - cached: 0, - }, - output: { - normal: 90, - }, - }, - image: 0, - }, reasoning: EFFORT_MEDIUM_TO_XHIGH, } as const const OPENAI_GPT_5_5_BATCH = { @@ -9641,18 +6197,6 @@ const OPENAI_GPT_5_5_BATCH = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 2.5, - cached: 0.25, - }, - output: { - normal: 15, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_XHIGH, } as const const OPENAI_GPT_5_6_LUNA = { @@ -9672,18 +6216,6 @@ const OPENAI_GPT_5_6_LUNA = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 0.2, - cached: 0.27, - }, - output: { - normal: 1.2, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const const OPENAI_GPT_5_6_LUNA_PRO = { @@ -9703,18 +6235,6 @@ const OPENAI_GPT_5_6_LUNA_PRO = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 0.2, - cached: 0.27, - }, - output: { - normal: 1.2, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const const OPENAI_GPT_5_6_LUNA_PRO_BATCH = { @@ -9733,18 +6253,6 @@ const OPENAI_GPT_5_6_LUNA_PRO_BATCH = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 0.1, - cached: 0.01, - }, - output: { - normal: 0.6, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const const OPENAI_GPT_5_6_LUNA_BATCH = { @@ -9763,18 +6271,6 @@ const OPENAI_GPT_5_6_LUNA_BATCH = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 0.1, - cached: 0.01, - }, - output: { - normal: 0.6, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const const OPENAI_GPT_5_6_SOL = { @@ -9794,18 +6290,6 @@ const OPENAI_GPT_5_6_SOL = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 4, - cached: 5.4, - }, - output: { - normal: 20, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const const OPENAI_GPT_5_6_SOL_PRO = { @@ -9825,18 +6309,6 @@ const OPENAI_GPT_5_6_SOL_PRO = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 4, - cached: 5.4, - }, - output: { - normal: 20, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const const OPENAI_GPT_5_6_SOL_PRO_BATCH = { @@ -9855,18 +6327,6 @@ const OPENAI_GPT_5_6_SOL_PRO_BATCH = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 2, - cached: 2.7, - }, - output: { - normal: 10, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const const OPENAI_GPT_5_6_SOL_BATCH = { @@ -9885,18 +6345,6 @@ const OPENAI_GPT_5_6_SOL_BATCH = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 2, - cached: 2.7, - }, - output: { - normal: 10, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const const OPENAI_GPT_5_6_TERRA = { @@ -9916,18 +6364,6 @@ const OPENAI_GPT_5_6_TERRA = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 2, - cached: 2.7, - }, - output: { - normal: 12, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const const OPENAI_GPT_5_6_TERRA_PRO = { @@ -9947,18 +6383,6 @@ const OPENAI_GPT_5_6_TERRA_PRO = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 2, - cached: 2.7, - }, - output: { - normal: 12, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const const OPENAI_GPT_5_6_TERRA_PRO_BATCH = { @@ -9977,18 +6401,6 @@ const OPENAI_GPT_5_6_TERRA_PRO_BATCH = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 1, - cached: 0.1, - }, - output: { - normal: 6, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const const OPENAI_GPT_5_6_TERRA_BATCH = { @@ -10007,18 +6419,6 @@ const OPENAI_GPT_5_6_TERRA_BATCH = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 1, - cached: 0.1, - }, - output: { - normal: 6, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const const OPENAI_GPT_6_ASTRA = { @@ -10038,18 +6438,6 @@ const OPENAI_GPT_6_ASTRA = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 10, - cached: 13.5, - }, - output: { - normal: 50, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_MAX, } as const const OPENAI_GPT_6_ASTRA_PRO = { @@ -10069,18 +6457,6 @@ const OPENAI_GPT_6_ASTRA_PRO = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 10, - cached: 13.5, - }, - output: { - normal: 50, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_MAX, } as const const OPENAI_GPT_6_ASTRA_PRO_BATCH = { @@ -10099,18 +6475,6 @@ const OPENAI_GPT_6_ASTRA_PRO_BATCH = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 5, - cached: 6.75, - }, - output: { - normal: 25, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_MAX, } as const const OPENAI_GPT_6_ASTRA_BATCH = { @@ -10129,18 +6493,6 @@ const OPENAI_GPT_6_ASTRA_BATCH = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 5, - cached: 6.75, - }, - output: { - normal: 25, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_MAX, } as const const OPENAI_GPT_6_LUNA = { @@ -10160,18 +6512,6 @@ const OPENAI_GPT_6_LUNA = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 0.1, - cached: 0.135, - }, - output: { - normal: 0.5, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const const OPENAI_GPT_6_LUNA_PRO = { @@ -10191,18 +6531,6 @@ const OPENAI_GPT_6_LUNA_PRO = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 0.1, - cached: 0.135, - }, - output: { - normal: 0.5, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const const OPENAI_GPT_6_LUNA_PRO_BATCH = { @@ -10221,18 +6549,6 @@ const OPENAI_GPT_6_LUNA_PRO_BATCH = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 0.05, - cached: 0.0675, - }, - output: { - normal: 0.25, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const const OPENAI_GPT_6_LUNA_BATCH = { @@ -10251,18 +6567,6 @@ const OPENAI_GPT_6_LUNA_BATCH = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 0.05, - cached: 0.0675, - }, - output: { - normal: 0.25, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const const OPENAI_GPT_6_SOL = { @@ -10282,18 +6586,6 @@ const OPENAI_GPT_6_SOL = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 2, - cached: 2.7, - }, - output: { - normal: 10, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const const OPENAI_GPT_6_SOL_PRO = { @@ -10313,18 +6605,6 @@ const OPENAI_GPT_6_SOL_PRO = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 2, - cached: 2.7, - }, - output: { - normal: 10, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const const OPENAI_GPT_6_SOL_PRO_BATCH = { @@ -10343,18 +6623,6 @@ const OPENAI_GPT_6_SOL_PRO_BATCH = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 1, - cached: 1.35, - }, - output: { - normal: 5, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const const OPENAI_GPT_6_SOL_BATCH = { @@ -10373,18 +6641,6 @@ const OPENAI_GPT_6_SOL_BATCH = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 1, - cached: 1.35, - }, - output: { - normal: 5, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_MAX, } as const const OPENAI_GPT_6_1_SOL = { @@ -10404,18 +6660,6 @@ const OPENAI_GPT_6_1_SOL = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 2, - cached: 2.6, - }, - output: { - normal: 10, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_MAX, } as const const OPENAI_GPT_6_1_SOL_PRO = { @@ -10435,18 +6679,6 @@ const OPENAI_GPT_6_1_SOL_PRO = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 2, - cached: 2.6, - }, - output: { - normal: 10, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_MAX, } as const const OPENAI_GPT_6_1_SOL_PRO_BATCH = { @@ -10465,18 +6697,6 @@ const OPENAI_GPT_6_1_SOL_PRO_BATCH = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 1, - cached: 1.3, - }, - output: { - normal: 5, - }, - }, - image: 0, - }, } as const const OPENAI_GPT_6_1_SOL_BATCH = { id: 'openai/gpt-6.1-sol:batch', @@ -10494,18 +6714,6 @@ const OPENAI_GPT_6_1_SOL_BATCH = { }, context_window: 1050000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 1, - cached: 1.3, - }, - output: { - normal: 5, - }, - }, - image: 0, - }, } as const const OPENAI_GPT_AUDIO = { id: 'openai/gpt-audio', @@ -10530,18 +6738,6 @@ const OPENAI_GPT_AUDIO = { }, context_window: 128000, max_output_tokens: 16384, - pricing: { - text: { - input: { - normal: 2.5, - cached: 0, - }, - output: { - normal: 10, - }, - }, - image: 0, - }, } as const const OPENAI_GPT_AUDIO_MINI = { id: 'openai/gpt-audio-mini', @@ -10566,18 +6762,6 @@ const OPENAI_GPT_AUDIO_MINI = { }, context_window: 128000, max_output_tokens: 16384, - pricing: { - text: { - input: { - normal: 0.6, - cached: 0, - }, - output: { - normal: 2.4, - }, - }, - image: 0, - }, } as const const OPENAI_GPT_CHAT_LATEST = { id: 'openai/gpt-chat-latest', @@ -10589,18 +6773,6 @@ const OPENAI_GPT_CHAT_LATEST = { }, context_window: 400000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 5, - cached: 0.5, - }, - output: { - normal: 30, - }, - }, - image: 0, - }, } as const const OPENAI_GPT_OSS_120B = { id: 'openai/gpt-oss-120b', @@ -10626,18 +6798,6 @@ const OPENAI_GPT_OSS_120B = { }, context_window: 131072, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0.15, - cached: 0.075, - }, - output: { - normal: 0.6, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_HIGH, } as const const OPENAI_GPT_OSS_120B_BATCH = { @@ -10662,18 +6822,6 @@ const OPENAI_GPT_OSS_120B_BATCH = { }, context_window: 131072, max_output_tokens: 117964, - pricing: { - text: { - input: { - normal: 0.0296, - cached: 0, - }, - output: { - normal: 0.136, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_HIGH, } as const const OPENAI_GPT_OSS_20B = { @@ -10700,18 +6848,6 @@ const OPENAI_GPT_OSS_20B = { }, context_window: 131072, max_output_tokens: 32768, - pricing: { - text: { - input: { - normal: 0.018, - cached: 0.009, - }, - output: { - normal: 0.09, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_HIGH, } as const const OPENAI_GPT_OSS_20B_BATCH = { @@ -10736,18 +6872,6 @@ const OPENAI_GPT_OSS_20B_BATCH = { }, context_window: 131072, max_output_tokens: 117964, - pricing: { - text: { - input: { - normal: 0.024, - cached: 0, - }, - output: { - normal: 0.112, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_HIGH, } as const const OPENAI_GPT_OSS_SAFEGUARD_20B = { @@ -10769,18 +6893,6 @@ const OPENAI_GPT_OSS_SAFEGUARD_20B = { }, context_window: 131072, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0.075, - cached: 0.0375, - }, - output: { - normal: 0.3, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_HIGH, } as const const OPENAI_O1 = { @@ -10799,18 +6911,6 @@ const OPENAI_O1 = { }, context_window: 200000, max_output_tokens: 100000, - pricing: { - text: { - input: { - normal: 15, - cached: 7.5, - }, - output: { - normal: 60, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const OPENAI_O1_PRO = { @@ -10823,18 +6923,6 @@ const OPENAI_O1_PRO = { }, context_window: 200000, max_output_tokens: 100000, - pricing: { - text: { - input: { - normal: 150, - cached: 0, - }, - output: { - normal: 600, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const OPENAI_O3 = { @@ -10853,18 +6941,6 @@ const OPENAI_O3 = { }, context_window: 200000, max_output_tokens: 100000, - pricing: { - text: { - input: { - normal: 2, - cached: 0.5, - }, - output: { - normal: 8, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const OPENAI_O3_MINI = { @@ -10883,18 +6959,6 @@ const OPENAI_O3_MINI = { }, context_window: 200000, max_output_tokens: 100000, - pricing: { - text: { - input: { - normal: 1.1, - cached: 0.55, - }, - output: { - normal: 4.4, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const OPENAI_O3_MINI_HIGH = { @@ -10913,18 +6977,6 @@ const OPENAI_O3_MINI_HIGH = { }, context_window: 200000, max_output_tokens: 100000, - pricing: { - text: { - input: { - normal: 1.1, - cached: 0.55, - }, - output: { - normal: 4.4, - }, - }, - image: 0, - }, reasoning: EFFORT_HIGH, } as const const OPENAI_O3_MINI_BATCH = { @@ -10943,18 +6995,6 @@ const OPENAI_O3_MINI_BATCH = { }, context_window: 200000, max_output_tokens: 100000, - pricing: { - text: { - input: { - normal: 0.55, - cached: 0.275, - }, - output: { - normal: 2.2, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const OPENAI_O3_PRO = { @@ -10973,18 +7013,6 @@ const OPENAI_O3_PRO = { }, context_window: 200000, max_output_tokens: 100000, - pricing: { - text: { - input: { - normal: 20, - cached: 0, - }, - output: { - normal: 80, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const OPENAI_O3_BATCH = { @@ -11003,18 +7031,6 @@ const OPENAI_O3_BATCH = { }, context_window: 200000, max_output_tokens: 100000, - pricing: { - text: { - input: { - normal: 1, - cached: 0.25, - }, - output: { - normal: 4, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const OPENAI_O4_MINI = { @@ -11033,18 +7049,6 @@ const OPENAI_O4_MINI = { }, context_window: 200000, max_output_tokens: 100000, - pricing: { - text: { - input: { - normal: 1.1, - cached: 0.275, - }, - output: { - normal: 4.4, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const OPENAI_O4_MINI_HIGH = { @@ -11063,18 +7067,6 @@ const OPENAI_O4_MINI_HIGH = { }, context_window: 200000, max_output_tokens: 100000, - pricing: { - text: { - input: { - normal: 1.1, - cached: 0.275, - }, - output: { - normal: 4.4, - }, - }, - image: 0, - }, reasoning: EFFORT_HIGH, } as const const OPENAI_O4_MINI_BATCH = { @@ -11093,18 +7085,6 @@ const OPENAI_O4_MINI_BATCH = { }, context_window: 200000, max_output_tokens: 100000, - pricing: { - text: { - input: { - normal: 0.55, - cached: 0.1375, - }, - output: { - normal: 2.2, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const PERCEPTRON_PERCEPTRON_MK1 = { @@ -11124,18 +7104,6 @@ const PERCEPTRON_PERCEPTRON_MK1 = { }, context_window: 32768, max_output_tokens: 8192, - pricing: { - text: { - input: { - normal: 0.15, - cached: 0, - }, - output: { - normal: 1.5, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const PERCEPTRON_PERCEPTRON_MK1_5 = { @@ -11156,18 +7124,6 @@ const PERCEPTRON_PERCEPTRON_MK1_5 = { }, context_window: 36864, max_output_tokens: 8192, - pricing: { - text: { - input: { - normal: 0.15, - cached: 0, - }, - output: { - normal: 1.5, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_MINIMAL_TO_HIGH, } as const const PERPLEXITY_SONAR = { @@ -11186,18 +7142,6 @@ const PERPLEXITY_SONAR = { }, context_window: 127072, max_output_tokens: 114364, - pricing: { - text: { - input: { - normal: 1, - cached: 0, - }, - output: { - normal: 1, - }, - }, - image: 0, - }, } as const const PERPLEXITY_SONAR_DEEP_RESEARCH = { id: 'perplexity/sonar-deep-research', @@ -11216,18 +7160,6 @@ const PERPLEXITY_SONAR_DEEP_RESEARCH = { }, context_window: 128000, max_output_tokens: 115200, - pricing: { - text: { - input: { - normal: 2, - cached: 0, - }, - output: { - normal: 8, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const PERPLEXITY_SONAR_PRO = { @@ -11246,18 +7178,6 @@ const PERPLEXITY_SONAR_PRO = { }, context_window: 200000, max_output_tokens: 8000, - pricing: { - text: { - input: { - normal: 3, - cached: 0, - }, - output: { - normal: 15, - }, - }, - image: 0, - }, } as const const PERPLEXITY_SONAR_PRO_SEARCH = { id: 'perplexity/sonar-pro-search', @@ -11276,18 +7196,6 @@ const PERPLEXITY_SONAR_PRO_SEARCH = { }, context_window: 200000, max_output_tokens: 8000, - pricing: { - text: { - input: { - normal: 3, - cached: 0, - }, - output: { - normal: 15, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const PERPLEXITY_SONAR_REASONING_PRO = { @@ -11307,18 +7215,6 @@ const PERPLEXITY_SONAR_REASONING_PRO = { }, context_window: 128000, max_output_tokens: 115200, - pricing: { - text: { - input: { - normal: 2, - cached: 0, - }, - output: { - normal: 8, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const POOLSIDE_LAGUNA_S_2_1 = { @@ -11331,18 +7227,6 @@ const POOLSIDE_LAGUNA_S_2_1 = { }, context_window: 1048576, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 0.09, - cached: 0.009, - }, - output: { - normal: 0.18, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const POOLSIDE_LAGUNA_S_2_1_FREE = { @@ -11355,18 +7239,6 @@ const POOLSIDE_LAGUNA_S_2_1_FREE = { }, context_window: 262144, max_output_tokens: 32768, - pricing: { - text: { - input: { - normal: 0, - cached: 0, - }, - output: { - normal: 0, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const POOLSIDE_LAGUNA_XS_2_1 = { @@ -11379,18 +7251,6 @@ const POOLSIDE_LAGUNA_XS_2_1 = { }, context_window: 262144, max_output_tokens: 32768, - pricing: { - text: { - input: { - normal: 0.06, - cached: 0.03, - }, - output: { - normal: 0.12, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const POOLSIDE_LAGUNA_XS_2_1_FREE = { @@ -11403,18 +7263,6 @@ const POOLSIDE_LAGUNA_XS_2_1_FREE = { }, context_window: 262144, max_output_tokens: 32768, - pricing: { - text: { - input: { - normal: 0, - cached: 0, - }, - output: { - normal: 0, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const PRISM_ML_TERNARY_BONSAI_2_27B = { @@ -11440,18 +7288,6 @@ const PRISM_ML_TERNARY_BONSAI_2_27B = { }, context_window: 262144, max_output_tokens: 32768, - pricing: { - text: { - input: { - normal: 0.075, - cached: 0.0375, - }, - output: { - normal: 0.5, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_MEDIUM_XHIGH, } as const const QWEN_QWEN_2_5_72B_INSTRUCT = { @@ -11475,18 +7311,6 @@ const QWEN_QWEN_2_5_72B_INSTRUCT = { }, context_window: 32768, max_output_tokens: 16384, - pricing: { - text: { - input: { - normal: 0.36, - cached: 0, - }, - output: { - normal: 0.4, - }, - }, - image: 0, - }, } as const const QWEN_QWEN_2_5_7B_INSTRUCT = { id: 'qwen/qwen-2.5-7b-instruct', @@ -11508,18 +7332,6 @@ const QWEN_QWEN_2_5_7B_INSTRUCT = { }, context_window: 32768, max_output_tokens: 29491, - pricing: { - text: { - input: { - normal: 0.1, - cached: 0, - }, - output: { - normal: 0.2, - }, - }, - image: 0, - }, } as const const QWEN_QWEN_2_5_CODER_32B_INSTRUCT = { id: 'qwen/qwen-2.5-coder-32b-instruct', @@ -11541,18 +7353,6 @@ const QWEN_QWEN_2_5_CODER_32B_INSTRUCT = { }, context_window: 32768, max_output_tokens: 29491, - pricing: { - text: { - input: { - normal: 0.66, - cached: 0, - }, - output: { - normal: 1, - }, - }, - image: 0, - }, } as const const QWEN_QWEN_PLUS = { id: 'qwen/qwen-plus', @@ -11576,18 +7376,6 @@ const QWEN_QWEN_PLUS = { }, context_window: 1000000, max_output_tokens: 32768, - pricing: { - text: { - input: { - normal: 0.26, - cached: 0.377, - }, - output: { - normal: 0.78, - }, - }, - image: 0, - }, } as const const QWEN_QWEN2_5_VL_72B_INSTRUCT = { id: 'qwen/qwen2.5-vl-72b-instruct', @@ -11611,18 +7399,6 @@ const QWEN_QWEN2_5_VL_72B_INSTRUCT = { }, context_window: 128000, max_output_tokens: 115200, - pricing: { - text: { - input: { - normal: 0.8, - cached: 0.4, - }, - output: { - normal: 1, - }, - }, - image: 0, - }, } as const const QWEN_QWEN3_14B = { id: 'qwen/qwen3-14b', @@ -11648,18 +7424,6 @@ const QWEN_QWEN3_14B = { }, context_window: 40960, max_output_tokens: 16384, - pricing: { - text: { - input: { - normal: 0.12, - cached: 0, - }, - output: { - normal: 0.24, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const QWEN_QWEN3_235B_A22B_2507 = { @@ -11685,18 +7449,6 @@ const QWEN_QWEN3_235B_A22B_2507 = { }, context_window: 262144, max_output_tokens: 16384, - pricing: { - text: { - input: { - normal: 0.09, - cached: 0, - }, - output: { - normal: 0.55, - }, - }, - image: 0, - }, } as const const QWEN_QWEN3_235B_A22B_THINKING_2507 = { id: 'qwen/qwen3-235b-a22b-thinking-2507', @@ -11717,18 +7469,6 @@ const QWEN_QWEN3_235B_A22B_THINKING_2507 = { }, context_window: 128000, max_output_tokens: 16384, - pricing: { - text: { - input: { - normal: 0.45, - cached: 0, - }, - output: { - normal: 3.5, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const QWEN_QWEN3_30B_A3B = { @@ -11753,18 +7493,6 @@ const QWEN_QWEN3_30B_A3B = { }, context_window: 40960, max_output_tokens: 16384, - pricing: { - text: { - input: { - normal: 0.12, - cached: 0, - }, - output: { - normal: 0.5, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const QWEN_QWEN3_30B_A3B_INSTRUCT_2507 = { @@ -11790,18 +7518,6 @@ const QWEN_QWEN3_30B_A3B_INSTRUCT_2507 = { }, context_window: 262144, max_output_tokens: 235929, - pricing: { - text: { - input: { - normal: 0.09, - cached: 0, - }, - output: { - normal: 0.3, - }, - }, - image: 0, - }, } as const const QWEN_QWEN3_32B = { id: 'qwen/qwen3-32b', @@ -11827,18 +7543,6 @@ const QWEN_QWEN3_32B = { }, context_window: 131072, max_output_tokens: 16384, - pricing: { - text: { - input: { - normal: 0.08, - cached: 0, - }, - output: { - normal: 0.28, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const QWEN_QWEN3_CODER = { @@ -11864,18 +7568,6 @@ const QWEN_QWEN3_CODER = { }, context_window: 262144, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0.3, - cached: 0.1, - }, - output: { - normal: 1, - }, - }, - image: 0, - }, } as const const QWEN_QWEN3_CODER_30B_A3B_INSTRUCT = { id: 'qwen/qwen3-coder-30b-a3b-instruct', @@ -11895,18 +7587,6 @@ const QWEN_QWEN3_CODER_30B_A3B_INSTRUCT = { }, context_window: 262144, max_output_tokens: 235929, - pricing: { - text: { - input: { - normal: 0.07, - cached: 0, - }, - output: { - normal: 0.28, - }, - }, - image: 0, - }, } as const const QWEN_QWEN3_CODER_FLASH = { id: 'qwen/qwen3-coder-flash', @@ -11930,18 +7610,6 @@ const QWEN_QWEN3_CODER_FLASH = { }, context_window: 1000000, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0.195, - cached: 0.28275, - }, - output: { - normal: 0.975, - }, - }, - image: 0, - }, } as const const QWEN_QWEN3_CODER_NEXT = { id: 'qwen/qwen3-coder-next', @@ -11966,18 +7634,6 @@ const QWEN_QWEN3_CODER_NEXT = { }, context_window: 262144, max_output_tokens: 235929, - pricing: { - text: { - input: { - normal: 0.12, - cached: 0.07, - }, - output: { - normal: 0.8, - }, - }, - image: 0, - }, } as const const QWEN_QWEN3_NEXT_80B_A3B_INSTRUCT = { id: 'qwen/qwen3-next-80b-a3b-instruct', @@ -12002,18 +7658,6 @@ const QWEN_QWEN3_NEXT_80B_A3B_INSTRUCT = { }, context_window: 262144, max_output_tokens: 16384, - pricing: { - text: { - input: { - normal: 0.09, - cached: 0, - }, - output: { - normal: 1.1, - }, - }, - image: 0, - }, } as const const QWEN_QWEN3_NEXT_80B_A3B_THINKING = { id: 'qwen/qwen3-next-80b-a3b-thinking', @@ -12038,18 +7682,6 @@ const QWEN_QWEN3_NEXT_80B_A3B_THINKING = { }, context_window: 262144, max_output_tokens: 235929, - pricing: { - text: { - input: { - normal: 0.15, - cached: 0, - }, - output: { - normal: 1.2, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const QWEN_QWEN3_VL_235B_A22B_INSTRUCT = { @@ -12075,18 +7707,6 @@ const QWEN_QWEN3_VL_235B_A22B_INSTRUCT = { }, context_window: 262144, max_output_tokens: 32768, - pricing: { - text: { - input: { - normal: 0.21, - cached: 0.1, - }, - output: { - normal: 1.9, - }, - }, - image: 0, - }, } as const const QWEN_QWEN3_VL_30B_A3B_INSTRUCT = { id: 'qwen/qwen3-vl-30b-a3b-instruct', @@ -12111,18 +7731,6 @@ const QWEN_QWEN3_VL_30B_A3B_INSTRUCT = { }, context_window: 262144, max_output_tokens: 16384, - pricing: { - text: { - input: { - normal: 0.15, - cached: 0, - }, - output: { - normal: 0.6, - }, - }, - image: 0, - }, } as const const QWEN_QWEN3_VL_30B_A3B_THINKING = { id: 'qwen/qwen3-vl-30b-a3b-thinking', @@ -12142,18 +7750,6 @@ const QWEN_QWEN3_VL_30B_A3B_THINKING = { }, context_window: 262144, max_output_tokens: 235929, - pricing: { - text: { - input: { - normal: 0.29, - cached: 0, - }, - output: { - normal: 1, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const QWEN_QWEN3_VL_8B_INSTRUCT = { @@ -12179,18 +7775,6 @@ const QWEN_QWEN3_VL_8B_INSTRUCT = { }, context_window: 262144, max_output_tokens: 235929, - pricing: { - text: { - input: { - normal: 0.25, - cached: 0.12, - }, - output: { - normal: 0.75, - }, - }, - image: 0, - }, } as const const QWEN_QWEN3_5_122B_A10B = { id: 'qwen/qwen3.5-122b-a10b', @@ -12216,18 +7800,6 @@ const QWEN_QWEN3_5_122B_A10B = { }, context_window: 262144, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0.4, - cached: 0, - }, - output: { - normal: 3.2, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const QWEN_QWEN3_5_27B = { @@ -12254,18 +7826,6 @@ const QWEN_QWEN3_5_27B = { }, context_window: 262144, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0.27, - cached: 0.27, - }, - output: { - normal: 2.16, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const QWEN_QWEN3_5_35B_A3B = { @@ -12292,18 +7852,6 @@ const QWEN_QWEN3_5_35B_A3B = { }, context_window: 262144, max_output_tokens: 81920, - pricing: { - text: { - input: { - normal: 0.14, - cached: 0.05, - }, - output: { - normal: 1, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const QWEN_QWEN3_5_397B_A17B = { @@ -12330,18 +7878,6 @@ const QWEN_QWEN3_5_397B_A17B = { }, context_window: 262144, max_output_tokens: 235929, - pricing: { - text: { - input: { - normal: 0.5, - cached: 0.3, - }, - output: { - normal: 3.6, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const QWEN_QWEN3_5_9B = { @@ -12368,18 +7904,6 @@ const QWEN_QWEN3_5_9B = { }, context_window: 262144, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0.08, - cached: 0.04, - }, - output: { - normal: 0.13, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const QWEN_QWEN3_5_FLASH_02_23 = { @@ -12403,18 +7927,6 @@ const QWEN_QWEN3_5_FLASH_02_23 = { }, context_window: 1000000, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0.065, - cached: 0, - }, - output: { - normal: 0.26, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const QWEN_QWEN3_5_PLUS_02_15 = { @@ -12440,18 +7952,6 @@ const QWEN_QWEN3_5_PLUS_02_15 = { }, context_window: 1000000, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0.26, - cached: 0, - }, - output: { - normal: 1.56, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const QWEN_QWEN3_5_PLUS_20260420 = { @@ -12477,18 +7977,6 @@ const QWEN_QWEN3_5_PLUS_20260420 = { }, context_window: 1000000, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0.3, - cached: 0.375, - }, - output: { - normal: 1.8, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const QWEN_QWEN3_6_27B = { @@ -12515,18 +8003,6 @@ const QWEN_QWEN3_6_27B = { }, context_window: 262144, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0.25, - cached: 0.025, - }, - output: { - normal: 2, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const QWEN_QWEN3_6_35B_A3B = { @@ -12553,18 +8029,6 @@ const QWEN_QWEN3_6_35B_A3B = { }, context_window: 262144, max_output_tokens: 235929, - pricing: { - text: { - input: { - normal: 0.1, - cached: 0.05, - }, - output: { - normal: 0.95, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const QWEN_QWEN3_6_FLASH = { @@ -12590,18 +8054,6 @@ const QWEN_QWEN3_6_FLASH = { }, context_window: 1000000, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0.1875, - cached: 0.234375, - }, - output: { - normal: 1.125, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const QWEN_QWEN3_6_PLUS = { @@ -12627,18 +8079,6 @@ const QWEN_QWEN3_6_PLUS = { }, context_window: 1000000, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0.325, - cached: 0.40625, - }, - output: { - normal: 1.95, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const QWEN_QWEN3_7_FLASH = { @@ -12662,18 +8102,6 @@ const QWEN_QWEN3_7_FLASH = { }, context_window: 1000000, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0.03, - cached: 0.044, - }, - output: { - normal: 0.13, - }, - }, - image: 0, - }, reasoning: BUDGET_OFF_HIGH, } as const const QWEN_QWEN3_7_MAX = { @@ -12699,18 +8127,6 @@ const QWEN_QWEN3_7_MAX = { }, context_window: 1000000, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 1.475, - cached: 2.13875, - }, - output: { - normal: 4.425, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const QWEN_QWEN3_7_PLUS = { @@ -12736,18 +8152,6 @@ const QWEN_QWEN3_7_PLUS = { }, context_window: 1000000, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 0.32, - cached: 0.464, - }, - output: { - normal: 1.28, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const QWEN_QWEN3_7_PLUS_BATCH = { @@ -12773,18 +8177,6 @@ const QWEN_QWEN3_7_PLUS_BATCH = { }, context_window: 262144, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 0.23, - cached: 0, - }, - output: { - normal: 0.92, - }, - }, - image: 0, - }, } as const const QWEN_QWEN3_8_2_4T_A95B = { id: 'qwen/qwen3.8-2.4t-a95b', @@ -12810,18 +8202,6 @@ const QWEN_QWEN3_8_2_4T_A95B = { }, context_window: 1048576, max_output_tokens: 909000, - pricing: { - text: { - input: { - normal: 2, - cached: 0.25, - }, - output: { - normal: 6, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_MEDIUM_XHIGH, } as const const QWEN_QWEN3_8_27B = { @@ -12848,18 +8228,6 @@ const QWEN_QWEN3_8_27B = { }, context_window: 1000000, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0.04, - cached: 0.018, - }, - output: { - normal: 1.35, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_MEDIUM_XHIGH, } as const const QWEN_QWEN3_8_FLASH = { @@ -12885,18 +8253,6 @@ const QWEN_QWEN3_8_FLASH = { }, context_window: 1000000, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 0.15, - cached: 0.016, - }, - output: { - normal: 0.47, - }, - }, - image: 0, - }, reasoning: BUDGET_OFF_HIGH, } as const const QWEN_QWEN3_8_MAX_0902 = { @@ -12922,18 +8278,6 @@ const QWEN_QWEN3_8_MAX_0902 = { }, context_window: 1000000, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 2, - cached: 0.25, - }, - output: { - normal: 6, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_XHIGH, } as const const QWEN_QWEN3_8_MAX_PRIME = { @@ -12959,18 +8303,6 @@ const QWEN_QWEN3_8_MAX_PRIME = { }, context_window: 1000000, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 4, - cached: 0.5, - }, - output: { - normal: 12, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_XHIGH, } as const const QWEN_QWEN3_8_OMNI_FLASH = { @@ -12996,18 +8328,6 @@ const QWEN_QWEN3_8_OMNI_FLASH = { }, context_window: 1000000, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 0.15, - cached: 0.016, - }, - output: { - normal: 0.47, - }, - }, - image: 0, - }, reasoning: BUDGET_OFF_HIGH, } as const const RECURSIVE_FLINT_V1_0_FREE = { @@ -13030,18 +8350,6 @@ const RECURSIVE_FLINT_V1_0_FREE = { }, context_window: 262144, max_output_tokens: 235929, - pricing: { - text: { - input: { - normal: 0, - cached: 0, - }, - output: { - normal: 0, - }, - }, - image: 0, - }, } as const const REFLECTION_BEAM_1_0_501B_A23B = { id: 'reflection/beam-1.0-501b-a23b', @@ -13067,18 +8375,6 @@ const REFLECTION_BEAM_1_0_501B_A23B = { }, context_window: 1048576, max_output_tokens: 943718, - pricing: { - text: { - input: { - normal: 0.3, - cached: 0.04, - }, - output: { - normal: 1, - }, - }, - image: 0, - }, } as const const REKAAI_REKA_EDGE = { id: 'rekaai/reka-edge', @@ -13101,18 +8397,6 @@ const REKAAI_REKA_EDGE = { }, context_window: 16384, max_output_tokens: 14745, - pricing: { - text: { - input: { - normal: 0.1, - cached: 0, - }, - output: { - normal: 0.1, - }, - }, - image: 0, - }, } as const const REKAAI_REKA_FLASH_3 = { id: 'rekaai/reka-flash-3', @@ -13135,18 +8419,6 @@ const REKAAI_REKA_FLASH_3 = { }, context_window: 65536, max_output_tokens: 58982, - pricing: { - text: { - input: { - normal: 0.1, - cached: 0, - }, - output: { - normal: 0.2, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const RELACE_RELACE_APPLY_3 = { @@ -13159,18 +8431,6 @@ const RELACE_RELACE_APPLY_3 = { }, context_window: 256000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 0.85, - cached: 0, - }, - output: { - normal: 1.25, - }, - }, - image: 0, - }, } as const const RELACE_RELACE_SEARCH = { id: 'relace/relace-search', @@ -13190,18 +8450,6 @@ const RELACE_RELACE_SEARCH = { }, context_window: 256000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 1, - cached: 0, - }, - output: { - normal: 3, - }, - }, - image: 0, - }, } as const const SAKANA_FUGU_MAX = { id: 'sakana/fugu-max', @@ -13213,18 +8461,6 @@ const SAKANA_FUGU_MAX = { }, context_window: 1000000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 2, - cached: 0.25, - }, - output: { - normal: 6, - }, - }, - image: 0, - }, reasoning: EFFORT_HIGH_TO_MAX, } as const const SAKANA_FUGU_ULTRA = { @@ -13237,18 +8473,6 @@ const SAKANA_FUGU_ULTRA = { }, context_window: 1000000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 5, - cached: 0.5, - }, - output: { - normal: 30, - }, - }, - image: 0, - }, reasoning: EFFORT_HIGH_TO_MAX, } as const const SAKANA_FUGU_ULTRA_V2 = { @@ -13261,18 +8485,6 @@ const SAKANA_FUGU_ULTRA_V2 = { }, context_window: 1000000, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 5, - cached: 0.5, - }, - output: { - normal: 30, - }, - }, - image: 0, - }, reasoning: EFFORT_HIGH_TO_MAX, } as const const SAKANA_SAKANA_NAMAZU = { @@ -13285,18 +8497,6 @@ const SAKANA_SAKANA_NAMAZU = { }, context_window: 262144, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0.95, - cached: 0.15, - }, - output: { - normal: 4, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_HIGH, } as const const SAO10K_L3_LUNARIS_8B = { @@ -13321,18 +8521,6 @@ const SAO10K_L3_LUNARIS_8B = { }, context_window: 8192, max_output_tokens: 7372, - pricing: { - text: { - input: { - normal: 0.04, - cached: 0, - }, - output: { - normal: 0.05, - }, - }, - image: 0, - }, } as const const SAO10K_L3_1_EURYALE_70B = { id: 'sao10k/l3.1-euryale-70b', @@ -13353,18 +8541,6 @@ const SAO10K_L3_1_EURYALE_70B = { }, context_window: 131072, max_output_tokens: 16384, - pricing: { - text: { - input: { - normal: 0.85, - cached: 0, - }, - output: { - normal: 0.85, - }, - }, - image: 0, - }, } as const const SCALEDOWN_EXTRACT = { id: 'scaledown/extract', @@ -13376,18 +8552,6 @@ const SCALEDOWN_EXTRACT = { }, context_window: 1000000, max_output_tokens: 900000, - pricing: { - text: { - input: { - normal: 0.04, - cached: 0, - }, - output: { - normal: 0, - }, - }, - image: 0, - }, } as const const SCALEDOWN_SUMMARIZE = { id: 'scaledown/summarize', @@ -13399,18 +8563,6 @@ const SCALEDOWN_SUMMARIZE = { }, context_window: 1000000, max_output_tokens: 4000, - pricing: { - text: { - input: { - normal: 0.04, - cached: 0, - }, - output: { - normal: 0, - }, - }, - image: 0, - }, } as const const STEPFUN_STEP_3_5_FLASH = { id: 'stepfun/step-3.5-flash', @@ -13429,18 +8581,6 @@ const STEPFUN_STEP_3_5_FLASH = { }, context_window: 262144, max_output_tokens: 65536, - pricing: { - text: { - input: { - normal: 0.1, - cached: 0, - }, - output: { - normal: 0.3, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const STEPFUN_STEP_3_7_FLASH = { @@ -13466,18 +8606,6 @@ const STEPFUN_STEP_3_7_FLASH = { }, context_window: 262144, max_output_tokens: 230400, - pricing: { - text: { - input: { - normal: 0.2, - cached: 0.04, - }, - output: { - normal: 1.15, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_HIGH, } as const const STEPFUN_STEP_5_PREVIEW = { @@ -13504,18 +8632,6 @@ const STEPFUN_STEP_5_PREVIEW = { }, context_window: 1048576, max_output_tokens: 64000, - pricing: { - text: { - input: { - normal: 1, - cached: 0.1, - }, - output: { - normal: 2.7, - }, - }, - image: 0, - }, } as const const TENCENT_HUNYUAN_A13B_INSTRUCT = { id: 'tencent/hunyuan-a13b-instruct', @@ -13534,18 +8650,6 @@ const TENCENT_HUNYUAN_A13B_INSTRUCT = { }, context_window: 131072, max_output_tokens: 117964, - pricing: { - text: { - input: { - normal: 0.14, - cached: 0, - }, - output: { - normal: 0.57, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const TENCENT_HY_MT2_1_8B = { @@ -13563,18 +8667,6 @@ const TENCENT_HY_MT2_1_8B = { }, context_window: 8192, max_output_tokens: 4096, - pricing: { - text: { - input: { - normal: 0.044, - cached: 0, - }, - output: { - normal: 0.177, - }, - }, - image: 0, - }, } as const const TENCENT_HY_MT2_30B_A3B = { id: 'tencent/hy-mt2-30b-a3b', @@ -13592,18 +8684,6 @@ const TENCENT_HY_MT2_30B_A3B = { }, context_window: 8192, max_output_tokens: 4096, - pricing: { - text: { - input: { - normal: 0.074, - cached: 0, - }, - output: { - normal: 0.295, - }, - }, - image: 0, - }, } as const const TENCENT_HY_MT2_7B = { id: 'tencent/hy-mt2-7b', @@ -13621,18 +8701,6 @@ const TENCENT_HY_MT2_7B = { }, context_window: 8192, max_output_tokens: 4096, - pricing: { - text: { - input: { - normal: 0.074, - cached: 0, - }, - output: { - normal: 0.295, - }, - }, - image: 0, - }, } as const const TENCENT_HY3 = { id: 'tencent/hy3', @@ -13657,18 +8725,6 @@ const TENCENT_HY3 = { }, context_window: 262144, max_output_tokens: 128000, - pricing: { - text: { - input: { - normal: 0.132, - cached: 0.033, - }, - output: { - normal: 0.528, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_HIGH, } as const const TENCENT_HY3_PREVIEW = { @@ -13688,18 +8744,6 @@ const TENCENT_HY3_PREVIEW = { }, context_window: 262144, max_output_tokens: 235929, - pricing: { - text: { - input: { - normal: 0.18, - cached: 0.06, - }, - output: { - normal: 0.6, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_HIGH, } as const const TENCENT_HY4_PREVIEW = { @@ -13725,18 +8769,6 @@ const TENCENT_HY4_PREVIEW = { }, context_window: 1048576, max_output_tokens: 64000, - pricing: { - text: { - input: { - normal: 0.834, - cached: 0.042, - }, - output: { - normal: 2.501, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_HIGH, } as const const THEDRUMMER_CYDONIA_24B_V4_1 = { @@ -13761,18 +8793,6 @@ const THEDRUMMER_CYDONIA_24B_V4_1 = { }, context_window: 131072, max_output_tokens: 117964, - pricing: { - text: { - input: { - normal: 0.3, - cached: 0.15, - }, - output: { - normal: 0.5, - }, - }, - image: 0, - }, } as const const THEDRUMMER_SKYFALL_36B_V2 = { id: 'thedrummer/skyfall-36b-v2', @@ -13796,18 +8816,6 @@ const THEDRUMMER_SKYFALL_36B_V2 = { }, context_window: 32768, max_output_tokens: 29491, - pricing: { - text: { - input: { - normal: 0.55, - cached: 0.25, - }, - output: { - normal: 0.8, - }, - }, - image: 0, - }, } as const const THEDRUMMER_UNSLOPNEMO_12B = { id: 'thedrummer/unslopnemo-12b', @@ -13830,18 +8838,6 @@ const THEDRUMMER_UNSLOPNEMO_12B = { }, context_window: 1024000, max_output_tokens: 819200, - pricing: { - text: { - input: { - normal: 0.4, - cached: 0, - }, - output: { - normal: 0.4, - }, - }, - image: 0, - }, } as const const THINKINGMACHINES_INKLING = { id: 'thinkingmachines/inkling', @@ -13864,18 +8860,6 @@ const THINKINGMACHINES_INKLING = { }, context_window: 524288, max_output_tokens: 471859, - pricing: { - text: { - input: { - normal: 1, - cached: 0.17, - }, - output: { - normal: 4.05, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_MINIMAL_TO_HIGH_MAX, } as const const THINKINGMACHINES_INKLING_SMALL = { @@ -13899,18 +8883,6 @@ const THINKINGMACHINES_INKLING_SMALL = { }, context_window: 524288, max_output_tokens: 262144, - pricing: { - text: { - input: { - normal: 0.45, - cached: 0.1, - }, - output: { - normal: 1.2, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_MINIMAL_TO_HIGH_MAX, } as const const THINKINGMACHINES_INKLING_SMALL_FREE = { @@ -13932,18 +8904,6 @@ const THINKINGMACHINES_INKLING_SMALL_FREE = { }, context_window: 1048576, max_output_tokens: 262144, - pricing: { - text: { - input: { - normal: 0, - cached: 0, - }, - output: { - normal: 0, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_MINIMAL_TO_HIGH_MAX, } as const const THINKINGMACHINES_INKLING_FREE = { @@ -13965,18 +8925,6 @@ const THINKINGMACHINES_INKLING_FREE = { }, context_window: 1048576, max_output_tokens: 262144, - pricing: { - text: { - input: { - normal: 0, - cached: 0, - }, - output: { - normal: 0, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_MINIMAL_TO_HIGH_MAX, } as const const UNBIASED_PARETO_26_10 = { @@ -13989,18 +8937,6 @@ const UNBIASED_PARETO_26_10 = { }, context_window: 1048576, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 0.8, - cached: 0.03, - }, - output: { - normal: 3.2, - }, - }, - image: 0, - }, } as const const UNBIASED_PARETO_26_9 = { id: 'unbiased/pareto-26.9', @@ -14018,18 +8954,6 @@ const UNBIASED_PARETO_26_9 = { }, context_window: 262144, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 2.5, - cached: 0.25, - }, - output: { - normal: 7.5, - }, - }, - image: 0, - }, } as const const UNDI95_REMM_SLERP_L2_13B = { id: 'undi95/remm-slerp-l2-13b', @@ -14053,18 +8977,6 @@ const UNDI95_REMM_SLERP_L2_13B = { }, context_window: 6144, max_output_tokens: 5529, - pricing: { - text: { - input: { - normal: 0.35, - cached: 0, - }, - output: { - normal: 0.65, - }, - }, - image: 0, - }, } as const const UPSTAGE_SOLAR_MINI4 = { id: 'upstage/solar-mini4', @@ -14086,18 +8998,6 @@ const UPSTAGE_SOLAR_MINI4 = { }, context_window: 524288, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 0.05, - cached: 0.005, - }, - output: { - normal: 0.2, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_MINIMAL_TO_MAX, } as const const UPSTAGE_SOLAR_PRO_3 = { @@ -14120,18 +9020,6 @@ const UPSTAGE_SOLAR_PRO_3 = { }, context_window: 131072, max_output_tokens: 117964, - pricing: { - text: { - input: { - normal: 0.15, - cached: 0.015, - }, - output: { - normal: 0.6, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_MINIMAL_TO_HIGH, } as const const UPSTAGE_SOLAR_PRO4 = { @@ -14154,18 +9042,6 @@ const UPSTAGE_SOLAR_PRO4 = { }, context_window: 524288, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 0.15, - cached: 0.03, - }, - output: { - normal: 0.6, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_MINIMAL_TO_MAX, } as const const WRITER_PALMYRA_X5 = { @@ -14178,18 +9054,6 @@ const WRITER_PALMYRA_X5 = { }, context_window: 1040000, max_output_tokens: 8192, - pricing: { - text: { - input: { - normal: 0.6, - cached: 0, - }, - output: { - normal: 6, - }, - }, - image: 0, - }, } as const const X_AI_GROK_4_20 = { id: 'x-ai/grok-4.20', @@ -14211,18 +9075,6 @@ const X_AI_GROK_4_20 = { }, context_window: 2000000, max_output_tokens: 1800000, - pricing: { - text: { - input: { - normal: 1.25, - cached: 0.2, - }, - output: { - normal: 2.5, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const X_AI_GROK_4_20_MULTI_AGENT = { @@ -14244,18 +9096,6 @@ const X_AI_GROK_4_20_MULTI_AGENT = { }, context_window: 2000000, max_output_tokens: 1800000, - pricing: { - text: { - input: { - normal: 1.25, - cached: 0.2, - }, - output: { - normal: 2.5, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_XHIGH, } as const const X_AI_GROK_4_3 = { @@ -14278,18 +9118,6 @@ const X_AI_GROK_4_3 = { }, context_window: 1000000, max_output_tokens: 900000, - pricing: { - text: { - input: { - normal: 1.25, - cached: 0.2, - }, - output: { - normal: 2.5, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_HIGH, } as const const X_AI_GROK_4_3_BATCH = { @@ -14312,18 +9140,6 @@ const X_AI_GROK_4_3_BATCH = { }, context_window: 1000000, max_output_tokens: 900000, - pricing: { - text: { - input: { - normal: 1, - cached: 0.16, - }, - output: { - normal: 2, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_LOW_TO_HIGH, } as const const X_AI_GROK_4_5 = { @@ -14346,18 +9162,6 @@ const X_AI_GROK_4_5 = { }, context_window: 500000, max_output_tokens: 450000, - pricing: { - text: { - input: { - normal: 2, - cached: 0.3, - }, - output: { - normal: 6, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_HIGH, } as const const X_AI_GROK_4_6 = { @@ -14381,18 +9185,6 @@ const X_AI_GROK_4_6 = { }, context_window: 500000, max_output_tokens: 450000, - pricing: { - text: { - input: { - normal: 2, - cached: 0.5, - }, - output: { - normal: 6, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_XHIGH, } as const const X_AI_GROK_4_7 = { @@ -14415,18 +9207,6 @@ const X_AI_GROK_4_7 = { }, context_window: 500000, max_output_tokens: 450000, - pricing: { - text: { - input: { - normal: 2, - cached: 0.5, - }, - output: { - normal: 6, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_TO_XHIGH, } as const const X_AI_GROK_BUILD_0_1 = { @@ -14449,18 +9229,6 @@ const X_AI_GROK_BUILD_0_1 = { }, context_window: 256000, max_output_tokens: 230400, - pricing: { - text: { - input: { - normal: 1, - cached: 0.2, - }, - output: { - normal: 2, - }, - }, - image: 0, - }, reasoning: EFFORT_MINIMAL_TO_HIGH, } as const const XIAOMI_MIMO_V2_5 = { @@ -14484,18 +9252,6 @@ const XIAOMI_MIMO_V2_5 = { }, context_window: 1050000, max_output_tokens: 945000, - pricing: { - text: { - input: { - normal: 0.119, - cached: 0.00255, - }, - output: { - normal: 0.238, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const XIAOMI_MIMO_V2_5_PRO = { @@ -14521,18 +9277,6 @@ const XIAOMI_MIMO_V2_5_PRO = { }, context_window: 1050000, max_output_tokens: 945000, - pricing: { - text: { - input: { - normal: 0.3045, - cached: 0.0028, - }, - output: { - normal: 0.609, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const XIAOMI_MIMO_V2_6_FLASH = { @@ -14559,18 +9303,6 @@ const XIAOMI_MIMO_V2_6_FLASH = { }, context_window: 1050000, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 0.14, - cached: 0.0028, - }, - output: { - normal: 0.28, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const XIAOMI_MIMO_V2_6_PRO = { @@ -14595,18 +9327,6 @@ const XIAOMI_MIMO_V2_6_PRO = { }, context_window: 1050000, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 0.435, - cached: 0.0036, - }, - output: { - normal: 0.87, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const XIAOMI_MIMO_V2_6_PRO_ULTRASPEED = { @@ -14629,18 +9349,6 @@ const XIAOMI_MIMO_V2_6_PRO_ULTRASPEED = { }, context_window: 1048576, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 4.35, - cached: 0.036, - }, - output: { - normal: 8.7, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const XINGCHEN_AGI_XING4_0_29B_A4B_FREE = { @@ -14664,18 +9372,6 @@ const XINGCHEN_AGI_XING4_0_29B_A4B_FREE = { }, context_window: 262144, max_output_tokens: 235929, - pricing: { - text: { - input: { - normal: 0, - cached: 0, - }, - output: { - normal: 0, - }, - }, - image: 0, - }, } as const const Z_AI_GLM_4_5 = { id: 'z-ai/glm-4.5', @@ -14694,18 +9390,6 @@ const Z_AI_GLM_4_5 = { }, context_window: 131072, max_output_tokens: 98304, - pricing: { - text: { - input: { - normal: 0.6, - cached: 0.11, - }, - output: { - normal: 2.2, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const Z_AI_GLM_4_5_AIR = { @@ -14728,18 +9412,6 @@ const Z_AI_GLM_4_5_AIR = { }, context_window: 131072, max_output_tokens: 98304, - pricing: { - text: { - input: { - normal: 0.13, - cached: 0.025, - }, - output: { - normal: 0.85, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const Z_AI_GLM_4_5V = { @@ -14763,18 +9435,6 @@ const Z_AI_GLM_4_5V = { }, context_window: 65536, max_output_tokens: 16384, - pricing: { - text: { - input: { - normal: 0.6, - cached: 0.11, - }, - output: { - normal: 1.8, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const Z_AI_GLM_4_6 = { @@ -14799,18 +9459,6 @@ const Z_AI_GLM_4_6 = { }, context_window: 204800, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 0.55, - cached: 0.11, - }, - output: { - normal: 2.2, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const Z_AI_GLM_4_6V = { @@ -14834,18 +9482,6 @@ const Z_AI_GLM_4_6V = { }, context_window: 131072, max_output_tokens: 32768, - pricing: { - text: { - input: { - normal: 0.3, - cached: 0.055, - }, - output: { - normal: 0.9, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const Z_AI_GLM_4_7 = { @@ -14870,18 +9506,6 @@ const Z_AI_GLM_4_7 = { }, context_window: 204800, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 0.54, - cached: 0.099, - }, - output: { - normal: 1.98, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const Z_AI_GLM_4_7_FLASH = { @@ -14908,18 +9532,6 @@ const Z_AI_GLM_4_7_FLASH = { }, context_window: 200000, max_output_tokens: 117964, - pricing: { - text: { - input: { - normal: 0.0605, - cached: 0, - }, - output: { - normal: 0.4, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const Z_AI_GLM_5 = { @@ -14945,18 +9557,6 @@ const Z_AI_GLM_5 = { }, context_window: 204800, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 1, - cached: 0.2, - }, - output: { - normal: 3.2, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const Z_AI_GLM_5_TURBO = { @@ -14976,18 +9576,6 @@ const Z_AI_GLM_5_TURBO = { }, context_window: 202752, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 1.2, - cached: 0.24, - }, - output: { - normal: 4, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const Z_AI_GLM_5_1 = { @@ -15014,18 +9602,6 @@ const Z_AI_GLM_5_1 = { }, context_window: 204800, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 1.4, - cached: 0.26, - }, - output: { - normal: 4.4, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const const Z_AI_GLM_5_2 = { @@ -15053,18 +9629,6 @@ const Z_AI_GLM_5_2 = { }, context_window: 1048576, max_output_tokens: 943718, - pricing: { - text: { - input: { - normal: 0.0341, - cached: 0.033, - }, - output: { - normal: 7, - }, - }, - image: 0, - }, reasoning: EFFORT_NONE_HIGH_XHIGH, } as const const Z_AI_GLM_5_3 = { @@ -15092,18 +9656,6 @@ const Z_AI_GLM_5_3 = { }, context_window: 1048576, max_output_tokens: 943718, - pricing: { - text: { - input: { - normal: 0.079, - cached: 0.078, - }, - output: { - normal: 1.4, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_HIGH_MAX, } as const const Z_AI_GLM_5_3_FLASH = { @@ -15131,18 +9683,6 @@ const Z_AI_GLM_5_3_FLASH = { }, context_window: 1048576, max_output_tokens: 943718, - pricing: { - text: { - input: { - normal: 0.0052, - cached: 0.0052, - }, - output: { - normal: 0.1985, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_HIGH_MAX, } as const const Z_AI_GLM_5_3_FLASH_BATCH = { @@ -15169,18 +9709,6 @@ const Z_AI_GLM_5_3_FLASH_BATCH = { }, context_window: 1048576, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 0.05, - cached: 0.01, - }, - output: { - normal: 0.18, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_HIGH_MAX, } as const const Z_AI_GLM_5_3_FLASHX = { @@ -15200,18 +9728,6 @@ const Z_AI_GLM_5_3_FLASHX = { }, context_window: 1048576, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 0.37, - cached: 0.09, - }, - output: { - normal: 1.25, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_HIGH_MAX, } as const const Z_AI_GLM_5_3_PRIME = { @@ -15237,18 +9753,6 @@ const Z_AI_GLM_5_3_PRIME = { }, context_window: 1000000, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 2.8, - cached: 0.56, - }, - output: { - normal: 8.8, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_HIGH_MAX, } as const const Z_AI_GLM_5_3_BATCH = { @@ -15273,18 +9777,6 @@ const Z_AI_GLM_5_3_BATCH = { }, context_window: 1048576, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 0.45, - cached: 0.1, - }, - output: { - normal: 2, - }, - }, - image: 0, - }, reasoning: EFFORT_LOW_HIGH_MAX, } as const const Z_AI_GLM_5V_TURBO = { @@ -15304,18 +9796,6 @@ const Z_AI_GLM_5V_TURBO = { }, context_window: 202752, max_output_tokens: 131072, - pricing: { - text: { - input: { - normal: 1.2, - cached: 0.24, - }, - output: { - normal: 4, - }, - }, - image: 0, - }, reasoning: EFFORT_OFF_HIGH, } as const diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cb2f1b2686..4b99c35337 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -28,6 +28,9 @@ importers: '@faker-js/faker': specifier: ^10.1.0 version: 10.1.0 + '@modelschemas/client': + specifier: ^0.2.1 + version: 0.2.1 '@stylistic/eslint-plugin': specifier: ^5.10.0 version: 5.10.0(eslint@9.39.4(jiti@2.7.0)) @@ -3745,7 +3748,7 @@ importers: devDependencies: '@google/genai': specifier: ^2.10.0 - version: 2.10.0(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.3.6)) + version: 2.10.0(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.6.5)) '@tanstack/ai': specifier: workspace:* version: link:../ai @@ -6945,6 +6948,9 @@ packages: resolution: {integrity: sha512-FdvwZU5N03O77Suh35JqjAqq5R1ZTEPFtwu6N4BgBq28qrQtrCnpbLL5U2pwYCuE194jAw0xnlOVmIqhfoYuUQ==} engines: {node: '>=20'} + '@modelschemas/client@0.2.1': + resolution: {integrity: sha512-y1055MBmvtHS9r3j0YnTAeP13AYNbZPwHvUeywMrNahGdm+mtTgi8FGDu8QFZ3hcF1gLu8h3qWtaGrFT/K7aIg==} + '@msgpack/msgpack@3.1.3': resolution: {integrity: sha512-47XIizs9XZXvuJgoaJUIE2lFoID8ugvc0jzSHP+Ptfk8nTbnR8g788wv48N03Kx0UkAv559HWRQ3yzOgzlRNUA==} engines: {node: '>= 18'} @@ -22720,6 +22726,19 @@ snapshots: - supports-color - utf-8-validate + '@google/genai@2.10.0(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.6.5))': + dependencies: + google-auth-library: 10.5.0 + p-retry: 4.6.2 + protobufjs: 7.6.4 + ws: 8.21.0 + optionalDependencies: + '@modelcontextprotocol/sdk': 1.29.0(@cfworker/json-schema@4.1.1)(zod@4.6.5) + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + '@graphql-typed-document-node/core@3.2.0(graphql@16.14.2)': dependencies: graphql: 16.14.2 @@ -23297,11 +23316,38 @@ snapshots: transitivePeerDependencies: - supports-color + '@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.6.5)': + dependencies: + '@hono/node-server': 1.19.17(hono@4.13.8) + ajv: 8.20.0 + ajv-formats: 3.0.1(ajv@8.20.0) + content-type: 1.0.5 + cors: 2.8.6 + cross-spawn: 7.0.6 + eventsource: 3.0.7 + eventsource-parser: 3.1.1 + express: 5.2.1 + express-rate-limit: 8.7.0(express@5.2.1)(supports-color@7.2.0) + hono: 4.13.8 + jose: 6.2.12 + json-schema-typed: 8.0.2 + pkce-challenge: 5.0.1 + raw-body: 3.0.2 + zod: 4.6.5 + zod-to-json-schema: 3.25.2(zod@4.6.5) + optionalDependencies: + '@cfworker/json-schema': 4.1.1 + transitivePeerDependencies: + - supports-color + optional: true + '@modelcontextprotocol/server@2.1.0': dependencies: '@modelcontextprotocol/core': 2.1.0 zod: 4.3.6 + '@modelschemas/client@0.2.1': {} + '@msgpack/msgpack@3.1.3': {} '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.4': diff --git a/scripts/convert-openrouter-models.ts b/scripts/convert-openrouter-models.ts index 5af4cc99e2..e36591a5de 100644 --- a/scripts/convert-openrouter-models.ts +++ b/scripts/convert-openrouter-models.ts @@ -47,21 +47,6 @@ function mapInputModality(modality: string): InputModality | null { return mapping[modality.toLowerCase()] || null } -function convertPricing(priceStr: string, isImage: boolean = false): number { - // OpenRouter pricing is typically per token (in dollars) - // Convert to number - const price = parseFloat(priceStr) - if (isImage) { - return isNaN(price) ? 0 : price - } - return finalPrice(isNaN(price) ? 0 : price) -} -function finalPrice(price: number): number { - // Ensure price is non-negative and rounded to avoid floating-point errors - const result = price * 1_000_000 - // Round to a reasonable number of decimal places - return Math.round(result * 1e10) / 1e10 -} const perModelProviderOptions: Record = {} const perModelInputModalities: Record = {} @@ -358,16 +343,6 @@ function generateModelMetaString(model: OpenRouterModel): string { if (outputModalities.includes('video')) { videoModels.add(`${constName}.id`) } - const inputPrice = convertPricing(model.pricing.prompt) - const outputPrice = convertPricing(model.pricing.completion) - const imagePrice = convertPricing(model.pricing.image ?? '0', true) - const inputCacheReadPrice = convertPricing( - model.pricing.input_cache_read ?? '0', - ) - const inputCacheWritePrice = convertPricing( - model.pricing.input_cache_write ?? '0', - ) - const paramNameMap: Record = { max_tokens: 'maxCompletionTokens', frequency_penalty: 'frequencyPenalty', @@ -435,18 +410,6 @@ function generateModelMetaString(model: OpenRouterModel): string { ) } - lines.push(` pricing: {`) - lines.push(` text: {`) - lines.push(` input: {`) - lines.push(` normal: ${inputPrice},`) - lines.push(` cached: ${inputCacheReadPrice + inputCacheWritePrice},`) - lines.push(` },`) - lines.push(` output: {`) - lines.push(` normal: ${outputPrice},`) - lines.push(` },`) - lines.push(` },`) - lines.push(` image: ${imagePrice},`) - lines.push(` },`) const reasoning = existingReasoning[model.id] if (reasoning) { lines.push(` reasoning: ${reasoningShapeName(reasoning)},`) diff --git a/scripts/model-sync/catalog.test.ts b/scripts/model-sync/catalog.test.ts new file mode 100644 index 0000000000..79da332d9c --- /dev/null +++ b/scripts/model-sync/catalog.test.ts @@ -0,0 +1,303 @@ +import { describe, expect, it } from 'vitest' +import { + alreadySynced, + hasImageOutput, + outputsText, + parseCatalogModels, + selectNativeInserts, + skipNativeModelReason, + toSyncModel, +} from './catalog' +import type { CatalogModel } from './catalog' + +function native(overrides: Partial = {}): CatalogModel { + return { + provider: 'anthropic', + rawId: 'claude-sonnet-5', + activity: 'chat', + firstSeenAt: 1_780_000_000, + deprecatedAt: null, + contextWindow: null, + maxOutput: null, + inputModalities: ['text'], + outputModalities: ['text'], + capabilities: [], + reasoningMandatory: false, + ...overrides, + } +} + +describe('parseCatalogModels', () => { + it('reads modelschemas listModels payloads and drops rows without rawId', () => { + const models = parseCatalogModels({ + count: 2, + models: [ + { + provider: 'openai', + rawId: 'gpt-5', + activity: 'chat', + contextWindow: 400_000, + maxOutput: 128_000, + modalities: { input: ['text', 'image'], output: ['text'] }, + capabilities: { tools: true, reasoning: true, temperature: false }, + firstSeenAt: 1_754_425_777, + deprecatedAt: null, + }, + { provider: 'openai', activity: 'chat' }, + ], + }) + expect(models).toHaveLength(1) + expect(models[0]).toMatchObject({ + rawId: 'gpt-5', + contextWindow: 400_000, + inputModalities: ['text', 'image'], + capabilities: ['tools', 'reasoning'], + }) + }) + + it('maps BytePlus object capabilities onto supported_parameters', () => { + const models = parseCatalogModels({ + models: [ + { + rawId: 'deepseek-v4-pro-ga-260813', + activity: 'chat', + firstSeenAt: 1_790_000_000, + deprecatedAt: null, + capabilities: { + tools: { function_calling: true }, + structured_outputs: { json_schema: false, json_object: false }, + maxReasoningTokens: 393216, + }, + }, + ], + }) + expect(models[0]?.capabilities).toEqual([ + 'tools', + 'tool_choice', + 'reasoning', + 'include_reasoning', + ]) + }) +}) + +describe('parseCatalogModels drift', () => { + const row = { rawId: 'm', firstSeenAt: 1, deprecatedAt: null } + + it('reads reasoning.mandatory', () => { + const [model] = parseCatalogModels({ + models: [{ ...row, reasoning: { mode: 'adaptive', mandatory: true } }], + }) + expect(model?.reasoningMandatory).toBe(true) + }) + + it('throws when no row has a rawId', () => { + expect(() => parseCatalogModels({ models: [{ id: 'm' }] })).toThrow( + 'none of 1 rows has a rawId', + ) + }) + + it('throws when firstSeenAt is gone, so the age check cannot pass everything', () => { + expect(() => + parseCatalogModels({ models: [{ rawId: 'm', deprecatedAt: null }] }), + ).toThrow('no row has a firstSeenAt') + }) + + it('throws when deprecatedAt is gone, so deprecated rows cannot pass', () => { + expect(() => + parseCatalogModels({ models: [{ rawId: 'm', firstSeenAt: 1 }] }), + ).toThrow('no row has a deprecatedAt key') + }) + + it('accepts an empty models array', () => { + expect(parseCatalogModels({ models: [] })).toEqual([]) + }) +}) + +describe('toSyncModel', () => { + it('takes every field from the native row, and fills nothing', () => { + expect( + toSyncModel( + native({ + rawId: 'grok-5', + provider: 'grok', + contextWindow: 2_000_000, + capabilities: ['tools'], + }), + 'grok', + ), + ).toEqual({ + nativeId: 'grok-5', + contextWindow: 2_000_000, + maxOutput: null, + inputModalities: ['text'], + outputModalities: ['text'], + supportedParameters: ['tools'], + reasoningMandatory: false, + }) + }) +}) + +describe('skipNativeModelReason', () => { + const cutoff = 1_700_000_000 + + it('skips dated Anthropic snapshots, non-chat activity, and old rows', () => { + expect( + skipNativeModelReason( + native({ rawId: 'claude-haiku-4-5-20251001' }), + 'anthropic', + [], + cutoff, + ['chat'], + ), + ).toBe('dated snapshot') + expect( + skipNativeModelReason( + native({ activity: 'image', rawId: 'grok-imagine-image' }), + 'grok', + [], + cutoff, + ['chat'], + ), + ).toBe('activity image') + expect( + skipNativeModelReason( + native({ firstSeenAt: cutoff - 1 }), + 'anthropic', + [], + cutoff, + ['chat'], + ), + ).toBe('too old') + }) + + it('keeps a current chat model', () => { + expect( + skipNativeModelReason(native(), 'anthropic', [], cutoff, ['chat']), + ).toBeNull() + }) + + it('treats transcribe ids as non-chat even when activity is chat', () => { + expect( + skipNativeModelReason( + native({ rawId: 'gemini-3.5-transcribe', provider: 'gemini' }), + 'gemini', + [], + cutoff, + ['chat'], + ), + ).toBe('non-chat family') + }) + + it('skips a row with no input modalities instead of guessing them', () => { + expect( + skipNativeModelReason( + native({ inputModalities: [] }), + 'gemini', + [], + cutoff, + ['chat'], + ), + ).toBe('no modalities') + }) + + it('keeps Groq rows with no activity', () => { + expect( + skipNativeModelReason( + native({ activity: null, rawId: 'qwen/qwen3.8-27b' }), + 'groq', + [], + cutoff, + [null], + ), + ).toBeNull() + }) +}) + +describe('outputsText', () => { + it('treats empty modalities plus unset activity as chat', () => { + const model = toSyncModel( + native({ + activity: null, + rawId: 'qwen/qwen3.8-27b', + outputModalities: [], + }), + 'groq', + ) + expect(outputsText(model, null)).toBe(true) + }) +}) + +describe('selectNativeInserts', () => { + const rules = { + provider: 'anthropic' as const, + skipPatterns: ['claude-legacy-'], + acceptedActivities: ['chat'], + cutoffTimestamp: 0, + } + + it('inserts a new model with no price and no second source', () => { + const selection = selectNativeInserts( + [native({ rawId: 'claude-new-1' })], + rules, + () => false, + ) + expect(selection.inserts.map(({ model }) => model.nativeId)).toEqual([ + 'claude-new-1', + ]) + }) + + it('skips a model that is already in the file', () => { + const selection = selectNativeInserts( + [native({ rawId: 'claude-new-1' })], + rules, + () => true, + ) + expect(selection.skipped).toEqual({ 'already synced': 1 }) + }) + + it('counts every other skip by reason', () => { + const selection = selectNativeInserts( + [ + native({ rawId: 'claude-art-1', outputModalities: ['image'] }), + native({ rawId: 'claude-old-1', deprecatedAt: 1 }), + native({ rawId: 'claude-sonnet-6:thinking' }), + native({ rawId: 'claude-legacy-2' }), + native({ rawId: 'claude-blank-1', inputModalities: [] }), + ], + rules, + () => false, + ) + expect(selection.inserts).toEqual([]) + expect(selection.skipped).toEqual({ + 'image output': 1, + deprecated: 1, + 'routing variant': 1, + 'skip pattern': 1, + 'no modalities': 1, + }) + }) +}) + +describe('hasImageOutput / alreadySynced', () => { + it('treats image activity and image output as image models', () => { + expect(hasImageOutput(native({ activity: 'image' }))).toBe(true) + expect( + hasImageOutput(native({ outputModalities: ['image', 'text'] })), + ).toBe(true) + expect(hasImageOutput(native({ outputModalities: ['text'] }))).toBe(false) + }) + + it('matches existing ids with dots or dashes', () => { + expect( + alreadySynced( + 'claude-sonnet-4.5', + new Set(['claude-sonnet-4-5']), + new Set(), + ), + ).toBe(true) + expect( + alreadySynced('gpt-5.6-luna', new Set(), new Set(['GPT_5_6_LUNA'])), + ).toBe(true) + expect(alreadySynced('gpt-5.6-luna', new Set(), new Set())).toBe(false) + }) +}) diff --git a/scripts/model-sync/catalog.ts b/scripts/model-sync/catalog.ts new file mode 100644 index 0000000000..462806e55e --- /dev/null +++ b/scripts/model-sync/catalog.ts @@ -0,0 +1,293 @@ +/** + * modelschemas catalog rows for native-provider model-meta inserts. + * + * Each provider's own catalog supplies ids, activity, limits, modalities, and + * capabilities. A field the catalog leaves empty stays empty. There is no + * second source, and model-meta carries no prices (they change too often to + * ship in a package). + */ + +import { toModelConstName, toNativeProviderId } from './ids' +import type { SyncedProvider } from './provider-supports' + +const NON_CHAT_MODEL_PREFIXES = [ + 'lyria-', + 'veo-', + 'imagen-', + 'sora-', + 'dall-e-', + 'tts-', +] + +const DATED_SNAPSHOT = /-\d{8}$/ + +export interface CatalogModel { + provider: string + rawId: string + activity: string | null + firstSeenAt: number | null + deprecatedAt: number | null + contextWindow: number | null + maxOutput: number | null + inputModalities: Array + outputModalities: Array + capabilities: Array + /** `reasoning.mandatory`: thinking cannot be turned off (Claude Fable). */ + reasoningMandatory: boolean +} + +export interface SyncModel { + nativeId: string + contextWindow: number | null + maxOutput: number | null + inputModalities: Array + outputModalities: Array + supportedParameters: Array + reasoningMandatory: boolean +} + +export function isRecord(value: unknown): value is Record { + return typeof value === 'object' && value !== null && !Array.isArray(value) +} + +function asStringArray(value: unknown): Array { + if (!Array.isArray(value)) return [] + return value.filter((item): item is string => typeof item === 'string') +} + +function asFiniteNumber(value: unknown): number | null { + return typeof value === 'number' && Number.isFinite(value) ? value : null +} + +/** + * The parameter names a model is stated to support. modelschemas sends a map + * of flags (`{ tools: true }`): `true` keys only, because an absent key is + * unknown, not false. BytePlus sends a feature object instead. + */ +function asSupportedParameters(value: unknown): Array { + if (Array.isArray(value)) return asStringArray(value) + if (!isRecord(value)) return [] + const flags = Object.entries(value) + if (flags.every(([, flag]) => typeof flag === 'boolean')) { + return flags.filter(([, flag]) => flag).map(([name]) => name) + } + const params: Array = [] + const tools = isRecord(value.tools) ? value.tools : null + if (tools?.function_calling === true) { + params.push('tools', 'tool_choice') + } + const structured = isRecord(value.structured_outputs) + ? value.structured_outputs + : null + if (structured?.json_schema === true || structured?.json_object === true) { + params.push('structured_outputs', 'response_format') + } + if ( + typeof value.maxReasoningTokens === 'number' && + value.maxReasoningTokens > 0 + ) { + params.push('reasoning', 'include_reasoning') + } + return params +} + +export function parseCatalogModel(value: unknown): CatalogModel | null { + if (!isRecord(value)) return null + if (typeof value.rawId !== 'string' || value.rawId.length === 0) return null + const modalities = isRecord(value.modalities) ? value.modalities : null + const reasoning = isRecord(value.reasoning) ? value.reasoning : null + return { + provider: typeof value.provider === 'string' ? value.provider : '', + rawId: value.rawId, + activity: typeof value.activity === 'string' ? value.activity : null, + firstSeenAt: asFiniteNumber(value.firstSeenAt), + deprecatedAt: asFiniteNumber(value.deprecatedAt), + contextWindow: asFiniteNumber(value.contextWindow), + maxOutput: asFiniteNumber(value.maxOutput), + inputModalities: asStringArray(modalities?.input), + outputModalities: asStringArray(modalities?.output), + capabilities: asSupportedParameters(value.capabilities), + reasoningMandatory: reasoning?.mandatory === true, + } +} + +/** + * Parse a `listModels` payload. A changed payload shape must not look like + * "no new models", and a renamed `firstSeenAt` / `deprecatedAt` must not + * let the whole historical catalog through the age and deprecation checks. + */ +export function parseCatalogModels(data: unknown): Array { + const rows = isRecord(data) ? data.models : undefined + if (!Array.isArray(rows)) { + throw new Error('modelschemas listModels: no models array') + } + const models = rows + .map((row) => parseCatalogModel(row)) + .filter((model): model is CatalogModel => model !== null) + if (rows.length === 0) return models + if (models.length === 0) { + throw new Error( + `modelschemas listModels: none of ${rows.length} rows has a rawId`, + ) + } + if (!models.some((model) => model.firstSeenAt != null)) { + throw new Error('modelschemas listModels: no row has a firstSeenAt') + } + if (!rows.some((row) => isRecord(row) && 'deprecatedAt' in row)) { + throw new Error('modelschemas listModels: no row has a deprecatedAt key') + } + return models +} + +export function toSyncModel( + native: CatalogModel, + provider: SyncedProvider, +): SyncModel { + return { + nativeId: toNativeProviderId(native.rawId, provider), + contextWindow: native.contextWindow, + maxOutput: native.maxOutput, + inputModalities: native.inputModalities, + outputModalities: native.outputModalities, + supportedParameters: native.capabilities, + reasoningMandatory: native.reasoningMandatory, + } +} + +export function matchesSkipPattern( + rawId: string, + patterns: Array, +): boolean { + return patterns.some((pattern) => rawId.startsWith(pattern)) +} + +export function isNonChatFamily(rawId: string): boolean { + return ( + rawId.includes('transcribe') || + matchesSkipPattern(rawId, NON_CHAT_MODEL_PREFIXES) + ) +} + +export function isDatedAnthropicSnapshot(rawId: string): boolean { + return DATED_SNAPSHOT.test(rawId) +} + +export function hasImageOutput(model: { + activity: string | null + outputModalities: Array +}): boolean { + return model.activity === 'image' || model.outputModalities.includes('image') +} + +export function outputsText( + model: SyncModel, + activity: string | null, +): boolean { + if (model.outputModalities.includes('text')) return true + if ( + model.outputModalities.includes('image') || + model.outputModalities.includes('video') + ) { + return false + } + return ( + model.outputModalities.length === 0 && + (activity === 'chat' || activity === null) + ) +} + +/** + * Why this native row should not be inserted. `null` means keep going. + */ +export function skipNativeModelReason( + model: CatalogModel, + provider: SyncedProvider, + skipPatterns: Array, + cutoffTimestamp: number, + acceptedActivities: Array, +): string | null { + if (model.deprecatedAt != null) return 'deprecated' + if (!acceptedActivities.includes(model.activity)) { + return `activity ${model.activity}` + } + if (model.inputModalities.length === 0) return 'no modalities' + if (model.rawId.includes(':')) return 'routing variant' + if (isNonChatFamily(model.rawId)) return 'non-chat family' + if (matchesSkipPattern(model.rawId, skipPatterns)) return 'skip pattern' + if (provider === 'anthropic' && isDatedAnthropicSnapshot(model.rawId)) { + return 'dated snapshot' + } + if (model.firstSeenAt != null && model.firstSeenAt < cutoffTimestamp) { + return 'too old' + } + return null +} + +export interface NativeInsertRules { + provider: SyncedProvider + skipPatterns: Array + acceptedActivities: Array + cutoffTimestamp: number +} + +export interface NativeInsertSelection { + inserts: Array<{ model: SyncModel; activity: string | null }> + /** Count of every other skip, by reason. */ + skipped: Record +} + +/** Pick the catalog rows that become new model-meta constants. */ +export function selectNativeInserts( + rows: Array, + rules: NativeInsertRules, + isSynced: (nativeId: string) => boolean, +): NativeInsertSelection { + const selection: NativeInsertSelection = { + inserts: [], + skipped: {}, + } + const skip = (reason: string) => { + selection.skipped[reason] = (selection.skipped[reason] ?? 0) + 1 + } + for (const row of rows) { + const reason = skipNativeModelReason( + row, + rules.provider, + rules.skipPatterns, + rules.cutoffTimestamp, + rules.acceptedActivities, + ) + if (reason) { + skip(reason) + continue + } + const model = toSyncModel(row, rules.provider) + if (isSynced(model.nativeId)) { + skip('already synced') + continue + } + if ( + hasImageOutput({ + activity: row.activity, + outputModalities: model.outputModalities, + }) + ) { + skip('image output') + continue + } + selection.inserts.push({ model, activity: row.activity }) + } + return selection +} + +export function alreadySynced( + nativeId: string, + existingIds: Set, + existingConstNames: Set, +): boolean { + const normalized = nativeId.replaceAll('.', '-') + return ( + existingIds.has(normalized) || + existingConstNames.has(toModelConstName(nativeId)) + ) +} diff --git a/scripts/model-sync/ids.ts b/scripts/model-sync/ids.ts index c3c2bf88e4..fdcfc616e3 100644 --- a/scripts/model-sync/ids.ts +++ b/scripts/model-sync/ids.ts @@ -22,19 +22,17 @@ export function rejectRoutingAliases( } /** - * Native adapters only accept the provider's own ids. OpenRouter uses dots - * in Claude version suffixes (`claude-haiku-4.5`, `claude-fable-5.1`); - * Anthropic's Messages API uses dashes (`claude-haiku-4-5`, - * `claude-fable-5-1`). Other providers keep the OpenRouter stripped id. + * Native adapters only accept the provider's own ids. Anthropic's Messages + * API uses dashes in Claude version suffixes (`claude-haiku-4-5`), and + * OpenRouter uses dots (`claude-haiku-4.5`). The native modelschemas id is + * already dashed; this guards against a dotted one. Other providers keep + * the raw id. */ -export function toNativeProviderId( - strippedId: string, - provider: 'openai' | 'anthropic' | 'gemini' | 'grok', -): string { +export function toNativeProviderId(rawId: string, provider: string): string { if (provider === 'anthropic') { - return strippedId.replaceAll('.', '-') + return rawId.replaceAll('.', '-') } - return strippedId + return rawId } export function toModelConstName(modelId: string): string { diff --git a/scripts/model-sync/llmgateway.test.ts b/scripts/model-sync/llmgateway.test.ts index 95ce095378..2abdd0f5c9 100644 --- a/scripts/model-sync/llmgateway.test.ts +++ b/scripts/model-sync/llmgateway.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'vitest' -import { catalogRowToMeta, pricePerMillion } from './llmgateway' +import { catalogRowToMeta } from './llmgateway' const minimax = { id: 'minimax-m3.1-flash', @@ -7,11 +7,6 @@ const minimax = { input_modalities: ['text', 'image'], output_modalities: ['text'], }, - pricing: { - prompt: '0.15e-6', - completion: '0.6e-6', - input_cache_read: '0.015e-6', - }, context_length: 1048576, max_output: 524288, json_output: false, @@ -28,18 +23,8 @@ const minimax = { } describe('LLM Gateway catalog rows', () => { - it('scales per-token prices to USD per million', () => { - expect(pricePerMillion('2.0e-6')).toBe(2) - expect(pricePerMillion('0.15e-6')).toBe(0.15) - expect(pricePerMillion('0')).toBeUndefined() - }) - - it('maps reasoning efforts and prices for a chat row', () => { + it('maps reasoning efforts for a chat row', () => { const meta = catalogRowToMeta(minimax) - expect(meta?.pricing).toEqual({ - input: { normal: 0.15, cached: 0.015 }, - output: { normal: 0.6 }, - }) expect(meta?.reasoning).toEqual({ levels: { low: 'low', diff --git a/scripts/model-sync/llmgateway.ts b/scripts/model-sync/llmgateway.ts index f062732203..3ede4f424f 100644 --- a/scripts/model-sync/llmgateway.ts +++ b/scripts/model-sync/llmgateway.ts @@ -59,7 +59,6 @@ export interface LlmGatewayCatalogRow { input_modalities?: unknown output_modalities?: unknown } - pricing?: Record context_length?: unknown max_output?: unknown supported_parameters?: unknown @@ -72,10 +71,6 @@ export interface LlmGatewayModelMeta { id: string contextWindow?: number maxCompletionTokens?: number - pricing: { - input?: { normal: number; cached?: number } - output?: { normal: number } - } input: Array features: Array reasoning?: ReasoningShape @@ -109,14 +104,6 @@ function positiveInt(value: unknown): number | undefined { return n } -/** Catalog prices are USD per token. Model meta stores USD per million. */ -export function pricePerMillion(value: unknown): number | undefined { - if (typeof value !== 'string' && typeof value !== 'number') return undefined - const perToken = typeof value === 'number' ? value : Number(value) - if (!Number.isFinite(perToken) || perToken <= 0) return undefined - return Math.round(perToken * 1e6 * 1e6) / 1e6 -} - function inputOf(row: LlmGatewayCatalogRow): Array { const mapped = stringList(row.architecture?.input_modalities) .map((modality) => INPUT_ALIASES[modality.toLowerCase()]) @@ -181,9 +168,6 @@ export function catalogRowToMeta( flags.add('vision') } - const normal = pricePerMillion(row.pricing?.prompt) - const cached = pricePerMillion(row.pricing?.input_cache_read) - const output = pricePerMillion(row.pricing?.completion) const maxFromProvider = providers .map((provider) => positiveInt(provider.max_output)) .find((value) => value !== undefined) @@ -192,13 +176,6 @@ export function catalogRowToMeta( id: row.id, contextWindow: positiveInt(row.context_length), maxCompletionTokens: positiveInt(row.max_output) ?? maxFromProvider, - pricing: { - input: - normal === undefined - ? undefined - : { normal, ...(cached === undefined ? {} : { cached }) }, - output: output === undefined ? undefined : { normal: output }, - }, input, features: FEATURE_ORDER.filter((feature) => flags.has(feature)), reasoning, diff --git a/scripts/model-sync/modelschemas.test.ts b/scripts/model-sync/modelschemas.test.ts new file mode 100644 index 0000000000..048465529b --- /dev/null +++ b/scripts/model-sync/modelschemas.test.ts @@ -0,0 +1,65 @@ +import { describe, expect, it } from 'vitest' +import { createSyncClient, fetchSyncCatalogs } from './modelschemas' + +function clientReturning(respond: (provider: string) => Response) { + return createSyncClient({ + apiKey: '', + fetch: async (input) => { + const url = new URL(input instanceof Request ? input.url : String(input)) + return respond(url.searchParams.get('provider') ?? '') + }, + }) +} + +const row = (rawId: string) => ({ rawId, firstSeenAt: 1, deprecatedAt: null }) + +const json = (body: unknown, status = 200) => + new Response(JSON.stringify(body), { + status, + headers: { 'Content-Type': 'application/json' }, + }) + +describe('fetchSyncCatalogs', () => { + it('fails when modelschemas is down', async () => { + const client = clientReturning(() => + json({ error: { message: 'unavailable' } }, 503), + ) + await expect(fetchSyncCatalogs(client)).rejects.toThrow('unavailable') + }) + + it('fails on an empty native catalog instead of reporting no new models', async () => { + const client = clientReturning((provider) => + json({ models: provider === 'groq' ? [] : [row('x')] }), + ) + await expect(fetchSyncCatalogs(client)).rejects.toThrow( + 'empty groq catalog', + ) + }) + + it('fails when one native provider errors', async () => { + const client = clientReturning((provider) => + provider === 'mistral' + ? json({ error: { message: 'mistral down' } }, 500) + : json({ models: [row('x')] }), + ) + await expect(fetchSyncCatalogs(client)).rejects.toThrow('mistral down') + }) + + it('fails on a payload with no models array', async () => { + const client = clientReturning(() => json({ data: [] })) + // From client 0.2, `listModels` maps `models` to brand the ids, so it + // throws before `parseCatalogModels` can name the missing array. + await expect(fetchSyncCatalogs(client)).rejects.toThrow() + }) + + it('returns each native catalog, and does not fetch openrouter', async () => { + const asked: Array = [] + const client = clientReturning((provider) => { + asked.push(provider) + return json({ models: [row(`${provider}-model`)] }) + }) + const catalogs = await fetchSyncCatalogs(client) + expect(catalogs.mistral[0]?.rawId).toBe('mistral-model') + expect(asked).not.toContain('openrouter') + }) +}) diff --git a/scripts/model-sync/modelschemas.ts b/scripts/model-sync/modelschemas.ts new file mode 100644 index 0000000000..392c8aece7 --- /dev/null +++ b/scripts/model-sync/modelschemas.ts @@ -0,0 +1,95 @@ +/** + * Thin wrapper around `@modelschemas/client` for the model sync scripts. + */ + +import { + createModelschemasClient, + getSchema, + listModels, +} from '@modelschemas/client' +import type { GetSchemaData } from '@modelschemas/client' +import { isRecord, parseCatalogModels } from './catalog' +import type { CatalogModel } from './catalog' +import { SYNCED_PROVIDERS } from './provider-supports' +import type { SyncedProvider } from './provider-supports' + +export function createSyncClient(options?: { + apiKey?: string + fetch?: typeof globalThis.fetch +}): ReturnType { + const apiKey = options?.apiKey ?? process.env.MODELSCHEMAS_API_KEY + return createModelschemasClient({ + baseUrl: 'https://modelschemas.com', + ...(apiKey ? { apiKey } : {}), + ...(options?.fetch ? { fetch: options.fetch } : {}), + }) +} + +type SyncClient = ReturnType + +function errorMessage(error: unknown): string { + if (typeof error === 'string') return error + if (!isRecord(error)) return String(error) + if (isRecord(error.error) && typeof error.error.message === 'string') { + return error.error.message + } + if (typeof error.message === 'string') return error.message + return JSON.stringify(error) +} + +/** The raw `listModels` payload for one provider. */ +export async function listRawModels( + client: SyncClient, + provider: string, +): Promise { + const result = await listModels({ client, query: { provider } }) + if (result.error !== undefined) { + throw new Error( + `modelschemas listModels provider=${provider}: ${errorMessage(result.error)}`, + ) + } + return result.data +} + +export async function fetchCatalog( + client: SyncClient, + provider: string, +): Promise> { + return parseCatalogModels(await listRawModels(client, provider)) +} + +/** The raw input-schema payload for one endpoint, e.g. `v1/music`. */ +export async function getInputSchema( + client: SyncClient, + path: GetSchemaData['path'], +): Promise { + const result = await getSchema({ client, path, query: { kind: 'input' } }) + if (result.error !== undefined) { + const { provider, activity, endpointId } = path + throw new Error( + `modelschemas getSchema ${provider}/${activity}/${endpointId}: ${errorMessage(result.error)}`, + ) + } + return result.data +} + +/** + * Every synced provider's own catalog. An empty catalog throws: it would + * hide every insert for that provider behind a "no new models" exit 0. + */ +export async function fetchSyncCatalogs( + client: SyncClient, +): Promise>> { + const nativeLists = await Promise.all( + SYNCED_PROVIDERS.map((provider) => fetchCatalog(client, provider)), + ) + const native = {} as Record> + for (const [index, provider] of SYNCED_PROVIDERS.entries()) { + const rows = nativeLists[index] + if (!rows?.length) { + throw new Error(`modelschemas returned an empty ${provider} catalog`) + } + native[provider] = rows + } + return native +} diff --git a/scripts/model-sync/native-insert.test.ts b/scripts/model-sync/native-insert.test.ts index d8be383028..4bafe9f9df 100644 --- a/scripts/model-sync/native-insert.test.ts +++ b/scripts/model-sync/native-insert.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'vitest' -import { applyChatModelCatalogInserts } from './native-insert' +import { applyChatModelCatalogInserts, insertConstants } from './native-insert' const STUB = `const FOO = { id: 'claude-foo', @@ -184,4 +184,46 @@ export type OpenAIModelInputModalitiesByName = { [CLAUDE_FABLE_5_1.id]: CLAUDE_FABLE_5_1.supports.input, } satisfies AnthropicModelInputModalitiesByName`) }) + + it('throws when a type map is missing, so no constant is left unreferenced', () => { + expect(() => + applyChatModelCatalogInserts( + STUB.replace('AnthropicModelInputModalitiesByName', 'Renamed'), + ANTHROPIC_CONFIG, + [ + { + constName: 'CLAUDE_NEW', + providerOptionsEntry: 'AnthropicSamplingOptions', + hasMaxOutputTokens: false, + }, + ], + ), + ).toThrow("Could not find type map 'AnthropicModelInputModalitiesByName'") + }) +}) + +describe('insertConstants', () => { + it('keeps the JSDoc of the first export on that export', () => { + const stub = `const OLD = { name: 'old' } + +/** + * All supported chat model identifiers. + */ +export const CHAT_MODELS = [OLD.name] as const +` + const result = insertConstants(stub, [`const NEW = { name: 'new' }`]) + expect(result).toContain( + `const NEW = { name: 'new' }\n\n/**\n * All supported chat model identifiers.\n */\nexport const CHAT_MODELS`, + ) + expect(result.indexOf('const OLD')).toBeLessThan( + result.indexOf('const NEW'), + ) + }) + + it('inserts right before the export when it has no JSDoc', () => { + const result = insertConstants(`const A = 1\n\nexport const B = 2\n`, [ + 'const C = 3', + ]) + expect(result).toBe(`const A = 1\n\nconst C = 3\n\nexport const B = 2\n`) + }) }) diff --git a/scripts/model-sync/native-insert.ts b/scripts/model-sync/native-insert.ts index 33d9cdd031..fe5ea0a529 100644 --- a/scripts/model-sync/native-insert.ts +++ b/scripts/model-sync/native-insert.ts @@ -2,10 +2,10 @@ * File-mutation helpers for `sync-provider-models.ts`. * * Kept here so the insert path (chat array + type maps) can be unit-tested - * without running the full OpenRouter fetch. + * without running the full modelschemas fetch. */ -type ArrayRef = '.name' | '.id' +export type ArrayRef = '.name' | '.id' export function insertConstants( content: string, @@ -16,13 +16,21 @@ export function insertConstants( if (exportIndex === -1) { return content + block } - return content.slice(0, exportIndex) + block + content.slice(exportIndex) + // Insert above the export's JSDoc, so the comment stays on its export. + const doc = /\n\/\*\*(?:(?!\*\/)[\s\S])*\*\/\s*$/.exec( + content.slice(0, exportIndex), + ) + const at = doc ? doc.index : exportIndex + return content.slice(0, at) + block + content.slice(at) } /** * Insert entries immediately AFTER the opening bracket. Each inserted line * carries its own trailing comma so the existing body does not need a * comma-guess. See the grok-4.5 single-line array breakage. + * + * Every insert helper throws when its anchor is missing: the constants are + * already in the file, and nothing would reference them. */ function addToArray( content: string, @@ -35,8 +43,7 @@ function addToArray( const afterDecl = declIndex === -1 ? -1 : declIndex + decl.length const bracket = afterDecl === -1 ? -1 : content.indexOf('[', afterDecl) if (declIndex === -1 || bracket === -1 || bracket - afterDecl > 40) { - console.warn(` Warning: Could not find array '${arrayName}' in file`) - return content + throw new Error(`Could not find array '${arrayName}' in file`) } const newEntries = entries @@ -56,8 +63,7 @@ function addToTypeMap( ) const match = pattern.exec(content) if (!match) { - console.warn(` Warning: Could not find type map '${typeName}' in file`) - return content + throw new Error(`Could not find type map '${typeName}' in file`) } const newEntries = entries.join('\n') @@ -74,8 +80,7 @@ function addToObjectMap( ) const match = pattern.exec(content) if (!match) { - console.warn(` Warning: Could not find object map '${mapName}' in file`) - return content + throw new Error(`Could not find object map '${mapName}' in file`) } const newEntries = entries.join('\n') diff --git a/scripts/model-sync/provider-supports.test.ts b/scripts/model-sync/provider-supports.test.ts index 1c541d409e..a3a68114c1 100644 --- a/scripts/model-sync/provider-supports.test.ts +++ b/scripts/model-sync/provider-supports.test.ts @@ -71,6 +71,31 @@ describe('buildProviderSupportsBody', () => { expect(body).toContain('thinking') }) + it('writes Groq features without copying hosted tools', () => { + const body = buildProviderSupportsBody({ + provider: 'groq', + inputModalities: ['text'], + supportedParameters: ['tools', 'structured_outputs'], + }) + expect(body).toContain("endpoints: ['chat']") + expect(body).toContain('tools: [] as const') + expect(body).toContain("'json_schema'") + expect(body).not.toContain('browser_search') + }) + + it('writes BytePlus capabilities but leaves structured outputs to the probed list', () => { + const body = buildProviderSupportsBody({ + provider: 'byteplus', + inputModalities: ['text', 'image'], + outputModalities: ['text'], + supportedParameters: ['tools', 'reasoning', 'structured_outputs'], + }) + expect(body).toContain('tool_calling') + expect(body).toContain('reasoning') + expect(body).toContain('tools: [] as const') + expect(body).not.toContain('structured_outputs') + }) + it('lists Grok server tools', () => { const body = buildProviderSupportsBody({ provider: 'grok', @@ -88,7 +113,6 @@ describe('buildAnthropicProviderOptionsType', () => { it('uses max_tokens and no sampling when sampling is not listed', () => { const type = buildAnthropicProviderOptionsType({ supportedParameters: ['max_tokens', 'reasoning', 'tools'], - hasCachedPricing: true, }) expect(type).toContain('AnthropicCacheControlOptions') expect(type).toContain('AnthropicMaxTokensOptions') diff --git a/scripts/model-sync/provider-supports.ts b/scripts/model-sync/provider-supports.ts index b025193b09..e63a871343 100644 --- a/scripts/model-sync/provider-supports.ts +++ b/scripts/model-sync/provider-supports.ts @@ -1,18 +1,29 @@ /** * `supports` blocks for newly synced native-provider models. * - * Input modalities come from OpenRouter. Features come from - * `supported_parameters`. Server-tool lists are the current first-party - * vocabulary for that provider, written only when the catalog lists `tools` - * or `tool_choice`. Anthropic thinking flags follow the same parameter - * split as `buildAnthropicProviderOptionsType`. + * Input modalities and `supported_parameters` come from the provider's own + * modelschemas catalog, with no second source. Server-tool lists are the current first-party vocabulary for + * openai, anthropic, gemini and grok, written only when the catalog lists + * `tools` or `tool_choice`. Anthropic thinking flags follow the same + * parameter split as `buildAnthropicProviderOptionsType`. */ -export type SyncedProvider = 'openai' | 'anthropic' | 'gemini' | 'grok' +export const SYNCED_PROVIDERS = [ + 'openai', + 'anthropic', + 'gemini', + 'grok', + 'groq', + 'mistral', + 'byteplus', +] as const + +export type SyncedProvider = (typeof SYNCED_PROVIDERS)[number] export interface ProviderSupportsInput { provider: SyncedProvider inputModalities: Array + outputModalities?: Array supportedParameters?: Array reasoningMandatory?: boolean } @@ -70,7 +81,6 @@ function quoteList(values: Array): string { interface AnthropicProviderOptionsInput { supportedParameters?: Array - hasCachedPricing?: boolean } const ANTHROPIC_BASE_OPTIONS = [ @@ -83,9 +93,10 @@ const ANTHROPIC_BASE_OPTIONS = [ /** * Per-model Anthropic provider-options intersection, inferred from the - * OpenRouter catalog. Does not copy another model's tool list. Thinking is - * not here: `chat({ reasoning })` sets it, with the levels of each model's - * `reasoning` field in `model-meta.ts`. + * modelschemas capabilities. Every current Claude model takes prompt caching. + * Does not copy another model's tool list. Thinking is not here: + * `chat({ reasoning })` sets it, with the levels of each model's `reasoning` + * field in `model-meta.ts`. * * - sampling listed → sampling options. * - no sampling (Sonnet 5, Opus 4.7+, Fable 5) → `max_tokens` only. @@ -96,10 +107,10 @@ export function buildAnthropicProviderOptionsType( const params = input.supportedParameters ?? [] const hasSampling = hasParam(params, ['temperature', 'top_p', 'top_k']) - const parts: Array = [...ANTHROPIC_BASE_OPTIONS] - if (input.hasCachedPricing) { - parts.unshift('AnthropicCacheControlOptions') - } + const parts: Array = [ + 'AnthropicCacheControlOptions', + ...ANTHROPIC_BASE_OPTIONS, + ] parts.push('AnthropicToolChoiceOptions') parts.push( @@ -200,5 +211,40 @@ export function buildProviderSupportsBody( lines.push(toolsLine(hasTools, GROK_SERVER_TOOLS)) return lines.join('\n') } + case 'groq': + case 'mistral': { + const features = ['streaming'] + if (hasTools) features.push('tools') + if (hasStructured) { + features.push('json_object', 'json_schema') + } + if (hasReasoning) features.push('reasoning') + if (input.inputModalities.includes('image')) features.push('vision') + const lines = [ + ` input: ${inputList},`, + ` output: ['text'],`, + ` endpoints: ['chat'],`, + ` features: ${quoteList(features)},`, + ] + // Groq hosted tools (browser_search, …) are per-model; never guess them. + if (input.provider === 'groq') lines.push(` tools: [] as const,`) + return lines.join('\n') + } + case 'byteplus': { + // No `structured_outputs`: the runtime gate is the live-probed + // BYTEPLUS_STRUCTURED_OUTPUT_CHAT_MODELS list, which a sync cannot update. + const capabilities: Array = [] + if (hasReasoning) capabilities.push('reasoning') + if (hasTools) capabilities.push('tool_calling') + const output = quoteList( + input.outputModalities?.length ? input.outputModalities : ['text'], + ) + const lines = [` input: ${inputList},`, ` output: ${output},`] + if (capabilities.length > 0) { + lines.push(` capabilities: ${quoteList(capabilities)},`) + } + lines.push(` tools: [] as const,`) + return lines.join('\n') + } } } diff --git a/scripts/sync-elevenlabs-models.ts b/scripts/sync-elevenlabs-models.ts index b48b1629ba..f45c8b756a 100644 --- a/scripts/sync-elevenlabs-models.ts +++ b/scripts/sync-elevenlabs-models.ts @@ -2,15 +2,18 @@ * Inserts new ElevenLabs model ids into * `packages/ai-elevenlabs/src/model-meta.ts`. * - * Text-to-speech: https://modelschemas.com/v1/models?provider=elevenlabs - * Music: request schema `v1/music` (compose). That enum is the SDK - * `MusicModelId` set. - * Sound effects: `v1/sound-generation`. - * Voice design: `v1/text-to-voice/design`. + * Reads modelschemas through `@modelschemas/client`: + * - Text-to-speech: `listModels` for provider `elevenlabs`. + * - Music: request schema `v1/music` (compose). That enum is the SDK + * `MusicModelId` set. + * - Sound effects: `v1/sound-generation`. + * - Voice design: `v1/text-to-voice/design`. * * Usage: * pnpm tsx scripts/sync-elevenlabs-models.ts * + * Optional: MODELSCHEMAS_API_KEY raises the modelschemas rate limit. + * * Runs as part of `pnpm generate:models` (the daily Sync Model Metadata * workflow). Only adds missing ids. Transcription stays hand-maintained: * its speech-to-text schema has no `model_id` enum. Music and voice design @@ -26,9 +29,12 @@ import { ttsModelIdsFromCatalog, } from './model-sync/elevenlabs' import type { ElevenLabsCatalogModel } from './model-sync/elevenlabs' +import { + createSyncClient, + getInputSchema, + listRawModels, +} from './model-sync/modelschemas' -const CATALOG_URL = 'https://modelschemas.com/v1/models?provider=elevenlabs' -const SCHEMA_ROOT = 'https://modelschemas.com/v1/schemas/elevenlabs/audio' const __dirname = dirname(fileURLToPath(import.meta.url)) const META_FILE = resolve( __dirname, @@ -40,41 +46,34 @@ interface CatalogResponse { models?: Array } -function schemaUrl(endpointId: string): string { - return `${SCHEMA_ROOT}/${endpointId}?kind=input` -} - -async function readJson(url: string): Promise { - const response = await fetch(url) - if (!response.ok) { - throw new Error( - `modelschemas ${response.status} ${response.statusText} for ${url}`, - ) - } - return response.json() -} - -function unwrapSchema(payload: unknown, url: string): unknown { +function unwrapSchema(payload: unknown, endpointId: string): unknown { if ( typeof payload !== 'object' || payload === null || !('schema' in payload) ) { - throw new Error(`modelschemas response has no schema for ${url}`) + throw new Error(`modelschemas response has no schema for ${endpointId}`) } return payload.schema } async function main() { - const musicUrl = schemaUrl('v1/music') - const sfxUrl = schemaUrl('v1/sound-generation') - const voiceUrl = schemaUrl('v1/text-to-voice/design') - const [catalogPayload, musicPayload, sfxPayload, voicePayload] = + const client = createSyncClient() + const schema = async (endpointId: string) => + unwrapSchema( + await getInputSchema(client, { + provider: 'elevenlabs', + activity: 'audio', + endpointId, + }), + endpointId, + ) + const [catalogPayload, musicSchema, sfxSchema, voiceSchema] = await Promise.all([ - readJson(CATALOG_URL), - readJson(musicUrl), - readJson(sfxUrl), - readJson(voiceUrl), + listRawModels(client, 'elevenlabs'), + schema('v1/music'), + schema('v1/sound-generation'), + schema('v1/text-to-voice/design'), ]) const body = catalogPayload as CatalogResponse @@ -94,14 +93,14 @@ async function main() { 'ELEVENLABS_AUDIO_MODELS', 'audio', [ - ...modelIdsFromRequestSchema(unwrapSchema(musicPayload, musicUrl)), - ...modelIdsFromRequestSchema(unwrapSchema(sfxPayload, sfxUrl)), + ...modelIdsFromRequestSchema(musicSchema), + ...modelIdsFromRequestSchema(sfxSchema), ], ], [ 'ELEVENLABS_VOICE_MODELS', 'voice', - modelIdsFromRequestSchema(unwrapSchema(voicePayload, voiceUrl)), + modelIdsFromRequestSchema(voiceSchema), ], ] if (groups.some(([, , ids]) => ids.length === 0)) { diff --git a/scripts/sync-provider-models.ts b/scripts/sync-provider-models.ts index 0d1536a529..edc12efe3f 100644 --- a/scripts/sync-provider-models.ts +++ b/scripts/sync-provider-models.ts @@ -1,79 +1,67 @@ /** - * Syncs OpenRouter models into native provider model-meta.ts files. + * Syncs modelschemas catalogs into native provider model-meta.ts files. * - * For each supported provider (OpenAI, Anthropic, Gemini, Grok), this script: - * 1. Reads the OpenRouter model list - * 2. Filters models matching the provider prefix + * For each synced provider, this script: + * 1. Lists that provider's models from modelschemas (`@modelschemas/client`) + * 2. Uses the native row's limits, modalities, and capabilities. A field the + * row leaves empty stays empty, and a row with no modalities is skipped * 3. Identifies models missing from the provider's model-meta.ts * 4. Generates and inserts new model constants, array entries, and type map entries * * Usage: * pnpm tsx scripts/sync-provider-models.ts * - * ## Providers deliberately NOT synced + * Optional: MODELSCHEMAS_API_KEY raises the modelschemas rate limit. * - * The sync is only safe when the provider's own model ids can be derived from - * OpenRouter's. Adding an entry to `PROVIDER_MAP` for a provider where that - * doesn't hold generates ids that 404 at request time, which is worse than no - * automation. These are excluded on purpose: + * ## Providers deliberately NOT synced * - * - **byteplus** (`@tanstack/ai-byteplus`) — OpenRouter lists the same models - * under undated slugs (`bytedance-seed/seed-1.6`), but BytePlus Ark - * addresses them by *date-suffixed* id (`seed-1-6-250615`), and the suffix - * is not derivable from anything OpenRouter publishes. Ark's own `GET - * /models` is the catalog, and it is not exhaustive. On top of that the - * package's capability tables are live-probe-verified specifically because - * the published metadata is wrong in both directions, so a metadata-driven - * sync would overwrite probed facts with worse ones. Use `/gap-analysis - * byteplus` instead; the probe recipe is in that package's `model-meta.ts`. - * - **fal** — media-only provider whose endpoint ids are not OpenRouter - * models. fal image fields have their own generator - * (`scripts/generate-fal-image-field-map.ts`). - * - **elevenlabs** — text-to-speech, music, sound effects, and voice design - * ids come from modelschemas via `scripts/sync-elevenlabs-models.ts`, not - * OpenRouter. Transcription stays hand-maintained. + * - **fal** — 1k+ model-grained endpoints; image field maps have their own + * generator (`scripts/generate-fal-image-field-map.ts`). + * - **elevenlabs** — id arrays, not ModelMeta constants; see + * `scripts/sync-elevenlabs-models.ts`. * - **bedrock** — ids are AWS-region-qualified; see * `scripts/fetch-bedrock-models.ts`. + * - **ollama**, **llmgateway**, **vercel-gateway**, **lovable** — different + * catalogs (local, aggregator, or their own fetch scripts). + * - **claude-code**, **codex**, **opencode**, **grok-build** — harness aliases. + * BytePlus video/image duration and size tables stay hand-curated. */ import { execFileSync } from 'node:child_process' -import { readFile, writeFile } from 'node:fs/promises' +import { readFile, readdir, writeFile } from 'node:fs/promises' import { dirname, resolve } from 'node:path' import { fileURLToPath } from 'node:url' import { - isRoutingAlias, - toModelConstName, - toNativeProviderId, -} from './model-sync/ids' + alreadySynced, + outputsText, + selectNativeInserts, +} from './model-sync/catalog' +import type { CatalogModel, SyncModel } from './model-sync/catalog' +import { toModelConstName } from './model-sync/ids' import { applyChatModelCatalogInserts, insertConstants, } from './model-sync/native-insert' +import { createSyncClient, fetchSyncCatalogs } from './model-sync/modelschemas' import { buildAnthropicProviderOptionsType, buildProviderSupportsBody, } from './model-sync/provider-supports' +import type { ArrayRef } from './model-sync/native-insert' import type { SyncedProvider } from './model-sync/provider-supports' -import { models } from './openrouter.models' -import type { OpenRouterModel } from './openrouter.models' const __dirname = dirname(fileURLToPath(import.meta.url)) const ROOT = resolve(__dirname, '..') -// --------------------------------------------------------------------------- -// Provider configuration -// --------------------------------------------------------------------------- - /** Seconds in 30 days — models older than this before the last sync are skipped */ const MAX_MODEL_AGE_SECONDS = 30 * 24 * 60 * 60 const LAST_RUN_FILE = resolve(ROOT, 'scripts/.sync-models-last-run') interface ProviderConfig { - /** npm package name for changeset */ packageName: string metaFile: string /** How array entries reference the constant, e.g. '.name' or '.id' */ - arrayRef: '.name' | '.id' + arrayRef: ArrayRef /** Which field name is used for context window size */ contextField: 'context_window' | 'max_input_tokens' /** Name of the exported chat model array */ @@ -102,8 +90,6 @@ interface ProviderConfig { * test expects every registered model in the set. */ combinedToolsAndSchemaSetName?: string - /** Provider key for conservative supports generation */ - kind: SyncedProvider /** Valid input modality types for this provider's ModelMeta interface */ validInputModalities: Array /** The satisfies type clause (after 'as const satisfies') */ @@ -114,12 +100,15 @@ interface ProviderConfig { hasBothNameAndId: boolean /** Whether the provider options type is a mapped type (skip insertion) */ providerOptionsIsMappedType: boolean - /** Model ID patterns to always skip (matched against stripped ID) */ + /** Raw-id prefixes to always skip */ skipPatterns: Array + /** Activities to insert. `null` means the catalog left activity unset. */ + acceptedActivities: Array + outputTokenField: 'max_output_tokens' | 'max_completion_tokens' } -const PROVIDER_MAP: Record = { - 'openai/': { +const PROVIDER_MAP: Record = { + openai: { packageName: '@tanstack/ai-openai', metaFile: resolve(ROOT, 'packages/ai-openai/src/model-meta.ts'), arrayRef: '.name', @@ -129,7 +118,6 @@ const PROVIDER_MAP: Record = { inputModalitiesTypeName: 'OpenAIModelInputModalitiesByName', toolCapabilitiesTypeName: 'OpenAIChatModelToolCapabilitiesByName', validInputModalities: ['text', 'image', 'audio', 'video'], - kind: 'openai', referenceSatisfies: 'ModelMeta', referenceProviderOptionsEntry: @@ -143,8 +131,10 @@ const PROVIDER_MAP: Record = { 'gpt-oss-', // Open-source/experimental models 'chatgpt-', // ChatGPT branded models ], + acceptedActivities: ['chat'], + outputTokenField: 'max_output_tokens', }, - 'anthropic/': { + anthropic: { packageName: '@tanstack/ai-anthropic', metaFile: resolve(ROOT, 'packages/ai-anthropic/src/model-meta.ts'), arrayRef: '.id', @@ -156,7 +146,6 @@ const PROVIDER_MAP: Record = { maxOutputTokensMapName: 'ANTHROPIC_MODEL_MAX_OUTPUT_TOKENS', combinedToolsAndSchemaSetName: 'ANTHROPIC_COMBINED_TOOLS_AND_SCHEMA_MODELS', validInputModalities: ['text', 'image', 'audio', 'video', 'document'], - kind: 'anthropic', referenceSatisfies: 'ModelMeta', referenceProviderOptionsEntry: @@ -164,8 +153,10 @@ const PROVIDER_MAP: Record = { hasBothNameAndId: true, providerOptionsIsMappedType: false, skipPatterns: [], + acceptedActivities: ['chat'], + outputTokenField: 'max_output_tokens', }, - 'google/': { + gemini: { packageName: '@tanstack/ai-gemini', metaFile: resolve(ROOT, 'packages/ai-gemini/src/model-meta.ts'), arrayRef: '.name', @@ -175,7 +166,6 @@ const PROVIDER_MAP: Record = { inputModalitiesTypeName: 'GeminiModelInputModalitiesByName', toolCapabilitiesTypeName: 'GeminiChatModelToolCapabilitiesByName', validInputModalities: ['text', 'image', 'audio', 'video', 'document'], - kind: 'gemini', referenceSatisfies: 'ModelMeta', referenceProviderOptionsEntry: @@ -185,8 +175,10 @@ const PROVIDER_MAP: Record = { skipPatterns: [ 'gemma-', // Gemma open-source models (not Gemini API models) ], + acceptedActivities: ['chat'], + outputTokenField: 'max_output_tokens', }, - 'x-ai/': { + grok: { packageName: '@tanstack/ai-grok', metaFile: resolve(ROOT, 'packages/ai-grok/src/model-meta.ts'), arrayRef: '.name', @@ -196,19 +188,79 @@ const PROVIDER_MAP: Record = { inputModalitiesTypeName: 'GrokModelInputModalitiesByName', toolCapabilitiesTypeName: 'GrokChatModelToolCapabilitiesByName', validInputModalities: ['text', 'image', 'audio', 'video', 'document'], - kind: 'grok', referenceSatisfies: 'ModelMeta', referenceProviderOptionsEntry: 'GrokProviderOptions', hasBothNameAndId: false, providerOptionsIsMappedType: true, skipPatterns: [], + acceptedActivities: ['chat'], + outputTokenField: 'max_output_tokens', + }, + groq: { + packageName: '@tanstack/ai-groq', + metaFile: resolve(ROOT, 'packages/ai-groq/src/model-meta.ts'), + arrayRef: '.name', + contextField: 'context_window', + chatArrayName: 'GROQ_CHAT_MODELS', + providerOptionsTypeName: 'GroqChatModelProviderOptionsByName', + inputModalitiesTypeName: 'GroqModelInputModalitiesByName', + toolCapabilitiesTypeName: 'GroqChatModelToolCapabilitiesByName', + validInputModalities: ['text', 'image', 'audio'], + referenceSatisfies: 'ModelMeta', + referenceProviderOptionsEntry: 'GroqTextProviderOptions', + hasBothNameAndId: false, + providerOptionsIsMappedType: true, + skipPatterns: ['whisper-', 'canopylabs/'], + acceptedActivities: [null, 'chat'], + outputTokenField: 'max_completion_tokens', + }, + mistral: { + packageName: '@tanstack/ai-mistral', + metaFile: resolve(ROOT, 'packages/ai-mistral/src/model-meta.ts'), + arrayRef: '.name', + contextField: 'context_window', + chatArrayName: 'MISTRAL_CHAT_MODELS', + providerOptionsTypeName: 'MistralChatModelProviderOptionsByName', + inputModalitiesTypeName: 'MistralModelInputModalitiesByName', + validInputModalities: ['text', 'image', 'audio', 'document'], + referenceSatisfies: 'ModelMeta', + referenceProviderOptionsEntry: 'MistralTextProviderOptions', + hasBothNameAndId: false, + providerOptionsIsMappedType: false, + skipPatterns: [ + 'mistral-embed', + 'codestral-embed', + 'mistral-ocr', + 'mistral-moderation', + 'voxtral-', + 'mistral-vibe', + 'mistral-code-fim', + 'mistral-code-', + 'glm-', + 'zai-', + ], + acceptedActivities: [null, 'chat'], + outputTokenField: 'max_completion_tokens', + }, + byteplus: { + packageName: '@tanstack/ai-byteplus', + metaFile: resolve(ROOT, 'packages/ai-byteplus/src/model-meta.ts'), + arrayRef: '.name', + contextField: 'context_window', + chatArrayName: 'BYTEPLUS_CHAT_MODELS', + providerOptionsTypeName: 'BytePlusChatModelProviderOptionsByName', + inputModalitiesTypeName: 'BytePlusModelInputModalitiesByName', + validInputModalities: ['text', 'image', 'audio', 'video', 'document'], + referenceSatisfies: 'ModelMeta', + referenceProviderOptionsEntry: 'BytePlusTextProviderOptions', + hasBothNameAndId: false, + providerOptionsIsMappedType: true, + skipPatterns: [], + acceptedActivities: ['chat'], + outputTokenField: 'max_output_tokens', }, } -// --------------------------------------------------------------------------- -// Utility functions -// --------------------------------------------------------------------------- - type InputModality = 'text' | 'image' | 'audio' | 'video' | 'document' const MODALITY_MAP: Record = { @@ -220,324 +272,207 @@ const MODALITY_MAP: Record = { document: 'document', } -/** - * Map OpenRouter input modalities to our standard modality types. - * Same mapping as the existing convert-openrouter-models.ts script. - */ function mapInputModalities(modalities: Array): Array { const mapped = modalities .map((m) => MODALITY_MAP[m.toLowerCase()]) .filter((m): m is InputModality => m !== undefined) - // Ensure at least 'text' is present if (!mapped.includes('text')) { mapped.unshift('text') } return mapped } -/** Strip the provider prefix from an OpenRouter model ID */ -function stripPrefix(prefix: string, modelId: string): string { - return modelId.slice(prefix.length) -} - -/** - * Convert an OpenRouter price string to per-million-token pricing. - * Same logic as the existing convert script. - */ -function convertPrice(priceStr: string | undefined): number { - const price = parseFloat(priceStr ?? '0') - if (isNaN(price)) return 0 - const result = price * 1_000_000 - return Math.round(result * 1e10) / 1e10 -} - -function anthropicOptionsType(model: OpenRouterModel): string { +function anthropicOptionsType(model: SyncModel): string { return buildAnthropicProviderOptionsType({ - supportedParameters: model.supported_parameters, - hasCachedPricing: convertPrice(model.pricing.input_cache_read) > 0, + supportedParameters: model.supportedParameters, }) } function providerOptionsEntryFor( - model: OpenRouterModel, + model: SyncModel, + provider: SyncedProvider, config: ProviderConfig, ): string { - if (config.kind === 'anthropic') return anthropicOptionsType(model) + if (provider === 'anthropic') return anthropicOptionsType(model) return config.referenceProviderOptionsEntry } function satisfiesClause( - model: OpenRouterModel, + model: SyncModel, + provider: SyncedProvider, config: ProviderConfig, ): string { - if (config.kind === 'anthropic') { + if (provider === 'anthropic') { return `ModelMeta<${anthropicOptionsType(model)}>` } return config.referenceSatisfies } -/** - * Normalize a model ID for comparison. - * Handles cases where the same model uses dots vs dashes - * (e.g., Anthropic's 'claude-3-5-haiku' vs OpenRouter's 'claude-3.5-haiku'). - */ -function normalizeId(id: string): string { - return id.replace(/[.]/g, '-') -} - -/** - * Extract existing model IDs from a model-meta file. - * Matches BOTH name: 'xxx' AND id: 'xxx' lines to get a complete set, - * since providers like Anthropic use different naming between name and id. - * Returns a normalized set for comparison purposes. - */ function extractExistingModelIds(content: string): Set { - const ids = new Set() - // Match both name and id fields inside const blocks - const nameRegex = /^\s+name:\s*'([^']+)'/gm - const idRegex = /^\s+id:\s*'([^']+)'/gm - let match - while ((match = nameRegex.exec(content)) !== null) { - ids.add(normalizeId(match[1]!)) - } - while ((match = idRegex.exec(content)) !== null) { - ids.add(normalizeId(match[1]!)) - } - return ids + return new Set( + Array.from(content.matchAll(/^\s+(?:name|id):\s*'([^']+)'/gm), (m) => + m[1]!.replaceAll('.', '-'), + ), + ) } -/** - * Extract existing constant names from a model-meta file. - * Matches: const UPPER_CASE_NAME = - */ function extractExistingConstNames(content: string): Set { - const names = new Set() - const regex = /^const\s+([A-Z][A-Z0-9_]+)\s*=/gm - let match - while ((match = regex.exec(content)) !== null) { - names.add(match[1]!) - } - return names -} - -/** - * Check if an OpenRouter model outputs text (for chat model array). - */ -function outputsText(model: OpenRouterModel): boolean { - return model.architecture.output_modalities.includes('text') -} - -/** - * Check if an OpenRouter model produces image output. - * - * Image-generation models are skipped entirely by the sync — regardless of - * whether they ALSO output text — because image model arrays require manual - * curation with specialized type maps (sizes, provider options, the native - * image union). This covers text+image "native" image models such as the - * Gemini "Nano Banana" family (`gemini-*-image`, e.g. - * `gemini-3.1-flash-lite-image`), which would otherwise be misclassified as - * chat models (they output text) and inserted with a bogus `output: ['text']`. - */ -function outputsImage(model: OpenRouterModel): boolean { - return model.architecture.output_modalities.includes('image') -} - -/** - * Non-chat model family prefixes to exclude from chat model arrays. - * These are audio/music/video/image generation models that happen to - * include 'text' in their output modalities but are not chat models. - */ -const NON_CHAT_MODEL_PREFIXES = [ - 'lyria-', // Google music generation - 'veo-', // Google video generation - 'imagen-', // Google image generation - 'sora-', // OpenAI video generation - 'dall-e-', // OpenAI image generation - 'tts-', // Text-to-speech models -] - -function isNonChatModel(strippedId: string): boolean { - return NON_CHAT_MODEL_PREFIXES.some((p) => strippedId.startsWith(p)) -} - -/** - * Check if a model should be skipped based on provider-specific patterns. - */ -function matchesSkipPattern( - strippedId: string, - patterns: Array, -): boolean { - return patterns.some((p) => strippedId.startsWith(p)) + return new Set( + Array.from( + content.matchAll(/^const\s+([A-Z][A-Z0-9_]+)\s*=/gm), + (m) => m[1]!, + ), + ) } -/** - * Read the last sync run timestamp. Returns epoch seconds, or null if no previous run. - */ async function readLastRunTimestamp(): Promise { + let content: string try { - const content = await readFile(LAST_RUN_FILE, 'utf-8') - const ts = parseInt(content.trim(), 10) - return isNaN(ts) ? null : ts - } catch { - return null + content = await readFile(LAST_RUN_FILE, 'utf-8') + } catch (error) { + // First run. Any other read error must not silently reset the cutoff. + if (isNodeError(error) && error.code === 'ENOENT') return null + throw error } + const ts = parseInt(content.trim(), 10) + if (isNaN(ts)) throw new Error(`${LAST_RUN_FILE} is not a timestamp`) + return ts +} + +function isNodeError(error: unknown): error is NodeJS.ErrnoException { + return error instanceof Error && 'code' in error } -/** - * Write the current timestamp as the last sync run. - */ async function writeLastRunTimestamp(): Promise { const now = Math.floor(Date.now() / 1000) await writeFile(LAST_RUN_FILE, String(now) + '\n', 'utf-8') } -/** - * Check if a model is too old to sync. Models created more than 30 days - * before the last sync run are considered deprecated/legacy and skipped. - */ -function isModelTooOld( - model: OpenRouterModel, - cutoffTimestamp: number, -): boolean { - if (!model.created) return false // No date = don't skip - return model.created < cutoffTimestamp -} - -// --------------------------------------------------------------------------- -// Model constant generation -// --------------------------------------------------------------------------- - function generateModelConstant( - model: OpenRouterModel, - prefix: string, + model: SyncModel, + provider: SyncedProvider, config: ProviderConfig, ): string { - const strippedId = stripPrefix(prefix, model.id) - const nativeId = toNativeProviderId(strippedId, config.kind) - const constName = toModelConstName(nativeId) + const constName = toModelConstName(model.nativeId) - const inputNormal = convertPrice(model.pricing.prompt) - const inputCached = convertPrice(model.pricing.input_cache_read) - const outputNormal = convertPrice(model.pricing.completion) - - // Use actual input modalities from OpenRouter data, filtered to what this provider supports - const inputModalities = mapInputModalities( - model.architecture.input_modalities, - ).filter((m) => config.validInputModalities.includes(m)) + const inputModalities = mapInputModalities(model.inputModalities).filter( + (m) => config.validInputModalities.includes(m), + ) const lines: Array = [] lines.push(`const ${constName} = {`) - - // name field - lines.push(` name: '${nativeId}',`) - - // id field (Anthropic has both name and id, set to same value for new models) + lines.push(` name: '${model.nativeId}',`) if (config.hasBothNameAndId) { - lines.push(` id: '${nativeId}',`) + lines.push(` id: '${model.nativeId}',`) } - - // context / max_input_tokens - if (model.context_length > 0) { + if (isPositive(model.contextWindow)) { lines.push( - ` ${config.contextField}: ${formatNumber(model.context_length)},`, + ` ${config.contextField}: ${formatNumber(model.contextWindow)},`, ) } - - // max_output_tokens - if (model.top_provider.max_completion_tokens) { + if (isPositive(model.maxOutput)) { lines.push( - ` max_output_tokens: ${formatNumber(model.top_provider.max_completion_tokens)},`, + ` ${config.outputTokenField}: ${formatNumber(model.maxOutput)},`, ) } - lines.push(` supports: {`) lines.push( buildProviderSupportsBody({ - provider: config.kind, + provider, inputModalities, - supportedParameters: model.supported_parameters, - reasoningMandatory: model.reasoning?.mandatory === true, + outputModalities: model.outputModalities, + supportedParameters: model.supportedParameters, + reasoningMandatory: model.reasoningMandatory, }), ) lines.push(` },`) - - // pricing - lines.push(` pricing: {`) - lines.push(` input: {`) - lines.push(` normal: ${inputNormal},`) - if (inputCached > 0) { - lines.push(` cached: ${inputCached},`) - } - lines.push(` },`) - lines.push(` output: {`) - lines.push(` normal: ${outputNormal},`) - lines.push(` },`) - lines.push(` },`) - - lines.push(`} as const satisfies ${satisfiesClause(model, config)}`) - + lines.push(`} as const satisfies ${satisfiesClause(model, provider, config)}`) return lines.join('\n') } -/** - * Format a number with underscore separators for readability. - * E.g. 131072 -> '131_072', 200000 -> '200_000' - */ -function formatNumber(n: number): string { - if (n < 1000) return String(n) - const str = String(n) - // Insert underscores every 3 digits from the right - const parts: Array = [] - let remaining = str - while (remaining.length > 3) { - parts.unshift(remaining.slice(-3)) - remaining = remaining.slice(0, -3) - } - parts.unshift(remaining) - return parts.join('_') +function isPositive(n: number | null): n is number { + return n != null && n > 0 } -// --------------------------------------------------------------------------- -// Git-based change detection -// --------------------------------------------------------------------------- +/** 1048576 → 1_048_576 */ +function formatNumber(n: number): string { + return n.toLocaleString('en-US').replaceAll(',', '_') +} -/** - * Detect packages with uncommitted changes by running `git diff`. - * This captures changes from ALL prior pipeline steps (e.g. convert-openrouter-models.ts) - * not just the models added by this script. - */ +/** Packages the fetch scripts changed, so the changeset covers them too. */ function detectChangedPackages(): Set { + const diff = execFileSync( + 'git', + ['diff', 'HEAD', '--name-only', '--', 'packages/'], + { encoding: 'utf-8', cwd: ROOT }, + ) const changed = new Set() - try { - const diff = execFileSync( - 'git', - ['diff', 'HEAD', '--name-only', '--', 'packages/'], - { encoding: 'utf-8', cwd: ROOT }, - ).trim() - if (!diff) return changed - - for (const line of diff.split('\n')) { - // packages/ai-openrouter/... → @tanstack/ai-openrouter - const match = line.match(/^packages\/([\w-]+)\//) - if (match) { - changed.add(`@tanstack/${match[1]}`) - } - } - } catch { - // git not available (e.g. running outside a repo) — fall back to empty set + for (const match of diff.matchAll(/^packages\/([\w-]+)\//gm)) { + changed.add(`@tanstack/${match[1]}`) } return changed } -// --------------------------------------------------------------------------- -// Main -// --------------------------------------------------------------------------- +async function syncModelMeta( + provider: SyncedProvider, + config: ProviderConfig, + catalogs: Record>, + cutoffTimestamp: number, +): Promise { + console.log(`\nProcessing provider: ${provider}`) + const rows = catalogs[provider] + console.log(` Found ${rows.length} modelschemas models for '${provider}'`) + + let content = await readFile(config.metaFile, 'utf-8') + const existingIds = extractExistingModelIds(content) + const existingConstNames = extractExistingConstNames(content) + console.log( + ` Existing models in file: ${existingIds.size} IDs, ${existingConstNames.size} constants`, + ) -async function main() { - let totalAdded = 0 - const changedPackages = new Set() + const { inserts, skipped } = selectNativeInserts( + rows, + { ...config, provider, cutoffTimestamp }, + (nativeId) => alreadySynced(nativeId, existingIds, existingConstNames), + ) + const skipCounts = Object.entries(skipped) + .map(([reason, count]) => `${reason}=${count}`) + .join(', ') + if (skipCounts) console.log(` Skipped: ${skipCounts}`) + + if (inserts.length === 0) { + console.log(' No new models to add.') + return 0 + } + + console.log(` Adding ${inserts.length} new models:`) + for (const { model } of inserts) { + console.log(` - ${model.nativeId} (${toModelConstName(model.nativeId)})`) + } + + content = insertConstants( + content, + inserts.map(({ model }) => generateModelConstant(model, provider, config)), + ) + content = applyChatModelCatalogInserts( + content, + config, + inserts + .filter(({ model, activity }) => outputsText(model, activity)) + .map(({ model }) => ({ + constName: toModelConstName(model.nativeId), + providerOptionsEntry: providerOptionsEntryFor(model, provider, config), + hasMaxOutputTokens: isPositive(model.maxOutput), + acceptsCombinedToolsAndSchema: !model.nativeId.endsWith('-fast'), + })), + ) + + await writeFile(config.metaFile, content, 'utf-8') + console.log(` Wrote updated file: ${config.metaFile}`) + return inserts.length +} - // Determine age cutoff: skip models created >30 days before last run +async function main() { const lastRun = await readLastRunTimestamp() const now = Math.floor(Date.now() / 1000) const cutoffTimestamp = (lastRun ?? now) - MAX_MODEL_AGE_SECONDS @@ -548,152 +483,31 @@ async function main() { `Model age cutoff: ${cutoffDate} (skipping models created before this date)`, ) - for (const [prefix, config] of Object.entries(PROVIDER_MAP)) { - console.log(`\nProcessing provider: ${prefix}`) - - // Filter OpenRouter models for this prefix - const providerModels = models.filter((m) => m.id.startsWith(prefix)) - console.log( - ` Found ${providerModels.length} OpenRouter models with prefix '${prefix}'`, - ) - - // Read the provider's model-meta.ts - let content: string - try { - content = await readFile(config.metaFile, 'utf-8') - } catch { - console.warn(` Skipping: could not read ${config.metaFile}`) - continue - } - - // Extract existing model IDs (normalized) and constant names - const existingIds = extractExistingModelIds(content) - const existingConstNames = extractExistingConstNames(content) - - console.log( - ` Existing models in file: ${existingIds.size} IDs, ${existingConstNames.size} constants`, - ) - - // Find new models - const newModels: Array<{ - model: OpenRouterModel - constName: string - strippedId: string - }> = [] - - for (const model of providerModels) { - if (isRoutingAlias(model.id)) { - continue - } - - const strippedId = stripPrefix(prefix, model.id) - const nativeId = toNativeProviderId(strippedId, config.kind) - const constName = toModelConstName(nativeId) - - // Skip models with ':' variants (e.g., 'anthropic/claude-3.7-sonnet:thinking') - // These are routing variants, not separate models - if (strippedId.includes(':')) { - continue - } - - // Skip non-chat model families (audio/music/video/image generation) - if (isNonChatModel(strippedId)) { - continue - } - - // Skip provider-specific patterns (deprecated/legacy model families) - if (matchesSkipPattern(strippedId, config.skipPatterns)) { - continue - } - - // Skip models that are too old (created >30 days before last sync) - if (isModelTooOld(model, cutoffTimestamp)) { - continue - } - - // Normalize for comparison to handle dots-vs-dashes naming differences - if ( - !existingIds.has(normalizeId(strippedId)) && - !existingConstNames.has(constName) - ) { - newModels.push({ model, constName, strippedId: nativeId }) - } - } - - if (newModels.length === 0) { - console.log(' No new models to add.') - continue - } - - console.log(` Adding ${newModels.length} new models:`) - for (const { strippedId, constName } of newModels) { - console.log(` - ${strippedId} (${constName})`) - } - - // Filter out image-generation models (they need manual curation for - // size/provider type maps + the native image union). This includes - // text+image models like the Gemini "Nano Banana" native image family, - // not just image-only models. - const filteredModels = newModels.filter(({ model }) => !outputsImage(model)) - const skippedImageModels = newModels.length - filteredModels.length - if (skippedImageModels > 0) { - console.log( - ` Skipping ${skippedImageModels} image-generation models (require manual curation)`, - ) - } + const catalogs = await fetchSyncCatalogs(createSyncClient()) + const counts = Object.entries(catalogs) + .map(([id, rows]) => `${id}=${rows.length}`) + .join(', ') + console.log(`Fetched modelschemas catalogs: ${counts}`) - if (filteredModels.length === 0) { - console.log(' No eligible models to add after filtering.') - continue - } - - // Generate constants - const constants = filteredModels.map(({ model }) => - generateModelConstant(model, prefix, config), - ) - - // Insert constants before first export - content = insertConstants(content, constants) - - // NOTE: We intentionally do NOT add models to image arrays. - // Image model arrays have specialized type maps (sizes, provider options) - // that require manual curation. - - const chatModels = filteredModels.filter(({ model }) => outputsText(model)) - content = applyChatModelCatalogInserts( - content, - { - chatArrayName: config.chatArrayName, - arrayRef: config.arrayRef, - providerOptionsTypeName: config.providerOptionsTypeName, - inputModalitiesTypeName: config.inputModalitiesTypeName, - toolCapabilitiesTypeName: config.toolCapabilitiesTypeName, - maxOutputTokensMapName: config.maxOutputTokensMapName, - combinedToolsAndSchemaSetName: config.combinedToolsAndSchemaSetName, - providerOptionsIsMappedType: config.providerOptionsIsMappedType, - }, - chatModels.map(({ model, constName, strippedId }) => ({ - constName, - providerOptionsEntry: providerOptionsEntryFor(model, config), - hasMaxOutputTokens: Boolean(model.top_provider.max_completion_tokens), - acceptsCombinedToolsAndSchema: !strippedId.endsWith('-fast'), - })), + const changedPackages = new Set() + let totalAdded = 0 + for (const [provider, config] of Object.entries(PROVIDER_MAP) as Array< + [SyncedProvider, ProviderConfig] + >) { + const added = await syncModelMeta( + provider, + config, + catalogs, + cutoffTimestamp, ) - - // Write the modified file - await writeFile(config.metaFile, content, 'utf-8') - console.log(` Wrote updated file: ${config.metaFile}`) - totalAdded += filteredModels.length - changedPackages.add(config.packageName) + totalAdded += added + if (added > 0) changedPackages.add(config.packageName) } console.log(`\nDone. Added ${totalAdded} new models total.`) - // Record this run's timestamp for future age-based filtering await writeLastRunTimestamp() - // Detect all packages with uncommitted changes (includes changes from - // convert-openrouter-models.ts which runs before this script) const allChangedPackages = detectChangedPackages() for (const pkg of changedPackages) { allChangedPackages.add(pkg) @@ -704,48 +518,34 @@ async function main() { } } -/** - * Create or update the sync-models changeset file. - * If one already exists, merges the package lists. Otherwise creates a new one. - */ async function createChangeset(changedPackages: Set) { const changesetDir = resolve(ROOT, '.changeset') - const { readdir } = await import('node:fs/promises') - const files = await readdir(changesetDir) - const existing = files.find( + const existing = (await readdir(changesetDir)).find( (f) => f.startsWith('sync-models') && f.endsWith('.md'), ) - + const changesetPath = resolve(changesetDir, existing ?? 'sync-models.md') if (existing) { - const existingPath = resolve(changesetDir, existing) - const existingContent = await readFile(existingPath, 'utf-8') - - // Merge existing packages into the set - const pkgRegex = /'([^']+)':\s*patch/g - let match - while ((match = pkgRegex.exec(existingContent)) !== null) { + const existingContent = await readFile(changesetPath, 'utf-8') + for (const match of existingContent.matchAll(/'([^']+)':\s*patch/g)) { changedPackages.add(match[1]!) } - - const content = buildChangesetContent(changedPackages) - await writeFile(existingPath, content, 'utf-8') - console.log(`\nChangeset updated: ${existingPath}`) - } else { - const changesetFile = resolve(changesetDir, 'sync-models.md') - const content = buildChangesetContent(changedPackages) - await writeFile(changesetFile, content, 'utf-8') - console.log(`\nChangeset created: ${changesetFile}`) } - + await writeFile( + changesetPath, + buildChangesetContent(changedPackages), + 'utf-8', + ) + console.log( + `\nChangeset ${existing ? 'updated' : 'created'}: ${changesetPath}`, + ) console.log(` Packages: ${Array.from(changedPackages).sort().join(', ')}`) } - function buildChangesetContent(packages: Set): string { const packageLines = Array.from(packages) .sort() .map((pkg) => `'${pkg}': patch`) .join('\n') - return `---\n${packageLines}\n---\n\nUpdate model metadata from OpenRouter API\n` + return `---\n${packageLines}\n---\n\nUpdate model metadata from modelschemas\n` } main().catch((err) => { diff --git a/skills/tanstack-ai/SKILL.md b/skills/tanstack-ai/SKILL.md index a443e3c963..10128fe78e 100644 --- a/skills/tanstack-ai/SKILL.md +++ b/skills/tanstack-ai/SKILL.md @@ -90,6 +90,8 @@ lockfile shows which package manager to use. Things that trip agents up: +- Model prices: never from memory and never from `model-meta.ts` (it has + none). Read them live from modelschemas, as in `docs/advanced/model-prices.md`. - Model ids: never from memory. Most adapters ship them in `node_modules/@tanstack/ai-/src/model-meta.ts`; take the newest id with the capability the task needs. diff --git a/tsconfig.docs.json b/tsconfig.docs.json index 46a896715f..a846b65aa7 100644 --- a/tsconfig.docs.json +++ b/tsconfig.docs.json @@ -41,6 +41,12 @@ "./node_modules/.kiira/node_modules/@fal-ai/client/src/realtime/index.d.ts", "./examples/ts-react-media/node_modules/@fal-ai/client/src/realtime/index.d.ts" ], + "@modelschemas/rate-card/evaluator": [ + "./node_modules/.kiira/node_modules/@modelschemas/rate-card/dist/evaluator.d.ts" + ], + "@modelschemas/rate-card/schema": [ + "./node_modules/.kiira/node_modules/@modelschemas/rate-card/dist/rate-card.schema.d.ts" + ], "@upstash/agentkit-tanstack-ai/persistence": [ "./node_modules/.kiira/node_modules/@upstash/agentkit-tanstack-ai/dist/persistence.d.ts" ],