From b744a706f2321755f9ca16ab336cef5440a8a9b8 Mon Sep 17 00:00:00 2001 From: Rahul Karajgikar Date: Tue, 17 Feb 2026 22:15:13 +0530 Subject: [PATCH 01/25] docs(claude): add custom-plan command --- .claude/commands/custom-plan.md | 153 ++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 .claude/commands/custom-plan.md diff --git a/.claude/commands/custom-plan.md b/.claude/commands/custom-plan.md new file mode 100644 index 000000000..7a3738af6 --- /dev/null +++ b/.claude/commands/custom-plan.md @@ -0,0 +1,153 @@ +--- +description: "Create a structured feature plan using PLAN + WORKING_MEMORY + USER_VERIFICATION (tasklist) files" +allowed-tools: ["bash", "read", "glob", "grep", "task"] +--- + +# Custom Plan (PLAN + Working Memory + Tasklist) + +Create feature plans using the same paradigm as `feature-plans/image-and-core-di-refactor/`: +- `PLAN.md` is the source of truth (problem, goals, design, and a concrete tasklist). +- `WORKING_MEMORY.md` is the live scratchpad agents update while executing. +- `USER_VERIFICATION.md` is the owner-only decision + manual verification checklist. + +## 1) Create the plan directory + files + +Create a new directory: +- `feature-plans//` + +Add these three files: +- `feature-plans//PLAN.md` +- `feature-plans//WORKING_MEMORY.md` +- `feature-plans//USER_VERIFICATION.md` + +## 2) Write `PLAN.md` (durable, structured) + +At the top, link the other two files and state the update rules: + +```md +# + +**Working memory:** [`WORKING_MEMORY.md`](./WORKING_MEMORY.md) — read before starting work; update after each task. +**Owner verification list:** [`USER_VERIFICATION.md`](./USER_VERIFICATION.md) — add entries for owner-only decisions or manual checks; clear before shipping. +``` + +Recommended sections (adapt as needed): +1. **Problem** (current behavior + pain) +2. **Goals** (explicit outcomes) +3. **Non-goals** (what you’re not doing) +4. **Constraints** (compat, deadlines, security, performance, dependencies) +5. **Proposed design** (data model, APIs, UX flows, before/after behavior) +6. **Risks / mitigations** (what can go wrong, how we’ll detect it) +7. **Tasklist** (phases + numbered tasks with exit criteria) + +### Tasklist conventions + +Put a single, unambiguous execution checklist in the plan: +- Use **phases** for grouping (Phase 0, Phase 1, …). +- Use **task IDs** like `0.1`, `0.2`, `1.1`, etc. +- Each task should be “commit-sized” and include **Exit criteria** that can be verified. +- Prefer task text that names concrete files/symbols/commands. + +Example task shape: + +```md +## <N>. Tasklist + +### Phase 0 — Foundation +> Goal: <one sentence> + +- [ ] **0.1 <Task title>** + - Deliverables: <files, routes, UI screens, commands> + - Exit: <tests/commands/manual checks that prove it’s done> +``` + +### Owner-only decisions + +If you hit any unresolved decision that requires product judgment, credentials, or manual local verification: +- Add an item to `USER_VERIFICATION.md` immediately. +- Keep the main plan unblocked by marking the decision as deferred to verification. + +## 3) Write `WORKING_MEMORY.md` (live scratchpad) + +Purpose: capture what’s currently being worked on, what changed, and what was learned. + +Recommended structure: + +```md +# Working Memory — <Topic> + +> Live scratchpad for agents working through `PLAN.md`. Read before starting work. Update after each task. + +## How to use this file +1. Before starting: read Current Task + Key Decisions. +2. When starting a task: set Current Task (task ID + plan). +3. During: log findings/blockers/decisions in Notes. +4. After finishing: move it to Completed Tasks and set the next Current Task. +5. When you discover owner-only decisions/manual checks: add to `USER_VERIFICATION.md`. + +## Current Task +**Task:** <id + title> +**Status:** <in progress | blocked | waiting on owner | done> +**Branch:** <branch name> + +### Plan +- <bullets> + +### Notes +<dated log entries> + +## Key Decisions +| Date | Decision | Reasoning | +|------|----------|-----------| +| YYYY-MM-DD | … | … | + +## Open Questions / Blockers +- … + +## Completed Tasks +| Task | Title | Date | Notes | +|------|-------|------|-------| +| 0.1 | … | YYYY-MM-DD | … | +``` + +## 4) Write `USER_VERIFICATION.md` (owner checklist) + +Use this when something is: +- owner judgment (tradeoffs, “which option”), or +- manual verification (OAuth flows, API keys, smoke tests, UI polish), or +- environment-dependent (ports, external services). + +Recommended structure: + +```md +# Owner Verification — <Topic> + +## Open Items +| ID | Item | Why owner-only | Target phase | Status | Notes | +|----|------|----------------|--------------|--------|-------| +| UV-1 | … | … | 2.3 | Open | … | + +## Resolved Items +| ID | Decision / Verification | Date | Notes | +|----|--------------------------|------|-------| +| UV-0 | … | YYYY-MM-DD | … | +``` + +## 5) Committing changes in `feature-plans/` (gitignored) + +`feature-plans/` is gitignored, so you must force-add updates when committing. + +Stage explicitly (no `git add .` / `-A`): + +```bash +# Non-ignored files stage normally +git add .claude/commands/custom-plan.md + +# Feature plans must be force-added +git add -f feature-plans/<topic> + +git diff --staged +git commit -m "docs(feature-plans): <topic> plan updates" +``` + +For the rest of the session: **commit every time you change anything under `feature-plans/`** using `git add -f feature-plans/<topic>` so the updates don’t get lost. From 1bc1cb3ff20862ffcc88c2131b49df87c2e72412 Mon Sep 17 00:00:00 2001 From: Rahul Karajgikar <rahul@trytruffle.ai> Date: Tue, 17 Feb 2026 22:15:35 +0530 Subject: [PATCH 02/25] docs(feature-plans): add oauth provider connect plan --- .../oauth-and-more-providers/PLAN.md | 397 ++++++++++++++++++ .../USER_VERIFICATION.md | 37 ++ .../WORKING_MEMORY.md | 83 ++++ 3 files changed, 517 insertions(+) create mode 100644 feature-plans/oauth-and-more-providers/PLAN.md create mode 100644 feature-plans/oauth-and-more-providers/USER_VERIFICATION.md create mode 100644 feature-plans/oauth-and-more-providers/WORKING_MEMORY.md diff --git a/feature-plans/oauth-and-more-providers/PLAN.md b/feature-plans/oauth-and-more-providers/PLAN.md new file mode 100644 index 000000000..ce043226f --- /dev/null +++ b/feature-plans/oauth-and-more-providers/PLAN.md @@ -0,0 +1,397 @@ +# OAuth + Multi-Method Provider Connect + +This plan updates Dexto onboarding/login flows to support **multiple login methods per provider** (OAuth/subscription, BYOK API keys, device-code flows, “setup-token”-style flows) and expands the set of “first-class” providers where it’s worthwhile. + +**Working memory:** [`WORKING_MEMORY.md`](./WORKING_MEMORY.md) is a colocated scratchpad that agents should actively update while working through this plan. **Read it before starting work. Update it after each task.** + +**Owner verification list:** [`USER_VERIFICATION.md`](./USER_VERIFICATION.md) tracks **owner-only** decisions and manual checks we deliberately defer while implementing. **Add an entry whenever you discover an unresolved decision or an environment-dependent verification.** Clear the list before shipping. + +Primary references: +- **OpenClaw** (`~/Projects/external/openclaw`) — onboarding wizard + auth profiles + provider auth plugins. +- **OpenCode** (`~/Projects/external/opencode`) — `/connect` UX + models.dev-backed provider catalog + plugin auth methods. + +--- + +## 1. Problem + +Today Dexto largely treats provider auth as “do you have an API key env var?”, with an exception for `dexto-nova` (Dexto login → `DEXTO_API_KEY`). + +Ground truth in the repo today: +- **Provider API keys** are resolved from env vars (`packages/core/src/utils/api-key-resolver.ts`) and can be written via server routes (`packages/server/src/hono/routes/key.ts` → `@dexto/agent-management` writes to a context-aware `.env`). +- **Dexto account login** state lives in `~/.dexto/auth.json` (see `packages/cli/src/cli/auth/service.ts` and `packages/agent-management/src/utils/dexto-auth.ts`). The CLI loads `DEXTO_API_KEY` from this file early (`packages/cli/src/index-main.ts`) for `dexto-nova` routing. + +We want: +- **Per-provider auth method selection** (e.g. OpenAI: ChatGPT OAuth *or* API key). +- A clear **/connect** experience from the interactive CLI (and a corresponding WebUI flow). +- A single internal shape for “a provider supports these login methods”, so UX and behavior match what’s truly supported. + +--- + +## 2. Goals + +- Add a **`/connect`** interactive CLI command to connect a provider via one of its supported methods. +- Support **multiple login methods per provider** (when available), at minimum: + - **OpenAI**: API key + ChatGPT OAuth (Codex-style). + - **Anthropic**: API key + subscription token (“setup-token” flow, if viable). + - **Bedrock**: AWS bearer token + AWS credential chain guidance. +- Make provider auth **runtime-affecting**: + - OAuth tokens should be refreshable without forcing the user to re-login. + - The LLM factory should be able to apply provider-specific runtime options (headers/fetch/baseURL) depending on the active auth method. +- Keep **models.dev as the model registry source of truth** (we already do). + +--- + +## 3. Non-Goals (for this initial iteration) + +- Dynamically installing arbitrary provider SDK packages at runtime (OpenCode can because it’s Bun-first and leans on dynamic installs). +- Perfect parity with OpenCode’s “75+ direct providers” UX in v1. +- OpenClaw-style **profile rotation/failover** (cooldowns, usage-based ordering) in v1 — we’ll start with saved profiles + a single default profile per provider. + +--- + +## 4. Prior Art — OpenClaw (Concrete Observations) + +### 4.1 Method grouping in onboarding +- The onboarding wizard prompts a **provider group** first, then an **auth method** if the group has >1 option. + - Source: `~/Projects/external/openclaw/src/commands/auth-choice-options.ts` + - UX: `promptAuthChoiceGrouped()` in `~/Projects/external/openclaw/src/commands/auth-choice-prompt.ts` + +### 4.2 Auth profiles (multiple credentials per provider) +- Credentials are stored as **profiles** (e.g. `anthropic:default`, `openai-codex:default`) and config references a profile ID. +- Profiles support multiple credential modes (`api_key`, `token`, `oauth`) and include usage stats + cooldowns. + - Entry: `~/Projects/external/openclaw/src/agents/auth-profiles/*` + - Key resolver (including OAuth refresh): `~/Projects/external/openclaw/src/agents/auth-profiles/oauth.ts` + +### 4.3 OAuth flows with “VPS-aware” UX +- Shared helper supports: + - local browser open + localhost callback, OR + - remote/VPS mode that prints a URL and asks user to paste redirect/code. + - Source: `~/Projects/external/openclaw/src/commands/oauth-flow.ts` + +### 4.4 Provider auth plugins return “config patch + credentials” +- Provider plugins return: + - profiles to store, + - `configPatch` (models/providers + defaults), + - `defaultModel` suggestion, + - notes. + - Source types: `~/Projects/external/openclaw/src/plugins/types.ts` (`ProviderPlugin`, `ProviderAuthMethod`, `ProviderAuthResult`) + - Example OAuth provider plugin: `~/Projects/external/openclaw/extensions/minimax-portal-auth/index.ts` + +### 4.5 Model catalog is *not* models.dev +- OpenClaw uses `@mariozechner/pi-ai` model registry + `models.json` generation, and only bridges certain OAuth creds into `auth.json` for discovery. + - Source: `~/Projects/external/openclaw/src/agents/model-catalog.ts` + +Key takeaways to borrow: +- **Group provider → pick method** UX. +- **Credential profiles** and a resolver that can **refresh OAuth**. +- A shared OAuth UX helper that supports **headless/remote** flows. + +--- + +## 5. Prior Art — OpenCode (Concrete Observations) + +### 5.1 `/connect` UX (TUI) and a matching CLI flow +- TUI `/connect` launches a dialog: + 1) choose provider + 2) choose method (if provider has plugin-auth methods; otherwise default to API key) + 3) complete OAuth (device-code auto polling or code entry) or paste API key + - UI: `~/Projects/external/opencode/packages/app/src/components/dialog-select-provider.tsx` + - UI: `~/Projects/external/opencode/packages/app/src/components/dialog-connect-provider.tsx` +- CLI equivalent: `opencode auth login` + - Source: `~/Projects/external/opencode/packages/opencode/src/cli/cmd/auth.ts` + +### 5.2 Provider/model catalog from models.dev +- Providers/models are fetched + cached from models.dev: + - Source: `~/Projects/external/opencode/packages/opencode/src/provider/models.ts` +- Provider registry merges: + - models.dev → config overrides → env vars → stored keys → plugin OAuth → custom loaders + - Source: `~/Projects/external/opencode/packages/opencode/src/provider/provider.ts` + +### 5.3 Plugin auth methods for “OAuth vs API key” per provider +- Auth methods are per provider and can include multiple methods. +- OpenAI plugin supports both ChatGPT OAuth (browser callback + device-code) and API key. + - Source: `~/Projects/external/opencode/packages/opencode/src/plugin/codex.ts` +- GitHub Copilot uses device-code and supports enterprise variant selection. + - Source: `~/Projects/external/opencode/packages/opencode/src/plugin/copilot.ts` + +### 5.4 OAuth is *runtime-affecting*, not just “store a token” +- For ChatGPT OAuth, the plugin: + - injects `Authorization: Bearer <access token>` + - rewrites requests to `https://chatgpt.com/backend-api/codex/responses` + - refreshes the access token when expired + - Source: `~/Projects/external/opencode/packages/opencode/src/plugin/codex.ts` + +Key takeaways to borrow: +- A first-class **/connect** UX. +- A method list per provider, where OAuth methods are **two-phase** (authorize → callback). +- OAuth methods that can return **runtime request overrides** (headers/fetch/url rewriting). +- Strong alignment between **provider catalog** and **what can actually be connected**. + +--- + +## 6. Proposed Dexto Design + +### 6.1 Unify “provider auth methods” (types + registry) + +Add a module (location TBD; see `USER_VERIFICATION.md`) that defines: +- `ProviderAuthMethod` definitions and a registry keyed by provider (method metadata for CLI/WebUI/server). +- `ProviderAuthMethodKind`: `api_key | oauth_pkce | oauth_device_code | token | aws_chain | custom`. +- `ProviderAuthResult` for **persisted outputs** (credentials + metadata). +- `ProviderRuntimeAuth` for **runtime outputs** used by the LLM factory: + - `apiKey?: string` + - `headers?: Record<string,string>` + - `fetch?: typeof fetch` + - `baseURL?: string` + - `notes?: string[]` + +Important: for OpenAI “ChatGPT OAuth/Codex”, runtime behavior is different (bearer token + URL rewrite). This must be modeled as runtime overrides, not just “we got a key”. + +### 6.2 Credential storage: provider credentials + active method + +We need to support: +- multiple saved credential profiles per provider +- a per-provider default profile (so most users never touch agent config) +- OAuth refresh metadata (expires, refresh token, account/org ids) + +Proposed on-disk layout (subject to owner verification in `USER_VERIFICATION.md`): +- `~/.dexto/auth/` (new, `0o700`) + - `dexto.json` — Dexto account login state (migrate from legacy `~/.dexto/auth.json`). + - `llm-profiles.json` — LLM provider credential profiles + defaults. + +Backwards compatibility: +- Continue to read `~/.dexto/auth.json` (legacy) and migrate-on-write to `~/.dexto/auth/dexto.json`. + +`llm-profiles.json` should support: +- Multiple saved profiles per provider, keyed by `profileId` like `${providerId}:${name}` (examples: `openai:work`, `openai:codex-oauth`, `openrouter:team`). +- A per-provider default pointer so most users never touch agent config: + - `defaults[providerId] = profileId` +- Profile credential modes (`api_key`, `oauth`, `token`, …) with refresh metadata for OAuth (`expiresAt`, `refreshToken`, optional account/org ids). + +Resolution precedence (v1, proposed): +1) explicit `llm.apiKey` in agent config +2) optional explicit `llm.authProfileId` (if we ship it in v1) +3) default profile for `llm.provider` from `llm-profiles.json` +4) env var fallback (existing behavior) + +### 6.3 Server API (for WebUI + future remote clients) + +Add Hono routes in `packages/server/src/hono/routes/` analogous to the existing `/llm/key` surface: +- `GET /llm/auth/methods` → per-provider supported methods (labels + kinds + requirements). +- `GET /llm/auth/profiles` → list saved profiles (masked previews only) + per-provider defaults. +- `POST /llm/auth/profiles` → upsert a profile (API-key, token) or store an OAuth result. +- `POST /llm/auth/defaults` → set `defaults[providerId] = profileId`. +- `POST /llm/auth/api-key` → store BYOK (existing `/llm/key` can remain; we can alias/migrate). +- `POST /llm/auth/oauth/authorize` → returns `{ url, mode: auto|code, instructions, stateId }`. +- `POST /llm/auth/oauth/callback` → completes OAuth (with optional `code`) and persists credential. +- `GET /llm/auth/status` → per-provider connection status + which method is active (no secrets, masked previews only). + +Implementation note: +- Even for CLI-only first pass, designing the API as a **two-phase authorize/callback** flow reduces later churn. + +### 6.4 CLI UX + +#### 6.4.1 New interactive command: `/connect` +- Location: `packages/cli/src/cli/commands/interactive-commands/` +- Flow: + 1) pick provider (curated list first + search; align with `LLM_REGISTRY` curated scope) + 2) choose action: + - connect **new** profile, or + - switch **default** profile (if profiles exist), or + - manage profiles (remove/rename) (optional v1) + 3) for “connect new profile”: show supported methods for that provider + 4) run method flow: + - API key: paste, optional verify, store + - OAuth: open URL, auto-poll (device code) or ask for code/redirect URL (PKCE or remote mode) + - Token/setup-token: show instructions, paste token, store + 5) prompt: “Set as default for `${providerId}`?” (writes `defaults[providerId]`) + 6) optional: prompt to set default model (or defer to `/model`) + +#### 6.4.2 Update `dexto setup` onboarding +- Make `dexto setup` call the same underlying “connect provider” logic, rather than duplicating API key prompts. +- If `dexto-nova` is enabled, keep the current “login to Dexto” path as the simplest default, but allow “connect other providers” as a branch. +- Ensure “method choice” is provider-aware (OpenAI: OAuth vs BYOK). + +### 6.5 LLM factory integration (runtime correctness) + +Extend `packages/core/src/llm/services/factory.ts`: +- Replace `resolveApiKeyForProvider(provider)` with a new resolver that can return: + - BYOK API key, or + - OAuth-based runtime overrides for the provider. + +Initial target integrations: +- **OpenAI** + - `api_key` → current behavior + - `chatgpt_oauth_codex` → custom fetch: + - strip the SDK’s Authorization header + - inject `Bearer <access token>` + - refresh token when expired + - rewrite to Codex endpoint when calling Responses API +- **Anthropic** + - `api_key` → current behavior + - `setup_token` → treat token as the API key material if compatible with `@ai-sdk/anthropic` +- **Bedrock** + - keep AWS chain behavior + - add a “bearer token” method as a first-class connect option that stores `AWS_BEARER_TOKEN_BEDROCK` + +### 6.6 Provider expansion strategy (“more providers”) + +We should expand providers in two tiers: + +**Tier 1: native SDK providers we already basically support via OpenRouter/LiteLLM, but want first-class** +- Add `mistral`, `perplexity`, `together`, `deepseek`, `fireworks`, etc **only if** + - we can implement them cleanly in `factory.ts` using existing AI SDK packages, and + - we can define a stable env var + API key validation story. + +**Tier 2: “use gateway”** +- For everything else, steer to: + - `openrouter` (BYOK) or + - `litellm` (self-hosted) or + - `dexto-nova` (Dexto account) + +--- + +## 7. Provider / Method Matrix (Initial) + +| Provider | Methods to support in v1 | Notes | +|---|---|---| +| `dexto-nova` | Dexto login (existing) | WebUI currently instructs CLI login; keep that but expose status/methods via API. | +| `openai` | API key, ChatGPT OAuth (Codex) | OAuth requires request rewrite + refresh (see OpenCode plugin). | +| `anthropic` | API key, setup-token | Depends on token compatibility; if not viable, fallback to API key only. | +| `google` | API key | (Optional later) add Gemini CLI/Code Assist OAuth patterns if we see value. | +| `bedrock` | AWS chain, bearer token | Make bearer-token connect UX explicit; keep “chain” guidance. | +| `vertex` | ADC | Expose a “connect” flow that teaches `gcloud auth application-default login` + required env vars. | +| `openrouter` | API key | Already. | +| `litellm` | API key + baseURL | Already via setup/custom model. | +| `openai-compatible` | API key + baseURL + custom models | Already via custom model wizard; integrate with /connect for the provider-level credential if desired. | +| `glama` | API key | Already. | + +--- + +## 8. Tasklist + +### Phase 0 — Decisions + interface design +> **Goal:** settle storage/layout and define the internal shapes so CLI/WebUI/server can share a single source of truth. + +- [ ] **0.1 Decide auth storage layout + migration** + - Deliverables: + - Final on-disk layout for Dexto auth + LLM provider profiles (including permissions). + - Migration story from legacy `~/.dexto/auth.json`. + - Exit: + - `USER_VERIFICATION.md` contains the resolved decision and any explicit follow-ups. + +- [ ] **0.2 Define provider auth method + profile types** + - Deliverables: + - `ProviderAuthMethod`, `ProviderAuthMethodKind`, `ProviderAuthResult`, `ProviderRuntimeAuth`. + - `ProviderCredentialProfile` (stored credential material). + - Exit: + - Shared types are defined with no “shadow copies” (server + CLI consume the same types). + +- [ ] **0.3 Decide resolution precedence + config surface** + - Deliverables: + - Final precedence rules for `llm.apiKey` / `llm.authProfileId` / defaults / env. + - Decision whether we ship `llm.authProfileId` in v1. + - Exit: + - `USER_VERIFICATION.md` marks the decision resolved. + +### Phase 1 — Scaffolding + API surface (API keys + profile plumbing) +> **Goal:** ship a first working `/connect` for API-key methods + a stable server API surface for WebUI parity. + +- [ ] **1.1 Add LLM profile store in `@dexto/agent-management`** + - Deliverables: + - Read/write `llm-profiles.json` (or chosen store) with `0o600` files and atomic writes. + - List/upsert/delete profiles; set per-provider default. + - Exit: + - Unit coverage for parsing + write safety + basic CRUD. + +- [ ] **1.2 Add server routes for methods/profiles/defaults/status** + - Deliverables: + - Hono routes in `packages/server/src/hono/routes/` for methods, profiles, defaults, status. + - Keep `/llm/key` working; decide whether to alias/migrate it. + - Exit: + - Routes return stable JSON shapes and secrets are never returned. + +- [ ] **1.3 Add CLI interactive `/connect` (API key methods first)** + - Deliverables: + - New interactive command in `packages/cli/src/cli/commands/interactive-commands/`. + - Flow: choose provider → choose method → complete method → set default. + - Ability to switch default without re-auth (if multiple profiles exist). + - Exit: + - Manual CLI smoke: connect an API-key provider, set default, and confirm Dexto can run using it. + +- [ ] **1.4 Route `dexto setup` through the same connect logic** + - Deliverables: + - `dexto setup` reuses `/connect` internals rather than duplicating provider auth prompts. + - Exit: + - Setup path still works for Dexto login and at least one BYOK provider. + +### Phase 2 — OpenAI ChatGPT OAuth (Codex) +> **Goal:** make OAuth a first-class method whose tokens affect runtime requests (not just storage). + +- [ ] **2.1 Implement OpenAI OAuth authorize/callback flows + persistence** + - Deliverables: + - OAuth flow helper that supports local browser callback and headless/device-code paths. + - Persist token + refresh metadata in the profile store. + - Exit: + - Manual OAuth connect succeeds; token is stored; secrets are not logged. + +- [ ] **2.2 Implement refresh token logic** + - Deliverables: + - Refresh on expiry with safe concurrent refresh behavior. + - Exit: + - Unit tests cover refresh success/failure and persistence updates. + +- [ ] **2.3 Implement runtime wiring in `packages/core/src/llm/services/factory.ts`** + - Deliverables: + - Provider-specific runtime overrides for OpenAI OAuth (headers/fetch/baseURL/URL rewrite as needed). + - Exit: + - Regression tests cover request rewrite correctness (unit-level; network mocked). + +### Phase 3 — Anthropic setup-token (subscription) (if viable) +> **Goal:** add a second “non-api-key” method to validate the model. + +- [ ] **3.1 Add `setup-token` method UX + storage** + - Exit: + - Token is stored as a profile and can be selected as default. + +- [ ] **3.2 Validate runtime compatibility** + - Exit: + - Confirm compatibility with `@ai-sdk/anthropic`, or explicitly defer/remove this method for v1. + +### Phase 4 — Bedrock + Vertex first-class connect UX +> **Goal:** make non-key providers feel “connectable” (guided setup) even if they use ADC/credential chains. + +- [ ] **4.1 Add Bedrock connect UX (chain vs bearer token)** + - Exit: + - Clear UX for “store bearer token” and “use AWS credential chain” paths. + +- [ ] **4.2 Add Vertex connect UX (ADC guidance)** + - Exit: + - UX clearly guides `gcloud auth application-default login` + required env vars. + +### Phase 5 — WebUI parity +> **Goal:** WebUI reflects the same method-based auth model as the CLI. + +- [ ] **5.1 Add “Connect provider” UI** + - Exit: + - WebUI can list providers, show methods, and connect at least API-key methods via server API. + +- [ ] **5.2 Update “API keys” settings panel** + - Exit: + - WebUI shows connection status by method (not only “key exists”). + +--- + +## 9. Security / UX Notes + +- OAuth should support **headless** environments (device-code or “paste redirect URL” flows). +- Store secrets with `0o600` and avoid logging. +- If we keep localhost callback servers, ensure: + - random `state` + verification (OpenCode does; our current Supabase flow has limitations). + - short timeouts + clear cancellation paths. +- Prefer device-code where the upstream supports it (OpenCode’s headless ChatGPT method is a good template). + +--- + +## 10. Open Questions (tracked for owner) + +Owner-only questions and manual checks are tracked in `USER_VERIFICATION.md` (each item should map to a UV-* entry). Keep this section as a pointer, not a second source of truth. diff --git a/feature-plans/oauth-and-more-providers/USER_VERIFICATION.md b/feature-plans/oauth-and-more-providers/USER_VERIFICATION.md new file mode 100644 index 000000000..b9af179fa --- /dev/null +++ b/feature-plans/oauth-and-more-providers/USER_VERIFICATION.md @@ -0,0 +1,37 @@ +# Owner Verification — OAuth + Multi-Method Provider Connect + +> **This file tracks owner-only decisions and manual verifications that we defer while implementing.** +> Agents should keep it up to date throughout the work. + +--- + +## How to use this file + +1. **When a decision is deferred:** Add an item under “Open Items” with a short description and why it needs owner input. +2. **When a manual verification is required:** Add an item (e.g., “run OAuth E2E”, “confirm runtime request rewrite”, “choose between options A/B”). +3. **During implementation:** If you add a TODO that requires owner sign‑off, also add it here (so it doesn’t get lost). +4. **Before shipping:** Review this list and resolve/close everything, or explicitly defer items to a follow‑up plan. + +--- + +## Open Items + +| ID | Item | Why owner-only | Target phase | Status | Notes | +|----|------|----------------|--------------|--------|-------| +| UV-1 | Auth storage layout + migration | Affects backwards compatibility and security posture | 0.1 | Open | Decide whether to migrate `~/.dexto/auth.json` → `~/.dexto/auth/{dexto.json,llm-profiles.json}` vs extend the existing file vs alternate layout. | +| UV-2 | OpenAI Codex OAuth provider identity | Product/UX naming + config surface | 0.2 | Open | Decide `provider: openai + method=codex-oauth` vs a distinct provider ID (e.g., `openai-codex`). | +| UV-3 | `llm.authProfileId` in v1? | UX vs complexity tradeoff | 0.3 | Open | Decide whether per-agent pinning ships in v1 or defaults-per-provider only. | +| UV-4 | Where OAuth refresh logic lives | Architecture boundary decision | 2.2 | Open | Decide shared refresh helper vs per-provider method impl; core vs agent-management ownership. | +| UV-5 | Anthropic setup-token viability | Requires real-world validation + SDK behavior check | 3.2 | Open | If incompatible with `@ai-sdk/anthropic`, decide whether to drop this method for v1. | +| UV-6 | “More providers” scope for v1 | Product scope decision | 6.6 / Phase 1 | Open | Decide which providers become first-class in v1 vs steer to OpenRouter/LiteLLM/Dexto Nova. | +| UV-7 | Manual smoke: `/connect` UX | Requires local interactive runs | Phase 1+ | Open | Verify connect flow UX: create/switch default profiles, no secret leakage, file permissions are correct. | +| UV-8 | Manual smoke: OpenAI OAuth runtime behavior | Requires real OAuth account + network | Phase 2 | Open | Verify token refresh + request rewrite works end-to-end (including Responses API behavior). | +| UV-9 | Manual smoke: WebUI parity | Requires running WebUI | Phase 5 | Open | Verify WebUI reflects method-based auth and doesn’t regress existing API key settings. | + +--- + +## Resolved Items + +| ID | Decision / Verification | Date | Notes | +|----|--------------------------|------|-------| +| _TBD_ | | | | diff --git a/feature-plans/oauth-and-more-providers/WORKING_MEMORY.md b/feature-plans/oauth-and-more-providers/WORKING_MEMORY.md new file mode 100644 index 000000000..06ef013f7 --- /dev/null +++ b/feature-plans/oauth-and-more-providers/WORKING_MEMORY.md @@ -0,0 +1,83 @@ +# Working Memory — OAuth + Multi-Method Provider Connect + +> **This file is a live scratchpad for agents working through the OAuth provider connect plan.** +> Update it after completing each task. Read it before starting any task. + +--- + +## How to use this file + +1. **Before starting work:** Read the "Current Task" and "Key Decisions" sections to understand where things left off. +2. **When starting a task:** Update "Current Task" with the task ID, title, and your initial plan. +3. **During a task:** Log findings, blockers, and decisions in "Current Task Notes." +4. **After completing a task:** Move the task to "Completed Tasks," clear "Current Task Notes," and update "Current Task" to the next one. +5. **If you discover something unexpected:** Add it to "Open Questions / Blockers" or "Key Decisions." +6. **When you discover owner-only decisions or manual checks:** Add/update an item in `USER_VERIFICATION.md` (and mark items resolved when done). + +--- + +## Current Task + +**Task:** **Owner verification — UV-1..UV-* (plan gate)** +**Status:** _Waiting on owner_ +**Branch:** `oauth-provider-revamp` + +### Plan +- Review `feature-plans/oauth-and-more-providers/USER_VERIFICATION.md` and resolve key decisions (storage layout, provider ID strategy, config surface). +- Once UV items are cleared (or explicitly deferred), start Phase 0 tasks in `PLAN.md`. + +### Notes +_Log findings, issues, and progress here as you work._ + +2026-02-17: +- Imported the OAuth provider plan into this worktree and refactored it to the `PLAN.md` + `WORKING_MEMORY.md` + `USER_VERIFICATION.md` paradigm. +- Tasklist re-written with numbered tasks and explicit exit criteria. + +--- + +## Key Decisions + +_Record important decisions made during implementation that aren't in the main plan. Include date and reasoning._ + +| Date | Decision | Reasoning | +|------|----------|-----------| +| _TBD_ | | | + +--- + +## Open Questions / Blockers + +- See `feature-plans/oauth-and-more-providers/USER_VERIFICATION.md` for owner-only questions. + +--- + +## Completed Tasks + +_Move tasks here after completion. Keep a brief log of what was done and any deviations from the plan._ + +| Task | Title | Date | Notes | +|------|-------|------|-------| +| _TBD_ | | | | + +--- + +## Phase Progress + +| Phase | Status | Notes | +|-------|--------|-------| +| Phase 0 — Decisions + interface design | Not started | — | +| Phase 1 — Scaffolding + API surface | Not started | — | +| Phase 2 — OpenAI ChatGPT OAuth (Codex) | Not started | — | +| Phase 3 — Anthropic setup-token (if viable) | Not started | — | +| Phase 4 — Bedrock + Vertex connect UX | Not started | — | +| Phase 5 — WebUI parity | Not started | — | + +--- + +## Checkpoint Log + +_Record checkpoint validation results after each phase boundary._ + +| Phase boundary | Date | Result | Issues | +|----------------|------|--------|--------| +| _TBD_ | | | | From 97f3c5ff58ac6df85abfe732e0dff88a34db2f5c Mon Sep 17 00:00:00 2001 From: Rahul Karajgikar <rahul@trytruffle.ai> Date: Tue, 17 Feb 2026 22:26:54 +0530 Subject: [PATCH 03/25] docs(feature-plans): add opencode/openclaw reference pointers --- .../oauth-and-more-providers/PLAN.md | 49 +++++++++++++++++-- .../WORKING_MEMORY.md | 1 + 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/feature-plans/oauth-and-more-providers/PLAN.md b/feature-plans/oauth-and-more-providers/PLAN.md index ce043226f..cd2140dbf 100644 --- a/feature-plans/oauth-and-more-providers/PLAN.md +++ b/feature-plans/oauth-and-more-providers/PLAN.md @@ -18,6 +18,9 @@ Today Dexto largely treats provider auth as “do you have an API key env var? Ground truth in the repo today: - **Provider API keys** are resolved from env vars (`packages/core/src/utils/api-key-resolver.ts`) and can be written via server routes (`packages/server/src/hono/routes/key.ts` → `@dexto/agent-management` writes to a context-aware `.env`). +- **Provider key storage helpers** live in `@dexto/agent-management`: + - `packages/agent-management/src/utils/api-key-store.ts` (`saveProviderApiKey()`, `getProviderKeyStatus()`, Bedrock special-casing) + - `packages/agent-management/src/utils/api-key-resolver.ts` (env var resolution mirror) - **Dexto account login** state lives in `~/.dexto/auth.json` (see `packages/cli/src/cli/auth/service.ts` and `packages/agent-management/src/utils/dexto-auth.ts`). The CLI loads `DEXTO_API_KEY` from this file early (`packages/cli/src/index-main.ts`) for `dexto-nova` routing. We want: @@ -59,14 +62,15 @@ We want: ### 4.2 Auth profiles (multiple credentials per provider) - Credentials are stored as **profiles** (e.g. `anthropic:default`, `openai-codex:default`) and config references a profile ID. - Profiles support multiple credential modes (`api_key`, `token`, `oauth`) and include usage stats + cooldowns. - - Entry: `~/Projects/external/openclaw/src/agents/auth-profiles/*` - - Key resolver (including OAuth refresh): `~/Projects/external/openclaw/src/agents/auth-profiles/oauth.ts` + - Credential + store types: `~/Projects/external/openclaw/src/agents/auth-profiles/types.ts` + - Store persistence + locking + legacy coercion: `~/Projects/external/openclaw/src/agents/auth-profiles/store.ts` + - Key resolver (including OAuth refresh + fallback behaviors): `~/Projects/external/openclaw/src/agents/auth-profiles/oauth.ts` ### 4.3 OAuth flows with “VPS-aware” UX - Shared helper supports: - local browser open + localhost callback, OR - remote/VPS mode that prints a URL and asks user to paste redirect/code. - - Source: `~/Projects/external/openclaw/src/commands/oauth-flow.ts` + - Source: `~/Projects/external/openclaw/src/commands/oauth-flow.ts` (`createVpsAwareOAuthHandlers()`) ### 4.4 Provider auth plugins return “config patch + credentials” - Provider plugins return: @@ -97,6 +101,7 @@ Key takeaways to borrow: 3) complete OAuth (device-code auto polling or code entry) or paste API key - UI: `~/Projects/external/opencode/packages/app/src/components/dialog-select-provider.tsx` - UI: `~/Projects/external/opencode/packages/app/src/components/dialog-connect-provider.tsx` + - TUI (terminal) equivalent: `~/Projects/external/opencode/packages/opencode/src/cli/cmd/tui/component/dialog-provider.tsx` - CLI equivalent: `opencode auth login` - Source: `~/Projects/external/opencode/packages/opencode/src/cli/cmd/auth.ts` @@ -106,6 +111,7 @@ Key takeaways to borrow: - Provider registry merges: - models.dev → config overrides → env vars → stored keys → plugin OAuth → custom loaders - Source: `~/Projects/external/opencode/packages/opencode/src/provider/provider.ts` + - Stored credential file shape + permissions: `~/Projects/external/opencode/packages/opencode/src/auth/index.ts` (writes `auth.json` with `0o600`) ### 5.3 Plugin auth methods for “OAuth vs API key” per provider - Auth methods are per provider and can include multiple methods. @@ -113,6 +119,9 @@ Key takeaways to borrow: - Source: `~/Projects/external/opencode/packages/opencode/src/plugin/codex.ts` - GitHub Copilot uses device-code and supports enterprise variant selection. - Source: `~/Projects/external/opencode/packages/opencode/src/plugin/copilot.ts` + - Server-side two-phase OAuth orchestration (authorize → callback) and pending-state handling: + - `~/Projects/external/opencode/packages/opencode/src/provider/auth.ts` + - `~/Projects/external/opencode/packages/opencode/src/server/routes/provider.ts` ### 5.4 OAuth is *runtime-affecting*, not just “store a token” - For ChatGPT OAuth, the plugin: @@ -120,6 +129,12 @@ Key takeaways to borrow: - rewrites requests to `https://chatgpt.com/backend-api/codex/responses` - refreshes the access token when expired - Source: `~/Projects/external/opencode/packages/opencode/src/plugin/codex.ts` + - Key implementation details worth copying (see `CodexAuthPlugin()`): + - Localhost PKCE callback server (default port `1455`) + `state` verification + - Headless device-code flow (`/api/accounts/deviceauth/usercode` → poll `/api/accounts/deviceauth/token`) + - Token exchange/refresh against `${ISSUER}/oauth/token` + - Request rewrite triggers on `/v1/responses` and `/chat/completions` + - Optional `ChatGPT-Account-Id` header derived from JWT claims (`id_token` / `access_token`) Key takeaways to borrow: - A first-class **/connect** UX. @@ -146,6 +161,13 @@ Add a module (location TBD; see `USER_VERIFICATION.md`) that defines: Important: for OpenAI “ChatGPT OAuth/Codex”, runtime behavior is different (bearer token + URL rewrite). This must be modeled as runtime overrides, not just “we got a key”. +Reference shapes worth copying: +- OpenCode provider auth types + server orchestration: + - `~/Projects/external/opencode/packages/opencode/src/provider/auth.ts` (`ProviderAuth.Method`, `ProviderAuth.Authorization`, `authorize()`, `callback()`) + - `~/Projects/external/opencode/packages/opencode/src/server/routes/provider.ts` (`/:providerID/oauth/authorize` and `/:providerID/oauth/callback`) +- OpenClaw provider auth plugin types (profiles + config patch concept): + - `~/Projects/external/openclaw/src/plugins/types.ts` (`ProviderAuthMethod`, `ProviderAuthResult`, `ProviderAuthContext`) + ### 6.2 Credential storage: provider credentials + active method We need to support: @@ -173,6 +195,11 @@ Resolution precedence (v1, proposed): 3) default profile for `llm.provider` from `llm-profiles.json` 4) env var fallback (existing behavior) +Reference implementations: +- OpenCode auth storage (single auth entry per provider): `~/Projects/external/opencode/packages/opencode/src/auth/index.ts` +- OpenClaw auth profile store (multiple profiles + refresh + file locking): `~/Projects/external/openclaw/src/agents/auth-profiles/store.ts`, `~/Projects/external/openclaw/src/agents/auth-profiles/types.ts`, `~/Projects/external/openclaw/src/agents/auth-profiles/oauth.ts` +- Dexto current Dexto-account auth file (legacy): `packages/cli/src/cli/auth/service.ts`, `packages/agent-management/src/utils/dexto-auth.ts` + ### 6.3 Server API (for WebUI + future remote clients) Add Hono routes in `packages/server/src/hono/routes/` analogous to the existing `/llm/key` surface: @@ -188,6 +215,11 @@ Add Hono routes in `packages/server/src/hono/routes/` analogous to the existing Implementation note: - Even for CLI-only first pass, designing the API as a **two-phase authorize/callback** flow reduces later churn. +Reference server API: +- OpenCode routes: `~/Projects/external/opencode/packages/opencode/src/server/routes/provider.ts` (GET `/providers/auth`, POST `/:providerID/oauth/authorize`, POST `/:providerID/oauth/callback`) +- OpenCode orchestration + pending-state: `~/Projects/external/opencode/packages/opencode/src/provider/auth.ts` +- Dexto existing API-key route: `packages/server/src/hono/routes/key.ts` + ### 6.4 CLI UX #### 6.4.1 New interactive command: `/connect` @@ -206,6 +238,11 @@ Implementation note: 5) prompt: “Set as default for `${providerId}`?” (writes `defaults[providerId]`) 6) optional: prompt to set default model (or defer to `/model`) +Reference UX flows: +- OpenCode CLI flow (method selection + auto/code handling + extra prompts): `~/Projects/external/opencode/packages/opencode/src/cli/cmd/auth.ts` (`handlePluginAuth()`) +- OpenCode TUI dialog flow: `~/Projects/external/opencode/packages/opencode/src/cli/cmd/tui/component/dialog-provider.tsx` +- OpenClaw grouped provider → method prompt: `~/Projects/external/openclaw/src/commands/auth-choice-prompt.ts`, `~/Projects/external/openclaw/src/commands/auth-choice-options.ts` + #### 6.4.2 Update `dexto setup` onboarding - Make `dexto setup` call the same underlying “connect provider” logic, rather than duplicating API key prompts. - If `dexto-nova` is enabled, keep the current “login to Dexto” path as the simplest default, but allow “connect other providers” as a branch. @@ -218,6 +255,12 @@ Extend `packages/core/src/llm/services/factory.ts`: - BYOK API key, or - OAuth-based runtime overrides for the provider. +Reference runtime override patterns: +- OpenCode Codex runtime override: `~/Projects/external/opencode/packages/opencode/src/plugin/codex.ts` (strip auth header, set Bearer token, rewrite URL, refresh on expiry, optional `ChatGPT-Account-Id`) +- OpenCode Copilot runtime override: `~/Projects/external/opencode/packages/opencode/src/plugin/copilot.ts` (device-code auth + header rewrite + enterprise baseURL) +- OpenClaw OAuth refresh-with-lock pattern: `~/Projects/external/openclaw/src/agents/auth-profiles/oauth.ts` (`withFileLock` + refresh + persist) +- Dexto current factory: `packages/core/src/llm/services/factory.ts` + Initial target integrations: - **OpenAI** - `api_key` → current behavior diff --git a/feature-plans/oauth-and-more-providers/WORKING_MEMORY.md b/feature-plans/oauth-and-more-providers/WORKING_MEMORY.md index 06ef013f7..48cf2afa1 100644 --- a/feature-plans/oauth-and-more-providers/WORKING_MEMORY.md +++ b/feature-plans/oauth-and-more-providers/WORKING_MEMORY.md @@ -32,6 +32,7 @@ _Log findings, issues, and progress here as you work._ 2026-02-17: - Imported the OAuth provider plan into this worktree and refactored it to the `PLAN.md` + `WORKING_MEMORY.md` + `USER_VERIFICATION.md` paradigm. - Tasklist re-written with numbered tasks and explicit exit criteria. +- Read through OpenCode/OpenClaw reference implementations and updated `PLAN.md` with concrete file-path pointers for OAuth flows, storage shapes, and two-phase authorize/callback APIs. --- From b4c1ce1f2d4f3d34840cfd516b9c66649a2237d7 Mon Sep 17 00:00:00 2001 From: Rahul Karajgikar <rahul@trytruffle.ai> Date: Tue, 17 Feb 2026 23:54:51 +0530 Subject: [PATCH 04/25] docs(feature-plans): expand oauth plan for more providers --- .../oauth-and-more-providers/PLAN.md | 294 +++++++++++++++--- .../USER_VERIFICATION.md | 23 +- .../WORKING_MEMORY.md | 11 +- 3 files changed, 273 insertions(+), 55 deletions(-) diff --git a/feature-plans/oauth-and-more-providers/PLAN.md b/feature-plans/oauth-and-more-providers/PLAN.md index cd2140dbf..a754ee321 100644 --- a/feature-plans/oauth-and-more-providers/PLAN.md +++ b/feature-plans/oauth-and-more-providers/PLAN.md @@ -28,6 +28,14 @@ We want: - A clear **/connect** experience from the interactive CLI (and a corresponding WebUI flow). - A single internal shape for “a provider supports these login methods”, so UX and behavior match what’s truly supported. +Known complications / gaps: +- **OpenAI Codex OAuth may require allowlisting** (expected failure mode for many accounts). We must implement it with graceful fallback messaging to API key mode. +- **OAuth client IDs / redirect URIs are product-critical**. We must use Dexto-owned OAuth app credentials (don’t copy OpenCode/OpenClaw client IDs). Redirect URIs must be registered; some providers may require allowlisting for our app. +- **Anthropic setup-token viability is uncertain** (we should implement until proven infeasible, then gate/remove). +- **Provider IDs are currently fixed** (`LLM_PROVIDERS` enum in `packages/core/src/llm/types.ts`). Supporting `moonshot`, `zai`, `minimax-cn`, etc. as first-class providers requires either: + - expanding the enum + LLM factory support, or + - treating them as `openai-compatible` presets (provider-specific baseURL + env-var naming) without adding new provider IDs. + --- ## 2. Goals @@ -37,10 +45,15 @@ We want: - **OpenAI**: API key + ChatGPT OAuth (Codex-style). - **Anthropic**: API key + subscription token (“setup-token” flow, if viable). - **Bedrock**: AWS bearer token + AWS credential chain guidance. +- Expand first-class provider support for key ecosystems we care about: + - **MiniMax**: API key (OpenAI-compatible) + MiniMax Portal OAuth (device-code style) + CN endpoint presets. + - **GLM / Z.AI**: API key + endpoint presets (coding/global, global/CN). + - **Kimi (Moonshot)**: API key + global/CN endpoint presets. - Make provider auth **runtime-affecting**: - OAuth tokens should be refreshable without forcing the user to re-login. - The LLM factory should be able to apply provider-specific runtime options (headers/fetch/baseURL) depending on the active auth method. - Keep **models.dev as the model registry source of truth** (we already do). +- Use models.dev metadata to reduce churn when expanding supported providers/models (connect UI list, env-var expectations, curated defaults). --- @@ -80,11 +93,38 @@ We want: - notes. - Source types: `~/Projects/external/openclaw/src/plugins/types.ts` (`ProviderPlugin`, `ProviderAuthMethod`, `ProviderAuthResult`) - Example OAuth provider plugin: `~/Projects/external/openclaw/extensions/minimax-portal-auth/index.ts` + - Example OAuth device-code/PKCE implementation: `~/Projects/external/openclaw/extensions/minimax-portal-auth/oauth.ts` ### 4.5 Model catalog is *not* models.dev - OpenClaw uses `@mariozechner/pi-ai` model registry + `models.json` generation, and only bridges certain OAuth creds into `auth.json` for discovery. - Source: `~/Projects/external/openclaw/src/agents/model-catalog.ts` +### 4.6 Provider presets (base URLs, default models, endpoints) +- MiniMax provider config (OpenAI-compatible + Anthropic-compatible + CN variants): + - `~/Projects/external/openclaw/src/commands/onboard-auth.models.ts` + - `~/Projects/external/openclaw/src/commands/onboard-auth.config-minimax.ts` +- Kimi (Moonshot) presets (global + CN base URLs): + - `~/Projects/external/openclaw/src/commands/onboard-auth.models.ts` + - `~/Projects/external/openclaw/src/commands/onboard-auth.config-core.ts` (`applyMoonshot*`) +- Z.AI / GLM presets (coding/global, global/CN endpoints): + - `~/Projects/external/openclaw/src/commands/onboard-auth.models.ts` + - `~/Projects/external/openclaw/src/commands/onboard-auth.config-core.ts` (`applyZai*`) + +### 4.7 Anthropic “setup-token” (subscription token) flow +- Interactive prompting + applying setup-token auth choice: + - `~/Projects/external/openclaw/src/commands/auth-choice.apply.anthropic.ts` + - `~/Projects/external/openclaw/src/commands/models/auth.ts` +- Viability checks (live test scaffolding): `~/Projects/external/openclaw/src/agents/anthropic.setup-token.live.test.ts` + +### 4.8 Auth resolution precedence + env var mapping +- OpenClaw’s provider auth resolution is effectively: + 1) explicit `profileId` (if passed), + 2) profile order (from store override or config), + 3) env var mapping (including `*_OAUTH_TOKEN` fallbacks), + 4) provider config `models.json` overrides. + - Resolver: `~/Projects/external/openclaw/src/agents/model-auth.ts` (`resolveApiKeyForProvider()`, `resolveEnvApiKey()`) + - Order logic: `~/Projects/external/openclaw/src/agents/auth-profiles/order.ts` (`resolveAuthProfileOrder()`) + Key takeaways to borrow: - **Group provider → pick method** UX. - **Credential profiles** and a resolver that can **refresh OAuth**. @@ -108,6 +148,12 @@ Key takeaways to borrow: ### 5.2 Provider/model catalog from models.dev - Providers/models are fetched + cached from models.dev: - Source: `~/Projects/external/opencode/packages/opencode/src/provider/models.ts` +- OpenCode uses **provider metadata** from models.dev to drive UX and runtime: + - `provider.env` (recommended env var names) + - `provider.api` (base URL for OpenAI/Anthropic-compatible endpoints) + - `provider.npm` (recommended Vercel AI SDK package, e.g. `@ai-sdk/openai-compatible` vs `@ai-sdk/anthropic`) + - `provider.doc` (docs link) + - Source: `~/Projects/external/opencode/packages/opencode/src/provider/provider.ts` (`fromModelsDevProvider()`, `fromModelsDevModel()`) - Provider registry merges: - models.dev → config overrides → env vars → stored keys → plugin OAuth → custom loaders - Source: `~/Projects/external/opencode/packages/opencode/src/provider/provider.ts` @@ -144,9 +190,75 @@ Key takeaways to borrow: --- -## 6. Proposed Dexto Design +## 6. Provider/Auth method diff (OpenCode vs OpenClaw vs Dexto) + +### 6.1 Dexto today (in this repo) +- Fixed provider enum: `packages/core/src/llm/types.ts` (`LLM_PROVIDERS`) +- API key resolution: `packages/core/src/utils/api-key-resolver.ts`, `packages/agent-management/src/utils/api-key-resolver.ts` +- Persisted API keys (writes `.env`): `packages/agent-management/src/utils/api-key-store.ts`, server route `packages/server/src/hono/routes/key.ts` +- Dexto login state (for `dexto-nova`): `packages/cli/src/cli/auth/service.ts` (writes `~/.dexto/auth.json`), env injection `packages/cli/src/index-main.ts` + +### 6.2 OpenCode today (reference) +- Auth storage (`auth.json`, `0o600`): `~/Projects/external/opencode/packages/opencode/src/auth/index.ts` +- Provider auth orchestration (two-phase authorize/callback + pending-state): `~/Projects/external/opencode/packages/opencode/src/provider/auth.ts` +- Server routes: `~/Projects/external/opencode/packages/opencode/src/server/routes/provider.ts` +- OAuth implementations: + - OpenAI Codex (PKCE + device-code + runtime request rewrite): `~/Projects/external/opencode/packages/opencode/src/plugin/codex.ts` + - GitHub Copilot (device-code + header rewrite + enterprise prompts): `~/Projects/external/opencode/packages/opencode/src/plugin/copilot.ts` + +### 6.3 OpenClaw today (reference) +- Provider/method choice grouping: `~/Projects/external/openclaw/src/commands/auth-choice-options.ts`, `~/Projects/external/openclaw/src/commands/auth-choice-prompt.ts` +- Provider plugin auth surface: `~/Projects/external/openclaw/src/plugins/types.ts` +- Auth profile store + refresh/locking: `~/Projects/external/openclaw/src/agents/auth-profiles/store.ts`, `~/Projects/external/openclaw/src/agents/auth-profiles/oauth.ts` +- MiniMax portal OAuth (device-code/PKCE style): `~/Projects/external/openclaw/extensions/minimax-portal-auth/oauth.ts` +- Z.AI / Moonshot presets: `~/Projects/external/openclaw/src/commands/onboard-auth.models.ts`, `~/Projects/external/openclaw/src/commands/onboard-auth.config-core.ts` + +### 6.4 Side-by-side provider/method matrix (detailed, in-scope) + +| Provider / group | OpenCode methods | OpenClaw methods | Dexto today | Dexto planned (v1) | +|---|---|---|---|---| +| `openai` | OAuth (ChatGPT Pro/Plus browser + headless) + API key (`~/Projects/external/opencode/packages/opencode/src/plugin/codex.ts`) | `openai-codex` (OAuth), `openai-api-key` (API key) (`~/Projects/external/openclaw/src/commands/auth-choice-options.ts`) | API key via env vars (`OPENAI_API_KEY`, `OPENAI_KEY`) | API key + Codex OAuth (browser + headless), allowlist-aware UX + runtime request rewrite | +| `anthropic` | API key | `token` / `setup-token` (paste), `apiKey` (API key) (`~/Projects/external/openclaw/src/commands/auth-choice.apply.anthropic.ts`) | API key via env vars (`ANTHROPIC_API_KEY`, etc.) | API key + setup-token (implement; gate/remove if infeasible) | +| `minimax` | API key (models.dev provider ID `minimax`, `minimax-coding-plan`) | `minimax-portal` (OAuth), plus API key presets (`minimax-api`, `minimax-api-key-cn`, `minimax-api-lightning`) (`~/Projects/external/openclaw/src/commands/auth-choice-options.ts`, `~/Projects/external/openclaw/extensions/minimax-portal-auth/oauth.ts`, `~/Projects/external/openclaw/src/commands/onboard-auth.config-minimax.ts`) | Provider exists (`minimax`) but current runtime assumes OpenAI-compatible baseURL (`packages/core/src/llm/services/factory.ts`) | API key presets (global/CN + coding-plan variants) + MiniMax Portal OAuth method; align runtime transport with models.dev + OpenClaw endpoint variants | +| `moonshotai` (Kimi) | API key (models.dev provider IDs `moonshotai`, `moonshotai-cn`) | `moonshot-api-key` (global), `moonshot-api-key-cn` (CN) (`~/Projects/external/openclaw/src/commands/auth-choice-options.ts`) | Not first-class provider ID; can be used via `openai-compatible` manually | Add Moonshot presets (global + CN) with models.dev provider IDs and OpenClaw baseURL constants; optionally add a first-class provider ID (Phase 0.2) | +| `kimi-for-coding` (Kimi Code) | API key (models.dev provider ID `kimi-for-coding`) | `kimi-code-api-key` (API key) (`~/Projects/external/openclaw/src/commands/auth-choice.apply.api-providers.ts`) | Not supported | Add Kimi Code preset (Anthropic-compatible) + API key connect method; ensure runtime can target Anthropic-compatible endpoints | +| `zhipuai` (GLM / BigModel) | API key (models.dev provider IDs `zhipuai`, `zhipuai-coding-plan`) | (OpenClaw’s “CN” Z.AI endpoints point at `open.bigmodel.cn`) (`~/Projects/external/openclaw/src/commands/onboard-auth.models.ts`) | Supported as provider `glm` with fixed baseURL `https://open.bigmodel.cn/api/paas/v4` (`packages/core/src/llm/services/factory.ts`) | Add presets for Zhipu base URLs (standard + coding plan), and decide whether to alias `glm` ↔ `zhipuai` in UX/config (Phase 0.2) | +| `zai` (Z.AI) | API key (models.dev provider IDs `zai`, `zai-coding-plan`) | `zai-*` endpoint presets (`zai-coding-global`, `zai-coding-cn`, `zai-global`, `zai-cn`) (`~/Projects/external/openclaw/src/commands/auth-choice-options.ts`, `~/Projects/external/openclaw/src/commands/onboard-auth.models.ts`) | Not first-class (closest is `glm` for `open.bigmodel.cn`) | Add Z.AI presets and decide env var mapping (`ZHIPU_API_KEY` per models.dev vs `ZAI_API_KEY` per OpenClaw) (Phase 0.2) | +| `bedrock` | (API key/creds) | (N/A) | AWS chain in factory; bearer token is recognized in status helpers (`packages/agent-management/src/utils/api-key-store.ts`) | `/connect` guidance + explicit method choices | +| `vertex` | ADC | (N/A) | ADC-only (`GOOGLE_VERTEX_PROJECT`, etc.) | `/connect` guidance + status surface | +| `openrouter` | API key | `openrouter-api-key` | API key env var | Add profiles + `/connect` UX + status | +| `litellm` | API key + baseURL | `litellm-api-key` | API key env var + baseURL required | Add profiles + `/connect` UX for baseURL + key | +| `dexto-nova` | (N/A) | (N/A) | Dexto login (`~/.dexto/auth.json` → `DEXTO_API_KEY`) | Move to new auth store + expose status/methods via API | + +### 6.4.1 Additional OAuth/token methods in prior art (useful references; not required for v1 unless requested) + +| Provider / group | OpenCode | OpenClaw | What this teaches us | +|---|---|---|---| +| `github-copilot` | OAuth device-code + enterprise prompts (`~/Projects/external/opencode/packages/opencode/src/plugin/copilot.ts`) | `github-copilot` / `copilot-proxy` (`~/Projects/external/openclaw/src/commands/auth-choice-options.ts`) | Device-code UX, multi-tenant baseURL handling, runtime header rewrite | +| `qwen-portal` | (API key default) | OAuth portal (`~/Projects/external/openclaw/src/commands/auth-choice-options.ts`) | Second OAuth provider beyond OpenAI/MiniMax | +| `chutes` | (API key default) | OAuth (`~/Projects/external/openclaw/src/commands/auth-choice-options.ts`) | Third OAuth provider; token-as-key patterns | +| `google-gemini-cli` / `google-antigravity` | (API key default) | OAuth (`~/Projects/external/openclaw/src/commands/auth-choice-options.ts`) | Headless OAuth UX and ADC-adjacent guidance | + +**Key gap today:** Dexto has no persisted per-provider profiles, no method registry, and no OAuth/device-code flows besides Dexto login for `dexto-nova`. + +### 6.5 Concrete provider endpoint + env-var diffs (models.dev vs OpenClaw vs Dexto) + +This is the “actionable diff” for GLM/Z.AI, MiniMax, and Kimi/Moonshot. It’s the minimum reference set needed while implementing presets and picking transports. + +| Ecosystem | models.dev (provider IDs → baseURL/API + env + SDK hint) | OpenClaw (provider IDs/choices → baseURL + env) | Dexto today (provider → baseURL + env) | Implication for this plan | +|---|---|---|---|---| +| **MiniMax** | `minimax` → `https://api.minimax.io/anthropic/v1`, `MINIMAX_API_KEY`, `@ai-sdk/anthropic` | `minimax` OpenAI-compatible: `DEFAULT_MINIMAX_BASE_URL = https://api.minimax.io/v1` (`onboard-auth.models.ts`); Anthropic-compatible: `MINIMAX_API_BASE_URL = https://api.minimax.io/anthropic`, `MINIMAX_CN_API_BASE_URL = https://api.minimaxi.com/anthropic` (`onboard-auth.config-minimax.ts`); env: `MINIMAX_API_KEY` / `MINIMAX_OAUTH_TOKEN` (`model-auth.ts`) | `minimax` → `https://api.minimax.chat/v1` + `MINIMAX_API_KEY` (`packages/core/src/llm/services/factory.ts`, `packages/core/src/utils/api-key-resolver.ts`) | MiniMax has **multiple official surfaces** (OpenAI-compatible vs Anthropic-compatible vs Portal OAuth). Our presets must choose a default and also expose variants. Expect we’ll need an **Anthropic-compatible runtime path** for models.dev alignment (and/or keep OpenAI-compatible as an optional preset). | +| **MiniMax (CN)** | `minimax-cn` → `https://api.minimaxi.com/anthropic/v1`, `MINIMAX_API_KEY`, `@ai-sdk/anthropic` | `minimax-api-key-cn` choice uses `api.minimaxi.com` (`auth-choice-options.ts`) + `MINIMAX_CN_API_BASE_URL` (`onboard-auth.config-minimax.ts`) | no first-class CN preset | Add CN preset(s) and make region explicit in `/connect`. | +| **Moonshot (Kimi)** | `moonshotai` → `https://api.moonshot.ai/v1`, `MOONSHOT_API_KEY`, `@ai-sdk/openai-compatible`; `moonshotai-cn` → `https://api.moonshot.cn/v1` | `moonshot` provider: `MOONSHOT_BASE_URL`, `MOONSHOT_CN_BASE_URL` (`onboard-auth.models.ts` / `onboard-auth.config-core.ts`); env: `MOONSHOT_API_KEY` (`model-auth.ts`) | not first-class; can be used via `openai-compatible` if user supplies `baseURL` + key | Moonshot is a clean **OpenAI-compatible preset**. We should ship both baseURLs + a small curated model list. | +| **Kimi Code / “for coding”** | `kimi-for-coding` → `https://api.kimi.com/coding/v1`, `KIMI_API_KEY`, `@ai-sdk/anthropic` | `kimi-coding` provider + `kimi-code-api-key` choice (`auth-choice.apply.api-providers.ts`); env: `KIMI_API_KEY` / `KIMICODE_API_KEY` (`model-auth.ts`) | not supported | This is an **Anthropic-compatible preset** (not OpenAI-compatible). Plan should include an Anthropic-compatible runtime transport/preset path. | +| **Zhipu AI (GLM / BigModel)** | `zhipuai` → `https://open.bigmodel.cn/api/paas/v4`, `ZHIPU_API_KEY`, `@ai-sdk/openai-compatible`; `zhipuai-coding-plan` → `https://open.bigmodel.cn/api/coding/paas/v4` | OpenClaw’s “CN” Z.AI endpoints also point at `open.bigmodel.cn` (`onboard-auth.models.ts`); env: `ZHIPU_API_KEY` (`model-auth.ts`) | `glm` → `https://open.bigmodel.cn/api/paas/v4` + `ZHIPU_API_KEY` | Dexto’s `glm` is already close to models.dev’s `zhipuai`. We should decide whether to alias/rename for consistency and add coding-plan presets. | +| **Z.AI (GLM / global)** | `zai` → `https://api.z.ai/api/paas/v4`, `ZHIPU_API_KEY`, `@ai-sdk/openai-compatible`; `zai-coding-plan` → `https://api.z.ai/api/coding/paas/v4` | OpenClaw uses baseURLs `api.z.ai` + `open.bigmodel.cn` variants (`onboard-auth.models.ts`), but env mapping differs: `ZAI_API_KEY` / `Z_AI_API_KEY` for `zai` (`model-auth.ts`) | no first-class; closest is `glm` | We need an owner decision: accept both env var schemes and/or prefer models.dev’s `ZHIPU_API_KEY`. Connect UX should make this explicit to avoid surprise. | + +--- -### 6.1 Unify “provider auth methods” (types + registry) +## 7. Proposed Dexto Design + +### 7.1 Unify “provider auth methods” (types + registry) Add a module (location TBD; see `USER_VERIFICATION.md`) that defines: - `ProviderAuthMethod` definitions and a registry keyed by provider (method metadata for CLI/WebUI/server). @@ -168,7 +280,7 @@ Reference shapes worth copying: - OpenClaw provider auth plugin types (profiles + config patch concept): - `~/Projects/external/openclaw/src/plugins/types.ts` (`ProviderAuthMethod`, `ProviderAuthResult`, `ProviderAuthContext`) -### 6.2 Credential storage: provider credentials + active method +### 7.2 Credential storage: provider credentials + active method We need to support: - multiple saved credential profiles per provider @@ -177,11 +289,12 @@ We need to support: Proposed on-disk layout (subject to owner verification in `USER_VERIFICATION.md`): - `~/.dexto/auth/` (new, `0o700`) - - `dexto.json` — Dexto account login state (migrate from legacy `~/.dexto/auth.json`). + - `dexto.json` — Dexto account login state (replaces legacy `~/.dexto/auth.json`). - `llm-profiles.json` — LLM provider credential profiles + defaults. Backwards compatibility: -- Continue to read `~/.dexto/auth.json` (legacy) and migrate-on-write to `~/.dexto/auth/dexto.json`. +- **Explicit non-goal:** we do not maintain compatibility with `~/.dexto/auth.json`. +- We will require the user to re-login to populate `~/.dexto/auth/dexto.json` (optionally we can add a one-time import command later, but it is not required for v1). `llm-profiles.json` should support: - Multiple saved profiles per provider, keyed by `profileId` like `${providerId}:${name}` (examples: `openai:work`, `openai:codex-oauth`, `openrouter:team`). @@ -195,12 +308,17 @@ Resolution precedence (v1, proposed): 3) default profile for `llm.provider` from `llm-profiles.json` 4) env var fallback (existing behavior) +Decision pending: whether precedence should be **hardcoded** (simple, predictable) vs **configured in the profile store** (more flexible, higher complexity). Candidate directions: +- **A: Hardcoded precedence (default)** — keep the list above; `llm.apiKey` remains the “escape hatch”. +- **B: Store-driven precedence** — profile store contains per-provider default + optional per-agent override, and env vars become a fallback that can be toggled/disabled. +- **C: “Profiles only” mode** — agent config never contains raw API keys; `/connect` becomes the single supported way to persist credentials. + Reference implementations: - OpenCode auth storage (single auth entry per provider): `~/Projects/external/opencode/packages/opencode/src/auth/index.ts` - OpenClaw auth profile store (multiple profiles + refresh + file locking): `~/Projects/external/openclaw/src/agents/auth-profiles/store.ts`, `~/Projects/external/openclaw/src/agents/auth-profiles/types.ts`, `~/Projects/external/openclaw/src/agents/auth-profiles/oauth.ts` - Dexto current Dexto-account auth file (legacy): `packages/cli/src/cli/auth/service.ts`, `packages/agent-management/src/utils/dexto-auth.ts` -### 6.3 Server API (for WebUI + future remote clients) +### 7.3 Server API (for WebUI + future remote clients) Add Hono routes in `packages/server/src/hono/routes/` analogous to the existing `/llm/key` surface: - `GET /llm/auth/methods` → per-provider supported methods (labels + kinds + requirements). @@ -220,9 +338,9 @@ Reference server API: - OpenCode orchestration + pending-state: `~/Projects/external/opencode/packages/opencode/src/provider/auth.ts` - Dexto existing API-key route: `packages/server/src/hono/routes/key.ts` -### 6.4 CLI UX +### 7.4 CLI UX -#### 6.4.1 New interactive command: `/connect` +#### 7.4.1 New interactive command: `/connect` - Location: `packages/cli/src/cli/commands/interactive-commands/` - Flow: 1) pick provider (curated list first + search; align with `LLM_REGISTRY` curated scope) @@ -243,12 +361,12 @@ Reference UX flows: - OpenCode TUI dialog flow: `~/Projects/external/opencode/packages/opencode/src/cli/cmd/tui/component/dialog-provider.tsx` - OpenClaw grouped provider → method prompt: `~/Projects/external/openclaw/src/commands/auth-choice-prompt.ts`, `~/Projects/external/openclaw/src/commands/auth-choice-options.ts` -#### 6.4.2 Update `dexto setup` onboarding +#### 7.4.2 Update `dexto setup` onboarding - Make `dexto setup` call the same underlying “connect provider” logic, rather than duplicating API key prompts. - If `dexto-nova` is enabled, keep the current “login to Dexto” path as the simplest default, but allow “connect other providers” as a branch. - Ensure “method choice” is provider-aware (OpenAI: OAuth vs BYOK). -### 6.5 LLM factory integration (runtime correctness) +### 7.5 LLM factory integration (runtime correctness) Extend `packages/core/src/llm/services/factory.ts`: - Replace `resolveApiKeyForProvider(provider)` with a new resolver that can return: @@ -276,14 +394,29 @@ Initial target integrations: - keep AWS chain behavior - add a “bearer token” method as a first-class connect option that stores `AWS_BEARER_TOKEN_BEDROCK` -### 6.6 Provider expansion strategy (“more providers”) - -We should expand providers in two tiers: - -**Tier 1: native SDK providers we already basically support via OpenRouter/LiteLLM, but want first-class** -- Add `mistral`, `perplexity`, `together`, `deepseek`, `fireworks`, etc **only if** - - we can implement them cleanly in `factory.ts` using existing AI SDK packages, and - - we can define a stable env var + API key validation story. +### 7.6 Provider expansion strategy (“more providers”) + +Since Dexto already consumes models.dev, we can expand providers in tiers with minimal churn by separating: +1) **Catalog/UX** (provider list + models + env var expectations), and +2) **Runtime transport** (how we actually talk to the provider). + +Implementation note (important): +- Our current models.dev sync (`scripts/sync-llm-registry.ts`) only snapshots **models**, and discards provider-level fields we need for “more providers” UX (`provider.api`, `provider.env`, `provider.npm`, `provider.doc`). +- Options: + - Extend the generator to emit provider metadata (e.g. `packages/core/src/llm/registry/providers.generated.ts`) and use it in `/connect`. + - Or fetch provider metadata at runtime and cache it (mirroring `packages/core/src/llm/registry/auto-update.ts` patterns). +- Reference implementation: OpenCode’s models.dev provider transform is already built around these fields (`~/Projects/external/opencode/packages/opencode/src/provider/provider.ts`). + +**Tier 1: first-class providers (minimal work)** +- **OpenAI-compatible providers with stable base URLs** (can be implemented as presets + `createOpenAI(...).chat()` in `factory.ts`): + - Examples (models.dev-aligned): `moonshotai` / `moonshotai-cn` (Kimi), `zhipuai` / `zhipuai-coding-plan` (GLM via `open.bigmodel.cn`), `zai` / `zai-coding-plan` (GLM via `api.z.ai`), and other OpenAI-compatible endpoints surfaced via models.dev. + - Requirements: + - stable baseURL (or a small set of well-known baseURL variants) + - stable env var mapping + - no special request signing +- **Anthropic-compatible providers with stable base URLs** (can be implemented as presets + `createAnthropic({ baseURL }).messages()`): + - Examples (models.dev-aligned): `minimax` / `minimax-cn` and `kimi-for-coding`. +- **Providers with specialized SDKs/signing** (Bedrock, Vertex, etc.) stay explicit and require targeted runtime work. **Tier 2: “use gateway”** - For everything else, steer to: @@ -293,46 +426,66 @@ We should expand providers in two tiers: --- -## 7. Provider / Method Matrix (Initial) +## 8. Provider / Preset / Method Matrix (Initial) -| Provider | Methods to support in v1 | Notes | +| Provider / preset | Methods to support in v1 | Notes | |---|---|---| | `dexto-nova` | Dexto login (existing) | WebUI currently instructs CLI login; keep that but expose status/methods via API. | | `openai` | API key, ChatGPT OAuth (Codex) | OAuth requires request rewrite + refresh (see OpenCode plugin). | | `anthropic` | API key, setup-token | Depends on token compatibility; if not viable, fallback to API key only. | | `google` | API key | (Optional later) add Gemini CLI/Code Assist OAuth patterns if we see value. | +| `minimax` / `minimax-cn` | API key, MiniMax Portal OAuth, CN presets | models.dev indicates Anthropic-compatible baseURLs; OpenClaw also supports OpenAI-compatible variants. We should ship presets for both and choose a default. | +| `moonshotai` / `moonshotai-cn` | API key, global/CN presets | OpenAI-compatible; models.dev provides canonical baseURLs + env var hints; OpenClaw presets also exist. | +| `kimi-for-coding` | API key | Anthropic-compatible preset (distinct from Moonshot). | +| `zhipuai` / `zhipuai-coding-plan` | API key, endpoint presets | OpenAI-compatible; likely aliases Dexto’s current `glm` (owner decision). | +| `zai` / `zai-coding-plan` | API key, endpoint presets | OpenAI-compatible; env var mapping differs between models.dev and OpenClaw (Phase 0.2). | +| `glm` | API key | Existing Dexto provider; decide whether it becomes an alias to `zhipuai` or remains as-is (Phase 0.2). | | `bedrock` | AWS chain, bearer token | Make bearer-token connect UX explicit; keep “chain” guidance. | | `vertex` | ADC | Expose a “connect” flow that teaches `gcloud auth application-default login` + required env vars. | | `openrouter` | API key | Already. | | `litellm` | API key + baseURL | Already via setup/custom model. | | `openai-compatible` | API key + baseURL + custom models | Already via custom model wizard; integrate with /connect for the provider-level credential if desired. | +| `anthropic-compatible` (proposed) | API key + baseURL + custom models | Needed for models.dev-aligned presets like `minimax` and `kimi-for-coding` without pretending they’re Anthropic proper. | | `glama` | API key | Already. | --- -## 8. Tasklist +## 9. Tasklist ### Phase 0 — Decisions + interface design > **Goal:** settle storage/layout and define the internal shapes so CLI/WebUI/server can share a single source of truth. -- [ ] **0.1 Decide auth storage layout + migration** +- [ ] **0.1 Decide auth storage layout (breaking change)** - Deliverables: - Final on-disk layout for Dexto auth + LLM provider profiles (including permissions). - - Migration story from legacy `~/.dexto/auth.json`. + - Confirm the breaking-change stance: **no backwards-compat support** for legacy `~/.dexto/auth.json` (require re-login to populate the new store). - Exit: - `USER_VERIFICATION.md` contains the resolved decision and any explicit follow-ups. -- [ ] **0.2 Define provider auth method + profile types** +- [ ] **0.2 Decide provider identity + preset strategy (models.dev-driven)** + - Deliverables: + - Decide whether our user-facing provider IDs should align with **models.dev provider IDs** (example set: `moonshotai`, `moonshotai-cn`, `zai`, `zai-coding-plan`, `zhipuai`, `zhipuai-coding-plan`, `minimax`, `minimax-cn`, `kimi-for-coding`) vs remain “Dexto-local” (`glm`, `minimax`, etc.) with aliases. + - Define “preset” behavior (the core abstraction for “more providers”): + - which **transport** a preset uses (`openai-compatible` vs `anthropic-compatible` vs first-class SDK), + - which baseURL variants exist (global/CN, coding-plan vs standard), + - which env var names we display/accept (models.dev vs OpenClaw conventions, e.g. `ZHIPU_API_KEY` vs `ZAI_API_KEY`), + - which default model(s) we surface. + - Decide how models.dev provider metadata maps to connect UX (provider list, labels, baseURL hints, env var hints, curated defaults). + - Exit: + - Provider/method matrix updated and `USER_VERIFICATION.md` captures the choice. + +- [ ] **0.3 Define provider auth method + profile types** - Deliverables: - `ProviderAuthMethod`, `ProviderAuthMethodKind`, `ProviderAuthResult`, `ProviderRuntimeAuth`. - `ProviderCredentialProfile` (stored credential material). - Exit: - Shared types are defined with no “shadow copies” (server + CLI consume the same types). -- [ ] **0.3 Decide resolution precedence + config surface** +- [ ] **0.4 Decide resolution precedence + config surface** - Deliverables: - Final precedence rules for `llm.apiKey` / `llm.authProfileId` / defaults / env. - Decision whether we ship `llm.authProfileId` in v1. + - Decision whether precedence is hardcoded vs configured in the profile store (e.g., OpenClaw-style ordered profiles: `~/Projects/external/openclaw/src/agents/auth-profiles/order.ts`). - Exit: - `USER_VERIFICATION.md` marks the decision resolved. @@ -367,64 +520,123 @@ We should expand providers in two tiers: - Exit: - Setup path still works for Dexto login and at least one BYOK provider. -### Phase 2 — OpenAI ChatGPT OAuth (Codex) +### Phase 2 — Provider presets + “more providers” foundation (MiniMax / Z.AI / Moonshot / Kimi) +> **Goal:** make these providers connectable + runnable with minimal per-provider work, leveraging models.dev metadata and OpenAI-compatible presets where possible. + +- [ ] **2.1 Add provider preset catalog (models.dev-seeded; baseURL + env + transport)** + - Deliverables: + - A single place that defines **provider presets** with fields like: + - `modelsDevProviderId` (string, e.g. `moonshotai-cn`) + - `transport` (e.g. `openai-compatible` vs `anthropic-compatible` vs first-class SDK) + - `baseURL` (from models.dev `provider.api` when present, or curated override) + - `envVars` (from models.dev `provider.env` + any Dexto aliases) + - `docUrl` (from models.dev `provider.doc`, optional) + - `defaultModel` + curated model list (optional) + - Initial curated presets (at minimum): + - **MiniMax**: `minimax`, `minimax-cn`, `minimax-coding-plan`, `minimax-cn-coding-plan` (Anthropic-compatible per models.dev; plus optional OpenAI-compatible variants if we keep them) + - **Zhipu/GLM**: `zhipuai`, `zhipuai-coding-plan` + - **Z.AI**: `zai`, `zai-coding-plan` + - **Moonshot/Kimi**: `moonshotai`, `moonshotai-cn` + - **Kimi Code**: `kimi-for-coding` (Anthropic-compatible per models.dev) + - Each preset maps to one or more `/connect` methods (API key, OAuth, token), plus display labels + hints. + - Exit: + - `/connect` can show these providers/methods and persist profiles for API-key methods. + +- [ ] **2.2 Implement chosen runtime strategy for new providers** + - Deliverables (based on Phase 0.2 decision): + - **If first-class providers:** extend `packages/core/src/llm/types.ts` (`LLM_PROVIDERS`), `packages/core/src/llm/services/factory.ts` (provider switch), and API-key env var mapping so the models.dev-aligned IDs (e.g. `moonshotai`, `zai`, `zhipuai`, `minimax-cn`, `kimi-for-coding`) can run without “custom model” hacks. + - **If preset-based (recommended for breadth):** + - ensure profiles carry `transport + baseURL + modelsDevProviderId` so runtime can choose the correct SDK surface: + - OpenAI-compatible: `createOpenAI({ baseURL }).chat(...)` + - Anthropic-compatible: `createAnthropic({ baseURL }).messages(...)` (or a dedicated `anthropic-compatible` driver if we don’t want to change `anthropic`) + - ensure models.dev provider IDs still show up in UX even if runtime uses a shared driver (`openai-compatible`, `anthropic-compatible`). + - Exit: + - Manual smoke: connect + run at least one model for each preset ecosystem (MiniMax / Z.AI / Zhipu / Moonshot / Kimi Code). + +- [ ] **2.3 Expand `/connect` provider list using models.dev** + - Deliverables: + - Provider picker uses models.dev **provider registry** for name + env vars + baseURL + model list, with a curated “top providers” grouping. + - Providers without special methods still get a default “API key” method (and “custom baseURL” when applicable). + - Exit: + - `/connect` can add an API-key profile for a models.dev provider without adding per-provider code (where transport is already supported). + +### Phase 3 — OpenAI ChatGPT OAuth (Codex) > **Goal:** make OAuth a first-class method whose tokens affect runtime requests (not just storage). -- [ ] **2.1 Implement OpenAI OAuth authorize/callback flows + persistence** +- [ ] **3.1 Implement OpenAI OAuth authorize/callback flows + persistence** - Deliverables: + - Dexto-owned OpenAI OAuth app config (client ID + allowed redirect URIs) and a safe place to store the client ID (non-secret) in-repo. - OAuth flow helper that supports local browser callback and headless/device-code paths. - Persist token + refresh metadata in the profile store. + - Allowlist-aware error handling + UX (clear message + fallback to API key). - Exit: - - Manual OAuth connect succeeds; token is stored; secrets are not logged. + - Manual OAuth connect succeeds (for allowlisted accounts); token is stored; secrets are not logged. -- [ ] **2.2 Implement refresh token logic** +- [ ] **3.2 Implement refresh token logic** - Deliverables: - Refresh on expiry with safe concurrent refresh behavior. - Exit: - Unit tests cover refresh success/failure and persistence updates. -- [ ] **2.3 Implement runtime wiring in `packages/core/src/llm/services/factory.ts`** +- [ ] **3.3 Implement runtime wiring in `packages/core/src/llm/services/factory.ts`** - Deliverables: - Provider-specific runtime overrides for OpenAI OAuth (headers/fetch/baseURL/URL rewrite as needed). - Exit: - Regression tests cover request rewrite correctness (unit-level; network mocked). -### Phase 3 — Anthropic setup-token (subscription) (if viable) +### Phase 4 — MiniMax Portal OAuth (device-code/PKCE) +> **Goal:** add a second OAuth method (MiniMax) to validate the method registry + refresh patterns beyond OpenAI. + +- [ ] **4.1 Implement MiniMax OAuth authorize/callback flows + persistence** + - Deliverables: + - Dexto-owned MiniMax OAuth app config (client ID + allowed redirect URIs) OR explicit confirmation that the public client ID we reference is intended for third-party clients. + - Device-code/PKCE-style flow modeled after OpenClaw’s implementation: + - `~/Projects/external/openclaw/extensions/minimax-portal-auth/oauth.ts` + - `~/Projects/external/openclaw/extensions/minimax-portal-auth/index.ts` + - Persist token + refresh metadata in the profile store. + - Exit: + - Manual MiniMax OAuth connect succeeds; token is stored; secrets are not logged. + +- [ ] **4.2 Implement refresh token logic + runtime usage** + - Exit: + - Confirm the runtime auth material needed by MiniMax (bearer token vs derived API key) and implement refresh accordingly. + +### Phase 5 — Anthropic setup-token (subscription) (if viable) > **Goal:** add a second “non-api-key” method to validate the model. -- [ ] **3.1 Add `setup-token` method UX + storage** +- [ ] **5.1 Add `setup-token` method UX + storage** - Exit: - Token is stored as a profile and can be selected as default. -- [ ] **3.2 Validate runtime compatibility** +- [ ] **5.2 Validate runtime compatibility** - Exit: - Confirm compatibility with `@ai-sdk/anthropic`, or explicitly defer/remove this method for v1. -### Phase 4 — Bedrock + Vertex first-class connect UX +### Phase 6 — Bedrock + Vertex first-class connect UX > **Goal:** make non-key providers feel “connectable” (guided setup) even if they use ADC/credential chains. -- [ ] **4.1 Add Bedrock connect UX (chain vs bearer token)** +- [ ] **6.1 Add Bedrock connect UX (chain vs bearer token)** - Exit: - Clear UX for “store bearer token” and “use AWS credential chain” paths. -- [ ] **4.2 Add Vertex connect UX (ADC guidance)** +- [ ] **6.2 Add Vertex connect UX (ADC guidance)** - Exit: - UX clearly guides `gcloud auth application-default login` + required env vars. -### Phase 5 — WebUI parity +### Phase 7 — WebUI parity > **Goal:** WebUI reflects the same method-based auth model as the CLI. -- [ ] **5.1 Add “Connect provider” UI** +- [ ] **7.1 Add “Connect provider” UI** - Exit: - WebUI can list providers, show methods, and connect at least API-key methods via server API. -- [ ] **5.2 Update “API keys” settings panel** +- [ ] **7.2 Update “API keys” settings panel** - Exit: - WebUI shows connection status by method (not only “key exists”). --- -## 9. Security / UX Notes +## 10. Security / UX Notes - OAuth should support **headless** environments (device-code or “paste redirect URL” flows). - Store secrets with `0o600` and avoid logging. @@ -435,6 +647,6 @@ We should expand providers in two tiers: --- -## 10. Open Questions (tracked for owner) +## 11. Open Questions (tracked for owner) Owner-only questions and manual checks are tracked in `USER_VERIFICATION.md` (each item should map to a UV-* entry). Keep this section as a pointer, not a second source of truth. diff --git a/feature-plans/oauth-and-more-providers/USER_VERIFICATION.md b/feature-plans/oauth-and-more-providers/USER_VERIFICATION.md index b9af179fa..51c7588ac 100644 --- a/feature-plans/oauth-and-more-providers/USER_VERIFICATION.md +++ b/feature-plans/oauth-and-more-providers/USER_VERIFICATION.md @@ -18,15 +18,18 @@ | ID | Item | Why owner-only | Target phase | Status | Notes | |----|------|----------------|--------------|--------|-------| -| UV-1 | Auth storage layout + migration | Affects backwards compatibility and security posture | 0.1 | Open | Decide whether to migrate `~/.dexto/auth.json` → `~/.dexto/auth/{dexto.json,llm-profiles.json}` vs extend the existing file vs alternate layout. | -| UV-2 | OpenAI Codex OAuth provider identity | Product/UX naming + config surface | 0.2 | Open | Decide `provider: openai + method=codex-oauth` vs a distinct provider ID (e.g., `openai-codex`). | -| UV-3 | `llm.authProfileId` in v1? | UX vs complexity tradeoff | 0.3 | Open | Decide whether per-agent pinning ships in v1 or defaults-per-provider only. | -| UV-4 | Where OAuth refresh logic lives | Architecture boundary decision | 2.2 | Open | Decide shared refresh helper vs per-provider method impl; core vs agent-management ownership. | -| UV-5 | Anthropic setup-token viability | Requires real-world validation + SDK behavior check | 3.2 | Open | If incompatible with `@ai-sdk/anthropic`, decide whether to drop this method for v1. | -| UV-6 | “More providers” scope for v1 | Product scope decision | 6.6 / Phase 1 | Open | Decide which providers become first-class in v1 vs steer to OpenRouter/LiteLLM/Dexto Nova. | -| UV-7 | Manual smoke: `/connect` UX | Requires local interactive runs | Phase 1+ | Open | Verify connect flow UX: create/switch default profiles, no secret leakage, file permissions are correct. | -| UV-8 | Manual smoke: OpenAI OAuth runtime behavior | Requires real OAuth account + network | Phase 2 | Open | Verify token refresh + request rewrite works end-to-end (including Responses API behavior). | -| UV-9 | Manual smoke: WebUI parity | Requires running WebUI | Phase 5 | Open | Verify WebUI reflects method-based auth and doesn’t regress existing API key settings. | +| UV-1 | Auth storage layout (new `~/.dexto/auth/`) | Security posture + UX permanence | 0.1 | Open | Confirm final on-disk layout + permissions + atomic write strategy for `dexto.json` + `llm-profiles.json`. | +| UV-2 | OAuth app credentials + allowlisting (OpenAI Codex) | Requires external app registration + product comms | 3.1 | Open | We need Dexto-owned OpenAI OAuth client ID + registered redirect URIs; Codex OAuth may require allowlisting. Decide how we message failure + fallback to API key. | +| UV-3 | OAuth app credentials (MiniMax Portal) | Requires external app registration or explicit provider confirmation | 4.1 | Open | OpenClaw hardcodes a client ID; confirm whether we must register our own, or whether a public client ID is intended for third-party use. | +| UV-4 | Provider identity strategy (models.dev vs Dexto IDs) | Product naming + config compatibility | 0.2 | Open | Decide whether to align user-facing IDs with models.dev (`moonshotai`, `zhipuai`, `zai`, `minimax-cn`, `kimi-for-coding`, …) vs keep Dexto-local IDs (`glm`, `minimax`) with aliases. | +| UV-5 | Env var mapping for Z.AI / GLM | User expectation + migration risk | 0.2 | Open | models.dev uses `ZHIPU_API_KEY` for `zai`; OpenClaw uses `ZAI_API_KEY` / `Z_AI_API_KEY`. Decide which to accept and which to display as the “primary” hint. | +| UV-6 | MiniMax transport defaults (OpenAI-compatible vs Anthropic-compatible) | Impacts runtime correctness + preset design | 2.2 | Open | Dexto today assumes OpenAI-compatible (`api.minimax.chat`), while models.dev indicates Anthropic-compatible (`api.minimax.io/anthropic/v1`). Decide default + how we expose variants. | +| UV-7 | Models.dev provider metadata ingestion strategy | Impacts offline behavior + maintenance | 2.3 | Open | Decide whether we snapshot provider metadata at build-time (generated file) vs fetch+cache at runtime for `/connect` provider list + presets. | +| UV-8 | Resolution precedence surface | UX + “magic” risk | 0.4 | Open | Decide hardcoded precedence vs store-driven order; decide whether precedence lives in `llm-profiles` vs agent config; decide `llm.authProfileId` in v1. | +| UV-9 | Anthropic setup-token viability + ship criteria | External dependency + potential policy constraints | 5.2 | Open | Implement until infeasible; decide whether this is “experimental” and how we disable quickly if it breaks/gets blocked. | +| UV-10 | Manual smoke: `/connect` UX | Requires local interactive runs | Phase 1+ | Open | Verify connect flow UX: create/switch default profiles, no secret leakage, file permissions are correct. | +| UV-11 | Manual smoke: OpenAI OAuth runtime behavior | Requires real OAuth account + network | Phase 3 | Open | Verify token refresh + request rewrite works end-to-end (including Responses API behavior). | +| UV-12 | Manual smoke: WebUI parity | Requires running WebUI | Phase 7 | Open | Verify WebUI reflects method-based auth and doesn’t regress existing API key settings. | --- @@ -34,4 +37,4 @@ | ID | Decision / Verification | Date | Notes | |----|--------------------------|------|-------| -| _TBD_ | | | | +| UV-0 | No backwards compatibility with legacy `~/.dexto/auth.json` | 2026-02-17 | Require re-login to populate the new auth store; optional one-time import is not required for v1. | diff --git a/feature-plans/oauth-and-more-providers/WORKING_MEMORY.md b/feature-plans/oauth-and-more-providers/WORKING_MEMORY.md index 48cf2afa1..7b8b27eaf 100644 --- a/feature-plans/oauth-and-more-providers/WORKING_MEMORY.md +++ b/feature-plans/oauth-and-more-providers/WORKING_MEMORY.md @@ -33,6 +33,7 @@ _Log findings, issues, and progress here as you work._ - Imported the OAuth provider plan into this worktree and refactored it to the `PLAN.md` + `WORKING_MEMORY.md` + `USER_VERIFICATION.md` paradigm. - Tasklist re-written with numbered tasks and explicit exit criteria. - Read through OpenCode/OpenClaw reference implementations and updated `PLAN.md` with concrete file-path pointers for OAuth flows, storage shapes, and two-phase authorize/callback APIs. +- Pulled concrete models.dev provider metadata (provider IDs, base URLs, env vars, recommended SDKs) and updated `PLAN.md` to include an actionable diff for MiniMax / Z.AI / Zhipu / Moonshot / Kimi Code. Key finding: models.dev treats MiniMax + Kimi Code as **Anthropic-compatible**, while Dexto today assumes MiniMax is OpenAI-compatible. --- @@ -68,10 +69,12 @@ _Move tasks here after completion. Keep a brief log of what was done and any dev |-------|--------|-------| | Phase 0 — Decisions + interface design | Not started | — | | Phase 1 — Scaffolding + API surface | Not started | — | -| Phase 2 — OpenAI ChatGPT OAuth (Codex) | Not started | — | -| Phase 3 — Anthropic setup-token (if viable) | Not started | — | -| Phase 4 — Bedrock + Vertex connect UX | Not started | — | -| Phase 5 — WebUI parity | Not started | — | +| Phase 2 — Provider presets + more providers | Not started | — | +| Phase 3 — OpenAI ChatGPT OAuth (Codex) | Not started | — | +| Phase 4 — MiniMax Portal OAuth | Not started | — | +| Phase 5 — Anthropic setup-token (if viable) | Not started | — | +| Phase 6 — Bedrock + Vertex connect UX | Not started | — | +| Phase 7 — WebUI parity | Not started | — | --- From cc98884311b3931ac857644bb67c55e253659703 Mon Sep 17 00:00:00 2001 From: Rahul Karajgikar <rahul@trytruffle.ai> Date: Wed, 18 Feb 2026 00:33:03 +0530 Subject: [PATCH 05/25] docs(feature-plans): add provider coverage snapshot --- .../oauth-and-more-providers/PLAN.md | 1 + .../PROVIDER_COVERAGE.md | 203 ++++++++++++++++++ 2 files changed, 204 insertions(+) create mode 100644 feature-plans/oauth-and-more-providers/PROVIDER_COVERAGE.md diff --git a/feature-plans/oauth-and-more-providers/PLAN.md b/feature-plans/oauth-and-more-providers/PLAN.md index a754ee321..acf75485e 100644 --- a/feature-plans/oauth-and-more-providers/PLAN.md +++ b/feature-plans/oauth-and-more-providers/PLAN.md @@ -9,6 +9,7 @@ This plan updates Dexto onboarding/login flows to support **multiple login metho Primary references: - **OpenClaw** (`~/Projects/external/openclaw`) — onboarding wizard + auth profiles + provider auth plugins. - **OpenCode** (`~/Projects/external/opencode`) — `/connect` UX + models.dev-backed provider catalog + plugin auth methods. +- Provider coverage snapshot (exact provider IDs): [`PROVIDER_COVERAGE.md`](./PROVIDER_COVERAGE.md) --- diff --git a/feature-plans/oauth-and-more-providers/PROVIDER_COVERAGE.md b/feature-plans/oauth-and-more-providers/PROVIDER_COVERAGE.md new file mode 100644 index 000000000..051254d84 --- /dev/null +++ b/feature-plans/oauth-and-more-providers/PROVIDER_COVERAGE.md @@ -0,0 +1,203 @@ +# Provider Coverage Snapshot (Dexto vs OpenClaw vs OpenCode) + +Date: **2026-02-17** + +This file is a concrete snapshot of **provider IDs** across the three relevant codebases, so we can reason about “what can be supported” without hand-waving. + +Notes: +- This is intentionally “flat”: it lists IDs, not UX, auth methods, or transports. +- OpenCode’s list is primarily **models.dev provider IDs** (which is why it’s huge). +- OpenClaw and OpenCode can support additional “custom providers” via config; those are not enumerable and are not included here. + +--- + +## Dexto (in this repo) + +Source of truth: `packages/core/src/llm/types.ts` (`LLM_PROVIDERS`) + +Count: **17** + +```text +anthropic +bedrock +cohere +dexto-nova +glama +glm +google +groq +litellm +local +minimax +ollama +openai +openai-compatible +openrouter +vertex +xai +``` + +--- + +## OpenClaw (reference) + +Primary sources: +- Provider IDs that show up in the **auth/profile/env resolution** surface: `~/Projects/external/openclaw/src/agents/model-auth.ts` +- Provider IDs that are **auto-added** into `models.json` when credentials exist: `~/Projects/external/openclaw/src/agents/models-config.providers.ts` (`resolveImplicitProviders()`) +- Provider normalization (aliases like `opencode-zen` → `opencode`, `qwen` → `qwen-portal`): `~/Projects/external/openclaw/src/agents/model-selection.ts` (`normalizeProviderId()`) + +Count (LLM providers/backends): **36** + +```text +amazon-bedrock +anthropic +cerebras +chutes +cloudflare-ai-gateway +deepgram +github-copilot +google +google-vertex +groq +huggingface +kimi-coding +litellm +lmstudio +minimax +minimax-cn +minimax-portal +mistral +moonshot +nvidia +ollama +opencode +openai +openai-codex +openrouter +qianfan +qwen-portal +synthetic +together +venice +vercel-ai-gateway +vllm +voyage +xai +xiaomi +zai +``` + +Additional “CLI backends” (OpenClaw-specific; not models.dev providers): + +```text +claude-cli +codex-cli +``` + +--- + +## OpenCode (reference) + +Source of truth (base list): models.dev provider IDs (as of 2026-02-17): `https://models.dev/api.json` + +Additional OpenCode-specific provider IDs: +- OpenCode adds `github-copilot-enterprise` by cloning the models.dev `github-copilot` provider: + - `~/Projects/external/opencode/packages/opencode/src/provider/provider.ts` (search for “Copilot Enterprise”) + +Count (models.dev providers): **91** +Count (OpenCode effective providers incl. enterprise): **92** + +```text +302ai +abacus +aihubmix +alibaba +alibaba-cn +amazon-bedrock +anthropic +azure +azure-cognitive-services +bailing +baseten +berget +cerebras +chutes +cloudflare-ai-gateway +cloudflare-workers-ai +cohere +cortecs +deepinfra +deepseek +fastrouter +fireworks-ai +firmware +friendli +github-copilot +github-copilot-enterprise +github-models +gitlab +google +google-vertex +google-vertex-anthropic +groq +helicone +huggingface +iflowcn +inception +inference +io-net +jiekou +kilo +kimi-for-coding +kuae-cloud-coding-plan +llama +lmstudio +lucidquery +minimax +minimax-cn +minimax-cn-coding-plan +minimax-coding-plan +mistral +moark +modelscope +moonshotai +moonshotai-cn +morph +nano-gpt +nebius +nova +novita-ai +nvidia +ollama-cloud +openai +opencode +openrouter +ovhcloud +perplexity +poe +privatemode-ai +requesty +sap-ai-core +scaleway +siliconflow +siliconflow-cn +stackit +stepfun +submodel +synthetic +togetherai +upstage +v0 +venice +vercel +vivgrid +vultr +wandb +xai +xiaomi +zai +zai-coding-plan +zenmux +zhipuai +zhipuai-coding-plan +``` From 03a7b0ecf6cc4757164a37708f8696cb5c75b449 Mon Sep 17 00:00:00 2001 From: Rahul Karajgikar <rahul@trytruffle.ai> Date: Wed, 18 Feb 2026 02:45:36 +0530 Subject: [PATCH 06/25] feat(llm): connect + oauth profiles + provider expansion --- .../src/auth/connect-catalog.ts | 187 ++ .../src/auth/llm-profiles.test.ts | 58 + .../agent-management/src/auth/llm-profiles.ts | 266 +++ .../src/auth/runtime-auth-resolver.test.ts | 155 ++ .../src/auth/runtime-auth-resolver.ts | 478 ++++ packages/agent-management/src/index.ts | 35 + .../src/utils/api-key-resolver.ts | 10 + .../agent-management/src/utils/dexto-auth.ts | 9 +- packages/cli/src/cli/auth/service.ts | 15 +- .../cli/src/cli/commands/connect/index.ts | 296 +++ .../commands/connect/minimax-portal.test.ts | 89 + .../cli/commands/connect/minimax-portal.ts | 199 ++ .../cli/commands/connect/openai-codex.test.ts | 80 + .../src/cli/commands/connect/openai-codex.ts | 234 ++ .../commands/interactive-commands/commands.ts | 4 + .../interactive-commands/connect/index.ts | 19 + .../custom-model-wizard/provider-config.ts | 2 +- .../cli/ink-cli/utils/llm-provider-display.ts | 10 + packages/cli/src/config/cli-overrides.ts | 10 + packages/cli/src/index-main.ts | 18 +- packages/core/src/llm/auth/types.ts | 32 + packages/core/src/llm/index.ts | 1 + packages/core/src/llm/registry/index.ts | 69 +- .../core/src/llm/registry/models.generated.ts | 2095 ++++++++++++++++- packages/core/src/llm/registry/sync.ts | 120 + packages/core/src/llm/services/factory.ts | 185 +- .../llm/services/test-utils.integration.ts | 10 + packages/core/src/llm/types.ts | 10 + .../core/src/session/chat-session.test.ts | 9 +- packages/core/src/session/chat-session.ts | 8 +- packages/core/src/session/session-manager.ts | 2 + packages/core/src/utils/api-key-resolver.ts | 10 + .../core/src/utils/service-initializer.ts | 3 + .../test/import.integration.test.ts | 4 +- .../test/import.integration.test.ts | 4 +- .../__tests__/llm-connect.integration.test.ts | 45 + packages/server/src/hono/index.ts | 2 + .../server/src/hono/routes/llm-connect.ts | 156 ++ .../components/ModelPicker/constants.tsx | 10 + scripts/sync-llm-registry.ts | 100 + vitest.config.ts | 24 + vitest.integration.config.ts | 34 +- 42 files changed, 4949 insertions(+), 158 deletions(-) create mode 100644 packages/agent-management/src/auth/connect-catalog.ts create mode 100644 packages/agent-management/src/auth/llm-profiles.test.ts create mode 100644 packages/agent-management/src/auth/llm-profiles.ts create mode 100644 packages/agent-management/src/auth/runtime-auth-resolver.test.ts create mode 100644 packages/agent-management/src/auth/runtime-auth-resolver.ts create mode 100644 packages/cli/src/cli/commands/connect/index.ts create mode 100644 packages/cli/src/cli/commands/connect/minimax-portal.test.ts create mode 100644 packages/cli/src/cli/commands/connect/minimax-portal.ts create mode 100644 packages/cli/src/cli/commands/connect/openai-codex.test.ts create mode 100644 packages/cli/src/cli/commands/connect/openai-codex.ts create mode 100644 packages/cli/src/cli/commands/interactive-commands/connect/index.ts create mode 100644 packages/core/src/llm/auth/types.ts create mode 100644 packages/server/src/hono/__tests__/llm-connect.integration.test.ts create mode 100644 packages/server/src/hono/routes/llm-connect.ts diff --git a/packages/agent-management/src/auth/connect-catalog.ts b/packages/agent-management/src/auth/connect-catalog.ts new file mode 100644 index 000000000..25f9851ed --- /dev/null +++ b/packages/agent-management/src/auth/connect-catalog.ts @@ -0,0 +1,187 @@ +import { z } from 'zod'; + +export const ConnectMethodKindSchema = z.enum(['api_key', 'token', 'oauth', 'guidance']); +export type ConnectMethodKind = z.output<typeof ConnectMethodKindSchema>; + +export const ConnectMethodSchema = z + .object({ + id: z.string().min(1), + label: z.string().min(1), + kind: ConnectMethodKindSchema, + hint: z.string().optional(), + }) + .strict(); +export type ConnectMethod = z.output<typeof ConnectMethodSchema>; + +export const ConnectProviderSchema = z + .object({ + providerId: z.string().min(1), + label: z.string().min(1), + /** + * Optional models.dev provider id for linking metadata (api base URL, docs, env vars). + * This is not required to match Dexto's internal provider id. + */ + modelsDevProviderId: z.string().min(1).optional(), + methods: z.array(ConnectMethodSchema).min(1), + }) + .strict(); +export type ConnectProvider = z.output<typeof ConnectProviderSchema>; + +/** + * Curated catalog of providers and auth methods for `/connect`. + * + * Notes: + * - This is intentionally small in v1. We'll expand via models.dev provider metadata after + * we have stable runtime transport mappings. + * - Provider IDs here are "connect surface" IDs; they may map to existing LLM providers, + * presets, or future first-class providers. + */ +export const CONNECT_PROVIDERS: ConnectProvider[] = [ + { + providerId: 'openai', + label: 'OpenAI', + modelsDevProviderId: 'openai', + methods: [ + { id: 'oauth_codex', label: 'ChatGPT Pro/Plus (OAuth)', kind: 'oauth' }, + { id: 'api_key', label: 'API key', kind: 'api_key' }, + ], + }, + { + providerId: 'anthropic', + label: 'Anthropic', + modelsDevProviderId: 'anthropic', + methods: [ + { id: 'setup_token', label: 'Setup token (subscription)', kind: 'token' }, + { id: 'api_key', label: 'API key', kind: 'api_key' }, + ], + }, + { + providerId: 'minimax', + label: 'MiniMax', + modelsDevProviderId: 'minimax', + methods: [ + { id: 'portal_oauth_global', label: 'MiniMax Portal OAuth (Global)', kind: 'oauth' }, + { id: 'portal_oauth_cn', label: 'MiniMax Portal OAuth (CN)', kind: 'oauth' }, + { id: 'api_key', label: 'API key', kind: 'api_key' }, + ], + }, + { + providerId: 'minimax-cn', + label: 'MiniMax (CN)', + modelsDevProviderId: 'minimax-cn', + methods: [ + { id: 'portal_oauth_cn', label: 'MiniMax Portal OAuth (CN)', kind: 'oauth' }, + { id: 'api_key', label: 'API key', kind: 'api_key' }, + ], + }, + { + providerId: 'minimax-coding-plan', + label: 'MiniMax Coding Plan', + modelsDevProviderId: 'minimax-coding-plan', + methods: [ + { id: 'portal_oauth_global', label: 'MiniMax Portal OAuth (Global)', kind: 'oauth' }, + { id: 'portal_oauth_cn', label: 'MiniMax Portal OAuth (CN)', kind: 'oauth' }, + { id: 'api_key', label: 'API key', kind: 'api_key' }, + ], + }, + { + providerId: 'minimax-cn-coding-plan', + label: 'MiniMax Coding Plan (CN)', + modelsDevProviderId: 'minimax-cn-coding-plan', + methods: [ + { id: 'portal_oauth_cn', label: 'MiniMax Portal OAuth (CN)', kind: 'oauth' }, + { id: 'api_key', label: 'API key', kind: 'api_key' }, + ], + }, + { + providerId: 'moonshotai', + label: 'Moonshot AI (Kimi)', + modelsDevProviderId: 'moonshotai', + methods: [{ id: 'api_key', label: 'API key', kind: 'api_key' }], + }, + { + providerId: 'moonshotai-cn', + label: 'Moonshot AI (Kimi) (China)', + modelsDevProviderId: 'moonshotai-cn', + methods: [{ id: 'api_key', label: 'API key', kind: 'api_key' }], + }, + { + providerId: 'zhipuai', + label: 'Zhipu AI (GLM)', + modelsDevProviderId: 'zhipuai', + methods: [{ id: 'api_key', label: 'API key', kind: 'api_key' }], + }, + { + providerId: 'zhipuai-coding-plan', + label: 'Zhipu AI Coding Plan', + modelsDevProviderId: 'zhipuai-coding-plan', + methods: [{ id: 'api_key', label: 'API key', kind: 'api_key' }], + }, + { + providerId: 'zai', + label: 'Z.AI', + modelsDevProviderId: 'zai', + methods: [{ id: 'api_key', label: 'API key', kind: 'api_key' }], + }, + { + providerId: 'zai-coding-plan', + label: 'Z.AI Coding Plan', + modelsDevProviderId: 'zai-coding-plan', + methods: [{ id: 'api_key', label: 'API key', kind: 'api_key' }], + }, + { + providerId: 'kimi-for-coding', + label: 'Kimi For Coding', + modelsDevProviderId: 'kimi-for-coding', + methods: [{ id: 'api_key', label: 'API key', kind: 'api_key' }], + }, + { + providerId: 'openrouter', + label: 'OpenRouter', + modelsDevProviderId: 'openrouter', + methods: [{ id: 'api_key', label: 'API key', kind: 'api_key' }], + }, + { + providerId: 'litellm', + label: 'LiteLLM', + modelsDevProviderId: 'litellm', + methods: [ + { + id: 'guidance', + label: 'Guided setup', + kind: 'guidance', + hint: 'Set base URL and API key for your LiteLLM proxy', + }, + ], + }, + { + providerId: 'bedrock', + label: 'Amazon Bedrock', + modelsDevProviderId: 'amazon-bedrock', + methods: [ + { + id: 'guidance', + label: 'Guided setup', + kind: 'guidance', + hint: 'Use AWS credential chain or AWS_BEARER_TOKEN_BEDROCK', + }, + ], + }, + { + providerId: 'vertex', + label: 'Google Vertex AI', + modelsDevProviderId: 'google-vertex', + methods: [ + { + id: 'guidance', + label: 'Guided setup', + kind: 'guidance', + hint: 'Use Application Default Credentials (gcloud auth application-default login)', + }, + ], + }, +]; + +export function getConnectProvider(providerId: string): ConnectProvider | null { + return CONNECT_PROVIDERS.find((p) => p.providerId === providerId) ?? null; +} diff --git a/packages/agent-management/src/auth/llm-profiles.test.ts b/packages/agent-management/src/auth/llm-profiles.test.ts new file mode 100644 index 000000000..5ca0a8b8f --- /dev/null +++ b/packages/agent-management/src/auth/llm-profiles.test.ts @@ -0,0 +1,58 @@ +import { afterEach, beforeEach, describe, expect, it } from 'vitest'; +import { promises as fs } from 'node:fs'; +import path from 'node:path'; +import { tmpdir } from 'node:os'; + +import { + getDefaultLlmAuthProfileId, + getLlmAuthProfilesPath, + loadLlmAuthProfilesStore, + setDefaultLlmAuthProfile, + upsertLlmAuthProfile, + deleteLlmAuthProfile, +} from './llm-profiles.js'; + +describe('llm-profiles store', () => { + let tempHomeDir: string; + let previousHome: string | undefined; + + beforeEach(async () => { + tempHomeDir = await fs.mkdtemp(path.join(tmpdir(), 'dexto-llm-profiles-test-')); + previousHome = process.env.HOME; + process.env.HOME = tempHomeDir; + }); + + afterEach(async () => { + process.env.HOME = previousHome; + await fs.rm(tempHomeDir, { recursive: true, force: true }); + }); + + it('loads empty store when file missing', async () => { + const store = await loadLlmAuthProfilesStore(); + expect(store.version).toBe(1); + expect(store.defaults).toEqual({}); + expect(store.profiles).toEqual({}); + }); + + it('upserts profiles, forces permissions, and tracks defaults', async () => { + await upsertLlmAuthProfile({ + profileId: 'openai:default', + providerId: 'openai', + methodId: 'api_key', + credential: { type: 'api_key', key: 'sk-test-123' }, + }); + + const store = await loadLlmAuthProfilesStore(); + expect(store.profiles['openai:default']?.providerId).toBe('openai'); + + const filePath = getLlmAuthProfilesPath(); + const stat = await fs.stat(filePath); + expect(stat.mode & 0o777).toBe(0o600); + + await setDefaultLlmAuthProfile({ providerId: 'openai', profileId: 'openai:default' }); + expect(await getDefaultLlmAuthProfileId('openai')).toBe('openai:default'); + + await deleteLlmAuthProfile('openai:default'); + expect(await getDefaultLlmAuthProfileId('openai')).toBe(null); + }); +}); diff --git a/packages/agent-management/src/auth/llm-profiles.ts b/packages/agent-management/src/auth/llm-profiles.ts new file mode 100644 index 000000000..d7a2e1817 --- /dev/null +++ b/packages/agent-management/src/auth/llm-profiles.ts @@ -0,0 +1,266 @@ +/** + * LLM Auth Profiles Store + * + * Stores per-provider credential profiles (API keys, OAuth tokens, etc.) in: + * ~/.dexto/auth/llm-profiles.json + * + * Security: + * - File permissions are forced to 0o600 + * - Writes are atomic (tmp + rename) + */ + +import { randomUUID } from 'node:crypto'; +import { existsSync, readFileSync } from 'node:fs'; +import { promises as fs } from 'node:fs'; +import path from 'node:path'; +import { z } from 'zod'; +import { NonEmptyTrimmed } from '@dexto/core'; + +import { getDextoGlobalPath } from '../utils/path.js'; + +const STORE_VERSION = 1 as const; +const STORE_DIR = 'auth'; +const STORE_FILENAME = 'llm-profiles.json'; + +const FILE_MODE = 0o600; + +export const LlmAuthCredentialSchema = z + .discriminatedUnion('type', [ + z + .object({ + type: z.literal('api_key'), + key: NonEmptyTrimmed.describe('Provider API key'), + }) + .strict(), + z + .object({ + type: z.literal('token'), + token: NonEmptyTrimmed.describe('Static bearer token / setup token'), + expiresAt: z.number().int().positive().optional().describe('Expiry timestamp (ms)'), + }) + .strict(), + z + .object({ + type: z.literal('oauth'), + accessToken: NonEmptyTrimmed, + refreshToken: NonEmptyTrimmed, + expiresAt: z.number().int().positive().describe('Expiry timestamp (ms)'), + tokenType: z.string().optional().describe('Token type (e.g., Bearer)'), + /** + * Optional provider-specific metadata (account IDs, resource URLs, regions). + * Keep as string map so we can store small bits of info without schema churn. + */ + metadata: z.record(z.string(), z.string()).optional(), + }) + .strict(), + ]) + .describe('Credential material for an auth profile'); + +export type LlmAuthCredential = z.output<typeof LlmAuthCredentialSchema>; + +export const LlmAuthProfileSchema = z + .object({ + profileId: NonEmptyTrimmed.describe('Stable profile identifier (e.g., openai:default)'), + providerId: NonEmptyTrimmed.describe('Provider id (LLM provider or preset id)'), + methodId: NonEmptyTrimmed.describe('Auth method id (e.g., api_key, oauth_codex)'), + label: z.string().optional().describe('Human-friendly label'), + credential: LlmAuthCredentialSchema, + createdAt: z.number().int().positive(), + updatedAt: z.number().int().positive(), + }) + .strict(); + +export type LlmAuthProfile = z.output<typeof LlmAuthProfileSchema>; + +export const LlmAuthProfilesStoreSchema = z + .object({ + version: z.literal(STORE_VERSION), + defaults: z.record(z.string(), z.string()).describe('providerId -> profileId'), + profiles: z.record(z.string(), LlmAuthProfileSchema).describe('profileId -> profile'), + }) + .strict(); + +export type LlmAuthProfilesStore = z.output<typeof LlmAuthProfilesStoreSchema>; + +export function getLlmAuthProfilesPath(): string { + return getDextoGlobalPath(STORE_DIR, STORE_FILENAME); +} + +function createEmptyStore(): LlmAuthProfilesStore { + return { version: STORE_VERSION, defaults: {}, profiles: {} }; +} + +async function writeFileAtomic(filePath: string, content: string): Promise<void> { + await fs.mkdir(path.dirname(filePath), { recursive: true }); + + const tmpPath = `${filePath}.${randomUUID()}.tmp`; + try { + await fs.writeFile(tmpPath, content, { encoding: 'utf-8', mode: FILE_MODE }); + await fs.rename(tmpPath, filePath); + // Enforce permissions even if file existed previously with different mode. + await fs.chmod(filePath, FILE_MODE); + } catch (error) { + try { + await fs.unlink(tmpPath); + } catch { + // ignore cleanup errors + } + throw error; + } +} + +export async function loadLlmAuthProfilesStore(): Promise<LlmAuthProfilesStore> { + const filePath = getLlmAuthProfilesPath(); + + if (!existsSync(filePath)) { + return createEmptyStore(); + } + + try { + const content = await fs.readFile(filePath, 'utf-8'); + const parsed = LlmAuthProfilesStoreSchema.safeParse(JSON.parse(content)); + if (!parsed.success) { + return createEmptyStore(); + } + return parsed.data; + } catch (error) { + if ((error as NodeJS.ErrnoException).code === 'ENOENT') { + return createEmptyStore(); + } + throw error; + } +} + +export function loadLlmAuthProfilesStoreSync(): LlmAuthProfilesStore { + const filePath = getLlmAuthProfilesPath(); + if (!existsSync(filePath)) { + return createEmptyStore(); + } + + try { + const content = readFileSync(filePath, 'utf-8'); + const parsed = LlmAuthProfilesStoreSchema.safeParse(JSON.parse(content)); + if (!parsed.success) { + return createEmptyStore(); + } + return parsed.data; + } catch { + return createEmptyStore(); + } +} + +export async function saveLlmAuthProfilesStore(store: LlmAuthProfilesStore): Promise<void> { + const parsed = LlmAuthProfilesStoreSchema.safeParse(store); + if (!parsed.success) { + throw new Error( + `Invalid LLM auth profiles store: ${parsed.error.issues.map((i) => i.message).join(', ')}` + ); + } + + const filePath = getLlmAuthProfilesPath(); + await writeFileAtomic(filePath, JSON.stringify(parsed.data, null, 2)); +} + +export async function listLlmAuthProfiles(options?: { + providerId?: string | undefined; +}): Promise<LlmAuthProfile[]> { + const store = await loadLlmAuthProfilesStore(); + const profiles = Object.values(store.profiles); + const filtered = options?.providerId + ? profiles.filter((p) => p.providerId === options.providerId) + : profiles; + filtered.sort((a, b) => a.profileId.localeCompare(b.profileId)); + return filtered; +} + +export async function upsertLlmAuthProfile(input: { + profileId: string; + providerId: string; + methodId: string; + label?: string | undefined; + credential: LlmAuthCredential; +}): Promise<LlmAuthProfile> { + const now = Date.now(); + const store = await loadLlmAuthProfilesStore(); + const existing = store.profiles[input.profileId]; + + const next: LlmAuthProfile = { + profileId: input.profileId, + providerId: input.providerId, + methodId: input.methodId, + ...(input.label ? { label: input.label } : {}), + credential: input.credential, + createdAt: existing?.createdAt ?? now, + updatedAt: now, + }; + + const validated = LlmAuthProfileSchema.parse(next); + store.profiles[validated.profileId] = validated; + await saveLlmAuthProfilesStore(store); + return validated; +} + +export async function deleteLlmAuthProfile(profileId: string): Promise<boolean> { + const store = await loadLlmAuthProfilesStore(); + if (!store.profiles[profileId]) return false; + + delete store.profiles[profileId]; + for (const [providerId, defaultProfileId] of Object.entries(store.defaults)) { + if (defaultProfileId === profileId) { + delete store.defaults[providerId]; + } + } + + await saveLlmAuthProfilesStore(store); + return true; +} + +export async function setDefaultLlmAuthProfile(options: { + providerId: string; + profileId: string | null; +}): Promise<void> { + const store = await loadLlmAuthProfilesStore(); + + if (options.profileId === null) { + delete store.defaults[options.providerId]; + await saveLlmAuthProfilesStore(store); + return; + } + + const profile = store.profiles[options.profileId]; + if (!profile) { + throw new Error(`Profile not found: ${options.profileId}`); + } + if (profile.providerId !== options.providerId) { + throw new Error( + `Profile provider mismatch: expected ${options.providerId}, got ${profile.providerId}` + ); + } + + store.defaults[options.providerId] = options.profileId; + await saveLlmAuthProfilesStore(store); +} + +export async function getDefaultLlmAuthProfileId(providerId: string): Promise<string | null> { + const store = await loadLlmAuthProfilesStore(); + const profileId = store.defaults[providerId]; + if (!profileId) return null; + return store.profiles[profileId] ? profileId : null; +} + +export function getDefaultLlmAuthProfileIdSync(providerId: string): string | null { + const store = loadLlmAuthProfilesStoreSync(); + const profileId = store.defaults[providerId]; + if (!profileId) return null; + return store.profiles[profileId] ? profileId : null; +} + +export async function getLlmAuthProfile(profileId: string): Promise<LlmAuthProfile | null> { + const store = await loadLlmAuthProfilesStore(); + return store.profiles[profileId] ?? null; +} + +export function getLlmAuthProfileSync(profileId: string): LlmAuthProfile | null { + const store = loadLlmAuthProfilesStoreSync(); + return store.profiles[profileId] ?? null; +} diff --git a/packages/agent-management/src/auth/runtime-auth-resolver.test.ts b/packages/agent-management/src/auth/runtime-auth-resolver.test.ts new file mode 100644 index 000000000..c9ac702fc --- /dev/null +++ b/packages/agent-management/src/auth/runtime-auth-resolver.test.ts @@ -0,0 +1,155 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import { promises as fs } from 'node:fs'; +import path from 'node:path'; +import { tmpdir } from 'node:os'; + +import { + loadLlmAuthProfilesStore, + setDefaultLlmAuthProfile, + upsertLlmAuthProfile, +} from './llm-profiles.js'; +import { createDefaultLlmAuthResolver } from './runtime-auth-resolver.js'; + +describe('llm runtime auth resolver', () => { + let tempHomeDir: string; + let previousHome: string | undefined; + let originalFetch: typeof fetch | undefined; + let previousMiniMaxClientId: string | undefined; + + beforeEach(async () => { + tempHomeDir = await fs.mkdtemp(path.join(tmpdir(), 'dexto-llm-auth-resolver-test-')); + previousHome = process.env.HOME; + process.env.HOME = tempHomeDir; + originalFetch = globalThis.fetch; + previousMiniMaxClientId = process.env.DEXTO_MINIMAX_PORTAL_OAUTH_CLIENT_ID; + }); + + afterEach(async () => { + if (originalFetch) { + globalThis.fetch = originalFetch; + } + process.env.DEXTO_MINIMAX_PORTAL_OAUTH_CLIENT_ID = previousMiniMaxClientId; + process.env.HOME = previousHome; + await fs.rm(tempHomeDir, { recursive: true, force: true }); + vi.restoreAllMocks(); + }); + + it('returns minimax oauth runtime overrides (x-api-key + baseURL normalization)', async () => { + await upsertLlmAuthProfile({ + profileId: 'minimax:portal_oauth_cn', + providerId: 'minimax', + methodId: 'portal_oauth_cn', + credential: { + type: 'oauth', + accessToken: 'access-token', + refreshToken: 'refresh-token', + expiresAt: Date.now() + 60_000, + metadata: { + region: 'cn', + resourceUrl: 'https://api.minimaxi.com/anthropic', + }, + }, + }); + await setDefaultLlmAuthProfile({ + providerId: 'minimax', + profileId: 'minimax:portal_oauth_cn', + }); + + const resolver = createDefaultLlmAuthResolver(); + const runtime = resolver.resolveRuntimeAuth({ provider: 'minimax', model: 'MiniMax-M2.1' }); + expect(runtime?.apiKey).toBe('dexto-oauth-dummy-key'); + expect(runtime?.baseURL).toBe('https://api.minimaxi.com/anthropic/v1'); + expect(typeof runtime?.fetch).toBe('function'); + + const calls: Array<{ url: string; headers: Headers }> = []; + globalThis.fetch = (async (input: RequestInfo | URL, init?: RequestInit) => { + const url = + input instanceof URL + ? input.toString() + : typeof input === 'string' + ? input + : input.url; + calls.push({ url, headers: new Headers(init?.headers) }); + return new Response('ok', { status: 200 }); + }) satisfies typeof fetch; + + await runtime!.fetch!('https://example.com', { + headers: { + 'x-api-key': 'placeholder', + Authorization: 'Bearer placeholder', + }, + }); + + expect(calls).toHaveLength(1); + expect(calls[0]!.headers.get('x-api-key')).toBe('access-token'); + expect(calls[0]!.headers.get('authorization')).toBe(null); + }); + + it('refreshes minimax oauth tokens when expired', async () => { + process.env.DEXTO_MINIMAX_PORTAL_OAUTH_CLIENT_ID = 'client-id'; + + await upsertLlmAuthProfile({ + profileId: 'minimax:portal_oauth_global', + providerId: 'minimax', + methodId: 'portal_oauth_global', + credential: { + type: 'oauth', + accessToken: 'stale-access', + refreshToken: 'stale-refresh', + expiresAt: Date.now() - 1, + metadata: { region: 'global' }, + }, + }); + await setDefaultLlmAuthProfile({ + providerId: 'minimax', + profileId: 'minimax:portal_oauth_global', + }); + + const resolver = createDefaultLlmAuthResolver(); + const runtime = resolver.resolveRuntimeAuth({ provider: 'minimax', model: 'MiniMax-M2.1' }); + expect(runtime?.apiKey).toBe('dexto-oauth-dummy-key'); + expect(typeof runtime?.fetch).toBe('function'); + + const calls: Array<{ url: string; headers: Headers; body?: string }> = []; + globalThis.fetch = (async (input: RequestInfo | URL, init?: RequestInit) => { + const url = + input instanceof URL + ? input.toString() + : typeof input === 'string' + ? input + : input.url; + calls.push({ url, headers: new Headers(init?.headers), body: init?.body?.toString() }); + + if (url === 'https://api.minimax.io/oauth/token') { + return new Response( + JSON.stringify({ + status: 'success', + access_token: 'fresh-access', + refresh_token: 'fresh-refresh', + expired_in: 3600, + }), + { status: 200 } + ); + } + + return new Response('ok', { status: 200 }); + }) satisfies typeof fetch; + + await runtime!.fetch!('https://example.com', { headers: { 'x-api-key': 'placeholder' } }); + + expect(calls.length).toBeGreaterThanOrEqual(2); + expect(calls[0]!.url).toBe('https://api.minimax.io/oauth/token'); + + const requestCall = calls.find((c) => c.url === 'https://example.com'); + expect(requestCall?.headers.get('x-api-key')).toBe('fresh-access'); + + const store = await loadLlmAuthProfilesStore(); + const updated = store.profiles['minimax:portal_oauth_global']; + expect(updated?.credential.type).toBe('oauth'); + if (updated?.credential.type === 'oauth') { + expect(updated.credential.accessToken).toBe('fresh-access'); + expect(updated.credential.refreshToken).toBe('fresh-refresh'); + expect(updated.credential.expiresAt).toBeGreaterThan(Date.now()); + } + }); +}); diff --git a/packages/agent-management/src/auth/runtime-auth-resolver.ts b/packages/agent-management/src/auth/runtime-auth-resolver.ts new file mode 100644 index 000000000..6c7773924 --- /dev/null +++ b/packages/agent-management/src/auth/runtime-auth-resolver.ts @@ -0,0 +1,478 @@ +import type { + LlmAuthResolver, + LlmRuntimeAuthOverrides, + ResolveLlmRuntimeAuthInput, +} from '@dexto/core'; + +import { + getDefaultLlmAuthProfileIdSync, + getLlmAuthProfileSync, + upsertLlmAuthProfile, + type LlmAuthProfile, + type LlmAuthCredential, +} from './llm-profiles.js'; + +const OAUTH_DUMMY_KEY = 'dexto-oauth-dummy-key'; +const OPENAI_AUTH_ISSUER = 'https://auth.openai.com'; + +type RefreshLock = { + inFlight: Promise<void> | null; +}; + +function createRefreshLock(): RefreshLock { + return { inFlight: null }; +} + +const refreshLocksByProfileId = new Map<string, RefreshLock>(); + +function getLock(profileId: string): RefreshLock { + const existing = refreshLocksByProfileId.get(profileId); + if (existing) return existing; + const created = createRefreshLock(); + refreshLocksByProfileId.set(profileId, created); + return created; +} + +function removeAuthHeader(headers: Headers): void { + headers.delete('authorization'); + headers.delete('Authorization'); +} + +function upsertAuthHeader(headers: Headers, value: string): void { + headers.set('authorization', value); +} + +function mergeHeaders(initHeaders: RequestInit['headers']): Headers { + const headers = new Headers(); + if (!initHeaders) return headers; + + if (initHeaders instanceof Headers) { + initHeaders.forEach((value, key) => headers.set(key, value)); + return headers; + } + + if (Array.isArray(initHeaders)) { + for (const [key, value] of initHeaders) { + if (value !== undefined) headers.set(key, String(value)); + } + return headers; + } + + for (const [key, value] of Object.entries(initHeaders)) { + if (value !== undefined) headers.set(key, String(value)); + } + return headers; +} + +function isOauthCredential( + cred: LlmAuthCredential +): cred is Extract<LlmAuthCredential, { type: 'oauth' }> { + return cred.type === 'oauth'; +} + +function decodeJwtClaims(token: string): Record<string, unknown> | null { + const parts = token.split('.'); + if (parts.length !== 3) return null; + try { + const json = Buffer.from(parts[1]!, 'base64url').toString('utf-8'); + return JSON.parse(json) as Record<string, unknown>; + } catch { + return null; + } +} + +function extractChatGptAccountIdFromClaims(claims: Record<string, unknown>): string | null { + const direct = claims['chatgpt_account_id']; + if (typeof direct === 'string' && direct.trim()) return direct; + + const auth = claims['https://api.openai.com/auth']; + if (typeof auth === 'object' && auth !== null) { + const maybe = (auth as Record<string, unknown>)['chatgpt_account_id']; + if (typeof maybe === 'string' && maybe.trim()) return maybe; + } + + const orgs = claims['organizations']; + if (Array.isArray(orgs) && orgs.length > 0) { + const first = orgs[0]; + if (typeof first === 'object' && first !== null) { + const id = (first as Record<string, unknown>)['id']; + if (typeof id === 'string' && id.trim()) return id; + } + } + + return null; +} + +function extractChatGptAccountId(tokens: { + id_token?: string; + access_token?: string; +}): string | null { + if (tokens.id_token) { + const claims = decodeJwtClaims(tokens.id_token); + if (claims) { + const id = extractChatGptAccountIdFromClaims(claims); + if (id) return id; + } + } + if (tokens.access_token) { + const claims = decodeJwtClaims(tokens.access_token); + if (claims) { + const id = extractChatGptAccountIdFromClaims(claims); + if (id) return id; + } + } + return null; +} + +function toExpiresAt(expiresIn: number): number { + // Heuristic: duration seconds are small; epoch ms is ~1.7e12. + if (!Number.isFinite(expiresIn) || expiresIn <= 0) return Date.now(); + if (expiresIn < 10_000_000_000) { + return Date.now() + expiresIn * 1000; + } + return expiresIn; +} + +function normalizeAnthropicBaseUrl(url: string): string { + const trimmed = url.trim().replace(/\/$/, ''); + if (!trimmed) return trimmed; + if (trimmed.endsWith('/v1')) return trimmed; + return `${trimmed}/v1`; +} + +async function refreshOpenAiOauthTokens(refreshToken: string): Promise<{ + accessToken: string; + refreshToken: string; + expiresAt: number; + accountId: string | null; +}> { + const clientId = process.env.DEXTO_OPENAI_CODEX_OAUTH_CLIENT_ID?.trim(); + if (!clientId) { + throw new Error('Missing DEXTO_OPENAI_CODEX_OAUTH_CLIENT_ID'); + } + + const response = await fetch(`${OPENAI_AUTH_ISSUER}/oauth/token`, { + method: 'POST', + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + body: new URLSearchParams({ + grant_type: 'refresh_token', + refresh_token: refreshToken, + client_id: clientId, + }).toString(), + signal: AbortSignal.timeout(15_000), + }); + + if (!response.ok) { + const text = await response.text().catch(() => ''); + throw new Error( + `OpenAI OAuth refresh failed (${response.status}): ${text || response.statusText}` + ); + } + + const data = (await response.json()) as { + access_token?: string; + refresh_token?: string; + expires_in?: number; + id_token?: string; + }; + + if (!data.access_token) { + throw new Error('OpenAI OAuth refresh response missing access_token'); + } + + const expiresInSec = + typeof data.expires_in === 'number' && data.expires_in > 0 ? data.expires_in : 3600; + const accountId = extractChatGptAccountId({ + id_token: data.id_token, + access_token: data.access_token, + }); + + return { + accessToken: data.access_token, + refreshToken: data.refresh_token ?? refreshToken, + expiresAt: Date.now() + expiresInSec * 1000, + accountId, + }; +} + +async function refreshMiniMaxPortalOauthTokens(params: { + region: 'cn' | 'global'; + refreshToken: string; +}): Promise<{ + accessToken: string; + refreshToken: string; + expiresAt: number; + resourceUrl?: string; + notificationMessage?: string; +}> { + const clientId = process.env.DEXTO_MINIMAX_PORTAL_OAUTH_CLIENT_ID?.trim(); + if (!clientId) { + throw new Error('Missing DEXTO_MINIMAX_PORTAL_OAUTH_CLIENT_ID'); + } + + const baseUrl = params.region === 'cn' ? 'https://api.minimaxi.com' : 'https://api.minimax.io'; + const response = await fetch(`${baseUrl}/oauth/token`, { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + Accept: 'application/json', + }, + body: new URLSearchParams({ + grant_type: 'refresh_token', + refresh_token: params.refreshToken, + client_id: clientId, + }).toString(), + signal: AbortSignal.timeout(15_000), + }); + + const text = await response.text().catch(() => ''); + let payload: unknown; + try { + payload = text ? (JSON.parse(text) as unknown) : null; + } catch { + payload = null; + } + + if (!response.ok) { + throw new Error( + `MiniMax OAuth refresh failed (${response.status}): ${text || response.statusText}` + ); + } + + const data = payload as { + status?: string; + access_token?: string | null; + refresh_token?: string | null; + expired_in?: number | null; + resource_url?: string | null; + notification_message?: string | null; + }; + + if (data?.status !== 'success') { + throw new Error('MiniMax OAuth refresh returned non-success status'); + } + + if (!data.access_token || !data.refresh_token || !data.expired_in) { + throw new Error('MiniMax OAuth refresh response missing required fields'); + } + + return { + accessToken: data.access_token, + refreshToken: data.refresh_token, + expiresAt: toExpiresAt(data.expired_in), + ...(data.resource_url ? { resourceUrl: data.resource_url } : {}), + ...(data.notification_message ? { notificationMessage: data.notification_message } : {}), + }; +} + +async function refreshOauthProfileIfNeeded(profile: LlmAuthProfile): Promise<LlmAuthProfile> { + if (!isOauthCredential(profile.credential)) return profile; + + const now = Date.now(); + const safetyWindowMs = 30_000; + if (profile.credential.expiresAt > now + safetyWindowMs) { + return profile; + } + + const lock = getLock(profile.profileId); + if (lock.inFlight) { + await lock.inFlight; + return getLlmAuthProfileSync(profile.profileId) ?? profile; + } + + lock.inFlight = (async () => { + const latest = getLlmAuthProfileSync(profile.profileId) ?? profile; + if (!isOauthCredential(latest.credential)) return; + + if (latest.credential.expiresAt > Date.now() + safetyWindowMs) return; + + if (latest.providerId === 'openai' && latest.methodId === 'oauth_codex') { + const refreshed = await refreshOpenAiOauthTokens(latest.credential.refreshToken); + const nextCred: Extract<LlmAuthCredential, { type: 'oauth' }> = { + ...latest.credential, + accessToken: refreshed.accessToken, + refreshToken: refreshed.refreshToken, + expiresAt: refreshed.expiresAt, + ...(refreshed.accountId + ? { + metadata: { + ...(latest.credential.metadata ?? {}), + accountId: refreshed.accountId, + }, + } + : {}), + }; + await upsertLlmAuthProfile({ + profileId: latest.profileId, + providerId: latest.providerId, + methodId: latest.methodId, + label: latest.label, + credential: nextCred, + }); + return; + } + + if ( + latest.providerId.startsWith('minimax') && + (latest.methodId === 'portal_oauth_global' || latest.methodId === 'portal_oauth_cn') + ) { + const region = + (latest.credential.metadata?.region as 'cn' | 'global' | undefined) ?? + (latest.methodId === 'portal_oauth_cn' ? 'cn' : 'global'); + + const refreshed = await refreshMiniMaxPortalOauthTokens({ + region, + refreshToken: latest.credential.refreshToken, + }); + + const nextCred: Extract<LlmAuthCredential, { type: 'oauth' }> = { + ...latest.credential, + accessToken: refreshed.accessToken, + refreshToken: refreshed.refreshToken, + expiresAt: refreshed.expiresAt, + metadata: { + ...(latest.credential.metadata ?? {}), + region, + ...(refreshed.resourceUrl ? { resourceUrl: refreshed.resourceUrl } : {}), + }, + }; + + await upsertLlmAuthProfile({ + profileId: latest.profileId, + providerId: latest.providerId, + methodId: latest.methodId, + label: latest.label, + credential: nextCred, + }); + return; + } + + // Unknown OAuth provider/method: no refresh implemented yet. + })().finally(() => { + lock.inFlight = null; + }); + + await lock.inFlight; + return getLlmAuthProfileSync(profile.profileId) ?? profile; +} + +function buildOAuthFetchWrapper(params: { + profileId: string; + headerKind: 'authorization_bearer' | 'x_api_key'; + extraHeaders?: Record<string, string> | undefined; +}): typeof fetch { + return async (requestInput, init) => { + const headers = mergeHeaders(init?.headers); + + // Remove any SDK-injected auth header (dummy key). + removeAuthHeader(headers); + headers.delete('x-api-key'); + headers.delete('X-API-Key'); + + const profile = getLlmAuthProfileSync(params.profileId); + if (!profile || profile.credential.type !== 'oauth') { + return fetch(requestInput, { ...init, headers }); + } + + const refreshed = await refreshOauthProfileIfNeeded(profile); + const cred = refreshed.credential; + if (cred.type !== 'oauth') { + return fetch(requestInput, { ...init, headers }); + } + + if (params.headerKind === 'authorization_bearer') { + upsertAuthHeader(headers, `Bearer ${cred.accessToken}`); + } else { + headers.set('x-api-key', cred.accessToken); + } + + if (params.extraHeaders) { + for (const [key, value] of Object.entries(params.extraHeaders)) { + headers.set(key, value); + } + } + + // Provider-specific metadata headers (best-effort) + if (refreshed.providerId === 'openai' && refreshed.methodId === 'oauth_codex') { + const accountId = cred.metadata?.accountId; + if (accountId) { + headers.set('ChatGPT-Account-Id', accountId); + } + } + + return fetch(requestInput, { ...init, headers }); + }; +} + +export function createDefaultLlmAuthResolver(): LlmAuthResolver { + return { + resolveRuntimeAuth(input: ResolveLlmRuntimeAuthInput): LlmRuntimeAuthOverrides | null { + const defaultProfileId = getDefaultLlmAuthProfileIdSync(input.provider); + if (!defaultProfileId) return null; + + const profile = getLlmAuthProfileSync(defaultProfileId); + if (!profile) return null; + + // Basic credential types + if (profile.credential.type === 'api_key') { + return { apiKey: profile.credential.key }; + } + if (profile.credential.type === 'token') { + return { apiKey: profile.credential.token }; + } + + // OAuth methods (runtime-affecting) + if (profile.credential.type === 'oauth') { + if (profile.providerId === 'openai' && profile.methodId === 'oauth_codex') { + const baseURL = 'https://chatgpt.com/backend-api/codex'; + return { + apiKey: OAUTH_DUMMY_KEY, + baseURL, + fetch: buildOAuthFetchWrapper({ + profileId: profile.profileId, + headerKind: 'authorization_bearer', + }), + }; + } + + if ( + profile.providerId.startsWith('minimax') && + (profile.methodId === 'portal_oauth_global' || + profile.methodId === 'portal_oauth_cn') + ) { + const region = + (profile.credential.metadata?.region as 'cn' | 'global' | undefined) ?? + (profile.methodId === 'portal_oauth_cn' ? 'cn' : 'global'); + + const fallbackResourceUrl = + region === 'cn' + ? 'https://api.minimaxi.com/anthropic/v1' + : 'https://api.minimax.io/anthropic/v1'; + + const resourceUrl = + profile.credential.metadata?.resourceUrl?.trim() || fallbackResourceUrl; + + return { + apiKey: OAUTH_DUMMY_KEY, + baseURL: normalizeAnthropicBaseUrl(resourceUrl), + fetch: buildOAuthFetchWrapper({ + profileId: profile.profileId, + headerKind: 'x_api_key', + }), + }; + } + + // Default behavior for unknown OAuth provider/method: try bearer auth. + return { + apiKey: OAUTH_DUMMY_KEY, + fetch: buildOAuthFetchWrapper({ + profileId: profile.profileId, + headerKind: 'authorization_bearer', + }), + }; + } + + return null; + }, + }; +} diff --git a/packages/agent-management/src/index.ts b/packages/agent-management/src/index.ts index 924e1b984..2acbdc483 100644 --- a/packages/agent-management/src/index.ts +++ b/packages/agent-management/src/index.ts @@ -98,6 +98,41 @@ export { canUseDextoProvider, } from './utils/dexto-auth.js'; +// LLM auth profiles (multi-method provider connect) +export { + getLlmAuthProfilesPath, + loadLlmAuthProfilesStore, + loadLlmAuthProfilesStoreSync, + saveLlmAuthProfilesStore, + listLlmAuthProfiles, + upsertLlmAuthProfile, + deleteLlmAuthProfile, + setDefaultLlmAuthProfile, + getDefaultLlmAuthProfileId, + getDefaultLlmAuthProfileIdSync, + getLlmAuthProfile, + getLlmAuthProfileSync, + LlmAuthCredentialSchema, + LlmAuthProfileSchema, + LlmAuthProfilesStoreSchema, + type LlmAuthCredential, + type LlmAuthProfile, + type LlmAuthProfilesStore, +} from './auth/llm-profiles.js'; + +export { + CONNECT_PROVIDERS, + getConnectProvider, + ConnectProviderSchema, + ConnectMethodSchema, + ConnectMethodKindSchema, + type ConnectProvider, + type ConnectMethod, + type ConnectMethodKind, +} from './auth/connect-catalog.js'; + +export { createDefaultLlmAuthResolver } from './auth/runtime-auth-resolver.js'; + // Config management utilities export { updateAgentConfigFile, diff --git a/packages/agent-management/src/utils/api-key-resolver.ts b/packages/agent-management/src/utils/api-key-resolver.ts index 4366a3586..956a593fd 100644 --- a/packages/agent-management/src/utils/api-key-resolver.ts +++ b/packages/agent-management/src/utils/api-key-resolver.ts @@ -15,7 +15,17 @@ export const PROVIDER_API_KEY_MAP: Record<LLMProvider, string[]> = { cohere: ['COHERE_API_KEY'], xai: ['XAI_API_KEY', 'X_AI_API_KEY'], minimax: ['MINIMAX_API_KEY'], + 'minimax-cn': ['MINIMAX_API_KEY'], + 'minimax-coding-plan': ['MINIMAX_API_KEY'], + 'minimax-cn-coding-plan': ['MINIMAX_API_KEY'], glm: ['ZHIPU_API_KEY', 'ZHIPUAI_API_KEY'], + zhipuai: ['ZHIPU_API_KEY', 'ZHIPUAI_API_KEY'], + 'zhipuai-coding-plan': ['ZHIPU_API_KEY', 'ZHIPUAI_API_KEY'], + zai: ['ZHIPU_API_KEY'], + 'zai-coding-plan': ['ZHIPU_API_KEY'], + moonshotai: ['MOONSHOT_API_KEY'], + 'moonshotai-cn': ['MOONSHOT_API_KEY'], + 'kimi-for-coding': ['KIMI_API_KEY'], openrouter: ['OPENROUTER_API_KEY'], litellm: ['LITELLM_API_KEY', 'LITELLM_KEY'], glama: ['GLAMA_API_KEY'], diff --git a/packages/agent-management/src/utils/dexto-auth.ts b/packages/agent-management/src/utils/dexto-auth.ts index 1feee68a8..100560cd4 100644 --- a/packages/agent-management/src/utils/dexto-auth.ts +++ b/packages/agent-management/src/utils/dexto-auth.ts @@ -9,7 +9,8 @@ import { existsSync, promises as fs } from 'fs'; import { z } from 'zod'; import { getDextoGlobalPath } from '@dexto/core'; -const AUTH_CONFIG_FILE = 'auth.json'; +const AUTH_DIR = 'auth'; +const AUTH_CONFIG_FILE = 'dexto.json'; /** * Minimal schema for checking auth status. @@ -23,10 +24,10 @@ const AuthConfigSchema = z.object({ /** * Check if user is authenticated with Dexto. - * Returns true if auth.json exists with valid (non-expired) token. + * Returns true if dexto auth file exists with valid (non-expired) token. */ export async function isDextoAuthenticated(): Promise<boolean> { - const authPath = getDextoGlobalPath('', AUTH_CONFIG_FILE); + const authPath = getDextoGlobalPath(AUTH_DIR, AUTH_CONFIG_FILE); if (!existsSync(authPath)) { return false; @@ -62,7 +63,7 @@ export async function getDextoApiKeyFromAuth(): Promise<string | null> { } // Check auth config - const authPath = getDextoGlobalPath('', AUTH_CONFIG_FILE); + const authPath = getDextoGlobalPath(AUTH_DIR, AUTH_CONFIG_FILE); if (!existsSync(authPath)) { return null; diff --git a/packages/cli/src/cli/auth/service.ts b/packages/cli/src/cli/auth/service.ts index ae547a5d7..b54379c4e 100644 --- a/packages/cli/src/cli/auth/service.ts +++ b/packages/cli/src/cli/auth/service.ts @@ -7,7 +7,8 @@ import { z } from 'zod'; import { getDextoGlobalPath, logger } from '@dexto/core'; import { SUPABASE_URL, SUPABASE_ANON_KEY } from './constants.js'; -const AUTH_CONFIG_FILE = 'auth.json'; +const AUTH_DIR = 'auth'; +const AUTH_CONFIG_FILE = 'dexto.json'; export interface AuthConfig { /** Supabase access token from OAuth login (optional if using --api-key) */ @@ -38,8 +39,8 @@ const AuthConfigSchema = z }); export async function storeAuth(config: AuthConfig): Promise<void> { - const authPath = getDextoGlobalPath('', AUTH_CONFIG_FILE); - const dextoDir = getDextoGlobalPath('', ''); + const authPath = getDextoGlobalPath(AUTH_DIR, AUTH_CONFIG_FILE); + const dextoDir = getDextoGlobalPath(AUTH_DIR, ''); await fs.mkdir(dextoDir, { recursive: true }); await fs.writeFile(authPath, JSON.stringify(config, null, 2), { mode: 0o600 }); @@ -48,7 +49,7 @@ export async function storeAuth(config: AuthConfig): Promise<void> { } export async function loadAuth(): Promise<AuthConfig | null> { - const authPath = getDextoGlobalPath('', AUTH_CONFIG_FILE); + const authPath = getDextoGlobalPath(AUTH_DIR, AUTH_CONFIG_FILE); if (!existsSync(authPath)) { return null; @@ -78,7 +79,7 @@ export async function loadAuth(): Promise<AuthConfig | null> { } export async function removeAuth(): Promise<void> { - const authPath = getDextoGlobalPath('', AUTH_CONFIG_FILE); + const authPath = getDextoGlobalPath(AUTH_DIR, AUTH_CONFIG_FILE); if (existsSync(authPath)) { await fs.unlink(authPath); @@ -142,7 +143,7 @@ export async function getDextoApiKey(): Promise<string | null> { if (process.env.DEXTO_API_KEY?.trim()) { return process.env.DEXTO_API_KEY; } - // Fall back to auth.json (from `dexto login`) + // Fall back to dexto.json (from `dexto login`) const auth = await loadAuth(); return auth?.dextoApiKey || null; } @@ -192,5 +193,5 @@ async function refreshAccessToken(refreshToken: string): Promise<{ } export function getAuthFilePath(): string { - return getDextoGlobalPath('', AUTH_CONFIG_FILE); + return getDextoGlobalPath(AUTH_DIR, AUTH_CONFIG_FILE); } diff --git a/packages/cli/src/cli/commands/connect/index.ts b/packages/cli/src/cli/commands/connect/index.ts new file mode 100644 index 000000000..f843b6e1a --- /dev/null +++ b/packages/cli/src/cli/commands/connect/index.ts @@ -0,0 +1,296 @@ +import chalk from 'chalk'; +import * as p from '@clack/prompts'; +import open from 'open'; + +import { + CONNECT_PROVIDERS, + getConnectProvider, + setDefaultLlmAuthProfile, + upsertLlmAuthProfile, + type ConnectMethod, +} from '@dexto/agent-management'; + +import { extractChatGptAccountId, loginOpenAiCodexDeviceCode } from './openai-codex.js'; +import { loginMiniMaxPortalDeviceCode, type MiniMaxRegion } from './minimax-portal.js'; + +function isCancel<T>(value: T | symbol): value is symbol { + return p.isCancel(value); +} + +function toProviderOption(provider: (typeof CONNECT_PROVIDERS)[number]) { + return { + value: provider.providerId, + label: provider.label, + hint: provider.methods.length > 1 ? `${provider.methods.length} methods` : undefined, + } as const; +} + +function toMethodOption(method: ConnectMethod) { + return { + value: method.id, + label: method.label, + hint: method.hint, + } as const; +} + +function defaultProfileId(providerId: string, methodId: string): string { + return `${providerId}:${methodId}`; +} + +export async function handleConnectCommand(options?: { interactive?: boolean }): Promise<void> { + if (options?.interactive === false) { + throw new Error('Non-interactive connect is not implemented yet'); + } + + p.intro(chalk.inverse(' Connect Provider ')); + + const providerId = await p.select({ + message: 'Choose a provider', + options: CONNECT_PROVIDERS.map(toProviderOption), + }); + + if (isCancel(providerId)) { + p.cancel('Connect cancelled'); + return; + } + + const provider = getConnectProvider(providerId as string); + if (!provider) { + p.cancel(`Unknown provider: ${providerId as string}`); + return; + } + + const methodId = + provider.methods.length === 1 + ? provider.methods[0]!.id + : await p.select({ + message: `Choose a login method for ${provider.label}`, + options: provider.methods.map(toMethodOption), + }); + + if (isCancel(methodId)) { + p.cancel('Connect cancelled'); + return; + } + + const method = provider.methods.find((m) => m.id === methodId); + if (!method) { + p.cancel(`Unknown method: ${methodId as string}`); + return; + } + + const profileId = defaultProfileId(provider.providerId, method.id); + + if (method.kind === 'api_key') { + const apiKey = await p.password({ + message: `Enter ${provider.label} API key`, + validate: (value) => { + if (!value?.trim()) return 'API key is required'; + if (value.trim().length < 10) return 'API key looks unusually short'; + return undefined; + }, + }); + if (isCancel(apiKey)) { + p.cancel('Connect cancelled'); + return; + } + + await upsertLlmAuthProfile({ + profileId, + providerId: provider.providerId, + methodId: method.id, + label: method.label, + credential: { type: 'api_key', key: String(apiKey).trim() }, + }); + await setDefaultLlmAuthProfile({ providerId: provider.providerId, profileId }); + + p.outro(chalk.green(`✅ Connected ${provider.label} (API key saved)`)); + return; + } + + if (method.kind === 'token') { + const token = await p.password({ + message: `Enter ${provider.label} token`, + validate: (value) => { + if (!value?.trim()) return 'Token is required'; + if (value.trim().length < 10) return 'Token looks unusually short'; + return undefined; + }, + }); + if (isCancel(token)) { + p.cancel('Connect cancelled'); + return; + } + + await upsertLlmAuthProfile({ + profileId, + providerId: provider.providerId, + methodId: method.id, + label: method.label, + credential: { type: 'token', token: String(token).trim() }, + }); + await setDefaultLlmAuthProfile({ providerId: provider.providerId, profileId }); + + p.outro(chalk.green(`✅ Connected ${provider.label} (token saved)`)); + return; + } + + if (method.kind === 'oauth') { + if (provider.providerId === 'openai' && method.id === 'oauth_codex') { + const clientId = process.env.DEXTO_OPENAI_CODEX_OAUTH_CLIENT_ID?.trim(); + if (!clientId) { + p.outro( + chalk.red( + '❌ Missing DEXTO_OPENAI_CODEX_OAUTH_CLIENT_ID (OAuth app client id required)' + ) + ); + return; + } + + const spinner = p.spinner(); + spinner.start('Starting OpenAI OAuth (device code)…'); + + const userAgent = `dexto/${process.env.DEXTO_CLI_VERSION || 'dev'}`; + const flow = await loginOpenAiCodexDeviceCode({ clientId, userAgent }); + spinner.stop(`Open ${flow.deviceUrl} and enter code: ${flow.userCode}`); + + try { + await open(flow.deviceUrl); + } catch { + // ignore - user can open manually + } + + const pollSpinner = p.spinner(); + pollSpinner.start('Waiting for approval…'); + let tokens: Awaited<ReturnType<typeof flow.callback>>; + try { + tokens = await flow.callback(); + pollSpinner.stop('Approved'); + } catch (error) { + pollSpinner.stop('Failed'); + const message = error instanceof Error ? error.message : String(error); + console.log(''); + console.log( + chalk.yellow( + 'Note: OpenAI ChatGPT OAuth (Codex) may require allowlisting for our OAuth app.' + ) + ); + console.log(chalk.dim('If this fails, use the OpenAI API key method instead.')); + p.outro(chalk.red(`❌ OpenAI OAuth failed: ${message}`)); + return; + } + + const accountId = extractChatGptAccountId(tokens); + const expiresAt = Date.now() + tokens.expiresInSec * 1000; + + await upsertLlmAuthProfile({ + profileId, + providerId: provider.providerId, + methodId: method.id, + label: method.label, + credential: { + type: 'oauth', + accessToken: tokens.accessToken, + refreshToken: tokens.refreshToken, + expiresAt, + ...(accountId ? { metadata: { accountId } } : {}), + }, + }); + await setDefaultLlmAuthProfile({ providerId: provider.providerId, profileId }); + + p.outro(chalk.green('✅ Connected OpenAI (ChatGPT OAuth)')); + return; + } + + if (provider.providerId.startsWith('minimax')) { + const clientId = process.env.DEXTO_MINIMAX_PORTAL_OAUTH_CLIENT_ID?.trim(); + if (!clientId) { + p.outro( + chalk.red( + '❌ Missing DEXTO_MINIMAX_PORTAL_OAUTH_CLIENT_ID (OAuth app client id required)' + ) + ); + return; + } + + const region: MiniMaxRegion = + method.id === 'portal_oauth_cn' || provider.providerId.includes('-cn') + ? 'cn' + : ('global' satisfies MiniMaxRegion); + const spinner = p.spinner(); + spinner.start(`Starting MiniMax OAuth (${region})…`); + + const flow = await loginMiniMaxPortalDeviceCode({ region, clientId }); + spinner.stop(`Open ${flow.verificationUrl} and enter code: ${flow.userCode}`); + + try { + await open(flow.verificationUrl); + } catch { + // ignore - user can open manually + } + + const pollSpinner = p.spinner(); + pollSpinner.start('Waiting for approval…'); + const tokens = await flow.callback((message) => pollSpinner.message(message)); + pollSpinner.stop('Approved'); + + await upsertLlmAuthProfile({ + profileId, + providerId: provider.providerId, + methodId: method.id, + label: method.label, + credential: { + type: 'oauth', + accessToken: tokens.accessToken, + refreshToken: tokens.refreshToken, + expiresAt: tokens.expiresAt, + metadata: { + region, + ...(tokens.resourceUrl ? { resourceUrl: tokens.resourceUrl } : {}), + }, + }, + }); + await setDefaultLlmAuthProfile({ providerId: provider.providerId, profileId }); + + if (tokens.notificationMessage) { + console.log(chalk.dim(tokens.notificationMessage)); + } + + p.outro(chalk.green('✅ Connected MiniMax (OAuth)')); + return; + } + + p.outro(chalk.red(`❌ OAuth method not implemented for ${provider.label}`)); + return; + } + + if (method.kind === 'guidance') { + console.log(''); + console.log(chalk.cyan(`Guided setup for ${provider.label}`)); + + if (provider.modelsDevProviderId) { + console.log( + chalk.dim( + `Tip: See provider docs for ${provider.modelsDevProviderId} on models.dev and the upstream provider site.` + ) + ); + } + + const shouldOpenDocs = await p.confirm({ + message: 'Open provider documentation in your browser?', + initialValue: true, + }); + + if (!p.isCancel(shouldOpenDocs) && shouldOpenDocs) { + if (provider.modelsDevProviderId) { + // Best-effort: open models.dev provider page (if available); user can navigate from there. + await open(`https://models.dev/${provider.modelsDevProviderId}`); + } + } + + p.outro(chalk.green('✅ Guided setup complete')); + return; + } + + p.outro(chalk.red('❌ Unsupported connect method')); +} diff --git a/packages/cli/src/cli/commands/connect/minimax-portal.test.ts b/packages/cli/src/cli/commands/connect/minimax-portal.test.ts new file mode 100644 index 000000000..af6d180a2 --- /dev/null +++ b/packages/cli/src/cli/commands/connect/minimax-portal.test.ts @@ -0,0 +1,89 @@ +import { describe, expect, it, vi, beforeEach, afterEach } from 'vitest'; + +import { loginMiniMaxPortalDeviceCode } from './minimax-portal.js'; + +type MockFetchResponse = { + ok: boolean; + status: number; + statusText: string; + json?: () => Promise<unknown>; + text?: () => Promise<string>; +}; + +function okJson(data: unknown): MockFetchResponse { + return { + ok: true, + status: 200, + statusText: 'OK', + json: async () => data, + text: async () => JSON.stringify(data), + }; +} + +describe('minimax portal oauth (device code)', () => { + const originalFetch = global.fetch; + + beforeEach(() => { + vi.resetAllMocks(); + }); + + afterEach(() => { + global.fetch = originalFetch; + vi.resetAllMocks(); + }); + + it('completes oauth flow and returns tokens', async () => { + const mockFetch = vi.fn( + async (input: RequestInfo | URL, init?: RequestInit): Promise<MockFetchResponse> => { + const url = typeof input === 'string' ? input : input.toString(); + + if (url.endsWith('/oauth/code')) { + const body = typeof init?.body === 'string' ? init.body : ''; + const params = new URLSearchParams(body); + const state = params.get('state'); + return okJson({ + user_code: 'USER-CODE', + verification_uri: 'https://example.com/verify', + expired_in: Date.now() + 60_000, + interval: 1_000, + state, + }); + } + + if (url.endsWith('/oauth/token')) { + return { + ok: true, + status: 200, + statusText: 'OK', + text: async () => + JSON.stringify({ + status: 'success', + access_token: 'access-token', + refresh_token: 'refresh-token', + expired_in: 3600, + resource_url: 'https://api.minimax.io/anthropic/v1', + }), + }; + } + + throw new Error(`Unexpected fetch URL: ${url}`); + } + ); + + global.fetch = mockFetch as unknown as typeof fetch; + + const flow = await loginMiniMaxPortalDeviceCode({ + region: 'global', + clientId: 'client-id', + }); + + expect(flow.userCode).toBe('USER-CODE'); + expect(flow.verificationUrl).toBe('https://example.com/verify'); + + const tokens = await flow.callback(); + expect(tokens.accessToken).toBe('access-token'); + expect(tokens.refreshToken).toBe('refresh-token'); + expect(tokens.expiresAt).toBeGreaterThan(Date.now()); + expect(tokens.resourceUrl).toBe('https://api.minimax.io/anthropic/v1'); + }); +}); diff --git a/packages/cli/src/cli/commands/connect/minimax-portal.ts b/packages/cli/src/cli/commands/connect/minimax-portal.ts new file mode 100644 index 000000000..a168eba92 --- /dev/null +++ b/packages/cli/src/cli/commands/connect/minimax-portal.ts @@ -0,0 +1,199 @@ +import { createHash, randomBytes, randomUUID } from 'node:crypto'; + +export type MiniMaxRegion = 'cn' | 'global'; + +const MINIMAX_SCOPE = 'group_id profile model.completion'; +const MINIMAX_GRANT_TYPE = 'urn:ietf:params:oauth:grant-type:user_code'; + +function getBaseUrl(region: MiniMaxRegion): string { + return region === 'cn' ? 'https://api.minimaxi.com' : 'https://api.minimax.io'; +} + +function toFormUrlEncoded(data: Record<string, string>): string { + return Object.entries(data) + .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`) + .join('&'); +} + +function generatePkce(): { verifier: string; challenge: string; state: string } { + const verifier = randomBytes(32).toString('base64url'); + const challenge = createHash('sha256').update(verifier).digest('base64url'); + const state = randomBytes(16).toString('base64url'); + return { verifier, challenge, state }; +} + +function toExpiresAt(expiredIn: number): number { + // Heuristic: values in seconds are small; epoch ms is ~1.7e12. + if (!Number.isFinite(expiredIn) || expiredIn <= 0) return Date.now(); + if (expiredIn < 10_000_000_000) { + return Date.now() + expiredIn * 1000; + } + return expiredIn; +} + +export type MiniMaxOAuthTokens = { + accessToken: string; + refreshToken: string; + expiresAt: number; + resourceUrl?: string | undefined; + notificationMessage?: string | undefined; +}; + +export async function loginMiniMaxPortalDeviceCode(options: { + region: MiniMaxRegion; + clientId: string; +}): Promise<{ + verificationUrl: string; + userCode: string; + callback: (onProgress?: (message: string) => void) => Promise<MiniMaxOAuthTokens>; +}> { + const baseUrl = getBaseUrl(options.region); + const endpoints = { + code: `${baseUrl}/oauth/code`, + token: `${baseUrl}/oauth/token`, + }; + + const { verifier, challenge, state } = generatePkce(); + + const codeRes = await fetch(endpoints.code, { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + Accept: 'application/json', + 'x-request-id': randomUUID(), + }, + body: toFormUrlEncoded({ + response_type: 'code', + client_id: options.clientId, + scope: MINIMAX_SCOPE, + code_challenge: challenge, + code_challenge_method: 'S256', + state, + }), + signal: AbortSignal.timeout(15_000), + }); + + if (!codeRes.ok) { + const text = await codeRes.text().catch(() => ''); + throw new Error( + `MiniMax OAuth init failed (${codeRes.status}): ${text || codeRes.statusText}` + ); + } + + const oauth = (await codeRes.json()) as { + user_code?: string; + verification_uri?: string; + expired_in?: number; + interval?: number; + state?: string; + error?: string; + }; + + if (!oauth.user_code || !oauth.verification_uri) { + throw new Error( + oauth.error ?? + 'MiniMax OAuth authorization returned incomplete payload (missing user_code or verification_uri)' + ); + } + if (oauth.state !== state) { + throw new Error('MiniMax OAuth state mismatch'); + } + + const verificationUrl = oauth.verification_uri; + const userCode = oauth.user_code; + + const pollStart = Date.now(); + const expiresAt = toExpiresAt(oauth.expired_in ?? 0); + let pollIntervalMs = Math.max(oauth.interval ?? 2000, 500); + + let onProgress: ((message: string) => void) | undefined; + + type TokenPollPayload = { + status?: string; + access_token?: string | null; + refresh_token?: string | null; + expired_in?: number | null; + resource_url?: string | null; + notification_message?: string | null; + base_resp?: { status_msg?: string | null } | null; + }; + + function parsePayload(text: string): TokenPollPayload | null { + if (!text) return null; + try { + const json = JSON.parse(text) as unknown; + if (typeof json !== 'object' || json === null) return null; + return json as TokenPollPayload; + } catch { + return null; + } + } + + async function pollToken(): Promise<MiniMaxOAuthTokens> { + while (Date.now() < expiresAt) { + const res = await fetch(endpoints.token, { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + Accept: 'application/json', + }, + body: toFormUrlEncoded({ + grant_type: MINIMAX_GRANT_TYPE, + client_id: options.clientId, + user_code: userCode, + code_verifier: verifier, + }), + signal: AbortSignal.timeout(15_000), + }); + + const text = await res.text().catch(() => ''); + const payload = parsePayload(text); + + if (!res.ok) { + const msg = payload?.base_resp?.status_msg ?? text ?? res.statusText; + throw new Error(`MiniMax OAuth token poll failed (${res.status}): ${msg}`); + } + + const status: string | undefined = payload?.status; + if (status === 'success') { + const accessToken = payload?.access_token ?? undefined; + const refreshToken = payload?.refresh_token ?? undefined; + const expiredIn = payload?.expired_in ?? undefined; + if (!accessToken || !refreshToken || !expiredIn) { + throw new Error('MiniMax OAuth returned incomplete token payload'); + } + return { + accessToken, + refreshToken, + expiresAt: toExpiresAt(expiredIn), + ...(payload?.resource_url ? { resourceUrl: payload.resource_url } : {}), + ...(payload?.notification_message + ? { notificationMessage: payload.notification_message } + : {}), + }; + } + + if (status === 'error') { + throw new Error('MiniMax OAuth returned error status'); + } + + // Pending + pollIntervalMs = Math.min(Math.round(pollIntervalMs * 1.5), 10_000); + await new Promise((resolve) => setTimeout(resolve, pollIntervalMs)); + + const elapsedSec = Math.round((Date.now() - pollStart) / 1000); + onProgress?.(`Waiting for approval… (${elapsedSec}s)`); + } + + throw new Error('MiniMax OAuth timed out waiting for authorization'); + } + + return { + verificationUrl, + userCode, + callback: async (progressCb) => { + onProgress = progressCb; + return await pollToken(); + }, + }; +} diff --git a/packages/cli/src/cli/commands/connect/openai-codex.test.ts b/packages/cli/src/cli/commands/connect/openai-codex.test.ts new file mode 100644 index 000000000..7f1082eb8 --- /dev/null +++ b/packages/cli/src/cli/commands/connect/openai-codex.test.ts @@ -0,0 +1,80 @@ +import { describe, expect, it, vi, beforeEach, afterEach } from 'vitest'; + +import { loginOpenAiCodexDeviceCode } from './openai-codex.js'; + +type MockFetchResponse = { + ok: boolean; + status: number; + statusText: string; + json: () => Promise<unknown>; + text: () => Promise<string>; +}; + +function okJson(data: unknown): MockFetchResponse { + return { + ok: true, + status: 200, + statusText: 'OK', + json: async () => data, + text: async () => JSON.stringify(data), + }; +} + +describe('openai codex oauth (device code)', () => { + const originalFetch = global.fetch; + + beforeEach(() => { + vi.resetAllMocks(); + }); + + afterEach(() => { + global.fetch = originalFetch; + vi.resetAllMocks(); + }); + + it('completes device-code flow and returns tokens', async () => { + const mockFetch = vi.fn(async (input: RequestInfo | URL) => { + const url = typeof input === 'string' ? input : input.toString(); + + if (url.endsWith('/api/accounts/deviceauth/usercode')) { + return okJson({ + device_auth_id: 'device-auth-id', + user_code: 'ABCD-EFGH', + interval: '1', + }); + } + + if (url.endsWith('/api/accounts/deviceauth/token')) { + return okJson({ + authorization_code: 'auth-code', + code_verifier: 'code-verifier', + }); + } + + if (url.endsWith('/oauth/token')) { + return okJson({ + access_token: 'access-token', + refresh_token: 'refresh-token', + expires_in: 3600, + }); + } + + throw new Error(`Unexpected fetch URL: ${url}`); + }); + + global.fetch = mockFetch as unknown as typeof fetch; + + const flow = await loginOpenAiCodexDeviceCode({ + clientId: 'client-id', + userAgent: 'dexto-test', + }); + + expect(flow.deviceUrl).toContain('auth.openai.com'); + expect(flow.userCode).toBe('ABCD-EFGH'); + + const tokens = await flow.callback(); + expect(tokens.accessToken).toBe('access-token'); + expect(tokens.refreshToken).toBe('refresh-token'); + expect(tokens.expiresInSec).toBe(3600); + }); +}); diff --git a/packages/cli/src/cli/commands/connect/openai-codex.ts b/packages/cli/src/cli/commands/connect/openai-codex.ts new file mode 100644 index 000000000..1804e4510 --- /dev/null +++ b/packages/cli/src/cli/commands/connect/openai-codex.ts @@ -0,0 +1,234 @@ +import { randomBytes, createHash } from 'node:crypto'; + +const OPENAI_AUTH_ISSUER = 'https://auth.openai.com'; +const DEVICE_CODE_URL = `${OPENAI_AUTH_ISSUER}/codex/device`; + +export type OpenAiCodexTokens = { + accessToken: string; + refreshToken: string; + expiresInSec: number; + idToken?: string | undefined; +}; + +function decodeJwtClaims(token: string): Record<string, unknown> | null { + const parts = token.split('.'); + if (parts.length !== 3) return null; + try { + const json = Buffer.from(parts[1]!, 'base64url').toString('utf-8'); + return JSON.parse(json) as Record<string, unknown>; + } catch { + return null; + } +} + +function extractAccountIdFromClaims(claims: Record<string, unknown>): string | null { + const direct = claims['chatgpt_account_id']; + if (typeof direct === 'string' && direct.trim()) return direct; + + const auth = claims['https://api.openai.com/auth']; + if (typeof auth === 'object' && auth !== null) { + const maybe = (auth as Record<string, unknown>)['chatgpt_account_id']; + if (typeof maybe === 'string' && maybe.trim()) return maybe; + } + + const orgs = claims['organizations']; + if (Array.isArray(orgs) && orgs.length > 0) { + const first = orgs[0]; + if (typeof first === 'object' && first !== null) { + const id = (first as Record<string, unknown>)['id']; + if (typeof id === 'string' && id.trim()) return id; + } + } + + return null; +} + +export function extractChatGptAccountId(tokens: OpenAiCodexTokens): string | null { + if (tokens.idToken) { + const claims = decodeJwtClaims(tokens.idToken); + if (claims) { + const id = extractAccountIdFromClaims(claims); + if (id) return id; + } + } + + const accessClaims = decodeJwtClaims(tokens.accessToken); + if (accessClaims) { + return extractAccountIdFromClaims(accessClaims); + } + + return null; +} + +export async function loginOpenAiCodexDeviceCode(options: { + clientId: string; + userAgent: string; +}): Promise<{ + deviceUrl: string; + userCode: string; + pollIntervalMs: number; + callback: () => Promise<OpenAiCodexTokens>; +}> { + const deviceResponse = await fetch(`${OPENAI_AUTH_ISSUER}/api/accounts/deviceauth/usercode`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'User-Agent': options.userAgent, + }, + body: JSON.stringify({ client_id: options.clientId }), + signal: AbortSignal.timeout(15_000), + }); + + if (!deviceResponse.ok) { + const text = await deviceResponse.text().catch(() => ''); + throw new Error( + `OpenAI device auth init failed (${deviceResponse.status}): ${text || deviceResponse.statusText}` + ); + } + + const deviceData = (await deviceResponse.json()) as { + device_auth_id: string; + user_code: string; + interval?: string; + }; + + const intervalSec = Math.max(Number.parseInt(deviceData.interval ?? '5', 10) || 5, 1); + const pollIntervalMs = intervalSec * 1000; + + async function pollForAuthorizationCode(): Promise<{ + authorizationCode: string; + codeVerifier: string; + }> { + const startedAt = Date.now(); + const maxWaitMs = 10 * 60 * 1000; + + while (Date.now() < startedAt + maxWaitMs) { + const response = await fetch(`${OPENAI_AUTH_ISSUER}/api/accounts/deviceauth/token`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'User-Agent': options.userAgent, + }, + body: JSON.stringify({ + device_auth_id: deviceData.device_auth_id, + user_code: deviceData.user_code, + }), + signal: AbortSignal.timeout(15_000), + }); + + if (response.ok) { + const data = (await response.json()) as { + authorization_code: string; + code_verifier: string; + }; + return { + authorizationCode: data.authorization_code, + codeVerifier: data.code_verifier, + }; + } + + // Pending (user not approved yet) shows up as 403/404 in prior art. + if (response.status === 403 || response.status === 404) { + await new Promise((resolve) => setTimeout(resolve, pollIntervalMs + 3000)); + continue; + } + + const text = await response.text().catch(() => ''); + throw new Error( + `OpenAI device auth poll failed (${response.status}): ${text || response.statusText}` + ); + } + + throw new Error('OpenAI device auth timed out waiting for authorization'); + } + + async function exchangeAuthorizationCode(params: { + authorizationCode: string; + codeVerifier: string; + }): Promise<OpenAiCodexTokens> { + const tokenResponse = await fetch(`${OPENAI_AUTH_ISSUER}/oauth/token`, { + method: 'POST', + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + body: new URLSearchParams({ + grant_type: 'authorization_code', + code: params.authorizationCode, + redirect_uri: `${OPENAI_AUTH_ISSUER}/deviceauth/callback`, + client_id: options.clientId, + code_verifier: params.codeVerifier, + }).toString(), + signal: AbortSignal.timeout(15_000), + }); + + if (!tokenResponse.ok) { + const text = await tokenResponse.text().catch(() => ''); + throw new Error( + `OpenAI token exchange failed (${tokenResponse.status}): ${text || tokenResponse.statusText}` + ); + } + + const tokens = (await tokenResponse.json()) as { + access_token: string; + refresh_token: string; + expires_in?: number; + id_token?: string; + }; + + return { + accessToken: tokens.access_token, + refreshToken: tokens.refresh_token, + expiresInSec: tokens.expires_in ?? 3600, + ...(tokens.id_token ? { idToken: tokens.id_token } : {}), + }; + } + + return { + deviceUrl: DEVICE_CODE_URL, + userCode: deviceData.user_code, + pollIntervalMs, + callback: async () => { + const { authorizationCode, codeVerifier } = await pollForAuthorizationCode(); + return await exchangeAuthorizationCode({ authorizationCode, codeVerifier }); + }, + }; +} + +export type OpenAiBrowserOauthResult = { + url: string; + callback: () => Promise<OpenAiCodexTokens>; +}; + +function createPkceCodes(): { verifier: string; challenge: string } { + const verifier = randomBytes(32).toString('base64url'); + const challenge = createHash('sha256').update(verifier).digest('base64url'); + return { verifier, challenge }; +} + +function generateState(): string { + return randomBytes(16).toString('base64url'); +} + +export async function buildOpenAiCodexAuthorizeUrl(options: { + clientId: string; + redirectUri: string; + originator: string; +}): Promise<{ url: string; verifier: string; state: string }> { + const pkce = createPkceCodes(); + const state = generateState(); + const params = new URLSearchParams({ + response_type: 'code', + client_id: options.clientId, + redirect_uri: options.redirectUri, + scope: 'openid profile email offline_access', + code_challenge: pkce.challenge, + code_challenge_method: 'S256', + id_token_add_organizations: 'true', + codex_cli_simplified_flow: 'true', + state, + originator: options.originator, + }); + return { + url: `${OPENAI_AUTH_ISSUER}/oauth/authorize?${params.toString()}`, + verifier: pkce.verifier, + state, + }; +} diff --git a/packages/cli/src/cli/commands/interactive-commands/commands.ts b/packages/cli/src/cli/commands/interactive-commands/commands.ts index 9e27f3f08..f34cec172 100644 --- a/packages/cli/src/cli/commands/interactive-commands/commands.ts +++ b/packages/cli/src/cli/commands/interactive-commands/commands.ts @@ -36,6 +36,7 @@ import { toolCommands } from './tool-commands.js'; import { promptCommands } from './prompt-commands.js'; import { documentationCommands } from './documentation-commands.js'; import { loginCommand } from './auth/index.js'; +import { connectCommand } from './connect/index.js'; /** * Complete list of all available CLI commands. @@ -89,6 +90,9 @@ const baseCommands: CommandDefinition[] = [ // Auth commands (feature-flagged) ...(isDextoAuthEnabled() ? [loginCommand] : []), + + // Provider connect + connectCommand, ]; // Add help command that can see all commands diff --git a/packages/cli/src/cli/commands/interactive-commands/connect/index.ts b/packages/cli/src/cli/commands/interactive-commands/connect/index.ts new file mode 100644 index 000000000..0f404ca1f --- /dev/null +++ b/packages/cli/src/cli/commands/interactive-commands/connect/index.ts @@ -0,0 +1,19 @@ +/** + * Connect Commands Module + * + * Provider connect commands for interactive CLI. + */ + +import type { CommandDefinition } from '../command-parser.js'; +import { handleConnectCommand } from '../../connect/index.js'; + +export const connectCommand: CommandDefinition = { + name: 'connect', + description: 'Connect an LLM provider (OAuth, API keys, tokens)', + usage: '/connect', + category: 'General', + handler: async () => { + await handleConnectCommand({ interactive: true }); + return true; + }, +}; diff --git a/packages/cli/src/cli/ink-cli/components/overlays/custom-model-wizard/provider-config.ts b/packages/cli/src/cli/ink-cli/components/overlays/custom-model-wizard/provider-config.ts index 6426f9b44..b9c97b45b 100644 --- a/packages/cli/src/cli/ink-cli/components/overlays/custom-model-wizard/provider-config.ts +++ b/packages/cli/src/cli/ink-cli/components/overlays/custom-model-wizard/provider-config.ts @@ -473,7 +473,7 @@ export const PROVIDER_CONFIGS: Record<CustomModelProvider, ProviderConfig> = { }, { ...DISPLAY_NAME_STEP, placeholder: 'e.g., Claude 4.5 Sonnet via Dexto' }, REASONING_EFFORT_STEP, - // No API key step - Dexto uses OAuth login (DEXTO_API_KEY from auth.json) + // No API key step - Dexto uses OAuth login (DEXTO_API_KEY from ~/.dexto/auth/dexto.json) ], buildModel: (values, provider) => { const model: CustomModel = { diff --git a/packages/cli/src/cli/ink-cli/utils/llm-provider-display.ts b/packages/cli/src/cli/ink-cli/utils/llm-provider-display.ts index a59dd86c6..078b5ec28 100644 --- a/packages/cli/src/cli/ink-cli/utils/llm-provider-display.ts +++ b/packages/cli/src/cli/ink-cli/utils/llm-provider-display.ts @@ -9,7 +9,17 @@ const LLM_PROVIDER_DISPLAY_NAMES: Record<LLMProvider, string> = { xai: 'xAI', cohere: 'Cohere', minimax: 'MiniMax', + 'minimax-cn': 'MiniMax (CN)', + 'minimax-coding-plan': 'MiniMax (Coding Plan)', + 'minimax-cn-coding-plan': 'MiniMax (CN, Coding Plan)', glm: 'GLM', + zhipuai: 'Zhipu AI (GLM)', + 'zhipuai-coding-plan': 'Zhipu AI (Coding Plan)', + zai: 'Z.AI', + 'zai-coding-plan': 'Z.AI (Coding Plan)', + moonshotai: 'Moonshot AI (Kimi)', + 'moonshotai-cn': 'Moonshot AI (Kimi) (CN)', + 'kimi-for-coding': 'Kimi For Coding', openrouter: 'OpenRouter', litellm: 'LiteLLM', glama: 'Glama', diff --git a/packages/cli/src/config/cli-overrides.ts b/packages/cli/src/config/cli-overrides.ts index bea83cc23..c6f9e1dc5 100644 --- a/packages/cli/src/config/cli-overrides.ts +++ b/packages/cli/src/config/cli-overrides.ts @@ -209,7 +209,17 @@ function getEnvVarForProvider(provider: LLMProvider): string { xai: 'XAI_API_KEY', cohere: 'COHERE_API_KEY', minimax: 'MINIMAX_API_KEY', + 'minimax-cn': 'MINIMAX_API_KEY', + 'minimax-coding-plan': 'MINIMAX_API_KEY', + 'minimax-cn-coding-plan': 'MINIMAX_API_KEY', glm: 'ZHIPU_API_KEY', + zhipuai: 'ZHIPU_API_KEY', + 'zhipuai-coding-plan': 'ZHIPU_API_KEY', + zai: 'ZHIPU_API_KEY', + 'zai-coding-plan': 'ZHIPU_API_KEY', + moonshotai: 'MOONSHOT_API_KEY', + 'moonshotai-cn': 'MOONSHOT_API_KEY', + 'kimi-for-coding': 'KIMI_API_KEY', openrouter: 'OPENROUTER_API_KEY', litellm: 'LITELLM_API_KEY', glama: 'GLAMA_API_KEY', diff --git a/packages/cli/src/index-main.ts b/packages/cli/src/index-main.ts index 67dbdd32d..640779447 100644 --- a/packages/cli/src/index-main.ts +++ b/packages/cli/src/index-main.ts @@ -18,8 +18,8 @@ process.env.DEXTO_CLI_VERSION = pkg.version; // Populate DEXTO_API_KEY for Dexto gateway routing // Resolution order in getDextoApiKey(): // 1. Explicit env var (CI, testing, account override) -// 2. auth.json from `dexto login` -import { isDextoAuthEnabled } from '@dexto/agent-management'; +// 2. ~/.dexto/auth/dexto.json from `dexto login` +import { createDefaultLlmAuthResolver, isDextoAuthEnabled } from '@dexto/agent-management'; if (isDextoAuthEnabled()) { const { getDextoApiKey } = await import('./cli/auth/index.js'); const dextoApiKey = await getDextoApiKey(); @@ -777,7 +777,13 @@ async function bootstrapAgentFromGlobalOpts() { const validatedConfig = AgentConfigSchema.parse(enrichedConfig); const services = await resolveServicesFromConfig(validatedConfig, image); - const agent = new DextoAgent(toDextoAgentOptions({ config: validatedConfig, services })); + const agent = new DextoAgent( + toDextoAgentOptions({ + config: validatedConfig, + services, + overrides: { llmAuthResolver: createDefaultLlmAuthResolver() }, + }) + ); await agent.start(); // Register graceful shutdown @@ -1652,7 +1658,11 @@ program toDextoAgentOptions({ config: validatedConfig, services, - overrides: { sessionLoggerFactory, mcpAuthProviderFactory }, + overrides: { + sessionLoggerFactory, + mcpAuthProviderFactory, + llmAuthResolver: createDefaultLlmAuthResolver(), + }, }) ); diff --git a/packages/core/src/llm/auth/types.ts b/packages/core/src/llm/auth/types.ts new file mode 100644 index 000000000..19625b350 --- /dev/null +++ b/packages/core/src/llm/auth/types.ts @@ -0,0 +1,32 @@ +import type { LLMProvider } from '../types.js'; + +export type LlmRuntimeAuthOverrides = { + /** + * Credential value to give the SDK client constructor. + * + * - For API key methods: the actual API key. + * - For OAuth methods: typically a non-empty dummy value, while `fetch` injects + * the real access token per request (and can refresh on demand). + */ + apiKey?: string | undefined; + /** Optional base URL override used at runtime (not exposed in config schemas). */ + baseURL?: string | undefined; + /** Extra headers to merge into requests. */ + headers?: Record<string, string> | undefined; + /** + * Optional fetch wrapper to implement auth-dependent behavior: + * - inject authorization headers + * - refresh OAuth tokens + * - rewrite request URLs when required (e.g., Codex) + */ + fetch?: typeof fetch | undefined; +}; + +export type ResolveLlmRuntimeAuthInput = { + provider: LLMProvider; + model: string; +}; + +export interface LlmAuthResolver { + resolveRuntimeAuth(input: ResolveLlmRuntimeAuthInput): LlmRuntimeAuthOverrides | null; +} diff --git a/packages/core/src/llm/index.ts b/packages/core/src/llm/index.ts index 98ed20302..a2ffad535 100644 --- a/packages/core/src/llm/index.ts +++ b/packages/core/src/llm/index.ts @@ -4,6 +4,7 @@ export * from './registry/index.js'; export * from './curation.js'; export * from './validation.js'; export * from './types.js'; +export * from './auth/types.js'; export * from './services/index.js'; export * from './schemas.js'; export { diff --git a/packages/core/src/llm/registry/index.ts b/packages/core/src/llm/registry/index.ts index c96d4e1ce..342d79b60 100644 --- a/packages/core/src/llm/registry/index.ts +++ b/packages/core/src/llm/registry/index.ts @@ -187,13 +187,31 @@ export const LLM_REGISTRY: Record<LLMProvider, ProviderInfo> = { baseURLSupport: 'none', supportedFileTypes: [], // No defaults - models must explicitly specify support }, - // https://platform.minimax.io/docs/api-reference/text-openai-api - // MiniMax provides an OpenAI-compatible endpoint at https://api.minimax.chat/v1 + // https://platform.minimax.io/docs/guides/quickstart + // MiniMax provides an Anthropic-compatible endpoint (models.dev): + // https://api.minimax.io/anthropic/v1 minimax: { models: MODELS_BY_PROVIDER.minimax, baseURLSupport: 'none', supportedFileTypes: [], // No defaults - models must explicitly specify support }, + // https://api.minimaxi.com/anthropic/v1 (CN) + 'minimax-cn': { + models: MODELS_BY_PROVIDER['minimax-cn'], + baseURLSupport: 'none', + supportedFileTypes: [], + }, + // Coding plan routes through the same API base URL, but is modeled as a separate provider in models.dev + 'minimax-coding-plan': { + models: MODELS_BY_PROVIDER['minimax-coding-plan'], + baseURLSupport: 'none', + supportedFileTypes: [], + }, + 'minimax-cn-coding-plan': { + models: MODELS_BY_PROVIDER['minimax-cn-coding-plan'], + baseURLSupport: 'none', + supportedFileTypes: [], + }, // https://open.bigmodel.cn/dev/api/normal-model/glm-4 // GLM (Zhipu AI) provides an OpenAI-compatible endpoint glm: { @@ -201,6 +219,44 @@ export const LLM_REGISTRY: Record<LLMProvider, ProviderInfo> = { baseURLSupport: 'none', supportedFileTypes: [], // No defaults - models must explicitly specify support }, + // models.dev-aligned aliases/presets + zhipuai: { + models: MODELS_BY_PROVIDER.zhipuai, + baseURLSupport: 'none', + supportedFileTypes: [], + }, + 'zhipuai-coding-plan': { + models: MODELS_BY_PROVIDER['zhipuai-coding-plan'], + baseURLSupport: 'none', + supportedFileTypes: [], + }, + zai: { + models: MODELS_BY_PROVIDER.zai, + baseURLSupport: 'none', + supportedFileTypes: [], + }, + 'zai-coding-plan': { + models: MODELS_BY_PROVIDER['zai-coding-plan'], + baseURLSupport: 'none', + supportedFileTypes: [], + }, + // Moonshot (Kimi) OpenAI-compatible endpoints + moonshotai: { + models: MODELS_BY_PROVIDER.moonshotai, + baseURLSupport: 'none', + supportedFileTypes: [], + }, + 'moonshotai-cn': { + models: MODELS_BY_PROVIDER['moonshotai-cn'], + baseURLSupport: 'none', + supportedFileTypes: [], + }, + // Kimi For Coding (Anthropic-compatible) + 'kimi-for-coding': { + models: MODELS_BY_PROVIDER['kimi-for-coding'], + baseURLSupport: 'none', + supportedFileTypes: [], + }, // https://openrouter.ai/docs // OpenRouter is a unified API gateway providing access to 100+ models from various providers. // Model validation is handled dynamically via openrouter-model-registry.ts @@ -600,7 +656,16 @@ const OPENROUTER_PREFIX_BY_PROVIDER: Partial<Record<LLMProvider, string>> = { xai: 'x-ai', cohere: 'cohere', minimax: 'minimax', + 'minimax-cn': 'minimax', + 'minimax-coding-plan': 'minimax', + 'minimax-cn-coding-plan': 'minimax', glm: 'z-ai', + zhipuai: 'z-ai', + 'zhipuai-coding-plan': 'z-ai', + zai: 'z-ai', + 'zai-coding-plan': 'z-ai', + moonshotai: 'moonshotai', + 'moonshotai-cn': 'moonshotai', }; function getOpenRouterModelIdSet(): Set<string> { diff --git a/packages/core/src/llm/registry/models.generated.ts b/packages/core/src/llm/registry/models.generated.ts index 753e8c51f..b8466c05e 100644 --- a/packages/core/src/llm/registry/models.generated.ts +++ b/packages/core/src/llm/registry/models.generated.ts @@ -339,6 +339,32 @@ export const MODELS_BY_PROVIDER = { unit: 'per_million_tokens', }, }, + { + name: 'gpt-5.3-codex', + displayName: 'GPT-5.3 Codex', + maxInputTokens: 272000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1.75, + outputPerM: 14, + cacheReadPerM: 0.175, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.3-codex-spark', + displayName: 'GPT-5.3 Codex Spark', + maxInputTokens: 100000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1.75, + outputPerM: 14, + cacheReadPerM: 0.175, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, { name: 'o1', displayName: 'o1', @@ -709,6 +735,20 @@ export const MODELS_BY_PROVIDER = { unit: 'per_million_tokens', }, }, + { + name: 'claude-opus-4-6', + displayName: 'Claude Opus 4.6', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, { name: 'claude-sonnet-4-0', displayName: 'Claude Sonnet 4 (latest)', @@ -765,6 +805,20 @@ export const MODELS_BY_PROVIDER = { unit: 'per_million_tokens', }, }, + { + name: 'claude-sonnet-4-6', + displayName: 'Claude Sonnet 4.6', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, ], google: [ { @@ -1683,6 +1737,18 @@ export const MODELS_BY_PROVIDER = { unit: 'per_million_tokens', }, }, + { + name: 'command-r7b-arabic-02-2025', + displayName: 'Command R7B Arabic', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.0375, + outputPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, ], minimax: [ { @@ -1710,6 +1776,199 @@ export const MODELS_BY_PROVIDER = { }, default: true, }, + { + name: 'MiniMax-M2.5', + displayName: 'MiniMax-M2.5', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + cacheReadPerM: 0.03, + cacheWritePerM: 0.375, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'MiniMax-M2.5-highspeed', + displayName: 'MiniMax-M2.5-highspeed', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.4, + cacheReadPerM: 0.06, + cacheWritePerM: 0.375, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + 'minimax-cn': [ + { + name: 'MiniMax-M2', + displayName: 'MiniMax-M2', + maxInputTokens: 196608, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'MiniMax-M2.1', + displayName: 'MiniMax-M2.1', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + default: true, + }, + { + name: 'MiniMax-M2.5', + displayName: 'MiniMax-M2.5', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + cacheReadPerM: 0.03, + cacheWritePerM: 0.375, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'MiniMax-M2.5-highspeed', + displayName: 'MiniMax-M2.5-highspeed', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.4, + cacheReadPerM: 0.06, + cacheWritePerM: 0.375, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + 'minimax-coding-plan': [ + { + name: 'MiniMax-M2', + displayName: 'MiniMax-M2', + maxInputTokens: 196608, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'MiniMax-M2.1', + displayName: 'MiniMax-M2.1', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + default: true, + }, + { + name: 'MiniMax-M2.5', + displayName: 'MiniMax-M2.5', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'MiniMax-M2.5-highspeed', + displayName: 'MiniMax-M2.5-highspeed', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + 'minimax-cn-coding-plan': [ + { + name: 'MiniMax-M2', + displayName: 'MiniMax-M2', + maxInputTokens: 196608, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'MiniMax-M2.1', + displayName: 'MiniMax-M2.1', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + default: true, + }, + { + name: 'MiniMax-M2.5', + displayName: 'MiniMax-M2.5', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'MiniMax-M2.5-highspeed', + displayName: 'MiniMax-M2.5-highspeed', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, ], glm: [ { @@ -1821,35 +2080,766 @@ export const MODELS_BY_PROVIDER = { unit: 'per_million_tokens', }, }, - ], - openrouter: [ { - name: 'anthropic/claude-3.5-haiku', - displayName: 'Claude Haiku 3.5', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'glm-5', + displayName: 'GLM-5', + maxInputTokens: 204800, + supportedFileTypes: [], pricing: { - inputPerM: 0.8, - outputPerM: 4, - cacheReadPerM: 0.08, - cacheWritePerM: 1, + inputPerM: 1, + outputPerM: 3.2, + cacheReadPerM: 0.2, + cacheWritePerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, + ], + zhipuai: [ { - name: 'anthropic/claude-3.7-sonnet', - displayName: 'Claude Sonnet 3.7', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'glm-4.5', + displayName: 'GLM-4.5', + maxInputTokens: 131072, + supportedFileTypes: [], pricing: { - inputPerM: 15, - outputPerM: 75, - cacheReadPerM: 1.5, - cacheWritePerM: 18.75, - currency: 'USD', - unit: 'per_million_tokens', - }, + inputPerM: 0.6, + outputPerM: 2.2, + cacheReadPerM: 0.11, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-4.5-air', + displayName: 'GLM-4.5-Air', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 1.1, + cacheReadPerM: 0.03, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-4.5-flash', + displayName: 'GLM-4.5-Flash', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-4.5v', + displayName: 'GLM-4.5V', + maxInputTokens: 64000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.6, + outputPerM: 1.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-4.6', + displayName: 'GLM-4.6', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.2, + cacheReadPerM: 0.11, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-4.6v', + displayName: 'GLM-4.6V', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.3, + outputPerM: 0.9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-4.7', + displayName: 'GLM-4.7', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.2, + cacheReadPerM: 0.11, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + default: true, + }, + { + name: 'glm-4.7-flash', + displayName: 'GLM-4.7-Flash', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-5', + displayName: 'GLM-5', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 3.2, + cacheReadPerM: 0.2, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + 'zhipuai-coding-plan': [ + { + name: 'glm-4.5', + displayName: 'GLM-4.5', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-4.5-air', + displayName: 'GLM-4.5-Air', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-4.5-flash', + displayName: 'GLM-4.5-Flash', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-4.5v', + displayName: 'GLM-4.5V', + maxInputTokens: 64000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-4.6', + displayName: 'GLM-4.6', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-4.6v', + displayName: 'GLM-4.6V', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-4.6v-flash', + displayName: 'GLM-4.6V-Flash', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-4.7', + displayName: 'GLM-4.7', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + default: true, + }, + { + name: 'glm-5', + displayName: 'GLM-5', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + zai: [ + { + name: 'glm-4.5', + displayName: 'GLM-4.5', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.2, + cacheReadPerM: 0.11, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-4.5-air', + displayName: 'GLM-4.5-Air', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 1.1, + cacheReadPerM: 0.03, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-4.5-flash', + displayName: 'GLM-4.5-Flash', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-4.5v', + displayName: 'GLM-4.5V', + maxInputTokens: 64000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.6, + outputPerM: 1.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-4.6', + displayName: 'GLM-4.6', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.2, + cacheReadPerM: 0.11, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-4.6v', + displayName: 'GLM-4.6V', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.3, + outputPerM: 0.9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-4.7', + displayName: 'GLM-4.7', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.2, + cacheReadPerM: 0.11, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + default: true, + }, + { + name: 'glm-4.7-flash', + displayName: 'GLM-4.7-Flash', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-5', + displayName: 'GLM-5', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 3.2, + cacheReadPerM: 0.2, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + 'zai-coding-plan': [ + { + name: 'glm-4.5', + displayName: 'GLM-4.5', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-4.5-air', + displayName: 'GLM-4.5-Air', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-4.5-flash', + displayName: 'GLM-4.5-Flash', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-4.5v', + displayName: 'GLM-4.5V', + maxInputTokens: 64000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-4.6', + displayName: 'GLM-4.6', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-4.6v', + displayName: 'GLM-4.6V', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-4.7', + displayName: 'GLM-4.7', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + default: true, + }, + { + name: 'glm-4.7-flash', + displayName: 'GLM-4.7-Flash', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-4.7-flashx', + displayName: 'GLM-4.7-FlashX', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.07, + outputPerM: 0.4, + cacheReadPerM: 0.01, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-5', + displayName: 'GLM-5', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + moonshotai: [ + { + name: 'kimi-k2-0711-preview', + displayName: 'Kimi K2 0711', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.5, + cacheReadPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2-0905-preview', + displayName: 'Kimi K2 0905', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.5, + cacheReadPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2-thinking', + displayName: 'Kimi K2 Thinking', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.5, + cacheReadPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2-thinking-turbo', + displayName: 'Kimi K2 Thinking Turbo', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 1.15, + outputPerM: 8, + cacheReadPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2-turbo-preview', + displayName: 'Kimi K2 Turbo', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 2.4, + outputPerM: 10, + cacheReadPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2.5', + displayName: 'Kimi K2.5', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.6, + outputPerM: 3, + cacheReadPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + default: true, + }, + ], + 'moonshotai-cn': [ + { + name: 'kimi-k2-0711-preview', + displayName: 'Kimi K2 0711', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.5, + cacheReadPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2-0905-preview', + displayName: 'Kimi K2 0905', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.5, + cacheReadPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2-thinking', + displayName: 'Kimi K2 Thinking', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.5, + cacheReadPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2-thinking-turbo', + displayName: 'Kimi K2 Thinking Turbo', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 1.15, + outputPerM: 8, + cacheReadPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2-turbo-preview', + displayName: 'Kimi K2 Turbo', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 2.4, + outputPerM: 10, + cacheReadPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2.5', + displayName: 'Kimi K2.5', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.6, + outputPerM: 3, + cacheReadPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + default: true, + }, + ], + 'kimi-for-coding': [ + { + name: 'k2p5', + displayName: 'Kimi K2.5', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + default: true, + }, + { + name: 'kimi-k2-thinking', + displayName: 'Kimi K2 Thinking', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + openrouter: [ + { + name: 'allenai/molmo-2-8b:free', + displayName: 'Molmo2 8B (free)', + maxInputTokens: 36864, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-3.5-haiku', + displayName: 'Claude Haiku 3.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0.8, + outputPerM: 4, + cacheReadPerM: 0.08, + cacheWritePerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-3.7-sonnet', + displayName: 'Claude Sonnet 3.7', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 15, + outputPerM: 75, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, + currency: 'USD', + unit: 'per_million_tokens', + }, }, { name: 'anthropic/claude-haiku-4.5', @@ -1907,6 +2897,20 @@ export const MODELS_BY_PROVIDER = { unit: 'per_million_tokens', }, }, + { + name: 'anthropic/claude-opus-4.6', + displayName: 'Claude Opus 4.6', + maxInputTokens: 1000000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, { name: 'anthropic/claude-sonnet-4', displayName: 'Claude Sonnet 4', @@ -1959,6 +2963,78 @@ export const MODELS_BY_PROVIDER = { unit: 'per_million_tokens', }, }, + { + name: 'black-forest-labs/flux.2-flex', + displayName: 'FLUX.2 Flex', + maxInputTokens: 67344, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'black-forest-labs/flux.2-klein-4b', + displayName: 'FLUX.2 Klein 4B', + maxInputTokens: 40960, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'black-forest-labs/flux.2-max', + displayName: 'FLUX.2 Max', + maxInputTokens: 46864, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'black-forest-labs/flux.2-pro', + displayName: 'FLUX.2 Pro', + maxInputTokens: 46864, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'bytedance-seed/seedream-4.5', + displayName: 'Seedream 4.5', + maxInputTokens: 4096, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'cognitivecomputations/dolphin-mistral-24b-venice-edition:free', + displayName: 'Uncensored (free)', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, { name: 'cognitivecomputations/dolphin3.0-mistral-24b', displayName: 'Dolphin3.0 Mistral 24B', @@ -2281,8 +3357,92 @@ export const MODELS_BY_PROVIDER = { }, }, { - name: 'google/gemma-2-9b-it:free', - displayName: 'Gemma 2 9B (free)', + name: 'google/gemma-2-9b-it', + displayName: 'Gemma 2 9B', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0.03, + outputPerM: 0.09, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-3-12b-it', + displayName: 'Gemma 3 12B', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.03, + outputPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-3-12b-it:free', + displayName: 'Gemma 3 12B (free)', + maxInputTokens: 32768, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-3-27b-it', + displayName: 'Gemma 3 27B', + maxInputTokens: 96000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.04, + outputPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-3-27b-it:free', + displayName: 'Gemma 3 27B (free)', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-3-4b-it', + displayName: 'Gemma 3 4B', + maxInputTokens: 96000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.01703, + outputPerM: 0.06815, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-3-4b-it:free', + displayName: 'Gemma 3 4B (free)', + maxInputTokens: 32768, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-3n-e2b-it:free', + displayName: 'Gemma 3n 2B (free)', maxInputTokens: 8192, supportedFileTypes: [], pricing: { @@ -2293,22 +3453,22 @@ export const MODELS_BY_PROVIDER = { }, }, { - name: 'google/gemma-3-12b-it', - displayName: 'Gemma 3 12B IT', - maxInputTokens: 96000, - supportedFileTypes: ['image'], + name: 'google/gemma-3n-e4b-it', + displayName: 'Gemma 3n 4B', + maxInputTokens: 32768, + supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.02, + outputPerM: 0.04, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'google/gemma-3-27b-it', - displayName: 'Gemma 3 27B IT', - maxInputTokens: 96000, - supportedFileTypes: ['image'], + name: 'google/gemma-3n-e4b-it:free', + displayName: 'Gemma 3n 4B (free)', + maxInputTokens: 8192, + supportedFileTypes: [], pricing: { inputPerM: 0, outputPerM: 0, @@ -2317,10 +3477,10 @@ export const MODELS_BY_PROVIDER = { }, }, { - name: 'google/gemma-3-27b-it:free', - displayName: 'Gemma 3 27B', - maxInputTokens: 131072, - supportedFileTypes: ['image'], + name: 'kwaipilot/kat-coder-pro:free', + displayName: 'Kat Coder Pro (free)', + maxInputTokens: 256000, + supportedFileTypes: [], pricing: { inputPerM: 0, outputPerM: 0, @@ -2329,10 +3489,10 @@ export const MODELS_BY_PROVIDER = { }, }, { - name: 'google/gemma-3n-e4b-it', - displayName: 'Gemma 3n E4B IT', - maxInputTokens: 8192, - supportedFileTypes: ['image', 'audio'], + name: 'liquid/lfm-2.5-1.2b-instruct:free', + displayName: 'LFM2.5-1.2B-Instruct (free)', + maxInputTokens: 131072, + supportedFileTypes: [], pricing: { inputPerM: 0, outputPerM: 0, @@ -2341,10 +3501,10 @@ export const MODELS_BY_PROVIDER = { }, }, { - name: 'google/gemma-3n-e4b-it:free', - displayName: 'Gemma 3n 4B (free)', - maxInputTokens: 8192, - supportedFileTypes: ['image', 'audio'], + name: 'liquid/lfm-2.5-1.2b-thinking:free', + displayName: 'LFM2.5-1.2B-Thinking (free)', + maxInputTokens: 131072, + supportedFileTypes: [], pricing: { inputPerM: 0, outputPerM: 0, @@ -2353,9 +3513,9 @@ export const MODELS_BY_PROVIDER = { }, }, { - name: 'kwaipilot/kat-coder-pro:free', - displayName: 'Kat Coder Pro (free)', - maxInputTokens: 256000, + name: 'meta-llama/llama-3.1-405b-instruct:free', + displayName: 'Llama 3.1 405B Instruct (free)', + maxInputTokens: 131072, supportedFileTypes: [], pricing: { inputPerM: 0, @@ -2376,10 +3536,22 @@ export const MODELS_BY_PROVIDER = { unit: 'per_million_tokens', }, }, + { + name: 'meta-llama/llama-3.2-3b-instruct:free', + displayName: 'Llama 3.2 3B Instruct (free)', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, { name: 'meta-llama/llama-3.3-70b-instruct:free', displayName: 'Llama 3.3 70B Instruct (free)', - maxInputTokens: 65536, + maxInputTokens: 131072, supportedFileTypes: [], pricing: { inputPerM: 0, @@ -2462,6 +3634,19 @@ export const MODELS_BY_PROVIDER = { unit: 'per_million_tokens', }, }, + { + name: 'minimax/minimax-m2.5', + displayName: 'MiniMax M2.5', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + cacheReadPerM: 0.03, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, { name: 'mistralai/codestral-2508', displayName: 'Codestral 2508', @@ -2728,6 +3913,18 @@ export const MODELS_BY_PROVIDER = { unit: 'per_million_tokens', }, }, + { + name: 'nousresearch/hermes-3-llama-3.1-405b:free', + displayName: 'Hermes 3 405B Instruct (free)', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, { name: 'nousresearch/hermes-4-405b', displayName: 'Hermes 4 405B', @@ -2752,6 +3949,30 @@ export const MODELS_BY_PROVIDER = { unit: 'per_million_tokens', }, }, + { + name: 'nvidia/nemotron-3-nano-30b-a3b:free', + displayName: 'Nemotron 3 Nano 30B A3B (free)', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nvidia/nemotron-nano-12b-v2-vl:free', + displayName: 'Nemotron Nano 12B 2 VL (free)', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, { name: 'nvidia/nemotron-nano-9b-v2', displayName: 'nvidia-nemotron-nano-9b-v2', @@ -2764,6 +3985,18 @@ export const MODELS_BY_PROVIDER = { unit: 'per_million_tokens', }, }, + { + name: 'nvidia/nemotron-nano-9b-v2:free', + displayName: 'Nemotron Nano 9B V2 (free)', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, { name: 'openai/gpt-4.1', displayName: 'GPT-4.1', @@ -2968,7 +4201,7 @@ export const MODELS_BY_PROVIDER = { }, }, { - name: 'openai/gpt-5.2-chat-latest', + name: 'openai/gpt-5.2-chat', displayName: 'GPT-5.2 Chat', maxInputTokens: 128000, supportedFileTypes: ['image'], @@ -3029,6 +4262,18 @@ export const MODELS_BY_PROVIDER = { unit: 'per_million_tokens', }, }, + { + name: 'openai/gpt-oss-120b:free', + displayName: 'gpt-oss-120b (free)', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, { name: 'openai/gpt-oss-20b', displayName: 'GPT OSS 20B', @@ -3041,6 +4286,18 @@ export const MODELS_BY_PROVIDER = { unit: 'per_million_tokens', }, }, + { + name: 'openai/gpt-oss-20b:free', + displayName: 'gpt-oss-20b (free)', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, { name: 'openai/gpt-oss-safeguard-20b', displayName: 'GPT OSS Safeguard 20B', @@ -3066,6 +4323,18 @@ export const MODELS_BY_PROVIDER = { unit: 'per_million_tokens', }, }, + { + name: 'openrouter/aurora-alpha', + displayName: 'Aurora Alpha', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, { name: 'openrouter/sherlock-dash-alpha', displayName: 'Sherlock Dash Alpha', @@ -3090,6 +4359,18 @@ export const MODELS_BY_PROVIDER = { unit: 'per_million_tokens', }, }, + { + name: 'prime-intellect/intellect-3', + displayName: 'Intellect 3', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 1.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, { name: 'qwen/qwen-2.5-coder-32b-instruct', displayName: 'Qwen2.5 Coder 32B Instruct', @@ -3102,6 +4383,18 @@ export const MODELS_BY_PROVIDER = { unit: 'per_million_tokens', }, }, + { + name: 'qwen/qwen-2.5-vl-7b-instruct:free', + displayName: 'Qwen2.5-VL 7B Instruct (free)', + maxInputTokens: 32768, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, { name: 'qwen/qwen2.5-vl-32b-instruct:free', displayName: 'Qwen2.5 VL 32B Instruct (free)', @@ -3246,6 +4539,18 @@ export const MODELS_BY_PROVIDER = { unit: 'per_million_tokens', }, }, + { + name: 'qwen/qwen3-4b:free', + displayName: 'Qwen3 4B (free)', + maxInputTokens: 40960, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, { name: 'qwen/qwen3-8b:free', displayName: 'Qwen3 8B (free)', @@ -3342,6 +4647,18 @@ export const MODELS_BY_PROVIDER = { unit: 'per_million_tokens', }, }, + { + name: 'qwen/qwen3-next-80b-a3b-instruct:free', + displayName: 'Qwen3 Next 80B A3B Instruct (free)', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, { name: 'qwen/qwen3-next-80b-a3b-thinking', displayName: 'Qwen3 Next 80B A3B Thinking', @@ -3355,21 +4672,118 @@ export const MODELS_BY_PROVIDER = { }, }, { - name: 'qwen/qwq-32b:free', - displayName: 'QwQ 32B (free)', - maxInputTokens: 32768, + name: 'qwen/qwen3.5-397b-a17b', + displayName: 'Qwen3.5 397B A17B', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.6, + outputPerM: 3.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3.5-plus-02-15', + displayName: 'Qwen3.5 Plus 2026-02-15', + maxInputTokens: 1000000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.4, + outputPerM: 2.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwq-32b:free', + displayName: 'QwQ 32B (free)', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'rekaai/reka-flash-3', + displayName: 'Reka Flash 3', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'sarvamai/sarvam-m:free', + displayName: 'Sarvam-M (free)', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'sourceful/riverflow-v2-fast-preview', + displayName: 'Riverflow V2 Fast Preview', + maxInputTokens: 8192, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'sourceful/riverflow-v2-max-preview', + displayName: 'Riverflow V2 Max Preview', + maxInputTokens: 8192, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'sourceful/riverflow-v2-standard-preview', + displayName: 'Riverflow V2 Standard Preview', + maxInputTokens: 8192, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'stepfun/step-3.5-flash', + displayName: 'Step 3.5 Flash', + maxInputTokens: 256000, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.1, + outputPerM: 0.3, + cacheReadPerM: 0.02, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'rekaai/reka-flash-3', - displayName: 'Reka Flash 3', - maxInputTokens: 32768, + name: 'stepfun/step-3.5-flash:free', + displayName: 'Step 3.5 Flash (free)', + maxInputTokens: 256000, supportedFileTypes: [], pricing: { inputPerM: 0, @@ -3379,8 +4793,8 @@ export const MODELS_BY_PROVIDER = { }, }, { - name: 'sarvamai/sarvam-m:free', - displayName: 'Sarvam-M (free)', + name: 'thudm/glm-z1-32b:free', + displayName: 'GLM Z1 32B (free)', maxInputTokens: 32768, supportedFileTypes: [], pricing: { @@ -3391,9 +4805,9 @@ export const MODELS_BY_PROVIDER = { }, }, { - name: 'thudm/glm-z1-32b:free', - displayName: 'GLM Z1 32B (free)', - maxInputTokens: 32768, + name: 'tngtech/deepseek-r1t2-chimera:free', + displayName: 'DeepSeek R1T2 Chimera (free)', + maxInputTokens: 163840, supportedFileTypes: [], pricing: { inputPerM: 0, @@ -3403,8 +4817,8 @@ export const MODELS_BY_PROVIDER = { }, }, { - name: 'tngtech/deepseek-r1t2-chimera:free', - displayName: 'DeepSeek R1T2 Chimera (free)', + name: 'tngtech/tng-r1t-chimera:free', + displayName: 'R1T Chimera (free)', maxInputTokens: 163840, supportedFileTypes: [], pricing: { @@ -3525,6 +4939,19 @@ export const MODELS_BY_PROVIDER = { unit: 'per_million_tokens', }, }, + { + name: 'xiaomi/mimo-v2-flash', + displayName: 'MiMo-V2-Flash', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.3, + cacheReadPerM: 0.01, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, { name: 'z-ai/glm-4.5', displayName: 'GLM 4.5', @@ -3612,6 +5039,31 @@ export const MODELS_BY_PROVIDER = { unit: 'per_million_tokens', }, }, + { + name: 'z-ai/glm-4.7-flash', + displayName: 'GLM-4.7-Flash', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.07, + outputPerM: 0.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'z-ai/glm-5', + displayName: 'GLM-5', + maxInputTokens: 202752, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 3.2, + cacheReadPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, ], litellm: [], glama: [], @@ -3700,6 +5152,20 @@ export const MODELS_BY_PROVIDER = { unit: 'per_million_tokens', }, }, + { + name: 'claude-opus-4-6@default', + displayName: 'Claude Opus 4.6', + maxInputTokens: 1000000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, { name: 'claude-opus-4@20250514', displayName: 'Claude Opus 4', @@ -3728,6 +5194,20 @@ export const MODELS_BY_PROVIDER = { unit: 'per_million_tokens', }, }, + { + name: 'claude-sonnet-4-6@default', + displayName: 'Claude Sonnet 4.6', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, { name: 'claude-sonnet-4@20250514', displayName: 'Claude Sonnet 4', @@ -4001,6 +5481,19 @@ export const MODELS_BY_PROVIDER = { unit: 'per_million_tokens', }, }, + { + name: 'zai-org/glm-5-maas', + displayName: 'GLM-5', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 3.2, + cacheReadPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, ], bedrock: [ { @@ -4274,6 +5767,20 @@ export const MODELS_BY_PROVIDER = { unit: 'per_million_tokens', }, }, + { + name: 'anthropic.claude-opus-4-6-v1', + displayName: 'Claude Opus 4.6', + maxInputTokens: 1000000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, { name: 'anthropic.claude-sonnet-4-20250514-v1:0', displayName: 'Claude Sonnet 4', @@ -4303,6 +5810,20 @@ export const MODELS_BY_PROVIDER = { }, default: true, }, + { + name: 'anthropic.claude-sonnet-4-6', + displayName: 'Claude Sonnet 4.6', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, { name: 'anthropic.claude-v2', displayName: 'Claude 2', @@ -4316,99 +5837,265 @@ export const MODELS_BY_PROVIDER = { }, }, { - name: 'anthropic.claude-v2:1', - displayName: 'Claude 2.1', + name: 'anthropic.claude-v2:1', + displayName: 'Claude 2.1', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 8, + outputPerM: 24, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'cohere.command-light-text-v14', + displayName: 'Command Light', + maxInputTokens: 4096, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'cohere.command-r-plus-v1:0', + displayName: 'Command R+', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 3, + outputPerM: 15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'cohere.command-r-v1:0', + displayName: 'Command R', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.5, + outputPerM: 1.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'cohere.command-text-v14', + displayName: 'Command', + maxInputTokens: 4096, + supportedFileTypes: [], + pricing: { + inputPerM: 1.5, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek.r1-v1:0', + displayName: 'DeepSeek-R1', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 1.35, + outputPerM: 5.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek.v3-v1:0', + displayName: 'DeepSeek-V3.1', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.58, + outputPerM: 1.68, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek.v3.2-v1:0', + displayName: 'DeepSeek-V3.2', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.62, + outputPerM: 1.85, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'eu.anthropic.claude-haiku-4-5-20251001-v1:0', + displayName: 'Claude Haiku 4.5 (EU)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1, + outputPerM: 5, + cacheReadPerM: 0.1, + cacheWritePerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'eu.anthropic.claude-opus-4-5-20251101-v1:0', + displayName: 'Claude Opus 4.5 (EU)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'eu.anthropic.claude-opus-4-6-v1', + displayName: 'Claude Opus 4.6 (EU)', + maxInputTokens: 1000000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'eu.anthropic.claude-sonnet-4-20250514-v1:0', + displayName: 'Claude Sonnet 4 (EU)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'eu.anthropic.claude-sonnet-4-5-20250929-v1:0', + displayName: 'Claude Sonnet 4.5 (EU)', maxInputTokens: 200000, - supportedFileTypes: [], + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 8, - outputPerM: 24, + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'cohere.command-light-text-v14', - displayName: 'Command Light', - maxInputTokens: 4096, - supportedFileTypes: [], + name: 'eu.anthropic.claude-sonnet-4-6', + displayName: 'Claude Sonnet 4.6 (EU)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0.3, - outputPerM: 0.6, + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'cohere.command-r-plus-v1:0', - displayName: 'Command R+', - maxInputTokens: 128000, - supportedFileTypes: [], + name: 'global.anthropic.claude-haiku-4-5-20251001-v1:0', + displayName: 'Claude Haiku 4.5 (Global)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 3, - outputPerM: 15, + inputPerM: 1, + outputPerM: 5, + cacheReadPerM: 0.1, + cacheWritePerM: 1.25, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'cohere.command-r-v1:0', - displayName: 'Command R', - maxInputTokens: 128000, - supportedFileTypes: [], + name: 'global.anthropic.claude-opus-4-5-20251101-v1:0', + displayName: 'Claude Opus 4.5 (Global)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0.5, - outputPerM: 1.5, + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'cohere.command-text-v14', - displayName: 'Command', - maxInputTokens: 4096, - supportedFileTypes: [], + name: 'global.anthropic.claude-opus-4-6-v1', + displayName: 'Claude Opus 4.6 (Global)', + maxInputTokens: 1000000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 1.5, - outputPerM: 2, + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'deepseek.r1-v1:0', - displayName: 'DeepSeek-R1', - maxInputTokens: 128000, - supportedFileTypes: [], + name: 'global.anthropic.claude-sonnet-4-20250514-v1:0', + displayName: 'Claude Sonnet 4 (Global)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 1.35, - outputPerM: 5.4, + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'deepseek.v3-v1:0', - displayName: 'DeepSeek-V3.1', - maxInputTokens: 163840, - supportedFileTypes: [], + name: 'global.anthropic.claude-sonnet-4-5-20250929-v1:0', + displayName: 'Claude Sonnet 4.5 (Global)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0.58, - outputPerM: 1.68, + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'global.anthropic.claude-opus-4-5-20251101-v1:0', - displayName: 'Claude Opus 4.5 (Global)', + name: 'global.anthropic.claude-sonnet-4-6', + displayName: 'Claude Sonnet 4.6 (Global)', maxInputTokens: 200000, supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 5, - outputPerM: 25, - cacheReadPerM: 0.5, - cacheWritePerM: 6.25, + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, currency: 'USD', unit: 'per_million_tokens', }, @@ -4593,6 +6280,18 @@ export const MODELS_BY_PROVIDER = { unit: 'per_million_tokens', }, }, + { + name: 'minimax.minimax-m2.1', + displayName: 'MiniMax M2.1', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, { name: 'mistral.ministral-3-14b-instruct', displayName: 'Ministral 14B 3.0', @@ -4689,6 +6388,18 @@ export const MODELS_BY_PROVIDER = { unit: 'per_million_tokens', }, }, + { + name: 'moonshotai.kimi-k2.5', + displayName: 'Kimi K2.5', + maxInputTokens: 256000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.6, + outputPerM: 3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, { name: 'nvidia.nemotron-nano-12b-v2', displayName: 'NVIDIA Nemotron Nano 12B v2 VL BF16', @@ -4833,6 +6544,166 @@ export const MODELS_BY_PROVIDER = { unit: 'per_million_tokens', }, }, + { + name: 'us.anthropic.claude-haiku-4-5-20251001-v1:0', + displayName: 'Claude Haiku 4.5 (US)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1, + outputPerM: 5, + cacheReadPerM: 0.1, + cacheWritePerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'us.anthropic.claude-opus-4-1-20250805-v1:0', + displayName: 'Claude Opus 4.1 (US)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 15, + outputPerM: 75, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'us.anthropic.claude-opus-4-20250514-v1:0', + displayName: 'Claude Opus 4 (US)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 15, + outputPerM: 75, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'us.anthropic.claude-opus-4-5-20251101-v1:0', + displayName: 'Claude Opus 4.5 (US)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'us.anthropic.claude-opus-4-6-v1', + displayName: 'Claude Opus 4.6 (US)', + maxInputTokens: 1000000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'us.anthropic.claude-sonnet-4-20250514-v1:0', + displayName: 'Claude Sonnet 4 (US)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'us.anthropic.claude-sonnet-4-5-20250929-v1:0', + displayName: 'Claude Sonnet 4.5 (US)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'us.anthropic.claude-sonnet-4-6', + displayName: 'Claude Sonnet 4.6 (US)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'writer.palmyra-x4-v1:0', + displayName: 'Palmyra X4', + maxInputTokens: 122880, + supportedFileTypes: [], + pricing: { + inputPerM: 2.5, + outputPerM: 10, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'writer.palmyra-x5-v1:0', + displayName: 'Palmyra X5', + maxInputTokens: 1040000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai.glm-4.7', + displayName: 'GLM-4.7', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai.glm-4.7-flash', + displayName: 'GLM-4.7-Flash', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.07, + outputPerM: 0.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, ], local: [], ollama: [], diff --git a/packages/core/src/llm/registry/sync.ts b/packages/core/src/llm/registry/sync.ts index d799d909f..4a398b0e3 100644 --- a/packages/core/src/llm/registry/sync.ts +++ b/packages/core/src/llm/registry/sync.ts @@ -272,7 +272,17 @@ export function buildModelsByProviderFromParsedSources(params: { xai: 'grok-4', cohere: 'command-a-03-2025', minimax: 'MiniMax-M2.1', + 'minimax-cn': 'MiniMax-M2.1', + 'minimax-coding-plan': 'MiniMax-M2.1', + 'minimax-cn-coding-plan': 'MiniMax-M2.1', glm: 'glm-4.7', + zhipuai: 'glm-4.7', + 'zhipuai-coding-plan': 'glm-4.7', + zai: 'glm-4.7', + 'zai-coding-plan': 'glm-4.7', + moonshotai: 'kimi-k2.5', + 'moonshotai-cn': 'kimi-k2.5', + 'kimi-for-coding': 'k2p5', vertex: 'gemini-3-flash-preview', bedrock: 'anthropic.claude-sonnet-4-5-20250929-v1:0', }; @@ -285,7 +295,17 @@ export function buildModelsByProviderFromParsedSources(params: { xai: (id: string) => id.startsWith('grok-'), cohere: (id: string) => id.startsWith('command-'), minimax: (_id: string) => true, + 'minimax-cn': (_id: string) => true, + 'minimax-coding-plan': (_id: string) => true, + 'minimax-cn-coding-plan': (_id: string) => true, glm: (id: string) => id.startsWith('glm-'), + zhipuai: (id: string) => id.startsWith('glm-'), + 'zhipuai-coding-plan': (id: string) => id.startsWith('glm-'), + zai: (id: string) => id.startsWith('glm-'), + 'zai-coding-plan': (id: string) => id.startsWith('glm-'), + moonshotai: (_id: string) => true, + 'moonshotai-cn': (_id: string) => true, + 'kimi-for-coding': (_id: string) => true, vertex: (_id: string) => true, bedrock: (_id: string) => true, openrouter: (_id: string) => true, @@ -356,6 +376,37 @@ export function buildModelsByProviderFromParsedSources(params: { }, modelsDevApi, }), + 'minimax-cn': buildModelsFromModelsDevProvider({ + spec: { + provider: 'minimax-cn', + modelsDevProviderId: 'minimax-cn', + ...(defaults['minimax-cn'] ? { defaultModelId: defaults['minimax-cn'] } : {}), + includeModelId: include['minimax-cn'], + }, + modelsDevApi, + }), + 'minimax-coding-plan': buildModelsFromModelsDevProvider({ + spec: { + provider: 'minimax-coding-plan', + modelsDevProviderId: 'minimax-coding-plan', + ...(defaults['minimax-coding-plan'] + ? { defaultModelId: defaults['minimax-coding-plan'] } + : {}), + includeModelId: include['minimax-coding-plan'], + }, + modelsDevApi, + }), + 'minimax-cn-coding-plan': buildModelsFromModelsDevProvider({ + spec: { + provider: 'minimax-cn-coding-plan', + modelsDevProviderId: 'minimax-cn-coding-plan', + ...(defaults['minimax-cn-coding-plan'] + ? { defaultModelId: defaults['minimax-cn-coding-plan'] } + : {}), + includeModelId: include['minimax-cn-coding-plan'], + }, + modelsDevApi, + }), glm: buildModelsFromModelsDevProvider({ spec: { provider: 'glm', @@ -365,6 +416,75 @@ export function buildModelsByProviderFromParsedSources(params: { }, modelsDevApi, }), + zhipuai: buildModelsFromModelsDevProvider({ + spec: { + provider: 'zhipuai', + modelsDevProviderId: 'zhipuai', + ...(defaults.zhipuai ? { defaultModelId: defaults.zhipuai } : {}), + includeModelId: include.zhipuai, + }, + modelsDevApi, + }), + 'zhipuai-coding-plan': buildModelsFromModelsDevProvider({ + spec: { + provider: 'zhipuai-coding-plan', + modelsDevProviderId: 'zhipuai-coding-plan', + ...(defaults['zhipuai-coding-plan'] + ? { defaultModelId: defaults['zhipuai-coding-plan'] } + : {}), + includeModelId: include['zhipuai-coding-plan'], + }, + modelsDevApi, + }), + zai: buildModelsFromModelsDevProvider({ + spec: { + provider: 'zai', + modelsDevProviderId: 'zai', + ...(defaults.zai ? { defaultModelId: defaults.zai } : {}), + includeModelId: include.zai, + }, + modelsDevApi, + }), + 'zai-coding-plan': buildModelsFromModelsDevProvider({ + spec: { + provider: 'zai-coding-plan', + modelsDevProviderId: 'zai-coding-plan', + ...(defaults['zai-coding-plan'] + ? { defaultModelId: defaults['zai-coding-plan'] } + : {}), + includeModelId: include['zai-coding-plan'], + }, + modelsDevApi, + }), + moonshotai: buildModelsFromModelsDevProvider({ + spec: { + provider: 'moonshotai', + modelsDevProviderId: 'moonshotai', + ...(defaults.moonshotai ? { defaultModelId: defaults.moonshotai } : {}), + includeModelId: include.moonshotai, + }, + modelsDevApi, + }), + 'moonshotai-cn': buildModelsFromModelsDevProvider({ + spec: { + provider: 'moonshotai-cn', + modelsDevProviderId: 'moonshotai-cn', + ...(defaults['moonshotai-cn'] ? { defaultModelId: defaults['moonshotai-cn'] } : {}), + includeModelId: include['moonshotai-cn'], + }, + modelsDevApi, + }), + 'kimi-for-coding': buildModelsFromModelsDevProvider({ + spec: { + provider: 'kimi-for-coding', + modelsDevProviderId: 'kimi-for-coding', + ...(defaults['kimi-for-coding'] + ? { defaultModelId: defaults['kimi-for-coding'] } + : {}), + includeModelId: include['kimi-for-coding'], + }, + modelsDevApi, + }), openrouter: buildModelsFromModelsDevProvider({ spec: { provider: 'openrouter', diff --git a/packages/core/src/llm/services/factory.ts b/packages/core/src/llm/services/factory.ts index a4bdef0c8..a2728fc0c 100644 --- a/packages/core/src/llm/services/factory.ts +++ b/packages/core/src/llm/services/factory.ts @@ -19,6 +19,7 @@ import type { SystemPromptManager } from '../../systemPrompt/manager.js'; import type { Logger } from '../../logger/v2/types.js'; import { requiresApiKey } from '../registry/index.js'; import { getPrimaryApiKeyEnvVar, resolveApiKeyForProvider } from '../../utils/api-key-resolver.js'; +import type { LlmAuthResolver } from '../auth/types.js'; // Dexto Gateway headers for usage tracking const DEXTO_GATEWAY_HEADERS = { @@ -35,6 +36,8 @@ export interface DextoProviderContext { sessionId?: string; /** Client source for usage attribution (cli, web, sdk) */ clientSource?: 'cli' | 'web' | 'sdk'; + /** Optional runtime auth resolver (profiles, OAuth, etc.) */ + authResolver?: LlmAuthResolver | null; } /** @@ -52,7 +55,11 @@ export function createVercelModel( context?: DextoProviderContext ): LanguageModel { const { provider, model, baseURL } = llmConfig; - const apiKey = llmConfig.apiKey || resolveApiKeyForProvider(provider); + const runtimeAuth = context?.authResolver?.resolveRuntimeAuth({ provider, model }) ?? null; + const apiKey = llmConfig.apiKey || runtimeAuth?.apiKey || resolveApiKeyForProvider(provider); + const extraHeaders = runtimeAuth?.headers; + const runtimeFetch = runtimeAuth?.fetch; + const runtimeBaseURL = runtimeAuth?.baseURL; // Runtime check: if provider requires API key but none is configured, fail with helpful message if (requiresApiKey(provider) && !apiKey?.trim()) { @@ -64,34 +71,151 @@ export function createVercelModel( case 'openai': { // Regular OpenAI - strict compatibility, no baseURL // Explicitly use the Responses API (default in AI SDK 5+). - return createOpenAI({ apiKey: apiKey ?? '' }).responses(model); + return createOpenAI({ + apiKey: apiKey ?? '', + ...(runtimeBaseURL ? { baseURL: runtimeBaseURL } : {}), + ...(extraHeaders ? { headers: extraHeaders } : {}), + ...(runtimeFetch ? { fetch: runtimeFetch } : {}), + }).responses(model); } case 'openai-compatible': { // OpenAI-compatible - requires baseURL, uses chat completions endpoint // Must use .chat() as most compatible endpoints (like Ollama) don't support Responses API const compatibleBaseURL = - baseURL?.replace(/\/$/, '') || process.env.OPENAI_BASE_URL?.replace(/\/$/, ''); + baseURL?.replace(/\/$/, '') || + runtimeBaseURL?.replace(/\/$/, '') || + process.env.OPENAI_BASE_URL?.replace(/\/$/, ''); if (!compatibleBaseURL) { throw LLMError.baseUrlMissing('openai-compatible'); } - return createOpenAI({ apiKey: apiKey ?? '', baseURL: compatibleBaseURL }).chat(model); + return createOpenAI({ + apiKey: apiKey ?? '', + baseURL: compatibleBaseURL, + ...(extraHeaders ? { headers: extraHeaders } : {}), + ...(runtimeFetch ? { fetch: runtimeFetch } : {}), + }).chat(model); } case 'openrouter': { // OpenRouter - unified API gateway for 100+ models (BYOK) // Model IDs are in OpenRouter format (e.g., 'anthropic/claude-sonnet-4-5-20250929') const orBaseURL = baseURL || 'https://openrouter.ai/api/v1'; // Use Responses API (OpenAI-compatible) via /api/v1/responses - return createOpenAI({ apiKey: apiKey ?? '', baseURL: orBaseURL }).responses(model); + return createOpenAI({ + apiKey: apiKey ?? '', + baseURL: orBaseURL, + ...(extraHeaders ? { headers: extraHeaders } : {}), + ...(runtimeFetch ? { fetch: runtimeFetch } : {}), + }).responses(model); } case 'minimax': { - // MiniMax - OpenAI-compatible endpoint - const minimaxBaseURL = baseURL || 'https://api.minimax.chat/v1'; - return createOpenAI({ apiKey: apiKey ?? '', baseURL: minimaxBaseURL }).chat(model); + // MiniMax - Anthropic-compatible endpoint (models.dev): https://api.minimax.io/anthropic/v1 + const minimaxBaseURL = runtimeBaseURL || 'https://api.minimax.io/anthropic/v1'; + return createAnthropic({ + apiKey: apiKey ?? '', + baseURL: minimaxBaseURL, + ...(extraHeaders ? { headers: extraHeaders } : {}), + ...(runtimeFetch ? { fetch: runtimeFetch } : {}), + })(model); + } + case 'minimax-cn': { + const minimaxBaseURL = runtimeBaseURL || 'https://api.minimaxi.com/anthropic/v1'; + return createAnthropic({ + apiKey: apiKey ?? '', + baseURL: minimaxBaseURL, + ...(extraHeaders ? { headers: extraHeaders } : {}), + ...(runtimeFetch ? { fetch: runtimeFetch } : {}), + })(model); + } + case 'minimax-coding-plan': { + const minimaxBaseURL = runtimeBaseURL || 'https://api.minimax.io/anthropic/v1'; + return createAnthropic({ + apiKey: apiKey ?? '', + baseURL: minimaxBaseURL, + ...(extraHeaders ? { headers: extraHeaders } : {}), + ...(runtimeFetch ? { fetch: runtimeFetch } : {}), + })(model); + } + case 'minimax-cn-coding-plan': { + const minimaxBaseURL = runtimeBaseURL || 'https://api.minimaxi.com/anthropic/v1'; + return createAnthropic({ + apiKey: apiKey ?? '', + baseURL: minimaxBaseURL, + ...(extraHeaders ? { headers: extraHeaders } : {}), + ...(runtimeFetch ? { fetch: runtimeFetch } : {}), + })(model); } case 'glm': { // Zhipu AI (GLM) - OpenAI-compatible endpoint const glmBaseURL = baseURL || 'https://open.bigmodel.cn/api/paas/v4'; - return createOpenAI({ apiKey: apiKey ?? '', baseURL: glmBaseURL }).chat(model); + return createOpenAI({ + apiKey: apiKey ?? '', + baseURL: glmBaseURL, + ...(extraHeaders ? { headers: extraHeaders } : {}), + ...(runtimeFetch ? { fetch: runtimeFetch } : {}), + }).chat(model); + } + case 'zhipuai': { + const zhipuBaseURL = baseURL || 'https://open.bigmodel.cn/api/paas/v4'; + return createOpenAI({ + apiKey: apiKey ?? '', + baseURL: zhipuBaseURL, + ...(extraHeaders ? { headers: extraHeaders } : {}), + ...(runtimeFetch ? { fetch: runtimeFetch } : {}), + }).chat(model); + } + case 'zhipuai-coding-plan': { + const zhipuBaseURL = baseURL || 'https://open.bigmodel.cn/api/coding/paas/v4'; + return createOpenAI({ + apiKey: apiKey ?? '', + baseURL: zhipuBaseURL, + ...(extraHeaders ? { headers: extraHeaders } : {}), + ...(runtimeFetch ? { fetch: runtimeFetch } : {}), + }).chat(model); + } + case 'zai': { + const zaiBaseURL = baseURL || 'https://api.z.ai/api/paas/v4'; + return createOpenAI({ + apiKey: apiKey ?? '', + baseURL: zaiBaseURL, + ...(extraHeaders ? { headers: extraHeaders } : {}), + ...(runtimeFetch ? { fetch: runtimeFetch } : {}), + }).chat(model); + } + case 'zai-coding-plan': { + const zaiBaseURL = baseURL || 'https://api.z.ai/api/coding/paas/v4'; + return createOpenAI({ + apiKey: apiKey ?? '', + baseURL: zaiBaseURL, + ...(extraHeaders ? { headers: extraHeaders } : {}), + ...(runtimeFetch ? { fetch: runtimeFetch } : {}), + }).chat(model); + } + case 'moonshotai': { + const moonshotBaseURL = baseURL || 'https://api.moonshot.ai/v1'; + return createOpenAI({ + apiKey: apiKey ?? '', + baseURL: moonshotBaseURL, + ...(extraHeaders ? { headers: extraHeaders } : {}), + ...(runtimeFetch ? { fetch: runtimeFetch } : {}), + }).chat(model); + } + case 'moonshotai-cn': { + const moonshotBaseURL = baseURL || 'https://api.moonshot.cn/v1'; + return createOpenAI({ + apiKey: apiKey ?? '', + baseURL: moonshotBaseURL, + ...(extraHeaders ? { headers: extraHeaders } : {}), + ...(runtimeFetch ? { fetch: runtimeFetch } : {}), + }).chat(model); + } + case 'kimi-for-coding': { + const kimiBaseURL = runtimeBaseURL || 'https://api.kimi.com/coding/v1'; + return createAnthropic({ + apiKey: apiKey ?? '', + baseURL: kimiBaseURL, + ...(extraHeaders ? { headers: extraHeaders } : {}), + ...(runtimeFetch ? { fetch: runtimeFetch } : {}), + })(model); } case 'litellm': { // LiteLLM - OpenAI-compatible proxy for 100+ LLM providers @@ -99,13 +223,23 @@ export function createVercelModel( if (!baseURL) { throw LLMError.baseUrlMissing('litellm'); } - return createOpenAI({ apiKey: apiKey ?? '', baseURL }).chat(model); + return createOpenAI({ + apiKey: apiKey ?? '', + baseURL, + ...(extraHeaders ? { headers: extraHeaders } : {}), + ...(runtimeFetch ? { fetch: runtimeFetch } : {}), + }).chat(model); } case 'glama': { // Glama - OpenAI-compatible gateway for multiple LLM providers // Fixed endpoint, no user configuration needed const glamaBaseURL = 'https://glama.ai/api/gateway/openai/v1'; - return createOpenAI({ apiKey: apiKey ?? '', baseURL: glamaBaseURL }).chat(model); + return createOpenAI({ + apiKey: apiKey ?? '', + baseURL: glamaBaseURL, + ...(extraHeaders ? { headers: extraHeaders } : {}), + ...(runtimeFetch ? { fetch: runtimeFetch } : {}), + }).chat(model); } case 'dexto-nova': { // Dexto Gateway - OpenAI-compatible proxy with per-request billing @@ -120,6 +254,7 @@ export function createVercelModel( // Build headers for usage tracking const headers: Record<string, string> = { + ...(extraHeaders ? extraHeaders : {}), [DEXTO_GATEWAY_HEADERS.CLIENT_SOURCE]: context?.clientSource ?? 'cli', }; if (context?.sessionId) { @@ -130,9 +265,12 @@ export function createVercelModel( } // Model is already in OpenRouter format - pass through directly - return createOpenAI({ apiKey: apiKey ?? '', baseURL: dextoBaseURL, headers }).chat( - model - ); + return createOpenAI({ + apiKey: apiKey ?? '', + baseURL: dextoBaseURL, + headers, + ...(runtimeFetch ? { fetch: runtimeFetch } : {}), + }).chat(model); } case 'vertex': { // Google Vertex AI - supports both Gemini and Claude models @@ -203,7 +341,12 @@ export function createVercelModel( return createAmazonBedrock({ region })(modelId); } case 'anthropic': - return createAnthropic({ apiKey: apiKey ?? '' })(model); + return createAnthropic({ + apiKey: apiKey ?? '', + ...(runtimeBaseURL ? { baseURL: runtimeBaseURL } : {}), + ...(extraHeaders ? { headers: extraHeaders } : {}), + ...(runtimeFetch ? { fetch: runtimeFetch } : {}), + })(model); case 'google': return createGoogleGenerativeAI({ apiKey: apiKey ?? '' })(model); case 'groq': @@ -218,7 +361,12 @@ export function createVercelModel( // Default URL: http://localhost:11434 const ollamaBaseURL = baseURL || 'http://localhost:11434/v1'; // Ollama doesn't require an API key, but the SDK needs a non-empty string - return createOpenAI({ apiKey: 'ollama', baseURL: ollamaBaseURL }).chat(model); + return createOpenAI({ + apiKey: 'ollama', + baseURL: ollamaBaseURL, + ...(extraHeaders ? { headers: extraHeaders } : {}), + ...(runtimeFetch ? { fetch: runtimeFetch } : {}), + }).chat(model); } case 'local': { // Native node-llama-cpp execution via AI SDK adapter. @@ -257,9 +405,10 @@ export function createLLMService( sessionId: string, resourceManager: import('../../resources/index.js').ResourceManager, logger: Logger, - compactionStrategy?: import('../../context/compaction/types.js').CompactionStrategy | null + compactionStrategy?: import('../../context/compaction/types.js').CompactionStrategy | null, + authResolver?: LlmAuthResolver | null ): VercelLLMService { - const model = createVercelModel(config, { sessionId }); + const model = createVercelModel(config, { sessionId, authResolver: authResolver ?? null }); return new VercelLLMService( toolManager, diff --git a/packages/core/src/llm/services/test-utils.integration.ts b/packages/core/src/llm/services/test-utils.integration.ts index 3f0651d58..253da353c 100644 --- a/packages/core/src/llm/services/test-utils.integration.ts +++ b/packages/core/src/llm/services/test-utils.integration.ts @@ -188,7 +188,17 @@ export const TestConfigs = { xai: 'grok-beta', cohere: 'command-r', minimax: 'MiniMax-M2.1', + 'minimax-cn': 'MiniMax-M2.1', + 'minimax-coding-plan': 'MiniMax-M2.1', + 'minimax-cn-coding-plan': 'MiniMax-M2.1', glm: 'glm-4.7', + zhipuai: 'glm-4.7', + 'zhipuai-coding-plan': 'glm-4.7', + zai: 'glm-4.7', + 'zai-coding-plan': 'glm-4.7', + moonshotai: 'kimi-k2.5', + 'moonshotai-cn': 'kimi-k2.5', + 'kimi-for-coding': 'k2p5', 'openai-compatible': 'gpt-5-mini', openrouter: 'anthropic/claude-3.5-haiku', // OpenRouter model format: provider/model litellm: 'gpt-4', // LiteLLM model names follow the provider's convention diff --git a/packages/core/src/llm/types.ts b/packages/core/src/llm/types.ts index 55e7e9fb1..58aa83b1b 100644 --- a/packages/core/src/llm/types.ts +++ b/packages/core/src/llm/types.ts @@ -8,7 +8,17 @@ export const LLM_PROVIDERS = [ 'xai', 'cohere', 'minimax', + 'minimax-cn', + 'minimax-coding-plan', + 'minimax-cn-coding-plan', 'glm', + 'zhipuai', + 'zhipuai-coding-plan', + 'zai', + 'zai-coding-plan', + 'moonshotai', + 'moonshotai-cn', + 'kimi-for-coding', 'openrouter', 'litellm', 'glama', diff --git a/packages/core/src/session/chat-session.test.ts b/packages/core/src/session/chat-session.test.ts index 6ab9fcbbf..d74b00576 100644 --- a/packages/core/src/session/chat-session.test.ts +++ b/packages/core/src/session/chat-session.test.ts @@ -282,7 +282,8 @@ describe('ChatSession', () => { sessionId, mockServices.resourceManager, mockLogger, - null // compaction strategy + null, // compaction strategy + null // auth resolver ); }); @@ -308,7 +309,8 @@ describe('ChatSession', () => { sessionId, mockServices.resourceManager, mockLogger, - null // compaction strategy + null, // compaction strategy + null // auth resolver ); }); @@ -425,7 +427,8 @@ describe('ChatSession', () => { sessionId, mockServices.resourceManager, // ResourceManager parameter mockLogger, // Logger parameter - null // compaction strategy + null, // compaction strategy + null // auth resolver ); // Verify session-specific history provider creation diff --git a/packages/core/src/session/chat-session.ts b/packages/core/src/session/chat-session.ts index 197aa6ffa..f6d8b774f 100644 --- a/packages/core/src/session/chat-session.ts +++ b/packages/core/src/session/chat-session.ts @@ -27,6 +27,7 @@ import type { UserMessageInput } from './message-queue.js'; import type { ContentInput } from '../agent/types.js'; import { getModelPricing, calculateCost } from '../llm/registry/index.js'; import type { CompactionStrategy } from '../context/compaction/types.js'; +import type { LlmAuthResolver } from '../llm/auth/types.js'; /** * Represents an isolated conversation session within a Dexto agent. @@ -144,6 +145,7 @@ export class ChatSession { mcpManager: MCPManager; sessionManager: import('./session-manager.js').SessionManager; compactionStrategy: CompactionStrategy | null; + llmAuthResolver?: LlmAuthResolver | null; }, public readonly id: string, logger: Logger @@ -268,7 +270,8 @@ export class ChatSession { this.id, this.services.resourceManager, // Pass ResourceManager for blob storage this.logger, // Pass logger for dependency injection - compactionStrategy // Pass compaction strategy + compactionStrategy, // Pass compaction strategy + this.services.llmAuthResolver ?? null ); this.logger.debug(`ChatSession ${this.id}: Services initialized with storage`); @@ -648,7 +651,8 @@ export class ChatSession { this.id, this.services.resourceManager, this.logger, - compactionStrategy // Pass compaction strategy + compactionStrategy, // Pass compaction strategy + this.services.llmAuthResolver ?? null ); // Replace the LLM service diff --git a/packages/core/src/session/session-manager.ts b/packages/core/src/session/session-manager.ts index fe8b742a4..2425f32f3 100644 --- a/packages/core/src/session/session-manager.ts +++ b/packages/core/src/session/session-manager.ts @@ -12,6 +12,7 @@ import type { HookManager } from '../hooks/manager.js'; import { SessionError } from './errors.js'; import type { TokenUsage } from '../llm/types.js'; import type { CompactionStrategy } from '../context/compaction/types.js'; +import type { LlmAuthResolver } from '../llm/auth/types.js'; export type SessionLoggerFactory = (options: { baseLogger: Logger; agentId: string; @@ -124,6 +125,7 @@ export class SessionManager { hookManager: HookManager; mcpManager: import('../mcp/manager.js').MCPManager; compactionStrategy: CompactionStrategy | null; + llmAuthResolver?: LlmAuthResolver | null; workspaceManager?: import('../workspace/manager.js').WorkspaceManager; }, config: SessionManagerConfig = {}, diff --git a/packages/core/src/utils/api-key-resolver.ts b/packages/core/src/utils/api-key-resolver.ts index fc6e0398b..10857eb1b 100644 --- a/packages/core/src/utils/api-key-resolver.ts +++ b/packages/core/src/utils/api-key-resolver.ts @@ -15,7 +15,17 @@ export const PROVIDER_API_KEY_MAP: Record<LLMProvider, string[]> = { cohere: ['COHERE_API_KEY'], xai: ['XAI_API_KEY', 'X_AI_API_KEY'], minimax: ['MINIMAX_API_KEY'], + 'minimax-cn': ['MINIMAX_API_KEY'], + 'minimax-coding-plan': ['MINIMAX_API_KEY'], + 'minimax-cn-coding-plan': ['MINIMAX_API_KEY'], glm: ['ZHIPU_API_KEY', 'ZHIPUAI_API_KEY'], + zhipuai: ['ZHIPU_API_KEY', 'ZHIPUAI_API_KEY'], + 'zhipuai-coding-plan': ['ZHIPU_API_KEY', 'ZHIPUAI_API_KEY'], + zai: ['ZHIPU_API_KEY'], + 'zai-coding-plan': ['ZHIPU_API_KEY'], + moonshotai: ['MOONSHOT_API_KEY'], + 'moonshotai-cn': ['MOONSHOT_API_KEY'], + 'kimi-for-coding': ['KIMI_API_KEY'], openrouter: ['OPENROUTER_API_KEY'], litellm: ['LITELLM_API_KEY', 'LITELLM_KEY'], glama: ['GLAMA_API_KEY'], diff --git a/packages/core/src/utils/service-initializer.ts b/packages/core/src/utils/service-initializer.ts index 8ee4f664b..42b72e2a2 100644 --- a/packages/core/src/utils/service-initializer.ts +++ b/packages/core/src/utils/service-initializer.ts @@ -28,6 +28,7 @@ import { MemoryManager } from '../memory/index.js'; import { HookManager } from '../hooks/manager.js'; import type { Hook } from '../hooks/types.js'; import type { CompactionStrategy } from '../context/compaction/types.js'; +import type { LlmAuthResolver } from '../llm/auth/types.js'; /** * Type for the core agent services returned by createAgentServices @@ -68,6 +69,7 @@ export type InitializeServicesOptions = { toolManagerFactory?: ToolManagerFactory; storageManager?: StorageManager; hooks?: Hook[] | undefined; + llmAuthResolver?: LlmAuthResolver | null; }; // High-level factory to load, validate, and wire up all agent services in one call @@ -256,6 +258,7 @@ export async function createAgentServices( hookManager, // Add hook manager for hook execution mcpManager, // Add MCP manager for ChatSession compactionStrategy: compactionStrategy ?? null, + llmAuthResolver: overrides?.llmAuthResolver ?? null, workspaceManager, // Workspace context propagation }, { diff --git a/packages/image-local/test/import.integration.test.ts b/packages/image-local/test/import.integration.test.ts index c28b25f98..88d0885a1 100644 --- a/packages/image-local/test/import.integration.test.ts +++ b/packages/image-local/test/import.integration.test.ts @@ -13,7 +13,7 @@ describe('Image Local - Import Integration', () => { const imageSpecifier = metaResolve ? metaResolve('@dexto/image-local') : pathToFileURL( - path.join(path.dirname(fileURLToPath(import.meta.url)), '..', 'dist', 'index.js') + path.join(path.dirname(fileURLToPath(import.meta.url)), '..', 'src', 'index.ts') ).href; const image = await loadImage(imageSpecifier); @@ -47,5 +47,5 @@ describe('Image Local - Import Integration', () => { expect(image.hooks['response-sanitizer']).toBeDefined(); expect(image.logger).toBeDefined(); - }, 15_000); + }, 60_000); }); diff --git a/packages/image-logger-agent/test/import.integration.test.ts b/packages/image-logger-agent/test/import.integration.test.ts index 07615ad82..b8e2306b4 100644 --- a/packages/image-logger-agent/test/import.integration.test.ts +++ b/packages/image-logger-agent/test/import.integration.test.ts @@ -9,7 +9,7 @@ describe('Image Logger Agent - Import Integration', () => { const imageSpecifier = metaResolve ? metaResolve('@dexto/image-logger-agent') : pathToFileURL( - path.join(path.dirname(fileURLToPath(import.meta.url)), '..', 'dist', 'index.js') + path.join(path.dirname(fileURLToPath(import.meta.url)), '..', 'src', 'index.ts') ).href; const image = await loadImage(imageSpecifier); @@ -19,5 +19,5 @@ describe('Image Logger Agent - Import Integration', () => { expect(image.hooks['request-logger']).toBeDefined(); expect(image.hooks['content-policy']).toBeDefined(); expect(image.hooks['response-sanitizer']).toBeDefined(); - }, 15_000); + }, 60_000); }); diff --git a/packages/server/src/hono/__tests__/llm-connect.integration.test.ts b/packages/server/src/hono/__tests__/llm-connect.integration.test.ts new file mode 100644 index 000000000..b351eb6fc --- /dev/null +++ b/packages/server/src/hono/__tests__/llm-connect.integration.test.ts @@ -0,0 +1,45 @@ +import { describe, it, expect, beforeAll, afterAll } from 'vitest'; +import { + createTestAgent, + startTestServer, + httpRequest, + type TestServer, + expectResponseStructure, + validators, +} from './test-fixtures.js'; + +describe('LLM Connect Routes', () => { + let testServer: TestServer | undefined; + + beforeAll(async () => { + const agent = await createTestAgent(); + testServer = await startTestServer(agent); + }, 30000); + + afterAll(async () => { + if (testServer) { + await testServer.cleanup(); + } + }); + + it('GET /api/llm/connect/providers returns curated providers', async () => { + if (!testServer) throw new Error('Test server not initialized'); + const res = await httpRequest(testServer.baseUrl, 'GET', '/api/llm/connect/providers'); + expect(res.status).toBe(200); + expectResponseStructure(res.body, { providers: validators.array }); + + const providers = (res.body as { providers: Array<{ providerId: string }> }).providers; + expect(providers.length).toBeGreaterThan(0); + expect(providers.some((p) => p.providerId === 'openai')).toBe(true); + }); + + it('GET /api/llm/connect/profiles returns redacted profile list', async () => { + if (!testServer) throw new Error('Test server not initialized'); + const res = await httpRequest(testServer.baseUrl, 'GET', '/api/llm/connect/profiles'); + expect(res.status).toBe(200); + expectResponseStructure(res.body, { + defaults: validators.object, + profiles: validators.array, + }); + }); +}); diff --git a/packages/server/src/hono/index.ts b/packages/server/src/hono/index.ts index 6630c3084..cf0bcd6c6 100644 --- a/packages/server/src/hono/index.ts +++ b/packages/server/src/hono/index.ts @@ -22,6 +22,7 @@ import { createApprovalsRouter } from './routes/approvals.js'; import { createQueueRouter } from './routes/queue.js'; import { createOpenRouterRouter } from './routes/openrouter.js'; import { createKeyRouter } from './routes/key.js'; +import { createLlmConnectRouter } from './routes/llm-connect.js'; import { createToolsRouter } from './routes/tools.js'; import { createDiscoveryRouter } from './routes/discovery.js'; import { createModelsRouter } from './routes/models.js'; @@ -183,6 +184,7 @@ export function createDextoApp(options: CreateDextoAppOptions) { .route(routePrefix, createQueueRouter(getAgent)) .route(routePrefix, createOpenRouterRouter()) .route(routePrefix, createKeyRouter()) + .route(routePrefix, createLlmConnectRouter()) .route(routePrefix, createToolsRouter(getAgent)) .route(routePrefix, createDiscoveryRouter(resolvedGetAgentConfigPath)) .route(routePrefix, createModelsRouter()) diff --git a/packages/server/src/hono/routes/llm-connect.ts b/packages/server/src/hono/routes/llm-connect.ts new file mode 100644 index 000000000..a16517049 --- /dev/null +++ b/packages/server/src/hono/routes/llm-connect.ts @@ -0,0 +1,156 @@ +import { OpenAPIHono, createRoute, z } from '@hono/zod-openapi'; +import { + CONNECT_PROVIDERS, + ConnectProviderSchema, + loadLlmAuthProfilesStore, + deleteLlmAuthProfile, + setDefaultLlmAuthProfile, +} from '@dexto/agent-management'; + +const ProfileRedactedSchema = z + .object({ + profileId: z.string(), + providerId: z.string(), + methodId: z.string(), + label: z.string().optional(), + credentialType: z.enum(['api_key', 'token', 'oauth']), + createdAt: z.number(), + updatedAt: z.number(), + expiresAt: z.number().optional(), + }) + .strict(); + +const ProvidersResponseSchema = z + .object({ + providers: z.array(ConnectProviderSchema).describe('Curated connect providers'), + }) + .strict(); + +const ProfilesResponseSchema = z + .object({ + defaults: z.record(z.string(), z.string()).describe('providerId -> default profileId'), + profiles: z.array(ProfileRedactedSchema).describe('Saved profiles (redacted)'), + }) + .strict(); + +const DeleteProfileParamsSchema = z + .object({ + profileId: z.string().describe('Profile id to delete'), + }) + .strict(); + +const SetDefaultBodySchema = z + .object({ + providerId: z.string().describe('Provider id'), + profileId: z + .string() + .nullable() + .describe('Profile id to set as default (null clears the default)'), + }) + .strict(); + +export function createLlmConnectRouter() { + const app = new OpenAPIHono(); + + const providersRoute = createRoute({ + method: 'get', + path: '/llm/connect/providers', + summary: 'Connect Providers', + description: 'Lists curated providers and supported login methods for /connect.', + tags: ['llm'], + responses: { + 200: { + description: 'Provider/method catalog', + content: { 'application/json': { schema: ProvidersResponseSchema } }, + }, + }, + }); + + const profilesRoute = createRoute({ + method: 'get', + path: '/llm/connect/profiles', + summary: 'Connect Profiles', + description: 'Lists saved provider auth profiles (redacted) and per-provider defaults.', + tags: ['llm'], + responses: { + 200: { + description: 'Profiles + defaults', + content: { 'application/json': { schema: ProfilesResponseSchema } }, + }, + }, + }); + + const deleteProfileRoute = createRoute({ + method: 'delete', + path: '/llm/connect/profiles/{profileId}', + summary: 'Delete Connect Profile', + description: 'Deletes a saved profile and clears defaults that reference it.', + tags: ['llm'], + request: { params: DeleteProfileParamsSchema }, + responses: { + 200: { + description: 'Delete result', + content: { + 'application/json': { + schema: z + .object({ ok: z.boolean() }) + .strict() + .describe('Delete profile response'), + }, + }, + }, + }, + }); + + const setDefaultRoute = createRoute({ + method: 'post', + path: '/llm/connect/defaults', + summary: 'Set Default Profile', + description: 'Sets the default profile for a provider (or clears it).', + tags: ['llm'], + request: { body: { content: { 'application/json': { schema: SetDefaultBodySchema } } } }, + responses: { + 200: { + description: 'Default updated', + content: { + 'application/json': { + schema: z.object({ ok: z.literal(true) }).strict(), + }, + }, + }, + }, + }); + + return app + .openapi(providersRoute, (ctx) => { + return ctx.json({ providers: CONNECT_PROVIDERS }); + }) + .openapi(profilesRoute, async (ctx) => { + const store = await loadLlmAuthProfilesStore(); + const profiles = Object.values(store.profiles).map((p) => ({ + profileId: p.profileId, + providerId: p.providerId, + methodId: p.methodId, + ...(p.label ? { label: p.label } : {}), + credentialType: p.credential.type, + createdAt: p.createdAt, + updatedAt: p.updatedAt, + ...(p.credential.type === 'oauth' ? { expiresAt: p.credential.expiresAt } : {}), + ...(p.credential.type === 'token' && p.credential.expiresAt + ? { expiresAt: p.credential.expiresAt } + : {}), + })); + + return ctx.json({ defaults: store.defaults, profiles }); + }) + .openapi(deleteProfileRoute, async (ctx) => { + const { profileId } = ctx.req.valid('param'); + const ok = await deleteLlmAuthProfile(profileId); + return ctx.json({ ok }); + }) + .openapi(setDefaultRoute, async (ctx) => { + const { providerId, profileId } = ctx.req.valid('json'); + await setDefaultLlmAuthProfile({ providerId, profileId }); + return ctx.json({ ok: true as const }); + }); +} diff --git a/packages/webui/components/ModelPicker/constants.tsx b/packages/webui/components/ModelPicker/constants.tsx index e6481a524..bf12aad0e 100644 --- a/packages/webui/components/ModelPicker/constants.tsx +++ b/packages/webui/components/ModelPicker/constants.tsx @@ -13,7 +13,17 @@ export const PROVIDER_LOGOS: Record<LLMProvider, string> = { 'openai-compatible': '/logos/openai.svg', cohere: '/logos/cohere-color.svg', minimax: '', + 'minimax-cn': '', + 'minimax-coding-plan': '', + 'minimax-cn-coding-plan': '', glm: '', + zhipuai: '', + 'zhipuai-coding-plan': '', + zai: '', + 'zai-coding-plan': '', + moonshotai: '', + 'moonshotai-cn': '', + 'kimi-for-coding': '', openrouter: '/logos/openrouter.svg', litellm: '/logos/litellm.svg', glama: '/logos/glama.svg', diff --git a/scripts/sync-llm-registry.ts b/scripts/sync-llm-registry.ts index 56f434356..097df65ae 100644 --- a/scripts/sync-llm-registry.ts +++ b/scripts/sync-llm-registry.ts @@ -203,7 +203,17 @@ type DextoProvider = | 'xai' | 'cohere' | 'minimax' + | 'minimax-cn' + | 'minimax-coding-plan' + | 'minimax-cn-coding-plan' | 'glm' + | 'zhipuai' + | 'zhipuai-coding-plan' + | 'zai' + | 'zai-coding-plan' + | 'moonshotai' + | 'moonshotai-cn' + | 'kimi-for-coding' | 'openrouter' | 'litellm' | 'glama' @@ -343,7 +353,17 @@ async function syncLlmRegistry() { xai: 'grok-4', cohere: 'command-a-03-2025', minimax: 'MiniMax-M2.1', + 'minimax-cn': 'MiniMax-M2.1', + 'minimax-coding-plan': 'MiniMax-M2.1', + 'minimax-cn-coding-plan': 'MiniMax-M2.1', glm: 'glm-4.7', + zhipuai: 'glm-4.7', + 'zhipuai-coding-plan': 'glm-4.7', + zai: 'glm-4.7', + 'zai-coding-plan': 'glm-4.7', + moonshotai: 'kimi-k2.5', + 'moonshotai-cn': 'kimi-k2.5', + 'kimi-for-coding': 'k2p5', vertex: 'gemini-3-flash-preview', bedrock: 'anthropic.claude-sonnet-4-5-20250929-v1:0', // gateway/dynamic providers intentionally omit defaults here @@ -357,7 +377,17 @@ async function syncLlmRegistry() { xai: (id: string) => id.startsWith('grok-'), cohere: (id: string) => id.startsWith('command-'), minimax: (_id: string) => true, + 'minimax-cn': (_id: string) => true, + 'minimax-coding-plan': (_id: string) => true, + 'minimax-cn-coding-plan': (_id: string) => true, glm: (id: string) => id.startsWith('glm-'), + zhipuai: (id: string) => id.startsWith('glm-'), + 'zhipuai-coding-plan': (id: string) => id.startsWith('glm-'), + zai: (id: string) => id.startsWith('glm-'), + 'zai-coding-plan': (id: string) => id.startsWith('glm-'), + moonshotai: (_id: string) => true, + 'moonshotai-cn': (_id: string) => true, + 'kimi-for-coding': (_id: string) => true, vertex: (_id: string) => true, bedrock: (_id: string) => true, openrouter: (_id: string) => true, @@ -414,6 +444,27 @@ async function syncLlmRegistry() { defaultModelId: defaults.minimax, includeModelId: include.minimax, }), + 'minimax-cn': buildModelsFromModelsDevProvider({ + provider: 'minimax-cn', + modelsDevApi: modelsDevJson, + modelsDevProviderId: 'minimax-cn', + defaultModelId: defaults['minimax-cn'], + includeModelId: include['minimax-cn'], + }), + 'minimax-coding-plan': buildModelsFromModelsDevProvider({ + provider: 'minimax-coding-plan', + modelsDevApi: modelsDevJson, + modelsDevProviderId: 'minimax-coding-plan', + defaultModelId: defaults['minimax-coding-plan'], + includeModelId: include['minimax-coding-plan'], + }), + 'minimax-cn-coding-plan': buildModelsFromModelsDevProvider({ + provider: 'minimax-cn-coding-plan', + modelsDevApi: modelsDevJson, + modelsDevProviderId: 'minimax-cn-coding-plan', + defaultModelId: defaults['minimax-cn-coding-plan'], + includeModelId: include['minimax-cn-coding-plan'], + }), glm: buildModelsFromModelsDevProvider({ provider: 'glm', modelsDevApi: modelsDevJson, @@ -421,6 +472,55 @@ async function syncLlmRegistry() { defaultModelId: defaults.glm, includeModelId: include.glm, }), + zhipuai: buildModelsFromModelsDevProvider({ + provider: 'zhipuai', + modelsDevApi: modelsDevJson, + modelsDevProviderId: 'zhipuai', + defaultModelId: defaults.zhipuai, + includeModelId: include.zhipuai, + }), + 'zhipuai-coding-plan': buildModelsFromModelsDevProvider({ + provider: 'zhipuai-coding-plan', + modelsDevApi: modelsDevJson, + modelsDevProviderId: 'zhipuai-coding-plan', + defaultModelId: defaults['zhipuai-coding-plan'], + includeModelId: include['zhipuai-coding-plan'], + }), + zai: buildModelsFromModelsDevProvider({ + provider: 'zai', + modelsDevApi: modelsDevJson, + modelsDevProviderId: 'zai', + defaultModelId: defaults.zai, + includeModelId: include.zai, + }), + 'zai-coding-plan': buildModelsFromModelsDevProvider({ + provider: 'zai-coding-plan', + modelsDevApi: modelsDevJson, + modelsDevProviderId: 'zai-coding-plan', + defaultModelId: defaults['zai-coding-plan'], + includeModelId: include['zai-coding-plan'], + }), + moonshotai: buildModelsFromModelsDevProvider({ + provider: 'moonshotai', + modelsDevApi: modelsDevJson, + modelsDevProviderId: 'moonshotai', + defaultModelId: defaults.moonshotai, + includeModelId: include.moonshotai, + }), + 'moonshotai-cn': buildModelsFromModelsDevProvider({ + provider: 'moonshotai-cn', + modelsDevApi: modelsDevJson, + modelsDevProviderId: 'moonshotai-cn', + defaultModelId: defaults['moonshotai-cn'], + includeModelId: include['moonshotai-cn'], + }), + 'kimi-for-coding': buildModelsFromModelsDevProvider({ + provider: 'kimi-for-coding', + modelsDevApi: modelsDevJson, + modelsDevProviderId: 'kimi-for-coding', + defaultModelId: defaults['kimi-for-coding'], + includeModelId: include['kimi-for-coding'], + }), openrouter: buildModelsFromModelsDevProvider({ provider: 'openrouter', modelsDevApi: modelsDevJson, diff --git a/vitest.config.ts b/vitest.config.ts index b0655b18c..40a80ae48 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -5,11 +5,35 @@ export default defineConfig({ resolve: { alias: { // Workspace aliases for packages used directly in tests + '@dexto/core/utils/path.js': path.resolve(__dirname, 'packages/core/src/utils/path.ts'), + '@dexto/core': path.resolve(__dirname, 'packages/core/src/index.ts'), '@dexto/agent-config': path.resolve(__dirname, 'packages/agent-config/src/index.ts'), '@dexto/agent-management': path.resolve( __dirname, 'packages/agent-management/src/index.ts' ), + '@dexto/tools-builtins': path.resolve( + __dirname, + 'packages/tools-builtins/src/index.ts' + ), + '@dexto/tools-filesystem': path.resolve( + __dirname, + 'packages/tools-filesystem/src/index.ts' + ), + '@dexto/tools-lifecycle': path.resolve( + __dirname, + 'packages/tools-lifecycle/src/index.ts' + ), + '@dexto/tools-plan': path.resolve(__dirname, 'packages/tools-plan/src/index.ts'), + '@dexto/tools-process': path.resolve(__dirname, 'packages/tools-process/src/index.ts'), + '@dexto/tools-todo': path.resolve(__dirname, 'packages/tools-todo/src/index.ts'), + '@dexto/image-local': path.resolve(__dirname, 'packages/image-local/src/index.ts'), + '@dexto/image-logger-agent': path.resolve( + __dirname, + 'packages/image-logger-agent/src/index.ts' + ), + '@dexto/orchestration': path.resolve(__dirname, 'packages/orchestration/src/index.ts'), + '@dexto/analytics': path.resolve(__dirname, 'packages/analytics/src/index.ts'), '@dexto/storage/schemas': path.resolve(__dirname, 'packages/storage/src/schemas.ts'), '@dexto/storage': path.resolve(__dirname, 'packages/storage/src/index.ts'), }, diff --git a/vitest.integration.config.ts b/vitest.integration.config.ts index 03f568795..e8f8e1a22 100644 --- a/vitest.integration.config.ts +++ b/vitest.integration.config.ts @@ -3,7 +3,39 @@ import path from 'path'; export default defineConfig({ resolve: { - alias: {}, + alias: { + '@dexto/core/utils/path.js': path.resolve(__dirname, 'packages/core/src/utils/path.ts'), + '@dexto/core': path.resolve(__dirname, 'packages/core/src/index.ts'), + '@dexto/agent-config': path.resolve(__dirname, 'packages/agent-config/src/index.ts'), + '@dexto/agent-management': path.resolve( + __dirname, + 'packages/agent-management/src/index.ts' + ), + '@dexto/tools-builtins': path.resolve( + __dirname, + 'packages/tools-builtins/src/index.ts' + ), + '@dexto/tools-filesystem': path.resolve( + __dirname, + 'packages/tools-filesystem/src/index.ts' + ), + '@dexto/tools-lifecycle': path.resolve( + __dirname, + 'packages/tools-lifecycle/src/index.ts' + ), + '@dexto/tools-plan': path.resolve(__dirname, 'packages/tools-plan/src/index.ts'), + '@dexto/tools-process': path.resolve(__dirname, 'packages/tools-process/src/index.ts'), + '@dexto/tools-todo': path.resolve(__dirname, 'packages/tools-todo/src/index.ts'), + '@dexto/image-local': path.resolve(__dirname, 'packages/image-local/src/index.ts'), + '@dexto/image-logger-agent': path.resolve( + __dirname, + 'packages/image-logger-agent/src/index.ts' + ), + '@dexto/orchestration': path.resolve(__dirname, 'packages/orchestration/src/index.ts'), + '@dexto/analytics': path.resolve(__dirname, 'packages/analytics/src/index.ts'), + '@dexto/storage/schemas': path.resolve(__dirname, 'packages/storage/src/schemas.ts'), + '@dexto/storage': path.resolve(__dirname, 'packages/storage/src/index.ts'), + }, }, test: { globals: true, From 8c7339cfc147ab9822f356176a99ce699d1a1b8f Mon Sep 17 00:00:00 2001 From: Rahul Karajgikar <rahul@trytruffle.ai> Date: Wed, 18 Feb 2026 03:34:39 +0530 Subject: [PATCH 07/25] fix(llm): tighten connect auth + openapi schemas --- .../src/auth/runtime-auth-resolver.test.ts | 13 ++++-- .../src/auth/runtime-auth-resolver.ts | 30 +++---------- .../cli/src/cli/commands/connect/index.ts | 26 +++++++---- .../src/cli/commands/connect/openai-codex.ts | 43 ------------------- packages/cli/src/cli/commands/init-app.ts | 35 ++++++++++----- packages/cli/src/cli/utils/provider-setup.ts | 6 ++- .../server/src/hono/routes/llm-connect.ts | 40 ++++++++++------- 7 files changed, 86 insertions(+), 107 deletions(-) diff --git a/packages/agent-management/src/auth/runtime-auth-resolver.test.ts b/packages/agent-management/src/auth/runtime-auth-resolver.test.ts index c9ac702fc..8b0abb663 100644 --- a/packages/agent-management/src/auth/runtime-auth-resolver.test.ts +++ b/packages/agent-management/src/auth/runtime-auth-resolver.test.ts @@ -61,7 +61,7 @@ describe('llm runtime auth resolver', () => { expect(runtime?.baseURL).toBe('https://api.minimaxi.com/anthropic/v1'); expect(typeof runtime?.fetch).toBe('function'); - const calls: Array<{ url: string; headers: Headers }> = []; + const calls: Array<{ url: string; headers: globalThis.Headers }> = []; globalThis.fetch = (async (input: RequestInfo | URL, init?: RequestInit) => { const url = input instanceof URL @@ -69,7 +69,7 @@ describe('llm runtime auth resolver', () => { : typeof input === 'string' ? input : input.url; - calls.push({ url, headers: new Headers(init?.headers) }); + calls.push({ url, headers: new globalThis.Headers(init?.headers) }); return new Response('ok', { status: 200 }); }) satisfies typeof fetch; @@ -110,7 +110,7 @@ describe('llm runtime auth resolver', () => { expect(runtime?.apiKey).toBe('dexto-oauth-dummy-key'); expect(typeof runtime?.fetch).toBe('function'); - const calls: Array<{ url: string; headers: Headers; body?: string }> = []; + const calls: Array<{ url: string; headers: globalThis.Headers; body?: string }> = []; globalThis.fetch = (async (input: RequestInfo | URL, init?: RequestInit) => { const url = input instanceof URL @@ -118,7 +118,12 @@ describe('llm runtime auth resolver', () => { : typeof input === 'string' ? input : input.url; - calls.push({ url, headers: new Headers(init?.headers), body: init?.body?.toString() }); + const body = init?.body?.toString(); + calls.push({ + url, + headers: new globalThis.Headers(init?.headers), + ...(body !== undefined ? { body } : {}), + }); if (url === 'https://api.minimax.io/oauth/token') { return new Response( diff --git a/packages/agent-management/src/auth/runtime-auth-resolver.ts b/packages/agent-management/src/auth/runtime-auth-resolver.ts index 6c7773924..1445d0809 100644 --- a/packages/agent-management/src/auth/runtime-auth-resolver.ts +++ b/packages/agent-management/src/auth/runtime-auth-resolver.ts @@ -33,35 +33,16 @@ function getLock(profileId: string): RefreshLock { return created; } -function removeAuthHeader(headers: Headers): void { +function removeAuthHeader(headers: globalThis.Headers): void { headers.delete('authorization'); - headers.delete('Authorization'); } -function upsertAuthHeader(headers: Headers, value: string): void { +function upsertAuthHeader(headers: globalThis.Headers, value: string): void { headers.set('authorization', value); } -function mergeHeaders(initHeaders: RequestInit['headers']): Headers { - const headers = new Headers(); - if (!initHeaders) return headers; - - if (initHeaders instanceof Headers) { - initHeaders.forEach((value, key) => headers.set(key, value)); - return headers; - } - - if (Array.isArray(initHeaders)) { - for (const [key, value] of initHeaders) { - if (value !== undefined) headers.set(key, String(value)); - } - return headers; - } - - for (const [key, value] of Object.entries(initHeaders)) { - if (value !== undefined) headers.set(key, String(value)); - } - return headers; +function mergeHeaders(initHeaders: RequestInit['headers']): globalThis.Headers { + return new globalThis.Headers(initHeaders); } function isOauthCredential( @@ -183,8 +164,8 @@ async function refreshOpenAiOauthTokens(refreshToken: string): Promise<{ const expiresInSec = typeof data.expires_in === 'number' && data.expires_in > 0 ? data.expires_in : 3600; const accountId = extractChatGptAccountId({ - id_token: data.id_token, access_token: data.access_token, + ...(data.id_token ? { id_token: data.id_token } : {}), }); return { @@ -367,7 +348,6 @@ function buildOAuthFetchWrapper(params: { // Remove any SDK-injected auth header (dummy key). removeAuthHeader(headers); headers.delete('x-api-key'); - headers.delete('X-API-Key'); const profile = getLlmAuthProfileSync(params.profileId); if (!profile || profile.credential.type !== 'oauth') { diff --git a/packages/cli/src/cli/commands/connect/index.ts b/packages/cli/src/cli/commands/connect/index.ts index f843b6e1a..2e8196ffc 100644 --- a/packages/cli/src/cli/commands/connect/index.ts +++ b/packages/cli/src/cli/commands/connect/index.ts @@ -17,20 +17,22 @@ function isCancel<T>(value: T | symbol): value is symbol { return p.isCancel(value); } -function toProviderOption(provider: (typeof CONNECT_PROVIDERS)[number]) { +function toProviderOption(provider: (typeof CONNECT_PROVIDERS)[number]): p.Option<string> { + const hint = provider.methods.length > 1 ? `${provider.methods.length} methods` : undefined; return { value: provider.providerId, label: provider.label, - hint: provider.methods.length > 1 ? `${provider.methods.length} methods` : undefined, - } as const; + ...(hint ? { hint } : {}), + }; } -function toMethodOption(method: ConnectMethod) { +function toMethodOption(method: ConnectMethod): p.Option<string> { + const hint = method.hint?.trim(); return { value: method.id, label: method.label, - hint: method.hint, - } as const; + ...(hint ? { hint } : {}), + }; } function defaultProfileId(providerId: string, methodId: string): string { @@ -231,8 +233,16 @@ export async function handleConnectCommand(options?: { interactive?: boolean }): const pollSpinner = p.spinner(); pollSpinner.start('Waiting for approval…'); - const tokens = await flow.callback((message) => pollSpinner.message(message)); - pollSpinner.stop('Approved'); + let tokens: Awaited<ReturnType<typeof flow.callback>>; + try { + tokens = await flow.callback((message) => pollSpinner.message(message)); + pollSpinner.stop('Approved'); + } catch (error) { + pollSpinner.stop('Failed'); + const message = error instanceof Error ? error.message : String(error); + p.outro(chalk.red(`❌ MiniMax OAuth failed: ${message}`)); + return; + } await upsertLlmAuthProfile({ profileId, diff --git a/packages/cli/src/cli/commands/connect/openai-codex.ts b/packages/cli/src/cli/commands/connect/openai-codex.ts index 1804e4510..8a1acaad9 100644 --- a/packages/cli/src/cli/commands/connect/openai-codex.ts +++ b/packages/cli/src/cli/commands/connect/openai-codex.ts @@ -1,5 +1,3 @@ -import { randomBytes, createHash } from 'node:crypto'; - const OPENAI_AUTH_ISSUER = 'https://auth.openai.com'; const DEVICE_CODE_URL = `${OPENAI_AUTH_ISSUER}/codex/device`; @@ -191,44 +189,3 @@ export async function loginOpenAiCodexDeviceCode(options: { }, }; } - -export type OpenAiBrowserOauthResult = { - url: string; - callback: () => Promise<OpenAiCodexTokens>; -}; - -function createPkceCodes(): { verifier: string; challenge: string } { - const verifier = randomBytes(32).toString('base64url'); - const challenge = createHash('sha256').update(verifier).digest('base64url'); - return { verifier, challenge }; -} - -function generateState(): string { - return randomBytes(16).toString('base64url'); -} - -export async function buildOpenAiCodexAuthorizeUrl(options: { - clientId: string; - redirectUri: string; - originator: string; -}): Promise<{ url: string; verifier: string; state: string }> { - const pkce = createPkceCodes(); - const state = generateState(); - const params = new URLSearchParams({ - response_type: 'code', - client_id: options.clientId, - redirect_uri: options.redirectUri, - scope: 'openid profile email offline_access', - code_challenge: pkce.challenge, - code_challenge_method: 'S256', - id_token_add_organizations: 'true', - codex_cli_simplified_flow: 'true', - state, - originator: options.originator, - }); - return { - url: `${OPENAI_AUTH_ISSUER}/oauth/authorize?${params.toString()}`, - verifier: pkce.verifier, - state, - }; -} diff --git a/packages/cli/src/cli/commands/init-app.ts b/packages/cli/src/cli/commands/init-app.ts index 1a46f5377..db43a640a 100644 --- a/packages/cli/src/cli/commands/init-app.ts +++ b/packages/cli/src/cli/commands/init-app.ts @@ -5,7 +5,7 @@ import fsExtra from 'fs-extra'; import path from 'node:path'; import { getPackageManager, getPackageManagerInstallCommand } from '../utils/package-mgmt.js'; import { executeWithTimeout } from '../utils/execute.js'; -import { type LLMProvider, getDefaultModelForProvider } from '@dexto/core'; +import { type LLMProvider, LLM_PROVIDERS, getDefaultModelForProvider } from '@dexto/core'; import { saveProviderApiKey } from '@dexto/agent-management'; import { getProviderDisplayName, @@ -20,6 +20,10 @@ function debug(message: string): void { } } +function isLLMProvider(value: unknown): value is LLMProvider { + return typeof value === 'string' && (LLM_PROVIDERS as readonly string[]).includes(value); +} + /** * Get user preferences needed to initialize a Dexto app * @returns The user preferences @@ -30,15 +34,23 @@ export async function getUserInputToInitDextoApp(): Promise<{ directory: string; createExampleFile: boolean; }> { - const answers = await p.group( + const answers = await p.group<{ + llmProvider: string | symbol; + llmApiKey: string | symbol; + directory: string | symbol; + createExampleFile: boolean | symbol; + }>( { llmProvider: () => - p.select({ + p.select<string>({ message: 'Choose your AI provider', options: PROVIDER_OPTIONS, }), llmApiKey: async ({ results }) => { - const llmProvider = results.llmProvider as LLMProvider; + const llmProvider = results.llmProvider; + if (!isLLMProvider(llmProvider)) { + throw new Error(`Unknown provider selection: ${llmProvider}`); + } const selection = await p.select({ message: `Enter your API key for ${getProviderDisplayName(llmProvider)}?`, options: [ @@ -97,12 +109,15 @@ export async function getUserInputToInitDextoApp(): Promise<{ } ); - // Type assertion to bypass the possible 'Symbol' type returned by p.group which is handled in onCancel - return answers as { - llmProvider: LLMProvider; - directory: string; - llmApiKey: string; - createExampleFile: boolean; + if (!isLLMProvider(answers.llmProvider)) { + throw new Error(`Unknown provider selection: ${answers.llmProvider}`); + } + + return { + llmProvider: answers.llmProvider, + llmApiKey: answers.llmApiKey, + directory: answers.directory, + createExampleFile: answers.createExampleFile, }; } diff --git a/packages/cli/src/cli/utils/provider-setup.ts b/packages/cli/src/cli/utils/provider-setup.ts index a26cc4f56..c03f01321 100644 --- a/packages/cli/src/cli/utils/provider-setup.ts +++ b/packages/cli/src/cli/utils/provider-setup.ts @@ -279,7 +279,7 @@ function buildProviderOptions(): Array<{ value: LLMProvider; label: string; hint export async function selectProvider(): Promise<LLMProvider | '_back' | null> { const options = buildProviderOptions(); - const choice = await p.select({ + const choice = await p.select<string>({ message: 'Choose your AI provider', options: [ ...options, @@ -295,7 +295,9 @@ export async function selectProvider(): Promise<LLMProvider | '_back' | null> { return null; } - return choice as LLMProvider | '_back'; + if (choice === '_back') return '_back'; + if (isLLMProvider(choice)) return choice; + return null; } /** diff --git a/packages/server/src/hono/routes/llm-connect.ts b/packages/server/src/hono/routes/llm-connect.ts index a16517049..ab56a624c 100644 --- a/packages/server/src/hono/routes/llm-connect.ts +++ b/packages/server/src/hono/routes/llm-connect.ts @@ -9,35 +9,41 @@ import { const ProfileRedactedSchema = z .object({ - profileId: z.string(), - providerId: z.string(), - methodId: z.string(), - label: z.string().optional(), - credentialType: z.enum(['api_key', 'token', 'oauth']), - createdAt: z.number(), - updatedAt: z.number(), - expiresAt: z.number().optional(), + profileId: z.string().describe('Unique profile id'), + providerId: z.string().describe('LLM provider id'), + methodId: z.string().describe('Auth method id'), + label: z.string().optional().describe('Optional display label'), + credentialType: z + .enum(['api_key', 'token', 'oauth']) + .describe('Credential type (redacted)'), + createdAt: z.number().describe('Profile creation time (unix ms)'), + updatedAt: z.number().describe('Profile last update time (unix ms)'), + expiresAt: z.number().optional().describe('Token expiry time (unix ms)'), }) - .strict(); + .strict() + .describe('Redacted auth profile (no secrets)'); const ProvidersResponseSchema = z .object({ providers: z.array(ConnectProviderSchema).describe('Curated connect providers'), }) - .strict(); + .strict() + .describe('Connect providers response'); const ProfilesResponseSchema = z .object({ defaults: z.record(z.string(), z.string()).describe('providerId -> default profileId'), profiles: z.array(ProfileRedactedSchema).describe('Saved profiles (redacted)'), }) - .strict(); + .strict() + .describe('Connect profiles response'); const DeleteProfileParamsSchema = z .object({ profileId: z.string().describe('Profile id to delete'), }) - .strict(); + .strict() + .describe('Delete profile path params'); const SetDefaultBodySchema = z .object({ @@ -47,7 +53,8 @@ const SetDefaultBodySchema = z .nullable() .describe('Profile id to set as default (null clears the default)'), }) - .strict(); + .strict() + .describe('Set default profile request body'); export function createLlmConnectRouter() { const app = new OpenAPIHono(); @@ -93,7 +100,7 @@ export function createLlmConnectRouter() { content: { 'application/json': { schema: z - .object({ ok: z.boolean() }) + .object({ ok: z.boolean().describe('Whether the profile was deleted') }) .strict() .describe('Delete profile response'), }, @@ -114,7 +121,10 @@ export function createLlmConnectRouter() { description: 'Default updated', content: { 'application/json': { - schema: z.object({ ok: z.literal(true) }).strict(), + schema: z + .object({ ok: z.literal(true).describe('Request succeeded') }) + .strict() + .describe('Set default profile response'), }, }, }, From e7888f6b2df9236cff030edfa8d46340a384f33b Mon Sep 17 00:00:00 2001 From: Rahul Karajgikar <rahul@trytruffle.ai> Date: Wed, 18 Feb 2026 12:39:40 +0530 Subject: [PATCH 08/25] docs(commands): make custom-plan self-contained --- .claude/commands/custom-plan.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.claude/commands/custom-plan.md b/.claude/commands/custom-plan.md index 7a3738af6..55ae33dd8 100644 --- a/.claude/commands/custom-plan.md +++ b/.claude/commands/custom-plan.md @@ -5,7 +5,7 @@ allowed-tools: ["bash", "read", "glob", "grep", "task"] # Custom Plan (PLAN + Working Memory + Tasklist) -Create feature plans using the same paradigm as `feature-plans/image-and-core-di-refactor/`: +Create feature plans using the PLAN + Working Memory + Tasklist paradigm: - `PLAN.md` is the source of truth (problem, goals, design, and a concrete tasklist). - `WORKING_MEMORY.md` is the live scratchpad agents update while executing. - `USER_VERIFICATION.md` is the owner-only decision + manual verification checklist. From 5108f8555becb3c69a2fbd97c935e6349868760b Mon Sep 17 00:00:00 2001 From: Rahul Karajgikar <rahul@trytruffle.ai> Date: Wed, 18 Feb 2026 14:47:15 +0530 Subject: [PATCH 09/25] fix(auth): harden llm oauth runtime + profiles store --- .../src/auth/llm-profiles.test.ts | 32 ++- .../agent-management/src/auth/llm-profiles.ts | 204 +++++++++++++----- .../src/auth/runtime-auth-resolver.test.ts | 154 ++++++++++++- .../src/auth/runtime-auth-resolver.ts | 63 +++++- .../cli/src/cli/commands/connect/index.ts | 6 +- 5 files changed, 393 insertions(+), 66 deletions(-) diff --git a/packages/agent-management/src/auth/llm-profiles.test.ts b/packages/agent-management/src/auth/llm-profiles.test.ts index 5ca0a8b8f..16a1301ff 100644 --- a/packages/agent-management/src/auth/llm-profiles.test.ts +++ b/packages/agent-management/src/auth/llm-profiles.test.ts @@ -23,7 +23,11 @@ describe('llm-profiles store', () => { }); afterEach(async () => { - process.env.HOME = previousHome; + if (previousHome === undefined) { + delete process.env.HOME; + } else { + process.env.HOME = previousHome; + } await fs.rm(tempHomeDir, { recursive: true, force: true }); }); @@ -34,6 +38,32 @@ describe('llm-profiles store', () => { expect(store.profiles).toEqual({}); }); + it('backs up a corrupt store file and returns an empty store', async () => { + const filePath = getLlmAuthProfilesPath(); + await fs.mkdir(path.dirname(filePath), { recursive: true }); + + const corrupt = '{not-json'; + await fs.writeFile(filePath, corrupt, { encoding: 'utf-8' }); + + const store = await loadLlmAuthProfilesStore(); + expect(store.defaults).toEqual({}); + expect(store.profiles).toEqual({}); + + await expect(fs.stat(filePath)).rejects.toMatchObject({ code: 'ENOENT' }); + + const dir = path.dirname(filePath); + const entries = await fs.readdir(dir); + const backups = entries.filter((e) => e.startsWith('llm-profiles.json.corrupt.')); + expect(backups).toHaveLength(1); + + const backupPath = path.join(dir, backups[0]!); + const backupContent = await fs.readFile(backupPath, 'utf-8'); + expect(backupContent).toBe(corrupt); + + const stat = await fs.stat(backupPath); + expect(stat.mode & 0o777).toBe(0o600); + }); + it('upserts profiles, forces permissions, and tracks defaults', async () => { await upsertLlmAuthProfile({ profileId: 'openai:default', diff --git a/packages/agent-management/src/auth/llm-profiles.ts b/packages/agent-management/src/auth/llm-profiles.ts index d7a2e1817..01f60d003 100644 --- a/packages/agent-management/src/auth/llm-profiles.ts +++ b/packages/agent-management/src/auth/llm-profiles.ts @@ -10,7 +10,7 @@ */ import { randomUUID } from 'node:crypto'; -import { existsSync, readFileSync } from 'node:fs'; +import { chmodSync, existsSync, readFileSync, renameSync } from 'node:fs'; import { promises as fs } from 'node:fs'; import path from 'node:path'; import { z } from 'zod'; @@ -23,6 +23,9 @@ const STORE_DIR = 'auth'; const STORE_FILENAME = 'llm-profiles.json'; const FILE_MODE = 0o600; +const STORE_LOCK_TIMEOUT_MS = 5000; +const STORE_LOCK_STALE_MS = 60_000; +const STORE_LOCK_RETRY_DELAY_MS = 50; export const LlmAuthCredentialSchema = z .discriminatedUnion('type', [ @@ -86,10 +89,91 @@ export function getLlmAuthProfilesPath(): string { return getDextoGlobalPath(STORE_DIR, STORE_FILENAME); } +function getStoreLockPath(storePath: string): string { + return `${storePath}.lock`; +} + function createEmptyStore(): LlmAuthProfilesStore { return { version: STORE_VERSION, defaults: {}, profiles: {} }; } +function createCorruptBackupPath(storePath: string): string { + const ts = new Date().toISOString().replace(/[:.]/g, '-'); + return `${storePath}.corrupt.${ts}.${randomUUID()}`; +} + +async function backupCorruptStoreFile(storePath: string): Promise<void> { + const backupPath = createCorruptBackupPath(storePath); + try { + await fs.rename(storePath, backupPath); + await fs.chmod(backupPath, FILE_MODE).catch(() => undefined); + } catch (error) { + if ((error as NodeJS.ErrnoException).code === 'ENOENT') return; + throw error; + } +} + +function backupCorruptStoreFileSync(storePath: string): void { + const backupPath = createCorruptBackupPath(storePath); + try { + renameSync(storePath, backupPath); + try { + chmodSync(backupPath, FILE_MODE); + } catch { + // ignore chmod failures + } + } catch (error) { + if ((error as NodeJS.ErrnoException).code === 'ENOENT') return; + throw error; + } +} + +async function maybeRemoveStaleLock(lockPath: string): Promise<void> { + try { + const stat = await fs.stat(lockPath); + if (Date.now() - stat.mtimeMs > STORE_LOCK_STALE_MS) { + await fs.unlink(lockPath); + } + } catch (error) { + if ((error as NodeJS.ErrnoException).code === 'ENOENT') return; + throw error; + } +} + +async function withStoreLock<T>(fn: () => Promise<T>): Promise<T> { + const storePath = getLlmAuthProfilesPath(); + const lockPath = getStoreLockPath(storePath); + + await fs.mkdir(path.dirname(storePath), { recursive: true }); + + const startedAt = Date.now(); + while (true) { + try { + const handle = await fs.open(lockPath, 'wx', FILE_MODE); + try { + await handle.writeFile(`${process.pid}\n${new Date().toISOString()}\n`, 'utf-8'); + } finally { + await handle.close(); + } + await fs.chmod(lockPath, FILE_MODE).catch(() => undefined); + break; + } catch (error) { + if ((error as NodeJS.ErrnoException).code !== 'EEXIST') throw error; + await maybeRemoveStaleLock(lockPath); + if (Date.now() - startedAt > STORE_LOCK_TIMEOUT_MS) { + throw new Error(`Timed out acquiring LLM auth store lock: ${lockPath}`); + } + await new Promise((resolve) => setTimeout(resolve, STORE_LOCK_RETRY_DELAY_MS)); + } + } + + try { + return await fn(); + } finally { + await fs.unlink(lockPath).catch(() => undefined); + } +} + async function writeFileAtomic(filePath: string, content: string): Promise<void> { await fs.mkdir(path.dirname(filePath), { recursive: true }); @@ -118,8 +202,17 @@ export async function loadLlmAuthProfilesStore(): Promise<LlmAuthProfilesStore> try { const content = await fs.readFile(filePath, 'utf-8'); - const parsed = LlmAuthProfilesStoreSchema.safeParse(JSON.parse(content)); + let decoded: unknown; + try { + decoded = JSON.parse(content) as unknown; + } catch { + await backupCorruptStoreFile(filePath); + return createEmptyStore(); + } + + const parsed = LlmAuthProfilesStoreSchema.safeParse(decoded); if (!parsed.success) { + await backupCorruptStoreFile(filePath); return createEmptyStore(); } return parsed.data; @@ -139,8 +232,17 @@ export function loadLlmAuthProfilesStoreSync(): LlmAuthProfilesStore { try { const content = readFileSync(filePath, 'utf-8'); - const parsed = LlmAuthProfilesStoreSchema.safeParse(JSON.parse(content)); + let decoded: unknown; + try { + decoded = JSON.parse(content) as unknown; + } catch { + backupCorruptStoreFileSync(filePath); + return createEmptyStore(); + } + + const parsed = LlmAuthProfilesStoreSchema.safeParse(decoded); if (!parsed.success) { + backupCorruptStoreFileSync(filePath); return createEmptyStore(); } return parsed.data; @@ -180,65 +282,71 @@ export async function upsertLlmAuthProfile(input: { label?: string | undefined; credential: LlmAuthCredential; }): Promise<LlmAuthProfile> { - const now = Date.now(); - const store = await loadLlmAuthProfilesStore(); - const existing = store.profiles[input.profileId]; - - const next: LlmAuthProfile = { - profileId: input.profileId, - providerId: input.providerId, - methodId: input.methodId, - ...(input.label ? { label: input.label } : {}), - credential: input.credential, - createdAt: existing?.createdAt ?? now, - updatedAt: now, - }; - - const validated = LlmAuthProfileSchema.parse(next); - store.profiles[validated.profileId] = validated; - await saveLlmAuthProfilesStore(store); - return validated; + return await withStoreLock(async () => { + const now = Date.now(); + const store = await loadLlmAuthProfilesStore(); + const existing = store.profiles[input.profileId]; + + const next: LlmAuthProfile = { + profileId: input.profileId, + providerId: input.providerId, + methodId: input.methodId, + ...(input.label ? { label: input.label } : {}), + credential: input.credential, + createdAt: existing?.createdAt ?? now, + updatedAt: now, + }; + + const validated = LlmAuthProfileSchema.parse(next); + store.profiles[validated.profileId] = validated; + await saveLlmAuthProfilesStore(store); + return validated; + }); } export async function deleteLlmAuthProfile(profileId: string): Promise<boolean> { - const store = await loadLlmAuthProfilesStore(); - if (!store.profiles[profileId]) return false; - - delete store.profiles[profileId]; - for (const [providerId, defaultProfileId] of Object.entries(store.defaults)) { - if (defaultProfileId === profileId) { - delete store.defaults[providerId]; + return await withStoreLock(async () => { + const store = await loadLlmAuthProfilesStore(); + if (!store.profiles[profileId]) return false; + + delete store.profiles[profileId]; + for (const [providerId, defaultProfileId] of Object.entries(store.defaults)) { + if (defaultProfileId === profileId) { + delete store.defaults[providerId]; + } } - } - await saveLlmAuthProfilesStore(store); - return true; + await saveLlmAuthProfilesStore(store); + return true; + }); } export async function setDefaultLlmAuthProfile(options: { providerId: string; profileId: string | null; }): Promise<void> { - const store = await loadLlmAuthProfilesStore(); + return await withStoreLock(async () => { + const store = await loadLlmAuthProfilesStore(); - if (options.profileId === null) { - delete store.defaults[options.providerId]; - await saveLlmAuthProfilesStore(store); - return; - } + if (options.profileId === null) { + delete store.defaults[options.providerId]; + await saveLlmAuthProfilesStore(store); + return; + } - const profile = store.profiles[options.profileId]; - if (!profile) { - throw new Error(`Profile not found: ${options.profileId}`); - } - if (profile.providerId !== options.providerId) { - throw new Error( - `Profile provider mismatch: expected ${options.providerId}, got ${profile.providerId}` - ); - } + const profile = store.profiles[options.profileId]; + if (!profile) { + throw new Error(`Profile not found: ${options.profileId}`); + } + if (profile.providerId !== options.providerId) { + throw new Error( + `Profile provider mismatch: expected ${options.providerId}, got ${profile.providerId}` + ); + } - store.defaults[options.providerId] = options.profileId; - await saveLlmAuthProfilesStore(store); + store.defaults[options.providerId] = options.profileId; + await saveLlmAuthProfilesStore(store); + }); } export async function getDefaultLlmAuthProfileId(providerId: string): Promise<string | null> { diff --git a/packages/agent-management/src/auth/runtime-auth-resolver.test.ts b/packages/agent-management/src/auth/runtime-auth-resolver.test.ts index 8b0abb663..ccf150260 100644 --- a/packages/agent-management/src/auth/runtime-auth-resolver.test.ts +++ b/packages/agent-management/src/auth/runtime-auth-resolver.test.ts @@ -15,6 +15,7 @@ describe('llm runtime auth resolver', () => { let previousHome: string | undefined; let originalFetch: typeof fetch | undefined; let previousMiniMaxClientId: string | undefined; + let previousOpenAiClientId: string | undefined; beforeEach(async () => { tempHomeDir = await fs.mkdtemp(path.join(tmpdir(), 'dexto-llm-auth-resolver-test-')); @@ -22,14 +23,30 @@ describe('llm runtime auth resolver', () => { process.env.HOME = tempHomeDir; originalFetch = globalThis.fetch; previousMiniMaxClientId = process.env.DEXTO_MINIMAX_PORTAL_OAUTH_CLIENT_ID; + previousOpenAiClientId = process.env.DEXTO_OPENAI_CODEX_OAUTH_CLIENT_ID; }); afterEach(async () => { if (originalFetch) { globalThis.fetch = originalFetch; } - process.env.DEXTO_MINIMAX_PORTAL_OAUTH_CLIENT_ID = previousMiniMaxClientId; - process.env.HOME = previousHome; + if (previousMiniMaxClientId === undefined) { + delete process.env.DEXTO_MINIMAX_PORTAL_OAUTH_CLIENT_ID; + } else { + process.env.DEXTO_MINIMAX_PORTAL_OAUTH_CLIENT_ID = previousMiniMaxClientId; + } + + if (previousOpenAiClientId === undefined) { + delete process.env.DEXTO_OPENAI_CODEX_OAUTH_CLIENT_ID; + } else { + process.env.DEXTO_OPENAI_CODEX_OAUTH_CLIENT_ID = previousOpenAiClientId; + } + + if (previousHome === undefined) { + delete process.env.HOME; + } else { + process.env.HOME = previousHome; + } await fs.rm(tempHomeDir, { recursive: true, force: true }); vi.restoreAllMocks(); }); @@ -85,9 +102,61 @@ describe('llm runtime auth resolver', () => { expect(calls[0]!.headers.get('authorization')).toBe(null); }); - it('refreshes minimax oauth tokens when expired', async () => { - process.env.DEXTO_MINIMAX_PORTAL_OAUTH_CLIENT_ID = 'client-id'; + it('preserves Request headers when init.headers is omitted', async () => { + await upsertLlmAuthProfile({ + profileId: 'minimax:portal_oauth_cn', + providerId: 'minimax', + methodId: 'portal_oauth_cn', + credential: { + type: 'oauth', + accessToken: 'access-token', + refreshToken: 'refresh-token', + expiresAt: Date.now() + 60_000, + metadata: { region: 'cn' }, + }, + }); + await setDefaultLlmAuthProfile({ + providerId: 'minimax', + profileId: 'minimax:portal_oauth_cn', + }); + const resolver = createDefaultLlmAuthResolver(); + const runtime = resolver.resolveRuntimeAuth({ provider: 'minimax', model: 'MiniMax-M2.1' }); + expect(runtime?.apiKey).toBe('dexto-oauth-dummy-key'); + expect(typeof runtime?.fetch).toBe('function'); + + const calls: Array<{ url: string; headers: globalThis.Headers }> = []; + globalThis.fetch = (async (input: RequestInfo | URL, init?: RequestInit) => { + const url = + input instanceof URL + ? input.toString() + : typeof input === 'string' + ? input + : input.url; + calls.push({ url, headers: new globalThis.Headers(init?.headers) }); + return new Response('ok', { status: 200 }); + }) satisfies typeof fetch; + + const request = new globalThis.Request('https://example.com', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-Custom': 'abc', + 'x-api-key': 'placeholder', + }, + body: JSON.stringify({ hello: 'world' }), + }); + + await runtime!.fetch!(request); + + expect(calls).toHaveLength(1); + expect(calls[0]!.url).toBe('https://example.com/'); + expect(calls[0]!.headers.get('content-type')).toBe('application/json'); + expect(calls[0]!.headers.get('x-custom')).toBe('abc'); + expect(calls[0]!.headers.get('x-api-key')).toBe('access-token'); + }); + + it('refreshes minimax oauth tokens when expired', async () => { await upsertLlmAuthProfile({ profileId: 'minimax:portal_oauth_global', providerId: 'minimax', @@ -97,7 +166,7 @@ describe('llm runtime auth resolver', () => { accessToken: 'stale-access', refreshToken: 'stale-refresh', expiresAt: Date.now() - 1, - metadata: { region: 'global' }, + metadata: { region: 'global', clientId: 'client-id' }, }, }); await setDefaultLlmAuthProfile({ @@ -126,6 +195,7 @@ describe('llm runtime auth resolver', () => { }); if (url === 'https://api.minimax.io/oauth/token') { + expect(body).toContain('client_id=client-id'); return new Response( JSON.stringify({ status: 'success', @@ -157,4 +227,78 @@ describe('llm runtime auth resolver', () => { expect(updated.credential.expiresAt).toBeGreaterThan(Date.now()); } }); + + it('refreshes openai oauth tokens using the stored clientId', async () => { + delete process.env.DEXTO_OPENAI_CODEX_OAUTH_CLIENT_ID; + + await upsertLlmAuthProfile({ + profileId: 'openai:oauth_codex', + providerId: 'openai', + methodId: 'oauth_codex', + credential: { + type: 'oauth', + accessToken: 'stale-access', + refreshToken: 'stale-refresh', + expiresAt: Date.now() - 1, + metadata: { clientId: 'client-id' }, + }, + }); + await setDefaultLlmAuthProfile({ + providerId: 'openai', + profileId: 'openai:oauth_codex', + }); + + const resolver = createDefaultLlmAuthResolver(); + const runtime = resolver.resolveRuntimeAuth({ provider: 'openai', model: 'gpt-4o-mini' }); + expect(runtime?.apiKey).toBe('dexto-oauth-dummy-key'); + expect(typeof runtime?.fetch).toBe('function'); + + const calls: Array<{ url: string; headers: globalThis.Headers; body?: string }> = []; + globalThis.fetch = (async (input: RequestInfo | URL, init?: RequestInit) => { + const url = + input instanceof URL + ? input.toString() + : typeof input === 'string' + ? input + : input.url; + const body = init?.body?.toString(); + calls.push({ + url, + headers: new globalThis.Headers(init?.headers), + ...(body !== undefined ? { body } : {}), + }); + + if (url === 'https://auth.openai.com/oauth/token') { + expect(body).toContain('client_id=client-id'); + expect(body).toContain('refresh_token=stale-refresh'); + return new Response( + JSON.stringify({ + access_token: 'fresh-access', + refresh_token: 'fresh-refresh', + expires_in: 3600, + }), + { status: 200 } + ); + } + + return new Response('ok', { status: 200 }); + }) satisfies typeof fetch; + + await runtime!.fetch!('https://example.com', { + headers: { Authorization: 'Bearer stale' }, + }); + + expect(calls.some((c) => c.url === 'https://auth.openai.com/oauth/token')).toBe(true); + const requestCall = calls.find((c) => c.url === 'https://example.com'); + expect(requestCall?.headers.get('authorization')).toBe('Bearer fresh-access'); + + const store = await loadLlmAuthProfilesStore(); + const updated = store.profiles['openai:oauth_codex']; + expect(updated?.credential.type).toBe('oauth'); + if (updated?.credential.type === 'oauth') { + expect(updated.credential.accessToken).toBe('fresh-access'); + expect(updated.credential.refreshToken).toBe('fresh-refresh'); + expect(updated.credential.expiresAt).toBeGreaterThan(Date.now()); + } + }); }); diff --git a/packages/agent-management/src/auth/runtime-auth-resolver.ts b/packages/agent-management/src/auth/runtime-auth-resolver.ts index 1445d0809..4c931464e 100644 --- a/packages/agent-management/src/auth/runtime-auth-resolver.ts +++ b/packages/agent-management/src/auth/runtime-auth-resolver.ts @@ -41,8 +41,26 @@ function upsertAuthHeader(headers: globalThis.Headers, value: string): void { headers.set('authorization', value); } -function mergeHeaders(initHeaders: RequestInit['headers']): globalThis.Headers { - return new globalThis.Headers(initHeaders); +function isRequest(value: unknown): value is globalThis.Request { + return typeof globalThis.Request !== 'undefined' && value instanceof globalThis.Request; +} + +function mergeHeaders(params: { + requestInput: RequestInfo | URL; + initHeaders: RequestInit['headers'] | undefined; +}): globalThis.Headers { + const headers = new globalThis.Headers(); + + if (isRequest(params.requestInput)) { + params.requestInput.headers.forEach((value, key) => headers.set(key, value)); + } + + if (params.initHeaders) { + const init = new globalThis.Headers(params.initHeaders); + init.forEach((value, key) => headers.set(key, value)); + } + + return headers; } function isOauthCredential( @@ -121,13 +139,27 @@ function normalizeAnthropicBaseUrl(url: string): string { return `${trimmed}/v1`; } -async function refreshOpenAiOauthTokens(refreshToken: string): Promise<{ +function toSafeErrorText(text: string): string { + const trimmed = text.trim(); + if (!trimmed) return ''; + const singleLine = trimmed.replace(/\s+/g, ' '); + const maxLen = 500; + if (singleLine.length <= maxLen) return singleLine; + return `${singleLine.slice(0, maxLen)}…`; +} + +async function refreshOpenAiOauthTokens(params: { + refreshToken: string; + clientIdFromProfile?: string | undefined; +}): Promise<{ accessToken: string; refreshToken: string; expiresAt: number; accountId: string | null; }> { - const clientId = process.env.DEXTO_OPENAI_CODEX_OAUTH_CLIENT_ID?.trim(); + const clientId = + process.env.DEXTO_OPENAI_CODEX_OAUTH_CLIENT_ID?.trim() || + params.clientIdFromProfile?.trim(); if (!clientId) { throw new Error('Missing DEXTO_OPENAI_CODEX_OAUTH_CLIENT_ID'); } @@ -137,7 +169,7 @@ async function refreshOpenAiOauthTokens(refreshToken: string): Promise<{ headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ grant_type: 'refresh_token', - refresh_token: refreshToken, + refresh_token: params.refreshToken, client_id: clientId, }).toString(), signal: AbortSignal.timeout(15_000), @@ -145,8 +177,9 @@ async function refreshOpenAiOauthTokens(refreshToken: string): Promise<{ if (!response.ok) { const text = await response.text().catch(() => ''); + const safe = toSafeErrorText(text); throw new Error( - `OpenAI OAuth refresh failed (${response.status}): ${text || response.statusText}` + `OpenAI OAuth refresh failed (${response.status}): ${safe || response.statusText}` ); } @@ -170,7 +203,7 @@ async function refreshOpenAiOauthTokens(refreshToken: string): Promise<{ return { accessToken: data.access_token, - refreshToken: data.refresh_token ?? refreshToken, + refreshToken: data.refresh_token ?? params.refreshToken, expiresAt: Date.now() + expiresInSec * 1000, accountId, }; @@ -179,6 +212,7 @@ async function refreshOpenAiOauthTokens(refreshToken: string): Promise<{ async function refreshMiniMaxPortalOauthTokens(params: { region: 'cn' | 'global'; refreshToken: string; + clientIdFromProfile?: string | undefined; }): Promise<{ accessToken: string; refreshToken: string; @@ -186,7 +220,9 @@ async function refreshMiniMaxPortalOauthTokens(params: { resourceUrl?: string; notificationMessage?: string; }> { - const clientId = process.env.DEXTO_MINIMAX_PORTAL_OAUTH_CLIENT_ID?.trim(); + const clientId = + process.env.DEXTO_MINIMAX_PORTAL_OAUTH_CLIENT_ID?.trim() || + params.clientIdFromProfile?.trim(); if (!clientId) { throw new Error('Missing DEXTO_MINIMAX_PORTAL_OAUTH_CLIENT_ID'); } @@ -215,8 +251,9 @@ async function refreshMiniMaxPortalOauthTokens(params: { } if (!response.ok) { + const safe = toSafeErrorText(text); throw new Error( - `MiniMax OAuth refresh failed (${response.status}): ${text || response.statusText}` + `MiniMax OAuth refresh failed (${response.status}): ${safe || response.statusText}` ); } @@ -268,7 +305,10 @@ async function refreshOauthProfileIfNeeded(profile: LlmAuthProfile): Promise<Llm if (latest.credential.expiresAt > Date.now() + safetyWindowMs) return; if (latest.providerId === 'openai' && latest.methodId === 'oauth_codex') { - const refreshed = await refreshOpenAiOauthTokens(latest.credential.refreshToken); + const refreshed = await refreshOpenAiOauthTokens({ + refreshToken: latest.credential.refreshToken, + clientIdFromProfile: latest.credential.metadata?.clientId, + }); const nextCred: Extract<LlmAuthCredential, { type: 'oauth' }> = { ...latest.credential, accessToken: refreshed.accessToken, @@ -304,6 +344,7 @@ async function refreshOauthProfileIfNeeded(profile: LlmAuthProfile): Promise<Llm const refreshed = await refreshMiniMaxPortalOauthTokens({ region, refreshToken: latest.credential.refreshToken, + clientIdFromProfile: latest.credential.metadata?.clientId, }); const nextCred: Extract<LlmAuthCredential, { type: 'oauth' }> = { @@ -343,7 +384,7 @@ function buildOAuthFetchWrapper(params: { extraHeaders?: Record<string, string> | undefined; }): typeof fetch { return async (requestInput, init) => { - const headers = mergeHeaders(init?.headers); + const headers = mergeHeaders({ requestInput, initHeaders: init?.headers }); // Remove any SDK-injected auth header (dummy key). removeAuthHeader(headers); diff --git a/packages/cli/src/cli/commands/connect/index.ts b/packages/cli/src/cli/commands/connect/index.ts index 2e8196ffc..036fb8fa0 100644 --- a/packages/cli/src/cli/commands/connect/index.ts +++ b/packages/cli/src/cli/commands/connect/index.ts @@ -195,7 +195,10 @@ export async function handleConnectCommand(options?: { interactive?: boolean }): accessToken: tokens.accessToken, refreshToken: tokens.refreshToken, expiresAt, - ...(accountId ? { metadata: { accountId } } : {}), + metadata: { + clientId, + ...(accountId ? { accountId } : {}), + }, }, }); await setDefaultLlmAuthProfile({ providerId: provider.providerId, profileId }); @@ -256,6 +259,7 @@ export async function handleConnectCommand(options?: { interactive?: boolean }): expiresAt: tokens.expiresAt, metadata: { region, + clientId, ...(tokens.resourceUrl ? { resourceUrl: tokens.resourceUrl } : {}), }, }, From 69b57cce698ab08562c3ac9c918a04cb644fcdd1 Mon Sep 17 00:00:00 2001 From: Rahul Karajgikar <rahul@trytruffle.ai> Date: Wed, 18 Feb 2026 14:47:32 +0530 Subject: [PATCH 10/25] chore(openapi): sync generated spec --- docs/static/openapi/openapi.json | 1707 ++++++++++++++++++++++++++++++ 1 file changed, 1707 insertions(+) diff --git a/docs/static/openapi/openapi.json b/docs/static/openapi/openapi.json index 2d125bebc..22fbe93c3 100644 --- a/docs/static/openapi/openapi.json +++ b/docs/static/openapi/openapi.json @@ -2821,7 +2821,17 @@ "xai", "cohere", "minimax", + "minimax-cn", + "minimax-coding-plan", + "minimax-cn-coding-plan", "glm", + "zhipuai", + "zhipuai-coding-plan", + "zai", + "zai-coding-plan", + "moonshotai", + "moonshotai-cn", + "kimi-for-coding", "openrouter", "litellm", "glama", @@ -3152,7 +3162,17 @@ "xai", "cohere", "minimax", + "minimax-cn", + "minimax-coding-plan", + "minimax-cn-coding-plan", "glm", + "zhipuai", + "zhipuai-coding-plan", + "zai", + "zai-coding-plan", + "moonshotai", + "moonshotai-cn", + "kimi-for-coding", "openrouter", "litellm", "glama", @@ -4482,6 +4502,393 @@ "additionalProperties": false, "description": "Provider catalog entry with models and capabilities" }, + "minimax-cn": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "minimax-coding-plan": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "minimax-cn-coding-plan": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, "glm": { "type": "object", "properties": { @@ -4611,6 +5018,909 @@ "additionalProperties": false, "description": "Provider catalog entry with models and capabilities" }, + "zhipuai": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "zhipuai-coding-plan": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "zai": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "zai-coding-plan": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "moonshotai": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "moonshotai-cn": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "kimi-for-coding": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, "openrouter": { "type": "object", "properties": { @@ -5789,7 +7099,17 @@ "xai", "cohere", "minimax", + "minimax-cn", + "minimax-coding-plan", + "minimax-cn-coding-plan", "glm", + "zhipuai", + "zhipuai-coding-plan", + "zai", + "zai-coding-plan", + "moonshotai", + "moonshotai-cn", + "kimi-for-coding", "openrouter", "litellm", "glama", @@ -5896,7 +7216,17 @@ "xai", "cohere", "minimax", + "minimax-cn", + "minimax-coding-plan", + "minimax-cn-coding-plan", "glm", + "zhipuai", + "zhipuai-coding-plan", + "zai", + "zai-coding-plan", + "moonshotai", + "moonshotai-cn", + "kimi-for-coding", "openrouter", "litellm", "glama", @@ -6337,7 +7667,17 @@ "xai", "cohere", "minimax", + "minimax-cn", + "minimax-coding-plan", + "minimax-cn-coding-plan", "glm", + "zhipuai", + "zhipuai-coding-plan", + "zai", + "zai-coding-plan", + "moonshotai", + "moonshotai-cn", + "kimi-for-coding", "openrouter", "litellm", "glama", @@ -6385,7 +7725,17 @@ "xai", "cohere", "minimax", + "minimax-cn", + "minimax-coding-plan", + "minimax-cn-coding-plan", "glm", + "zhipuai", + "zhipuai-coding-plan", + "zai", + "zai-coding-plan", + "moonshotai", + "moonshotai-cn", + "kimi-for-coding", "openrouter", "litellm", "glama", @@ -7678,7 +9028,17 @@ "xai", "cohere", "minimax", + "minimax-cn", + "minimax-coding-plan", + "minimax-cn-coding-plan", "glm", + "zhipuai", + "zhipuai-coding-plan", + "zai", + "zai-coding-plan", + "moonshotai", + "moonshotai-cn", + "kimi-for-coding", "openrouter", "litellm", "glama", @@ -8481,7 +9841,17 @@ "xai", "cohere", "minimax", + "minimax-cn", + "minimax-coding-plan", + "minimax-cn-coding-plan", "glm", + "zhipuai", + "zhipuai-coding-plan", + "zai", + "zai-coding-plan", + "moonshotai", + "moonshotai-cn", + "kimi-for-coding", "openrouter", "litellm", "glama", @@ -8899,7 +10269,17 @@ "xai", "cohere", "minimax", + "minimax-cn", + "minimax-coding-plan", + "minimax-cn-coding-plan", "glm", + "zhipuai", + "zhipuai-coding-plan", + "zai", + "zai-coding-plan", + "moonshotai", + "moonshotai-cn", + "kimi-for-coding", "openrouter", "litellm", "glama", @@ -14094,7 +15474,17 @@ "xai", "cohere", "minimax", + "minimax-cn", + "minimax-coding-plan", + "minimax-cn-coding-plan", "glm", + "zhipuai", + "zhipuai-coding-plan", + "zai", + "zai-coding-plan", + "moonshotai", + "moonshotai-cn", + "kimi-for-coding", "openrouter", "litellm", "glama", @@ -14131,7 +15521,17 @@ "xai", "cohere", "minimax", + "minimax-cn", + "minimax-coding-plan", + "minimax-cn-coding-plan", "glm", + "zhipuai", + "zhipuai-coding-plan", + "zai", + "zai-coding-plan", + "moonshotai", + "moonshotai-cn", + "kimi-for-coding", "openrouter", "litellm", "glama", @@ -14194,7 +15594,17 @@ "xai", "cohere", "minimax", + "minimax-cn", + "minimax-coding-plan", + "minimax-cn-coding-plan", "glm", + "zhipuai", + "zhipuai-coding-plan", + "zai", + "zai-coding-plan", + "moonshotai", + "moonshotai-cn", + "kimi-for-coding", "openrouter", "litellm", "glama", @@ -14248,7 +15658,17 @@ "xai", "cohere", "minimax", + "minimax-cn", + "minimax-coding-plan", + "minimax-cn-coding-plan", "glm", + "zhipuai", + "zhipuai-coding-plan", + "zai", + "zai-coding-plan", + "moonshotai", + "moonshotai-cn", + "kimi-for-coding", "openrouter", "litellm", "glama", @@ -14279,6 +15699,293 @@ } } }, + "/api/llm/connect/providers": { + "get": { + "summary": "Connect Providers", + "description": "Lists curated providers and supported login methods for /connect.", + "tags": [ + "llm" + ], + "responses": { + "200": { + "description": "Provider/method catalog", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "providers": { + "type": "array", + "items": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "minLength": 1 + }, + "label": { + "type": "string", + "minLength": 1 + }, + "modelsDevProviderId": { + "type": "string", + "minLength": 1 + }, + "methods": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 1 + }, + "label": { + "type": "string", + "minLength": 1 + }, + "kind": { + "type": "string", + "enum": [ + "api_key", + "token", + "oauth", + "guidance" + ] + }, + "hint": { + "type": "string" + } + }, + "required": [ + "id", + "label", + "kind" + ], + "additionalProperties": false + }, + "minItems": 1 + } + }, + "required": [ + "providerId", + "label", + "methods" + ], + "additionalProperties": false + }, + "description": "Curated connect providers" + } + }, + "required": [ + "providers" + ], + "additionalProperties": false, + "description": "Connect providers response" + } + } + } + } + } + } + }, + "/api/llm/connect/profiles": { + "get": { + "summary": "Connect Profiles", + "description": "Lists saved provider auth profiles (redacted) and per-provider defaults.", + "tags": [ + "llm" + ], + "responses": { + "200": { + "description": "Profiles + defaults", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "defaults": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "providerId -> default profileId" + }, + "profiles": { + "type": "array", + "items": { + "type": "object", + "properties": { + "profileId": { + "type": "string", + "description": "Unique profile id" + }, + "providerId": { + "type": "string", + "description": "LLM provider id" + }, + "methodId": { + "type": "string", + "description": "Auth method id" + }, + "label": { + "type": "string", + "description": "Optional display label" + }, + "credentialType": { + "type": "string", + "enum": [ + "api_key", + "token", + "oauth" + ], + "description": "Credential type (redacted)" + }, + "createdAt": { + "type": "number", + "description": "Profile creation time (unix ms)" + }, + "updatedAt": { + "type": "number", + "description": "Profile last update time (unix ms)" + }, + "expiresAt": { + "type": "number", + "description": "Token expiry time (unix ms)" + } + }, + "required": [ + "profileId", + "providerId", + "methodId", + "credentialType", + "createdAt", + "updatedAt" + ], + "additionalProperties": false, + "description": "Redacted auth profile (no secrets)" + }, + "description": "Saved profiles (redacted)" + } + }, + "required": [ + "defaults", + "profiles" + ], + "additionalProperties": false, + "description": "Connect profiles response" + } + } + } + } + } + } + }, + "/api/llm/connect/profiles/{profileId}": { + "delete": { + "summary": "Delete Connect Profile", + "description": "Deletes a saved profile and clears defaults that reference it.", + "tags": [ + "llm" + ], + "parameters": [ + { + "schema": { + "type": "string", + "description": "Profile id to delete" + }, + "required": true, + "description": "Profile id to delete", + "name": "profileId", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Delete result", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "ok": { + "type": "boolean", + "description": "Whether the profile was deleted" + } + }, + "required": [ + "ok" + ], + "additionalProperties": false, + "description": "Delete profile response" + } + } + } + } + } + } + }, + "/api/llm/connect/defaults": { + "post": { + "summary": "Set Default Profile", + "description": "Sets the default profile for a provider (or clears it).", + "tags": [ + "llm" + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider id" + }, + "profileId": { + "type": "string", + "nullable": true, + "description": "Profile id to set as default (null clears the default)" + } + }, + "required": [ + "providerId", + "profileId" + ], + "additionalProperties": false, + "description": "Set default profile request body" + } + } + } + }, + "responses": { + "200": { + "description": "Default updated", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "ok": { + "type": "boolean", + "enum": [ + true + ], + "description": "Request succeeded" + } + }, + "required": [ + "ok" + ], + "additionalProperties": false, + "description": "Set default profile response" + } + } + } + } + } + } + }, "/api/tools": { "get": { "summary": "List All Tools", From 64dbc1d77912bdba0d0531198916a787a7bad63e Mon Sep 17 00:00:00 2001 From: Rahul Karajgikar <rahul@trytruffle.ai> Date: Wed, 18 Feb 2026 15:17:29 +0530 Subject: [PATCH 11/25] fix(auth): sanitize oauth errors + clientId checks --- .../agent-management/src/auth/llm-profiles.ts | 4 +- .../src/auth/runtime-auth-resolver.test.ts | 118 ++++++++++++++++++ .../src/auth/runtime-auth-resolver.ts | 85 ++++++++++--- packages/agent-management/src/index.ts | 1 - .../cli/commands/connect/minimax-portal.ts | 17 ++- .../src/cli/commands/connect/oauth-error.ts | 50 ++++++++ .../src/cli/commands/connect/openai-codex.ts | 20 ++- 7 files changed, 255 insertions(+), 40 deletions(-) create mode 100644 packages/cli/src/cli/commands/connect/oauth-error.ts diff --git a/packages/agent-management/src/auth/llm-profiles.ts b/packages/agent-management/src/auth/llm-profiles.ts index 01f60d003..6627a6cce 100644 --- a/packages/agent-management/src/auth/llm-profiles.ts +++ b/packages/agent-management/src/auth/llm-profiles.ts @@ -23,8 +23,8 @@ const STORE_DIR = 'auth'; const STORE_FILENAME = 'llm-profiles.json'; const FILE_MODE = 0o600; -const STORE_LOCK_TIMEOUT_MS = 5000; -const STORE_LOCK_STALE_MS = 60_000; +const STORE_LOCK_TIMEOUT_MS = 15_000; +const STORE_LOCK_STALE_MS = 15_000; const STORE_LOCK_RETRY_DELAY_MS = 50; export const LlmAuthCredentialSchema = z diff --git a/packages/agent-management/src/auth/runtime-auth-resolver.test.ts b/packages/agent-management/src/auth/runtime-auth-resolver.test.ts index ccf150260..e5fe83f75 100644 --- a/packages/agent-management/src/auth/runtime-auth-resolver.test.ts +++ b/packages/agent-management/src/auth/runtime-auth-resolver.test.ts @@ -156,7 +156,62 @@ describe('llm runtime auth resolver', () => { expect(calls[0]!.headers.get('x-api-key')).toBe('access-token'); }); + it('overlays init.headers on top of Request headers', async () => { + await upsertLlmAuthProfile({ + profileId: 'minimax:portal_oauth_cn', + providerId: 'minimax', + methodId: 'portal_oauth_cn', + credential: { + type: 'oauth', + accessToken: 'access-token', + refreshToken: 'refresh-token', + expiresAt: Date.now() + 60_000, + metadata: { region: 'cn' }, + }, + }); + await setDefaultLlmAuthProfile({ + providerId: 'minimax', + profileId: 'minimax:portal_oauth_cn', + }); + + const resolver = createDefaultLlmAuthResolver(); + const runtime = resolver.resolveRuntimeAuth({ provider: 'minimax', model: 'MiniMax-M2.1' }); + expect(typeof runtime?.fetch).toBe('function'); + + const calls: Array<{ url: string; headers: globalThis.Headers }> = []; + globalThis.fetch = (async (input: RequestInfo | URL, init?: RequestInit) => { + const url = + input instanceof URL + ? input.toString() + : typeof input === 'string' + ? input + : input.url; + calls.push({ url, headers: new globalThis.Headers(init?.headers) }); + return new Response('ok', { status: 200 }); + }) satisfies typeof fetch; + + const request = new globalThis.Request('https://example.com', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-Custom': 'old', + }, + body: JSON.stringify({ hello: 'world' }), + }); + + await runtime!.fetch!(request, { + headers: { 'X-Custom': 'new', 'x-api-key': 'placeholder' }, + }); + + expect(calls).toHaveLength(1); + expect(calls[0]!.headers.get('content-type')).toBe('application/json'); + expect(calls[0]!.headers.get('x-custom')).toBe('new'); + expect(calls[0]!.headers.get('x-api-key')).toBe('access-token'); + }); + it('refreshes minimax oauth tokens when expired', async () => { + delete process.env.DEXTO_MINIMAX_PORTAL_OAUTH_CLIENT_ID; + await upsertLlmAuthProfile({ profileId: 'minimax:portal_oauth_global', providerId: 'minimax', @@ -228,6 +283,69 @@ describe('llm runtime auth resolver', () => { } }); + it('dedupes concurrent minimax oauth refresh calls for the same profile', async () => { + delete process.env.DEXTO_MINIMAX_PORTAL_OAUTH_CLIENT_ID; + + await upsertLlmAuthProfile({ + profileId: 'minimax:portal_oauth_global', + providerId: 'minimax', + methodId: 'portal_oauth_global', + credential: { + type: 'oauth', + accessToken: 'stale-access', + refreshToken: 'stale-refresh', + expiresAt: Date.now() - 1, + metadata: { region: 'global', clientId: 'client-id' }, + }, + }); + await setDefaultLlmAuthProfile({ + providerId: 'minimax', + profileId: 'minimax:portal_oauth_global', + }); + + const resolver = createDefaultLlmAuthResolver(); + const runtime = resolver.resolveRuntimeAuth({ provider: 'minimax', model: 'MiniMax-M2.1' }); + expect(typeof runtime?.fetch).toBe('function'); + + let refreshCalls = 0; + const requestCalls: Array<{ url: string; headers: globalThis.Headers }> = []; + globalThis.fetch = (async (input: RequestInfo | URL, init?: RequestInit) => { + const url = + input instanceof URL + ? input.toString() + : typeof input === 'string' + ? input + : input.url; + + if (url === 'https://api.minimax.io/oauth/token') { + refreshCalls += 1; + await new Promise((resolve) => setTimeout(resolve, 50)); + return new Response( + JSON.stringify({ + status: 'success', + access_token: 'fresh-access', + refresh_token: 'fresh-refresh', + expired_in: 3600, + }), + { status: 200 } + ); + } + + requestCalls.push({ url, headers: new globalThis.Headers(init?.headers) }); + return new Response('ok', { status: 200 }); + }) satisfies typeof fetch; + + await Promise.all([ + runtime!.fetch!('https://example.com/one', { headers: { 'x-api-key': 'placeholder' } }), + runtime!.fetch!('https://example.com/two', { headers: { 'x-api-key': 'placeholder' } }), + ]); + + expect(refreshCalls).toBe(1); + expect(requestCalls).toHaveLength(2); + expect(requestCalls[0]!.headers.get('x-api-key')).toBe('fresh-access'); + expect(requestCalls[1]!.headers.get('x-api-key')).toBe('fresh-access'); + }); + it('refreshes openai oauth tokens using the stored clientId', async () => { delete process.env.DEXTO_OPENAI_CODEX_OAUTH_CLIENT_ID; diff --git a/packages/agent-management/src/auth/runtime-auth-resolver.ts b/packages/agent-management/src/auth/runtime-auth-resolver.ts index 4c931464e..6ecb84c48 100644 --- a/packages/agent-management/src/auth/runtime-auth-resolver.ts +++ b/packages/agent-management/src/auth/runtime-auth-resolver.ts @@ -139,15 +139,39 @@ function normalizeAnthropicBaseUrl(url: string): string { return `${trimmed}/v1`; } -function toSafeErrorText(text: string): string { - const trimmed = text.trim(); - if (!trimmed) return ''; - const singleLine = trimmed.replace(/\s+/g, ' '); - const maxLen = 500; +function toMiniMaxRegion(value: unknown): 'cn' | 'global' | null { + if (value === 'cn' || value === 'global') return value; + return null; +} + +function toShortSingleLineText(value: string, maxLen: number): string { + const singleLine = value.replace(/\s+/g, ' ').trim(); if (singleLine.length <= maxLen) return singleLine; return `${singleLine.slice(0, maxLen)}…`; } +function toWhitelistedOauthErrorText(payload: unknown): string | null { + if (typeof payload !== 'object' || payload === null) return null; + const record = payload as Record<string, unknown>; + + const parts: string[] = []; + function addField(key: string): void { + const value = record[key]; + if (typeof value !== 'string') return; + const trimmed = value.trim(); + if (!trimmed) return; + parts.push(`${key}: ${toShortSingleLineText(trimmed, 200)}`); + } + + addField('error'); + addField('error_description'); + addField('message'); + addField('status'); + addField('status_msg'); + + return parts.length > 0 ? parts.join(', ') : null; +} + async function refreshOpenAiOauthTokens(params: { refreshToken: string; clientIdFromProfile?: string | undefined; @@ -157,11 +181,20 @@ async function refreshOpenAiOauthTokens(params: { expiresAt: number; accountId: string | null; }> { - const clientId = - process.env.DEXTO_OPENAI_CODEX_OAUTH_CLIENT_ID?.trim() || - params.clientIdFromProfile?.trim(); + const clientIdFromProfile = params.clientIdFromProfile?.trim(); + const clientIdFromEnv = process.env.DEXTO_OPENAI_CODEX_OAUTH_CLIENT_ID?.trim(); + + if (clientIdFromProfile && clientIdFromEnv && clientIdFromProfile !== clientIdFromEnv) { + throw new Error( + 'OpenAI OAuth clientId mismatch between profile and DEXTO_OPENAI_CODEX_OAUTH_CLIENT_ID; reconnect or unset the env var.' + ); + } + + const clientId = clientIdFromProfile || clientIdFromEnv; if (!clientId) { - throw new Error('Missing DEXTO_OPENAI_CODEX_OAUTH_CLIENT_ID'); + throw new Error( + 'Missing OpenAI OAuth clientId (reconnect or set DEXTO_OPENAI_CODEX_OAUTH_CLIENT_ID)' + ); } const response = await fetch(`${OPENAI_AUTH_ISSUER}/oauth/token`, { @@ -177,9 +210,14 @@ async function refreshOpenAiOauthTokens(params: { if (!response.ok) { const text = await response.text().catch(() => ''); - const safe = toSafeErrorText(text); + let details: string | null = null; + try { + details = toWhitelistedOauthErrorText(JSON.parse(text) as unknown); + } catch { + details = null; + } throw new Error( - `OpenAI OAuth refresh failed (${response.status}): ${safe || response.statusText}` + `OpenAI OAuth refresh failed (${response.status}): ${details || response.statusText}` ); } @@ -220,11 +258,20 @@ async function refreshMiniMaxPortalOauthTokens(params: { resourceUrl?: string; notificationMessage?: string; }> { - const clientId = - process.env.DEXTO_MINIMAX_PORTAL_OAUTH_CLIENT_ID?.trim() || - params.clientIdFromProfile?.trim(); + const clientIdFromProfile = params.clientIdFromProfile?.trim(); + const clientIdFromEnv = process.env.DEXTO_MINIMAX_PORTAL_OAUTH_CLIENT_ID?.trim(); + + if (clientIdFromProfile && clientIdFromEnv && clientIdFromProfile !== clientIdFromEnv) { + throw new Error( + 'MiniMax OAuth clientId mismatch between profile and DEXTO_MINIMAX_PORTAL_OAUTH_CLIENT_ID; reconnect or unset the env var.' + ); + } + + const clientId = clientIdFromProfile || clientIdFromEnv; if (!clientId) { - throw new Error('Missing DEXTO_MINIMAX_PORTAL_OAUTH_CLIENT_ID'); + throw new Error( + 'Missing MiniMax OAuth clientId (reconnect or set DEXTO_MINIMAX_PORTAL_OAUTH_CLIENT_ID)' + ); } const baseUrl = params.region === 'cn' ? 'https://api.minimaxi.com' : 'https://api.minimax.io'; @@ -251,9 +298,9 @@ async function refreshMiniMaxPortalOauthTokens(params: { } if (!response.ok) { - const safe = toSafeErrorText(text); + const details = toWhitelistedOauthErrorText(payload); throw new Error( - `MiniMax OAuth refresh failed (${response.status}): ${safe || response.statusText}` + `MiniMax OAuth refresh failed (${response.status}): ${details || response.statusText}` ); } @@ -338,7 +385,7 @@ async function refreshOauthProfileIfNeeded(profile: LlmAuthProfile): Promise<Llm (latest.methodId === 'portal_oauth_global' || latest.methodId === 'portal_oauth_cn') ) { const region = - (latest.credential.metadata?.region as 'cn' | 'global' | undefined) ?? + toMiniMaxRegion(latest.credential.metadata?.region) ?? (latest.methodId === 'portal_oauth_cn' ? 'cn' : 'global'); const refreshed = await refreshMiniMaxPortalOauthTokens({ @@ -462,7 +509,7 @@ export function createDefaultLlmAuthResolver(): LlmAuthResolver { profile.methodId === 'portal_oauth_cn') ) { const region = - (profile.credential.metadata?.region as 'cn' | 'global' | undefined) ?? + toMiniMaxRegion(profile.credential.metadata?.region) ?? (profile.methodId === 'portal_oauth_cn' ? 'cn' : 'global'); const fallbackResourceUrl = diff --git a/packages/agent-management/src/index.ts b/packages/agent-management/src/index.ts index 2acbdc483..6eb01d5f3 100644 --- a/packages/agent-management/src/index.ts +++ b/packages/agent-management/src/index.ts @@ -103,7 +103,6 @@ export { getLlmAuthProfilesPath, loadLlmAuthProfilesStore, loadLlmAuthProfilesStoreSync, - saveLlmAuthProfilesStore, listLlmAuthProfiles, upsertLlmAuthProfile, deleteLlmAuthProfile, diff --git a/packages/cli/src/cli/commands/connect/minimax-portal.ts b/packages/cli/src/cli/commands/connect/minimax-portal.ts index a168eba92..07e838a25 100644 --- a/packages/cli/src/cli/commands/connect/minimax-portal.ts +++ b/packages/cli/src/cli/commands/connect/minimax-portal.ts @@ -1,5 +1,7 @@ import { createHash, randomBytes, randomUUID } from 'node:crypto'; +import { formatOauthHttpError } from './oauth-error.js'; + export type MiniMaxRegion = 'cn' | 'global'; const MINIMAX_SCOPE = 'group_id profile model.completion'; @@ -74,10 +76,8 @@ export async function loginMiniMaxPortalDeviceCode(options: { }); if (!codeRes.ok) { - const text = await codeRes.text().catch(() => ''); - throw new Error( - `MiniMax OAuth init failed (${codeRes.status}): ${text || codeRes.statusText}` - ); + const text = await formatOauthHttpError(codeRes); + throw new Error(`MiniMax OAuth init failed: ${text}`); } const oauth = (await codeRes.json()) as { @@ -150,8 +150,13 @@ export async function loginMiniMaxPortalDeviceCode(options: { const payload = parsePayload(text); if (!res.ok) { - const msg = payload?.base_resp?.status_msg ?? text ?? res.statusText; - throw new Error(`MiniMax OAuth token poll failed (${res.status}): ${msg}`); + const msg = + typeof payload?.base_resp?.status_msg === 'string' + ? payload.base_resp.status_msg.trim() + : ''; + throw new Error( + `MiniMax OAuth token poll failed (${res.status}): ${msg || res.statusText}` + ); } const status: string | undefined = payload?.status; diff --git a/packages/cli/src/cli/commands/connect/oauth-error.ts b/packages/cli/src/cli/commands/connect/oauth-error.ts new file mode 100644 index 000000000..16775e45d --- /dev/null +++ b/packages/cli/src/cli/commands/connect/oauth-error.ts @@ -0,0 +1,50 @@ +function toShortSingleLineText(value: string, maxLen: number): string { + const singleLine = value.replace(/\s+/g, ' ').trim(); + if (singleLine.length <= maxLen) return singleLine; + return `${singleLine.slice(0, maxLen)}…`; +} + +function toWhitelistedOauthErrorText(payload: unknown): string | null { + if (typeof payload !== 'object' || payload === null) return null; + const record = payload as Record<string, unknown>; + + const parts: string[] = []; + function addField(key: string): void { + const value = record[key]; + if (typeof value !== 'string') return; + const trimmed = value.trim(); + if (!trimmed) return; + parts.push(`${key}: ${toShortSingleLineText(trimmed, 200)}`); + } + + addField('error'); + addField('error_description'); + addField('message'); + addField('status'); + addField('status_msg'); + + return parts.length > 0 ? parts.join(', ') : null; +} + +export async function formatOauthHttpError(response: Response): Promise<string> { + const statusLine = `${response.status} ${response.statusText}`.trim(); + + let text = ''; + try { + text = await response.text(); + } catch { + text = ''; + } + + if (!text.trim()) return statusLine; + + try { + const payload = JSON.parse(text) as unknown; + const details = toWhitelistedOauthErrorText(payload); + if (details) return `${statusLine}: ${details}`; + } catch { + // ignore parse errors + } + + return statusLine; +} diff --git a/packages/cli/src/cli/commands/connect/openai-codex.ts b/packages/cli/src/cli/commands/connect/openai-codex.ts index 8a1acaad9..c97b73dce 100644 --- a/packages/cli/src/cli/commands/connect/openai-codex.ts +++ b/packages/cli/src/cli/commands/connect/openai-codex.ts @@ -1,3 +1,5 @@ +import { formatOauthHttpError } from './oauth-error.js'; + const OPENAI_AUTH_ISSUER = 'https://auth.openai.com'; const DEVICE_CODE_URL = `${OPENAI_AUTH_ISSUER}/codex/device`; @@ -78,10 +80,8 @@ export async function loginOpenAiCodexDeviceCode(options: { }); if (!deviceResponse.ok) { - const text = await deviceResponse.text().catch(() => ''); - throw new Error( - `OpenAI device auth init failed (${deviceResponse.status}): ${text || deviceResponse.statusText}` - ); + const text = await formatOauthHttpError(deviceResponse); + throw new Error(`OpenAI device auth init failed: ${text}`); } const deviceData = (await deviceResponse.json()) as { @@ -131,10 +131,8 @@ export async function loginOpenAiCodexDeviceCode(options: { continue; } - const text = await response.text().catch(() => ''); - throw new Error( - `OpenAI device auth poll failed (${response.status}): ${text || response.statusText}` - ); + const text = await formatOauthHttpError(response); + throw new Error(`OpenAI device auth poll failed: ${text}`); } throw new Error('OpenAI device auth timed out waiting for authorization'); @@ -158,10 +156,8 @@ export async function loginOpenAiCodexDeviceCode(options: { }); if (!tokenResponse.ok) { - const text = await tokenResponse.text().catch(() => ''); - throw new Error( - `OpenAI token exchange failed (${tokenResponse.status}): ${text || tokenResponse.statusText}` - ); + const text = await formatOauthHttpError(tokenResponse); + throw new Error(`OpenAI token exchange failed: ${text}`); } const tokens = (await tokenResponse.json()) as { From c3b74b6433422e07f1120bc9d82383f4734d0a1f Mon Sep 17 00:00:00 2001 From: Rahul Karajgikar <rahul@trytruffle.ai> Date: Wed, 18 Feb 2026 18:58:14 +0530 Subject: [PATCH 12/25] docs(feature-plans): rebase oauth plan direction --- .../oauth-and-more-providers/PLAN.md | 43 +++++- .../PROVIDER_COVERAGE.md | 12 +- .../UPDATED_DIRECTION.md | 128 ++++++++++++++++++ .../USER_VERIFICATION.md | 5 +- .../WORKING_MEMORY.md | 27 ++-- 5 files changed, 195 insertions(+), 20 deletions(-) create mode 100644 feature-plans/oauth-and-more-providers/UPDATED_DIRECTION.md diff --git a/feature-plans/oauth-and-more-providers/PLAN.md b/feature-plans/oauth-and-more-providers/PLAN.md index acf75485e..dad0a7203 100644 --- a/feature-plans/oauth-and-more-providers/PLAN.md +++ b/feature-plans/oauth-and-more-providers/PLAN.md @@ -6,9 +6,13 @@ This plan updates Dexto onboarding/login flows to support **multiple login metho **Owner verification list:** [`USER_VERIFICATION.md`](./USER_VERIFICATION.md) tracks **owner-only** decisions and manual checks we deliberately defer while implementing. **Add an entry whenever you discover an unresolved decision or an environment-dependent verification.** Clear the list before shipping. +**Direction update (2026-02-18):** [`UPDATED_DIRECTION.md`](./UPDATED_DIRECTION.md) captures verified upstream observations (OpenRouter catalog completeness, no release-date filtering in OpenCode) and the updated direction (pi-style multi-source registry + transport mapping). + Primary references: - **OpenClaw** (`~/Projects/external/openclaw`) — onboarding wizard + auth profiles + provider auth plugins. - **OpenCode** (`~/Projects/external/opencode`) — `/connect` UX + models.dev-backed provider catalog + plugin auth methods. +- **pi-mono** (`~/Projects/external/pi-mono`) — model registry generation (multi-source) + explicit `api`/transport discriminators. +- **models.dev** (`~/Projects/external/models.dev`) — provider/model metadata source (and clarifies when catalogs are curated vs exhaustive). - Provider coverage snapshot (exact provider IDs): [`PROVIDER_COVERAGE.md`](./PROVIDER_COVERAGE.md) --- @@ -54,6 +58,7 @@ Known complications / gaps: - OAuth tokens should be refreshable without forcing the user to re-login. - The LLM factory should be able to apply provider-specific runtime options (headers/fetch/baseURL) depending on the active auth method. - Keep **models.dev as the model registry source of truth** (we already do). +- **Additionally ingest gateway catalogs** (starting with OpenRouter `/models`) during sync, because models.dev may intentionally curate gateway providers. - Use models.dev metadata to reduce churn when expanding supported providers/models (connect UI list, env-var expectations, curated defaults). --- @@ -493,21 +498,21 @@ Implementation note (important): ### Phase 1 — Scaffolding + API surface (API keys + profile plumbing) > **Goal:** ship a first working `/connect` for API-key methods + a stable server API surface for WebUI parity. -- [ ] **1.1 Add LLM profile store in `@dexto/agent-management`** +- [x] **1.1 Add LLM profile store in `@dexto/agent-management`** - Deliverables: - Read/write `llm-profiles.json` (or chosen store) with `0o600` files and atomic writes. - List/upsert/delete profiles; set per-provider default. - Exit: - Unit coverage for parsing + write safety + basic CRUD. -- [ ] **1.2 Add server routes for methods/profiles/defaults/status** +- [x] **1.2 Add server routes for methods/profiles/defaults/status** - Deliverables: - Hono routes in `packages/server/src/hono/routes/` for methods, profiles, defaults, status. - Keep `/llm/key` working; decide whether to alias/migrate it. - Exit: - Routes return stable JSON shapes and secrets are never returned. -- [ ] **1.3 Add CLI interactive `/connect` (API key methods first)** +- [x] **1.3 Add CLI interactive `/connect` (API key methods first)** - Deliverables: - New interactive command in `packages/cli/src/cli/commands/interactive-commands/`. - Flow: choose provider → choose method → complete method → set default. @@ -515,12 +520,44 @@ Implementation note (important): - Exit: - Manual CLI smoke: connect an API-key provider, set default, and confirm Dexto can run using it. +- [ ] **1.3.1 Finish multi-profile UX (no overwrite)** + - Deliverables: + - `/connect` can create **multiple profiles per provider+method** (prompt for a label, generate a unique `profileId`, and do not overwrite existing credentials). + - `/connect` can list existing profiles for a provider and switch the default without re-auth. + - `/connect` can delete a profile (and clears defaults that point at it). + - Exit: + - Manual CLI smoke: connect the same provider twice (two profiles), switch defaults, run each successfully. + - [ ] **1.4 Route `dexto setup` through the same connect logic** - Deliverables: - `dexto setup` reuses `/connect` internals rather than duplicating provider auth prompts. - Exit: - Setup path still works for Dexto login and at least one BYOK provider. +### Phase 1.5 — Model/provider registry sources (models.dev + gateway catalogs) +> **Goal:** make our catalog source choices explicit (pi-style), and ensure “gateway providers” are not artificially limited by models.dev curation. + +- [ ] **1.5.1 Generate a provider snapshot from models.dev (offline, committed)** + - Deliverables: + - Extend the sync script to output a `providers.generated.ts` snapshot (provider id/name/env/doc/npm/api). + - Consume this snapshot for `/connect` provider metadata (labels, env hints, docs links), so the connect UI isn’t hand-maintained. + - Exit: + - Regenerated snapshots are stable and reviewed in git; no secrets. + +- [ ] **1.5.2 Ingest OpenRouter live model catalog during sync** + - Deliverables: + - During `sync-llm-*`, fetch OpenRouter’s live `/models` and merge it into our OpenRouter model list. + - Define merge precedence for shared fields (context length, pricing, etc.) and how we represent models missing metadata. + - Exit: + - Our OpenRouter model picker/catalog can include models that exist in OpenRouter but not in models.dev. + +- [ ] **1.5.3 Decide/implement “ancient model” visibility as a scope (optional)** + - Deliverables: + - Add an explicit “hide deprecated/hide old” scope to catalog endpoints/pickers (do not assume upstream filtering). + - Use `status === "deprecated"` where present; optionally use `release_date`/`last_updated` thresholds for models.dev-derived catalogs. + - Exit: + - UX can opt into a time-window filter without losing access to older IDs (still selectable via search / explicit ID). + ### Phase 2 — Provider presets + “more providers” foundation (MiniMax / Z.AI / Moonshot / Kimi) > **Goal:** make these providers connectable + runnable with minimal per-provider work, leveraging models.dev metadata and OpenAI-compatible presets where possible. diff --git a/feature-plans/oauth-and-more-providers/PROVIDER_COVERAGE.md b/feature-plans/oauth-and-more-providers/PROVIDER_COVERAGE.md index 051254d84..0ee74b8b3 100644 --- a/feature-plans/oauth-and-more-providers/PROVIDER_COVERAGE.md +++ b/feature-plans/oauth-and-more-providers/PROVIDER_COVERAGE.md @@ -1,12 +1,13 @@ # Provider Coverage Snapshot (Dexto vs OpenClaw vs OpenCode) -Date: **2026-02-17** +Date: **2026-02-18** This file is a concrete snapshot of **provider IDs** across the three relevant codebases, so we can reason about “what can be supported” without hand-waving. Notes: - This is intentionally “flat”: it lists IDs, not UX, auth methods, or transports. - OpenCode’s list is primarily **models.dev provider IDs** (which is why it’s huge). +- models.dev’s **gateway provider** catalogs (notably OpenRouter) can be intentionally curated; consumers like OpenCode will not necessarily show OpenRouter’s full live `/models` surface. - OpenClaw and OpenCode can support additional “custom providers” via config; those are not enumerable and are not included here. --- @@ -98,14 +99,14 @@ codex-cli ## OpenCode (reference) -Source of truth (base list): models.dev provider IDs (as of 2026-02-17): `https://models.dev/api.json` +Source of truth (base list): models.dev provider IDs (as of 2026-02-18): `https://models.dev/api.json` Additional OpenCode-specific provider IDs: - OpenCode adds `github-copilot-enterprise` by cloning the models.dev `github-copilot` provider: - `~/Projects/external/opencode/packages/opencode/src/provider/provider.ts` (search for “Copilot Enterprise”) -Count (models.dev providers): **91** -Count (OpenCode effective providers incl. enterprise): **92** +Count (models.dev providers): **94** +Count (OpenCode effective providers incl. enterprise): **95** ```text 302ai @@ -122,6 +123,7 @@ baseten berget cerebras chutes +cloudferro-sherlock cloudflare-ai-gateway cloudflare-workers-ai cohere @@ -176,6 +178,8 @@ ovhcloud perplexity poe privatemode-ai +qihang-ai +qiniu-ai requesty sap-ai-core scaleway diff --git a/feature-plans/oauth-and-more-providers/UPDATED_DIRECTION.md b/feature-plans/oauth-and-more-providers/UPDATED_DIRECTION.md new file mode 100644 index 000000000..70dc1bd38 --- /dev/null +++ b/feature-plans/oauth-and-more-providers/UPDATED_DIRECTION.md @@ -0,0 +1,128 @@ +# Updated Direction — OAuth + Provider Catalog Revamp + +Date: **2026-02-18** + +This is an addendum to [`PLAN.md`](./PLAN.md). It captures key insights discovered after Phase 1 scaffolding landed, and updates the direction for achieving “pi parity” (broad provider/model coverage) without re-architecting the system. + +## 1) Key Verifications (OpenCode + models.dev) + +### 1.1 No “last 6 months” model filtering in current OpenCode + +What OpenCode actually does today: +- Model picker shows **Favorites** and **Recent (last used)** sections, and hides models with `status === "deprecated"`. + - Source: `~/Projects/external/opencode/packages/opencode/src/cli/cmd/tui/component/dialog-model.tsx` + +What we did *not* find: +- Any OpenCode or models.dev code that filters the catalog by `release_date` (eg “only show models released in the last 6 months”). + - models.dev web UI only supports search + sort; no time-window filter: + - Source: `~/Projects/external/models.dev/packages/web/src/index.ts` + +> If we want a “hide ancient models” UX, we should implement it explicitly (likely as an optional scope in our catalog endpoints), not assume it exists upstream. + +### 1.2 OpenCode’s OpenRouter model list is incomplete because models.dev is curated + +OpenCode’s provider catalog is derived from models.dev (`https://models.dev/api.json`), not OpenRouter’s live `/models` endpoint: +- Source: `~/Projects/external/opencode/packages/opencode/src/provider/models.ts` +- Source: `~/Projects/external/opencode/packages/opencode/src/server/routes/provider.ts` + +**Implication:** OpenCode can only show the subset of OpenRouter models that models.dev tracks. + +Concrete example (verified): +- OpenRouter live catalog includes `openai/gpt-3.5-turbo-0613` (`https://openrouter.ai/api/v1/models`). +- models.dev’s OpenRouter provider does **not** include that model (`https://models.dev/api.json`). + +Also, models.dev’s OpenRouter provider is a committed TOML snapshot: +- Source: `~/Projects/external/models.dev/providers/openrouter/provider.toml` +- Source: `~/Projects/external/models.dev/providers/openrouter/models/` + +So: “OpenCode doesn’t list some OpenRouter models” is not a transport limitation; it’s a **catalog source** choice. + +## 2) Direction: Follow pi’s “multi-source model registry” approach + +pi does not rely on a single upstream catalog. It generates a merged model list from multiple sources: +- models.dev fetch + normalization +- OpenRouter fetch + normalization +- Additional gateway catalogs (eg “AI Gateway”) fetch + normalization + +Reference: +- `~/Projects/external/pi-mono/packages/ai/scripts/generate-models.ts` + +We should adopt the same idea in Dexto’s sync pipeline: + +### 2.1 Keep models.dev as the baseline for direct providers + +models.dev is still valuable for: +- provider IDs + names + env var hints + docs links +- cross-provider model metadata (modalities, tool-call, pricing, context) + +### 2.2 Additionally ingest gateway catalogs (starting with OpenRouter) + +We should treat gateway catalogs as their own sources, because models.dev may be intentionally curated. + +For Dexto, the immediate high-value source is: +- OpenRouter live model catalog (`https://openrouter.ai/api/v1/models`) + +Notes: +- Dexto already has a runtime OpenRouter validator/cache (TTL + throttle) at: + - `packages/core/src/llm/providers/openrouter-model-registry.ts` +- That runtime cache is great for “is this ID valid?”, but it doesn’t automatically improve our *static* model picker/catalog unless we integrate it into our registry generation or expose it as a dynamic catalog endpoint. + +## 3) “Minimal transports” is still a viable base (with a clear path to pi parity) + +The earlier “minimal transports” statement refers to the **request-shape layer** (which SDK surface we target), not the size of the model catalog. + +We can keep the initial transport set small while preserving a path to pi-style parity: + +### 3.1 Add a stable internal transport discriminator (extensible) + +pi uses an explicit `api` discriminator (eg `"openai-completions"`, `"openai-responses"`, `"anthropic-messages"`, …) and then routes to a small set of adapters. +- Source: `~/Projects/external/pi-mono/packages/ai/src/types.ts` + +In Dexto, we can do the same with a small internal `TransportKind` (or `ApiKind`) used by our LLM factory: +- Start small (enough for most providers): OpenAI Chat, OpenAI Responses, Anthropic, Google, OpenRouter, Bedrock, Vertex. +- Add additional kinds incrementally (Azure, Copilot, etc.) without changing the overall architecture. + +### 3.2 Use `models.dev provider.npm` as the *default* transport hint (not the whole truth) + +models.dev has a provider-level `npm` field that indicates the intended Vercel AI SDK provider package. +- This is a strong default for transport selection. +- It’s not sufficient for all edge cases (some providers need custom headers, region logic, or per-model routing). + +pi demonstrates this exact pattern: +- For OpenCode Zen models, they map `model.provider.npm` → `api` and then still add special-case routing where needed. + - Source: `~/Projects/external/pi-mono/packages/ai/scripts/generate-models.ts` + +## 4) Phase 1 recap (already implemented) + remaining gaps + +### 4.1 Implemented in this repo (Phase 1 scaffolding) + +Shipped building blocks: +- Core runtime auth contract: + - `packages/core/src/llm/auth/types.ts` +- Multi-profile store + defaults: + - `packages/agent-management/src/auth/llm-profiles.ts` +- Runtime resolver that converts the active profile into request overrides (apiKey/headers/baseURL/fetch) and handles token refresh logic: + - `packages/agent-management/src/auth/runtime-auth-resolver.ts` +- Server surface for connect providers + redacted profiles/defaults: + - `packages/server/src/hono/routes/llm-connect.ts` +- CLI interactive `/connect`: + - `packages/cli/src/cli/commands/connect/index.ts` + +### 4.2 Known follow-up gaps + +- `/connect` currently overwrites credentials because `profileId` is fixed to `${providerId}:${methodId}`: + - Source: `packages/cli/src/cli/commands/connect/index.ts` + - We need true multi-profile support (prompt for profile label/name, generate stable IDs, and allow switching defaults without re-auth). + +## 5) Changes this implies for the tasklist + +We should update the plan’s next phases to include: +- Multi-profile UX completion (create multiple profiles; switch active; delete). +- Sync pipeline changes: + - ingest gateway catalogs (OpenRouter first) in `sync-llm-*` + - generate a provider snapshot (name/env/doc/npm/api) for `/connect` and onboarding + - keep model snapshot generation separate from gateway live validation +- LLM factory refactor: + - table-driven “boring providers” based on `npm` + `api` baseURL + - keep explicit code only for real exceptions (dexto-nova, openrouter, bedrock, vertex, oauth URL rewrites, local/ollama) + diff --git a/feature-plans/oauth-and-more-providers/USER_VERIFICATION.md b/feature-plans/oauth-and-more-providers/USER_VERIFICATION.md index 51c7588ac..5536884ea 100644 --- a/feature-plans/oauth-and-more-providers/USER_VERIFICATION.md +++ b/feature-plans/oauth-and-more-providers/USER_VERIFICATION.md @@ -18,18 +18,19 @@ | ID | Item | Why owner-only | Target phase | Status | Notes | |----|------|----------------|--------------|--------|-------| -| UV-1 | Auth storage layout (new `~/.dexto/auth/`) | Security posture + UX permanence | 0.1 | Open | Confirm final on-disk layout + permissions + atomic write strategy for `dexto.json` + `llm-profiles.json`. | +| UV-1 | Auth storage layout (new `~/.dexto/auth/`) | Security posture + UX permanence | 0.1 | Open | Implemented file-backed `~/.dexto/auth/llm-profiles.json` with `0o600` + atomic writes; confirm layout + naming + any migration story. | | UV-2 | OAuth app credentials + allowlisting (OpenAI Codex) | Requires external app registration + product comms | 3.1 | Open | We need Dexto-owned OpenAI OAuth client ID + registered redirect URIs; Codex OAuth may require allowlisting. Decide how we message failure + fallback to API key. | | UV-3 | OAuth app credentials (MiniMax Portal) | Requires external app registration or explicit provider confirmation | 4.1 | Open | OpenClaw hardcodes a client ID; confirm whether we must register our own, or whether a public client ID is intended for third-party use. | | UV-4 | Provider identity strategy (models.dev vs Dexto IDs) | Product naming + config compatibility | 0.2 | Open | Decide whether to align user-facing IDs with models.dev (`moonshotai`, `zhipuai`, `zai`, `minimax-cn`, `kimi-for-coding`, …) vs keep Dexto-local IDs (`glm`, `minimax`) with aliases. | | UV-5 | Env var mapping for Z.AI / GLM | User expectation + migration risk | 0.2 | Open | models.dev uses `ZHIPU_API_KEY` for `zai`; OpenClaw uses `ZAI_API_KEY` / `Z_AI_API_KEY`. Decide which to accept and which to display as the “primary” hint. | | UV-6 | MiniMax transport defaults (OpenAI-compatible vs Anthropic-compatible) | Impacts runtime correctness + preset design | 2.2 | Open | Dexto today assumes OpenAI-compatible (`api.minimax.chat`), while models.dev indicates Anthropic-compatible (`api.minimax.io/anthropic/v1`). Decide default + how we expose variants. | -| UV-7 | Models.dev provider metadata ingestion strategy | Impacts offline behavior + maintenance | 2.3 | Open | Decide whether we snapshot provider metadata at build-time (generated file) vs fetch+cache at runtime for `/connect` provider list + presets. | +| UV-7 | Provider + gateway catalog ingestion strategy | Impacts offline behavior + maintenance + UX | 1.5 | Open | Decide build-time snapshot vs runtime fetch+cache for: (a) models.dev provider metadata (name/env/doc/npm/api), and (b) gateway model catalogs (OpenRouter live `/models` vs models.dev curated list). | | UV-8 | Resolution precedence surface | UX + “magic” risk | 0.4 | Open | Decide hardcoded precedence vs store-driven order; decide whether precedence lives in `llm-profiles` vs agent config; decide `llm.authProfileId` in v1. | | UV-9 | Anthropic setup-token viability + ship criteria | External dependency + potential policy constraints | 5.2 | Open | Implement until infeasible; decide whether this is “experimental” and how we disable quickly if it breaks/gets blocked. | | UV-10 | Manual smoke: `/connect` UX | Requires local interactive runs | Phase 1+ | Open | Verify connect flow UX: create/switch default profiles, no secret leakage, file permissions are correct. | | UV-11 | Manual smoke: OpenAI OAuth runtime behavior | Requires real OAuth account + network | Phase 3 | Open | Verify token refresh + request rewrite works end-to-end (including Responses API behavior). | | UV-12 | Manual smoke: WebUI parity | Requires running WebUI | Phase 7 | Open | Verify WebUI reflects method-based auth and doesn’t regress existing API key settings. | +| UV-13 | “Ancient model” visibility policy | Product UX / defaults | 1.5.3 | Open | Decide whether we should ship an explicit time-window filter (eg “hide models older than X months”), and if so, which metadata to trust (`release_date`, `last_updated`, `status`). | --- diff --git a/feature-plans/oauth-and-more-providers/WORKING_MEMORY.md b/feature-plans/oauth-and-more-providers/WORKING_MEMORY.md index 7b8b27eaf..0dc791476 100644 --- a/feature-plans/oauth-and-more-providers/WORKING_MEMORY.md +++ b/feature-plans/oauth-and-more-providers/WORKING_MEMORY.md @@ -18,22 +18,23 @@ ## Current Task -**Task:** **Owner verification — UV-1..UV-* (plan gate)** +**Task:** **Owner review — Updated direction + tasklist rebase** **Status:** _Waiting on owner_ **Branch:** `oauth-provider-revamp` ### Plan -- Review `feature-plans/oauth-and-more-providers/USER_VERIFICATION.md` and resolve key decisions (storage layout, provider ID strategy, config surface). -- Once UV items are cleared (or explicitly deferred), start Phase 0 tasks in `PLAN.md`. +- Review the direction update in `feature-plans/oauth-and-more-providers/UPDATED_DIRECTION.md`. +- Confirm the rebaselined tasklist in `feature-plans/oauth-and-more-providers/PLAN.md` (new Phase 1.5 for gateway catalogs; fix `/connect` multi-profile overwrite). +- Once aligned, proceed with **1.3.1** (multi-profile UX) and **1.5.2** (OpenRouter live catalog ingestion) in that order. ### Notes _Log findings, issues, and progress here as you work._ -2026-02-17: -- Imported the OAuth provider plan into this worktree and refactored it to the `PLAN.md` + `WORKING_MEMORY.md` + `USER_VERIFICATION.md` paradigm. -- Tasklist re-written with numbered tasks and explicit exit criteria. -- Read through OpenCode/OpenClaw reference implementations and updated `PLAN.md` with concrete file-path pointers for OAuth flows, storage shapes, and two-phase authorize/callback APIs. -- Pulled concrete models.dev provider metadata (provider IDs, base URLs, env vars, recommended SDKs) and updated `PLAN.md` to include an actionable diff for MiniMax / Z.AI / Zhipu / Moonshot / Kimi Code. Key finding: models.dev treats MiniMax + Kimi Code as **Anthropic-compatible**, while Dexto today assumes MiniMax is OpenAI-compatible. +2026-02-18: +- Verified OpenCode has **no release-date (“last 6 months”) catalog filter**; the picker is Favorites + Recent (last used) and hides deprecated models. +- Verified OpenCode’s OpenRouter model list is **limited by models.dev curation** (not OpenRouter’s live `/models`). +- Added `UPDATED_DIRECTION.md` and updated `PLAN.md` to adopt a pi-style multi-source model registry direction (models.dev baseline + gateway catalogs, starting with OpenRouter). +- Phase 1 scaffolding exists in-repo (profiles store + runtime resolver + server routes + CLI `/connect`), but `/connect` still overwrites profiles because `profileId` is fixed to `${providerId}:${methodId}`. --- @@ -59,7 +60,10 @@ _Move tasks here after completion. Keep a brief log of what was done and any dev | Task | Title | Date | Notes | |------|-------|------|-------| -| _TBD_ | | | | +| 1.1 | LLM profile store (`llm-profiles.json`) | 2026-02-18 | Implemented file-backed multi-profile store + defaults + tests. | +| 1.2 | Server routes for connect providers/profiles/defaults | 2026-02-18 | Added `packages/server/src/hono/routes/llm-connect.ts` (redacted profiles). | +| 1.3 | CLI interactive `/connect` | 2026-02-18 | Added `/connect` flow + initial OAuth method scaffolding; still needs multi-profile IDs. | +| — | Direction + tasklist rebase | 2026-02-18 | Added `UPDATED_DIRECTION.md`; updated tasklist to include gateway catalog ingestion. | --- @@ -67,8 +71,9 @@ _Move tasks here after completion. Keep a brief log of what was done and any dev | Phase | Status | Notes | |-------|--------|-------| -| Phase 0 — Decisions + interface design | Not started | — | -| Phase 1 — Scaffolding + API surface | Not started | — | +| Phase 0 — Decisions + interface design | Partial | Several decisions are implemented but still tracked in `USER_VERIFICATION.md` for owner confirmation. | +| Phase 1 — Scaffolding + API surface | Completed | Profiles store + runtime resolver + server routes + CLI `/connect` landed. | +| Phase 1.5 — Model/provider registry sources | Not started | Add OpenRouter live catalog ingestion + provider snapshot generation. | | Phase 2 — Provider presets + more providers | Not started | — | | Phase 3 — OpenAI ChatGPT OAuth (Codex) | Not started | — | | Phase 4 — MiniMax Portal OAuth | Not started | — | From 65e484fb155bd9de76746cd7d72b1411b0f302f0 Mon Sep 17 00:00:00 2001 From: Rahul Karajgikar <rahul@trytruffle.ai> Date: Wed, 18 Feb 2026 19:43:56 +0530 Subject: [PATCH 13/25] docs(feature-plans): add gateway catalog ingestion --- .../oauth-and-more-providers/PLAN.md | 19 ++++++++++++++- .../UPDATED_DIRECTION.md | 23 +++++++++++++++++-- .../USER_VERIFICATION.md | 2 +- .../WORKING_MEMORY.md | 2 +- 4 files changed, 41 insertions(+), 5 deletions(-) diff --git a/feature-plans/oauth-and-more-providers/PLAN.md b/feature-plans/oauth-and-more-providers/PLAN.md index dad0a7203..f803b976c 100644 --- a/feature-plans/oauth-and-more-providers/PLAN.md +++ b/feature-plans/oauth-and-more-providers/PLAN.md @@ -547,11 +547,28 @@ Implementation note (important): - [ ] **1.5.2 Ingest OpenRouter live model catalog during sync** - Deliverables: - During `sync-llm-*`, fetch OpenRouter’s live `/models` and merge it into our OpenRouter model list. + - Reference implementation: `~/Projects/external/pi-mono/packages/ai/scripts/generate-models.ts` (`fetchOpenRouterModels()`) - Define merge precedence for shared fields (context length, pricing, etc.) and how we represent models missing metadata. + - Prefer a deterministic merge strategy that preserves a path to “all models”: + - Use models.dev as the baseline metadata (modalities, attachment, tool_call, etc.) when present. + - Use OpenRouter live for completeness (model existence), `context_length`, and pricing. + - De-dupe by model ID; keep the first-seen model as authoritative (pi’s approach: models.dev takes priority, gateway fills gaps). + - Reference: `~/Projects/external/pi-mono/packages/ai/scripts/generate-models.ts` (dedup section). - Exit: - Our OpenRouter model picker/catalog can include models that exist in OpenRouter but not in models.dev. -- [ ] **1.5.3 Decide/implement “ancient model” visibility as a scope (optional)** +- [ ] **1.5.3 Ingest Vercel AI Gateway live model catalog during sync** + - Deliverables: + - During `sync-llm-*`, fetch Vercel AI Gateway’s live model catalog and merge it into the `vercel` provider model list. + - Endpoint (as used by pi): `https://ai-gateway.vercel.sh/v1/models` + - Reference implementation: `~/Projects/external/pi-mono/packages/ai/scripts/generate-models.ts` (`fetchAiGatewayModels()`) + - Filter to “agent-capable” models for curated pickers by default: + - pi’s heuristic: include only models whose `tags` include `tool-use`. + - Normalize metadata into our registry shape (pricing per 1M tokens, supported file types, context/max tokens). + - Exit: + - Dexto can surface Vercel AI Gateway models in the catalog without relying on models.dev’s snapshot (and can track deltas over time). + +- [ ] **1.5.4 Decide/implement “ancient model” visibility as a scope (optional)** - Deliverables: - Add an explicit “hide deprecated/hide old” scope to catalog endpoints/pickers (do not assume upstream filtering). - Use `status === "deprecated"` where present; optionally use `release_date`/`last_updated` thresholds for models.dev-derived catalogs. diff --git a/feature-plans/oauth-and-more-providers/UPDATED_DIRECTION.md b/feature-plans/oauth-and-more-providers/UPDATED_DIRECTION.md index 70dc1bd38..258682eda 100644 --- a/feature-plans/oauth-and-more-providers/UPDATED_DIRECTION.md +++ b/feature-plans/oauth-and-more-providers/UPDATED_DIRECTION.md @@ -42,7 +42,7 @@ So: “OpenCode doesn’t list some OpenRouter models” is not a transport limi pi does not rely on a single upstream catalog. It generates a merged model list from multiple sources: - models.dev fetch + normalization - OpenRouter fetch + normalization -- Additional gateway catalogs (eg “AI Gateway”) fetch + normalization +- Additional gateway catalogs (eg Vercel AI Gateway) fetch + normalization Reference: - `~/Projects/external/pi-mono/packages/ai/scripts/generate-models.ts` @@ -67,6 +67,26 @@ Notes: - `packages/core/src/llm/providers/openrouter-model-registry.ts` - That runtime cache is great for “is this ID valid?”, but it doesn’t automatically improve our *static* model picker/catalog unless we integrate it into our registry generation or expose it as a dynamic catalog endpoint. +### 2.3 Also ingest Vercel AI Gateway’s live model catalog + +pi also fetches Vercel AI Gateway’s model catalog and treats it as a first-class source: +- Endpoint: `https://ai-gateway.vercel.sh/v1/models` +- Reference: `~/Projects/external/pi-mono/packages/ai/scripts/generate-models.ts` (`fetchAiGatewayModels()`) + +This matters for the same reason as OpenRouter: +- models.dev may be stale or curated compared to the live gateway catalog. +- We can keep our core transport surface small, but still keep a path to “all models” by ingesting gateway catalogs separately. + +### 2.4 Deterministic merge + de-dupe strategy (keep the path to “all models”) + +pi’s merge strategy is intentionally simple and stable: +- Merge sources in a fixed order (models.dev first). +- De-dupe by `(provider, modelId)`. +- Keep the first-seen model as authoritative (so models.dev wins when both have an entry; gateway sources fill gaps). + +Reference: +- `~/Projects/external/pi-mono/packages/ai/scripts/generate-models.ts` (section “Group by provider and deduplicate by model ID”). + ## 3) “Minimal transports” is still a viable base (with a clear path to pi parity) The earlier “minimal transports” statement refers to the **request-shape layer** (which SDK surface we target), not the size of the model catalog. @@ -125,4 +145,3 @@ We should update the plan’s next phases to include: - LLM factory refactor: - table-driven “boring providers” based on `npm` + `api` baseURL - keep explicit code only for real exceptions (dexto-nova, openrouter, bedrock, vertex, oauth URL rewrites, local/ollama) - diff --git a/feature-plans/oauth-and-more-providers/USER_VERIFICATION.md b/feature-plans/oauth-and-more-providers/USER_VERIFICATION.md index 5536884ea..25811a168 100644 --- a/feature-plans/oauth-and-more-providers/USER_VERIFICATION.md +++ b/feature-plans/oauth-and-more-providers/USER_VERIFICATION.md @@ -30,7 +30,7 @@ | UV-10 | Manual smoke: `/connect` UX | Requires local interactive runs | Phase 1+ | Open | Verify connect flow UX: create/switch default profiles, no secret leakage, file permissions are correct. | | UV-11 | Manual smoke: OpenAI OAuth runtime behavior | Requires real OAuth account + network | Phase 3 | Open | Verify token refresh + request rewrite works end-to-end (including Responses API behavior). | | UV-12 | Manual smoke: WebUI parity | Requires running WebUI | Phase 7 | Open | Verify WebUI reflects method-based auth and doesn’t regress existing API key settings. | -| UV-13 | “Ancient model” visibility policy | Product UX / defaults | 1.5.3 | Open | Decide whether we should ship an explicit time-window filter (eg “hide models older than X months”), and if so, which metadata to trust (`release_date`, `last_updated`, `status`). | +| UV-13 | “Ancient model” visibility policy | Product UX / defaults | 1.5.4 | Open | Decide whether we should ship an explicit time-window filter (eg “hide models older than X months”), and if so, which metadata to trust (`release_date`, `last_updated`, `status`). | --- diff --git a/feature-plans/oauth-and-more-providers/WORKING_MEMORY.md b/feature-plans/oauth-and-more-providers/WORKING_MEMORY.md index 0dc791476..8a5ebfb9b 100644 --- a/feature-plans/oauth-and-more-providers/WORKING_MEMORY.md +++ b/feature-plans/oauth-and-more-providers/WORKING_MEMORY.md @@ -25,7 +25,7 @@ ### Plan - Review the direction update in `feature-plans/oauth-and-more-providers/UPDATED_DIRECTION.md`. - Confirm the rebaselined tasklist in `feature-plans/oauth-and-more-providers/PLAN.md` (new Phase 1.5 for gateway catalogs; fix `/connect` multi-profile overwrite). -- Once aligned, proceed with **1.3.1** (multi-profile UX) and **1.5.2** (OpenRouter live catalog ingestion) in that order. +- Once aligned, proceed with **1.3.1** (multi-profile UX) and then Phase 1.5 gateway ingestion (**1.5.2** OpenRouter, **1.5.3** Vercel AI Gateway) in that order. ### Notes _Log findings, issues, and progress here as you work._ From be215fe5fc8a8a82f426c9b5a9940a80df8349e9 Mon Sep 17 00:00:00 2001 From: Rahul Karajgikar <rahul@trytruffle.ai> Date: Wed, 18 Feb 2026 19:47:23 +0530 Subject: [PATCH 14/25] docs(feature-plans): add npm transport roadmap --- .../NPM_TRANSPORT_COVERAGE.md | 300 ++++++++++++++++++ .../oauth-and-more-providers/PLAN.md | 26 +- 2 files changed, 323 insertions(+), 3 deletions(-) create mode 100644 feature-plans/oauth-and-more-providers/NPM_TRANSPORT_COVERAGE.md diff --git a/feature-plans/oauth-and-more-providers/NPM_TRANSPORT_COVERAGE.md b/feature-plans/oauth-and-more-providers/NPM_TRANSPORT_COVERAGE.md new file mode 100644 index 000000000..224e92ce6 --- /dev/null +++ b/feature-plans/oauth-and-more-providers/NPM_TRANSPORT_COVERAGE.md @@ -0,0 +1,300 @@ +# NPM / Transport Coverage Snapshot (models.dev → runtime mapping) + +Date: **2026-02-18** + +Source: `https://models.dev/api.json` + +Purpose: models.dev encodes the intended Vercel AI SDK provider module via `provider.npm`. Grouping provider IDs by `npm` gives us a *small, stable set of “transport kinds”* to implement, while still enabling a path to supporting “all providers”. + +This file is a concrete snapshot of: +- models.dev provider IDs grouped by `npm` (23 unique values as of this date) +- what Dexto can support *immediately* (based on existing core dependencies + transports) +- what requires additional work (new deps and/or bespoke drivers) + +Related: +- Provider IDs snapshot: [`PROVIDER_COVERAGE.md`](./PROVIDER_COVERAGE.md) +- Direction rationale: [`UPDATED_DIRECTION.md`](./UPDATED_DIRECTION.md) + +--- + +## 1) Summary + +- Total models.dev providers: **94** +- Unique `provider.npm` values: **23** +- Providers covered by Dexto’s **existing** transport surface (no new deps): **81 / 94** + - This is because **64 / 94** providers are `@ai-sdk/openai-compatible` (OpenAI Chat + baseURL). + +Unique npm counts (from models.dev): +- 64 `@ai-sdk/openai-compatible` +- 7 `@ai-sdk/anthropic` +- 2 `@ai-sdk/openai` +- 2 `@ai-sdk/azure` +- 1 each for the remaining 18 values + +--- + +## 2) Dexto “transport kinds” (stable) vs provider IDs (dynamic) + +The intended architecture (post Phase 1.5/2.3): +- **Transport kinds** in core remain a small, stable set (OpenAI, OpenAI-compatible, Anthropic, Vertex, Bedrock, etc.). +- **Provider IDs** can expand dynamically (models.dev’s 94 providers) by mapping: + - `provider.npm` → transport kind + - `provider.api` (when present) → baseURL + - `provider.env` / `provider.doc` → connect UX hints + +This keeps a clear path to “all providers” without turning `LLM_PROVIDERS` into a 94-item enum. + +--- + +## 3) Coverage status (as of this repo today) + +### 3.1 Covered by existing core dependencies (81 providers) + +These `npm` values already correspond to SDKs we have (or can route via `createOpenAI`), so Phase 2.3 can expose these providers without adding new packages: + +- `@ai-sdk/openai-compatible` (64) → `createOpenAI({ baseURL }).chat(model)` +- `@ai-sdk/openai` (2) → `createOpenAI({ baseURL? }).responses(model)` (or `.chat` where needed) +- `@ai-sdk/anthropic` (7) → `createAnthropic({ baseURL? })(model)` +- `@ai-sdk/google` (1) → `createGoogleGenerativeAI({ apiKey })(model)` +- `@ai-sdk/google-vertex` (1) → `createVertex({ project, location })(model)` (ADC) +- `@ai-sdk/google-vertex/anthropic` (1) → `createVertexAnthropic({ project, location })(model)` (ADC) +- `@ai-sdk/groq` (1) → `createGroq({ apiKey })(model)` +- `@ai-sdk/xai` (1) → `createXai({ apiKey })(model)` +- `@ai-sdk/cohere` (1) → `createCohere({ apiKey })(model)` +- `@ai-sdk/amazon-bedrock` (1) → `createAmazonBedrock({ region })(model)` (AWS creds) +- `@openrouter/ai-sdk-provider` (1) → Dexto can route via `createOpenAI({ baseURL: openrouter }).responses(model)` (no need to import the OpenRouter SDK initially) + +### 3.2 Not covered yet (13 providers; 12 npm values) + +These providers require either: +- adding the provider SDK package + wiring, or +- a deliberate compatibility strategy (eg treat as OpenAI-compatible by adding a curated baseURL if the upstream supports it), or +- deferring support. + +Not covered `npm` values: +- `@ai-sdk/azure` (2 providers) +- `@ai-sdk/cerebras` (1) +- `@ai-sdk/deepinfra` (1) +- `@ai-sdk/mistral` (1) +- `@ai-sdk/perplexity` (1) +- `@ai-sdk/togetherai` (1) +- `@ai-sdk/gateway` (1) — Vercel AI Gateway provider module in models.dev +- `@ai-sdk/vercel` (1) — v0 provider module +- `ai-gateway-provider` (1) — Cloudflare AI Gateway provider module +- `venice-ai-sdk-provider` (1) +- `@gitlab/gitlab-ai-provider` (1) +- `@jerome-benoit/sap-ai-provider-v2` (1) + +--- + +## 4) Provider IDs grouped by `provider.npm` (snapshot) + +## @ai-sdk/amazon-bedrock (1) + +```text +amazon-bedrock +``` + +## @ai-sdk/anthropic (7) + +```text +anthropic +kimi-for-coding +minimax +minimax-cn +minimax-cn-coding-plan +minimax-coding-plan +zenmux +``` + +## @ai-sdk/azure (2) + +```text +azure +azure-cognitive-services +``` + +## @ai-sdk/cerebras (1) + +```text +cerebras +``` + +## @ai-sdk/cohere (1) + +```text +cohere +``` + +## @ai-sdk/deepinfra (1) + +```text +deepinfra +``` + +## @ai-sdk/gateway (1) + +```text +vercel +``` + +## @ai-sdk/google (1) + +```text +google +``` + +## @ai-sdk/google-vertex (1) + +```text +google-vertex +``` + +## @ai-sdk/google-vertex/anthropic (1) + +```text +google-vertex-anthropic +``` + +## @ai-sdk/groq (1) + +```text +groq +``` + +## @ai-sdk/mistral (1) + +```text +mistral +``` + +## @ai-sdk/openai (2) + +```text +openai +vivgrid +``` + +## @ai-sdk/openai-compatible (64) + +```text +302ai +abacus +aihubmix +alibaba +alibaba-cn +bailing +baseten +berget +chutes +cloudferro-sherlock +cloudflare-workers-ai +cortecs +deepseek +fastrouter +fireworks-ai +firmware +friendli +github-copilot +github-models +helicone +huggingface +iflowcn +inception +inference +io-net +jiekou +kilo +kuae-cloud-coding-plan +llama +lmstudio +lucidquery +moark +modelscope +moonshotai +moonshotai-cn +morph +nano-gpt +nebius +nova +novita-ai +nvidia +ollama-cloud +opencode +ovhcloud +poe +privatemode-ai +qihang-ai +qiniu-ai +requesty +scaleway +siliconflow +siliconflow-cn +stackit +stepfun +submodel +synthetic +upstage +vultr +wandb +xiaomi +zai +zai-coding-plan +zhipuai +zhipuai-coding-plan +``` + +## @ai-sdk/perplexity (1) + +```text +perplexity +``` + +## @ai-sdk/togetherai (1) + +```text +togetherai +``` + +## @ai-sdk/vercel (1) + +```text +v0 +``` + +## @ai-sdk/xai (1) + +```text +xai +``` + +## @gitlab/gitlab-ai-provider (1) + +```text +gitlab +``` + +## @jerome-benoit/sap-ai-provider-v2 (1) + +```text +sap-ai-core +``` + +## @openrouter/ai-sdk-provider (1) + +```text +openrouter +``` + +## ai-gateway-provider (1) + +```text +cloudflare-ai-gateway +``` + +## venice-ai-sdk-provider (1) + +```text +venice +``` + diff --git a/feature-plans/oauth-and-more-providers/PLAN.md b/feature-plans/oauth-and-more-providers/PLAN.md index f803b976c..638074924 100644 --- a/feature-plans/oauth-and-more-providers/PLAN.md +++ b/feature-plans/oauth-and-more-providers/PLAN.md @@ -14,6 +14,7 @@ Primary references: - **pi-mono** (`~/Projects/external/pi-mono`) — model registry generation (multi-source) + explicit `api`/transport discriminators. - **models.dev** (`~/Projects/external/models.dev`) — provider/model metadata source (and clarifies when catalogs are curated vs exhaustive). - Provider coverage snapshot (exact provider IDs): [`PROVIDER_COVERAGE.md`](./PROVIDER_COVERAGE.md) +- Provider grouping by `provider.npm` (transport mapping roadmap): [`NPM_TRANSPORT_COVERAGE.md`](./NPM_TRANSPORT_COVERAGE.md) --- @@ -610,10 +611,29 @@ Implementation note (important): - [ ] **2.3 Expand `/connect` provider list using models.dev** - Deliverables: - - Provider picker uses models.dev **provider registry** for name + env vars + baseURL + model list, with a curated “top providers” grouping. - - Providers without special methods still get a default “API key” method (and “custom baseURL” when applicable). + - Provider picker is driven by the generated **models.dev provider snapshot** (name + env vars + docs + `npm` + baseURL when present), with a curated “top providers” grouping. + - Providers are classified by `provider.npm` into: + - **Supported (transport-mapped)**: `/connect` offers an API-key method (or guidance when creds aren’t stored), and runtime can create the model without per-provider code. + - **Unsupported (no transport yet)**: shown as disabled with a clear “not supported yet” hint + pointer to the plan section that adds the missing transport (`NPM_TRANSPORT_COVERAGE.md` is the roadmap). + - “Boring” OpenAI-compatible providers should require **zero per-provider code** beyond the transport mapping: + - save API key + - use models.dev `provider.api` as baseURL + - run via the shared OpenAI-compatible driver - Exit: - - `/connect` can add an API-key profile for a models.dev provider without adding per-provider code (where transport is already supported). + - `/connect` can add an API-key profile for *any* models.dev provider whose `provider.npm` maps to an implemented transport, without adding per-provider code. + +### Phase 2.4 — Expand transport coverage to “all providers” +> **Goal:** achieve near-total models.dev provider coverage by implementing transports per unique `provider.npm` value (small set), rather than per provider ID (large set). + +- [ ] **2.4.1 Implement remaining `provider.npm` transports (models.dev roadmap)** + - Deliverables: + - For each “unsupported” `provider.npm` value in [`NPM_TRANSPORT_COVERAGE.md`](./NPM_TRANSPORT_COVERAGE.md), decide one of: + - add the provider SDK package + wire it into the LLM factory, or + - intentionally defer (with a documented reason), or + - treat as OpenAI-compatible via a curated baseURL if the upstream is actually OpenAI-compatible. + - Keep the LLM factory table-driven: adding a new `provider.npm` should be a small, isolated change (no switch-case sprawl). + - Exit: + - `NPM_TRANSPORT_COVERAGE.md` “not covered yet” list shrinks over time, and `/connect` auto-enables newly supported providers without additional UX work. ### Phase 3 — OpenAI ChatGPT OAuth (Codex) > **Goal:** make OAuth a first-class method whose tokens affect runtime requests (not just storage). From aa59c4dd4ccc58507851164c2b9f14bc77edb3c9 Mon Sep 17 00:00:00 2001 From: Rahul Karajgikar <rahul@trytruffle.ai> Date: Thu, 19 Feb 2026 16:46:53 +0530 Subject: [PATCH 15/25] docs(feature-plans): make models.dev provider IDs canonical --- .../NPM_TRANSPORT_COVERAGE.md | 3 +- .../oauth-and-more-providers/PLAN.md | 69 ++++++++++--------- .../PROVIDER_COVERAGE.md | 24 +++++-- .../UPDATED_DIRECTION.md | 10 +++ .../USER_VERIFICATION.md | 4 +- 5 files changed, 66 insertions(+), 44 deletions(-) diff --git a/feature-plans/oauth-and-more-providers/NPM_TRANSPORT_COVERAGE.md b/feature-plans/oauth-and-more-providers/NPM_TRANSPORT_COVERAGE.md index 224e92ce6..a1103048f 100644 --- a/feature-plans/oauth-and-more-providers/NPM_TRANSPORT_COVERAGE.md +++ b/feature-plans/oauth-and-more-providers/NPM_TRANSPORT_COVERAGE.md @@ -42,7 +42,7 @@ The intended architecture (post Phase 1.5/2.3): - `provider.api` (when present) → baseURL - `provider.env` / `provider.doc` → connect UX hints -This keeps a clear path to “all providers” without turning `LLM_PROVIDERS` into a 94-item enum. +This keeps a clear path to “all providers” while keeping runtime code small; it’s fine if `LLM_PROVIDERS` becomes a 94-item union **as long as it’s generated** (not hand-maintained). --- @@ -297,4 +297,3 @@ cloudflare-ai-gateway ```text venice ``` - diff --git a/feature-plans/oauth-and-more-providers/PLAN.md b/feature-plans/oauth-and-more-providers/PLAN.md index 638074924..65a855e0b 100644 --- a/feature-plans/oauth-and-more-providers/PLAN.md +++ b/feature-plans/oauth-and-more-providers/PLAN.md @@ -27,7 +27,7 @@ Ground truth in the repo today: - **Provider key storage helpers** live in `@dexto/agent-management`: - `packages/agent-management/src/utils/api-key-store.ts` (`saveProviderApiKey()`, `getProviderKeyStatus()`, Bedrock special-casing) - `packages/agent-management/src/utils/api-key-resolver.ts` (env var resolution mirror) -- **Dexto account login** state lives in `~/.dexto/auth.json` (see `packages/cli/src/cli/auth/service.ts` and `packages/agent-management/src/utils/dexto-auth.ts`). The CLI loads `DEXTO_API_KEY` from this file early (`packages/cli/src/index-main.ts`) for `dexto-nova` routing. +- **Dexto account login** state lives in `~/.dexto/auth/dexto.json` (see `packages/cli/src/cli/auth/service.ts` and `packages/agent-management/src/utils/dexto-auth.ts`). The CLI loads `DEXTO_API_KEY` from this file early (`packages/cli/src/index-main.ts`) for `dexto-nova` routing. We want: - **Per-provider auth method selection** (e.g. OpenAI: ChatGPT OAuth *or* API key). @@ -38,9 +38,10 @@ Known complications / gaps: - **OpenAI Codex OAuth may require allowlisting** (expected failure mode for many accounts). We must implement it with graceful fallback messaging to API key mode. - **OAuth client IDs / redirect URIs are product-critical**. We must use Dexto-owned OAuth app credentials (don’t copy OpenCode/OpenClaw client IDs). Redirect URIs must be registered; some providers may require allowlisting for our app. - **Anthropic setup-token viability is uncertain** (we should implement until proven infeasible, then gate/remove). -- **Provider IDs are currently fixed** (`LLM_PROVIDERS` enum in `packages/core/src/llm/types.ts`). Supporting `moonshot`, `zai`, `minimax-cn`, etc. as first-class providers requires either: - - expanding the enum + LLM factory support, or - - treating them as `openai-compatible` presets (provider-specific baseURL + env-var naming) without adding new provider IDs. +- **Provider IDs are currently fixed** (`LLM_PROVIDERS` in `packages/core/src/llm/types.ts`), but our direction is **models.dev-driven provider IDs**: + - Treat **models.dev provider IDs** as canonical “first-class” providers (e.g. `deepseek`, `zhipuai`, `zai`, `moonshotai`, `minimax-cn`, …). + - `LLM_PROVIDERS` / `LLMProvider` should be **generated from the models.dev provider snapshot** (plus a small Dexto-only overlay like `dexto-nova`, `openai-compatible`, `ollama`, `local`). + - **Backward compatibility is explicitly not required** for legacy provider IDs (e.g. `glm`, `vertex`, `bedrock`) or legacy auth storage. --- @@ -203,7 +204,7 @@ Key takeaways to borrow: - Fixed provider enum: `packages/core/src/llm/types.ts` (`LLM_PROVIDERS`) - API key resolution: `packages/core/src/utils/api-key-resolver.ts`, `packages/agent-management/src/utils/api-key-resolver.ts` - Persisted API keys (writes `.env`): `packages/agent-management/src/utils/api-key-store.ts`, server route `packages/server/src/hono/routes/key.ts` -- Dexto login state (for `dexto-nova`): `packages/cli/src/cli/auth/service.ts` (writes `~/.dexto/auth.json`), env injection `packages/cli/src/index-main.ts` +- Dexto login state (for `dexto-nova`): `packages/cli/src/cli/auth/service.ts` (writes `~/.dexto/auth/dexto.json`), env injection `packages/cli/src/index-main.ts` ### 6.2 OpenCode today (reference) - Auth storage (`auth.json`, `0o600`): `~/Projects/external/opencode/packages/opencode/src/auth/index.ts` @@ -226,16 +227,16 @@ Key takeaways to borrow: |---|---|---|---|---| | `openai` | OAuth (ChatGPT Pro/Plus browser + headless) + API key (`~/Projects/external/opencode/packages/opencode/src/plugin/codex.ts`) | `openai-codex` (OAuth), `openai-api-key` (API key) (`~/Projects/external/openclaw/src/commands/auth-choice-options.ts`) | API key via env vars (`OPENAI_API_KEY`, `OPENAI_KEY`) | API key + Codex OAuth (browser + headless), allowlist-aware UX + runtime request rewrite | | `anthropic` | API key | `token` / `setup-token` (paste), `apiKey` (API key) (`~/Projects/external/openclaw/src/commands/auth-choice.apply.anthropic.ts`) | API key via env vars (`ANTHROPIC_API_KEY`, etc.) | API key + setup-token (implement; gate/remove if infeasible) | -| `minimax` | API key (models.dev provider ID `minimax`, `minimax-coding-plan`) | `minimax-portal` (OAuth), plus API key presets (`minimax-api`, `minimax-api-key-cn`, `minimax-api-lightning`) (`~/Projects/external/openclaw/src/commands/auth-choice-options.ts`, `~/Projects/external/openclaw/extensions/minimax-portal-auth/oauth.ts`, `~/Projects/external/openclaw/src/commands/onboard-auth.config-minimax.ts`) | Provider exists (`minimax`) but current runtime assumes OpenAI-compatible baseURL (`packages/core/src/llm/services/factory.ts`) | API key presets (global/CN + coding-plan variants) + MiniMax Portal OAuth method; align runtime transport with models.dev + OpenClaw endpoint variants | -| `moonshotai` (Kimi) | API key (models.dev provider IDs `moonshotai`, `moonshotai-cn`) | `moonshot-api-key` (global), `moonshot-api-key-cn` (CN) (`~/Projects/external/openclaw/src/commands/auth-choice-options.ts`) | Not first-class provider ID; can be used via `openai-compatible` manually | Add Moonshot presets (global + CN) with models.dev provider IDs and OpenClaw baseURL constants; optionally add a first-class provider ID (Phase 0.2) | -| `kimi-for-coding` (Kimi Code) | API key (models.dev provider ID `kimi-for-coding`) | `kimi-code-api-key` (API key) (`~/Projects/external/openclaw/src/commands/auth-choice.apply.api-providers.ts`) | Not supported | Add Kimi Code preset (Anthropic-compatible) + API key connect method; ensure runtime can target Anthropic-compatible endpoints | -| `zhipuai` (GLM / BigModel) | API key (models.dev provider IDs `zhipuai`, `zhipuai-coding-plan`) | (OpenClaw’s “CN” Z.AI endpoints point at `open.bigmodel.cn`) (`~/Projects/external/openclaw/src/commands/onboard-auth.models.ts`) | Supported as provider `glm` with fixed baseURL `https://open.bigmodel.cn/api/paas/v4` (`packages/core/src/llm/services/factory.ts`) | Add presets for Zhipu base URLs (standard + coding plan), and decide whether to alias `glm` ↔ `zhipuai` in UX/config (Phase 0.2) | -| `zai` (Z.AI) | API key (models.dev provider IDs `zai`, `zai-coding-plan`) | `zai-*` endpoint presets (`zai-coding-global`, `zai-coding-cn`, `zai-global`, `zai-cn`) (`~/Projects/external/openclaw/src/commands/auth-choice-options.ts`, `~/Projects/external/openclaw/src/commands/onboard-auth.models.ts`) | Not first-class (closest is `glm` for `open.bigmodel.cn`) | Add Z.AI presets and decide env var mapping (`ZHIPU_API_KEY` per models.dev vs `ZAI_API_KEY` per OpenClaw) (Phase 0.2) | -| `bedrock` | (API key/creds) | (N/A) | AWS chain in factory; bearer token is recognized in status helpers (`packages/agent-management/src/utils/api-key-store.ts`) | `/connect` guidance + explicit method choices | -| `vertex` | ADC | (N/A) | ADC-only (`GOOGLE_VERTEX_PROJECT`, etc.) | `/connect` guidance + status surface | +| `minimax` | API key (models.dev provider ID `minimax`, `minimax-coding-plan`) | `minimax-portal` (OAuth), plus API key presets (`minimax-api`, `minimax-api-key-cn`, `minimax-api-lightning`) (`~/Projects/external/openclaw/src/commands/auth-choice-options.ts`, `~/Projects/external/openclaw/extensions/minimax-portal-auth/oauth.ts`, `~/Projects/external/openclaw/src/commands/onboard-auth.config-minimax.ts`) | First-class providers (`minimax*`); runtime uses Anthropic-compatible baseURLs (models.dev-aligned) (`packages/core/src/llm/services/factory.ts`) | Keep models.dev baseURLs as the default; optionally expose OpenAI-compatible variants as explicit presets if we decide they’re valuable | +| `moonshotai` (Kimi) | API key (models.dev provider IDs `moonshotai`, `moonshotai-cn`) | `moonshot-api-key` (global), `moonshot-api-key-cn` (CN) (`~/Projects/external/openclaw/src/commands/auth-choice-options.ts`) | First-class providers (`moonshotai`, `moonshotai-cn`) | Generate provider IDs from models.dev; keep baseURL + env hints sourced from snapshot | +| `kimi-for-coding` (Kimi Code) | API key (models.dev provider ID `kimi-for-coding`) | `kimi-code-api-key` (API key) (`~/Projects/external/openclaw/src/commands/auth-choice.apply.api-providers.ts`) | First-class provider (`kimi-for-coding`) | Keep models.dev-aligned Anthropic-compatible baseURL + API key method | +| `zhipuai` (GLM / BigModel) | API key (models.dev provider IDs `zhipuai`, `zhipuai-coding-plan`) | (OpenClaw’s “CN” Z.AI endpoints point at `open.bigmodel.cn`) (`~/Projects/external/openclaw/src/commands/onboard-auth.models.ts`) | First-class providers (`zhipuai`, `zhipuai-coding-plan`); legacy `glm` should be removed | Align fully to models.dev provider IDs; no aliases/back-compat required | +| `zai` (Z.AI) | API key (models.dev provider IDs `zai`, `zai-coding-plan`) | `zai-*` endpoint presets (`zai-coding-global`, `zai-coding-cn`, `zai-global`, `zai-cn`) (`~/Projects/external/openclaw/src/commands/auth-choice-options.ts`, `~/Projects/external/openclaw/src/commands/onboard-auth.models.ts`) | First-class providers (`zai`, `zai-coding-plan`) | Decide env var accept/display policy (models.dev `ZHIPU_API_KEY` vs OpenClaw `ZAI_API_KEY` variants) | +| `amazon-bedrock` | (API key/creds) | (N/A) | AWS chain in factory; bearer token is recognized in status helpers (`packages/agent-management/src/utils/api-key-store.ts`) | Rename provider ID to models.dev’s `amazon-bedrock`; keep `/connect` guidance + explicit method choices | +| `google-vertex` | ADC | (N/A) | ADC-only (`GOOGLE_VERTEX_PROJECT`, etc.) | Rename provider ID to models.dev’s `google-vertex`; keep `/connect` guidance + status surface | | `openrouter` | API key | `openrouter-api-key` | API key env var | Add profiles + `/connect` UX + status | | `litellm` | API key + baseURL | `litellm-api-key` | API key env var + baseURL required | Add profiles + `/connect` UX for baseURL + key | -| `dexto-nova` | (N/A) | (N/A) | Dexto login (`~/.dexto/auth.json` → `DEXTO_API_KEY`) | Move to new auth store + expose status/methods via API | +| `dexto-nova` | (N/A) | (N/A) | Dexto login (`~/.dexto/auth/dexto.json` → `DEXTO_API_KEY`) | Expose status/methods via API; keep auth store under `~/.dexto/auth/` | ### 6.4.1 Additional OAuth/token methods in prior art (useful references; not required for v1 unless requested) @@ -254,12 +255,12 @@ This is the “actionable diff” for GLM/Z.AI, MiniMax, and Kimi/Moonshot. It | Ecosystem | models.dev (provider IDs → baseURL/API + env + SDK hint) | OpenClaw (provider IDs/choices → baseURL + env) | Dexto today (provider → baseURL + env) | Implication for this plan | |---|---|---|---|---| -| **MiniMax** | `minimax` → `https://api.minimax.io/anthropic/v1`, `MINIMAX_API_KEY`, `@ai-sdk/anthropic` | `minimax` OpenAI-compatible: `DEFAULT_MINIMAX_BASE_URL = https://api.minimax.io/v1` (`onboard-auth.models.ts`); Anthropic-compatible: `MINIMAX_API_BASE_URL = https://api.minimax.io/anthropic`, `MINIMAX_CN_API_BASE_URL = https://api.minimaxi.com/anthropic` (`onboard-auth.config-minimax.ts`); env: `MINIMAX_API_KEY` / `MINIMAX_OAUTH_TOKEN` (`model-auth.ts`) | `minimax` → `https://api.minimax.chat/v1` + `MINIMAX_API_KEY` (`packages/core/src/llm/services/factory.ts`, `packages/core/src/utils/api-key-resolver.ts`) | MiniMax has **multiple official surfaces** (OpenAI-compatible vs Anthropic-compatible vs Portal OAuth). Our presets must choose a default and also expose variants. Expect we’ll need an **Anthropic-compatible runtime path** for models.dev alignment (and/or keep OpenAI-compatible as an optional preset). | -| **MiniMax (CN)** | `minimax-cn` → `https://api.minimaxi.com/anthropic/v1`, `MINIMAX_API_KEY`, `@ai-sdk/anthropic` | `minimax-api-key-cn` choice uses `api.minimaxi.com` (`auth-choice-options.ts`) + `MINIMAX_CN_API_BASE_URL` (`onboard-auth.config-minimax.ts`) | no first-class CN preset | Add CN preset(s) and make region explicit in `/connect`. | -| **Moonshot (Kimi)** | `moonshotai` → `https://api.moonshot.ai/v1`, `MOONSHOT_API_KEY`, `@ai-sdk/openai-compatible`; `moonshotai-cn` → `https://api.moonshot.cn/v1` | `moonshot` provider: `MOONSHOT_BASE_URL`, `MOONSHOT_CN_BASE_URL` (`onboard-auth.models.ts` / `onboard-auth.config-core.ts`); env: `MOONSHOT_API_KEY` (`model-auth.ts`) | not first-class; can be used via `openai-compatible` if user supplies `baseURL` + key | Moonshot is a clean **OpenAI-compatible preset**. We should ship both baseURLs + a small curated model list. | -| **Kimi Code / “for coding”** | `kimi-for-coding` → `https://api.kimi.com/coding/v1`, `KIMI_API_KEY`, `@ai-sdk/anthropic` | `kimi-coding` provider + `kimi-code-api-key` choice (`auth-choice.apply.api-providers.ts`); env: `KIMI_API_KEY` / `KIMICODE_API_KEY` (`model-auth.ts`) | not supported | This is an **Anthropic-compatible preset** (not OpenAI-compatible). Plan should include an Anthropic-compatible runtime transport/preset path. | -| **Zhipu AI (GLM / BigModel)** | `zhipuai` → `https://open.bigmodel.cn/api/paas/v4`, `ZHIPU_API_KEY`, `@ai-sdk/openai-compatible`; `zhipuai-coding-plan` → `https://open.bigmodel.cn/api/coding/paas/v4` | OpenClaw’s “CN” Z.AI endpoints also point at `open.bigmodel.cn` (`onboard-auth.models.ts`); env: `ZHIPU_API_KEY` (`model-auth.ts`) | `glm` → `https://open.bigmodel.cn/api/paas/v4` + `ZHIPU_API_KEY` | Dexto’s `glm` is already close to models.dev’s `zhipuai`. We should decide whether to alias/rename for consistency and add coding-plan presets. | -| **Z.AI (GLM / global)** | `zai` → `https://api.z.ai/api/paas/v4`, `ZHIPU_API_KEY`, `@ai-sdk/openai-compatible`; `zai-coding-plan` → `https://api.z.ai/api/coding/paas/v4` | OpenClaw uses baseURLs `api.z.ai` + `open.bigmodel.cn` variants (`onboard-auth.models.ts`), but env mapping differs: `ZAI_API_KEY` / `Z_AI_API_KEY` for `zai` (`model-auth.ts`) | no first-class; closest is `glm` | We need an owner decision: accept both env var schemes and/or prefer models.dev’s `ZHIPU_API_KEY`. Connect UX should make this explicit to avoid surprise. | +| **MiniMax** | `minimax` → `https://api.minimax.io/anthropic/v1`, `MINIMAX_API_KEY`, `@ai-sdk/anthropic` | `minimax` OpenAI-compatible: `DEFAULT_MINIMAX_BASE_URL = https://api.minimax.io/v1` (`onboard-auth.models.ts`); Anthropic-compatible: `MINIMAX_API_BASE_URL = https://api.minimax.io/anthropic`, `MINIMAX_CN_API_BASE_URL = https://api.minimaxi.com/anthropic` (`onboard-auth.config-minimax.ts`); env: `MINIMAX_API_KEY` / `MINIMAX_OAUTH_TOKEN` (`model-auth.ts`) | `minimax` → `https://api.minimax.io/anthropic/v1` + `MINIMAX_API_KEY` (`packages/core/src/llm/services/factory.ts`, `packages/core/src/utils/api-key-resolver.ts`) | MiniMax has **multiple official surfaces** (OpenAI-compatible vs Anthropic-compatible vs Portal OAuth). We default to models.dev’s Anthropic-compatible baseURL; decide whether we also ship OpenAI-compatible variants as explicit (optional) presets. | +| **MiniMax (CN)** | `minimax-cn` → `https://api.minimaxi.com/anthropic/v1`, `MINIMAX_API_KEY`, `@ai-sdk/anthropic` | `minimax-api-key-cn` choice uses `api.minimaxi.com` (`auth-choice-options.ts`) + `MINIMAX_CN_API_BASE_URL` (`onboard-auth.config-minimax.ts`) | `minimax-cn` → `https://api.minimaxi.com/anthropic/v1` + `MINIMAX_API_KEY` | Keep region explicit in `/connect` and decide whether we also ship OpenAI-compatible variants as explicit presets. | +| **Moonshot (Kimi)** | `moonshotai` → `https://api.moonshot.ai/v1`, `MOONSHOT_API_KEY`, `@ai-sdk/openai-compatible`; `moonshotai-cn` → `https://api.moonshot.cn/v1` | `moonshot` provider: `MOONSHOT_BASE_URL`, `MOONSHOT_CN_BASE_URL` (`onboard-auth.models.ts` / `onboard-auth.config-core.ts`); env: `MOONSHOT_API_KEY` (`model-auth.ts`) | `moonshotai` / `moonshotai-cn` → baseURLs + `MOONSHOT_API_KEY` | Clean OpenAI-compatible presets; ensure provider IDs + baseURLs are generated from models.dev snapshot and keep a small curated model list. | +| **Kimi Code / “for coding”** | `kimi-for-coding` → `https://api.kimi.com/coding/v1`, `KIMI_API_KEY`, `@ai-sdk/anthropic` | `kimi-coding` provider + `kimi-code-api-key` choice (`auth-choice.apply.api-providers.ts`); env: `KIMI_API_KEY` / `KIMICODE_API_KEY` (`model-auth.ts`) | `kimi-for-coding` → `https://api.kimi.com/coding/v1` + `KIMI_API_KEY` | Anthropic-compatible preset (not OpenAI-compatible). Ensure runtime transport/preset path stays explicit. | +| **Zhipu AI (GLM / BigModel)** | `zhipuai` → `https://open.bigmodel.cn/api/paas/v4`, `ZHIPU_API_KEY`, `@ai-sdk/openai-compatible`; `zhipuai-coding-plan` → `https://open.bigmodel.cn/api/coding/paas/v4` | OpenClaw’s “CN” Z.AI endpoints also point at `open.bigmodel.cn` (`onboard-auth.models.ts`); env: `ZHIPU_API_KEY` (`model-auth.ts`) | `zhipuai` → `https://open.bigmodel.cn/api/paas/v4` + `ZHIPU_API_KEY` (legacy `glm` should be removed) | Adopt models.dev provider IDs as canonical; no `glm` alias/back-compat. | +| **Z.AI (GLM / global)** | `zai` → `https://api.z.ai/api/paas/v4`, `ZHIPU_API_KEY`, `@ai-sdk/openai-compatible`; `zai-coding-plan` → `https://api.z.ai/api/coding/paas/v4` | OpenClaw uses baseURLs `api.z.ai` + `open.bigmodel.cn` variants (`onboard-auth.models.ts`), but env mapping differs: `ZAI_API_KEY` / `Z_AI_API_KEY` for `zai` (`model-auth.ts`) | `zai` → `https://api.z.ai/api/paas/v4` + `ZHIPU_API_KEY` | We need an owner decision: accept both env var schemes and/or prefer models.dev’s `ZHIPU_API_KEY`. Connect UX should make this explicit to avoid surprise. | --- @@ -444,11 +445,10 @@ Implementation note (important): | `minimax` / `minimax-cn` | API key, MiniMax Portal OAuth, CN presets | models.dev indicates Anthropic-compatible baseURLs; OpenClaw also supports OpenAI-compatible variants. We should ship presets for both and choose a default. | | `moonshotai` / `moonshotai-cn` | API key, global/CN presets | OpenAI-compatible; models.dev provides canonical baseURLs + env var hints; OpenClaw presets also exist. | | `kimi-for-coding` | API key | Anthropic-compatible preset (distinct from Moonshot). | -| `zhipuai` / `zhipuai-coding-plan` | API key, endpoint presets | OpenAI-compatible; likely aliases Dexto’s current `glm` (owner decision). | +| `zhipuai` / `zhipuai-coding-plan` | API key, endpoint presets | OpenAI-compatible; canonical models.dev IDs (no `glm` alias/back-compat). | | `zai` / `zai-coding-plan` | API key, endpoint presets | OpenAI-compatible; env var mapping differs between models.dev and OpenClaw (Phase 0.2). | -| `glm` | API key | Existing Dexto provider; decide whether it becomes an alias to `zhipuai` or remains as-is (Phase 0.2). | -| `bedrock` | AWS chain, bearer token | Make bearer-token connect UX explicit; keep “chain” guidance. | -| `vertex` | ADC | Expose a “connect” flow that teaches `gcloud auth application-default login` + required env vars. | +| `amazon-bedrock` | AWS chain, bearer token | Make bearer-token connect UX explicit; keep “chain” guidance. | +| `google-vertex` | ADC | Expose a “connect” flow that teaches `gcloud auth application-default login` + required env vars. | | `openrouter` | API key | Already. | | `litellm` | API key + baseURL | Already via setup/custom model. | | `openai-compatible` | API key + baseURL + custom models | Already via custom model wizard; integrate with /connect for the provider-level credential if desired. | @@ -469,9 +469,11 @@ Implementation note (important): - Exit: - `USER_VERIFICATION.md` contains the resolved decision and any explicit follow-ups. -- [ ] **0.2 Decide provider identity + preset strategy (models.dev-driven)** +- [x] **0.2 Decide provider identity + preset strategy (models.dev-driven)** - Deliverables: - - Decide whether our user-facing provider IDs should align with **models.dev provider IDs** (example set: `moonshotai`, `moonshotai-cn`, `zai`, `zai-coding-plan`, `zhipuai`, `zhipuai-coding-plan`, `minimax`, `minimax-cn`, `kimi-for-coding`) vs remain “Dexto-local” (`glm`, `minimax`, etc.) with aliases. + - **Decision:** user-facing provider IDs align with **models.dev provider IDs** (no Dexto-local aliases/back-compat). + - Deprecate/remove legacy IDs like `glm`, `vertex`, `bedrock` in favor of models.dev IDs (`zhipuai`, `google-vertex`, `amazon-bedrock`, …). + - Make `LLM_PROVIDERS` / `LLMProvider` **generated from models.dev** (plus a small Dexto-only overlay like `dexto-nova`, `openai-compatible`, `ollama`, `local`). - Define “preset” behavior (the core abstraction for “more providers”): - which **transport** a preset uses (`openai-compatible` vs `anthropic-compatible` vs first-class SDK), - which baseURL variants exist (global/CN, coding-plan vs standard), @@ -541,6 +543,7 @@ Implementation note (important): - [ ] **1.5.1 Generate a provider snapshot from models.dev (offline, committed)** - Deliverables: - Extend the sync script to output a `providers.generated.ts` snapshot (provider id/name/env/doc/npm/api). + - Generate `LLM_PROVIDERS` / `LLMProvider` from this snapshot (plus a small Dexto-only overlay), so core types don’t require hand-maintained provider lists. - Consume this snapshot for `/connect` provider metadata (labels, env hints, docs links), so the connect UI isn’t hand-maintained. - Exit: - Regenerated snapshots are stable and reviewed in git; no secrets. @@ -585,7 +588,7 @@ Implementation note (important): - `modelsDevProviderId` (string, e.g. `moonshotai-cn`) - `transport` (e.g. `openai-compatible` vs `anthropic-compatible` vs first-class SDK) - `baseURL` (from models.dev `provider.api` when present, or curated override) - - `envVars` (from models.dev `provider.env` + any Dexto aliases) + - `envVars` (from models.dev `provider.env` + any additional accepted env vars we choose to support) - `docUrl` (from models.dev `provider.doc`, optional) - `defaultModel` + curated model list (optional) - Initial curated presets (at minimum): @@ -599,13 +602,13 @@ Implementation note (important): - `/connect` can show these providers/methods and persist profiles for API-key methods. - [ ] **2.2 Implement chosen runtime strategy for new providers** - - Deliverables (based on Phase 0.2 decision): - - **If first-class providers:** extend `packages/core/src/llm/types.ts` (`LLM_PROVIDERS`), `packages/core/src/llm/services/factory.ts` (provider switch), and API-key env var mapping so the models.dev-aligned IDs (e.g. `moonshotai`, `zai`, `zhipuai`, `minimax-cn`, `kimi-for-coding`) can run without “custom model” hacks. - - **If preset-based (recommended for breadth):** - - ensure profiles carry `transport + baseURL + modelsDevProviderId` so runtime can choose the correct SDK surface: - - OpenAI-compatible: `createOpenAI({ baseURL }).chat(...)` - - Anthropic-compatible: `createAnthropic({ baseURL }).messages(...)` (or a dedicated `anthropic-compatible` driver if we don’t want to change `anthropic`) - - ensure models.dev provider IDs still show up in UX even if runtime uses a shared driver (`openai-compatible`, `anthropic-compatible`). + - Deliverables: + - Treat models.dev provider IDs as first-class throughout: + - `LLM_PROVIDERS` / `LLMProvider` generated from models.dev provider snapshot (+ Dexto-only overlay). + - Remove deprecated Dexto-local provider IDs (no aliases/back-compat required). + - Keep runtime scalable (avoid 94+ switch-cases): + - Route “boring providers” via a **transport mapping** keyed by models.dev `provider.npm` (and `provider.api` for baseURL). + - Keep bespoke code paths only for true exceptions (`dexto-nova`, `openrouter`, `local`/`ollama`, cloud auth providers, OAuth rewrite cases). - Exit: - Manual smoke: connect + run at least one model for each preset ecosystem (MiniMax / Z.AI / Zhipu / Moonshot / Kimi Code). diff --git a/feature-plans/oauth-and-more-providers/PROVIDER_COVERAGE.md b/feature-plans/oauth-and-more-providers/PROVIDER_COVERAGE.md index 0ee74b8b3..bda2a2af0 100644 --- a/feature-plans/oauth-and-more-providers/PROVIDER_COVERAGE.md +++ b/feature-plans/oauth-and-more-providers/PROVIDER_COVERAGE.md @@ -16,26 +16,36 @@ Notes: Source of truth: `packages/core/src/llm/types.ts` (`LLM_PROVIDERS`) -Count: **17** +Count: **27** ```text +openai +openai-compatible anthropic -bedrock +google +groq +xai cohere dexto-nova glama glm -google -groq litellm local minimax +minimax-cn +minimax-coding-plan +minimax-cn-coding-plan +moonshotai +moonshotai-cn ollama -openai -openai-compatible openrouter vertex -xai +bedrock +kimi-for-coding +zhipuai +zhipuai-coding-plan +zai +zai-coding-plan ``` --- diff --git a/feature-plans/oauth-and-more-providers/UPDATED_DIRECTION.md b/feature-plans/oauth-and-more-providers/UPDATED_DIRECTION.md index 258682eda..0dad56246 100644 --- a/feature-plans/oauth-and-more-providers/UPDATED_DIRECTION.md +++ b/feature-plans/oauth-and-more-providers/UPDATED_DIRECTION.md @@ -87,6 +87,16 @@ pi’s merge strategy is intentionally simple and stable: Reference: - `~/Projects/external/pi-mono/packages/ai/scripts/generate-models.ts` (section “Group by provider and deduplicate by model ID”). +### 2.5 Provider identity: models.dev provider IDs are canonical (no back-compat) + +Decision (owner): treat **models.dev provider IDs** as our canonical, user-facing provider IDs. + +Implications: +- Expand core’s `LLMProvider` to include all models.dev provider IDs (generated from the provider snapshot). +- Deprecate/remove Dexto-local legacy IDs (e.g. `glm`, `vertex`, `bedrock`) in favor of models.dev IDs (e.g. `zhipuai`, `google-vertex`, `amazon-bedrock`). +- Keep a small Dexto-only overlay for providers that are not on models.dev (e.g. `dexto-nova`, `openai-compatible`, `local`, `ollama`). +- No aliases/backward compatibility required: breaking config changes are acceptable. + ## 3) “Minimal transports” is still a viable base (with a clear path to pi parity) The earlier “minimal transports” statement refers to the **request-shape layer** (which SDK surface we target), not the size of the model catalog. diff --git a/feature-plans/oauth-and-more-providers/USER_VERIFICATION.md b/feature-plans/oauth-and-more-providers/USER_VERIFICATION.md index 25811a168..44ba4ced5 100644 --- a/feature-plans/oauth-and-more-providers/USER_VERIFICATION.md +++ b/feature-plans/oauth-and-more-providers/USER_VERIFICATION.md @@ -21,9 +21,8 @@ | UV-1 | Auth storage layout (new `~/.dexto/auth/`) | Security posture + UX permanence | 0.1 | Open | Implemented file-backed `~/.dexto/auth/llm-profiles.json` with `0o600` + atomic writes; confirm layout + naming + any migration story. | | UV-2 | OAuth app credentials + allowlisting (OpenAI Codex) | Requires external app registration + product comms | 3.1 | Open | We need Dexto-owned OpenAI OAuth client ID + registered redirect URIs; Codex OAuth may require allowlisting. Decide how we message failure + fallback to API key. | | UV-3 | OAuth app credentials (MiniMax Portal) | Requires external app registration or explicit provider confirmation | 4.1 | Open | OpenClaw hardcodes a client ID; confirm whether we must register our own, or whether a public client ID is intended for third-party use. | -| UV-4 | Provider identity strategy (models.dev vs Dexto IDs) | Product naming + config compatibility | 0.2 | Open | Decide whether to align user-facing IDs with models.dev (`moonshotai`, `zhipuai`, `zai`, `minimax-cn`, `kimi-for-coding`, …) vs keep Dexto-local IDs (`glm`, `minimax`) with aliases. | | UV-5 | Env var mapping for Z.AI / GLM | User expectation + migration risk | 0.2 | Open | models.dev uses `ZHIPU_API_KEY` for `zai`; OpenClaw uses `ZAI_API_KEY` / `Z_AI_API_KEY`. Decide which to accept and which to display as the “primary” hint. | -| UV-6 | MiniMax transport defaults (OpenAI-compatible vs Anthropic-compatible) | Impacts runtime correctness + preset design | 2.2 | Open | Dexto today assumes OpenAI-compatible (`api.minimax.chat`), while models.dev indicates Anthropic-compatible (`api.minimax.io/anthropic/v1`). Decide default + how we expose variants. | +| UV-6 | MiniMax transport defaults (OpenAI-compatible vs Anthropic-compatible) | Impacts runtime correctness + preset design | 2.2 | Open | Runtime now defaults to models.dev’s Anthropic-compatible baseURL; decide whether we also ship OpenAI-compatible variants as explicit (optional) presets. | | UV-7 | Provider + gateway catalog ingestion strategy | Impacts offline behavior + maintenance + UX | 1.5 | Open | Decide build-time snapshot vs runtime fetch+cache for: (a) models.dev provider metadata (name/env/doc/npm/api), and (b) gateway model catalogs (OpenRouter live `/models` vs models.dev curated list). | | UV-8 | Resolution precedence surface | UX + “magic” risk | 0.4 | Open | Decide hardcoded precedence vs store-driven order; decide whether precedence lives in `llm-profiles` vs agent config; decide `llm.authProfileId` in v1. | | UV-9 | Anthropic setup-token viability + ship criteria | External dependency + potential policy constraints | 5.2 | Open | Implement until infeasible; decide whether this is “experimental” and how we disable quickly if it breaks/gets blocked. | @@ -39,3 +38,4 @@ | ID | Decision / Verification | Date | Notes | |----|--------------------------|------|-------| | UV-0 | No backwards compatibility with legacy `~/.dexto/auth.json` | 2026-02-17 | Require re-login to populate the new auth store; optional one-time import is not required for v1. | +| UV-4 | Provider identity: models.dev IDs are canonical; deprecate Dexto-local IDs | 2026-02-18 | Align user-facing IDs to models.dev; generate `LLMProvider` from models.dev provider snapshot (plus small Dexto-only overlay). No alias/back-compat required. | From 7f9e7040e3d4e1b54becfe2bb1bffdeeb2e952bf Mon Sep 17 00:00:00 2001 From: Rahul Karajgikar <rahul@trytruffle.ai> Date: Thu, 19 Feb 2026 19:13:12 +0530 Subject: [PATCH 16/25] docs(feature-plans): add worktree context + reasoning alignment --- feature-plans/oauth-and-more-providers/PLAN.md | 8 ++++++++ feature-plans/oauth-and-more-providers/WORKING_MEMORY.md | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/feature-plans/oauth-and-more-providers/PLAN.md b/feature-plans/oauth-and-more-providers/PLAN.md index 65a855e0b..cda1a1c7b 100644 --- a/feature-plans/oauth-and-more-providers/PLAN.md +++ b/feature-plans/oauth-and-more-providers/PLAN.md @@ -16,6 +16,10 @@ Primary references: - Provider coverage snapshot (exact provider IDs): [`PROVIDER_COVERAGE.md`](./PROVIDER_COVERAGE.md) - Provider grouping by `provider.npm` (transport mapping roadmap): [`NPM_TRANSPORT_COVERAGE.md`](./NPM_TRANSPORT_COVERAGE.md) +Repo context: +- Worktree: `~/Projects/dexto-worktrees/oauth-provider-revamp` (branch: `oauth-provider-revamp`, based off `main`). +- `feature-plans/` is gitignored for untracked files. Stage commits with `git add -f feature-plans/...` (avoid `git add .` / `git add -A`). + --- ## 1. Problem @@ -42,6 +46,7 @@ Known complications / gaps: - Treat **models.dev provider IDs** as canonical “first-class” providers (e.g. `deepseek`, `zhipuai`, `zai`, `moonshotai`, `minimax-cn`, …). - `LLM_PROVIDERS` / `LLMProvider` should be **generated from the models.dev provider snapshot** (plus a small Dexto-only overlay like `dexto-nova`, `openai-compatible`, `ollama`, `local`). - **Backward compatibility is explicitly not required** for legacy provider IDs (e.g. `glm`, `vertex`, `bedrock`) or legacy auth storage. +- **Reasoning toggles alignment:** we have a parallel “reasoning toggles” effort (reasoning presets + harness/CLI toggles). Once `LLMProvider` expands to models.dev provider IDs, reasoning logic must be keyed by **transport kind** (derived from models.dev `provider.npm`), not by a small hardcoded provider enum, so that reasoning presets apply to the full provider set. --- @@ -622,6 +627,9 @@ Implementation note (important): - save API key - use models.dev `provider.api` as baseURL - run via the shared OpenAI-compatible driver + - Align reasoning preset support with the same transport mapping: + - Update provider-options/reasoning logic to branch on **transport kind** (derived from `provider.npm`) instead of provider IDs, so reasoning presets work across all models.dev providers (e.g. `deepseek` should behave like an OpenAI-compatible transport). + - Ensure the LLM factory’s chosen SDK provider keying matches provider-options keys (so providerOptions actually apply). - Exit: - `/connect` can add an API-key profile for *any* models.dev provider whose `provider.npm` maps to an implemented transport, without adding per-provider code. diff --git a/feature-plans/oauth-and-more-providers/WORKING_MEMORY.md b/feature-plans/oauth-and-more-providers/WORKING_MEMORY.md index 8a5ebfb9b..482e06476 100644 --- a/feature-plans/oauth-and-more-providers/WORKING_MEMORY.md +++ b/feature-plans/oauth-and-more-providers/WORKING_MEMORY.md @@ -14,10 +14,18 @@ 5. **If you discover something unexpected:** Add it to "Open Questions / Blockers" or "Key Decisions." 6. **When you discover owner-only decisions or manual checks:** Add/update an item in `USER_VERIFICATION.md` (and mark items resolved when done). +Repo context: +- Worktree: `~/Projects/dexto-worktrees/oauth-provider-revamp` (branch: `oauth-provider-revamp`). +- `feature-plans/` is gitignored for untracked files. Stage commits with `git add -f feature-plans/...`. + --- ## Current Task +**Next planned work (post-merge with “reasoning toggles” branch):** +- Implement Phase **1.5.1** provider snapshot generation and use it to generate `LLM_PROVIDERS` / `LLMProvider` (models.dev canonical IDs + small Dexto-only overlay). +- When expanding provider IDs to models.dev, ensure **reasoning presets** remain correct by keying reasoning/provider-options on the same transport mapping (`provider.npm` → transport kind), not on a small hardcoded provider enum. + **Task:** **Owner review — Updated direction + tasklist rebase** **Status:** _Waiting on owner_ **Branch:** `oauth-provider-revamp` From 75ca29aed6777ed75ae32d68faf996e6a3526f7f Mon Sep 17 00:00:00 2001 From: Rahul Karajgikar <rahul@trytruffle.ai> Date: Thu, 19 Feb 2026 19:58:46 +0530 Subject: [PATCH 17/25] update doc --- feature-plans/oauth-and-more-providers/UPDATED_DIRECTION.md | 1 + 1 file changed, 1 insertion(+) diff --git a/feature-plans/oauth-and-more-providers/UPDATED_DIRECTION.md b/feature-plans/oauth-and-more-providers/UPDATED_DIRECTION.md index 0dad56246..373076327 100644 --- a/feature-plans/oauth-and-more-providers/UPDATED_DIRECTION.md +++ b/feature-plans/oauth-and-more-providers/UPDATED_DIRECTION.md @@ -66,6 +66,7 @@ Notes: - Dexto already has a runtime OpenRouter validator/cache (TTL + throttle) at: - `packages/core/src/llm/providers/openrouter-model-registry.ts` - That runtime cache is great for “is this ID valid?”, but it doesn’t automatically improve our *static* model picker/catalog unless we integrate it into our registry generation or expose it as a dynamic catalog endpoint. +- Dexto Nova gateway is a wrapper on openrouter so it will have the exact same supported model list and names ### 2.3 Also ingest Vercel AI Gateway’s live model catalog From b50bb66ce811d9a7e87efabde3a2d0cfe4a28202 Mon Sep 17 00:00:00 2001 From: Rahul Karajgikar <rahul@trytruffle.ai> Date: Thu, 19 Feb 2026 20:08:51 +0530 Subject: [PATCH 18/25] docs(feature-plans): use deterministic auth slots --- .../oauth-and-more-providers/PLAN.md | 22 +++++++++++++------ .../UPDATED_DIRECTION.md | 4 +++- .../WORKING_MEMORY.md | 7 +++--- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/feature-plans/oauth-and-more-providers/PLAN.md b/feature-plans/oauth-and-more-providers/PLAN.md index cda1a1c7b..9c20669b6 100644 --- a/feature-plans/oauth-and-more-providers/PLAN.md +++ b/feature-plans/oauth-and-more-providers/PLAN.md @@ -310,7 +310,10 @@ Backwards compatibility: - We will require the user to re-login to populate `~/.dexto/auth/dexto.json` (optionally we can add a one-time import command later, but it is not required for v1). `llm-profiles.json` should support: -- Multiple saved profiles per provider, keyed by `profileId` like `${providerId}:${name}` (examples: `openai:work`, `openai:codex-oauth`, `openrouter:team`). +- **Deterministic “auth slots”** per provider+method (no custom naming in v1): + - `profileId = ${providerId}:${methodId}` (e.g. `openai:api_key`, `openai:oauth_codex`). + - Display label is the method label (no user-defined profile names). + - Future (optional): if we ever need *multiple* API keys for the same method, extend with a numeric suffix (e.g. `openai:api_key:2`) without introducing free-form naming. - A per-provider default pointer so most users never touch agent config: - `defaults[providerId] = profileId` - Profile credential modes (`api_key`, `oauth`, `token`, …) with refresh metadata for OAuth (`expiresAt`, `refreshToken`, optional account/org ids). @@ -358,9 +361,9 @@ Reference server API: - Flow: 1) pick provider (curated list first + search; align with `LLM_REGISTRY` curated scope) 2) choose action: - - connect **new** profile, or + - connect/replace the **method slot**, or - switch **default** profile (if profiles exist), or - - manage profiles (remove/rename) (optional v1) + - manage profiles (remove) (optional v1) 3) for “connect new profile”: show supported methods for that provider 4) run method flow: - API key: paste, optional verify, store @@ -530,11 +533,16 @@ Implementation note (important): - [ ] **1.3.1 Finish multi-profile UX (no overwrite)** - Deliverables: - - `/connect` can create **multiple profiles per provider+method** (prompt for a label, generate a unique `profileId`, and do not overwrite existing credentials). - - `/connect` can list existing profiles for a provider and switch the default without re-auth. - - `/connect` can delete a profile (and clears defaults that point at it). + - `/connect` uses **deterministic auth slots** (`profileId = ${providerId}:${methodId}`) and does **not** ask the user to name profiles. + - `/connect` lists existing method slots for a provider and lets the user: + - set default to an existing slot (no re-auth), + - replace credentials for an existing slot (explicit confirmation), + - delete a slot (and clears defaults that point at it). - Exit: - - Manual CLI smoke: connect the same provider twice (two profiles), switch defaults, run each successfully. + - Manual CLI smoke: + - connect a provider with multiple methods (e.g. OpenAI) to create 2 slots (API key + OAuth), + - switch defaults between existing slots without re-auth, + - attempt to reconnect an existing slot and confirm it prompts before replacing. - [ ] **1.4 Route `dexto setup` through the same connect logic** - Deliverables: diff --git a/feature-plans/oauth-and-more-providers/UPDATED_DIRECTION.md b/feature-plans/oauth-and-more-providers/UPDATED_DIRECTION.md index 373076327..dce153326 100644 --- a/feature-plans/oauth-and-more-providers/UPDATED_DIRECTION.md +++ b/feature-plans/oauth-and-more-providers/UPDATED_DIRECTION.md @@ -143,7 +143,9 @@ Shipped building blocks: - `/connect` currently overwrites credentials because `profileId` is fixed to `${providerId}:${methodId}`: - Source: `packages/cli/src/cli/commands/connect/index.ts` - - We need true multi-profile support (prompt for profile label/name, generate stable IDs, and allow switching defaults without re-auth). + - We need “auth slot” UX: keep deterministic IDs, but **don’t silently overwrite**. + - Allow switching defaults without re-auth by selecting an existing slot. + - If the slot already exists, prompt the user to replace credentials (explicit confirm) vs keep existing. ## 5) Changes this implies for the tasklist diff --git a/feature-plans/oauth-and-more-providers/WORKING_MEMORY.md b/feature-plans/oauth-and-more-providers/WORKING_MEMORY.md index 482e06476..4570853c8 100644 --- a/feature-plans/oauth-and-more-providers/WORKING_MEMORY.md +++ b/feature-plans/oauth-and-more-providers/WORKING_MEMORY.md @@ -32,8 +32,8 @@ Repo context: ### Plan - Review the direction update in `feature-plans/oauth-and-more-providers/UPDATED_DIRECTION.md`. -- Confirm the rebaselined tasklist in `feature-plans/oauth-and-more-providers/PLAN.md` (new Phase 1.5 for gateway catalogs; fix `/connect` multi-profile overwrite). -- Once aligned, proceed with **1.3.1** (multi-profile UX) and then Phase 1.5 gateway ingestion (**1.5.2** OpenRouter, **1.5.3** Vercel AI Gateway) in that order. +- Confirm the rebaselined tasklist in `feature-plans/oauth-and-more-providers/PLAN.md` (new Phase 1.5 for gateway catalogs; fix `/connect` “auth slot” overwrite prompts + default switching). +- Once aligned, proceed with **1.3.1** (auth slot UX) and then Phase 1.5 gateway ingestion (**1.5.2** OpenRouter, **1.5.3** Vercel AI Gateway) in that order. ### Notes _Log findings, issues, and progress here as you work._ @@ -43,6 +43,7 @@ _Log findings, issues, and progress here as you work._ - Verified OpenCode’s OpenRouter model list is **limited by models.dev curation** (not OpenRouter’s live `/models`). - Added `UPDATED_DIRECTION.md` and updated `PLAN.md` to adopt a pi-style multi-source model registry direction (models.dev baseline + gateway catalogs, starting with OpenRouter). - Phase 1 scaffolding exists in-repo (profiles store + runtime resolver + server routes + CLI `/connect`), but `/connect` still overwrites profiles because `profileId` is fixed to `${providerId}:${methodId}`. + - Keep deterministic IDs, but add UX to avoid silent overwrites (explicit replace confirmation + “switch default to existing slot”). --- @@ -70,7 +71,7 @@ _Move tasks here after completion. Keep a brief log of what was done and any dev |------|-------|------|-------| | 1.1 | LLM profile store (`llm-profiles.json`) | 2026-02-18 | Implemented file-backed multi-profile store + defaults + tests. | | 1.2 | Server routes for connect providers/profiles/defaults | 2026-02-18 | Added `packages/server/src/hono/routes/llm-connect.ts` (redacted profiles). | -| 1.3 | CLI interactive `/connect` | 2026-02-18 | Added `/connect` flow + initial OAuth method scaffolding; still needs multi-profile IDs. | +| 1.3 | CLI interactive `/connect` | 2026-02-18 | Added `/connect` flow + initial OAuth method scaffolding; still needs auth slot management (no silent overwrite + switch default without re-auth). | | — | Direction + tasklist rebase | 2026-02-18 | Added `UPDATED_DIRECTION.md`; updated tasklist to include gateway catalog ingestion. | --- From c2001201e9aba8ded4df95e6f57fb1dd9dfe3923 Mon Sep 17 00:00:00 2001 From: Rahul Karajgikar <rahul@trytruffle.ai> Date: Thu, 19 Feb 2026 20:59:09 +0530 Subject: [PATCH 19/25] docs(feature-plans): add upstream edge-case audit tasks --- .../oauth-and-more-providers/PLAN.md | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/feature-plans/oauth-and-more-providers/PLAN.md b/feature-plans/oauth-and-more-providers/PLAN.md index 9c20669b6..ad78eb5cb 100644 --- a/feature-plans/oauth-and-more-providers/PLAN.md +++ b/feature-plans/oauth-and-more-providers/PLAN.md @@ -650,6 +650,11 @@ Implementation note (important): - add the provider SDK package + wire it into the LLM factory, or - intentionally defer (with a documented reason), or - treat as OpenAI-compatible via a curated baseURL if the upstream is actually OpenAI-compatible. + - Before implementing each new transport, re-audit upstream transport quirks and record the ones we need: + - OpenCode normalization + providerOptions keying: `~/Projects/external/opencode/packages/opencode/src/provider/transform.ts`, `~/Projects/external/opencode/packages/opencode/src/provider/provider.ts` + - pi-mono transport mapping style + gateway ingestion: `~/Projects/external/pi-mono/packages/ai/scripts/generate-models.ts` + - OpenClaw provider preset/onboard behaviors (when relevant): `~/Projects/external/openclaw/src/commands/onboard-auth.models.ts`, `~/Projects/external/openclaw/src/commands/model-auth.ts` + - Capture findings in `WORKING_MEMORY.md` and add UV items if any behavior is product-sensitive. - Keep the LLM factory table-driven: adding a new `provider.npm` should be a small, isolated change (no switch-case sprawl). - Exit: - `NPM_TRANSPORT_COVERAGE.md` “not covered yet” list shrinks over time, and `/connect` auto-enables newly supported providers without additional UX work. @@ -657,6 +662,16 @@ Implementation note (important): ### Phase 3 — OpenAI ChatGPT OAuth (Codex) > **Goal:** make OAuth a first-class method whose tokens affect runtime requests (not just storage). +- [ ] **3.0 Re-audit upstream Codex OAuth implementations (edge cases)** + - Deliverables: + - Re-read and extract any “must copy” edge cases (PKCE/device-code details, callback state verification, request rewrite behavior, account header extraction): + - OpenCode: `~/Projects/external/opencode/packages/opencode/src/plugin/codex.ts` + - OpenClaw: `~/Projects/external/openclaw/src/commands/openai-codex-oauth.ts`, `~/Projects/external/openclaw/src/commands/openai-codex-oauth.test.ts` + - pi-mono transport split context: `~/Projects/external/pi-mono/packages/ai/scripts/generate-models.ts` (OpenAI “responses vs completions” mapping patterns) + - Update `WORKING_MEMORY.md` with any discovered deltas and add owner-verification items for product-sensitive behavior (allowlisting, redirect URIs, messaging). + - Exit: + - Edge-case checklist captured in working memory; Phase 3 tasks incorporate any required deltas. + - [ ] **3.1 Implement OpenAI OAuth authorize/callback flows + persistence** - Deliverables: - Dexto-owned OpenAI OAuth app config (client ID + allowed redirect URIs) and a safe place to store the client ID (non-secret) in-repo. @@ -681,6 +696,16 @@ Implementation note (important): ### Phase 4 — MiniMax Portal OAuth (device-code/PKCE) > **Goal:** add a second OAuth method (MiniMax) to validate the method registry + refresh patterns beyond OpenAI. +- [ ] **4.0 Re-audit upstream MiniMax Portal OAuth implementations (edge cases)** + - Deliverables: + - Re-read and extract any “must copy” edge cases (device code polling, refresh format, region/resource URL behavior): + - OpenClaw: `~/Projects/external/openclaw/extensions/minimax-portal-auth/oauth.ts`, `~/Projects/external/openclaw/extensions/minimax-portal-auth/index.ts` + - OpenCode provider quirks worth mirroring: `~/Projects/external/opencode/packages/opencode/src/provider/error.ts`, `~/Projects/external/opencode/packages/opencode/src/provider/transform.ts` + - pi-mono transport split context: `~/Projects/external/pi-mono/packages/ai/scripts/generate-models.ts` + - Update `WORKING_MEMORY.md` with any discovered deltas and add UV items for client ID/redirect URI/product decisions. + - Exit: + - Edge-case checklist captured in working memory; Phase 4 tasks incorporate any required deltas. + - [ ] **4.1 Implement MiniMax OAuth authorize/callback flows + persistence** - Deliverables: - Dexto-owned MiniMax OAuth app config (client ID + allowed redirect URIs) OR explicit confirmation that the public client ID we reference is intended for third-party clients. @@ -698,6 +723,16 @@ Implementation note (important): ### Phase 5 — Anthropic setup-token (subscription) (if viable) > **Goal:** add a second “non-api-key” method to validate the model. +- [ ] **5.0 Re-audit upstream Anthropic setup-token handling (edge cases)** + - Deliverables: + - Re-read setup-token validation + UX expectations and capture rules we must match (prefix/length, interactive-only constraints, profile selection): + - OpenClaw: `~/Projects/external/openclaw/src/commands/models/auth.ts`, `~/Projects/external/openclaw/src/commands/auth-token.ts`, `~/Projects/external/openclaw/src/agents/anthropic.setup-token.live.test.ts` + - OpenCode: `~/Projects/external/opencode/packages/opencode/src/provider/transform.ts` (Anthropic message normalization patterns) + - pi-mono: `~/Projects/external/pi-mono/packages/ai/scripts/generate-models.ts` (Anthropic transport mapping patterns) + - Update `WORKING_MEMORY.md` with any discovered deltas and add UV items if feasibility is unclear. + - Exit: + - Edge-case checklist captured in working memory; Phase 5 tasks incorporate any required deltas. + - [ ] **5.1 Add `setup-token` method UX + storage** - Exit: - Token is stored as a profile and can be selected as default. @@ -709,6 +744,16 @@ Implementation note (important): ### Phase 6 — Bedrock + Vertex first-class connect UX > **Goal:** make non-key providers feel “connectable” (guided setup) even if they use ADC/credential chains. +- [ ] **6.0 Re-audit upstream Bedrock/Vertex provider handling (edge cases)** + - Deliverables: + - Re-read upstream provider transforms and capture quirks we need (providerOptions keys, vertex/anthropic handling, fetch overrides): + - OpenCode: `~/Projects/external/opencode/packages/opencode/src/provider/transform.ts` + - pi-mono: `~/Projects/external/pi-mono/packages/ai/scripts/generate-models.ts` + - OpenClaw: `~/Projects/external/openclaw/src/commands/onboard-auth.config-core.ts` and related onboard config files + - Update `WORKING_MEMORY.md` with any discovered deltas and add UV items for UX/policy decisions. + - Exit: + - Edge-case checklist captured in working memory; Phase 6 tasks incorporate any required deltas. + - [ ] **6.1 Add Bedrock connect UX (chain vs bearer token)** - Exit: - Clear UX for “store bearer token” and “use AWS credential chain” paths. From 151774e8918c22ee6a859c9e76156fc366cecfca Mon Sep 17 00:00:00 2001 From: Rahul Karajgikar <rahul@trytruffle.ai> Date: Thu, 19 Feb 2026 21:27:54 +0530 Subject: [PATCH 20/25] docs(feature-plans): align connect API + productionize codex/minimax phases --- .../oauth-and-more-providers/PLAN.md | 51 ++++++++++++------- .../USER_VERIFICATION.md | 1 + 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/feature-plans/oauth-and-more-providers/PLAN.md b/feature-plans/oauth-and-more-providers/PLAN.md index ad78eb5cb..40d7dce3a 100644 --- a/feature-plans/oauth-and-more-providers/PLAN.md +++ b/feature-plans/oauth-and-more-providers/PLAN.md @@ -337,14 +337,16 @@ Reference implementations: ### 7.3 Server API (for WebUI + future remote clients) Add Hono routes in `packages/server/src/hono/routes/` analogous to the existing `/llm/key` surface: -- `GET /llm/auth/methods` → per-provider supported methods (labels + kinds + requirements). -- `GET /llm/auth/profiles` → list saved profiles (masked previews only) + per-provider defaults. -- `POST /llm/auth/profiles` → upsert a profile (API-key, token) or store an OAuth result. -- `POST /llm/auth/defaults` → set `defaults[providerId] = profileId`. -- `POST /llm/auth/api-key` → store BYOK (existing `/llm/key` can remain; we can alias/migrate). -- `POST /llm/auth/oauth/authorize` → returns `{ url, mode: auto|code, instructions, stateId }`. -- `POST /llm/auth/oauth/callback` → completes OAuth (with optional `code`) and persists credential. -- `GET /llm/auth/status` → per-provider connection status + which method is active (no secrets, masked previews only). +- `GET /llm/connect/providers` → per-provider supported methods (labels + kinds + requirements). +- `GET /llm/connect/profiles` → list saved profiles (masked previews only) + per-provider defaults. +- `DELETE /llm/connect/profiles/{profileId}` → delete a profile and clear defaults pointing at it. +- `POST /llm/connect/defaults` → set `defaults[providerId] = profileId` (or clear). + +Future expansions (when WebUI needs to *create* profiles or run OAuth via the server): +- `POST /llm/connect/profiles` → upsert a profile (API-key, token) or store an OAuth result. +- `POST /llm/connect/oauth/authorize` → returns `{ url, mode: auto|code, instructions, stateId }`. +- `POST /llm/connect/oauth/callback` → completes OAuth (with optional `code`) and persists credential. +- `GET /llm/connect/status` → per-provider connection status + which method is active (no secrets, masked previews only). Implementation note: - Even for CLI-only first pass, designing the API as a **two-phase authorize/callback** flow reduces later churn. @@ -662,6 +664,11 @@ Implementation note (important): ### Phase 3 — OpenAI ChatGPT OAuth (Codex) > **Goal:** make OAuth a first-class method whose tokens affect runtime requests (not just storage). +Status (scaffolding already exists in-repo): +- Device-code CLI flow: `packages/cli/src/cli/commands/connect/openai-codex.ts` +- Profile persistence: `packages/agent-management/src/auth/llm-profiles.ts` +- Refresh + runtime overrides (baseURL + fetch wrapper): `packages/agent-management/src/auth/runtime-auth-resolver.ts` + - [ ] **3.0 Re-audit upstream Codex OAuth implementations (edge cases)** - Deliverables: - Re-read and extract any “must copy” edge cases (PKCE/device-code details, callback state verification, request rewrite behavior, account header extraction): @@ -672,30 +679,36 @@ Implementation note (important): - Exit: - Edge-case checklist captured in working memory; Phase 3 tasks incorporate any required deltas. -- [ ] **3.1 Implement OpenAI OAuth authorize/callback flows + persistence** +- [ ] **3.1 Productionize OpenAI Codex OAuth (device-code first)** - Deliverables: - - Dexto-owned OpenAI OAuth app config (client ID + allowed redirect URIs) and a safe place to store the client ID (non-secret) in-repo. - - OAuth flow helper that supports local browser callback and headless/device-code paths. - - Persist token + refresh metadata in the profile store. + - Dexto-owned OpenAI OAuth app config (client ID + allowlisting/redirect URIs policy) and a safe place to store the client ID (non-secret) in-repo. + - Ensure the connect method is **model-scoped** to Codex-capable models (or represented as a separate provider/preset) so it cannot become the default for unrelated OpenAI models. + - Persist token + refresh metadata in the profile store (already implemented; harden + verify). - Allowlist-aware error handling + UX (clear message + fallback to API key). - Exit: - - Manual OAuth connect succeeds (for allowlisted accounts); token is stored; secrets are not logged. + - Manual OAuth connect succeeds (for allowlisted accounts); token is stored; secrets are not logged; default semantics cannot “poison” normal OpenAI usage. -- [ ] **3.2 Implement refresh token logic** +- [ ] **3.2 Harden refresh token logic (existing)** - Deliverables: - Refresh on expiry with safe concurrent refresh behavior. - Exit: - Unit tests cover refresh success/failure and persistence updates. -- [ ] **3.3 Implement runtime wiring in `packages/core/src/llm/services/factory.ts`** +- [ ] **3.3 Harden runtime wiring + request rewrite behavior (existing)** - Deliverables: - Provider-specific runtime overrides for OpenAI OAuth (headers/fetch/baseURL/URL rewrite as needed). + - Ensure any rewrite behavior is gated to the Codex OAuth method and Codex-scoped models. - Exit: - Regression tests cover request rewrite correctness (unit-level; network mocked). ### Phase 4 — MiniMax Portal OAuth (device-code/PKCE) > **Goal:** add a second OAuth method (MiniMax) to validate the method registry + refresh patterns beyond OpenAI. +Status (scaffolding already exists in-repo): +- Device-code CLI flow: `packages/cli/src/cli/commands/connect/minimax-portal.ts` +- Profile persistence: `packages/agent-management/src/auth/llm-profiles.ts` +- Refresh + runtime overrides (resource URL/baseURL + fetch wrapper): `packages/agent-management/src/auth/runtime-auth-resolver.ts` + - [ ] **4.0 Re-audit upstream MiniMax Portal OAuth implementations (edge cases)** - Deliverables: - Re-read and extract any “must copy” edge cases (device code polling, refresh format, region/resource URL behavior): @@ -706,17 +719,17 @@ Implementation note (important): - Exit: - Edge-case checklist captured in working memory; Phase 4 tasks incorporate any required deltas. -- [ ] **4.1 Implement MiniMax OAuth authorize/callback flows + persistence** +- [ ] **4.1 Productionize MiniMax Portal OAuth (device-code first)** - Deliverables: - Dexto-owned MiniMax OAuth app config (client ID + allowed redirect URIs) OR explicit confirmation that the public client ID we reference is intended for third-party clients. - - Device-code/PKCE-style flow modeled after OpenClaw’s implementation: + - Device-code flow modeled after OpenClaw’s implementation: - `~/Projects/external/openclaw/extensions/minimax-portal-auth/oauth.ts` - `~/Projects/external/openclaw/extensions/minimax-portal-auth/index.ts` - - Persist token + refresh metadata in the profile store. + - Persist token + refresh metadata in the profile store (already implemented; harden + verify). - Exit: - Manual MiniMax OAuth connect succeeds; token is stored; secrets are not logged. -- [ ] **4.2 Implement refresh token logic + runtime usage** +- [ ] **4.2 Harden refresh token logic + runtime usage (existing)** - Exit: - Confirm the runtime auth material needed by MiniMax (bearer token vs derived API key) and implement refresh accordingly. diff --git a/feature-plans/oauth-and-more-providers/USER_VERIFICATION.md b/feature-plans/oauth-and-more-providers/USER_VERIFICATION.md index 44ba4ced5..b769b62f9 100644 --- a/feature-plans/oauth-and-more-providers/USER_VERIFICATION.md +++ b/feature-plans/oauth-and-more-providers/USER_VERIFICATION.md @@ -30,6 +30,7 @@ | UV-11 | Manual smoke: OpenAI OAuth runtime behavior | Requires real OAuth account + network | Phase 3 | Open | Verify token refresh + request rewrite works end-to-end (including Responses API behavior). | | UV-12 | Manual smoke: WebUI parity | Requires running WebUI | Phase 7 | Open | Verify WebUI reflects method-based auth and doesn’t regress existing API key settings. | | UV-13 | “Ancient model” visibility policy | Product UX / defaults | 1.5.4 | Open | Decide whether we should ship an explicit time-window filter (eg “hide models older than X months”), and if so, which metadata to trust (`release_date`, `last_updated`, `status`). | +| UV-14 | Codex OAuth model scope + default semantics | Product UX + avoids breaking non-Codex OpenAI usage | 3.1 | Open | Decide whether Codex OAuth is (a) model-gated within `openai`, or (b) represented as a separate provider/preset (e.g. `openai-codex`). Ensure setting it as a default cannot affect unrelated OpenAI models. | --- From 83f130b76eb9990fe267a3297bd6daf631f5b248 Mon Sep 17 00:00:00 2001 From: Rahul Karajgikar <rahul@trytruffle.ai> Date: Fri, 20 Feb 2026 14:10:52 +0530 Subject: [PATCH 21/25] feat(cli): improve /connect auth slot UX --- .../src/cli/commands/connect/index.test.ts | 160 ++++++++++++++++++ .../cli/src/cli/commands/connect/index.ts | 101 +++++++++-- 2 files changed, 250 insertions(+), 11 deletions(-) create mode 100644 packages/cli/src/cli/commands/connect/index.test.ts diff --git a/packages/cli/src/cli/commands/connect/index.test.ts b/packages/cli/src/cli/commands/connect/index.test.ts new file mode 100644 index 000000000..961207162 --- /dev/null +++ b/packages/cli/src/cli/commands/connect/index.test.ts @@ -0,0 +1,160 @@ +import { beforeEach, describe, expect, it, vi } from 'vitest'; + +import { handleConnectCommand } from './index.js'; +import type { LlmAuthProfile } from '@dexto/agent-management'; + +vi.mock('open', () => ({ default: vi.fn() })); + +vi.mock('@clack/prompts', () => ({ + intro: vi.fn(), + outro: vi.fn(), + cancel: vi.fn(), + select: vi.fn(), + password: vi.fn(), + confirm: vi.fn(), + spinner: vi.fn(() => ({ start: vi.fn(), stop: vi.fn(), message: vi.fn() })), + isCancel: vi.fn(() => false), + log: { warn: vi.fn(), success: vi.fn(), error: vi.fn(), info: vi.fn() }, +})); + +vi.mock('@dexto/agent-management', () => { + const CONNECT_PROVIDERS = [ + { + providerId: 'openai', + label: 'OpenAI', + methods: [{ id: 'api_key', label: 'API key', kind: 'api_key' }], + }, + ]; + + return { + CONNECT_PROVIDERS, + getConnectProvider: vi.fn((providerId: string) => { + return CONNECT_PROVIDERS.find((p) => p.providerId === providerId) ?? null; + }), + listLlmAuthProfiles: vi.fn(), + getDefaultLlmAuthProfileId: vi.fn(), + setDefaultLlmAuthProfile: vi.fn(), + upsertLlmAuthProfile: vi.fn(), + deleteLlmAuthProfile: vi.fn(), + }; +}); + +function makeProfile(params: { + profileId: string; + providerId: string; + methodId: string; +}): LlmAuthProfile { + return { + profileId: params.profileId, + providerId: params.providerId, + methodId: params.methodId, + label: 'Test label', + credential: { type: 'api_key', key: 'sk-test-123' }, + createdAt: Date.now(), + updatedAt: Date.now(), + }; +} + +describe('/connect command (auth slots)', () => { + beforeEach(async () => { + vi.clearAllMocks(); + + const prompts = await import('@clack/prompts'); + vi.mocked(prompts.isCancel).mockReturnValue(false); + }); + + it('creates a new api_key slot and sets default', async () => { + const prompts = await import('@clack/prompts'); + const agentManagement = await import('@dexto/agent-management'); + + vi.mocked(prompts.select).mockResolvedValueOnce('openai'); + vi.mocked(prompts.password).mockResolvedValueOnce('sk-live-1234567890'); + + vi.mocked(agentManagement.listLlmAuthProfiles).mockResolvedValueOnce([]); + vi.mocked(agentManagement.getDefaultLlmAuthProfileId).mockResolvedValueOnce(null); + + await handleConnectCommand({ interactive: true }); + + expect(agentManagement.upsertLlmAuthProfile).toHaveBeenCalledWith( + expect.objectContaining({ + profileId: 'openai:api_key', + providerId: 'openai', + methodId: 'api_key', + credential: { type: 'api_key', key: 'sk-live-1234567890' }, + }) + ); + expect(agentManagement.setDefaultLlmAuthProfile).toHaveBeenCalledWith({ + providerId: 'openai', + profileId: 'openai:api_key', + }); + }); + + it('uses existing slot (no re-auth) and sets default', async () => { + const prompts = await import('@clack/prompts'); + const agentManagement = await import('@dexto/agent-management'); + + vi.mocked(prompts.select) + .mockResolvedValueOnce('openai') // provider + .mockResolvedValueOnce('use_existing'); // action + + vi.mocked(agentManagement.listLlmAuthProfiles).mockResolvedValueOnce([ + makeProfile({ profileId: 'openai:api_key', providerId: 'openai', methodId: 'api_key' }), + ]); + vi.mocked(agentManagement.getDefaultLlmAuthProfileId).mockResolvedValueOnce(null); + + await handleConnectCommand({ interactive: true }); + + expect(agentManagement.setDefaultLlmAuthProfile).toHaveBeenCalledWith({ + providerId: 'openai', + profileId: 'openai:api_key', + }); + expect(agentManagement.upsertLlmAuthProfile).not.toHaveBeenCalled(); + expect(prompts.password).not.toHaveBeenCalled(); + }); + + it('replaces an existing slot when requested', async () => { + const prompts = await import('@clack/prompts'); + const agentManagement = await import('@dexto/agent-management'); + + vi.mocked(prompts.select) + .mockResolvedValueOnce('openai') // provider + .mockResolvedValueOnce('replace'); // action + vi.mocked(prompts.password).mockResolvedValueOnce('sk-new-1234567890'); + + vi.mocked(agentManagement.listLlmAuthProfiles).mockResolvedValueOnce([ + makeProfile({ profileId: 'openai:api_key', providerId: 'openai', methodId: 'api_key' }), + ]); + vi.mocked(agentManagement.getDefaultLlmAuthProfileId).mockResolvedValueOnce( + 'openai:api_key' + ); + + await handleConnectCommand({ interactive: true }); + + expect(agentManagement.upsertLlmAuthProfile).toHaveBeenCalledWith( + expect.objectContaining({ + profileId: 'openai:api_key', + credential: { type: 'api_key', key: 'sk-new-1234567890' }, + }) + ); + }); + + it('deletes an existing slot when requested', async () => { + const prompts = await import('@clack/prompts'); + const agentManagement = await import('@dexto/agent-management'); + + vi.mocked(prompts.select) + .mockResolvedValueOnce('openai') // provider + .mockResolvedValueOnce('delete'); // action + vi.mocked(prompts.confirm).mockResolvedValueOnce(true); + + vi.mocked(agentManagement.listLlmAuthProfiles).mockResolvedValueOnce([ + makeProfile({ profileId: 'openai:api_key', providerId: 'openai', methodId: 'api_key' }), + ]); + vi.mocked(agentManagement.getDefaultLlmAuthProfileId).mockResolvedValueOnce(null); + + await handleConnectCommand({ interactive: true }); + + expect(agentManagement.deleteLlmAuthProfile).toHaveBeenCalledWith('openai:api_key'); + expect(agentManagement.upsertLlmAuthProfile).not.toHaveBeenCalled(); + }); +}); diff --git a/packages/cli/src/cli/commands/connect/index.ts b/packages/cli/src/cli/commands/connect/index.ts index 036fb8fa0..7d99f010e 100644 --- a/packages/cli/src/cli/commands/connect/index.ts +++ b/packages/cli/src/cli/commands/connect/index.ts @@ -5,9 +5,11 @@ import open from 'open'; import { CONNECT_PROVIDERS, getConnectProvider, + deleteLlmAuthProfile, + getDefaultLlmAuthProfileId, + listLlmAuthProfiles, setDefaultLlmAuthProfile, upsertLlmAuthProfile, - type ConnectMethod, } from '@dexto/agent-management'; import { extractChatGptAccountId, loginOpenAiCodexDeviceCode } from './openai-codex.js'; @@ -26,19 +28,17 @@ function toProviderOption(provider: (typeof CONNECT_PROVIDERS)[number]): p.Optio }; } -function toMethodOption(method: ConnectMethod): p.Option<string> { - const hint = method.hint?.trim(); - return { - value: method.id, - label: method.label, - ...(hint ? { hint } : {}), - }; -} - function defaultProfileId(providerId: string, methodId: string): string { return `${providerId}:${methodId}`; } +function combineHint(...parts: Array<string | undefined>): string | undefined { + const cleaned = parts + .map((p) => p?.trim()) + .filter((p): p is string => Boolean(p && p.length > 0)); + return cleaned.length > 0 ? cleaned.join(' — ') : undefined; +} + export async function handleConnectCommand(options?: { interactive?: boolean }): Promise<void> { if (options?.interactive === false) { throw new Error('Non-interactive connect is not implemented yet'); @@ -62,12 +62,31 @@ export async function handleConnectCommand(options?: { interactive?: boolean }): return; } + const existingProfiles = await listLlmAuthProfiles({ providerId: provider.providerId }); + const existingByProfileId = new Map(existingProfiles.map((p) => [p.profileId, p])); + const defaultProfileIdForProvider = await getDefaultLlmAuthProfileId(provider.providerId); + const methodId = provider.methods.length === 1 ? provider.methods[0]!.id : await p.select({ message: `Choose a login method for ${provider.label}`, - options: provider.methods.map(toMethodOption), + options: provider.methods.map((method) => { + const profileId = defaultProfileId(provider.providerId, method.id); + const existing = existingByProfileId.get(profileId); + const connectedHint = + defaultProfileIdForProvider === profileId + ? 'Connected (default)' + : existing + ? 'Connected' + : undefined; + const hint = combineHint(connectedHint, method.hint); + return { + value: method.id, + label: method.label, + ...(hint ? { hint } : {}), + }; + }), }); if (isCancel(methodId)) { @@ -82,6 +101,66 @@ export async function handleConnectCommand(options?: { interactive?: boolean }): } const profileId = defaultProfileId(provider.providerId, method.id); + const existingProfile = existingByProfileId.get(profileId); + + if (existingProfile) { + const action = await p.select({ + message: `A ${method.label} connection already exists for ${provider.label}.`, + options: [ + { + value: 'use_existing', + label: + defaultProfileIdForProvider === profileId + ? 'Keep as default' + : 'Use existing (set default)', + hint: + defaultProfileIdForProvider === profileId + ? 'No changes' + : 'No re-auth required', + }, + { + value: 'replace', + label: 'Replace credentials', + hint: 'Requires re-auth / re-entering secrets', + }, + { + value: 'delete', + label: 'Delete credentials', + hint: + defaultProfileIdForProvider === profileId + ? 'Removes slot and clears default' + : 'Removes slot', + }, + ], + }); + + if (isCancel(action)) { + p.cancel('Connect cancelled'); + return; + } + + if (action === 'use_existing') { + await setDefaultLlmAuthProfile({ providerId: provider.providerId, profileId }); + p.outro(chalk.green(`✅ Set default ${provider.label} auth to ${method.label}`)); + return; + } + + if (action === 'delete') { + const confirmed = await p.confirm({ + message: `Delete saved ${method.label} credentials for ${provider.label}?`, + initialValue: false, + }); + + if (p.isCancel(confirmed) || !confirmed) { + p.cancel('Connect cancelled'); + return; + } + + await deleteLlmAuthProfile(profileId); + p.outro(chalk.green(`✅ Deleted ${provider.label} credentials for ${method.label}`)); + return; + } + } if (method.kind === 'api_key') { const apiKey = await p.password({ From 950251286e775e7356f0ec11a7022d72b5474d93 Mon Sep 17 00:00:00 2001 From: Rahul Karajgikar <rahul@trytruffle.ai> Date: Fri, 20 Feb 2026 14:11:13 +0530 Subject: [PATCH 22/25] docs(feature-plans): mark 1.3.1 complete --- .../oauth-and-more-providers/PLAN.md | 2 +- .../WORKING_MEMORY.md | 20 +++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/feature-plans/oauth-and-more-providers/PLAN.md b/feature-plans/oauth-and-more-providers/PLAN.md index 40d7dce3a..bb9c0b265 100644 --- a/feature-plans/oauth-and-more-providers/PLAN.md +++ b/feature-plans/oauth-and-more-providers/PLAN.md @@ -533,7 +533,7 @@ Implementation note (important): - Exit: - Manual CLI smoke: connect an API-key provider, set default, and confirm Dexto can run using it. -- [ ] **1.3.1 Finish multi-profile UX (no overwrite)** +- [x] **1.3.1 Finish multi-profile UX (no overwrite)** - Deliverables: - `/connect` uses **deterministic auth slots** (`profileId = ${providerId}:${methodId}`) and does **not** ask the user to name profiles. - `/connect` lists existing method slots for a provider and lets the user: diff --git a/feature-plans/oauth-and-more-providers/WORKING_MEMORY.md b/feature-plans/oauth-and-more-providers/WORKING_MEMORY.md index 4570853c8..fb552e245 100644 --- a/feature-plans/oauth-and-more-providers/WORKING_MEMORY.md +++ b/feature-plans/oauth-and-more-providers/WORKING_MEMORY.md @@ -22,18 +22,14 @@ Repo context: ## Current Task -**Next planned work (post-merge with “reasoning toggles” branch):** -- Implement Phase **1.5.1** provider snapshot generation and use it to generate `LLM_PROVIDERS` / `LLMProvider` (models.dev canonical IDs + small Dexto-only overlay). -- When expanding provider IDs to models.dev, ensure **reasoning presets** remain correct by keying reasoning/provider-options on the same transport mapping (`provider.npm` → transport kind), not on a small hardcoded provider enum. - -**Task:** **Owner review — Updated direction + tasklist rebase** -**Status:** _Waiting on owner_ +**Task:** **1.5.1 Generate provider snapshot + make `LLMProvider` generated** +**Status:** _Not started_ **Branch:** `oauth-provider-revamp` ### Plan -- Review the direction update in `feature-plans/oauth-and-more-providers/UPDATED_DIRECTION.md`. -- Confirm the rebaselined tasklist in `feature-plans/oauth-and-more-providers/PLAN.md` (new Phase 1.5 for gateway catalogs; fix `/connect` “auth slot” overwrite prompts + default switching). -- Once aligned, proceed with **1.3.1** (auth slot UX) and then Phase 1.5 gateway ingestion (**1.5.2** OpenRouter, **1.5.3** Vercel AI Gateway) in that order. +- Implement Phase **1.5.1** provider snapshot generation and use it to generate `LLM_PROVIDERS` / `LLMProvider` (models.dev canonical IDs + small Dexto-only overlay). +- When expanding provider IDs to models.dev, ensure **reasoning presets** remain correct by keying reasoning/provider-options on the same transport mapping (`provider.npm` → transport kind), not on a small hardcoded provider enum. +- After 1.5.1, proceed with gateway ingestion (**1.5.2** OpenRouter, **1.5.3** Vercel AI Gateway). ### Notes _Log findings, issues, and progress here as you work._ @@ -45,6 +41,9 @@ _Log findings, issues, and progress here as you work._ - Phase 1 scaffolding exists in-repo (profiles store + runtime resolver + server routes + CLI `/connect`), but `/connect` still overwrites profiles because `profileId` is fixed to `${providerId}:${methodId}`. - Keep deterministic IDs, but add UX to avoid silent overwrites (explicit replace confirmation + “switch default to existing slot”). +2026-02-20: +- Completed **1.3.1**: `/connect` now prompts when an auth slot already exists, supports “use existing” (set default without re-auth), explicit replace, and delete (clears defaults). + --- ## Key Decisions @@ -71,7 +70,8 @@ _Move tasks here after completion. Keep a brief log of what was done and any dev |------|-------|------|-------| | 1.1 | LLM profile store (`llm-profiles.json`) | 2026-02-18 | Implemented file-backed multi-profile store + defaults + tests. | | 1.2 | Server routes for connect providers/profiles/defaults | 2026-02-18 | Added `packages/server/src/hono/routes/llm-connect.ts` (redacted profiles). | -| 1.3 | CLI interactive `/connect` | 2026-02-18 | Added `/connect` flow + initial OAuth method scaffolding; still needs auth slot management (no silent overwrite + switch default without re-auth). | +| 1.3 | CLI interactive `/connect` | 2026-02-18 | Added `/connect` flow + initial OAuth method scaffolding. | +| 1.3.1 | Multi-profile UX (no overwrite) | 2026-02-20 | Added existing-slot action prompt (use existing / replace / delete) + connected/default hints in method picker + tests. | | — | Direction + tasklist rebase | 2026-02-18 | Added `UPDATED_DIRECTION.md`; updated tasklist to include gateway catalog ingestion. | --- From 76795d4fad96574a0f2f7a6149e9c631aebc8a8b Mon Sep 17 00:00:00 2001 From: Rahul Karajgikar <rahul@trytruffle.ai> Date: Mon, 23 Feb 2026 22:34:32 +0530 Subject: [PATCH 23/25] feat(llm): canonical provider ids + safer model inference --- package.json | 4 +- .../src/auth/connect-catalog.ts | 19 +- packages/agent-management/src/index.ts | 2 +- .../src/models/custom-models.ts | 9 +- .../src/utils/api-key-resolver.ts | 89 +- .../src/utils/api-key-store.ts | 4 +- packages/cli/src/cli/commands/setup.ts | 15 +- .../overlays/ModelSelectorRefactored.tsx | 30 +- .../custom-model-wizard/provider-config.ts | 52 +- .../cli/ink-cli/utils/llm-provider-display.ts | 8 +- .../cli/src/cli/utils/api-key-verification.ts | 10 +- packages/cli/src/cli/utils/provider-setup.ts | 30 +- packages/cli/src/config/cli-overrides.ts | 45 +- packages/core/src/llm/curation-config.ts | 6 +- .../core/src/llm/executor/provider-options.ts | 6 +- .../core/src/llm/executor/stream-processor.ts | 2 +- packages/core/src/llm/formatters/vercel.ts | 4 +- packages/core/src/llm/providers.generated.ts | 908 + .../core/src/llm/registry/auto-update.test.ts | 8 +- packages/core/src/llm/registry/auto-update.ts | 8 +- packages/core/src/llm/registry/index.test.ts | 80 +- packages/core/src/llm/registry/index.ts | 276 +- .../core/src/llm/registry/models.generated.ts | 36590 ++++++++++++++-- .../core/src/llm/registry/models.manual.ts | 2 +- packages/core/src/llm/registry/sync.ts | 296 +- packages/core/src/llm/resolver.ts | 16 +- packages/core/src/llm/services/factory.ts | 55 +- .../llm/services/test-utils.integration.ts | 26 +- packages/core/src/llm/types.ts | 34 +- packages/core/src/utils/api-key-resolver.ts | 103 +- .../ModelPicker/CompactModelCard.tsx | 10 +- .../ModelPicker/CustomModelForms.tsx | 10 +- .../components/ModelPicker/ModelCard.tsx | 19 +- .../ModelPicker/ModelPickerModal.tsx | 4 +- .../components/ModelPicker/constants.tsx | 18 +- .../settings/sections/ApiKeysSection.tsx | 5 +- ...ync-llm-registry.ts => sync-llm-models.ts} | 478 +- 37 files changed, 34935 insertions(+), 4346 deletions(-) create mode 100644 packages/core/src/llm/providers.generated.ts rename scripts/{sync-llm-registry.ts => sync-llm-models.ts} (52%) diff --git a/package.json b/package.json index a920f7702..c549ce6d4 100644 --- a/package.json +++ b/package.json @@ -51,8 +51,8 @@ "repo:typecheck": "turbo run typecheck", "sync-openapi-docs": "tsx scripts/generate-openapi-spec.ts", "sync-openapi-docs:check": "tsx scripts/generate-openapi-spec.ts --check", - "sync-llm-registry": "tsx scripts/sync-llm-registry.ts", - "sync-llm-registry:check": "tsx scripts/sync-llm-registry.ts --check", + "sync-llm-models": "tsx scripts/sync-llm-models.ts", + "sync-llm-models:check": "tsx scripts/sync-llm-models.ts --check", "start": "pnpm -C packages/cli start", "test": "vitest run", "test:ci": "vitest run --coverage", diff --git a/packages/agent-management/src/auth/connect-catalog.ts b/packages/agent-management/src/auth/connect-catalog.ts index 25f9851ed..e616f7be3 100644 --- a/packages/agent-management/src/auth/connect-catalog.ts +++ b/packages/agent-management/src/auth/connect-catalog.ts @@ -155,7 +155,7 @@ export const CONNECT_PROVIDERS: ConnectProvider[] = [ ], }, { - providerId: 'bedrock', + providerId: 'amazon-bedrock', label: 'Amazon Bedrock', modelsDevProviderId: 'amazon-bedrock', methods: [ @@ -168,8 +168,8 @@ export const CONNECT_PROVIDERS: ConnectProvider[] = [ ], }, { - providerId: 'vertex', - label: 'Google Vertex AI', + providerId: 'google-vertex', + label: 'Google Vertex AI (Gemini)', modelsDevProviderId: 'google-vertex', methods: [ { @@ -180,6 +180,19 @@ export const CONNECT_PROVIDERS: ConnectProvider[] = [ }, ], }, + { + providerId: 'google-vertex-anthropic', + label: 'Google Vertex AI (Claude)', + modelsDevProviderId: 'google-vertex-anthropic', + methods: [ + { + id: 'guidance', + label: 'Guided setup', + kind: 'guidance', + hint: 'Use Application Default Credentials (gcloud auth application-default login)', + }, + ], + }, ]; export function getConnectProvider(providerId: string): ConnectProvider | null { diff --git a/packages/agent-management/src/index.ts b/packages/agent-management/src/index.ts index 6eb01d5f3..e56ae9693 100644 --- a/packages/agent-management/src/index.ts +++ b/packages/agent-management/src/index.ts @@ -165,7 +165,7 @@ export { export { resolveApiKeyForProvider, getPrimaryApiKeyEnvVar, - PROVIDER_API_KEY_MAP, + getApiKeyEnvVarsForProvider, } from './utils/api-key-resolver.js'; // Custom models diff --git a/packages/agent-management/src/models/custom-models.ts b/packages/agent-management/src/models/custom-models.ts index 9b05f21eb..0bd37d320 100644 --- a/packages/agent-management/src/models/custom-models.ts +++ b/packages/agent-management/src/models/custom-models.ts @@ -16,10 +16,11 @@ export const CUSTOM_MODEL_PROVIDERS = [ 'openrouter', 'litellm', 'glama', - 'bedrock', + 'amazon-bedrock', 'ollama', 'local', - 'vertex', + 'google-vertex', + 'google-vertex-anthropic', 'dexto-nova', ] as const; export type CustomModelProvider = (typeof CUSTOM_MODEL_PROVIDERS)[number]; @@ -30,10 +31,10 @@ export type CustomModelProvider = (typeof CUSTOM_MODEL_PROVIDERS)[number]; * - openrouter: baseURL is auto-injected, maxInputTokens from registry * - litellm: requires baseURL, uses LITELLM_API_KEY or per-model override * - glama: fixed baseURL, uses GLAMA_API_KEY or per-model override - * - bedrock: no baseURL, uses AWS credentials from environment + * - amazon-bedrock: no baseURL, uses AWS credentials from environment * - ollama: optional baseURL (defaults to http://localhost:11434) * - local: no baseURL, uses local GGUF files via node-llama-cpp - * - vertex: no baseURL, uses Google Cloud ADC + * - google-vertex/google-vertex-anthropic: no baseURL, uses Google Cloud ADC * - dexto-nova: OpenRouter gateway using Dexto credits, requires auth login, uses OpenRouter model IDs * * TODO: For hosted deployments, API keys should be stored in a secure diff --git a/packages/agent-management/src/utils/api-key-resolver.ts b/packages/agent-management/src/utils/api-key-resolver.ts index 956a593fd..f581bf693 100644 --- a/packages/agent-management/src/utils/api-key-resolver.ts +++ b/packages/agent-management/src/utils/api-key-resolver.ts @@ -1,84 +1,5 @@ -import type { LLMProvider } from '@dexto/core'; - -/** - * Utility for resolving API keys from environment variables. - * This consolidates the API key resolution logic used across CLI and core components. - */ - -// Map the provider to its corresponding API key name (in order of preference) -export const PROVIDER_API_KEY_MAP: Record<LLMProvider, string[]> = { - openai: ['OPENAI_API_KEY', 'OPENAI_KEY'], - 'openai-compatible': ['OPENAI_API_KEY', 'OPENAI_KEY'], // Uses same keys as openai - anthropic: ['ANTHROPIC_API_KEY', 'ANTHROPIC_KEY', 'CLAUDE_API_KEY'], - google: ['GOOGLE_GENERATIVE_AI_API_KEY', 'GOOGLE_API_KEY', 'GEMINI_API_KEY'], - groq: ['GROQ_API_KEY'], - cohere: ['COHERE_API_KEY'], - xai: ['XAI_API_KEY', 'X_AI_API_KEY'], - minimax: ['MINIMAX_API_KEY'], - 'minimax-cn': ['MINIMAX_API_KEY'], - 'minimax-coding-plan': ['MINIMAX_API_KEY'], - 'minimax-cn-coding-plan': ['MINIMAX_API_KEY'], - glm: ['ZHIPU_API_KEY', 'ZHIPUAI_API_KEY'], - zhipuai: ['ZHIPU_API_KEY', 'ZHIPUAI_API_KEY'], - 'zhipuai-coding-plan': ['ZHIPU_API_KEY', 'ZHIPUAI_API_KEY'], - zai: ['ZHIPU_API_KEY'], - 'zai-coding-plan': ['ZHIPU_API_KEY'], - moonshotai: ['MOONSHOT_API_KEY'], - 'moonshotai-cn': ['MOONSHOT_API_KEY'], - 'kimi-for-coding': ['KIMI_API_KEY'], - openrouter: ['OPENROUTER_API_KEY'], - litellm: ['LITELLM_API_KEY', 'LITELLM_KEY'], - glama: ['GLAMA_API_KEY'], - // Vertex uses ADC (Application Default Credentials), not API keys - // GOOGLE_APPLICATION_CREDENTIALS points to service account JSON (optional) - // Primary config is GOOGLE_VERTEX_PROJECT (required) + GOOGLE_VERTEX_LOCATION (optional) - vertex: [], - // Bedrock supports two auth methods: - // 1. AWS_BEARER_TOKEN_BEDROCK - Bedrock API key (simplest) - // 2. AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY + AWS_REGION (IAM credentials) - // AWS_SESSION_TOKEN (optional, for temporary credentials) - bedrock: ['AWS_BEARER_TOKEN_BEDROCK'], - // Local providers don't require API keys - local: [], // Native node-llama-cpp execution - ollama: [], // Ollama server (may optionally use OLLAMA_API_KEY for remote servers) - // Dexto gateway - requires key from `dexto login` - 'dexto-nova': ['DEXTO_API_KEY'], - // perplexity: ['PERPLEXITY_API_KEY'], - // together: ['TOGETHER_API_KEY'], - // fireworks: ['FIREWORKS_API_KEY'], - // deepseek: ['DEEPSEEK_API_KEY'], -}; - -/** - * Resolves API key for a given provider from environment variables. - * - * @param provider The LLM provider - * @returns Resolved API key or undefined if not found - */ -export function resolveApiKeyForProvider(provider: LLMProvider): string | undefined { - const envVars = PROVIDER_API_KEY_MAP[provider]; - if (!envVars) { - return undefined; - } - - // Try each environment variable in order of preference - for (const envVar of envVars) { - const value = process.env[envVar]; - if (value && value.trim()) { - return value.trim(); - } - } - - return undefined; -} - -/** - * Gets the primary environment variable name for a provider (for display/error messages). - * - * @param provider The LLM provider - * @returns Primary environment variable name - */ -export function getPrimaryApiKeyEnvVar(provider: LLMProvider): string { - const envVars = PROVIDER_API_KEY_MAP[provider]; - return envVars?.[0] || `${provider.toUpperCase()}_API_KEY`; -} +export { + getApiKeyEnvVarsForProvider, + getPrimaryApiKeyEnvVar, + resolveApiKeyForProvider, +} from '@dexto/core'; diff --git a/packages/agent-management/src/utils/api-key-store.ts b/packages/agent-management/src/utils/api-key-store.ts index f8d979563..8ca49f6e1 100644 --- a/packages/agent-management/src/utils/api-key-store.ts +++ b/packages/agent-management/src/utils/api-key-store.ts @@ -41,7 +41,7 @@ export function getProviderKeyStatus(provider: LLMProvider): { // // TODO: Improve Vertex setup flow - add dedicated setup modal with these instructions // For now, we check GOOGLE_VERTEX_PROJECT as the "key" equivalent - if (provider === 'vertex') { + if (provider === 'google-vertex' || provider === 'google-vertex-anthropic') { const projectId = process.env.GOOGLE_VERTEX_PROJECT; return { hasApiKey: Boolean(projectId && projectId.trim()), @@ -54,7 +54,7 @@ export function getProviderKeyStatus(provider: LLMProvider): { // 2. AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY + AWS_REGION (IAM credentials, for production) // // We check for API key first, then fall back to checking AWS_REGION - if (provider === 'bedrock') { + if (provider === 'amazon-bedrock') { const apiKey = process.env.AWS_BEARER_TOKEN_BEDROCK; if (apiKey && apiKey.trim()) { return { diff --git a/packages/cli/src/cli/commands/setup.ts b/packages/cli/src/cli/commands/setup.ts index fa2ecbd92..1bff6a7db 100644 --- a/packages/cli/src/cli/commands/setup.ts +++ b/packages/cli/src/cli/commands/setup.ts @@ -1304,10 +1304,11 @@ async function promptCustomModelValues( 'openrouter', 'litellm', 'glama', - 'bedrock', + 'amazon-bedrock', 'ollama', 'local', - 'vertex', + 'google-vertex', + 'google-vertex-anthropic', ...(isDextoAuthEnabled() ? ['dexto-nova'] : []), ] as const; @@ -1400,7 +1401,11 @@ async function promptCustomModelValues( } let apiKey: string | undefined; - if (provider !== 'bedrock' && provider !== 'vertex') { + if ( + provider !== 'amazon-bedrock' && + provider !== 'google-vertex' && + provider !== 'google-vertex-anthropic' + ) { const apiKeyInput = await p.text({ message: 'API key (optional)', initialValue: initialModel?.apiKey ?? '', @@ -1928,7 +1933,7 @@ async function updateApiKey(currentProvider?: LLMProvider): Promise<void> { } // Handle providers that use non-API-key authentication - if (provider === 'vertex') { + if (provider === 'google-vertex' || provider === 'google-vertex-anthropic') { p.note( `Google Vertex AI uses Application Default Credentials (ADC).\n\n` + `To authenticate:\n` + @@ -1940,7 +1945,7 @@ async function updateApiKey(currentProvider?: LLMProvider): Promise<void> { return; } - if (provider === 'bedrock') { + if (provider === 'amazon-bedrock') { p.note( `Amazon Bedrock uses AWS credentials.\n\n` + `To authenticate, set these environment variables:\n` + diff --git a/packages/cli/src/cli/ink-cli/components/overlays/ModelSelectorRefactored.tsx b/packages/cli/src/cli/ink-cli/components/overlays/ModelSelectorRefactored.tsx index d6ff7cf3d..d970dbe67 100644 --- a/packages/cli/src/cli/ink-cli/components/overlays/ModelSelectorRefactored.tsx +++ b/packages/cli/src/cli/ink-cli/components/overlays/ModelSelectorRefactored.tsx @@ -244,13 +244,12 @@ const ModelSelector = forwardRef<ModelSelectorHandle, ModelSelectorProps>(functi provider === 'openai-compatible' || provider === 'openrouter' || provider === 'litellm' || - provider === 'glama' || - provider === 'bedrock' + provider === 'glama' ) continue; - // Skip ollama, local, and vertex - they'll be added dynamically below - if (provider === 'ollama' || provider === 'local' || provider === 'vertex') { + // Skip ollama and local - they'll be added dynamically below + if (provider === 'ollama' || provider === 'local') { continue; } @@ -328,29 +327,6 @@ const ModelSelector = forwardRef<ModelSelectorHandle, ModelSelectorProps>(functi }); } - // Add Vertex AI models from registry - const vertexModels = allModels['vertex']; - if (vertexModels) { - for (const model of vertexModels) { - modelList.push({ - provider: 'vertex', - name: model.name, - displayName: model.displayName, - maxInputTokens: model.maxInputTokens, - isDefault: defaultProvider === 'vertex' && defaultModel === model.name, - isCurrent: - currentConfig.provider === 'vertex' && - currentConfig.model === model.name, - isCustom: false, - ...(defaultReasoningEffort && - defaultProvider === 'vertex' && - defaultModel === model.name - ? { reasoningEffort: defaultReasoningEffort } - : {}), - }); - } - } - if (!cancelled) { setModels(modelList); setCustomModels(loadedCustomModels); diff --git a/packages/cli/src/cli/ink-cli/components/overlays/custom-model-wizard/provider-config.ts b/packages/cli/src/cli/ink-cli/components/overlays/custom-model-wizard/provider-config.ts index b9c97b45b..b24bd6db9 100644 --- a/packages/cli/src/cli/ink-cli/components/overlays/custom-model-wizard/provider-config.ts +++ b/packages/cli/src/cli/ink-cli/components/overlays/custom-model-wizard/provider-config.ts @@ -264,8 +264,8 @@ export const PROVIDER_CONFIGS: Record<CustomModelProvider, ProviderConfig> = { }, }, - bedrock: { - displayName: 'AWS Bedrock', + 'amazon-bedrock': { + displayName: 'Amazon Bedrock', description: 'Custom model IDs via AWS credentials', steps: [ { @@ -422,18 +422,18 @@ export const PROVIDER_CONFIGS: Record<CustomModelProvider, ProviderConfig> = { }, }, - vertex: { - displayName: 'Google Vertex AI', - description: 'Custom Vertex model IDs', + 'google-vertex': { + displayName: 'Google Vertex AI (Gemini)', + description: 'Custom Gemini model IDs via Vertex AI', steps: [ { field: 'name', label: 'Vertex Model ID', - placeholder: 'e.g., gemini-2.0-flash-exp, claude-4-5-sonnet@20250929', + placeholder: 'e.g., gemini-2.5-pro, gemini-2.5-flash', required: true, validate: validators.required('Model ID'), }, - { ...DISPLAY_NAME_STEP, placeholder: 'e.g., Gemini 2.0 Flash Exp' }, + { ...DISPLAY_NAME_STEP, placeholder: 'e.g., Gemini 2.5 Pro' }, { ...MAX_INPUT_TOKENS_STEP, placeholder: 'e.g., 1048576 (leave blank for default)', @@ -460,6 +460,44 @@ export const PROVIDER_CONFIGS: Record<CustomModelProvider, ProviderConfig> = { }, }, + 'google-vertex-anthropic': { + displayName: 'Google Vertex AI (Claude)', + description: 'Custom Claude model IDs via Vertex AI', + steps: [ + { + field: 'name', + label: 'Vertex Model ID', + placeholder: 'e.g., claude-sonnet-4@20250514', + required: true, + validate: validators.required('Model ID'), + }, + { ...DISPLAY_NAME_STEP, placeholder: 'e.g., Claude Sonnet 4' }, + { + ...MAX_INPUT_TOKENS_STEP, + placeholder: 'e.g., 200000 (leave blank for default)', + }, + ], + buildModel: (values, provider) => { + const model: CustomModel = { + name: values.name || '', + provider, + }; + if (values.displayName?.trim()) { + model.displayName = values.displayName.trim(); + } + if (values.maxInputTokens?.trim()) { + model.maxInputTokens = parseInt(values.maxInputTokens, 10); + } + return model; + }, + setupInfo: { + title: 'Google Vertex AI Setup', + description: + 'Vertex AI uses Google Cloud Application Default Credentials (ADC). Set GOOGLE_VERTEX_PROJECT and optionally GOOGLE_VERTEX_LOCATION. Run: gcloud auth application-default login', + docsUrl: 'https://docs.dexto.ai/docs/guides/supported-llm-providers#google-vertex-ai', + }, + }, + 'dexto-nova': { displayName: 'Dexto Nova', description: 'Access 100+ models with Nova credits', diff --git a/packages/cli/src/cli/ink-cli/utils/llm-provider-display.ts b/packages/cli/src/cli/ink-cli/utils/llm-provider-display.ts index 078b5ec28..45034b9f3 100644 --- a/packages/cli/src/cli/ink-cli/utils/llm-provider-display.ts +++ b/packages/cli/src/cli/ink-cli/utils/llm-provider-display.ts @@ -1,6 +1,6 @@ import type { LLMProvider } from '@dexto/core'; -const LLM_PROVIDER_DISPLAY_NAMES: Record<LLMProvider, string> = { +const LLM_PROVIDER_DISPLAY_NAMES: Partial<Record<LLMProvider, string>> = { openai: 'OpenAI', 'openai-compatible': 'OpenAI-Compatible', anthropic: 'Anthropic', @@ -12,7 +12,6 @@ const LLM_PROVIDER_DISPLAY_NAMES: Record<LLMProvider, string> = { 'minimax-cn': 'MiniMax (CN)', 'minimax-coding-plan': 'MiniMax (Coding Plan)', 'minimax-cn-coding-plan': 'MiniMax (CN, Coding Plan)', - glm: 'GLM', zhipuai: 'Zhipu AI (GLM)', 'zhipuai-coding-plan': 'Zhipu AI (Coding Plan)', zai: 'Z.AI', @@ -23,8 +22,9 @@ const LLM_PROVIDER_DISPLAY_NAMES: Record<LLMProvider, string> = { openrouter: 'OpenRouter', litellm: 'LiteLLM', glama: 'Glama', - vertex: 'Vertex', - bedrock: 'Bedrock', + 'google-vertex': 'Google Vertex AI (Gemini)', + 'google-vertex-anthropic': 'Google Vertex AI (Claude)', + 'amazon-bedrock': 'Amazon Bedrock', local: 'Local', ollama: 'Ollama', 'dexto-nova': 'Dexto Nova', diff --git a/packages/cli/src/cli/utils/api-key-verification.ts b/packages/cli/src/cli/utils/api-key-verification.ts index 5d8093e82..b173f0e0d 100644 --- a/packages/cli/src/cli/utils/api-key-verification.ts +++ b/packages/cli/src/cli/utils/api-key-verification.ts @@ -43,15 +43,19 @@ export async function verifyApiKey( return await verifyGlama(apiKey); case 'minimax': return await verifyMiniMax(apiKey); - case 'glm': + case 'zhipuai': + case 'zhipuai-coding-plan': + case 'zai': + case 'zai-coding-plan': return await verifyGLM(apiKey); case 'openai-compatible': case 'litellm': // For custom endpoints, we can't verify without a baseURL // Just do basic format check return { success: true, modelUsed: 'custom' }; - case 'vertex': - case 'bedrock': + case 'google-vertex': + case 'google-vertex-anthropic': + case 'amazon-bedrock': // These use cloud credentials, not API keys // Skip verification return { success: true, modelUsed: 'cloud-auth' }; diff --git a/packages/cli/src/cli/utils/provider-setup.ts b/packages/cli/src/cli/utils/provider-setup.ts index c03f01321..76c6ae43c 100644 --- a/packages/cli/src/cli/utils/provider-setup.ts +++ b/packages/cli/src/cli/utils/provider-setup.ts @@ -124,10 +124,10 @@ export const PROVIDER_REGISTRY: Partial<Record<LLMProvider, ProviderOption>> = { apiKeyUrl: 'https://platform.minimax.io/docs/faq/about-apis', envVar: 'MINIMAX_API_KEY', }, - glm: { - value: 'glm', - label: 'GLM (Zhipu)', - hint: 'GLM-4.7 series models', + zhipuai: { + value: 'zhipuai', + label: 'Zhipu AI (GLM)', + hint: 'GLM series models', category: 'cloud', apiKeyUrl: 'https://open.bigmodel.cn/', envVar: 'ZHIPU_API_KEY', @@ -166,17 +166,25 @@ export const PROVIDER_REGISTRY: Partial<Record<LLMProvider, ProviderOption>> = { requiresBaseURL: true, envVar: 'OPENAI_COMPATIBLE_API_KEY', }, - vertex: { - value: 'vertex', - label: 'Google Vertex AI', - hint: 'GCP-hosted Gemini & Claude (uses ADC)', + 'google-vertex': { + value: 'google-vertex', + label: 'Google Vertex AI (Gemini)', + hint: 'GCP-hosted Gemini models (uses ADC)', category: 'enterprise', apiKeyUrl: 'https://console.cloud.google.com/apis/credentials', envVar: 'GOOGLE_VERTEX_PROJECT', }, - bedrock: { - value: 'bedrock', - label: 'AWS Bedrock', + 'google-vertex-anthropic': { + value: 'google-vertex-anthropic', + label: 'Google Vertex AI (Claude)', + hint: 'GCP-hosted Claude models (uses ADC)', + category: 'enterprise', + apiKeyUrl: 'https://console.cloud.google.com/apis/credentials', + envVar: 'GOOGLE_VERTEX_PROJECT', + }, + 'amazon-bedrock': { + value: 'amazon-bedrock', + label: 'Amazon Bedrock', hint: 'AWS-hosted Claude & Nova (uses AWS creds)', category: 'enterprise', apiKeyUrl: 'https://console.aws.amazon.com/bedrock', diff --git a/packages/cli/src/config/cli-overrides.ts b/packages/cli/src/config/cli-overrides.ts index c6f9e1dc5..e6886f1dd 100644 --- a/packages/cli/src/config/cli-overrides.ts +++ b/packages/cli/src/config/cli-overrides.ts @@ -20,7 +20,7 @@ */ import type { AgentConfig } from '@dexto/agent-config'; -import type { LLMConfig, LLMProvider } from '@dexto/core'; +import { getPrimaryApiKeyEnvVar, type LLMConfig, type LLMProvider } from '@dexto/core'; import type { GlobalPreferences } from '@dexto/agent-management'; /** @@ -200,36 +200,15 @@ export function checkAgentCompatibility( * Get the environment variable name for a provider's API key */ function getEnvVarForProvider(provider: LLMProvider): string { - const envVarMap: Record<LLMProvider, string> = { - openai: 'OPENAI_API_KEY', - 'openai-compatible': 'OPENAI_API_KEY', - anthropic: 'ANTHROPIC_API_KEY', - google: 'GOOGLE_GENERATIVE_AI_API_KEY', - groq: 'GROQ_API_KEY', - xai: 'XAI_API_KEY', - cohere: 'COHERE_API_KEY', - minimax: 'MINIMAX_API_KEY', - 'minimax-cn': 'MINIMAX_API_KEY', - 'minimax-coding-plan': 'MINIMAX_API_KEY', - 'minimax-cn-coding-plan': 'MINIMAX_API_KEY', - glm: 'ZHIPU_API_KEY', - zhipuai: 'ZHIPU_API_KEY', - 'zhipuai-coding-plan': 'ZHIPU_API_KEY', - zai: 'ZHIPU_API_KEY', - 'zai-coding-plan': 'ZHIPU_API_KEY', - moonshotai: 'MOONSHOT_API_KEY', - 'moonshotai-cn': 'MOONSHOT_API_KEY', - 'kimi-for-coding': 'KIMI_API_KEY', - openrouter: 'OPENROUTER_API_KEY', - litellm: 'LITELLM_API_KEY', - glama: 'GLAMA_API_KEY', - vertex: 'GOOGLE_APPLICATION_CREDENTIALS', - bedrock: 'AWS_ACCESS_KEY_ID', - // Local providers don't require API keys (empty string signals no key needed) - local: '', - ollama: '', - // Dexto gateway uses DEXTO_API_KEY from `dexto login` - 'dexto-nova': 'DEXTO_API_KEY', - }; - return envVarMap[provider]; + if (provider === 'local' || provider === 'ollama') return ''; + if (provider === 'google-vertex' || provider === 'google-vertex-anthropic') { + return 'GOOGLE_VERTEX_PROJECT'; + } + if (provider === 'amazon-bedrock') { + return 'AWS_REGION'; + } + if (provider === 'dexto-nova') { + return 'DEXTO_API_KEY'; + } + return getPrimaryApiKeyEnvVar(provider).replace(/-/g, '_'); } diff --git a/packages/core/src/llm/curation-config.ts b/packages/core/src/llm/curation-config.ts index 240e1cae2..5afb3fb20 100644 --- a/packages/core/src/llm/curation-config.ts +++ b/packages/core/src/llm/curation-config.ts @@ -34,7 +34,7 @@ export const CURATED_MODEL_IDS_BY_PROVIDER: Partial<Record<LLMProvider, string[] 'gemini-2.5-pro', 'gemini-2.5-flash', ], - vertex: [ + 'google-vertex': [ 'gemini-3-pro-preview', 'gemini-3-flash-preview', 'gemini-2.5-pro', @@ -44,8 +44,8 @@ export const CURATED_MODEL_IDS_BY_PROVIDER: Partial<Record<LLMProvider, string[] groq: ['llama-3.3-70b-versatile', 'llama-3.1-8b-instant', 'qwen-qwq-32b'], cohere: ['command-a-03-2025', 'command-r-plus-08-2024', 'command-r-08-2024'], minimax: ['MiniMax-M2.1', 'MiniMax-M2'], - glm: ['glm-4.7', 'glm-4.5'], - bedrock: [ + zhipuai: ['glm-4.7', 'glm-4.5'], + 'amazon-bedrock': [ 'anthropic.claude-sonnet-4-5-20250929-v1:0', 'anthropic.claude-haiku-4-5-20251001-v1:0', 'amazon.nova-pro-v1:0', diff --git a/packages/core/src/llm/executor/provider-options.ts b/packages/core/src/llm/executor/provider-options.ts index c601883fa..c4c4563d3 100644 --- a/packages/core/src/llm/executor/provider-options.ts +++ b/packages/core/src/llm/executor/provider-options.ts @@ -51,7 +51,7 @@ export function buildProviderOptions( } // Bedrock: Enable caching and reasoning for Claude models - if (provider === 'bedrock' && modelLower.includes('claude')) { + if (provider === 'amazon-bedrock' && modelLower.includes('claude')) { return { bedrock: { cacheControl: { type: 'ephemeral' }, @@ -61,7 +61,7 @@ export function buildProviderOptions( } // Vertex: Enable caching and reasoning for Claude models - if (provider === 'vertex' && modelLower.includes('claude')) { + if (provider === 'google-vertex-anthropic') { return { 'vertex-anthropic': { cacheControl: { type: 'ephemeral' }, @@ -73,7 +73,7 @@ export function buildProviderOptions( // Google: Enable thinking for models that support it // Note: Google automatically enables thinking for thinking models, // but we explicitly enable includeThoughts to receive the reasoning - if (provider === 'google' || (provider === 'vertex' && !modelLower.includes('claude'))) { + if (provider === 'google' || provider === 'google-vertex') { return { google: { thinkingConfig: { diff --git a/packages/core/src/llm/executor/stream-processor.ts b/packages/core/src/llm/executor/stream-processor.ts index 3e68083fb..5b71e9896 100644 --- a/packages/core/src/llm/executor/stream-processor.ts +++ b/packages/core/src/llm/executor/stream-processor.ts @@ -244,7 +244,7 @@ export class StreamProcessor { // follow-up requests (function_call item references missing required reasoning items). const shouldPersistProviderMetadata = this.config.provider === 'google' || - (this.config.provider as string) === 'vertex'; + this.config.provider === 'google-vertex'; if (shouldPersistProviderMetadata && event.providerMetadata) { toolCall.providerOptions = { diff --git a/packages/core/src/llm/formatters/vercel.ts b/packages/core/src/llm/formatters/vercel.ts index 213f95591..71e128a9d 100644 --- a/packages/core/src/llm/formatters/vercel.ts +++ b/packages/core/src/llm/formatters/vercel.ts @@ -75,8 +75,8 @@ export class VercelMessageFormatter { const isClaudeModel = modelLower.includes('claude'); const isAnthropicProvider = context.provider === 'anthropic' || - (context.provider === 'bedrock' && isClaudeModel) || - (context.provider === 'vertex' && isClaudeModel); + (context.provider === 'amazon-bedrock' && isClaudeModel) || + context.provider === 'google-vertex-anthropic'; formatted.push({ role: 'system', diff --git a/packages/core/src/llm/providers.generated.ts b/packages/core/src/llm/providers.generated.ts new file mode 100644 index 000000000..d62743b9d --- /dev/null +++ b/packages/core/src/llm/providers.generated.ts @@ -0,0 +1,908 @@ +// This file is auto-generated by scripts/sync-llm-models.ts +// Do not edit manually - run 'pnpm run sync-llm-models' to update + +export type ProviderSnapshotEntry = { + id: string; + name: string; + env: readonly string[]; + npm: string; + api?: string; + doc?: string; +}; + +export const PROVIDERS_BY_ID = { + '302ai': { + id: '302ai', + name: '302.AI', + env: ['302AI_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.302.ai/v1', + doc: 'https://doc.302.ai', + }, + abacus: { + id: 'abacus', + name: 'Abacus', + env: ['ABACUS_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://routellm.abacus.ai/v1', + doc: 'https://abacus.ai/help/api', + }, + aihubmix: { + id: 'aihubmix', + name: 'AIHubMix', + env: ['AIHUBMIX_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://aihubmix.com/v1', + doc: 'https://docs.aihubmix.com', + }, + alibaba: { + id: 'alibaba', + name: 'Alibaba', + env: ['DASHSCOPE_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://dashscope-intl.aliyuncs.com/compatible-mode/v1', + doc: 'https://www.alibabacloud.com/help/en/model-studio/models', + }, + 'alibaba-cn': { + id: 'alibaba-cn', + name: 'Alibaba (China)', + env: ['DASHSCOPE_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://dashscope.aliyuncs.com/compatible-mode/v1', + doc: 'https://www.alibabacloud.com/help/en/model-studio/models', + }, + 'amazon-bedrock': { + id: 'amazon-bedrock', + name: 'Amazon Bedrock', + env: ['AWS_ACCESS_KEY_ID', 'AWS_SECRET_ACCESS_KEY', 'AWS_REGION'], + npm: '@ai-sdk/amazon-bedrock', + doc: 'https://docs.aws.amazon.com/bedrock/latest/userguide/models-supported.html', + }, + anthropic: { + id: 'anthropic', + name: 'Anthropic', + env: ['ANTHROPIC_API_KEY'], + npm: '@ai-sdk/anthropic', + doc: 'https://docs.anthropic.com/en/docs/about-claude/models', + }, + azure: { + id: 'azure', + name: 'Azure', + env: ['AZURE_RESOURCE_NAME', 'AZURE_API_KEY'], + npm: '@ai-sdk/azure', + doc: 'https://learn.microsoft.com/en-us/azure/ai-services/openai/concepts/models', + }, + 'azure-cognitive-services': { + id: 'azure-cognitive-services', + name: 'Azure Cognitive Services', + env: ['AZURE_COGNITIVE_SERVICES_RESOURCE_NAME', 'AZURE_COGNITIVE_SERVICES_API_KEY'], + npm: '@ai-sdk/azure', + doc: 'https://learn.microsoft.com/en-us/azure/ai-services/openai/concepts/models', + }, + bailing: { + id: 'bailing', + name: 'Bailing', + env: ['BAILING_API_TOKEN'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.tbox.cn/api/llm/v1/chat/completions', + doc: 'https://alipaytbox.yuque.com/sxs0ba/ling/intro', + }, + baseten: { + id: 'baseten', + name: 'Baseten', + env: ['BASETEN_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://inference.baseten.co/v1', + doc: 'https://docs.baseten.co/development/model-apis/overview', + }, + berget: { + id: 'berget', + name: 'Berget.AI', + env: ['BERGET_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.berget.ai/v1', + doc: 'https://api.berget.ai', + }, + cerebras: { + id: 'cerebras', + name: 'Cerebras', + env: ['CEREBRAS_API_KEY'], + npm: '@ai-sdk/cerebras', + doc: 'https://inference-docs.cerebras.ai/models/overview', + }, + chutes: { + id: 'chutes', + name: 'Chutes', + env: ['CHUTES_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://llm.chutes.ai/v1', + doc: 'https://llm.chutes.ai/v1/models', + }, + 'cloudferro-sherlock': { + id: 'cloudferro-sherlock', + name: 'CloudFerro Sherlock', + env: ['CLOUDFERRO_SHERLOCK_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api-sherlock.cloudferro.com/openai/v1/', + doc: 'https://docs.sherlock.cloudferro.com/', + }, + 'cloudflare-ai-gateway': { + id: 'cloudflare-ai-gateway', + name: 'Cloudflare AI Gateway', + env: ['CLOUDFLARE_API_TOKEN', 'CLOUDFLARE_ACCOUNT_ID', 'CLOUDFLARE_GATEWAY_ID'], + npm: 'ai-gateway-provider', + doc: 'https://developers.cloudflare.com/ai-gateway/', + }, + 'cloudflare-workers-ai': { + id: 'cloudflare-workers-ai', + name: 'Cloudflare Workers AI', + env: ['CLOUDFLARE_ACCOUNT_ID', 'CLOUDFLARE_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/ai/v1', + doc: 'https://developers.cloudflare.com/workers-ai/models/', + }, + cohere: { + id: 'cohere', + name: 'Cohere', + env: ['COHERE_API_KEY'], + npm: '@ai-sdk/cohere', + doc: 'https://docs.cohere.com/docs/models', + }, + cortecs: { + id: 'cortecs', + name: 'Cortecs', + env: ['CORTECS_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.cortecs.ai/v1', + doc: 'https://api.cortecs.ai/v1/models', + }, + deepinfra: { + id: 'deepinfra', + name: 'Deep Infra', + env: ['DEEPINFRA_API_KEY'], + npm: '@ai-sdk/deepinfra', + doc: 'https://deepinfra.com/models', + }, + deepseek: { + id: 'deepseek', + name: 'DeepSeek', + env: ['DEEPSEEK_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.deepseek.com', + doc: 'https://platform.deepseek.com/api-docs/pricing', + }, + evroc: { + id: 'evroc', + name: 'evroc', + env: ['EVROC_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://models.think.evroc.com/v1', + doc: 'https://docs.evroc.com/products/think/overview.html', + }, + fastrouter: { + id: 'fastrouter', + name: 'FastRouter', + env: ['FASTROUTER_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://go.fastrouter.ai/api/v1', + doc: 'https://fastrouter.ai/models', + }, + 'fireworks-ai': { + id: 'fireworks-ai', + name: 'Fireworks AI', + env: ['FIREWORKS_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.fireworks.ai/inference/v1/', + doc: 'https://fireworks.ai/docs/', + }, + firmware: { + id: 'firmware', + name: 'Firmware', + env: ['FIRMWARE_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://app.firmware.ai/api/v1', + doc: 'https://docs.firmware.ai', + }, + friendli: { + id: 'friendli', + name: 'Friendli', + env: ['FRIENDLI_TOKEN'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.friendli.ai/serverless/v1', + doc: 'https://friendli.ai/docs/guides/serverless_endpoints/introduction', + }, + 'github-copilot': { + id: 'github-copilot', + name: 'GitHub Copilot', + env: ['GITHUB_TOKEN'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.githubcopilot.com', + doc: 'https://docs.github.com/en/copilot', + }, + 'github-models': { + id: 'github-models', + name: 'GitHub Models', + env: ['GITHUB_TOKEN'], + npm: '@ai-sdk/openai-compatible', + api: 'https://models.github.ai/inference', + doc: 'https://docs.github.com/en/github-models', + }, + gitlab: { + id: 'gitlab', + name: 'GitLab Duo', + env: ['GITLAB_TOKEN'], + npm: '@gitlab/gitlab-ai-provider', + doc: 'https://docs.gitlab.com/user/duo_agent_platform/', + }, + google: { + id: 'google', + name: 'Google', + env: ['GOOGLE_GENERATIVE_AI_API_KEY', 'GEMINI_API_KEY'], + npm: '@ai-sdk/google', + doc: 'https://ai.google.dev/gemini-api/docs/pricing', + }, + 'google-vertex': { + id: 'google-vertex', + name: 'Vertex', + env: ['GOOGLE_VERTEX_PROJECT', 'GOOGLE_VERTEX_LOCATION', 'GOOGLE_APPLICATION_CREDENTIALS'], + npm: '@ai-sdk/google-vertex', + doc: 'https://cloud.google.com/vertex-ai/generative-ai/docs/models', + }, + 'google-vertex-anthropic': { + id: 'google-vertex-anthropic', + name: 'Vertex (Anthropic)', + env: ['GOOGLE_VERTEX_PROJECT', 'GOOGLE_VERTEX_LOCATION', 'GOOGLE_APPLICATION_CREDENTIALS'], + npm: '@ai-sdk/google-vertex/anthropic', + doc: 'https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/claude', + }, + groq: { + id: 'groq', + name: 'Groq', + env: ['GROQ_API_KEY'], + npm: '@ai-sdk/groq', + doc: 'https://console.groq.com/docs/models', + }, + helicone: { + id: 'helicone', + name: 'Helicone', + env: ['HELICONE_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://ai-gateway.helicone.ai/v1', + doc: 'https://helicone.ai/models', + }, + huggingface: { + id: 'huggingface', + name: 'Hugging Face', + env: ['HF_TOKEN'], + npm: '@ai-sdk/openai-compatible', + api: 'https://router.huggingface.co/v1', + doc: 'https://huggingface.co/docs/inference-providers', + }, + iflowcn: { + id: 'iflowcn', + name: 'iFlow', + env: ['IFLOW_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://apis.iflow.cn/v1', + doc: 'https://platform.iflow.cn/en/docs', + }, + inception: { + id: 'inception', + name: 'Inception', + env: ['INCEPTION_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.inceptionlabs.ai/v1/', + doc: 'https://platform.inceptionlabs.ai/docs', + }, + inference: { + id: 'inference', + name: 'Inference', + env: ['INFERENCE_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://inference.net/v1', + doc: 'https://inference.net/models', + }, + 'io-net': { + id: 'io-net', + name: 'IO.NET', + env: ['IOINTELLIGENCE_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.intelligence.io.solutions/api/v1', + doc: 'https://io.net/docs/guides/intelligence/io-intelligence', + }, + jiekou: { + id: 'jiekou', + name: 'Jiekou.AI', + env: ['JIEKOU_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.jiekou.ai/openai', + doc: 'https://docs.jiekou.ai/docs/support/quickstart?utm_source=github_models.dev', + }, + kilo: { + id: 'kilo', + name: 'Kilo Gateway', + env: ['KILO_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.kilo.ai/api/gateway', + doc: 'https://kilo.ai', + }, + 'kimi-for-coding': { + id: 'kimi-for-coding', + name: 'Kimi For Coding', + env: ['KIMI_API_KEY'], + npm: '@ai-sdk/anthropic', + api: 'https://api.kimi.com/coding/v1', + doc: 'https://www.kimi.com/coding/docs/en/third-party-agents.html', + }, + 'kuae-cloud-coding-plan': { + id: 'kuae-cloud-coding-plan', + name: 'KUAE Cloud Coding Plan', + env: ['KUAE_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://coding-plan-endpoint.kuaecloud.net/v1', + doc: 'https://docs.mthreads.com/kuaecloud/kuaecloud-doc-online/coding_plan/', + }, + llama: { + id: 'llama', + name: 'Llama', + env: ['LLAMA_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.llama.com/compat/v1/', + doc: 'https://llama.developer.meta.com/docs/models', + }, + lmstudio: { + id: 'lmstudio', + name: 'LMStudio', + env: ['LMSTUDIO_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'http://127.0.0.1:1234/v1', + doc: 'https://lmstudio.ai/models', + }, + lucidquery: { + id: 'lucidquery', + name: 'LucidQuery AI', + env: ['LUCIDQUERY_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://lucidquery.com/api/v1', + doc: 'https://lucidquery.com/api/docs', + }, + meganova: { + id: 'meganova', + name: 'Meganova', + env: ['MEGANOVA_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.meganova.ai/v1', + doc: 'https://docs.meganova.ai', + }, + minimax: { + id: 'minimax', + name: 'MiniMax (minimax.io)', + env: ['MINIMAX_API_KEY'], + npm: '@ai-sdk/anthropic', + api: 'https://api.minimax.io/anthropic/v1', + doc: 'https://platform.minimax.io/docs/guides/quickstart', + }, + 'minimax-cn': { + id: 'minimax-cn', + name: 'MiniMax (minimaxi.com)', + env: ['MINIMAX_API_KEY'], + npm: '@ai-sdk/anthropic', + api: 'https://api.minimaxi.com/anthropic/v1', + doc: 'https://platform.minimaxi.com/docs/guides/quickstart', + }, + 'minimax-cn-coding-plan': { + id: 'minimax-cn-coding-plan', + name: 'MiniMax Coding Plan (minimaxi.com)', + env: ['MINIMAX_API_KEY'], + npm: '@ai-sdk/anthropic', + api: 'https://api.minimaxi.com/anthropic/v1', + doc: 'https://platform.minimaxi.com/docs/coding-plan/intro', + }, + 'minimax-coding-plan': { + id: 'minimax-coding-plan', + name: 'MiniMax Coding Plan (minimax.io)', + env: ['MINIMAX_API_KEY'], + npm: '@ai-sdk/anthropic', + api: 'https://api.minimax.io/anthropic/v1', + doc: 'https://platform.minimax.io/docs/coding-plan/intro', + }, + mistral: { + id: 'mistral', + name: 'Mistral', + env: ['MISTRAL_API_KEY'], + npm: '@ai-sdk/mistral', + doc: 'https://docs.mistral.ai/getting-started/models/', + }, + moark: { + id: 'moark', + name: 'Moark', + env: ['MOARK_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://moark.com/v1', + doc: 'https://moark.com/docs/openapi/v1#tag/%E6%96%87%E6%9C%AC%E7%94%9F%E6%88%90', + }, + modelscope: { + id: 'modelscope', + name: 'ModelScope', + env: ['MODELSCOPE_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api-inference.modelscope.cn/v1', + doc: 'https://modelscope.cn/docs/model-service/API-Inference/intro', + }, + moonshotai: { + id: 'moonshotai', + name: 'Moonshot AI', + env: ['MOONSHOT_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.moonshot.ai/v1', + doc: 'https://platform.moonshot.ai/docs/api/chat', + }, + 'moonshotai-cn': { + id: 'moonshotai-cn', + name: 'Moonshot AI (China)', + env: ['MOONSHOT_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.moonshot.cn/v1', + doc: 'https://platform.moonshot.cn/docs/api/chat', + }, + morph: { + id: 'morph', + name: 'Morph', + env: ['MORPH_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.morphllm.com/v1', + doc: 'https://docs.morphllm.com/api-reference/introduction', + }, + 'nano-gpt': { + id: 'nano-gpt', + name: 'NanoGPT', + env: ['NANO_GPT_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://nano-gpt.com/api/v1', + doc: 'https://docs.nano-gpt.com', + }, + nebius: { + id: 'nebius', + name: 'Nebius Token Factory', + env: ['NEBIUS_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.tokenfactory.nebius.com/v1', + doc: 'https://docs.tokenfactory.nebius.com/', + }, + nova: { + id: 'nova', + name: 'Nova', + env: ['NOVA_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.nova.amazon.com/v1', + doc: 'https://nova.amazon.com/dev/documentation', + }, + 'novita-ai': { + id: 'novita-ai', + name: 'NovitaAI', + env: ['NOVITA_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.novita.ai/openai', + doc: 'https://novita.ai/docs/guides/introduction', + }, + nvidia: { + id: 'nvidia', + name: 'Nvidia', + env: ['NVIDIA_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://integrate.api.nvidia.com/v1', + doc: 'https://docs.api.nvidia.com/nim/', + }, + 'ollama-cloud': { + id: 'ollama-cloud', + name: 'Ollama Cloud', + env: ['OLLAMA_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://ollama.com/v1', + doc: 'https://docs.ollama.com/cloud', + }, + openai: { + id: 'openai', + name: 'OpenAI', + env: ['OPENAI_API_KEY'], + npm: '@ai-sdk/openai', + doc: 'https://platform.openai.com/docs/models', + }, + opencode: { + id: 'opencode', + name: 'OpenCode Zen', + env: ['OPENCODE_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://opencode.ai/zen/v1', + doc: 'https://opencode.ai/docs/zen', + }, + openrouter: { + id: 'openrouter', + name: 'OpenRouter', + env: ['OPENROUTER_API_KEY'], + npm: '@openrouter/ai-sdk-provider', + api: 'https://openrouter.ai/api/v1', + doc: 'https://openrouter.ai/models', + }, + ovhcloud: { + id: 'ovhcloud', + name: 'OVHcloud AI Endpoints', + env: ['OVHCLOUD_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://oai.endpoints.kepler.ai.cloud.ovh.net/v1', + doc: 'https://www.ovhcloud.com/en/public-cloud/ai-endpoints/catalog//', + }, + perplexity: { + id: 'perplexity', + name: 'Perplexity', + env: ['PERPLEXITY_API_KEY'], + npm: '@ai-sdk/perplexity', + doc: 'https://docs.perplexity.ai', + }, + poe: { + id: 'poe', + name: 'Poe', + env: ['POE_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.poe.com/v1', + doc: 'https://creator.poe.com/docs/external-applications/openai-compatible-api', + }, + 'privatemode-ai': { + id: 'privatemode-ai', + name: 'Privatemode AI', + env: ['PRIVATEMODE_API_KEY', 'PRIVATEMODE_ENDPOINT'], + npm: '@ai-sdk/openai-compatible', + api: 'http://localhost:8080/v1', + doc: 'https://docs.privatemode.ai/api/overview', + }, + 'qihang-ai': { + id: 'qihang-ai', + name: 'QiHang', + env: ['QIHANG_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.qhaigc.net/v1', + doc: 'https://www.qhaigc.net/docs', + }, + 'qiniu-ai': { + id: 'qiniu-ai', + name: 'Qiniu', + env: ['Qiniu_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.qnaigc.com.com/v1', + doc: 'https://developer.qiniu.com/aitokenapi', + }, + requesty: { + id: 'requesty', + name: 'Requesty', + env: ['REQUESTY_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://router.requesty.ai/v1', + doc: 'https://requesty.ai/solution/llm-routing/models', + }, + 'sap-ai-core': { + id: 'sap-ai-core', + name: 'SAP AI Core', + env: ['AICORE_SERVICE_KEY'], + npm: '@jerome-benoit/sap-ai-provider-v2', + doc: 'https://help.sap.com/docs/sap-ai-core', + }, + scaleway: { + id: 'scaleway', + name: 'Scaleway', + env: ['SCALEWAY_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.scaleway.ai/v1', + doc: 'https://www.scaleway.com/en/docs/generative-apis/', + }, + siliconflow: { + id: 'siliconflow', + name: 'SiliconFlow', + env: ['SILICONFLOW_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.siliconflow.com/v1', + doc: 'https://cloud.siliconflow.com/models', + }, + 'siliconflow-cn': { + id: 'siliconflow-cn', + name: 'SiliconFlow (China)', + env: ['SILICONFLOW_CN_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.siliconflow.cn/v1', + doc: 'https://cloud.siliconflow.com/models', + }, + stackit: { + id: 'stackit', + name: 'STACKIT', + env: ['STACKIT_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.openai-compat.model-serving.eu01.onstackit.cloud/v1', + doc: 'https://docs.stackit.cloud/products/data-and-ai/ai-model-serving/basics/available-shared-models', + }, + stepfun: { + id: 'stepfun', + name: 'StepFun', + env: ['STEPFUN_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.stepfun.com/v1', + doc: 'https://platform.stepfun.com/docs/zh/overview/concept', + }, + submodel: { + id: 'submodel', + name: 'submodel', + env: ['SUBMODEL_INSTAGEN_ACCESS_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://llm.submodel.ai/v1', + doc: 'https://submodel.gitbook.io', + }, + synthetic: { + id: 'synthetic', + name: 'Synthetic', + env: ['SYNTHETIC_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.synthetic.new/v1', + doc: 'https://synthetic.new/pricing', + }, + togetherai: { + id: 'togetherai', + name: 'Together AI', + env: ['TOGETHER_API_KEY'], + npm: '@ai-sdk/togetherai', + doc: 'https://docs.together.ai/docs/serverless-models', + }, + upstage: { + id: 'upstage', + name: 'Upstage', + env: ['UPSTAGE_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.upstage.ai/v1/solar', + doc: 'https://developers.upstage.ai/docs/apis/chat', + }, + v0: { + id: 'v0', + name: 'v0', + env: ['V0_API_KEY'], + npm: '@ai-sdk/vercel', + doc: 'https://sdk.vercel.ai/providers/ai-sdk-providers/vercel', + }, + venice: { + id: 'venice', + name: 'Venice AI', + env: ['VENICE_API_KEY'], + npm: 'venice-ai-sdk-provider', + doc: 'https://docs.venice.ai', + }, + vercel: { + id: 'vercel', + name: 'Vercel AI Gateway', + env: ['AI_GATEWAY_API_KEY'], + npm: '@ai-sdk/gateway', + doc: 'https://github.com/vercel/ai/tree/5eb85cc45a259553501f535b8ac79a77d0e79223/packages/gateway', + }, + vivgrid: { + id: 'vivgrid', + name: 'Vivgrid', + env: ['VIVGRID_API_KEY'], + npm: '@ai-sdk/openai', + api: 'https://api.vivgrid.com/v1', + doc: 'https://docs.vivgrid.com/models', + }, + vultr: { + id: 'vultr', + name: 'Vultr', + env: ['VULTR_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.vultrinference.com/v1', + doc: 'https://api.vultrinference.com/', + }, + wandb: { + id: 'wandb', + name: 'Weights & Biases', + env: ['WANDB_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.inference.wandb.ai/v1', + doc: 'https://weave-docs.wandb.ai/guides/integrations/inference/', + }, + xai: { + id: 'xai', + name: 'xAI', + env: ['XAI_API_KEY'], + npm: '@ai-sdk/xai', + doc: 'https://docs.x.ai/docs/models', + }, + xiaomi: { + id: 'xiaomi', + name: 'Xiaomi', + env: ['XIAOMI_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.xiaomimimo.com/v1', + doc: 'https://platform.xiaomimimo.com/#/docs', + }, + zai: { + id: 'zai', + name: 'Z.AI', + env: ['ZHIPU_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.z.ai/api/paas/v4', + doc: 'https://docs.z.ai/guides/overview/pricing', + }, + 'zai-coding-plan': { + id: 'zai-coding-plan', + name: 'Z.AI Coding Plan', + env: ['ZHIPU_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.z.ai/api/coding/paas/v4', + doc: 'https://docs.z.ai/devpack/overview', + }, + zenmux: { + id: 'zenmux', + name: 'ZenMux', + env: ['ZENMUX_API_KEY'], + npm: '@ai-sdk/anthropic', + api: 'https://zenmux.ai/api/anthropic/v1', + doc: 'https://docs.zenmux.ai', + }, + zhipuai: { + id: 'zhipuai', + name: 'Zhipu AI', + env: ['ZHIPU_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://open.bigmodel.cn/api/paas/v4', + doc: 'https://docs.z.ai/guides/overview/pricing', + }, + 'zhipuai-coding-plan': { + id: 'zhipuai-coding-plan', + name: 'Zhipu AI Coding Plan', + env: ['ZHIPU_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://open.bigmodel.cn/api/coding/paas/v4', + doc: 'https://docs.bigmodel.cn/cn/coding-plan/overview', + }, + 'dexto-nova': { + id: 'dexto-nova', + name: 'Dexto Nova', + env: ['DEXTO_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.dexto.ai/v1', + doc: 'https://dexto.ai', + }, + 'openai-compatible': { + id: 'openai-compatible', + name: 'OpenAI Compatible (Custom)', + env: ['OPENAI_API_KEY', 'OPENAI_KEY'], + npm: '@ai-sdk/openai-compatible', + }, + litellm: { + id: 'litellm', + name: 'LiteLLM', + env: ['LITELLM_API_KEY', 'LITELLM_KEY'], + npm: '@ai-sdk/openai-compatible', + doc: 'https://docs.litellm.ai', + }, + glama: { + id: 'glama', + name: 'Glama', + env: ['GLAMA_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://glama.ai/api/gateway/openai/v1', + doc: 'https://glama.ai', + }, + local: { + id: 'local', + name: 'Local (GGUF)', + env: [], + npm: '@ai-sdk/openai-compatible', + }, + ollama: { + id: 'ollama', + name: 'Ollama', + env: [], + npm: '@ai-sdk/openai-compatible', + api: 'http://localhost:11434/v1', + doc: 'https://ollama.com', + }, +} as const satisfies Record<string, ProviderSnapshotEntry>; + +export const LLM_PROVIDERS = [ + '302ai', + 'abacus', + 'aihubmix', + 'alibaba', + 'alibaba-cn', + 'amazon-bedrock', + 'anthropic', + 'azure', + 'azure-cognitive-services', + 'bailing', + 'baseten', + 'berget', + 'cerebras', + 'chutes', + 'cloudferro-sherlock', + 'cloudflare-ai-gateway', + 'cloudflare-workers-ai', + 'cohere', + 'cortecs', + 'deepinfra', + 'deepseek', + 'dexto-nova', + 'evroc', + 'fastrouter', + 'fireworks-ai', + 'firmware', + 'friendli', + 'github-copilot', + 'github-models', + 'gitlab', + 'glama', + 'google', + 'google-vertex', + 'google-vertex-anthropic', + 'groq', + 'helicone', + 'huggingface', + 'iflowcn', + 'inception', + 'inference', + 'io-net', + 'jiekou', + 'kilo', + 'kimi-for-coding', + 'kuae-cloud-coding-plan', + 'litellm', + 'llama', + 'lmstudio', + 'local', + 'lucidquery', + 'meganova', + 'minimax', + 'minimax-cn', + 'minimax-cn-coding-plan', + 'minimax-coding-plan', + 'mistral', + 'moark', + 'modelscope', + 'moonshotai', + 'moonshotai-cn', + 'morph', + 'nano-gpt', + 'nebius', + 'nova', + 'novita-ai', + 'nvidia', + 'ollama', + 'ollama-cloud', + 'openai', + 'openai-compatible', + 'opencode', + 'openrouter', + 'ovhcloud', + 'perplexity', + 'poe', + 'privatemode-ai', + 'qihang-ai', + 'qiniu-ai', + 'requesty', + 'sap-ai-core', + 'scaleway', + 'siliconflow', + 'siliconflow-cn', + 'stackit', + 'stepfun', + 'submodel', + 'synthetic', + 'togetherai', + 'upstage', + 'v0', + 'venice', + 'vercel', + 'vivgrid', + 'vultr', + 'wandb', + 'xai', + 'xiaomi', + 'zai', + 'zai-coding-plan', + 'zenmux', + 'zhipuai', + 'zhipuai-coding-plan', +] as const; diff --git a/packages/core/src/llm/registry/auto-update.test.ts b/packages/core/src/llm/registry/auto-update.test.ts index 08d872f37..861673453 100644 --- a/packages/core/src/llm/registry/auto-update.test.ts +++ b/packages/core/src/llm/registry/auto-update.test.ts @@ -35,9 +35,11 @@ const UPDATABLE_PROVIDERS: LLMProvider[] = [ 'xai', 'cohere', 'minimax', - 'glm', - 'vertex', - 'bedrock', + 'zhipuai', + 'moonshotai', + 'google-vertex', + 'google-vertex-anthropic', + 'amazon-bedrock', ]; async function writeCacheFile(cachePath: string, payload: unknown): Promise<void> { diff --git a/packages/core/src/llm/registry/auto-update.ts b/packages/core/src/llm/registry/auto-update.ts index a866abf79..b5c4fec7f 100644 --- a/packages/core/src/llm/registry/auto-update.ts +++ b/packages/core/src/llm/registry/auto-update.ts @@ -27,9 +27,11 @@ const UPDATABLE_PROVIDERS: LLMProvider[] = [ 'xai', 'cohere', 'minimax', - 'glm', - 'vertex', - 'bedrock', + 'zhipuai', + 'moonshotai', + 'google-vertex', + 'google-vertex-anthropic', + 'amazon-bedrock', ]; type CacheFile = { diff --git a/packages/core/src/llm/registry/index.test.ts b/packages/core/src/llm/registry/index.test.ts index 66a45bbe6..984bd211e 100644 --- a/packages/core/src/llm/registry/index.test.ts +++ b/packages/core/src/llm/registry/index.test.ts @@ -123,7 +123,7 @@ describe('LLM Registry Core Functions', () => { 'xai', 'cohere', 'minimax', - 'glm', + 'zhipuai', ] as const; const failures: Array<{ @@ -653,16 +653,16 @@ describe('Provider-Specific Tests', () => { }); }); - describe('Bedrock provider', () => { + describe('Amazon Bedrock provider', () => { it('has correct capabilities', () => { - expect(getSupportedProviders()).toContain('bedrock'); - expect(getSupportedModels('bedrock').length).toBeGreaterThan(0); - expect(getDefaultModelForProvider('bedrock')).toBe( + expect(getSupportedProviders()).toContain('amazon-bedrock'); + expect(getSupportedModels('amazon-bedrock').length).toBeGreaterThan(0); + expect(getDefaultModelForProvider('amazon-bedrock')).toBe( 'anthropic.claude-sonnet-4-5-20250929-v1:0' ); - expect(supportsBaseURL('bedrock')).toBe(false); - expect(requiresBaseURL('bedrock')).toBe(false); - expect(acceptsAnyModel('bedrock')).toBe(false); + expect(supportsBaseURL('amazon-bedrock')).toBe(false); + expect(requiresBaseURL('amazon-bedrock')).toBe(false); + expect(acceptsAnyModel('amazon-bedrock')).toBe(false); }); }); }); @@ -705,57 +705,57 @@ describe('Bedrock Region Prefix Handling', () => { const bedrockModel = 'anthropic.claude-sonnet-4-5-20250929-v1:0'; it('isValidProviderModel works with prefixed models', () => { - expect(isValidProviderModel('bedrock', bedrockModel)).toBe(true); - expect(isValidProviderModel('bedrock', `eu.${bedrockModel}`)).toBe(true); - expect(isValidProviderModel('bedrock', `us.${bedrockModel}`)).toBe(true); - expect(isValidProviderModel('bedrock', `global.${bedrockModel}`)).toBe(true); + expect(isValidProviderModel('amazon-bedrock', bedrockModel)).toBe(true); + expect(isValidProviderModel('amazon-bedrock', `eu.${bedrockModel}`)).toBe(true); + expect(isValidProviderModel('amazon-bedrock', `us.${bedrockModel}`)).toBe(true); + expect(isValidProviderModel('amazon-bedrock', `global.${bedrockModel}`)).toBe(true); }); it('getProviderFromModel works with prefixed models', () => { - expect(getProviderFromModel(bedrockModel)).toBe('bedrock'); - expect(getProviderFromModel(`eu.${bedrockModel}`)).toBe('bedrock'); - expect(getProviderFromModel(`us.${bedrockModel}`)).toBe('bedrock'); - expect(getProviderFromModel(`global.${bedrockModel}`)).toBe('bedrock'); + expect(getProviderFromModel(bedrockModel)).toBe('amazon-bedrock'); + expect(getProviderFromModel(`eu.${bedrockModel}`)).toBe('amazon-bedrock'); + expect(getProviderFromModel(`us.${bedrockModel}`)).toBe('amazon-bedrock'); + expect(getProviderFromModel(`global.${bedrockModel}`)).toBe('amazon-bedrock'); }); it('getMaxInputTokensForModel works with prefixed models', () => { - const expected = getMaxInputTokensForModel('bedrock', bedrockModel, mockLogger); - expect(getMaxInputTokensForModel('bedrock', `eu.${bedrockModel}`, mockLogger)).toBe( - expected - ); - expect(getMaxInputTokensForModel('bedrock', `us.${bedrockModel}`, mockLogger)).toBe( - expected - ); - expect(getMaxInputTokensForModel('bedrock', `global.${bedrockModel}`, mockLogger)).toBe( - expected - ); + const expected = getMaxInputTokensForModel('amazon-bedrock', bedrockModel, mockLogger); + expect( + getMaxInputTokensForModel('amazon-bedrock', `eu.${bedrockModel}`, mockLogger) + ).toBe(expected); + expect( + getMaxInputTokensForModel('amazon-bedrock', `us.${bedrockModel}`, mockLogger) + ).toBe(expected); + expect( + getMaxInputTokensForModel('amazon-bedrock', `global.${bedrockModel}`, mockLogger) + ).toBe(expected); }); it('getSupportedFileTypesForModel works with prefixed models', () => { - const expected = getSupportedFileTypesForModel('bedrock', bedrockModel); - expect(getSupportedFileTypesForModel('bedrock', `eu.${bedrockModel}`)).toEqual( + const expected = getSupportedFileTypesForModel('amazon-bedrock', bedrockModel); + expect(getSupportedFileTypesForModel('amazon-bedrock', `eu.${bedrockModel}`)).toEqual( expected ); - expect(getSupportedFileTypesForModel('bedrock', `us.${bedrockModel}`)).toEqual( - expected - ); - expect(getSupportedFileTypesForModel('bedrock', `global.${bedrockModel}`)).toEqual( + expect(getSupportedFileTypesForModel('amazon-bedrock', `us.${bedrockModel}`)).toEqual( expected ); + expect( + getSupportedFileTypesForModel('amazon-bedrock', `global.${bedrockModel}`) + ).toEqual(expected); }); it('getModelPricing works with prefixed models', () => { - const expected = getModelPricing('bedrock', bedrockModel); - expect(getModelPricing('bedrock', `eu.${bedrockModel}`)).toEqual(expected); - expect(getModelPricing('bedrock', `us.${bedrockModel}`)).toEqual(expected); - expect(getModelPricing('bedrock', `global.${bedrockModel}`)).toEqual(expected); + const expected = getModelPricing('amazon-bedrock', bedrockModel); + expect(getModelPricing('amazon-bedrock', `eu.${bedrockModel}`)).toEqual(expected); + expect(getModelPricing('amazon-bedrock', `us.${bedrockModel}`)).toEqual(expected); + expect(getModelPricing('amazon-bedrock', `global.${bedrockModel}`)).toEqual(expected); }); it('getModelDisplayName works with prefixed models', () => { - const expected = getModelDisplayName(bedrockModel, 'bedrock'); - expect(getModelDisplayName(`eu.${bedrockModel}`, 'bedrock')).toBe(expected); - expect(getModelDisplayName(`us.${bedrockModel}`, 'bedrock')).toBe(expected); - expect(getModelDisplayName(`global.${bedrockModel}`, 'bedrock')).toBe(expected); + const expected = getModelDisplayName(bedrockModel, 'amazon-bedrock'); + expect(getModelDisplayName(`eu.${bedrockModel}`, 'amazon-bedrock')).toBe(expected); + expect(getModelDisplayName(`us.${bedrockModel}`, 'amazon-bedrock')).toBe(expected); + expect(getModelDisplayName(`global.${bedrockModel}`, 'amazon-bedrock')).toBe(expected); }); }); }); diff --git a/packages/core/src/llm/registry/index.ts b/packages/core/src/llm/registry/index.ts index 342d79b60..687326096 100644 --- a/packages/core/src/llm/registry/index.ts +++ b/packages/core/src/llm/registry/index.ts @@ -37,6 +37,48 @@ const LEGACY_MODEL_ID_ALIASES: Partial<Record<LLMProvider, Record<string, string }, }; +// Provider inference should prefer canonical providers over resellers/proxies when model IDs overlap. +// This keeps `--model gpt-5` and similar flows stable even as models.dev adds more providers. +const PROVIDER_INFERENCE_PRIORITY: LLMProvider[] = [ + 'openai', + 'anthropic', + 'google', + 'xai', + 'groq', + 'cohere', + 'minimax', + 'zhipuai', + 'moonshotai', + 'google-vertex', + 'google-vertex-anthropic', + 'amazon-bedrock', + // Gateways/proxies/local last + 'openai-compatible', + 'openrouter', + 'dexto-nova', + 'ollama', + 'local', +]; + +const PROVIDERS_FOR_MODEL_INFERENCE: LLMProvider[] = (() => { + const seen = new Set<LLMProvider>(); + const ordered: LLMProvider[] = []; + + for (const provider of PROVIDER_INFERENCE_PRIORITY) { + if (seen.has(provider)) continue; + seen.add(provider); + ordered.push(provider); + } + + for (const provider of LLM_PROVIDERS) { + if (seen.has(provider)) continue; + seen.add(provider); + ordered.push(provider); + } + + return ordered; +})(); + function getNormalizedModelIdForLookup(provider: LLMProvider, model: string): string { const stripped = stripBedrockRegionPrefix(model); const lower = stripped.toLowerCase(); @@ -146,178 +188,100 @@ export const DEFAULT_MAX_INPUT_TOKENS = 128000; * - DO NOT use empty arrays as "unknown" - research the model's actual capabilities * - The web UI directly reflects these capabilities without fallback logic */ -export const LLM_REGISTRY: Record<LLMProvider, ProviderInfo> = { - openai: { - models: mergeModels(MODELS_BY_PROVIDER.openai, MANUAL_MODELS_BY_PROVIDER.openai), - baseURLSupport: 'none', - supportedFileTypes: [], // No defaults - models must explicitly specify support - }, - 'openai-compatible': { +export const LLM_REGISTRY: Record<LLMProvider, ProviderInfo> = (() => { + const registry = {} as Record<LLMProvider, ProviderInfo>; + + for (const provider of LLM_PROVIDERS) { + registry[provider] = { + models: mergeModels(MODELS_BY_PROVIDER[provider], MANUAL_MODELS_BY_PROVIDER[provider]), + baseURLSupport: 'none', + supportedFileTypes: [], // No defaults - models must explicitly specify support + }; + } + + registry['openai-compatible'] = { models: [], // Empty - accepts any model name for custom endpoints baseURLSupport: 'required', supportedFileTypes: ['pdf', 'image', 'audio'], // Allow all types for custom endpoints supportsCustomModels: true, - }, - anthropic: { - models: MODELS_BY_PROVIDER.anthropic, - baseURLSupport: 'none', - supportedFileTypes: [], // No defaults - models must explicitly specify support - }, - google: { - models: MODELS_BY_PROVIDER.google, - baseURLSupport: 'none', - supportedFileTypes: [], // No defaults - models must explicitly specify support - }, - // https://console.groq.com/docs/models - groq: { - models: MODELS_BY_PROVIDER.groq, - baseURLSupport: 'none', - supportedFileTypes: [], // Groq currently doesn't support file uploads - }, - // https://docs.x.ai/docs/models - // Note: XAI API only supports image uploads (JPG/PNG up to 20MB), not PDFs - xai: { - models: MODELS_BY_PROVIDER.xai, - baseURLSupport: 'none', - supportedFileTypes: [], // No defaults - models must explicitly specify support - }, - // https://docs.cohere.com/reference/models - cohere: { - models: MODELS_BY_PROVIDER.cohere, - baseURLSupport: 'none', - supportedFileTypes: [], // No defaults - models must explicitly specify support - }, - // https://platform.minimax.io/docs/guides/quickstart - // MiniMax provides an Anthropic-compatible endpoint (models.dev): - // https://api.minimax.io/anthropic/v1 - minimax: { - models: MODELS_BY_PROVIDER.minimax, - baseURLSupport: 'none', - supportedFileTypes: [], // No defaults - models must explicitly specify support - }, - // https://api.minimaxi.com/anthropic/v1 (CN) - 'minimax-cn': { - models: MODELS_BY_PROVIDER['minimax-cn'], - baseURLSupport: 'none', - supportedFileTypes: [], - }, - // Coding plan routes through the same API base URL, but is modeled as a separate provider in models.dev - 'minimax-coding-plan': { - models: MODELS_BY_PROVIDER['minimax-coding-plan'], - baseURLSupport: 'none', - supportedFileTypes: [], - }, - 'minimax-cn-coding-plan': { - models: MODELS_BY_PROVIDER['minimax-cn-coding-plan'], - baseURLSupport: 'none', - supportedFileTypes: [], - }, - // https://open.bigmodel.cn/dev/api/normal-model/glm-4 - // GLM (Zhipu AI) provides an OpenAI-compatible endpoint - glm: { - models: MODELS_BY_PROVIDER.glm, - baseURLSupport: 'none', - supportedFileTypes: [], // No defaults - models must explicitly specify support - }, - // models.dev-aligned aliases/presets - zhipuai: { - models: MODELS_BY_PROVIDER.zhipuai, - baseURLSupport: 'none', - supportedFileTypes: [], - }, - 'zhipuai-coding-plan': { - models: MODELS_BY_PROVIDER['zhipuai-coding-plan'], - baseURLSupport: 'none', - supportedFileTypes: [], - }, - zai: { - models: MODELS_BY_PROVIDER.zai, - baseURLSupport: 'none', - supportedFileTypes: [], - }, - 'zai-coding-plan': { - models: MODELS_BY_PROVIDER['zai-coding-plan'], - baseURLSupport: 'none', - supportedFileTypes: [], - }, - // Moonshot (Kimi) OpenAI-compatible endpoints - moonshotai: { - models: MODELS_BY_PROVIDER.moonshotai, - baseURLSupport: 'none', - supportedFileTypes: [], - }, - 'moonshotai-cn': { - models: MODELS_BY_PROVIDER['moonshotai-cn'], - baseURLSupport: 'none', - supportedFileTypes: [], - }, - // Kimi For Coding (Anthropic-compatible) - 'kimi-for-coding': { - models: MODELS_BY_PROVIDER['kimi-for-coding'], - baseURLSupport: 'none', - supportedFileTypes: [], - }, - // https://openrouter.ai/docs - // OpenRouter is a unified API gateway providing access to 100+ models from various providers. - // Model validation is handled dynamically via openrouter-model-registry.ts - openrouter: { + }; + + // OpenRouter is a unified API gateway providing access to many models. + registry.openrouter = { models: MODELS_BY_PROVIDER.openrouter, - baseURLSupport: 'none', // Fixed endpoint - baseURL auto-injected in resolver, no user override allowed + baseURLSupport: 'none', supportedFileTypes: ['pdf', 'image', 'audio'], // Allow all types - user assumes responsibility supportsCustomModels: true, - supportsAllRegistryModels: true, // Can serve models from all other providers - }, - // https://docs.litellm.ai/ - // LiteLLM is an OpenAI-compatible proxy that unifies 100+ LLM providers. - // User must host their own LiteLLM proxy and provide the baseURL. - litellm: { + supportsAllRegistryModels: true, + }; + + // LiteLLM: user-hosted OpenAI-compatible proxy (baseURL required) + registry.litellm = { models: [], baseURLSupport: 'required', supportedFileTypes: ['pdf', 'image', 'audio'], supportsCustomModels: true, - }, - // https://glama.ai/ - // Glama is an OpenAI-compatible gateway providing unified access to multiple LLM providers. - // Fixed endpoint: https://glama.ai/api/gateway/openai/v1 - glama: { + }; + + // Glama: fixed OpenAI-compatible gateway + registry.glama = { models: [], baseURLSupport: 'none', supportedFileTypes: ['pdf', 'image', 'audio'], supportsCustomModels: true, - }, - // https://cloud.google.com/vertex-ai - vertex: { - models: MODELS_BY_PROVIDER.vertex, - baseURLSupport: 'none', - supportedFileTypes: [], // No defaults - models must explicitly specify support - }, - // https://docs.aws.amazon.com/bedrock/latest/userguide/models.html - bedrock: { - models: MODELS_BY_PROVIDER.bedrock, - baseURLSupport: 'none', - supportedFileTypes: [], // No defaults - models must explicitly specify support - supportsCustomModels: true, - }, + }; + + // Amazon Bedrock: allow custom/unknown IDs (region prefixes, profile routing, etc.) + if (registry['amazon-bedrock']) { + const models = registry['amazon-bedrock'].models; + const hasDefault = models.some((m) => m.default); + if (!hasDefault) { + const preferredDefault = + models.find((m) => m.name === 'anthropic.claude-sonnet-4-5-20250929-v1:0') ?? + models.find((m) => /^anthropic\.claude-sonnet/i.test(m.name)) ?? + models.find((m) => /^anthropic\.claude/i.test(m.name)) ?? + models[0]; + + if (preferredDefault) { + registry['amazon-bedrock'] = { + ...registry['amazon-bedrock'], + models: models.map((m) => + m.name === preferredDefault.name ? { ...m, default: true } : m + ), + supportsCustomModels: true, + }; + } else { + registry['amazon-bedrock'] = { + ...registry['amazon-bedrock'], + supportsCustomModels: true, + }; + } + } else { + registry['amazon-bedrock'] = { + ...registry['amazon-bedrock'], + supportsCustomModels: true, + }; + } + } + // Native local model execution via node-llama-cpp - local: { + registry.local = { models: [], // Populated dynamically from local model registry baseURLSupport: 'none', supportedFileTypes: ['image'], supportsCustomModels: true, - }, + }; + // Ollama server integration - ollama: { + registry.ollama = { models: [], // Populated dynamically from Ollama API baseURLSupport: 'optional', supportedFileTypes: ['image'], supportsCustomModels: true, - }, - // Dexto Gateway - OpenAI-compatible proxy through api.dexto.ai - // Routes to OpenRouter with per-request billing (balance decrement) - // Requires DEXTO_API_KEY from dexto login - // - // Model IDs are in OpenRouter format (e.g., 'anthropic/claude-sonnet-4.5') - 'dexto-nova': { + }; + + // Dexto Gateway (OpenRouter proxy) - OpenAI-compatible proxy through api.dexto.ai + registry['dexto-nova'] = { models: [ // Claude models (Anthropic via OpenRouter) { @@ -458,8 +422,10 @@ export const LLM_REGISTRY: Record<LLMProvider, ProviderInfo> = { supportedFileTypes: ['pdf', 'image', 'audio'], supportsCustomModels: true, supportsAllRegistryModels: true, - }, -}; + }; + + return registry; +})(); /** * Strips Bedrock cross-region inference profile prefix (eu., us., global.) from model ID. @@ -577,7 +543,7 @@ export function getProviderFromModel(model: string): LLMProvider { throw LLMError.modelProviderUnknown(model); } - for (const provider of LLM_PROVIDERS) { + for (const provider of PROVIDERS_FOR_MODEL_INFERENCE) { const info = LLM_REGISTRY[provider]; const normalizedModel = getNormalizedModelIdForLookup(provider, model); if (info.models.some((m) => m.name.toLowerCase() === normalizedModel)) { @@ -659,7 +625,6 @@ const OPENROUTER_PREFIX_BY_PROVIDER: Partial<Record<LLMProvider, string>> = { 'minimax-cn': 'minimax', 'minimax-coding-plan': 'minimax', 'minimax-cn-coding-plan': 'minimax', - glm: 'z-ai', zhipuai: 'z-ai', 'zhipuai-coding-plan': 'z-ai', zai: 'z-ai', @@ -854,15 +819,16 @@ export function isModelValidForProvider(provider: LLMProvider, model: string): b * - Native local providers (local for node-llama-cpp, ollama for Ollama server) * - Local/self-hosted providers (openai-compatible for vLLM, LocalAI) * - Proxies that handle auth internally (litellm) - * - Cloud auth providers (vertex uses ADC, bedrock uses AWS credentials) + * - Cloud auth providers (Vertex uses ADC, Bedrock uses AWS credentials) */ const API_KEY_OPTIONAL_PROVIDERS: Set<LLMProvider> = new Set([ 'local', // Native node-llama-cpp execution - no auth needed 'ollama', // Ollama server - no auth needed by default 'openai-compatible', // vLLM, LocalAI - often no auth needed 'litellm', // Self-hosted proxy - handles auth internally - 'vertex', // Uses Google Cloud ADC (Application Default Credentials) - 'bedrock', // Uses AWS credentials (access key + secret or IAM role) + 'google-vertex', // Uses Google Cloud ADC (Application Default Credentials) + 'google-vertex-anthropic', // Uses Google Cloud ADC (Application Default Credentials) + 'amazon-bedrock', // Uses AWS credentials (access key + secret or IAM role) ]); /** @@ -870,7 +836,7 @@ const API_KEY_OPTIONAL_PROVIDERS: Set<LLMProvider> = new Set([ * Returns false for: * - Local providers (openai-compatible for Ollama, vLLM, LocalAI) * - Self-hosted proxies (litellm) - * - Cloud auth providers (vertex, bedrock) + * - Cloud auth providers (Vertex, Bedrock) * * @param provider The name of the provider. * @returns True if the provider requires an API key, false otherwise. diff --git a/packages/core/src/llm/registry/models.generated.ts b/packages/core/src/llm/registry/models.generated.ts index b8466c05e..bbb9a0b2a 100644 --- a/packages/core/src/llm/registry/models.generated.ts +++ b/packages/core/src/llm/registry/models.generated.ts @@ -1,1066 +1,951 @@ -// This file is auto-generated by scripts/sync-llm-registry.ts -// Do not edit manually - run 'pnpm run sync-llm-registry' to update +// This file is auto-generated by scripts/sync-llm-models.ts +// Do not edit manually - run 'pnpm run sync-llm-models' to update import type { LLMProvider } from '../types.js'; import type { ModelInfo } from './index.js'; export const MODELS_BY_PROVIDER = { - openai: [ + '302ai': [ { - name: 'gpt-3.5-turbo', - displayName: 'GPT-3.5-turbo', - maxInputTokens: 16385, - supportedFileTypes: [], + name: 'chatgpt-4o-latest', + displayName: 'chatgpt-4o-latest', + maxInputTokens: 128000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.5, - outputPerM: 1.5, - cacheReadPerM: 1.25, + inputPerM: 5, + outputPerM: 15, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gpt-4', - displayName: 'GPT-4', - maxInputTokens: 8192, - supportedFileTypes: [], + name: 'claude-haiku-4-5-20251001', + displayName: 'claude-haiku-4-5-20251001', + maxInputTokens: 200000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 30, - outputPerM: 60, + inputPerM: 1, + outputPerM: 5, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gpt-4-turbo', - displayName: 'GPT-4 Turbo', - maxInputTokens: 128000, - supportedFileTypes: ['pdf', 'image'], + name: 'claude-opus-4-1-20250805', + displayName: 'claude-opus-4-1-20250805', + maxInputTokens: 200000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 10, - outputPerM: 30, + inputPerM: 15, + outputPerM: 75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gpt-4.1', - displayName: 'GPT-4.1', - maxInputTokens: 1047576, - supportedFileTypes: ['pdf', 'image'], + name: 'claude-opus-4-1-20250805-thinking', + displayName: 'claude-opus-4-1-20250805-thinking', + maxInputTokens: 200000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 2, - outputPerM: 8, - cacheReadPerM: 0.5, + inputPerM: 15, + outputPerM: 75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gpt-4.1-mini', - displayName: 'GPT-4.1 mini', - maxInputTokens: 1047576, - supportedFileTypes: ['pdf', 'image'], + name: 'claude-opus-4-5-20251101', + displayName: 'claude-opus-4-5-20251101', + maxInputTokens: 200000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.4, - outputPerM: 1.6, - cacheReadPerM: 0.1, + inputPerM: 5, + outputPerM: 25, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gpt-4.1-nano', - displayName: 'GPT-4.1 nano', - maxInputTokens: 1047576, - supportedFileTypes: ['pdf', 'image'], + name: 'claude-opus-4-5-20251101-thinking', + displayName: 'claude-opus-4-5-20251101-thinking', + maxInputTokens: 200000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.1, - outputPerM: 0.4, - cacheReadPerM: 0.03, + inputPerM: 5, + outputPerM: 25, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gpt-4o', - displayName: 'GPT-4o', - maxInputTokens: 128000, - supportedFileTypes: ['pdf', 'image'], + name: 'claude-sonnet-4-5-20250929', + displayName: 'claude-sonnet-4-5-20250929', + maxInputTokens: 200000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 2.5, - outputPerM: 10, - cacheReadPerM: 1.25, + inputPerM: 3, + outputPerM: 15, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gpt-4o-2024-05-13', - displayName: 'GPT-4o (2024-05-13)', - maxInputTokens: 128000, - supportedFileTypes: ['pdf', 'image'], + name: 'claude-sonnet-4-5-20250929-thinking', + displayName: 'claude-sonnet-4-5-20250929-thinking', + maxInputTokens: 200000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 5, + inputPerM: 3, outputPerM: 15, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gpt-4o-2024-08-06', - displayName: 'GPT-4o (2024-08-06)', + name: 'deepseek-chat', + displayName: 'Deepseek-Chat', maxInputTokens: 128000, - supportedFileTypes: ['pdf', 'image'], + supportedFileTypes: [], pricing: { - inputPerM: 2.5, - outputPerM: 10, - cacheReadPerM: 1.25, + inputPerM: 0.29, + outputPerM: 0.43, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gpt-4o-2024-11-20', - displayName: 'GPT-4o (2024-11-20)', + name: 'deepseek-reasoner', + displayName: 'Deepseek-Reasoner', maxInputTokens: 128000, - supportedFileTypes: ['pdf', 'image'], + supportedFileTypes: [], pricing: { - inputPerM: 2.5, - outputPerM: 10, - cacheReadPerM: 1.25, + inputPerM: 0.29, + outputPerM: 0.43, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gpt-4o-mini', - displayName: 'GPT-4o mini', + name: 'deepseek-v3.2', + displayName: 'deepseek-v3.2', maxInputTokens: 128000, - supportedFileTypes: ['pdf', 'image'], + supportedFileTypes: [], pricing: { - inputPerM: 0.15, - outputPerM: 0.6, - cacheReadPerM: 0.08, + inputPerM: 0.29, + outputPerM: 0.43, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gpt-5', - displayName: 'GPT-5', - maxInputTokens: 272000, - supportedFileTypes: ['pdf', 'image'], + name: 'deepseek-v3.2-thinking', + displayName: 'DeepSeek-V3.2-Thinking', + maxInputTokens: 128000, + supportedFileTypes: [], pricing: { - inputPerM: 1.25, - outputPerM: 10, - cacheReadPerM: 0.125, + inputPerM: 0.29, + outputPerM: 0.43, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gpt-5-chat-latest', - displayName: 'GPT-5 Chat (latest)', - maxInputTokens: 272000, - supportedFileTypes: ['pdf', 'image'], + name: 'doubao-seed-1-6-thinking-250715', + displayName: 'doubao-seed-1-6-thinking-250715', + maxInputTokens: 256000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 1.25, - outputPerM: 10, + inputPerM: 0.121, + outputPerM: 1.21, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gpt-5-codex', - displayName: 'GPT-5-Codex', - maxInputTokens: 272000, + name: 'doubao-seed-1-6-vision-250815', + displayName: 'doubao-seed-1-6-vision-250815', + maxInputTokens: 256000, supportedFileTypes: ['image'], pricing: { - inputPerM: 1.25, - outputPerM: 10, - cacheReadPerM: 0.125, + inputPerM: 0.114, + outputPerM: 1.143, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gpt-5-mini', - displayName: 'GPT-5 Mini', - maxInputTokens: 272000, - supportedFileTypes: ['pdf', 'image'], + name: 'doubao-seed-1-8-251215', + displayName: 'doubao-seed-1-8-251215', + maxInputTokens: 224000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.25, - outputPerM: 2, - cacheReadPerM: 0.025, + inputPerM: 0.114, + outputPerM: 0.286, currency: 'USD', unit: 'per_million_tokens', }, - default: true, }, { - name: 'gpt-5-nano', - displayName: 'GPT-5 Nano', - maxInputTokens: 272000, - supportedFileTypes: ['pdf', 'image'], + name: 'doubao-seed-code-preview-251028', + displayName: 'doubao-seed-code-preview-251028', + maxInputTokens: 256000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.05, - outputPerM: 0.4, - cacheReadPerM: 0.005, + inputPerM: 0.17, + outputPerM: 1.14, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gpt-5-pro', - displayName: 'GPT-5 Pro', - maxInputTokens: 272000, - supportedFileTypes: ['pdf', 'image'], + name: 'gemini-2.0-flash-lite', + displayName: 'gemini-2.0-flash-lite', + maxInputTokens: 2000000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 15, - outputPerM: 120, + inputPerM: 0.075, + outputPerM: 0.3, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gpt-5.1', - displayName: 'GPT-5.1', - maxInputTokens: 272000, - supportedFileTypes: ['pdf', 'image'], + name: 'gemini-2.5-flash', + displayName: 'gemini-2.5-flash', + maxInputTokens: 1000000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 1.25, - outputPerM: 10, - cacheReadPerM: 0.13, + inputPerM: 0.3, + outputPerM: 2.5, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gpt-5.1-chat-latest', - displayName: 'GPT-5.1 Chat', - maxInputTokens: 128000, - supportedFileTypes: ['pdf', 'image'], + name: 'gemini-2.5-flash-image', + displayName: 'gemini-2.5-flash-image', + maxInputTokens: 32768, + supportedFileTypes: ['image'], pricing: { - inputPerM: 1.25, - outputPerM: 10, - cacheReadPerM: 0.125, + inputPerM: 0.3, + outputPerM: 30, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gpt-5.1-codex', - displayName: 'GPT-5.1 Codex', - maxInputTokens: 272000, - supportedFileTypes: ['pdf', 'image'], + name: 'gemini-2.5-flash-lite-preview-09-2025', + displayName: 'gemini-2.5-flash-lite-preview-09-2025', + maxInputTokens: 1000000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 1.25, - outputPerM: 10, - cacheReadPerM: 0.125, + inputPerM: 0.1, + outputPerM: 0.4, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gpt-5.1-codex-max', - displayName: 'GPT-5.1 Codex Max', - maxInputTokens: 272000, - supportedFileTypes: ['pdf', 'image'], + name: 'gemini-2.5-flash-nothink', + displayName: 'gemini-2.5-flash-nothink', + maxInputTokens: 1000000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 1.25, - outputPerM: 10, - cacheReadPerM: 0.125, + inputPerM: 0.3, + outputPerM: 2.5, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gpt-5.1-codex-mini', - displayName: 'GPT-5.1 Codex mini', - maxInputTokens: 272000, - supportedFileTypes: ['pdf', 'image'], + name: 'gemini-2.5-flash-preview-09-2025', + displayName: 'gemini-2.5-flash-preview-09-2025', + maxInputTokens: 1000000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.25, - outputPerM: 2, - cacheReadPerM: 0.025, + inputPerM: 0.3, + outputPerM: 2.5, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gpt-5.2', - displayName: 'GPT-5.2', - maxInputTokens: 272000, - supportedFileTypes: ['pdf', 'image'], + name: 'gemini-2.5-pro', + displayName: 'gemini-2.5-pro', + maxInputTokens: 1000000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 1.75, - outputPerM: 14, - cacheReadPerM: 0.175, + inputPerM: 1.25, + outputPerM: 10, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gpt-5.2-chat-latest', - displayName: 'GPT-5.2 Chat', - maxInputTokens: 128000, - supportedFileTypes: ['pdf', 'image'], + name: 'gemini-3-flash-preview', + displayName: 'gemini-3-flash-preview', + maxInputTokens: 1000000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 1.75, - outputPerM: 14, - cacheReadPerM: 0.175, + inputPerM: 0.5, + outputPerM: 3, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gpt-5.2-codex', - displayName: 'GPT-5.2 Codex', - maxInputTokens: 272000, - supportedFileTypes: ['pdf', 'image'], + name: 'gemini-3-pro-image-preview', + displayName: 'gemini-3-pro-image-preview', + maxInputTokens: 32768, + supportedFileTypes: ['image'], pricing: { - inputPerM: 1.75, - outputPerM: 14, - cacheReadPerM: 0.175, + inputPerM: 2, + outputPerM: 120, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gpt-5.2-pro', - displayName: 'GPT-5.2 Pro', - maxInputTokens: 272000, - supportedFileTypes: ['pdf', 'image'], + name: 'gemini-3-pro-preview', + displayName: 'gemini-3-pro-preview', + maxInputTokens: 1000000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 21, - outputPerM: 168, + inputPerM: 2, + outputPerM: 12, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gpt-5.3-codex', - displayName: 'GPT-5.3 Codex', - maxInputTokens: 272000, - supportedFileTypes: ['pdf', 'image'], + name: 'glm-4.5', + displayName: 'GLM-4.5', + maxInputTokens: 128000, + supportedFileTypes: [], pricing: { - inputPerM: 1.75, - outputPerM: 14, - cacheReadPerM: 0.175, + inputPerM: 0.286, + outputPerM: 1.142, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gpt-5.3-codex-spark', - displayName: 'GPT-5.3 Codex Spark', - maxInputTokens: 100000, - supportedFileTypes: ['pdf', 'image'], + name: 'glm-4.5v', + displayName: 'GLM-4.5V', + maxInputTokens: 64000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 1.75, - outputPerM: 14, - cacheReadPerM: 0.175, + inputPerM: 0.29, + outputPerM: 0.86, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'o1', - displayName: 'o1', + name: 'glm-4.6', + displayName: 'glm-4.6', maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + supportedFileTypes: [], pricing: { - inputPerM: 15, - outputPerM: 60, - cacheReadPerM: 7.5, + inputPerM: 0.286, + outputPerM: 1.142, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'o1-mini', - displayName: 'o1-mini', + name: 'glm-4.6v', + displayName: 'GLM-4.6V', maxInputTokens: 128000, - supportedFileTypes: [], + supportedFileTypes: ['image'], pricing: { - inputPerM: 1.1, - outputPerM: 4.4, - cacheReadPerM: 0.55, + inputPerM: 0.145, + outputPerM: 0.43, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'o1-preview', - displayName: 'o1-preview', - maxInputTokens: 128000, + name: 'glm-4.7', + displayName: 'glm-4.7', + maxInputTokens: 200000, supportedFileTypes: [], pricing: { - inputPerM: 15, - outputPerM: 60, - cacheReadPerM: 7.5, + inputPerM: 0.286, + outputPerM: 1.142, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'o1-pro', - displayName: 'o1-pro', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'gpt-4.1', + displayName: 'gpt-4.1', + maxInputTokens: 1000000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 150, - outputPerM: 600, + inputPerM: 2, + outputPerM: 8, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'o3', - displayName: 'o3', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'gpt-4.1-mini', + displayName: 'gpt-4.1-mini', + maxInputTokens: 1000000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 2, - outputPerM: 8, - cacheReadPerM: 0.5, + inputPerM: 0.4, + outputPerM: 1.6, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'o3-deep-research', - displayName: 'o3-deep-research', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'gpt-4.1-nano', + displayName: 'gpt-4.1-nano', + maxInputTokens: 1000000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 10, - outputPerM: 40, - cacheReadPerM: 2.5, + inputPerM: 0.1, + outputPerM: 0.4, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'o3-mini', - displayName: 'o3-mini', - maxInputTokens: 200000, - supportedFileTypes: [], + name: 'gpt-4o', + displayName: 'gpt-4o', + maxInputTokens: 128000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 1.1, - outputPerM: 4.4, - cacheReadPerM: 0.55, + inputPerM: 2.5, + outputPerM: 10, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'o3-pro', - displayName: 'o3-pro', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'gpt-5', + displayName: 'gpt-5', + maxInputTokens: 400000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 20, - outputPerM: 80, + inputPerM: 1.25, + outputPerM: 10, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'o4-mini', - displayName: 'o4-mini', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'gpt-5-mini', + displayName: 'gpt-5-mini', + maxInputTokens: 400000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 1.1, - outputPerM: 4.4, - cacheReadPerM: 0.28, + inputPerM: 0.25, + outputPerM: 2, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'o4-mini-deep-research', - displayName: 'o4-mini-deep-research', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'gpt-5-pro', + displayName: 'gpt-5-pro', + maxInputTokens: 400000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 2, - outputPerM: 8, - cacheReadPerM: 0.5, + inputPerM: 15, + outputPerM: 120, currency: 'USD', unit: 'per_million_tokens', }, }, - ], - 'openai-compatible': [], - anthropic: [ { - name: 'claude-3-5-haiku-20241022', - displayName: 'Claude Haiku 3.5', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'gpt-5-thinking', + displayName: 'gpt-5-thinking', + maxInputTokens: 400000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.8, - outputPerM: 4, - cacheReadPerM: 0.08, - cacheWritePerM: 1, + inputPerM: 1.25, + outputPerM: 10, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'claude-3-5-haiku-latest', - displayName: 'Claude Haiku 3.5 (latest)', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'gpt-5.1', + displayName: 'gpt-5.1', + maxInputTokens: 400000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.8, - outputPerM: 4, - cacheReadPerM: 0.08, - cacheWritePerM: 1, + inputPerM: 1.25, + outputPerM: 10, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'claude-3-5-sonnet-20240620', - displayName: 'Claude Sonnet 3.5', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'gpt-5.1-chat-latest', + displayName: 'gpt-5.1-chat-latest', + maxInputTokens: 128000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 3, - outputPerM: 15, - cacheReadPerM: 0.3, - cacheWritePerM: 3.75, + inputPerM: 1.25, + outputPerM: 10, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'claude-3-5-sonnet-20241022', - displayName: 'Claude Sonnet 3.5 v2', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'gpt-5.2', + displayName: 'gpt-5.2', + maxInputTokens: 400000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 3, - outputPerM: 15, - cacheReadPerM: 0.3, - cacheWritePerM: 3.75, + inputPerM: 1.75, + outputPerM: 14, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'claude-3-7-sonnet-20250219', - displayName: 'Claude Sonnet 3.7', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'gpt-5.2-chat-latest', + displayName: 'gpt-5.2-chat-latest', + maxInputTokens: 128000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 3, - outputPerM: 15, - cacheReadPerM: 0.3, - cacheWritePerM: 3.75, + inputPerM: 1.75, + outputPerM: 14, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'claude-3-7-sonnet-latest', - displayName: 'Claude Sonnet 3.7 (latest)', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'grok-4-1-fast-non-reasoning', + displayName: 'grok-4-1-fast-non-reasoning', + maxInputTokens: 2000000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 3, - outputPerM: 15, - cacheReadPerM: 0.3, - cacheWritePerM: 3.75, + inputPerM: 0.2, + outputPerM: 0.5, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'claude-3-haiku-20240307', - displayName: 'Claude Haiku 3', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'grok-4-1-fast-reasoning', + displayName: 'grok-4-1-fast-reasoning', + maxInputTokens: 2000000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.25, - outputPerM: 1.25, - cacheReadPerM: 0.03, - cacheWritePerM: 0.3, + inputPerM: 0.2, + outputPerM: 0.5, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'claude-3-opus-20240229', - displayName: 'Claude Opus 3', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'grok-4-fast-non-reasoning', + displayName: 'grok-4-fast-non-reasoning', + maxInputTokens: 2000000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 15, - outputPerM: 75, - cacheReadPerM: 1.5, - cacheWritePerM: 18.75, + inputPerM: 0.2, + outputPerM: 0.5, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'claude-3-sonnet-20240229', - displayName: 'Claude Sonnet 3', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], - pricing: { - inputPerM: 3, - outputPerM: 15, - cacheReadPerM: 0.3, - cacheWritePerM: 0.3, + name: 'grok-4-fast-reasoning', + displayName: 'grok-4-fast-reasoning', + maxInputTokens: 2000000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.2, + outputPerM: 0.5, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'claude-haiku-4-5', - displayName: 'Claude Haiku 4.5 (latest)', + name: 'grok-4.1', + displayName: 'grok-4.1', maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + supportedFileTypes: ['image'], pricing: { - inputPerM: 1, - outputPerM: 5, - cacheReadPerM: 0.1, - cacheWritePerM: 1.25, + inputPerM: 2, + outputPerM: 10, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'claude-haiku-4-5-20251001', - displayName: 'Claude Haiku 4.5', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'kimi-k2-0905-preview', + displayName: 'kimi-k2-0905-preview', + maxInputTokens: 262144, + supportedFileTypes: [], pricing: { - inputPerM: 1, - outputPerM: 5, - cacheReadPerM: 0.1, - cacheWritePerM: 1.25, + inputPerM: 0.632, + outputPerM: 2.53, currency: 'USD', unit: 'per_million_tokens', }, - default: true, }, { - name: 'claude-opus-4-0', - displayName: 'Claude Opus 4 (latest)', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'kimi-k2-thinking', + displayName: 'kimi-k2-thinking', + maxInputTokens: 262144, + supportedFileTypes: [], pricing: { - inputPerM: 15, - outputPerM: 75, - cacheReadPerM: 1.5, - cacheWritePerM: 18.75, + inputPerM: 0.575, + outputPerM: 2.3, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'claude-opus-4-1', - displayName: 'Claude Opus 4.1 (latest)', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'kimi-k2-thinking-turbo', + displayName: 'kimi-k2-thinking-turbo', + maxInputTokens: 262144, + supportedFileTypes: [], pricing: { - inputPerM: 15, - outputPerM: 75, - cacheReadPerM: 1.5, - cacheWritePerM: 18.75, + inputPerM: 1.265, + outputPerM: 9.119, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'claude-opus-4-1-20250805', - displayName: 'Claude Opus 4.1', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'MiniMax-M1', + displayName: 'MiniMax-M1', + maxInputTokens: 1000000, + supportedFileTypes: [], pricing: { - inputPerM: 15, - outputPerM: 75, - cacheReadPerM: 1.5, - cacheWritePerM: 18.75, + inputPerM: 0.132, + outputPerM: 1.254, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'claude-opus-4-20250514', - displayName: 'Claude Opus 4', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'MiniMax-M2', + displayName: 'MiniMax-M2', + maxInputTokens: 1000000, + supportedFileTypes: [], pricing: { - inputPerM: 15, - outputPerM: 75, - cacheReadPerM: 1.5, - cacheWritePerM: 18.75, + inputPerM: 0.33, + outputPerM: 1.32, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'claude-opus-4-5', - displayName: 'Claude Opus 4.5 (latest)', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'MiniMax-M2.1', + displayName: 'MiniMax-M2.1', + maxInputTokens: 1000000, + supportedFileTypes: [], pricing: { - inputPerM: 5, - outputPerM: 25, - cacheReadPerM: 0.5, - cacheWritePerM: 6.25, + inputPerM: 0.3, + outputPerM: 1.2, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'claude-opus-4-5-20251101', - displayName: 'Claude Opus 4.5', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'ministral-14b-2512', + displayName: 'ministral-14b-2512', + maxInputTokens: 128000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 5, - outputPerM: 25, - cacheReadPerM: 0.5, - cacheWritePerM: 6.25, + inputPerM: 0.33, + outputPerM: 0.33, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'claude-opus-4-6', - displayName: 'Claude Opus 4.6', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'mistral-large-2512', + displayName: 'mistral-large-2512', + maxInputTokens: 128000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 5, - outputPerM: 25, - cacheReadPerM: 0.5, - cacheWritePerM: 6.25, + inputPerM: 1.1, + outputPerM: 3.3, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'claude-sonnet-4-0', - displayName: 'Claude Sonnet 4 (latest)', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'qwen-flash', + displayName: 'Qwen-Flash', + maxInputTokens: 1000000, + supportedFileTypes: [], pricing: { - inputPerM: 3, - outputPerM: 15, - cacheReadPerM: 0.3, - cacheWritePerM: 3.75, + inputPerM: 0.022, + outputPerM: 0.22, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'claude-sonnet-4-20250514', - displayName: 'Claude Sonnet 4', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'qwen-max-latest', + displayName: 'Qwen-Max-Latest', + maxInputTokens: 131072, + supportedFileTypes: [], pricing: { - inputPerM: 3, - outputPerM: 15, - cacheReadPerM: 0.3, - cacheWritePerM: 3.75, + inputPerM: 0.343, + outputPerM: 1.372, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'claude-sonnet-4-5', - displayName: 'Claude Sonnet 4.5 (latest)', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'qwen-plus', + displayName: 'Qwen-Plus', + maxInputTokens: 1000000, + supportedFileTypes: [], pricing: { - inputPerM: 3, - outputPerM: 15, - cacheReadPerM: 0.3, - cacheWritePerM: 3.75, + inputPerM: 0.12, + outputPerM: 1.2, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'claude-sonnet-4-5-20250929', - displayName: 'Claude Sonnet 4.5', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'qwen3-235b-a22b', + displayName: 'Qwen3-235B-A22B', + maxInputTokens: 128000, + supportedFileTypes: [], pricing: { - inputPerM: 3, - outputPerM: 15, - cacheReadPerM: 0.3, - cacheWritePerM: 3.75, + inputPerM: 0.29, + outputPerM: 2.86, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'claude-sonnet-4-6', - displayName: 'Claude Sonnet 4.6', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'qwen3-235b-a22b-instruct-2507', + displayName: 'qwen3-235b-a22b-instruct-2507', + maxInputTokens: 128000, + supportedFileTypes: [], pricing: { - inputPerM: 3, - outputPerM: 15, - cacheReadPerM: 0.3, - cacheWritePerM: 3.75, + inputPerM: 0.29, + outputPerM: 1.143, currency: 'USD', unit: 'per_million_tokens', }, }, - ], - google: [ { - name: 'gemini-1.5-flash', - displayName: 'Gemini 1.5 Flash', - maxInputTokens: 1000000, - supportedFileTypes: ['image', 'audio'], + name: 'qwen3-30b-a3b', + displayName: 'Qwen3-30B-A3B', + maxInputTokens: 128000, + supportedFileTypes: [], pricing: { - inputPerM: 0.075, - outputPerM: 0.3, - cacheReadPerM: 0.01875, + inputPerM: 0.11, + outputPerM: 1.08, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gemini-1.5-flash-8b', - displayName: 'Gemini 1.5 Flash-8B', - maxInputTokens: 1000000, - supportedFileTypes: ['image', 'audio'], + name: 'qwen3-coder-480b-a35b-instruct', + displayName: 'qwen3-coder-480b-a35b-instruct', + maxInputTokens: 262144, + supportedFileTypes: [], pricing: { - inputPerM: 0.0375, - outputPerM: 0.15, - cacheReadPerM: 0.01, + inputPerM: 0.86, + outputPerM: 3.43, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gemini-1.5-pro', - displayName: 'Gemini 1.5 Pro', - maxInputTokens: 1000000, - supportedFileTypes: ['image', 'audio'], + name: 'qwen3-max-2025-09-23', + displayName: 'qwen3-max-2025-09-23', + maxInputTokens: 258048, + supportedFileTypes: [], pricing: { - inputPerM: 1.25, - outputPerM: 5, - cacheReadPerM: 0.3125, + inputPerM: 0.86, + outputPerM: 3.43, currency: 'USD', unit: 'per_million_tokens', }, }, + ], + abacus: [ { - name: 'gemini-2.0-flash', - displayName: 'Gemini 2.0 Flash', - maxInputTokens: 1048576, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'claude-3-7-sonnet-20250219', + displayName: 'Claude Sonnet 3.7', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0.1, - outputPerM: 0.4, - cacheReadPerM: 0.025, + inputPerM: 3, + outputPerM: 15, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gemini-2.0-flash-lite', - displayName: 'Gemini 2.0 Flash Lite', - maxInputTokens: 1048576, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'claude-haiku-4-5-20251001', + displayName: 'Claude Haiku 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0.075, - outputPerM: 0.3, + inputPerM: 1, + outputPerM: 5, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gemini-2.5-flash', - displayName: 'Gemini 2.5 Flash', - maxInputTokens: 1048576, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'claude-opus-4-1-20250805', + displayName: 'Claude Opus 4.1', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0.3, - outputPerM: 2.5, - cacheReadPerM: 0.075, + inputPerM: 15, + outputPerM: 75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gemini-2.5-flash-image', - displayName: 'Gemini 2.5 Flash Image', - maxInputTokens: 32768, - supportedFileTypes: ['image'], + name: 'claude-opus-4-20250514', + displayName: 'Claude Opus 4', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0.3, - outputPerM: 30, - cacheReadPerM: 0.075, + inputPerM: 15, + outputPerM: 75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gemini-2.5-flash-image-preview', - displayName: 'Gemini 2.5 Flash Image (Preview)', - maxInputTokens: 32768, - supportedFileTypes: ['image'], + name: 'claude-opus-4-5-20251101', + displayName: 'Claude Opus 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0.3, - outputPerM: 30, - cacheReadPerM: 0.075, + inputPerM: 5, + outputPerM: 25, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gemini-2.5-flash-lite', - displayName: 'Gemini 2.5 Flash Lite', - maxInputTokens: 1048576, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'claude-sonnet-4-20250514', + displayName: 'Claude Sonnet 4', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0.1, - outputPerM: 0.4, - cacheReadPerM: 0.025, + inputPerM: 3, + outputPerM: 15, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gemini-2.5-flash-lite-preview-06-17', - displayName: 'Gemini 2.5 Flash Lite Preview 06-17', - maxInputTokens: 1048576, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'claude-sonnet-4-5-20250929', + displayName: 'Claude Sonnet 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0.1, - outputPerM: 0.4, - cacheReadPerM: 0.025, + inputPerM: 3, + outputPerM: 15, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gemini-2.5-flash-lite-preview-09-2025', - displayName: 'Gemini 2.5 Flash Lite Preview 09-25', - maxInputTokens: 1048576, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'deepseek-ai/DeepSeek-R1', + displayName: 'DeepSeek R1', + maxInputTokens: 128000, + supportedFileTypes: [], pricing: { - inputPerM: 0.1, - outputPerM: 0.4, - cacheReadPerM: 0.025, + inputPerM: 3, + outputPerM: 7, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gemini-2.5-flash-preview-04-17', - displayName: 'Gemini 2.5 Flash Preview 04-17', - maxInputTokens: 1048576, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'deepseek-ai/DeepSeek-V3.1-Terminus', + displayName: 'DeepSeek V3.1 Terminus', + maxInputTokens: 128000, + supportedFileTypes: [], pricing: { - inputPerM: 0.15, - outputPerM: 0.6, - cacheReadPerM: 0.0375, + inputPerM: 0.27, + outputPerM: 1, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gemini-2.5-flash-preview-05-20', - displayName: 'Gemini 2.5 Flash Preview 05-20', - maxInputTokens: 1048576, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'deepseek-ai/DeepSeek-V3.2', + displayName: 'DeepSeek V3.2', + maxInputTokens: 128000, + supportedFileTypes: [], pricing: { - inputPerM: 0.15, - outputPerM: 0.6, - cacheReadPerM: 0.0375, + inputPerM: 0.27, + outputPerM: 0.4, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gemini-2.5-flash-preview-09-2025', - displayName: 'Gemini 2.5 Flash Preview 09-25', - maxInputTokens: 1048576, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'deepseek/deepseek-v3.1', + displayName: 'DeepSeek V3.1', + maxInputTokens: 128000, + supportedFileTypes: [], pricing: { - inputPerM: 0.3, - outputPerM: 2.5, - cacheReadPerM: 0.075, + inputPerM: 0.14, + outputPerM: 0.28, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gemini-2.5-flash-preview-tts', - displayName: 'Gemini 2.5 Flash Preview TTS', - maxInputTokens: 8000, - supportedFileTypes: [], + name: 'gemini-2.0-flash-001', + displayName: 'Gemini 2.0 Flash', + maxInputTokens: 1000000, + supportedFileTypes: ['image', 'audio'], pricing: { - inputPerM: 0.5, - outputPerM: 10, + inputPerM: 0.1, + outputPerM: 0.4, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gemini-2.5-pro', - displayName: 'Gemini 2.5 Pro', - maxInputTokens: 1048576, - supportedFileTypes: ['pdf', 'image', 'audio'], - pricing: { - inputPerM: 1.25, - outputPerM: 10, - cacheReadPerM: 0.31, - currency: 'USD', - unit: 'per_million_tokens', - }, + name: 'gemini-2.0-pro-exp-02-05', + displayName: 'Gemini 2.0 Pro Exp', + maxInputTokens: 2000000, + supportedFileTypes: ['image', 'audio'], }, { - name: 'gemini-2.5-pro-preview-05-06', - displayName: 'Gemini 2.5 Pro Preview 05-06', + name: 'gemini-2.5-flash', + displayName: 'Gemini 2.5 Flash', maxInputTokens: 1048576, supportedFileTypes: ['pdf', 'image', 'audio'], pricing: { - inputPerM: 1.25, - outputPerM: 10, - cacheReadPerM: 0.31, + inputPerM: 0.3, + outputPerM: 2.5, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gemini-2.5-pro-preview-06-05', - displayName: 'Gemini 2.5 Pro Preview 06-05', + name: 'gemini-2.5-pro', + displayName: 'Gemini 2.5 Pro', maxInputTokens: 1048576, supportedFileTypes: ['pdf', 'image', 'audio'], pricing: { inputPerM: 1.25, outputPerM: 10, - cacheReadPerM: 0.31, - currency: 'USD', - unit: 'per_million_tokens', - }, - }, - { - name: 'gemini-2.5-pro-preview-tts', - displayName: 'Gemini 2.5 Pro Preview TTS', - maxInputTokens: 8000, - supportedFileTypes: [], - pricing: { - inputPerM: 1, - outputPerM: 20, currency: 'USD', unit: 'per_million_tokens', }, @@ -1073,4637 +958,34678 @@ export const MODELS_BY_PROVIDER = { pricing: { inputPerM: 0.5, outputPerM: 3, - cacheReadPerM: 0.05, currency: 'USD', unit: 'per_million_tokens', }, - default: true, }, { name: 'gemini-3-pro-preview', displayName: 'Gemini 3 Pro Preview', maxInputTokens: 1000000, - supportedFileTypes: ['pdf', 'image', 'audio'], + supportedFileTypes: ['image', 'audio'], pricing: { inputPerM: 2, outputPerM: 12, - cacheReadPerM: 0.2, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gemini-embedding-001', - displayName: 'Gemini Embedding 001', - maxInputTokens: 2048, - supportedFileTypes: [], + name: 'gpt-4.1', + displayName: 'GPT-4.1', + maxInputTokens: 1047576, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.15, - outputPerM: 0, + inputPerM: 2, + outputPerM: 8, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gemini-flash-latest', - displayName: 'Gemini Flash Latest', - maxInputTokens: 1048576, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'gpt-4.1-mini', + displayName: 'GPT-4.1 Mini', + maxInputTokens: 1047576, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.3, - outputPerM: 2.5, - cacheReadPerM: 0.075, + inputPerM: 0.4, + outputPerM: 1.6, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gemini-flash-lite-latest', - displayName: 'Gemini Flash-Lite Latest', - maxInputTokens: 1048576, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'gpt-4.1-nano', + displayName: 'GPT-4.1 Nano', + maxInputTokens: 1047576, + supportedFileTypes: ['image'], pricing: { inputPerM: 0.1, outputPerM: 0.4, - cacheReadPerM: 0.025, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gemini-live-2.5-flash', - displayName: 'Gemini Live 2.5 Flash', + name: 'gpt-4o-2024-11-20', + displayName: 'GPT-4o (2024-11-20)', maxInputTokens: 128000, supportedFileTypes: ['image', 'audio'], pricing: { - inputPerM: 0.5, - outputPerM: 2, + inputPerM: 2.5, + outputPerM: 10, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gemini-live-2.5-flash-preview-native-audio', - displayName: 'Gemini Live 2.5 Flash Preview Native Audio', - maxInputTokens: 131072, - supportedFileTypes: ['audio'], + name: 'gpt-4o-mini', + displayName: 'GPT-4o Mini', + maxInputTokens: 128000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.5, - outputPerM: 2, + inputPerM: 0.15, + outputPerM: 0.6, currency: 'USD', unit: 'per_million_tokens', }, }, - ], - groq: [ { - name: 'deepseek-r1-distill-llama-70b', - displayName: 'DeepSeek R1 Distill Llama 70B', - maxInputTokens: 131072, - supportedFileTypes: [], + name: 'gpt-5', + displayName: 'GPT-5', + maxInputTokens: 400000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.75, - outputPerM: 0.99, + inputPerM: 1.25, + outputPerM: 10, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gemma2-9b-it', - displayName: 'Gemma 2 9B', - maxInputTokens: 8192, - supportedFileTypes: [], + name: 'gpt-5-mini', + displayName: 'GPT-5 Mini', + maxInputTokens: 400000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.2, - outputPerM: 0.2, + inputPerM: 0.25, + outputPerM: 2, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'llama-3.1-8b-instant', - displayName: 'Llama 3.1 8B Instant', - maxInputTokens: 131072, - supportedFileTypes: [], + name: 'gpt-5-nano', + displayName: 'GPT-5 Nano', + maxInputTokens: 400000, + supportedFileTypes: ['image'], pricing: { inputPerM: 0.05, - outputPerM: 0.08, + outputPerM: 0.4, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'llama-3.3-70b-versatile', - displayName: 'Llama 3.3 70B Versatile', - maxInputTokens: 131072, - supportedFileTypes: [], + name: 'gpt-5.1', + displayName: 'GPT-5.1', + maxInputTokens: 400000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.59, - outputPerM: 0.79, + inputPerM: 1.25, + outputPerM: 10, currency: 'USD', unit: 'per_million_tokens', }, - default: true, }, { - name: 'llama-guard-3-8b', - displayName: 'Llama Guard 3 8B', - maxInputTokens: 8192, - supportedFileTypes: [], + name: 'gpt-5.1-chat-latest', + displayName: 'GPT-5.1 Chat Latest', + maxInputTokens: 400000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.2, - outputPerM: 0.2, + inputPerM: 1.25, + outputPerM: 10, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'llama3-70b-8192', - displayName: 'Llama 3 70B', - maxInputTokens: 8192, - supportedFileTypes: [], + name: 'gpt-5.2', + displayName: 'GPT-5.2', + maxInputTokens: 400000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.59, - outputPerM: 0.79, + inputPerM: 1.75, + outputPerM: 14, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'llama3-8b-8192', - displayName: 'Llama 3 8B', - maxInputTokens: 8192, - supportedFileTypes: [], + name: 'gpt-5.2-chat-latest', + displayName: 'GPT-5.2 Chat Latest', + maxInputTokens: 400000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.05, - outputPerM: 0.08, + inputPerM: 1.5, + outputPerM: 12, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'meta-llama/llama-4-maverick-17b-128e-instruct', - displayName: 'Llama 4 Maverick 17B', - maxInputTokens: 131072, + name: 'grok-4-0709', + displayName: 'Grok 4', + maxInputTokens: 256000, supportedFileTypes: ['image'], pricing: { - inputPerM: 0.2, - outputPerM: 0.6, + inputPerM: 3, + outputPerM: 15, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'meta-llama/llama-4-scout-17b-16e-instruct', - displayName: 'Llama 4 Scout 17B', - maxInputTokens: 131072, + name: 'grok-4-1-fast-non-reasoning', + displayName: 'Grok 4.1 Fast (Non-Reasoning)', + maxInputTokens: 2000000, supportedFileTypes: ['image'], pricing: { - inputPerM: 0.11, - outputPerM: 0.34, + inputPerM: 0.2, + outputPerM: 0.5, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'meta-llama/llama-guard-4-12b', - displayName: 'Llama Guard 4 12B', - maxInputTokens: 131072, + name: 'grok-4-fast-non-reasoning', + displayName: 'Grok 4 Fast (Non-Reasoning)', + maxInputTokens: 2000000, supportedFileTypes: ['image'], pricing: { inputPerM: 0.2, - outputPerM: 0.2, + outputPerM: 0.5, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'mistral-saba-24b', - displayName: 'Mistral Saba 24B', - maxInputTokens: 32768, - supportedFileTypes: [], + name: 'grok-code-fast-1', + displayName: 'Grok Code Fast 1', + maxInputTokens: 256000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.79, - outputPerM: 0.79, + inputPerM: 0.2, + outputPerM: 1.5, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'moonshotai/kimi-k2-instruct', - displayName: 'Kimi K2 Instruct', - maxInputTokens: 131072, + name: 'kimi-k2-turbo-preview', + displayName: 'Kimi K2 Turbo Preview', + maxInputTokens: 256000, supportedFileTypes: [], pricing: { - inputPerM: 1, - outputPerM: 3, + inputPerM: 0.15, + outputPerM: 8, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'moonshotai/kimi-k2-instruct-0905', - displayName: 'Kimi K2 Instruct 0905', - maxInputTokens: 262144, + name: 'llama-3.3-70b-versatile', + displayName: 'Llama 3.3 70B Versatile', + maxInputTokens: 128000, supportedFileTypes: [], pricing: { - inputPerM: 1, - outputPerM: 3, + inputPerM: 0.59, + outputPerM: 0.79, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openai/gpt-oss-120b', - displayName: 'GPT OSS 120B', - maxInputTokens: 131072, - supportedFileTypes: [], + name: 'meta-llama/Llama-4-Maverick-17B-128E-Instruct-FP8', + displayName: 'Llama 4 Maverick 17B 128E Instruct FP8', + maxInputTokens: 1000000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.15, - outputPerM: 0.6, + inputPerM: 0.14, + outputPerM: 0.59, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openai/gpt-oss-20b', - displayName: 'GPT OSS 20B', - maxInputTokens: 131072, + name: 'meta-llama/Meta-Llama-3.1-405B-Instruct-Turbo', + displayName: 'Llama 3.1 405B Instruct Turbo', + maxInputTokens: 128000, supportedFileTypes: [], pricing: { - inputPerM: 0.075, - outputPerM: 0.3, + inputPerM: 3.5, + outputPerM: 3.5, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'qwen-qwq-32b', - displayName: 'Qwen QwQ 32B', - maxInputTokens: 131072, + name: 'meta-llama/Meta-Llama-3.1-70B-Instruct', + displayName: 'Llama 3.1 70B Instruct', + maxInputTokens: 128000, supportedFileTypes: [], pricing: { - inputPerM: 0.29, - outputPerM: 0.39, + inputPerM: 0.4, + outputPerM: 0.4, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'qwen/qwen3-32b', - displayName: 'Qwen3 32B', - maxInputTokens: 131072, + name: 'meta-llama/Meta-Llama-3.1-8B-Instruct', + displayName: 'Llama 3.1 8B Instruct', + maxInputTokens: 128000, supportedFileTypes: [], pricing: { - inputPerM: 0.29, - outputPerM: 0.59, + inputPerM: 0.02, + outputPerM: 0.05, currency: 'USD', unit: 'per_million_tokens', }, }, - ], - xai: [ { - name: 'grok-2', - displayName: 'Grok 2', - maxInputTokens: 131072, - supportedFileTypes: [], + name: 'o3', + displayName: 'o3', + maxInputTokens: 200000, + supportedFileTypes: ['image'], pricing: { inputPerM: 2, - outputPerM: 10, - cacheReadPerM: 2, + outputPerM: 8, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'grok-2-1212', - displayName: 'Grok 2 (1212)', - maxInputTokens: 131072, + name: 'o3-mini', + displayName: 'o3-mini', + maxInputTokens: 200000, supportedFileTypes: [], pricing: { - inputPerM: 2, - outputPerM: 10, - cacheReadPerM: 2, + inputPerM: 1.1, + outputPerM: 4.4, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'grok-2-latest', - displayName: 'Grok 2 Latest', - maxInputTokens: 131072, - supportedFileTypes: [], + name: 'o3-pro', + displayName: 'o3-pro', + maxInputTokens: 200000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 2, - outputPerM: 10, - cacheReadPerM: 2, + inputPerM: 20, + outputPerM: 80, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'grok-2-vision', - displayName: 'Grok 2 Vision', - maxInputTokens: 8192, + name: 'o4-mini', + displayName: 'o4-mini', + maxInputTokens: 200000, supportedFileTypes: ['image'], pricing: { - inputPerM: 2, - outputPerM: 10, - cacheReadPerM: 2, + inputPerM: 1.1, + outputPerM: 4.4, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'grok-2-vision-1212', - displayName: 'Grok 2 Vision (1212)', - maxInputTokens: 8192, + name: 'openai/gpt-oss-120b', + displayName: 'GPT-OSS 120B', + maxInputTokens: 128000, supportedFileTypes: ['image'], pricing: { - inputPerM: 2, - outputPerM: 10, - cacheReadPerM: 2, + inputPerM: 0.08, + outputPerM: 0.44, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'grok-2-vision-latest', - displayName: 'Grok 2 Vision Latest', - maxInputTokens: 8192, - supportedFileTypes: ['image'], + name: 'qwen-2.5-coder-32b', + displayName: 'Qwen 2.5 Coder 32B', + maxInputTokens: 128000, + supportedFileTypes: [], pricing: { - inputPerM: 2, - outputPerM: 10, - cacheReadPerM: 2, + inputPerM: 0.79, + outputPerM: 0.79, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'grok-3', - displayName: 'Grok 3', - maxInputTokens: 131072, + name: 'Qwen/Qwen2.5-72B-Instruct', + displayName: 'Qwen 2.5 72B Instruct', + maxInputTokens: 128000, supportedFileTypes: [], pricing: { - inputPerM: 3, - outputPerM: 15, - cacheReadPerM: 0.75, + inputPerM: 0.11, + outputPerM: 0.38, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'grok-3-fast', - displayName: 'Grok 3 Fast', - maxInputTokens: 131072, + name: 'Qwen/Qwen3-235B-A22B-Instruct-2507', + displayName: 'Qwen3 235B A22B Instruct', + maxInputTokens: 262144, supportedFileTypes: [], pricing: { - inputPerM: 5, - outputPerM: 25, - cacheReadPerM: 1.25, + inputPerM: 0.13, + outputPerM: 0.6, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'grok-3-fast-latest', - displayName: 'Grok 3 Fast Latest', - maxInputTokens: 131072, + name: 'Qwen/Qwen3-32B', + displayName: 'Qwen3 32B', + maxInputTokens: 128000, supportedFileTypes: [], pricing: { - inputPerM: 5, - outputPerM: 25, - cacheReadPerM: 1.25, + inputPerM: 0.09, + outputPerM: 0.29, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'grok-3-latest', - displayName: 'Grok 3 Latest', - maxInputTokens: 131072, + name: 'Qwen/qwen3-coder-480b-a35b-instruct', + displayName: 'Qwen3 Coder 480B A35B Instruct', + maxInputTokens: 262144, supportedFileTypes: [], pricing: { - inputPerM: 3, - outputPerM: 15, - cacheReadPerM: 0.75, + inputPerM: 0.29, + outputPerM: 1.2, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'grok-3-mini', - displayName: 'Grok 3 Mini', - maxInputTokens: 131072, + name: 'Qwen/QwQ-32B', + displayName: 'QwQ 32B', + maxInputTokens: 32768, supportedFileTypes: [], pricing: { - inputPerM: 0.3, - outputPerM: 0.5, - cacheReadPerM: 0.075, + inputPerM: 0.4, + outputPerM: 0.4, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'grok-3-mini-fast', - displayName: 'Grok 3 Mini Fast', + name: 'qwen3-max', + displayName: 'Qwen3 Max', maxInputTokens: 131072, supportedFileTypes: [], pricing: { - inputPerM: 0.6, - outputPerM: 4, - cacheReadPerM: 0.15, + inputPerM: 1.2, + outputPerM: 6, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'grok-3-mini-fast-latest', - displayName: 'Grok 3 Mini Fast Latest', - maxInputTokens: 131072, - supportedFileTypes: [], + name: 'route-llm', + displayName: 'Route LLM', + maxInputTokens: 128000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.6, - outputPerM: 4, - cacheReadPerM: 0.15, + inputPerM: 0.5, + outputPerM: 1.5, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'grok-3-mini-latest', - displayName: 'Grok 3 Mini Latest', - maxInputTokens: 131072, + name: 'zai-org/glm-4.5', + displayName: 'GLM-4.5', + maxInputTokens: 128000, supportedFileTypes: [], pricing: { - inputPerM: 0.3, - outputPerM: 0.5, - cacheReadPerM: 0.075, + inputPerM: 0.6, + outputPerM: 2.2, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'grok-4', - displayName: 'Grok 4', - maxInputTokens: 256000, + name: 'zai-org/glm-4.6', + displayName: 'GLM-4.6', + maxInputTokens: 128000, supportedFileTypes: [], pricing: { - inputPerM: 3, - outputPerM: 15, - cacheReadPerM: 0.75, + inputPerM: 0.6, + outputPerM: 2.2, currency: 'USD', unit: 'per_million_tokens', }, - default: true, }, { - name: 'grok-4-1-fast', - displayName: 'Grok 4.1 Fast', - maxInputTokens: 2000000, - supportedFileTypes: ['image'], + name: 'zai-org/glm-4.7', + displayName: 'GLM-4.7', + maxInputTokens: 128000, + supportedFileTypes: [], pricing: { - inputPerM: 0.2, - outputPerM: 0.5, - cacheReadPerM: 0.05, + inputPerM: 0.7, + outputPerM: 2.5, currency: 'USD', unit: 'per_million_tokens', }, }, + ], + aihubmix: [ { - name: 'grok-4-1-fast-non-reasoning', - displayName: 'Grok 4.1 Fast (Non-Reasoning)', - maxInputTokens: 2000000, - supportedFileTypes: ['image'], + name: 'claude-haiku-4-5', + displayName: 'Claude Haiku 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0.2, - outputPerM: 0.5, - cacheReadPerM: 0.05, + inputPerM: 1.1, + outputPerM: 5.5, + cacheReadPerM: 0.11, + cacheWritePerM: 1.25, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'grok-4-fast', - displayName: 'Grok 4 Fast', - maxInputTokens: 2000000, - supportedFileTypes: ['image'], + name: 'claude-opus-4-1', + displayName: 'Claude Opus 4.1', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0.2, - outputPerM: 0.5, - cacheReadPerM: 0.05, + inputPerM: 16.5, + outputPerM: 82.5, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'grok-4-fast-non-reasoning', - displayName: 'Grok 4 Fast (Non-Reasoning)', - maxInputTokens: 2000000, + name: 'claude-opus-4-5', + displayName: 'Claude Opus 4.5', + maxInputTokens: 200000, supportedFileTypes: ['image'], pricing: { - inputPerM: 0.2, - outputPerM: 0.5, - cacheReadPerM: 0.05, + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'grok-beta', - displayName: 'Grok Beta', - maxInputTokens: 131072, - supportedFileTypes: [], + name: 'claude-opus-4-6', + displayName: 'Claude Opus 4.6', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { inputPerM: 5, - outputPerM: 15, - cacheReadPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'grok-code-fast-1', - displayName: 'Grok Code Fast 1', - maxInputTokens: 256000, - supportedFileTypes: [], + name: 'claude-opus-4-6-think', + displayName: 'Claude Opus 4.6 Think', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0.2, - outputPerM: 1.5, - cacheReadPerM: 0.02, + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'grok-vision-beta', - displayName: 'Grok Vision Beta', - maxInputTokens: 8192, - supportedFileTypes: ['image'], + name: 'claude-sonnet-4-5', + displayName: 'Claude Sonnet 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 5, - outputPerM: 15, - cacheReadPerM: 5, + inputPerM: 3.3, + outputPerM: 16.5, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, currency: 'USD', unit: 'per_million_tokens', }, }, - ], - cohere: [ { - name: 'command-a-03-2025', - displayName: 'Command A', - maxInputTokens: 256000, - supportedFileTypes: [], + name: 'claude-sonnet-4-6', + displayName: 'Claude Sonnet 4.6', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 2.5, - outputPerM: 10, + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, currency: 'USD', unit: 'per_million_tokens', }, - default: true, }, { - name: 'command-a-reasoning-08-2025', - displayName: 'Command A Reasoning', - maxInputTokens: 256000, - supportedFileTypes: [], + name: 'claude-sonnet-4-6-think', + displayName: 'Claude Sonnet 4.6 Think', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 2.5, - outputPerM: 10, + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'command-a-translate-08-2025', - displayName: 'Command A Translate', - maxInputTokens: 8000, + name: 'coding-glm-4.7', + displayName: 'Coding-GLM-4.7', + maxInputTokens: 204800, supportedFileTypes: [], pricing: { - inputPerM: 2.5, - outputPerM: 10, + inputPerM: 0.27, + outputPerM: 1.1, + cacheReadPerM: 0.548, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'command-a-vision-07-2025', - displayName: 'Command A Vision', - maxInputTokens: 128000, - supportedFileTypes: ['image'], + name: 'coding-glm-4.7-free', + displayName: 'Coding GLM 4.7 Free', + maxInputTokens: 204800, + supportedFileTypes: [], pricing: { - inputPerM: 2.5, - outputPerM: 10, + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'command-r-08-2024', - displayName: 'Command R', - maxInputTokens: 128000, + name: 'coding-minimax-m2.1-free', + displayName: 'Coding MiniMax M2.1 Free', + maxInputTokens: 204800, supportedFileTypes: [], pricing: { - inputPerM: 0.15, - outputPerM: 0.6, + inputPerM: 0, + outputPerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'command-r-plus-08-2024', - displayName: 'Command R+', - maxInputTokens: 128000, + name: 'deepseek-v3.2', + displayName: 'DeepSeek-V3.2', + maxInputTokens: 131000, supportedFileTypes: [], pricing: { - inputPerM: 2.5, - outputPerM: 10, + inputPerM: 0.3, + outputPerM: 0.45, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'command-r7b-12-2024', - displayName: 'Command R7B', + name: 'deepseek-v3.2-fast', + displayName: 'DeepSeek-V3.2-Fast', maxInputTokens: 128000, supportedFileTypes: [], pricing: { - inputPerM: 0.0375, - outputPerM: 0.15, + inputPerM: 1.1, + outputPerM: 3.29, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'command-r7b-arabic-02-2025', - displayName: 'Command R7B Arabic', - maxInputTokens: 128000, + name: 'deepseek-v3.2-think', + displayName: 'DeepSeek-V3.2-Think', + maxInputTokens: 131000, supportedFileTypes: [], pricing: { - inputPerM: 0.0375, - outputPerM: 0.15, + inputPerM: 0.3, + outputPerM: 0.45, currency: 'USD', unit: 'per_million_tokens', }, }, - ], - minimax: [ { - name: 'MiniMax-M2', - displayName: 'MiniMax-M2', - maxInputTokens: 196608, - supportedFileTypes: [], + name: 'gemini-2.5-flash', + displayName: 'Gemini 2.5 Flash', + maxInputTokens: 1000000, + supportedFileTypes: ['image', 'audio'], pricing: { - inputPerM: 0.3, - outputPerM: 1.2, + inputPerM: 0.075, + outputPerM: 0.3, + cacheReadPerM: 0.02, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'MiniMax-M2.1', - displayName: 'MiniMax-M2.1', - maxInputTokens: 204800, - supportedFileTypes: [], + name: 'gemini-2.5-pro', + displayName: 'Gemini 2.5 Pro', + maxInputTokens: 2000000, + supportedFileTypes: ['image', 'audio'], pricing: { - inputPerM: 0.3, - outputPerM: 1.2, + inputPerM: 1.25, + outputPerM: 5, + cacheReadPerM: 0.31, currency: 'USD', unit: 'per_million_tokens', }, - default: true, }, { - name: 'MiniMax-M2.5', - displayName: 'MiniMax-M2.5', - maxInputTokens: 204800, - supportedFileTypes: [], + name: 'gemini-3-pro-preview', + displayName: 'Gemini 3 Pro Preview', + maxInputTokens: 1000000, + supportedFileTypes: ['image', 'audio'], pricing: { - inputPerM: 0.3, - outputPerM: 1.2, - cacheReadPerM: 0.03, - cacheWritePerM: 0.375, + inputPerM: 2, + outputPerM: 12, + cacheReadPerM: 0.5, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'MiniMax-M2.5-highspeed', - displayName: 'MiniMax-M2.5-highspeed', - maxInputTokens: 204800, - supportedFileTypes: [], + name: 'gemini-3-pro-preview-search', + displayName: 'Gemini 3 Pro Preview Search', + maxInputTokens: 1000000, + supportedFileTypes: ['image', 'audio'], pricing: { - inputPerM: 0.6, - outputPerM: 2.4, - cacheReadPerM: 0.06, - cacheWritePerM: 0.375, + inputPerM: 2, + outputPerM: 12, + cacheReadPerM: 0.5, currency: 'USD', unit: 'per_million_tokens', }, }, - ], - 'minimax-cn': [ { - name: 'MiniMax-M2', - displayName: 'MiniMax-M2', - maxInputTokens: 196608, - supportedFileTypes: [], + name: 'glm-4.6v', + displayName: 'GLM-4.6V', + maxInputTokens: 128000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.3, - outputPerM: 1.2, + inputPerM: 0.14, + outputPerM: 0.41, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'MiniMax-M2.1', - displayName: 'MiniMax-M2.1', + name: 'glm-4.7', + displayName: 'GLM-4.7', maxInputTokens: 204800, supportedFileTypes: [], pricing: { - inputPerM: 0.3, - outputPerM: 1.2, + inputPerM: 0.27, + outputPerM: 1.1, + cacheReadPerM: 0.548, currency: 'USD', unit: 'per_million_tokens', }, - default: true, }, { - name: 'MiniMax-M2.5', - displayName: 'MiniMax-M2.5', - maxInputTokens: 204800, - supportedFileTypes: [], + name: 'gpt-4.1', + displayName: 'GPT-4.1', + maxInputTokens: 1047576, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.3, - outputPerM: 1.2, - cacheReadPerM: 0.03, - cacheWritePerM: 0.375, + inputPerM: 2, + outputPerM: 8, + cacheReadPerM: 0.5, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'MiniMax-M2.5-highspeed', - displayName: 'MiniMax-M2.5-highspeed', - maxInputTokens: 204800, - supportedFileTypes: [], + name: 'gpt-4.1-mini', + displayName: 'GPT-4.1 mini', + maxInputTokens: 1047576, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.6, - outputPerM: 2.4, - cacheReadPerM: 0.06, - cacheWritePerM: 0.375, + inputPerM: 0.4, + outputPerM: 1.6, + cacheReadPerM: 0.1, currency: 'USD', unit: 'per_million_tokens', }, }, - ], - 'minimax-coding-plan': [ { - name: 'MiniMax-M2', - displayName: 'MiniMax-M2', - maxInputTokens: 196608, - supportedFileTypes: [], + name: 'gpt-4.1-nano', + displayName: 'GPT-4.1 nano', + maxInputTokens: 1047576, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.1, + outputPerM: 0.4, + cacheReadPerM: 0.03, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'MiniMax-M2.1', - displayName: 'MiniMax-M2.1', - maxInputTokens: 204800, - supportedFileTypes: [], + name: 'gpt-4o', + displayName: 'GPT-4o', + maxInputTokens: 128000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 2.5, + outputPerM: 10, + cacheReadPerM: 1.25, currency: 'USD', unit: 'per_million_tokens', }, - default: true, }, { - name: 'MiniMax-M2.5', - displayName: 'MiniMax-M2.5', - maxInputTokens: 204800, - supportedFileTypes: [], + name: 'gpt-5', + displayName: 'GPT-5', + maxInputTokens: 400000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0, - outputPerM: 0, - cacheReadPerM: 0, - cacheWritePerM: 0, + inputPerM: 5, + outputPerM: 20, + cacheReadPerM: 2.5, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'MiniMax-M2.5-highspeed', - displayName: 'MiniMax-M2.5-highspeed', - maxInputTokens: 204800, - supportedFileTypes: [], + name: 'gpt-5-codex', + displayName: 'GPT-5-Codex', + maxInputTokens: 400000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0, - outputPerM: 0, - cacheReadPerM: 0, - cacheWritePerM: 0, + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.13, currency: 'USD', unit: 'per_million_tokens', }, }, - ], - 'minimax-cn-coding-plan': [ { - name: 'MiniMax-M2', - displayName: 'MiniMax-M2', - maxInputTokens: 196608, - supportedFileTypes: [], + name: 'gpt-5-mini', + displayName: 'GPT-5-Mini', + maxInputTokens: 200000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 1.5, + outputPerM: 6, + cacheReadPerM: 0.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'MiniMax-M2.1', - displayName: 'MiniMax-M2.1', - maxInputTokens: 204800, - supportedFileTypes: [], + name: 'gpt-5-nano', + displayName: 'GPT-5-Nano', + maxInputTokens: 128000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.5, + outputPerM: 2, + cacheReadPerM: 0.25, currency: 'USD', unit: 'per_million_tokens', }, - default: true, }, { - name: 'MiniMax-M2.5', - displayName: 'MiniMax-M2.5', - maxInputTokens: 204800, - supportedFileTypes: [], + name: 'gpt-5-pro', + displayName: 'GPT-5-Pro', + maxInputTokens: 400000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0, - outputPerM: 0, - cacheReadPerM: 0, - cacheWritePerM: 0, + inputPerM: 7, + outputPerM: 28, + cacheReadPerM: 3.5, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'MiniMax-M2.5-highspeed', - displayName: 'MiniMax-M2.5-highspeed', - maxInputTokens: 204800, - supportedFileTypes: [], + name: 'gpt-5.1', + displayName: 'GPT-5.1', + maxInputTokens: 400000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0, - outputPerM: 0, - cacheReadPerM: 0, - cacheWritePerM: 0, + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.125, currency: 'USD', unit: 'per_million_tokens', }, }, - ], - glm: [ { - name: 'glm-4.5', - displayName: 'GLM-4.5', - maxInputTokens: 131072, - supportedFileTypes: [], + name: 'gpt-5.1-codex', + displayName: 'GPT-5.1 Codex', + maxInputTokens: 400000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.6, - outputPerM: 2.2, - cacheReadPerM: 0.11, - cacheWritePerM: 0, + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.13, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'glm-4.5-air', - displayName: 'GLM-4.5-Air', - maxInputTokens: 131072, - supportedFileTypes: [], + name: 'gpt-5.1-codex-max', + displayName: 'GPT-5.1-Codex-Max', + maxInputTokens: 400000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.2, - outputPerM: 1.1, + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.1-codex-mini', + displayName: 'GPT-5.1 Codex Mini', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.25, + outputPerM: 2, cacheReadPerM: 0.03, - cacheWritePerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'glm-4.5-flash', - displayName: 'GLM-4.5-Flash', - maxInputTokens: 131072, - supportedFileTypes: [], + name: 'gpt-5.2', + displayName: 'GPT-5.2', + maxInputTokens: 400000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0, - outputPerM: 0, - cacheReadPerM: 0, - cacheWritePerM: 0, + inputPerM: 1.75, + outputPerM: 14, + cacheReadPerM: 0.175, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'glm-4.5v', - displayName: 'GLM-4.5V', - maxInputTokens: 64000, + name: 'gpt-5.2-codex', + displayName: 'GPT-5.2-Codex', + maxInputTokens: 400000, supportedFileTypes: ['image'], pricing: { - inputPerM: 0.6, - outputPerM: 1.8, + inputPerM: 1.75, + outputPerM: 14, + cacheReadPerM: 0.175, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'glm-4.6', - displayName: 'GLM-4.6', - maxInputTokens: 204800, + name: 'Kimi-K2-0905', + displayName: 'Kimi K2 0905', + maxInputTokens: 262144, supportedFileTypes: [], pricing: { - inputPerM: 0.6, - outputPerM: 2.2, - cacheReadPerM: 0.11, - cacheWritePerM: 0, + inputPerM: 0.55, + outputPerM: 2.19, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'glm-4.6v', - displayName: 'GLM-4.6V', - maxInputTokens: 128000, + name: 'kimi-k2.5', + displayName: 'Kimi K2.5', + maxInputTokens: 262144, supportedFileTypes: ['image'], pricing: { - inputPerM: 0.3, - outputPerM: 0.9, + inputPerM: 0.6, + outputPerM: 3, + cacheReadPerM: 0.1, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'glm-4.7', - displayName: 'GLM-4.7', + name: 'minimax-m2.1', + displayName: 'MiniMax M2.1', maxInputTokens: 204800, supportedFileTypes: [], pricing: { - inputPerM: 0.6, - outputPerM: 2.2, - cacheReadPerM: 0.11, - cacheWritePerM: 0, + inputPerM: 0.29, + outputPerM: 1.15, currency: 'USD', unit: 'per_million_tokens', }, - default: true, }, { - name: 'glm-4.7-flash', - displayName: 'GLM-4.7-Flash', + name: 'o4-mini', + displayName: 'o4-mini', maxInputTokens: 200000, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, - cacheReadPerM: 0, - cacheWritePerM: 0, + inputPerM: 1.5, + outputPerM: 6, + cacheReadPerM: 0.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'glm-5', - displayName: 'GLM-5', - maxInputTokens: 204800, + name: 'qwen3-235b-a22b-instruct-2507', + displayName: 'Qwen3 235B A22B Instruct 2507', + maxInputTokens: 262144, supportedFileTypes: [], pricing: { - inputPerM: 1, - outputPerM: 3.2, - cacheReadPerM: 0.2, - cacheWritePerM: 0, + inputPerM: 0.28, + outputPerM: 1.12, currency: 'USD', unit: 'per_million_tokens', }, }, - ], - zhipuai: [ { - name: 'glm-4.5', - displayName: 'GLM-4.5', - maxInputTokens: 131072, + name: 'qwen3-235b-a22b-thinking-2507', + displayName: 'Qwen3 235B A22B Thinking 2507', + maxInputTokens: 262144, supportedFileTypes: [], pricing: { - inputPerM: 0.6, - outputPerM: 2.2, - cacheReadPerM: 0.11, - cacheWritePerM: 0, + inputPerM: 0.28, + outputPerM: 2.8, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'glm-4.5-air', - displayName: 'GLM-4.5-Air', - maxInputTokens: 131072, + name: 'qwen3-coder-480b-a35b-instruct', + displayName: 'Qwen3 Coder 480B A35B Instruct', + maxInputTokens: 262144, supportedFileTypes: [], pricing: { - inputPerM: 0.2, - outputPerM: 1.1, - cacheReadPerM: 0.03, - cacheWritePerM: 0, + inputPerM: 0.82, + outputPerM: 3.29, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'glm-4.5-flash', - displayName: 'GLM-4.5-Flash', - maxInputTokens: 131072, + name: 'qwen3-max-2026-01-23', + displayName: 'Qwen3 Max', + maxInputTokens: 262144, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, - cacheReadPerM: 0, - cacheWritePerM: 0, + inputPerM: 0.34, + outputPerM: 1.37, currency: 'USD', unit: 'per_million_tokens', }, }, + ], + alibaba: [ { - name: 'glm-4.5v', - displayName: 'GLM-4.5V', - maxInputTokens: 64000, + name: 'qvq-max', + displayName: 'QVQ Max', + maxInputTokens: 131072, supportedFileTypes: ['image'], pricing: { - inputPerM: 0.6, - outputPerM: 1.8, + inputPerM: 1.2, + outputPerM: 4.8, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'glm-4.6', - displayName: 'GLM-4.6', - maxInputTokens: 204800, + name: 'qwen-flash', + displayName: 'Qwen Flash', + maxInputTokens: 1000000, supportedFileTypes: [], pricing: { - inputPerM: 0.6, - outputPerM: 2.2, - cacheReadPerM: 0.11, - cacheWritePerM: 0, + inputPerM: 0.05, + outputPerM: 0.4, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'glm-4.6v', - displayName: 'GLM-4.6V', - maxInputTokens: 128000, - supportedFileTypes: ['image'], + name: 'qwen-max', + displayName: 'Qwen Max', + maxInputTokens: 32768, + supportedFileTypes: [], pricing: { - inputPerM: 0.3, - outputPerM: 0.9, + inputPerM: 1.6, + outputPerM: 6.4, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'glm-4.7', - displayName: 'GLM-4.7', - maxInputTokens: 204800, + name: 'qwen-mt-plus', + displayName: 'Qwen-MT Plus', + maxInputTokens: 16384, supportedFileTypes: [], pricing: { - inputPerM: 0.6, - outputPerM: 2.2, - cacheReadPerM: 0.11, - cacheWritePerM: 0, + inputPerM: 2.46, + outputPerM: 7.37, currency: 'USD', unit: 'per_million_tokens', }, - default: true, }, { - name: 'glm-4.7-flash', - displayName: 'GLM-4.7-Flash', - maxInputTokens: 200000, + name: 'qwen-mt-turbo', + displayName: 'Qwen-MT Turbo', + maxInputTokens: 16384, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, - cacheReadPerM: 0, - cacheWritePerM: 0, + inputPerM: 0.16, + outputPerM: 0.49, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'glm-5', - displayName: 'GLM-5', - maxInputTokens: 204800, - supportedFileTypes: [], + name: 'qwen-omni-turbo', + displayName: 'Qwen-Omni Turbo', + maxInputTokens: 32768, + supportedFileTypes: ['image', 'audio'], pricing: { - inputPerM: 1, - outputPerM: 3.2, - cacheReadPerM: 0.2, - cacheWritePerM: 0, + inputPerM: 0.07, + outputPerM: 0.27, currency: 'USD', unit: 'per_million_tokens', }, }, - ], - 'zhipuai-coding-plan': [ { - name: 'glm-4.5', - displayName: 'GLM-4.5', - maxInputTokens: 131072, - supportedFileTypes: [], + name: 'qwen-omni-turbo-realtime', + displayName: 'Qwen-Omni Turbo Realtime', + maxInputTokens: 32768, + supportedFileTypes: ['image', 'audio'], pricing: { - inputPerM: 0, - outputPerM: 0, - cacheReadPerM: 0, - cacheWritePerM: 0, + inputPerM: 0.27, + outputPerM: 1.07, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'glm-4.5-air', - displayName: 'GLM-4.5-Air', - maxInputTokens: 131072, + name: 'qwen-plus', + displayName: 'Qwen Plus', + maxInputTokens: 1000000, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, - cacheReadPerM: 0, - cacheWritePerM: 0, + inputPerM: 0.4, + outputPerM: 1.2, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'glm-4.5-flash', - displayName: 'GLM-4.5-Flash', - maxInputTokens: 131072, + name: 'qwen-plus-character-ja', + displayName: 'Qwen Plus Character (Japanese)', + maxInputTokens: 8192, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, - cacheReadPerM: 0, - cacheWritePerM: 0, + inputPerM: 0.5, + outputPerM: 1.4, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'glm-4.5v', - displayName: 'GLM-4.5V', - maxInputTokens: 64000, - supportedFileTypes: ['image'], + name: 'qwen-turbo', + displayName: 'Qwen Turbo', + maxInputTokens: 1000000, + supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.05, + outputPerM: 0.2, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'glm-4.6', - displayName: 'GLM-4.6', - maxInputTokens: 204800, - supportedFileTypes: [], + name: 'qwen-vl-max', + displayName: 'Qwen-VL Max', + maxInputTokens: 131072, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0, - outputPerM: 0, - cacheReadPerM: 0, - cacheWritePerM: 0, + inputPerM: 0.8, + outputPerM: 3.2, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'glm-4.6v', - displayName: 'GLM-4.6V', - maxInputTokens: 128000, + name: 'qwen-vl-ocr', + displayName: 'Qwen-VL OCR', + maxInputTokens: 34096, supportedFileTypes: ['image'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.72, + outputPerM: 0.72, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'glm-4.6v-flash', - displayName: 'GLM-4.6V-Flash', - maxInputTokens: 128000, + name: 'qwen-vl-plus', + displayName: 'Qwen-VL Plus', + maxInputTokens: 131072, supportedFileTypes: ['image'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.21, + outputPerM: 0.63, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'glm-4.7', - displayName: 'GLM-4.7', - maxInputTokens: 204800, + name: 'qwen2-5-14b-instruct', + displayName: 'Qwen2.5 14B Instruct', + maxInputTokens: 131072, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, - cacheReadPerM: 0, - cacheWritePerM: 0, + inputPerM: 0.35, + outputPerM: 1.4, currency: 'USD', unit: 'per_million_tokens', }, - default: true, }, { - name: 'glm-5', - displayName: 'GLM-5', - maxInputTokens: 204800, + name: 'qwen2-5-32b-instruct', + displayName: 'Qwen2.5 32B Instruct', + maxInputTokens: 131072, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, - cacheReadPerM: 0, - cacheWritePerM: 0, + inputPerM: 0.7, + outputPerM: 2.8, currency: 'USD', unit: 'per_million_tokens', }, }, - ], - zai: [ { - name: 'glm-4.5', - displayName: 'GLM-4.5', + name: 'qwen2-5-72b-instruct', + displayName: 'Qwen2.5 72B Instruct', maxInputTokens: 131072, supportedFileTypes: [], pricing: { - inputPerM: 0.6, - outputPerM: 2.2, - cacheReadPerM: 0.11, - cacheWritePerM: 0, + inputPerM: 1.4, + outputPerM: 5.6, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'glm-4.5-air', - displayName: 'GLM-4.5-Air', + name: 'qwen2-5-7b-instruct', + displayName: 'Qwen2.5 7B Instruct', maxInputTokens: 131072, supportedFileTypes: [], pricing: { - inputPerM: 0.2, - outputPerM: 1.1, - cacheReadPerM: 0.03, - cacheWritePerM: 0, + inputPerM: 0.175, + outputPerM: 0.7, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'glm-4.5-flash', - displayName: 'GLM-4.5-Flash', - maxInputTokens: 131072, - supportedFileTypes: [], + name: 'qwen2-5-omni-7b', + displayName: 'Qwen2.5-Omni 7B', + maxInputTokens: 32768, + supportedFileTypes: ['image', 'audio'], pricing: { - inputPerM: 0, - outputPerM: 0, - cacheReadPerM: 0, - cacheWritePerM: 0, + inputPerM: 0.1, + outputPerM: 0.4, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'glm-4.5v', - displayName: 'GLM-4.5V', - maxInputTokens: 64000, + name: 'qwen2-5-vl-72b-instruct', + displayName: 'Qwen2.5-VL 72B Instruct', + maxInputTokens: 131072, supportedFileTypes: ['image'], pricing: { - inputPerM: 0.6, - outputPerM: 1.8, + inputPerM: 2.8, + outputPerM: 8.4, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'glm-4.6', - displayName: 'GLM-4.6', - maxInputTokens: 204800, - supportedFileTypes: [], + name: 'qwen2-5-vl-7b-instruct', + displayName: 'Qwen2.5-VL 7B Instruct', + maxInputTokens: 131072, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.6, - outputPerM: 2.2, - cacheReadPerM: 0.11, - cacheWritePerM: 0, + inputPerM: 0.35, + outputPerM: 1.05, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'glm-4.6v', - displayName: 'GLM-4.6V', - maxInputTokens: 128000, - supportedFileTypes: ['image'], + name: 'qwen3-14b', + displayName: 'Qwen3 14B', + maxInputTokens: 131072, + supportedFileTypes: [], pricing: { - inputPerM: 0.3, - outputPerM: 0.9, + inputPerM: 0.35, + outputPerM: 1.4, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'glm-4.7', - displayName: 'GLM-4.7', - maxInputTokens: 204800, + name: 'qwen3-235b-a22b', + displayName: 'Qwen3 235B-A22B', + maxInputTokens: 131072, supportedFileTypes: [], pricing: { - inputPerM: 0.6, - outputPerM: 2.2, - cacheReadPerM: 0.11, - cacheWritePerM: 0, + inputPerM: 0.7, + outputPerM: 2.8, currency: 'USD', unit: 'per_million_tokens', }, - default: true, }, { - name: 'glm-4.7-flash', - displayName: 'GLM-4.7-Flash', - maxInputTokens: 200000, + name: 'qwen3-32b', + displayName: 'Qwen3 32B', + maxInputTokens: 131072, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, - cacheReadPerM: 0, - cacheWritePerM: 0, + inputPerM: 0.7, + outputPerM: 2.8, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'glm-5', - displayName: 'GLM-5', - maxInputTokens: 204800, + name: 'qwen3-8b', + displayName: 'Qwen3 8B', + maxInputTokens: 131072, supportedFileTypes: [], pricing: { - inputPerM: 1, - outputPerM: 3.2, - cacheReadPerM: 0.2, - cacheWritePerM: 0, + inputPerM: 0.18, + outputPerM: 0.7, currency: 'USD', unit: 'per_million_tokens', }, }, - ], - 'zai-coding-plan': [ { - name: 'glm-4.5', - displayName: 'GLM-4.5', - maxInputTokens: 131072, - supportedFileTypes: [], + name: 'qwen3-asr-flash', + displayName: 'Qwen3-ASR Flash', + maxInputTokens: 53248, + supportedFileTypes: ['audio'], pricing: { - inputPerM: 0, - outputPerM: 0, - cacheReadPerM: 0, - cacheWritePerM: 0, + inputPerM: 0.035, + outputPerM: 0.035, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'glm-4.5-air', - displayName: 'GLM-4.5-Air', - maxInputTokens: 131072, + name: 'qwen3-coder-30b-a3b-instruct', + displayName: 'Qwen3-Coder 30B-A3B Instruct', + maxInputTokens: 262144, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, - cacheReadPerM: 0, - cacheWritePerM: 0, + inputPerM: 0.45, + outputPerM: 2.25, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'glm-4.5-flash', - displayName: 'GLM-4.5-Flash', - maxInputTokens: 131072, + name: 'qwen3-coder-480b-a35b-instruct', + displayName: 'Qwen3-Coder 480B-A35B Instruct', + maxInputTokens: 262144, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, - cacheReadPerM: 0, - cacheWritePerM: 0, + inputPerM: 1.5, + outputPerM: 7.5, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'glm-4.5v', - displayName: 'GLM-4.5V', - maxInputTokens: 64000, - supportedFileTypes: ['image'], + name: 'qwen3-coder-flash', + displayName: 'Qwen3 Coder Flash', + maxInputTokens: 1000000, + supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.3, + outputPerM: 1.5, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'glm-4.6', - displayName: 'GLM-4.6', - maxInputTokens: 204800, + name: 'qwen3-coder-plus', + displayName: 'Qwen3 Coder Plus', + maxInputTokens: 1048576, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, - cacheReadPerM: 0, - cacheWritePerM: 0, + inputPerM: 1, + outputPerM: 5, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'glm-4.6v', - displayName: 'GLM-4.6V', - maxInputTokens: 128000, - supportedFileTypes: ['image'], + name: 'qwen3-livetranslate-flash-realtime', + displayName: 'Qwen3-LiveTranslate Flash Realtime', + maxInputTokens: 53248, + supportedFileTypes: ['image', 'audio'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 10, + outputPerM: 10, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'glm-4.7', - displayName: 'GLM-4.7', - maxInputTokens: 204800, + name: 'qwen3-max', + displayName: 'Qwen3 Max', + maxInputTokens: 262144, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, - cacheReadPerM: 0, - cacheWritePerM: 0, + inputPerM: 1.2, + outputPerM: 6, currency: 'USD', unit: 'per_million_tokens', }, - default: true, }, { - name: 'glm-4.7-flash', - displayName: 'GLM-4.7-Flash', - maxInputTokens: 200000, + name: 'qwen3-next-80b-a3b-instruct', + displayName: 'Qwen3-Next 80B-A3B Instruct', + maxInputTokens: 131072, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, - cacheReadPerM: 0, - cacheWritePerM: 0, + inputPerM: 0.5, + outputPerM: 2, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'glm-4.7-flashx', - displayName: 'GLM-4.7-FlashX', - maxInputTokens: 200000, + name: 'qwen3-next-80b-a3b-thinking', + displayName: 'Qwen3-Next 80B-A3B (Thinking)', + maxInputTokens: 131072, supportedFileTypes: [], pricing: { - inputPerM: 0.07, - outputPerM: 0.4, - cacheReadPerM: 0.01, - cacheWritePerM: 0, + inputPerM: 0.5, + outputPerM: 6, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'glm-5', - displayName: 'GLM-5', - maxInputTokens: 204800, - supportedFileTypes: [], + name: 'qwen3-omni-flash', + displayName: 'Qwen3-Omni Flash', + maxInputTokens: 65536, + supportedFileTypes: ['image', 'audio'], pricing: { - inputPerM: 0, - outputPerM: 0, - cacheReadPerM: 0, - cacheWritePerM: 0, + inputPerM: 0.43, + outputPerM: 1.66, currency: 'USD', unit: 'per_million_tokens', }, }, - ], - moonshotai: [ { - name: 'kimi-k2-0711-preview', - displayName: 'Kimi K2 0711', - maxInputTokens: 131072, - supportedFileTypes: [], + name: 'qwen3-omni-flash-realtime', + displayName: 'Qwen3-Omni Flash Realtime', + maxInputTokens: 65536, + supportedFileTypes: ['image', 'audio'], pricing: { - inputPerM: 0.6, - outputPerM: 2.5, - cacheReadPerM: 0.15, + inputPerM: 0.52, + outputPerM: 1.99, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'kimi-k2-0905-preview', - displayName: 'Kimi K2 0905', - maxInputTokens: 262144, - supportedFileTypes: [], + name: 'qwen3-vl-235b-a22b', + displayName: 'Qwen3-VL 235B-A22B', + maxInputTokens: 131072, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.6, - outputPerM: 2.5, - cacheReadPerM: 0.15, + inputPerM: 0.7, + outputPerM: 2.8, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'kimi-k2-thinking', - displayName: 'Kimi K2 Thinking', - maxInputTokens: 262144, - supportedFileTypes: [], + name: 'qwen3-vl-30b-a3b', + displayName: 'Qwen3-VL 30B-A3B', + maxInputTokens: 131072, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.6, - outputPerM: 2.5, - cacheReadPerM: 0.15, + inputPerM: 0.2, + outputPerM: 0.8, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'kimi-k2-thinking-turbo', - displayName: 'Kimi K2 Thinking Turbo', + name: 'qwen3-vl-plus', + displayName: 'Qwen3-VL Plus', maxInputTokens: 262144, - supportedFileTypes: [], + supportedFileTypes: ['image'], pricing: { - inputPerM: 1.15, - outputPerM: 8, - cacheReadPerM: 0.15, + inputPerM: 0.2, + outputPerM: 1.6, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'kimi-k2-turbo-preview', - displayName: 'Kimi K2 Turbo', + name: 'qwen3.5-397b-a17b', + displayName: 'Qwen3.5 397B-A17B', maxInputTokens: 262144, - supportedFileTypes: [], + supportedFileTypes: ['image'], pricing: { - inputPerM: 2.4, - outputPerM: 10, - cacheReadPerM: 0.6, + inputPerM: 0.6, + outputPerM: 3.6, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'kimi-k2.5', - displayName: 'Kimi K2.5', - maxInputTokens: 262144, + name: 'qwen3.5-plus', + displayName: 'Qwen3.5 Plus', + maxInputTokens: 1000000, supportedFileTypes: ['image'], pricing: { - inputPerM: 0.6, - outputPerM: 3, - cacheReadPerM: 0.1, + inputPerM: 0.4, + outputPerM: 2.4, currency: 'USD', unit: 'per_million_tokens', }, - default: true, }, - ], - 'moonshotai-cn': [ { - name: 'kimi-k2-0711-preview', - displayName: 'Kimi K2 0711', + name: 'qwq-plus', + displayName: 'QwQ Plus', maxInputTokens: 131072, supportedFileTypes: [], pricing: { - inputPerM: 0.6, - outputPerM: 2.5, - cacheReadPerM: 0.15, + inputPerM: 0.8, + outputPerM: 2.4, currency: 'USD', unit: 'per_million_tokens', }, }, + ], + 'alibaba-cn': [ { - name: 'kimi-k2-0905-preview', - displayName: 'Kimi K2 0905', - maxInputTokens: 262144, + name: 'deepseek-r1', + displayName: 'DeepSeek R1', + maxInputTokens: 131072, supportedFileTypes: [], pricing: { - inputPerM: 0.6, - outputPerM: 2.5, - cacheReadPerM: 0.15, + inputPerM: 0.574, + outputPerM: 2.294, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'kimi-k2-thinking', - displayName: 'Kimi K2 Thinking', - maxInputTokens: 262144, + name: 'deepseek-r1-0528', + displayName: 'DeepSeek R1 0528', + maxInputTokens: 131072, supportedFileTypes: [], pricing: { - inputPerM: 0.6, - outputPerM: 2.5, - cacheReadPerM: 0.15, + inputPerM: 0.574, + outputPerM: 2.294, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'kimi-k2-thinking-turbo', - displayName: 'Kimi K2 Thinking Turbo', - maxInputTokens: 262144, + name: 'deepseek-r1-distill-llama-70b', + displayName: 'DeepSeek R1 Distill Llama 70B', + maxInputTokens: 32768, supportedFileTypes: [], pricing: { - inputPerM: 1.15, - outputPerM: 8, - cacheReadPerM: 0.15, + inputPerM: 0.287, + outputPerM: 0.861, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'kimi-k2-turbo-preview', - displayName: 'Kimi K2 Turbo', - maxInputTokens: 262144, + name: 'deepseek-r1-distill-llama-8b', + displayName: 'DeepSeek R1 Distill Llama 8B', + maxInputTokens: 32768, supportedFileTypes: [], pricing: { - inputPerM: 2.4, - outputPerM: 10, - cacheReadPerM: 0.6, + inputPerM: 0, + outputPerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'kimi-k2.5', - displayName: 'Kimi K2.5', - maxInputTokens: 262144, - supportedFileTypes: ['image'], + name: 'deepseek-r1-distill-qwen-1-5b', + displayName: 'DeepSeek R1 Distill Qwen 1.5B', + maxInputTokens: 32768, + supportedFileTypes: [], pricing: { - inputPerM: 0.6, - outputPerM: 3, - cacheReadPerM: 0.1, + inputPerM: 0, + outputPerM: 0, currency: 'USD', unit: 'per_million_tokens', }, - default: true, }, - ], - 'kimi-for-coding': [ { - name: 'k2p5', - displayName: 'Kimi K2.5', - maxInputTokens: 262144, - supportedFileTypes: ['image'], + name: 'deepseek-r1-distill-qwen-14b', + displayName: 'DeepSeek R1 Distill Qwen 14B', + maxInputTokens: 32768, + supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, - cacheReadPerM: 0, - cacheWritePerM: 0, + inputPerM: 0.144, + outputPerM: 0.431, currency: 'USD', unit: 'per_million_tokens', }, - default: true, }, { - name: 'kimi-k2-thinking', - displayName: 'Kimi K2 Thinking', - maxInputTokens: 262144, + name: 'deepseek-r1-distill-qwen-32b', + displayName: 'DeepSeek R1 Distill Qwen 32B', + maxInputTokens: 32768, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, - cacheReadPerM: 0, - cacheWritePerM: 0, + inputPerM: 0.287, + outputPerM: 0.861, currency: 'USD', unit: 'per_million_tokens', }, }, - ], - openrouter: [ { - name: 'allenai/molmo-2-8b:free', - displayName: 'Molmo2 8B (free)', - maxInputTokens: 36864, - supportedFileTypes: ['image'], + name: 'deepseek-r1-distill-qwen-7b', + displayName: 'DeepSeek R1 Distill Qwen 7B', + maxInputTokens: 32768, + supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.072, + outputPerM: 0.144, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'anthropic/claude-3.5-haiku', - displayName: 'Claude Haiku 3.5', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'deepseek-v3', + displayName: 'DeepSeek V3', + maxInputTokens: 65536, + supportedFileTypes: [], pricing: { - inputPerM: 0.8, - outputPerM: 4, - cacheReadPerM: 0.08, - cacheWritePerM: 1, + inputPerM: 0.287, + outputPerM: 1.147, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'anthropic/claude-3.7-sonnet', - displayName: 'Claude Sonnet 3.7', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], - pricing: { - inputPerM: 15, - outputPerM: 75, - cacheReadPerM: 1.5, - cacheWritePerM: 18.75, + name: 'deepseek-v3-1', + displayName: 'DeepSeek V3.1', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.574, + outputPerM: 1.721, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'anthropic/claude-haiku-4.5', - displayName: 'Claude Haiku 4.5', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'deepseek-v3-2-exp', + displayName: 'DeepSeek V3.2 Exp', + maxInputTokens: 131072, + supportedFileTypes: [], pricing: { - inputPerM: 1, - outputPerM: 5, - cacheReadPerM: 0.1, - cacheWritePerM: 1.25, + inputPerM: 0.287, + outputPerM: 0.431, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'anthropic/claude-opus-4', - displayName: 'Claude Opus 4', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'kimi-k2-thinking', + displayName: 'Moonshot Kimi K2 Thinking', + maxInputTokens: 262144, + supportedFileTypes: [], pricing: { - inputPerM: 15, - outputPerM: 75, - cacheReadPerM: 1.5, - cacheWritePerM: 18.75, + inputPerM: 0.574, + outputPerM: 2.294, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'anthropic/claude-opus-4.1', - displayName: 'Claude Opus 4.1', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'kimi-k2.5', + displayName: 'Moonshot Kimi K2.5', + maxInputTokens: 262144, + supportedFileTypes: ['image'], pricing: { - inputPerM: 15, - outputPerM: 75, - cacheReadPerM: 1.5, - cacheWritePerM: 18.75, + inputPerM: 0.574, + outputPerM: 2.411, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'anthropic/claude-opus-4.5', - displayName: 'Claude Opus 4.5', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'moonshot-kimi-k2-instruct', + displayName: 'Moonshot Kimi K2 Instruct', + maxInputTokens: 131072, + supportedFileTypes: [], pricing: { - inputPerM: 5, - outputPerM: 25, - cacheReadPerM: 0.5, - cacheWritePerM: 6.25, + inputPerM: 0.574, + outputPerM: 2.294, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'anthropic/claude-opus-4.6', - displayName: 'Claude Opus 4.6', - maxInputTokens: 1000000, - supportedFileTypes: ['pdf', 'image'], + name: 'qvq-max', + displayName: 'QVQ Max', + maxInputTokens: 131072, + supportedFileTypes: ['image'], pricing: { - inputPerM: 5, - outputPerM: 25, - cacheReadPerM: 0.5, - cacheWritePerM: 6.25, + inputPerM: 1.147, + outputPerM: 4.588, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'anthropic/claude-sonnet-4', - displayName: 'Claude Sonnet 4', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'qwen-deep-research', + displayName: 'Qwen Deep Research', + maxInputTokens: 1000000, + supportedFileTypes: [], pricing: { - inputPerM: 3, - outputPerM: 15, - cacheReadPerM: 0.3, - cacheWritePerM: 3.75, + inputPerM: 7.742, + outputPerM: 23.367, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'anthropic/claude-sonnet-4.5', - displayName: 'Claude Sonnet 4.5', - maxInputTokens: 1000000, - supportedFileTypes: ['pdf', 'image'], + name: 'qwen-doc-turbo', + displayName: 'Qwen Doc Turbo', + maxInputTokens: 131072, + supportedFileTypes: [], pricing: { - inputPerM: 3, - outputPerM: 15, - cacheReadPerM: 0.3, - cacheWritePerM: 3.75, + inputPerM: 0.087, + outputPerM: 0.144, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'arcee-ai/trinity-large-preview:free', - displayName: 'Trinity Large Preview', - maxInputTokens: 131072, + name: 'qwen-flash', + displayName: 'Qwen Flash', + maxInputTokens: 1000000, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.022, + outputPerM: 0.216, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'arcee-ai/trinity-mini:free', - displayName: 'Trinity Mini', - maxInputTokens: 131072, + name: 'qwen-long', + displayName: 'Qwen Long', + maxInputTokens: 10000000, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.072, + outputPerM: 0.287, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'black-forest-labs/flux.2-flex', - displayName: 'FLUX.2 Flex', - maxInputTokens: 67344, - supportedFileTypes: ['image'], + name: 'qwen-math-plus', + displayName: 'Qwen Math Plus', + maxInputTokens: 4096, + supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.574, + outputPerM: 1.721, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'black-forest-labs/flux.2-klein-4b', - displayName: 'FLUX.2 Klein 4B', - maxInputTokens: 40960, - supportedFileTypes: ['image'], + name: 'qwen-math-turbo', + displayName: 'Qwen Math Turbo', + maxInputTokens: 4096, + supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.287, + outputPerM: 0.861, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'black-forest-labs/flux.2-max', - displayName: 'FLUX.2 Max', - maxInputTokens: 46864, - supportedFileTypes: ['image'], + name: 'qwen-max', + displayName: 'Qwen Max', + maxInputTokens: 131072, + supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.345, + outputPerM: 1.377, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'black-forest-labs/flux.2-pro', - displayName: 'FLUX.2 Pro', - maxInputTokens: 46864, - supportedFileTypes: ['image'], + name: 'qwen-mt-plus', + displayName: 'Qwen-MT Plus', + maxInputTokens: 16384, + supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.259, + outputPerM: 0.775, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'bytedance-seed/seedream-4.5', - displayName: 'Seedream 4.5', - maxInputTokens: 4096, - supportedFileTypes: ['image'], + name: 'qwen-mt-turbo', + displayName: 'Qwen-MT Turbo', + maxInputTokens: 16384, + supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.101, + outputPerM: 0.28, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'cognitivecomputations/dolphin-mistral-24b-venice-edition:free', - displayName: 'Uncensored (free)', + name: 'qwen-omni-turbo', + displayName: 'Qwen-Omni Turbo', maxInputTokens: 32768, - supportedFileTypes: [], + supportedFileTypes: ['image', 'audio'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.058, + outputPerM: 0.23, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'cognitivecomputations/dolphin3.0-mistral-24b', - displayName: 'Dolphin3.0 Mistral 24B', + name: 'qwen-omni-turbo-realtime', + displayName: 'Qwen-Omni Turbo Realtime', maxInputTokens: 32768, - supportedFileTypes: [], + supportedFileTypes: ['image', 'audio'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.23, + outputPerM: 0.918, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'cognitivecomputations/dolphin3.0-r1-mistral-24b', - displayName: 'Dolphin3.0 R1 Mistral 24B', - maxInputTokens: 32768, + name: 'qwen-plus', + displayName: 'Qwen Plus', + maxInputTokens: 1000000, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.115, + outputPerM: 0.287, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'deepseek/deepseek-chat-v3-0324', - displayName: 'DeepSeek V3 0324', - maxInputTokens: 16384, + name: 'qwen-plus-character', + displayName: 'Qwen Plus Character', + maxInputTokens: 32768, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.115, + outputPerM: 0.287, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'deepseek/deepseek-chat-v3.1', - displayName: 'DeepSeek-V3.1', - maxInputTokens: 163840, + name: 'qwen-turbo', + displayName: 'Qwen Turbo', + maxInputTokens: 1000000, supportedFileTypes: [], pricing: { - inputPerM: 0.2, - outputPerM: 0.8, + inputPerM: 0.044, + outputPerM: 0.087, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'deepseek/deepseek-r1-0528-qwen3-8b:free', - displayName: 'Deepseek R1 0528 Qwen3 8B (free)', + name: 'qwen-vl-max', + displayName: 'Qwen-VL Max', maxInputTokens: 131072, - supportedFileTypes: [], + supportedFileTypes: ['image'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.23, + outputPerM: 0.574, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'deepseek/deepseek-r1-0528:free', - displayName: 'R1 0528 (free)', - maxInputTokens: 163840, - supportedFileTypes: [], + name: 'qwen-vl-ocr', + displayName: 'Qwen-VL OCR', + maxInputTokens: 34096, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.717, + outputPerM: 0.717, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'deepseek/deepseek-r1-distill-llama-70b', - displayName: 'DeepSeek R1 Distill Llama 70B', - maxInputTokens: 8192, - supportedFileTypes: [], + name: 'qwen-vl-plus', + displayName: 'Qwen-VL Plus', + maxInputTokens: 131072, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.115, + outputPerM: 0.287, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'deepseek/deepseek-r1-distill-qwen-14b', - displayName: 'DeepSeek R1 Distill Qwen 14B', - maxInputTokens: 64000, + name: 'qwen2-5-14b-instruct', + displayName: 'Qwen2.5 14B Instruct', + maxInputTokens: 131072, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.144, + outputPerM: 0.431, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'deepseek/deepseek-r1:free', - displayName: 'R1 (free)', - maxInputTokens: 163840, + name: 'qwen2-5-32b-instruct', + displayName: 'Qwen2.5 32B Instruct', + maxInputTokens: 131072, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.287, + outputPerM: 0.861, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'deepseek/deepseek-v3-base:free', - displayName: 'DeepSeek V3 Base (free)', - maxInputTokens: 163840, + name: 'qwen2-5-72b-instruct', + displayName: 'Qwen2.5 72B Instruct', + maxInputTokens: 131072, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.574, + outputPerM: 1.721, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'deepseek/deepseek-v3.1-terminus', - displayName: 'DeepSeek V3.1 Terminus', + name: 'qwen2-5-7b-instruct', + displayName: 'Qwen2.5 7B Instruct', maxInputTokens: 131072, supportedFileTypes: [], pricing: { - inputPerM: 0.27, - outputPerM: 1, + inputPerM: 0.072, + outputPerM: 0.144, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'deepseek/deepseek-v3.1-terminus:exacto', - displayName: 'DeepSeek V3.1 Terminus (exacto)', + name: 'qwen2-5-coder-32b-instruct', + displayName: 'Qwen2.5-Coder 32B Instruct', maxInputTokens: 131072, supportedFileTypes: [], pricing: { - inputPerM: 0.27, - outputPerM: 1, + inputPerM: 0.287, + outputPerM: 0.861, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'deepseek/deepseek-v3.2', - displayName: 'DeepSeek V3.2', - maxInputTokens: 163840, + name: 'qwen2-5-coder-7b-instruct', + displayName: 'Qwen2.5-Coder 7B Instruct', + maxInputTokens: 131072, supportedFileTypes: [], pricing: { - inputPerM: 0.28, - outputPerM: 0.4, + inputPerM: 0.144, + outputPerM: 0.287, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'deepseek/deepseek-v3.2-speciale', - displayName: 'DeepSeek V3.2 Speciale', - maxInputTokens: 163840, + name: 'qwen2-5-math-72b-instruct', + displayName: 'Qwen2.5-Math 72B Instruct', + maxInputTokens: 4096, supportedFileTypes: [], pricing: { - inputPerM: 0.27, - outputPerM: 0.41, + inputPerM: 0.574, + outputPerM: 1.721, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'featherless/qwerky-72b', - displayName: 'Qwerky 72B', - maxInputTokens: 32768, + name: 'qwen2-5-math-7b-instruct', + displayName: 'Qwen2.5-Math 7B Instruct', + maxInputTokens: 4096, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.144, + outputPerM: 0.287, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'google/gemini-2.0-flash-001', - displayName: 'Gemini 2.0 Flash', - maxInputTokens: 1048576, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'qwen2-5-omni-7b', + displayName: 'Qwen2.5-Omni 7B', + maxInputTokens: 32768, + supportedFileTypes: ['image', 'audio'], pricing: { - inputPerM: 0.1, - outputPerM: 0.4, - cacheReadPerM: 0.025, + inputPerM: 0.087, + outputPerM: 0.345, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'google/gemini-2.0-flash-exp:free', - displayName: 'Gemini 2.0 Flash Experimental (free)', - maxInputTokens: 1048576, + name: 'qwen2-5-vl-72b-instruct', + displayName: 'Qwen2.5-VL 72B Instruct', + maxInputTokens: 131072, supportedFileTypes: ['image'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 2.294, + outputPerM: 6.881, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'google/gemini-2.5-flash', - displayName: 'Gemini 2.5 Flash', - maxInputTokens: 1048576, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'qwen2-5-vl-7b-instruct', + displayName: 'Qwen2.5-VL 7B Instruct', + maxInputTokens: 131072, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.3, - outputPerM: 2.5, - cacheReadPerM: 0.0375, + inputPerM: 0.287, + outputPerM: 0.717, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'google/gemini-2.5-flash-lite', - displayName: 'Gemini 2.5 Flash Lite', - maxInputTokens: 1048576, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'qwen3-14b', + displayName: 'Qwen3 14B', + maxInputTokens: 131072, + supportedFileTypes: [], pricing: { - inputPerM: 0.1, - outputPerM: 0.4, - cacheReadPerM: 0.025, + inputPerM: 0.144, + outputPerM: 0.574, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'google/gemini-2.5-flash-lite-preview-09-2025', - displayName: 'Gemini 2.5 Flash Lite Preview 09-25', - maxInputTokens: 1048576, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'qwen3-235b-a22b', + displayName: 'Qwen3 235B-A22B', + maxInputTokens: 131072, + supportedFileTypes: [], pricing: { - inputPerM: 0.1, - outputPerM: 0.4, - cacheReadPerM: 0.025, + inputPerM: 0.287, + outputPerM: 1.147, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'google/gemini-2.5-flash-preview-09-2025', - displayName: 'Gemini 2.5 Flash Preview 09-25', - maxInputTokens: 1048576, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'qwen3-32b', + displayName: 'Qwen3 32B', + maxInputTokens: 131072, + supportedFileTypes: [], pricing: { - inputPerM: 0.3, - outputPerM: 2.5, - cacheReadPerM: 0.031, + inputPerM: 0.287, + outputPerM: 1.147, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'google/gemini-2.5-pro', - displayName: 'Gemini 2.5 Pro', - maxInputTokens: 1048576, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'qwen3-8b', + displayName: 'Qwen3 8B', + maxInputTokens: 131072, + supportedFileTypes: [], pricing: { - inputPerM: 1.25, - outputPerM: 10, - cacheReadPerM: 0.31, + inputPerM: 0.072, + outputPerM: 0.287, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'google/gemini-2.5-pro-preview-05-06', - displayName: 'Gemini 2.5 Pro Preview 05-06', - maxInputTokens: 1048576, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'qwen3-asr-flash', + displayName: 'Qwen3-ASR Flash', + maxInputTokens: 53248, + supportedFileTypes: ['audio'], pricing: { - inputPerM: 1.25, - outputPerM: 10, - cacheReadPerM: 0.31, + inputPerM: 0.032, + outputPerM: 0.032, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'google/gemini-2.5-pro-preview-06-05', - displayName: 'Gemini 2.5 Pro Preview 06-05', - maxInputTokens: 1048576, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'qwen3-coder-30b-a3b-instruct', + displayName: 'Qwen3-Coder 30B-A3B Instruct', + maxInputTokens: 262144, + supportedFileTypes: [], pricing: { - inputPerM: 1.25, - outputPerM: 10, - cacheReadPerM: 0.31, + inputPerM: 0.216, + outputPerM: 0.861, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'google/gemini-3-flash-preview', - displayName: 'Gemini 3 Flash Preview', - maxInputTokens: 1048576, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'qwen3-coder-480b-a35b-instruct', + displayName: 'Qwen3-Coder 480B-A35B Instruct', + maxInputTokens: 262144, + supportedFileTypes: [], pricing: { - inputPerM: 0.5, - outputPerM: 3, - cacheReadPerM: 0.05, + inputPerM: 0.861, + outputPerM: 3.441, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'google/gemini-3-pro-preview', - displayName: 'Gemini 3 Pro Preview', - maxInputTokens: 1050000, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'qwen3-coder-flash', + displayName: 'Qwen3 Coder Flash', + maxInputTokens: 1000000, + supportedFileTypes: [], pricing: { - inputPerM: 2, - outputPerM: 12, + inputPerM: 0.144, + outputPerM: 0.574, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'google/gemma-2-9b-it', - displayName: 'Gemma 2 9B', - maxInputTokens: 8192, + name: 'qwen3-coder-plus', + displayName: 'Qwen3 Coder Plus', + maxInputTokens: 1048576, supportedFileTypes: [], pricing: { - inputPerM: 0.03, - outputPerM: 0.09, + inputPerM: 1, + outputPerM: 5, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'google/gemma-3-12b-it', - displayName: 'Gemma 3 12B', - maxInputTokens: 131072, - supportedFileTypes: ['image'], + name: 'qwen3-max', + displayName: 'Qwen3 Max', + maxInputTokens: 262144, + supportedFileTypes: [], pricing: { - inputPerM: 0.03, - outputPerM: 0.1, + inputPerM: 0.861, + outputPerM: 3.441, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'google/gemma-3-12b-it:free', - displayName: 'Gemma 3 12B (free)', - maxInputTokens: 32768, - supportedFileTypes: ['image'], + name: 'qwen3-next-80b-a3b-instruct', + displayName: 'Qwen3-Next 80B-A3B Instruct', + maxInputTokens: 131072, + supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.144, + outputPerM: 0.574, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'google/gemma-3-27b-it', - displayName: 'Gemma 3 27B', - maxInputTokens: 96000, - supportedFileTypes: ['image'], + name: 'qwen3-next-80b-a3b-thinking', + displayName: 'Qwen3-Next 80B-A3B (Thinking)', + maxInputTokens: 131072, + supportedFileTypes: [], pricing: { - inputPerM: 0.04, - outputPerM: 0.15, + inputPerM: 0.144, + outputPerM: 1.434, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'google/gemma-3-27b-it:free', - displayName: 'Gemma 3 27B (free)', - maxInputTokens: 131072, - supportedFileTypes: ['image'], + name: 'qwen3-omni-flash', + displayName: 'Qwen3-Omni Flash', + maxInputTokens: 65536, + supportedFileTypes: ['image', 'audio'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.058, + outputPerM: 0.23, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'google/gemma-3-4b-it', - displayName: 'Gemma 3 4B', - maxInputTokens: 96000, - supportedFileTypes: ['image'], + name: 'qwen3-omni-flash-realtime', + displayName: 'Qwen3-Omni Flash Realtime', + maxInputTokens: 65536, + supportedFileTypes: ['image', 'audio'], pricing: { - inputPerM: 0.01703, - outputPerM: 0.06815, + inputPerM: 0.23, + outputPerM: 0.918, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'google/gemma-3-4b-it:free', - displayName: 'Gemma 3 4B (free)', - maxInputTokens: 32768, + name: 'qwen3-vl-235b-a22b', + displayName: 'Qwen3-VL 235B-A22B', + maxInputTokens: 131072, supportedFileTypes: ['image'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.286705, + outputPerM: 1.14682, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'google/gemma-3n-e2b-it:free', - displayName: 'Gemma 3n 2B (free)', - maxInputTokens: 8192, - supportedFileTypes: [], + name: 'qwen3-vl-30b-a3b', + displayName: 'Qwen3-VL 30B-A3B', + maxInputTokens: 131072, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.108, + outputPerM: 0.431, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'google/gemma-3n-e4b-it', - displayName: 'Gemma 3n 4B', - maxInputTokens: 32768, - supportedFileTypes: [], + name: 'qwen3-vl-plus', + displayName: 'Qwen3-VL Plus', + maxInputTokens: 262144, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.02, - outputPerM: 0.04, + inputPerM: 0.143353, + outputPerM: 1.433525, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'google/gemma-3n-e4b-it:free', - displayName: 'Gemma 3n 4B (free)', - maxInputTokens: 8192, - supportedFileTypes: [], + name: 'qwen3.5-397b-a17b', + displayName: 'Qwen3.5 397B-A17B', + maxInputTokens: 262144, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.43, + outputPerM: 2.58, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'kwaipilot/kat-coder-pro:free', - displayName: 'Kat Coder Pro (free)', - maxInputTokens: 256000, - supportedFileTypes: [], + name: 'qwen3.5-plus', + displayName: 'Qwen3.5 Plus', + maxInputTokens: 1000000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.573, + outputPerM: 3.44, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'liquid/lfm-2.5-1.2b-instruct:free', - displayName: 'LFM2.5-1.2B-Instruct (free)', + name: 'qwq-32b', + displayName: 'QwQ 32B', maxInputTokens: 131072, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.287, + outputPerM: 0.861, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'liquid/lfm-2.5-1.2b-thinking:free', - displayName: 'LFM2.5-1.2B-Thinking (free)', + name: 'qwq-plus', + displayName: 'QwQ Plus', maxInputTokens: 131072, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.23, + outputPerM: 0.574, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'meta-llama/llama-3.1-405b-instruct:free', - displayName: 'Llama 3.1 405B Instruct (free)', - maxInputTokens: 131072, + name: 'tongyi-intent-detect-v3', + displayName: 'Tongyi Intent Detect V3', + maxInputTokens: 8192, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.058, + outputPerM: 0.144, currency: 'USD', unit: 'per_million_tokens', }, }, + ], + 'amazon-bedrock': [ { - name: 'meta-llama/llama-3.2-11b-vision-instruct', - displayName: 'Llama 3.2 11B Vision Instruct', - maxInputTokens: 131072, - supportedFileTypes: ['image'], + name: 'ai21.jamba-1-5-large-v1:0', + displayName: 'Jamba 1.5 Large', + maxInputTokens: 256000, + supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 2, + outputPerM: 8, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'meta-llama/llama-3.2-3b-instruct:free', - displayName: 'Llama 3.2 3B Instruct (free)', - maxInputTokens: 131072, - supportedFileTypes: ['image'], + name: 'ai21.jamba-1-5-mini-v1:0', + displayName: 'Jamba 1.5 Mini', + maxInputTokens: 256000, + supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.2, + outputPerM: 0.4, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'meta-llama/llama-3.3-70b-instruct:free', - displayName: 'Llama 3.3 70B Instruct (free)', - maxInputTokens: 131072, - supportedFileTypes: [], + name: 'amazon.nova-2-lite-v1:0', + displayName: 'Nova 2 Lite', + maxInputTokens: 128000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.33, + outputPerM: 2.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'meta-llama/llama-4-scout:free', - displayName: 'Llama 4 Scout (free)', - maxInputTokens: 64000, + name: 'amazon.nova-lite-v1:0', + displayName: 'Nova Lite', + maxInputTokens: 300000, supportedFileTypes: ['image'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.06, + outputPerM: 0.24, + cacheReadPerM: 0.015, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'microsoft/mai-ds-r1:free', - displayName: 'MAI DS R1 (free)', - maxInputTokens: 163840, + name: 'amazon.nova-micro-v1:0', + displayName: 'Nova Micro', + maxInputTokens: 128000, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.035, + outputPerM: 0.14, + cacheReadPerM: 0.00875, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'minimax/minimax-01', - displayName: 'MiniMax-01', + name: 'amazon.nova-premier-v1:0', + displayName: 'Nova Premier', maxInputTokens: 1000000, supportedFileTypes: ['image'], pricing: { - inputPerM: 0.2, - outputPerM: 1.1, + inputPerM: 2.5, + outputPerM: 12.5, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'minimax/minimax-m1', - displayName: 'MiniMax M1', - maxInputTokens: 1000000, - supportedFileTypes: [], + name: 'amazon.nova-pro-v1:0', + displayName: 'Nova Pro', + maxInputTokens: 300000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.4, - outputPerM: 2.2, + inputPerM: 0.8, + outputPerM: 3.2, + cacheReadPerM: 0.2, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'minimax/minimax-m2', - displayName: 'MiniMax M2', - maxInputTokens: 196600, - supportedFileTypes: [], + name: 'amazon.titan-text-express-v1', + displayName: 'Titan Text G1 - Express', + maxInputTokens: 128000, + supportedFileTypes: [], pricing: { - inputPerM: 0.28, - outputPerM: 1.15, - cacheReadPerM: 0.28, - cacheWritePerM: 1.15, + inputPerM: 0.2, + outputPerM: 0.6, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'minimax/minimax-m2.1', - displayName: 'MiniMax M2.1', - maxInputTokens: 204800, + name: 'amazon.titan-text-express-v1:0:8k', + displayName: 'Titan Text G1 - Express', + maxInputTokens: 128000, supportedFileTypes: [], pricing: { - inputPerM: 0.3, - outputPerM: 1.2, + inputPerM: 0.2, + outputPerM: 0.6, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'minimax/minimax-m2.5', - displayName: 'MiniMax M2.5', - maxInputTokens: 204800, - supportedFileTypes: [], + name: 'anthropic.claude-3-5-haiku-20241022-v1:0', + displayName: 'Claude Haiku 3.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0.3, - outputPerM: 1.2, - cacheReadPerM: 0.03, + inputPerM: 0.8, + outputPerM: 4, + cacheReadPerM: 0.08, + cacheWritePerM: 1, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'mistralai/codestral-2508', - displayName: 'Codestral 2508', - maxInputTokens: 256000, - supportedFileTypes: [], + name: 'anthropic.claude-3-5-sonnet-20240620-v1:0', + displayName: 'Claude Sonnet 3.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0.3, - outputPerM: 0.9, + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'mistralai/devstral-2512', - displayName: 'Devstral 2 2512', - maxInputTokens: 262144, - supportedFileTypes: [], + name: 'anthropic.claude-3-5-sonnet-20241022-v2:0', + displayName: 'Claude Sonnet 3.5 v2', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0.15, - outputPerM: 0.6, + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'mistralai/devstral-2512:free', - displayName: 'Devstral 2 2512 (free)', - maxInputTokens: 262144, - supportedFileTypes: [], + name: 'anthropic.claude-3-7-sonnet-20250219-v1:0', + displayName: 'Claude Sonnet 3.7', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'mistralai/devstral-medium-2507', - displayName: 'Devstral Medium', - maxInputTokens: 131072, - supportedFileTypes: [], + name: 'anthropic.claude-3-haiku-20240307-v1:0', + displayName: 'Claude Haiku 3', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0.4, - outputPerM: 2, + inputPerM: 0.25, + outputPerM: 1.25, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'mistralai/devstral-small-2505', - displayName: 'Devstral Small', - maxInputTokens: 128000, - supportedFileTypes: [], + name: 'anthropic.claude-3-opus-20240229-v1:0', + displayName: 'Claude Opus 3', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0.06, - outputPerM: 0.12, + inputPerM: 15, + outputPerM: 75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'mistralai/devstral-small-2505:free', - displayName: 'Devstral Small 2505 (free)', - maxInputTokens: 32768, - supportedFileTypes: [], + name: 'anthropic.claude-3-sonnet-20240229-v1:0', + displayName: 'Claude Sonnet 3', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 3, + outputPerM: 15, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'mistralai/devstral-small-2507', - displayName: 'Devstral Small 1.1', - maxInputTokens: 131072, - supportedFileTypes: [], + name: 'anthropic.claude-haiku-4-5-20251001-v1:0', + displayName: 'Claude Haiku 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0.1, - outputPerM: 0.3, + inputPerM: 1, + outputPerM: 5, + cacheReadPerM: 0.1, + cacheWritePerM: 1.25, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'mistralai/mistral-7b-instruct:free', - displayName: 'Mistral 7B Instruct (free)', - maxInputTokens: 32768, + name: 'anthropic.claude-instant-v1', + displayName: 'Claude Instant', + maxInputTokens: 100000, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.8, + outputPerM: 2.4, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'mistralai/mistral-medium-3', - displayName: 'Mistral Medium 3', - maxInputTokens: 131072, - supportedFileTypes: ['image'], + name: 'anthropic.claude-opus-4-1-20250805-v1:0', + displayName: 'Claude Opus 4.1', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0.4, - outputPerM: 2, + inputPerM: 15, + outputPerM: 75, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'mistralai/mistral-medium-3.1', - displayName: 'Mistral Medium 3.1', - maxInputTokens: 262144, - supportedFileTypes: ['image'], + name: 'anthropic.claude-opus-4-20250514-v1:0', + displayName: 'Claude Opus 4', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0.4, - outputPerM: 2, + inputPerM: 15, + outputPerM: 75, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'mistralai/mistral-nemo:free', - displayName: 'Mistral Nemo (free)', - maxInputTokens: 131072, - supportedFileTypes: [], + name: 'anthropic.claude-opus-4-5-20251101-v1:0', + displayName: 'Claude Opus 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'mistralai/mistral-small-3.1-24b-instruct', - displayName: 'Mistral Small 3.1 24B Instruct', - maxInputTokens: 128000, - supportedFileTypes: ['image'], + name: 'anthropic.claude-opus-4-6-v1', + displayName: 'Claude Opus 4.6', + maxInputTokens: 1000000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'mistralai/mistral-small-3.2-24b-instruct', - displayName: 'Mistral Small 3.2 24B Instruct', - maxInputTokens: 96000, - supportedFileTypes: ['image'], + name: 'anthropic.claude-sonnet-4-20250514-v1:0', + displayName: 'Claude Sonnet 4', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'mistralai/mistral-small-3.2-24b-instruct:free', - displayName: 'Mistral Small 3.2 24B (free)', - maxInputTokens: 96000, - supportedFileTypes: ['image'], + name: 'anthropic.claude-sonnet-4-5-20250929-v1:0', + displayName: 'Claude Sonnet 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'moonshotai/kimi-dev-72b:free', - displayName: 'Kimi Dev 72b (free)', - maxInputTokens: 131072, - supportedFileTypes: [], + name: 'anthropic.claude-sonnet-4-6', + displayName: 'Claude Sonnet 4.6', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'moonshotai/kimi-k2', - displayName: 'Kimi K2', - maxInputTokens: 131072, + name: 'anthropic.claude-v2', + displayName: 'Claude 2', + maxInputTokens: 100000, supportedFileTypes: [], pricing: { - inputPerM: 0.55, - outputPerM: 2.2, + inputPerM: 8, + outputPerM: 24, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'moonshotai/kimi-k2-0905', - displayName: 'Kimi K2 Instruct 0905', - maxInputTokens: 262144, + name: 'anthropic.claude-v2:1', + displayName: 'Claude 2.1', + maxInputTokens: 200000, supportedFileTypes: [], pricing: { - inputPerM: 0.6, - outputPerM: 2.5, + inputPerM: 8, + outputPerM: 24, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'moonshotai/kimi-k2-0905:exacto', - displayName: 'Kimi K2 Instruct 0905 (exacto)', - maxInputTokens: 262144, + name: 'cohere.command-light-text-v14', + displayName: 'Command Light', + maxInputTokens: 4096, supportedFileTypes: [], pricing: { - inputPerM: 0.6, - outputPerM: 2.5, + inputPerM: 0.3, + outputPerM: 0.6, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'moonshotai/kimi-k2-thinking', - displayName: 'Kimi K2 Thinking', - maxInputTokens: 262144, + name: 'cohere.command-r-plus-v1:0', + displayName: 'Command R+', + maxInputTokens: 128000, supportedFileTypes: [], pricing: { - inputPerM: 0.6, - outputPerM: 2.5, - cacheReadPerM: 0.15, + inputPerM: 3, + outputPerM: 15, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'moonshotai/kimi-k2:free', - displayName: 'Kimi K2 (free)', - maxInputTokens: 32800, + name: 'cohere.command-r-v1:0', + displayName: 'Command R', + maxInputTokens: 128000, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.5, + outputPerM: 1.5, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'moonshotai/kimi-k2.5', - displayName: 'Kimi K2.5', - maxInputTokens: 262144, - supportedFileTypes: ['image'], + name: 'cohere.command-text-v14', + displayName: 'Command', + maxInputTokens: 4096, + supportedFileTypes: [], pricing: { - inputPerM: 0.6, - outputPerM: 3, - cacheReadPerM: 0.1, + inputPerM: 1.5, + outputPerM: 2, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'nousresearch/deephermes-3-llama-3-8b-preview', - displayName: 'DeepHermes 3 Llama 3 8B Preview', - maxInputTokens: 131072, + name: 'deepseek.r1-v1:0', + displayName: 'DeepSeek-R1', + maxInputTokens: 128000, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 1.35, + outputPerM: 5.4, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'nousresearch/hermes-3-llama-3.1-405b:free', - displayName: 'Hermes 3 405B Instruct (free)', - maxInputTokens: 131072, + name: 'deepseek.v3-v1:0', + displayName: 'DeepSeek-V3.1', + maxInputTokens: 163840, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.58, + outputPerM: 1.68, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'nousresearch/hermes-4-405b', - displayName: 'Hermes 4 405B', - maxInputTokens: 131072, + name: 'deepseek.v3.2-v1:0', + displayName: 'DeepSeek-V3.2', + maxInputTokens: 163840, supportedFileTypes: [], pricing: { - inputPerM: 1, - outputPerM: 3, + inputPerM: 0.62, + outputPerM: 1.85, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'nousresearch/hermes-4-70b', - displayName: 'Hermes 4 70B', - maxInputTokens: 131072, - supportedFileTypes: [], + name: 'eu.anthropic.claude-haiku-4-5-20251001-v1:0', + displayName: 'Claude Haiku 4.5 (EU)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0.13, - outputPerM: 0.4, + inputPerM: 1, + outputPerM: 5, + cacheReadPerM: 0.1, + cacheWritePerM: 1.25, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'nvidia/nemotron-3-nano-30b-a3b:free', - displayName: 'Nemotron 3 Nano 30B A3B (free)', - maxInputTokens: 256000, - supportedFileTypes: [], + name: 'eu.anthropic.claude-opus-4-5-20251101-v1:0', + displayName: 'Claude Opus 4.5 (EU)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'nvidia/nemotron-nano-12b-v2-vl:free', - displayName: 'Nemotron Nano 12B 2 VL (free)', - maxInputTokens: 128000, - supportedFileTypes: ['image'], + name: 'eu.anthropic.claude-opus-4-6-v1', + displayName: 'Claude Opus 4.6 (EU)', + maxInputTokens: 1000000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'nvidia/nemotron-nano-9b-v2', - displayName: 'nvidia-nemotron-nano-9b-v2', - maxInputTokens: 131072, - supportedFileTypes: [], + name: 'eu.anthropic.claude-sonnet-4-20250514-v1:0', + displayName: 'Claude Sonnet 4 (EU)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0.04, - outputPerM: 0.16, + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'nvidia/nemotron-nano-9b-v2:free', - displayName: 'Nemotron Nano 9B V2 (free)', - maxInputTokens: 128000, - supportedFileTypes: [], + name: 'eu.anthropic.claude-sonnet-4-5-20250929-v1:0', + displayName: 'Claude Sonnet 4.5 (EU)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openai/gpt-4.1', - displayName: 'GPT-4.1', - maxInputTokens: 1047576, - supportedFileTypes: ['image'], + name: 'eu.anthropic.claude-sonnet-4-6', + displayName: 'Claude Sonnet 4.6 (EU)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 2, - outputPerM: 8, - cacheReadPerM: 0.5, + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openai/gpt-4.1-mini', - displayName: 'GPT-4.1 Mini', - maxInputTokens: 1047576, - supportedFileTypes: ['image'], + name: 'global.anthropic.claude-haiku-4-5-20251001-v1:0', + displayName: 'Claude Haiku 4.5 (Global)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0.4, - outputPerM: 1.6, + inputPerM: 1, + outputPerM: 5, cacheReadPerM: 0.1, + cacheWritePerM: 1.25, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openai/gpt-4o-mini', - displayName: 'GPT-4o-mini', - maxInputTokens: 128000, - supportedFileTypes: ['image'], + name: 'global.anthropic.claude-opus-4-5-20251101-v1:0', + displayName: 'Claude Opus 4.5 (Global)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0.15, - outputPerM: 0.6, - cacheReadPerM: 0.08, + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openai/gpt-5', - displayName: 'GPT-5', - maxInputTokens: 400000, - supportedFileTypes: ['image'], + name: 'global.anthropic.claude-opus-4-6-v1', + displayName: 'Claude Opus 4.6 (Global)', + maxInputTokens: 1000000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 1.25, - outputPerM: 10, + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openai/gpt-5-chat', - displayName: 'GPT-5 Chat (latest)', - maxInputTokens: 400000, - supportedFileTypes: ['image'], + name: 'global.anthropic.claude-sonnet-4-20250514-v1:0', + displayName: 'Claude Sonnet 4 (Global)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 1.25, - outputPerM: 10, + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openai/gpt-5-codex', - displayName: 'GPT-5 Codex', - maxInputTokens: 400000, - supportedFileTypes: ['image'], + name: 'global.anthropic.claude-sonnet-4-5-20250929-v1:0', + displayName: 'Claude Sonnet 4.5 (Global)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 1.25, - outputPerM: 10, - cacheReadPerM: 0.125, + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openai/gpt-5-image', - displayName: 'GPT-5 Image', - maxInputTokens: 400000, + name: 'global.anthropic.claude-sonnet-4-6', + displayName: 'Claude Sonnet 4.6 (Global)', + maxInputTokens: 200000, supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 5, - outputPerM: 10, - cacheReadPerM: 1.25, + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openai/gpt-5-mini', - displayName: 'GPT-5 Mini', - maxInputTokens: 400000, + name: 'google.gemma-3-12b-it', + displayName: 'Google Gemma 3 12B', + maxInputTokens: 131072, supportedFileTypes: ['image'], pricing: { - inputPerM: 0.25, - outputPerM: 2, + inputPerM: 0.049999999999999996, + outputPerM: 0.09999999999999999, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openai/gpt-5-nano', - displayName: 'GPT-5 Nano', - maxInputTokens: 400000, - supportedFileTypes: ['image'], + name: 'google.gemma-3-27b-it', + displayName: 'Google Gemma 3 27B Instruct', + maxInputTokens: 202752, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.05, - outputPerM: 0.4, + inputPerM: 0.12, + outputPerM: 0.2, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openai/gpt-5-pro', - displayName: 'GPT-5 Pro', - maxInputTokens: 400000, + name: 'google.gemma-3-4b-it', + displayName: 'Gemma 3 4B IT', + maxInputTokens: 128000, supportedFileTypes: ['image'], pricing: { - inputPerM: 15, - outputPerM: 120, + inputPerM: 0.04, + outputPerM: 0.08, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openai/gpt-5.1', - displayName: 'GPT-5.1', - maxInputTokens: 400000, - supportedFileTypes: ['image'], + name: 'meta.llama3-1-70b-instruct-v1:0', + displayName: 'Llama 3.1 70B Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], pricing: { - inputPerM: 1.25, - outputPerM: 10, - cacheReadPerM: 0.125, + inputPerM: 0.72, + outputPerM: 0.72, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openai/gpt-5.1-chat', - displayName: 'GPT-5.1 Chat', + name: 'meta.llama3-1-8b-instruct-v1:0', + displayName: 'Llama 3.1 8B Instruct', maxInputTokens: 128000, - supportedFileTypes: ['image'], + supportedFileTypes: [], pricing: { - inputPerM: 1.25, - outputPerM: 10, - cacheReadPerM: 0.125, + inputPerM: 0.22, + outputPerM: 0.22, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openai/gpt-5.1-codex', - displayName: 'GPT-5.1-Codex', - maxInputTokens: 400000, + name: 'meta.llama3-2-11b-instruct-v1:0', + displayName: 'Llama 3.2 11B Instruct', + maxInputTokens: 128000, supportedFileTypes: ['image'], pricing: { - inputPerM: 1.25, - outputPerM: 10, - cacheReadPerM: 0.125, + inputPerM: 0.16, + outputPerM: 0.16, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openai/gpt-5.1-codex-max', - displayName: 'GPT-5.1-Codex-Max', - maxInputTokens: 400000, - supportedFileTypes: ['image'], + name: 'meta.llama3-2-1b-instruct-v1:0', + displayName: 'Llama 3.2 1B Instruct', + maxInputTokens: 131000, + supportedFileTypes: [], pricing: { - inputPerM: 1.1, - outputPerM: 9, - cacheReadPerM: 0.11, + inputPerM: 0.1, + outputPerM: 0.1, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openai/gpt-5.1-codex-mini', - displayName: 'GPT-5.1-Codex-Mini', - maxInputTokens: 400000, - supportedFileTypes: ['image'], + name: 'meta.llama3-2-3b-instruct-v1:0', + displayName: 'Llama 3.2 3B Instruct', + maxInputTokens: 131000, + supportedFileTypes: [], pricing: { - inputPerM: 0.25, - outputPerM: 2, - cacheReadPerM: 0.025, + inputPerM: 0.15, + outputPerM: 0.15, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openai/gpt-5.2', - displayName: 'GPT-5.2', - maxInputTokens: 400000, + name: 'meta.llama3-2-90b-instruct-v1:0', + displayName: 'Llama 3.2 90B Instruct', + maxInputTokens: 128000, supportedFileTypes: ['image'], pricing: { - inputPerM: 1.75, - outputPerM: 14, - cacheReadPerM: 0.175, + inputPerM: 0.72, + outputPerM: 0.72, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openai/gpt-5.2-chat', - displayName: 'GPT-5.2 Chat', + name: 'meta.llama3-3-70b-instruct-v1:0', + displayName: 'Llama 3.3 70B Instruct', maxInputTokens: 128000, - supportedFileTypes: ['image'], + supportedFileTypes: [], pricing: { - inputPerM: 1.75, - outputPerM: 14, - cacheReadPerM: 0.175, + inputPerM: 0.72, + outputPerM: 0.72, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openai/gpt-5.2-codex', - displayName: 'GPT-5.2-Codex', - maxInputTokens: 400000, - supportedFileTypes: ['image'], + name: 'meta.llama3-70b-instruct-v1:0', + displayName: 'Llama 3 70B Instruct', + maxInputTokens: 8192, + supportedFileTypes: [], pricing: { - inputPerM: 1.75, - outputPerM: 14, - cacheReadPerM: 0.175, + inputPerM: 2.65, + outputPerM: 3.5, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openai/gpt-5.2-pro', - displayName: 'GPT-5.2 Pro', - maxInputTokens: 400000, + name: 'meta.llama3-8b-instruct-v1:0', + displayName: 'Llama 3 8B Instruct', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta.llama4-maverick-17b-instruct-v1:0', + displayName: 'Llama 4 Maverick 17B Instruct', + maxInputTokens: 1000000, supportedFileTypes: ['image'], pricing: { - inputPerM: 21, - outputPerM: 168, + inputPerM: 0.24, + outputPerM: 0.97, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openai/gpt-oss-120b', - displayName: 'GPT OSS 120B', - maxInputTokens: 131072, - supportedFileTypes: [], + name: 'meta.llama4-scout-17b-instruct-v1:0', + displayName: 'Llama 4 Scout 17B Instruct', + maxInputTokens: 3500000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.072, - outputPerM: 0.28, + inputPerM: 0.17, + outputPerM: 0.66, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openai/gpt-oss-120b:exacto', - displayName: 'GPT OSS 120B (exacto)', - maxInputTokens: 131072, + name: 'minimax.minimax-m2', + displayName: 'MiniMax M2', + maxInputTokens: 204608, supportedFileTypes: [], pricing: { - inputPerM: 0.05, - outputPerM: 0.24, + inputPerM: 0.3, + outputPerM: 1.2, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openai/gpt-oss-120b:free', - displayName: 'gpt-oss-120b (free)', - maxInputTokens: 131072, + name: 'minimax.minimax-m2.1', + displayName: 'MiniMax M2.1', + maxInputTokens: 204800, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.3, + outputPerM: 1.2, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openai/gpt-oss-20b', - displayName: 'GPT OSS 20B', - maxInputTokens: 131072, + name: 'mistral.ministral-3-14b-instruct', + displayName: 'Ministral 14B 3.0', + maxInputTokens: 128000, supportedFileTypes: [], pricing: { - inputPerM: 0.05, + inputPerM: 0.2, outputPerM: 0.2, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openai/gpt-oss-20b:free', - displayName: 'gpt-oss-20b (free)', - maxInputTokens: 131072, + name: 'mistral.ministral-3-8b-instruct', + displayName: 'Ministral 3 8B', + maxInputTokens: 128000, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.15, + outputPerM: 0.15, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openai/gpt-oss-safeguard-20b', - displayName: 'GPT OSS Safeguard 20B', - maxInputTokens: 131072, + name: 'mistral.mistral-7b-instruct-v0:2', + displayName: 'Mistral-7B-Instruct-v0.3', + maxInputTokens: 127000, supportedFileTypes: [], pricing: { - inputPerM: 0.075, - outputPerM: 0.3, + inputPerM: 0.11, + outputPerM: 0.11, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openai/o4-mini', - displayName: 'o4 Mini', - maxInputTokens: 200000, - supportedFileTypes: ['image'], + name: 'mistral.mistral-large-2402-v1:0', + displayName: 'Mistral Large (24.02)', + maxInputTokens: 128000, + supportedFileTypes: [], pricing: { - inputPerM: 1.1, - outputPerM: 4.4, - cacheReadPerM: 0.28, + inputPerM: 0.5, + outputPerM: 1.5, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openrouter/aurora-alpha', - displayName: 'Aurora Alpha', - maxInputTokens: 128000, + name: 'mistral.mixtral-8x7b-instruct-v0:1', + displayName: 'Mixtral-8x7B-Instruct-v0.1', + maxInputTokens: 32000, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.7, + outputPerM: 0.7, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openrouter/sherlock-dash-alpha', - displayName: 'Sherlock Dash Alpha', - maxInputTokens: 1840000, - supportedFileTypes: ['image'], + name: 'mistral.voxtral-mini-3b-2507', + displayName: 'Voxtral Mini 3B 2507', + maxInputTokens: 128000, + supportedFileTypes: ['audio'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.04, + outputPerM: 0.04, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openrouter/sherlock-think-alpha', - displayName: 'Sherlock Think Alpha', - maxInputTokens: 1840000, - supportedFileTypes: ['image'], + name: 'mistral.voxtral-small-24b-2507', + displayName: 'Voxtral Small 24B 2507', + maxInputTokens: 32000, + supportedFileTypes: ['audio'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.15, + outputPerM: 0.35, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'prime-intellect/intellect-3', - displayName: 'Intellect 3', - maxInputTokens: 131072, + name: 'moonshot.kimi-k2-thinking', + displayName: 'Kimi K2 Thinking', + maxInputTokens: 256000, supportedFileTypes: [], pricing: { - inputPerM: 0.2, - outputPerM: 1.1, + inputPerM: 0.6, + outputPerM: 2.5, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'qwen/qwen-2.5-coder-32b-instruct', - displayName: 'Qwen2.5 Coder 32B Instruct', - maxInputTokens: 32768, - supportedFileTypes: [], + name: 'moonshotai.kimi-k2.5', + displayName: 'Kimi K2.5', + maxInputTokens: 256000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.6, + outputPerM: 3, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'qwen/qwen-2.5-vl-7b-instruct:free', - displayName: 'Qwen2.5-VL 7B Instruct (free)', - maxInputTokens: 32768, + name: 'nvidia.nemotron-nano-12b-v2', + displayName: 'NVIDIA Nemotron Nano 12B v2 VL BF16', + maxInputTokens: 128000, supportedFileTypes: ['image'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.2, + outputPerM: 0.6, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'qwen/qwen2.5-vl-32b-instruct:free', - displayName: 'Qwen2.5 VL 32B Instruct (free)', - maxInputTokens: 8192, - supportedFileTypes: ['image'], + name: 'nvidia.nemotron-nano-9b-v2', + displayName: 'NVIDIA Nemotron Nano 9B v2', + maxInputTokens: 128000, + supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.06, + outputPerM: 0.23, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'qwen/qwen2.5-vl-72b-instruct', - displayName: 'Qwen2.5 VL 72B Instruct', - maxInputTokens: 32768, - supportedFileTypes: ['image'], + name: 'openai.gpt-oss-120b-1:0', + displayName: 'gpt-oss-120b', + maxInputTokens: 128000, + supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.15, + outputPerM: 0.6, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'qwen/qwen2.5-vl-72b-instruct:free', - displayName: 'Qwen2.5 VL 72B Instruct (free)', - maxInputTokens: 32768, - supportedFileTypes: ['image'], + name: 'openai.gpt-oss-20b-1:0', + displayName: 'gpt-oss-20b', + maxInputTokens: 128000, + supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.07, + outputPerM: 0.3, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'qwen/qwen3-14b:free', - displayName: 'Qwen3 14B (free)', - maxInputTokens: 40960, + name: 'openai.gpt-oss-safeguard-120b', + displayName: 'GPT OSS Safeguard 120B', + maxInputTokens: 128000, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.15, + outputPerM: 0.6, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'qwen/qwen3-235b-a22b-07-25', - displayName: 'Qwen3 235B A22B Instruct 2507', - maxInputTokens: 262144, + name: 'openai.gpt-oss-safeguard-20b', + displayName: 'GPT OSS Safeguard 20B', + maxInputTokens: 128000, supportedFileTypes: [], pricing: { - inputPerM: 0.15, - outputPerM: 0.85, + inputPerM: 0.07, + outputPerM: 0.2, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'qwen/qwen3-235b-a22b-07-25:free', - displayName: 'Qwen3 235B A22B Instruct 2507 (free)', + name: 'qwen.qwen3-235b-a22b-2507-v1:0', + displayName: 'Qwen3 235B A22B 2507', maxInputTokens: 262144, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.22, + outputPerM: 0.88, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'qwen/qwen3-235b-a22b-thinking-2507', - displayName: 'Qwen3 235B A22B Thinking 2507', - maxInputTokens: 262144, + name: 'qwen.qwen3-32b-v1:0', + displayName: 'Qwen3 32B (dense)', + maxInputTokens: 16384, supportedFileTypes: [], pricing: { - inputPerM: 0.078, - outputPerM: 0.312, + inputPerM: 0.15, + outputPerM: 0.6, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'qwen/qwen3-235b-a22b:free', - displayName: 'Qwen3 235B A22B (free)', - maxInputTokens: 131072, + name: 'qwen.qwen3-coder-30b-a3b-v1:0', + displayName: 'Qwen3 Coder 30B A3B Instruct', + maxInputTokens: 262144, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.15, + outputPerM: 0.6, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'qwen/qwen3-30b-a3b-instruct-2507', - displayName: 'Qwen3 30B A3B Instruct 2507', - maxInputTokens: 262000, + name: 'qwen.qwen3-coder-480b-a35b-v1:0', + displayName: 'Qwen3 Coder 480B A35B Instruct', + maxInputTokens: 131072, supportedFileTypes: [], pricing: { - inputPerM: 0.2, - outputPerM: 0.8, + inputPerM: 0.22, + outputPerM: 1.8, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'qwen/qwen3-30b-a3b-thinking-2507', - displayName: 'Qwen3 30B A3B Thinking 2507', + name: 'qwen.qwen3-next-80b-a3b', + displayName: 'Qwen/Qwen3-Next-80B-A3B-Instruct', maxInputTokens: 262000, supportedFileTypes: [], pricing: { - inputPerM: 0.2, - outputPerM: 0.8, + inputPerM: 0.14, + outputPerM: 1.4, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'qwen/qwen3-30b-a3b:free', - displayName: 'Qwen3 30B A3B (free)', - maxInputTokens: 40960, - supportedFileTypes: [], + name: 'qwen.qwen3-vl-235b-a22b', + displayName: 'Qwen/Qwen3-VL-235B-A22B-Instruct', + maxInputTokens: 262000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.3, + outputPerM: 1.5, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'qwen/qwen3-32b:free', - displayName: 'Qwen3 32B (free)', - maxInputTokens: 40960, - supportedFileTypes: [], + name: 'us.anthropic.claude-haiku-4-5-20251001-v1:0', + displayName: 'Claude Haiku 4.5 (US)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 1, + outputPerM: 5, + cacheReadPerM: 0.1, + cacheWritePerM: 1.25, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'qwen/qwen3-4b:free', - displayName: 'Qwen3 4B (free)', - maxInputTokens: 40960, - supportedFileTypes: [], + name: 'us.anthropic.claude-opus-4-1-20250805-v1:0', + displayName: 'Claude Opus 4.1 (US)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 15, + outputPerM: 75, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'qwen/qwen3-8b:free', - displayName: 'Qwen3 8B (free)', - maxInputTokens: 40960, - supportedFileTypes: [], + name: 'us.anthropic.claude-opus-4-20250514-v1:0', + displayName: 'Claude Opus 4 (US)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 15, + outputPerM: 75, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'qwen/qwen3-coder', - displayName: 'Qwen3 Coder', - maxInputTokens: 262144, - supportedFileTypes: [], + name: 'us.anthropic.claude-opus-4-5-20251101-v1:0', + displayName: 'Claude Opus 4.5 (US)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0.3, - outputPerM: 1.2, + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'qwen/qwen3-coder-30b-a3b-instruct', - displayName: 'Qwen3 Coder 30B A3B Instruct', - maxInputTokens: 160000, - supportedFileTypes: [], + name: 'us.anthropic.claude-opus-4-6-v1', + displayName: 'Claude Opus 4.6 (US)', + maxInputTokens: 1000000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0.07, - outputPerM: 0.27, + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'qwen/qwen3-coder-flash', - displayName: 'Qwen3 Coder Flash', - maxInputTokens: 128000, - supportedFileTypes: [], + name: 'us.anthropic.claude-sonnet-4-20250514-v1:0', + displayName: 'Claude Sonnet 4 (US)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0.3, - outputPerM: 1.5, + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'qwen/qwen3-coder:exacto', - displayName: 'Qwen3 Coder (exacto)', - maxInputTokens: 131072, - supportedFileTypes: [], + name: 'us.anthropic.claude-sonnet-4-5-20250929-v1:0', + displayName: 'Claude Sonnet 4.5 (US)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0.38, - outputPerM: 1.53, + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'qwen/qwen3-coder:free', - displayName: 'Qwen3 Coder 480B A35B Instruct (free)', - maxInputTokens: 262144, - supportedFileTypes: [], + name: 'us.anthropic.claude-sonnet-4-6', + displayName: 'Claude Sonnet 4.6 (US)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'qwen/qwen3-max', - displayName: 'Qwen3 Max', - maxInputTokens: 262144, + name: 'writer.palmyra-x4-v1:0', + displayName: 'Palmyra X4', + maxInputTokens: 122880, supportedFileTypes: [], pricing: { - inputPerM: 1.2, - outputPerM: 6, + inputPerM: 2.5, + outputPerM: 10, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'qwen/qwen3-next-80b-a3b-instruct', + name: 'writer.palmyra-x5-v1:0', + displayName: 'Palmyra X5', + maxInputTokens: 1040000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai.glm-4.7', + displayName: 'GLM-4.7', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai.glm-4.7-flash', + displayName: 'GLM-4.7-Flash', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.07, + outputPerM: 0.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + anthropic: [ + { + name: 'claude-3-5-haiku-20241022', + displayName: 'Claude Haiku 3.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0.8, + outputPerM: 4, + cacheReadPerM: 0.08, + cacheWritePerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-3-5-haiku-latest', + displayName: 'Claude Haiku 3.5 (latest)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0.8, + outputPerM: 4, + cacheReadPerM: 0.08, + cacheWritePerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-3-5-sonnet-20240620', + displayName: 'Claude Sonnet 3.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-3-5-sonnet-20241022', + displayName: 'Claude Sonnet 3.5 v2', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-3-7-sonnet-20250219', + displayName: 'Claude Sonnet 3.7', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-3-7-sonnet-latest', + displayName: 'Claude Sonnet 3.7 (latest)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-3-haiku-20240307', + displayName: 'Claude Haiku 3', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0.25, + outputPerM: 1.25, + cacheReadPerM: 0.03, + cacheWritePerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-3-opus-20240229', + displayName: 'Claude Opus 3', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 15, + outputPerM: 75, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-3-sonnet-20240229', + displayName: 'Claude Sonnet 3', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-haiku-4-5', + displayName: 'Claude Haiku 4.5 (latest)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1, + outputPerM: 5, + cacheReadPerM: 0.1, + cacheWritePerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-haiku-4-5-20251001', + displayName: 'Claude Haiku 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1, + outputPerM: 5, + cacheReadPerM: 0.1, + cacheWritePerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + default: true, + }, + { + name: 'claude-opus-4-0', + displayName: 'Claude Opus 4 (latest)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 15, + outputPerM: 75, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-opus-4-1', + displayName: 'Claude Opus 4.1 (latest)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 15, + outputPerM: 75, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-opus-4-1-20250805', + displayName: 'Claude Opus 4.1', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 15, + outputPerM: 75, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-opus-4-20250514', + displayName: 'Claude Opus 4', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 15, + outputPerM: 75, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-opus-4-5', + displayName: 'Claude Opus 4.5 (latest)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-opus-4-5-20251101', + displayName: 'Claude Opus 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-opus-4-6', + displayName: 'Claude Opus 4.6', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-sonnet-4-0', + displayName: 'Claude Sonnet 4 (latest)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-sonnet-4-20250514', + displayName: 'Claude Sonnet 4', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-sonnet-4-5', + displayName: 'Claude Sonnet 4.5 (latest)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-sonnet-4-5-20250929', + displayName: 'Claude Sonnet 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-sonnet-4-6', + displayName: 'Claude Sonnet 4.6', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + azure: [ + { + name: 'claude-haiku-4-5', + displayName: 'Claude Haiku 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1, + outputPerM: 5, + cacheReadPerM: 0.1, + cacheWritePerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-opus-4-1', + displayName: 'Claude Opus 4.1', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 15, + outputPerM: 75, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-opus-4-5', + displayName: 'Claude Opus 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-opus-4-6', + displayName: 'Claude Opus 4.6', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-sonnet-4-5', + displayName: 'Claude Sonnet 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'codestral-2501', + displayName: 'Codestral 25.01', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 0.9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'codex-mini', + displayName: 'Codex Mini', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 1.5, + outputPerM: 6, + cacheReadPerM: 0.375, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'cohere-command-a', + displayName: 'Command A', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 2.5, + outputPerM: 10, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'cohere-command-r-08-2024', + displayName: 'Command R', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'cohere-command-r-plus-08-2024', + displayName: 'Command R+', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 2.5, + outputPerM: 10, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'cohere-embed-v-4-0', + displayName: 'Embed v4', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.12, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'cohere-embed-v3-english', + displayName: 'Embed v3 English', + maxInputTokens: 512, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'cohere-embed-v3-multilingual', + displayName: 'Embed v3 Multilingual', + maxInputTokens: 512, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-r1', + displayName: 'DeepSeek-R1', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 1.35, + outputPerM: 5.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-r1-0528', + displayName: 'DeepSeek-R1-0528', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 1.35, + outputPerM: 5.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-v3-0324', + displayName: 'DeepSeek-V3-0324', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 1.14, + outputPerM: 4.56, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-v3.1', + displayName: 'DeepSeek-V3.1', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.56, + outputPerM: 1.68, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-v3.2', + displayName: 'DeepSeek-V3.2', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.58, + outputPerM: 1.68, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-v3.2-speciale', + displayName: 'DeepSeek-V3.2-Speciale', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.58, + outputPerM: 1.68, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-3.5-turbo-0125', + displayName: 'GPT-3.5 Turbo 0125', + maxInputTokens: 16384, + supportedFileTypes: [], + pricing: { + inputPerM: 0.5, + outputPerM: 1.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-3.5-turbo-0301', + displayName: 'GPT-3.5 Turbo 0301', + maxInputTokens: 4096, + supportedFileTypes: [], + pricing: { + inputPerM: 1.5, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-3.5-turbo-0613', + displayName: 'GPT-3.5 Turbo 0613', + maxInputTokens: 16384, + supportedFileTypes: [], + pricing: { + inputPerM: 3, + outputPerM: 4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-3.5-turbo-1106', + displayName: 'GPT-3.5 Turbo 1106', + maxInputTokens: 16384, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-3.5-turbo-instruct', + displayName: 'GPT-3.5 Turbo Instruct', + maxInputTokens: 4096, + supportedFileTypes: [], + pricing: { + inputPerM: 1.5, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4', + displayName: 'GPT-4', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 60, + outputPerM: 120, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4-32k', + displayName: 'GPT-4 32K', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 60, + outputPerM: 120, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4-turbo', + displayName: 'GPT-4 Turbo', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 10, + outputPerM: 30, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4-turbo-vision', + displayName: 'GPT-4 Turbo Vision', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 10, + outputPerM: 30, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4.1', + displayName: 'GPT-4.1', + maxInputTokens: 1047576, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2, + outputPerM: 8, + cacheReadPerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4.1-mini', + displayName: 'GPT-4.1 mini', + maxInputTokens: 1047576, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.4, + outputPerM: 1.6, + cacheReadPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4.1-nano', + displayName: 'GPT-4.1 nano', + maxInputTokens: 1047576, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.4, + cacheReadPerM: 0.03, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4o', + displayName: 'GPT-4o', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2.5, + outputPerM: 10, + cacheReadPerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4o-mini', + displayName: 'GPT-4o mini', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + cacheReadPerM: 0.08, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5', + displayName: 'GPT-5', + maxInputTokens: 272000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.13, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5-chat', + displayName: 'GPT-5 Chat', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.13, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5-codex', + displayName: 'GPT-5-Codex', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.13, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5-mini', + displayName: 'GPT-5 Mini', + maxInputTokens: 272000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.25, + outputPerM: 2, + cacheReadPerM: 0.03, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5-nano', + displayName: 'GPT-5 Nano', + maxInputTokens: 272000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.05, + outputPerM: 0.4, + cacheReadPerM: 0.01, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5-pro', + displayName: 'GPT-5 Pro', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 15, + outputPerM: 120, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.1', + displayName: 'GPT-5.1', + maxInputTokens: 272000, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.1-chat', + displayName: 'GPT-5.1 Chat', + maxInputTokens: 128000, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.1-codex', + displayName: 'GPT-5.1 Codex', + maxInputTokens: 400000, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.1-codex-max', + displayName: 'GPT-5.1 Codex Max', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.1-codex-mini', + displayName: 'GPT-5.1 Codex Mini', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.25, + outputPerM: 2, + cacheReadPerM: 0.025, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.2', + displayName: 'GPT-5.2', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.75, + outputPerM: 14, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.2-chat', + displayName: 'GPT-5.2 Chat', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.75, + outputPerM: 14, + cacheReadPerM: 0.175, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.2-codex', + displayName: 'GPT-5.2 Codex', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.75, + outputPerM: 14, + cacheReadPerM: 0.175, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'grok-3', + displayName: 'Grok 3', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'grok-3-mini', + displayName: 'Grok 3 Mini', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 0.5, + cacheReadPerM: 0.075, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'grok-4', + displayName: 'Grok 4', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'grok-4-fast-non-reasoning', + displayName: 'Grok 4 Fast (Non-Reasoning)', + maxInputTokens: 2000000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.2, + outputPerM: 0.5, + cacheReadPerM: 0.05, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'grok-4-fast-reasoning', + displayName: 'Grok 4 Fast (Reasoning)', + maxInputTokens: 2000000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.2, + outputPerM: 0.5, + cacheReadPerM: 0.05, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'grok-code-fast-1', + displayName: 'Grok Code Fast 1', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 1.5, + cacheReadPerM: 0.02, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2-thinking', + displayName: 'Kimi K2 Thinking', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.5, + cacheReadPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2.5', + displayName: 'Kimi K2.5', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.6, + outputPerM: 3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'llama-3.2-11b-vision-instruct', + displayName: 'Llama-3.2-11B-Vision-Instruct', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.37, + outputPerM: 0.37, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'llama-3.2-90b-vision-instruct', + displayName: 'Llama-3.2-90B-Vision-Instruct', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2.04, + outputPerM: 2.04, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'llama-3.3-70b-instruct', + displayName: 'Llama-3.3-70B-Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.71, + outputPerM: 0.71, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'llama-4-maverick-17b-128e-instruct-fp8', + displayName: 'Llama 4 Maverick 17B 128E Instruct FP8', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.25, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'llama-4-scout-17b-16e-instruct', + displayName: 'Llama 4 Scout 17B 16E Instruct', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.2, + outputPerM: 0.78, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mai-ds-r1', + displayName: 'MAI-DS-R1', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 1.35, + outputPerM: 5.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama-3-70b-instruct', + displayName: 'Meta-Llama-3-70B-Instruct', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 2.68, + outputPerM: 3.54, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama-3-8b-instruct', + displayName: 'Meta-Llama-3-8B-Instruct', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 0.61, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama-3.1-405b-instruct', + displayName: 'Meta-Llama-3.1-405B-Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 5.33, + outputPerM: 16, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama-3.1-70b-instruct', + displayName: 'Meta-Llama-3.1-70B-Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 2.68, + outputPerM: 3.54, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama-3.1-8b-instruct', + displayName: 'Meta-Llama-3.1-8B-Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 0.61, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'ministral-3b', + displayName: 'Ministral 3B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.04, + outputPerM: 0.04, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral-large-2411', + displayName: 'Mistral Large 24.11', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 2, + outputPerM: 6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral-medium-2505', + displayName: 'Mistral Medium 3', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.4, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral-nemo', + displayName: 'Mistral Nemo', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral-small-2503', + displayName: 'Mistral Small 3.1', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'model-router', + displayName: 'Model Router', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.14, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'o1', + displayName: 'o1', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 15, + outputPerM: 60, + cacheReadPerM: 7.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'o1-mini', + displayName: 'o1-mini', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 1.1, + outputPerM: 4.4, + cacheReadPerM: 0.55, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'o1-preview', + displayName: 'o1-preview', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 16.5, + outputPerM: 66, + cacheReadPerM: 8.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'o3', + displayName: 'o3', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2, + outputPerM: 8, + cacheReadPerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'o3-mini', + displayName: 'o3-mini', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 1.1, + outputPerM: 4.4, + cacheReadPerM: 0.55, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'o4-mini', + displayName: 'o4-mini', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.1, + outputPerM: 4.4, + cacheReadPerM: 0.28, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'phi-3-medium-128k-instruct', + displayName: 'Phi-3-medium-instruct (128k)', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.17, + outputPerM: 0.68, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'phi-3-medium-4k-instruct', + displayName: 'Phi-3-medium-instruct (4k)', + maxInputTokens: 4096, + supportedFileTypes: [], + pricing: { + inputPerM: 0.17, + outputPerM: 0.68, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'phi-3-mini-128k-instruct', + displayName: 'Phi-3-mini-instruct (128k)', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.13, + outputPerM: 0.52, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'phi-3-mini-4k-instruct', + displayName: 'Phi-3-mini-instruct (4k)', + maxInputTokens: 4096, + supportedFileTypes: [], + pricing: { + inputPerM: 0.13, + outputPerM: 0.52, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'phi-3-small-128k-instruct', + displayName: 'Phi-3-small-instruct (128k)', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'phi-3-small-8k-instruct', + displayName: 'Phi-3-small-instruct (8k)', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'phi-3.5-mini-instruct', + displayName: 'Phi-3.5-mini-instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.13, + outputPerM: 0.52, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'phi-3.5-moe-instruct', + displayName: 'Phi-3.5-MoE-instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.16, + outputPerM: 0.64, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'phi-4', + displayName: 'Phi-4', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.125, + outputPerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'phi-4-mini', + displayName: 'Phi-4-mini', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.075, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'phi-4-mini-reasoning', + displayName: 'Phi-4-mini-reasoning', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.075, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'phi-4-multimodal', + displayName: 'Phi-4-multimodal', + maxInputTokens: 128000, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0.08, + outputPerM: 0.32, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'phi-4-reasoning', + displayName: 'Phi-4-reasoning', + maxInputTokens: 32000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.125, + outputPerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'phi-4-reasoning-plus', + displayName: 'Phi-4-reasoning-plus', + maxInputTokens: 32000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.125, + outputPerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'text-embedding-3-large', + displayName: 'text-embedding-3-large', + maxInputTokens: 8191, + supportedFileTypes: [], + pricing: { + inputPerM: 0.13, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'text-embedding-3-small', + displayName: 'text-embedding-3-small', + maxInputTokens: 8191, + supportedFileTypes: [], + pricing: { + inputPerM: 0.02, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'text-embedding-ada-002', + displayName: 'text-embedding-ada-002', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + 'azure-cognitive-services': [ + { + name: 'claude-haiku-4-5', + displayName: 'Claude Haiku 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1, + outputPerM: 5, + cacheReadPerM: 0.1, + cacheWritePerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-opus-4-1', + displayName: 'Claude Opus 4.1', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 15, + outputPerM: 75, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-opus-4-5', + displayName: 'Claude Opus 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-opus-4-6', + displayName: 'Claude Opus 4.6', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-sonnet-4-5', + displayName: 'Claude Sonnet 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'codestral-2501', + displayName: 'Codestral 25.01', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 0.9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'codex-mini', + displayName: 'Codex Mini', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 1.5, + outputPerM: 6, + cacheReadPerM: 0.375, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'cohere-command-a', + displayName: 'Command A', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 2.5, + outputPerM: 10, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'cohere-command-r-08-2024', + displayName: 'Command R', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'cohere-command-r-plus-08-2024', + displayName: 'Command R+', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 2.5, + outputPerM: 10, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'cohere-embed-v-4-0', + displayName: 'Embed v4', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.12, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'cohere-embed-v3-english', + displayName: 'Embed v3 English', + maxInputTokens: 512, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'cohere-embed-v3-multilingual', + displayName: 'Embed v3 Multilingual', + maxInputTokens: 512, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-r1', + displayName: 'DeepSeek-R1', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 1.35, + outputPerM: 5.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-r1-0528', + displayName: 'DeepSeek-R1-0528', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 1.35, + outputPerM: 5.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-v3-0324', + displayName: 'DeepSeek-V3-0324', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 1.14, + outputPerM: 4.56, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-v3.1', + displayName: 'DeepSeek-V3.1', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.56, + outputPerM: 1.68, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-v3.2', + displayName: 'DeepSeek-V3.2', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.58, + outputPerM: 1.68, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-v3.2-speciale', + displayName: 'DeepSeek-V3.2-Speciale', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.58, + outputPerM: 1.68, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-3.5-turbo-0125', + displayName: 'GPT-3.5 Turbo 0125', + maxInputTokens: 16384, + supportedFileTypes: [], + pricing: { + inputPerM: 0.5, + outputPerM: 1.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-3.5-turbo-0301', + displayName: 'GPT-3.5 Turbo 0301', + maxInputTokens: 4096, + supportedFileTypes: [], + pricing: { + inputPerM: 1.5, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-3.5-turbo-0613', + displayName: 'GPT-3.5 Turbo 0613', + maxInputTokens: 16384, + supportedFileTypes: [], + pricing: { + inputPerM: 3, + outputPerM: 4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-3.5-turbo-1106', + displayName: 'GPT-3.5 Turbo 1106', + maxInputTokens: 16384, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-3.5-turbo-instruct', + displayName: 'GPT-3.5 Turbo Instruct', + maxInputTokens: 4096, + supportedFileTypes: [], + pricing: { + inputPerM: 1.5, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4', + displayName: 'GPT-4', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 60, + outputPerM: 120, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4-32k', + displayName: 'GPT-4 32K', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 60, + outputPerM: 120, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4-turbo', + displayName: 'GPT-4 Turbo', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 10, + outputPerM: 30, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4-turbo-vision', + displayName: 'GPT-4 Turbo Vision', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 10, + outputPerM: 30, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4.1', + displayName: 'GPT-4.1', + maxInputTokens: 1047576, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2, + outputPerM: 8, + cacheReadPerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4.1-mini', + displayName: 'GPT-4.1 mini', + maxInputTokens: 1047576, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.4, + outputPerM: 1.6, + cacheReadPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4.1-nano', + displayName: 'GPT-4.1 nano', + maxInputTokens: 1047576, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.4, + cacheReadPerM: 0.03, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4o', + displayName: 'GPT-4o', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2.5, + outputPerM: 10, + cacheReadPerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4o-mini', + displayName: 'GPT-4o mini', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + cacheReadPerM: 0.08, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5', + displayName: 'GPT-5', + maxInputTokens: 272000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.13, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5-chat', + displayName: 'GPT-5 Chat', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.13, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5-codex', + displayName: 'GPT-5-Codex', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.13, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5-mini', + displayName: 'GPT-5 Mini', + maxInputTokens: 272000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.25, + outputPerM: 2, + cacheReadPerM: 0.03, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5-nano', + displayName: 'GPT-5 Nano', + maxInputTokens: 272000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.05, + outputPerM: 0.4, + cacheReadPerM: 0.01, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5-pro', + displayName: 'GPT-5 Pro', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 15, + outputPerM: 120, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.1', + displayName: 'GPT-5.1', + maxInputTokens: 272000, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.1-chat', + displayName: 'GPT-5.1 Chat', + maxInputTokens: 128000, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.1-codex', + displayName: 'GPT-5.1 Codex', + maxInputTokens: 400000, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.1-codex-mini', + displayName: 'GPT-5.1 Codex Mini', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.25, + outputPerM: 2, + cacheReadPerM: 0.025, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.2', + displayName: 'GPT-5.2', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.75, + outputPerM: 14, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.2-chat', + displayName: 'GPT-5.2 Chat', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.75, + outputPerM: 14, + cacheReadPerM: 0.175, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.2-codex', + displayName: 'GPT-5.2 Codex', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.75, + outputPerM: 14, + cacheReadPerM: 0.175, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'grok-3', + displayName: 'Grok 3', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'grok-3-mini', + displayName: 'Grok 3 Mini', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 0.5, + cacheReadPerM: 0.075, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'grok-4', + displayName: 'Grok 4', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'grok-4-fast-non-reasoning', + displayName: 'Grok 4 Fast (Non-Reasoning)', + maxInputTokens: 2000000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.2, + outputPerM: 0.5, + cacheReadPerM: 0.05, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'grok-4-fast-reasoning', + displayName: 'Grok 4 Fast (Reasoning)', + maxInputTokens: 2000000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.2, + outputPerM: 0.5, + cacheReadPerM: 0.05, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'grok-code-fast-1', + displayName: 'Grok Code Fast 1', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 1.5, + cacheReadPerM: 0.02, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2-thinking', + displayName: 'Kimi K2 Thinking', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.5, + cacheReadPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2.5', + displayName: 'Kimi K2.5', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.6, + outputPerM: 3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'llama-3.2-11b-vision-instruct', + displayName: 'Llama-3.2-11B-Vision-Instruct', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.37, + outputPerM: 0.37, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'llama-3.2-90b-vision-instruct', + displayName: 'Llama-3.2-90B-Vision-Instruct', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2.04, + outputPerM: 2.04, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'llama-3.3-70b-instruct', + displayName: 'Llama-3.3-70B-Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.71, + outputPerM: 0.71, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'llama-4-maverick-17b-128e-instruct-fp8', + displayName: 'Llama 4 Maverick 17B 128E Instruct FP8', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.25, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'llama-4-scout-17b-16e-instruct', + displayName: 'Llama 4 Scout 17B 16E Instruct', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.2, + outputPerM: 0.78, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mai-ds-r1', + displayName: 'MAI-DS-R1', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 1.35, + outputPerM: 5.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama-3-70b-instruct', + displayName: 'Meta-Llama-3-70B-Instruct', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 2.68, + outputPerM: 3.54, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama-3-8b-instruct', + displayName: 'Meta-Llama-3-8B-Instruct', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 0.61, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama-3.1-405b-instruct', + displayName: 'Meta-Llama-3.1-405B-Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 5.33, + outputPerM: 16, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama-3.1-70b-instruct', + displayName: 'Meta-Llama-3.1-70B-Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 2.68, + outputPerM: 3.54, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama-3.1-8b-instruct', + displayName: 'Meta-Llama-3.1-8B-Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 0.61, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'ministral-3b', + displayName: 'Ministral 3B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.04, + outputPerM: 0.04, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral-large-2411', + displayName: 'Mistral Large 24.11', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 2, + outputPerM: 6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral-medium-2505', + displayName: 'Mistral Medium 3', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.4, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral-nemo', + displayName: 'Mistral Nemo', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral-small-2503', + displayName: 'Mistral Small 3.1', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'model-router', + displayName: 'Model Router', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.14, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'o1', + displayName: 'o1', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 15, + outputPerM: 60, + cacheReadPerM: 7.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'o1-mini', + displayName: 'o1-mini', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 1.1, + outputPerM: 4.4, + cacheReadPerM: 0.55, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'o1-preview', + displayName: 'o1-preview', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 16.5, + outputPerM: 66, + cacheReadPerM: 8.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'o3', + displayName: 'o3', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2, + outputPerM: 8, + cacheReadPerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'o3-mini', + displayName: 'o3-mini', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 1.1, + outputPerM: 4.4, + cacheReadPerM: 0.55, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'o4-mini', + displayName: 'o4-mini', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.1, + outputPerM: 4.4, + cacheReadPerM: 0.28, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'phi-3-medium-128k-instruct', + displayName: 'Phi-3-medium-instruct (128k)', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.17, + outputPerM: 0.68, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'phi-3-medium-4k-instruct', + displayName: 'Phi-3-medium-instruct (4k)', + maxInputTokens: 4096, + supportedFileTypes: [], + pricing: { + inputPerM: 0.17, + outputPerM: 0.68, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'phi-3-mini-128k-instruct', + displayName: 'Phi-3-mini-instruct (128k)', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.13, + outputPerM: 0.52, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'phi-3-mini-4k-instruct', + displayName: 'Phi-3-mini-instruct (4k)', + maxInputTokens: 4096, + supportedFileTypes: [], + pricing: { + inputPerM: 0.13, + outputPerM: 0.52, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'phi-3-small-128k-instruct', + displayName: 'Phi-3-small-instruct (128k)', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'phi-3-small-8k-instruct', + displayName: 'Phi-3-small-instruct (8k)', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'phi-3.5-mini-instruct', + displayName: 'Phi-3.5-mini-instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.13, + outputPerM: 0.52, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'phi-3.5-moe-instruct', + displayName: 'Phi-3.5-MoE-instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.16, + outputPerM: 0.64, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'phi-4', + displayName: 'Phi-4', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.125, + outputPerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'phi-4-mini', + displayName: 'Phi-4-mini', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.075, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'phi-4-mini-reasoning', + displayName: 'Phi-4-mini-reasoning', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.075, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'phi-4-multimodal', + displayName: 'Phi-4-multimodal', + maxInputTokens: 128000, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0.08, + outputPerM: 0.32, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'phi-4-reasoning', + displayName: 'Phi-4-reasoning', + maxInputTokens: 32000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.125, + outputPerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'phi-4-reasoning-plus', + displayName: 'Phi-4-reasoning-plus', + maxInputTokens: 32000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.125, + outputPerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'text-embedding-3-large', + displayName: 'text-embedding-3-large', + maxInputTokens: 8191, + supportedFileTypes: [], + pricing: { + inputPerM: 0.13, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'text-embedding-3-small', + displayName: 'text-embedding-3-small', + maxInputTokens: 8191, + supportedFileTypes: [], + pricing: { + inputPerM: 0.02, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'text-embedding-ada-002', + displayName: 'text-embedding-ada-002', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + bailing: [ + { + name: 'Ling-1T', + displayName: 'Ling-1T', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.57, + outputPerM: 2.29, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Ring-1T', + displayName: 'Ring-1T', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.57, + outputPerM: 2.29, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + baseten: [ + { + name: 'deepseek-ai/DeepSeek-V3.2', + displayName: 'DeepSeek V3.2', + maxInputTokens: 163800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 0.45, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/Kimi-K2-Instruct-0905', + displayName: 'Kimi K2 Instruct 0905', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/Kimi-K2-Thinking', + displayName: 'Kimi K2 Thinking', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/Kimi-K2.5', + displayName: 'Kimi K2.5', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-Coder-480B-A35B-Instruct', + displayName: 'Qwen3 Coder 480B A35B Instruct', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.38, + outputPerM: 1.53, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-4.6', + displayName: 'GLM 4.6', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-4.7', + displayName: 'GLM-4.7', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-5', + displayName: 'GLM-5', + maxInputTokens: 202752, + supportedFileTypes: [], + pricing: { + inputPerM: 0.95, + outputPerM: 3.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + berget: [ + { + name: 'BAAI/bge-reranker-v2-m3', + displayName: 'bge-reranker-v2-m3', + maxInputTokens: 512, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'intfloat/multilingual-e5-large', + displayName: 'Multilingual-E5-large', + maxInputTokens: 512, + supportedFileTypes: [], + pricing: { + inputPerM: 0.02, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'intfloat/multilingual-e5-large-instruct', + displayName: 'Multilingual-E5-large-instruct', + maxInputTokens: 512, + supportedFileTypes: [], + pricing: { + inputPerM: 0.02, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'KBLab/kb-whisper-large', + displayName: 'KB-Whisper-Large', + maxInputTokens: 480000, + supportedFileTypes: ['audio'], + pricing: { + inputPerM: 3, + outputPerM: 3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/Llama-3.3-70B-Instruct', + displayName: 'Llama 3.3 70B Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.9, + outputPerM: 0.9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/Mistral-Small-3.2-24B-Instruct-2506', + displayName: 'Mistral Small 3.2 24B Instruct 2506', + maxInputTokens: 32000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-120b', + displayName: 'GPT-OSS-120B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 0.9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-4.7', + displayName: 'GLM 4.7', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.7, + outputPerM: 2.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + cerebras: [ + { + name: 'gpt-oss-120b', + displayName: 'GPT OSS 120B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.25, + outputPerM: 0.69, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'llama3.1-8b', + displayName: 'Llama 3.1 8B', + maxInputTokens: 32000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen-3-235b-a22b-instruct-2507', + displayName: 'Qwen 3 235B Instruct', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-glm-4.7', + displayName: 'Z.AI GLM-4.7', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 2.25, + outputPerM: 2.75, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + chutes: [ + { + name: 'chutesai/Mistral-Small-3.1-24B-Instruct-2503', + displayName: 'Mistral Small 3.1 24B Instruct 2503', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.03, + outputPerM: 0.11, + cacheReadPerM: 0.015, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'chutesai/Mistral-Small-3.2-24B-Instruct-2506', + displayName: 'Mistral Small 3.2 24B Instruct 2506', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.06, + outputPerM: 0.18, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/DeepSeek-R1-0528-TEE', + displayName: 'DeepSeek R1 0528 TEE', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.4, + outputPerM: 1.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/DeepSeek-R1-Distill-Llama-70B', + displayName: 'DeepSeek R1 Distill Llama 70B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.03, + outputPerM: 0.11, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/DeepSeek-R1-TEE', + displayName: 'DeepSeek R1 TEE', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/DeepSeek-V3', + displayName: 'DeepSeek V3', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/DeepSeek-V3-0324-TEE', + displayName: 'DeepSeek V3 0324 TEE', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.19, + outputPerM: 0.87, + cacheReadPerM: 0.095, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/DeepSeek-V3.1-TEE', + displayName: 'DeepSeek V3.1 TEE', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/DeepSeek-V3.1-Terminus-TEE', + displayName: 'DeepSeek V3.1 Terminus TEE', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.23, + outputPerM: 0.9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/DeepSeek-V3.2-Speciale-TEE', + displayName: 'DeepSeek V3.2 Speciale TEE', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.27, + outputPerM: 0.41, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/DeepSeek-V3.2-TEE', + displayName: 'DeepSeek V3.2 TEE', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.25, + outputPerM: 0.38, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'MiniMaxAI/MiniMax-M2.1-TEE', + displayName: 'MiniMax M2.1 TEE', + maxInputTokens: 196608, + supportedFileTypes: [], + pricing: { + inputPerM: 0.27, + outputPerM: 1.12, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'MiniMaxAI/MiniMax-M2.5-TEE', + displayName: 'MiniMax M2.5 TEE', + maxInputTokens: 196608, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'miromind-ai/MiroThinker-v1.5-235B', + displayName: 'MiroThinker V1.5 235B', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + cacheReadPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/Devstral-2-123B-Instruct-2512-TEE', + displayName: 'Devstral 2 123B Instruct 2512 TEE', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.05, + outputPerM: 0.22, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/Kimi-K2-Instruct-0905', + displayName: 'Kimi K2 Instruct 0905', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.39, + outputPerM: 1.9, + cacheReadPerM: 0.195, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/Kimi-K2-Thinking-TEE', + displayName: 'Kimi K2 Thinking TEE', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.4, + outputPerM: 1.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/Kimi-K2.5-TEE', + displayName: 'Kimi K2.5 TEE', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.6, + outputPerM: 3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'NousResearch/DeepHermes-3-Mistral-24B-Preview', + displayName: 'DeepHermes 3 Mistral 24B Preview', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.02, + outputPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'NousResearch/Hermes-4-14B', + displayName: 'Hermes 4 14B', + maxInputTokens: 40960, + supportedFileTypes: [], + pricing: { + inputPerM: 0.01, + outputPerM: 0.05, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'NousResearch/Hermes-4-405B-FP8-TEE', + displayName: 'Hermes 4 405B FP8 TEE', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'NousResearch/Hermes-4-70B', + displayName: 'Hermes 4 70B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.11, + outputPerM: 0.38, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'NousResearch/Hermes-4.3-36B', + displayName: 'Hermes 4.3 36B', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.39, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nvidia/NVIDIA-Nemotron-3-Nano-30B-A3B-BF16', + displayName: 'NVIDIA Nemotron 3 Nano 30B A3B BF16', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.06, + outputPerM: 0.24, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-120b-TEE', + displayName: 'gpt oss 120b TEE', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.04, + outputPerM: 0.18, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-20b', + displayName: 'gpt oss 20b', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.02, + outputPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'OpenGVLab/InternVL3-78B-TEE', + displayName: 'InternVL3 78B TEE', + maxInputTokens: 32768, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.39, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen2.5-72B-Instruct', + displayName: 'Qwen2.5 72B Instruct', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.13, + outputPerM: 0.52, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen2.5-Coder-32B-Instruct', + displayName: 'Qwen2.5 Coder 32B Instruct', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.03, + outputPerM: 0.11, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen2.5-VL-32B-Instruct', + displayName: 'Qwen2.5 VL 32B Instruct', + maxInputTokens: 16384, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.05, + outputPerM: 0.22, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen2.5-VL-72B-Instruct-TEE', + displayName: 'Qwen2.5 VL 72B Instruct TEE', + maxInputTokens: 32768, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-14B', + displayName: 'Qwen3 14B', + maxInputTokens: 40960, + supportedFileTypes: [], + pricing: { + inputPerM: 0.05, + outputPerM: 0.22, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-235B-A22B', + displayName: 'Qwen3 235B A22B', + maxInputTokens: 40960, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-235B-A22B-Instruct-2507-TEE', + displayName: 'Qwen3 235B A22B Instruct 2507 TEE', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.08, + outputPerM: 0.55, + cacheReadPerM: 0.04, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-235B-A22B-Thinking-2507', + displayName: 'Qwen3 235B A22B Thinking 2507', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.11, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-30B-A3B', + displayName: 'Qwen3 30B A3B', + maxInputTokens: 40960, + supportedFileTypes: [], + pricing: { + inputPerM: 0.06, + outputPerM: 0.22, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-30B-A3B-Instruct-2507', + displayName: 'Qwen3 30B A3B Instruct 2507', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.08, + outputPerM: 0.33, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-32B', + displayName: 'Qwen3 32B', + maxInputTokens: 40960, + supportedFileTypes: [], + pricing: { + inputPerM: 0.08, + outputPerM: 0.24, + cacheReadPerM: 0.04, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-Coder-480B-A35B-Instruct-FP8-TEE', + displayName: 'Qwen3 Coder 480B A35B Instruct FP8 TEE', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.22, + outputPerM: 0.95, + cacheReadPerM: 0.11, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-Coder-Next', + displayName: 'Qwen3 Coder Next', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.07, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-Next-80B-A3B-Instruct', + displayName: 'Qwen3 Next 80B A3B Instruct', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-VL-235B-A22B-Instruct', + displayName: 'Qwen3 VL 235B A22B Instruct', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3.5-397B-A17B-TEE', + displayName: 'Qwen3.5 397B A17B TEE', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + cacheReadPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3Guard-Gen-0.6B', + displayName: 'Qwen3Guard Gen 0.6B', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.01, + outputPerM: 0.01, + cacheReadPerM: 0.005, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'rednote-hilab/dots.ocr', + displayName: 'dots.ocr', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.01, + outputPerM: 0.01, + cacheReadPerM: 0.005, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'tngtech/DeepSeek-R1T-Chimera', + displayName: 'DeepSeek R1T Chimera', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'tngtech/DeepSeek-TNG-R1T2-Chimera', + displayName: 'DeepSeek TNG R1T2 Chimera', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.25, + outputPerM: 0.85, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'tngtech/TNG-R1T-Chimera-TEE', + displayName: 'TNG R1T Chimera TEE', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.25, + outputPerM: 0.85, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'tngtech/TNG-R1T-Chimera-Turbo', + displayName: 'TNG R1T Chimera Turbo', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.22, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'unsloth/gemma-3-12b-it', + displayName: 'gemma 3 12b it', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.03, + outputPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'unsloth/gemma-3-27b-it', + displayName: 'gemma 3 27b it', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.04, + outputPerM: 0.15, + cacheReadPerM: 0.02, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'unsloth/gemma-3-4b-it', + displayName: 'gemma 3 4b it', + maxInputTokens: 96000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.01, + outputPerM: 0.03, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'unsloth/Llama-3.2-1B-Instruct', + displayName: 'Llama 3.2 1B Instruct', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.01, + outputPerM: 0.01, + cacheReadPerM: 0.005, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'unsloth/Llama-3.2-3B-Instruct', + displayName: 'Llama 3.2 3B Instruct', + maxInputTokens: 16384, + supportedFileTypes: [], + pricing: { + inputPerM: 0.01, + outputPerM: 0.01, + cacheReadPerM: 0.005, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'unsloth/Mistral-Nemo-Instruct-2407', + displayName: 'Mistral Nemo Instruct 2407', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.02, + outputPerM: 0.04, + cacheReadPerM: 0.01, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'unsloth/Mistral-Small-24B-Instruct-2501', + displayName: 'Mistral Small 24B Instruct 2501', + maxInputTokens: 32768, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.03, + outputPerM: 0.11, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'XiaomiMiMo/MiMo-V2-Flash', + displayName: 'MiMo V2 Flash', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.09, + outputPerM: 0.29, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-4.5-Air', + displayName: 'GLM 4.5 Air', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.05, + outputPerM: 0.22, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-4.5-FP8', + displayName: 'GLM 4.5 FP8', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-4.5-TEE', + displayName: 'GLM 4.5 TEE', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.35, + outputPerM: 1.55, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-4.6-FP8', + displayName: 'GLM 4.6 FP8', + maxInputTokens: 202752, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-4.6-TEE', + displayName: 'GLM 4.6 TEE', + maxInputTokens: 202752, + supportedFileTypes: [], + pricing: { + inputPerM: 0.35, + outputPerM: 1.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-4.6V', + displayName: 'GLM 4.6V', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.3, + outputPerM: 0.9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-4.7-Flash', + displayName: 'GLM 4.7 Flash', + maxInputTokens: 202752, + supportedFileTypes: [], + pricing: { + inputPerM: 0.06, + outputPerM: 0.35, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-4.7-FP8', + displayName: 'GLM 4.7 FP8', + maxInputTokens: 202752, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-4.7-TEE', + displayName: 'GLM 4.7 TEE', + maxInputTokens: 202752, + supportedFileTypes: [], + pricing: { + inputPerM: 0.4, + outputPerM: 1.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-5-TEE', + displayName: 'GLM 5 TEE', + maxInputTokens: 202752, + supportedFileTypes: [], + pricing: { + inputPerM: 0.75, + outputPerM: 2.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + 'cloudferro-sherlock': [ + { + name: 'meta-llama/Llama-3.3-70B-Instruct', + displayName: 'Llama 3.3 70B Instruct', + maxInputTokens: 70000, + supportedFileTypes: [], + pricing: { + inputPerM: 2.92, + outputPerM: 2.92, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-120b', + displayName: 'OpenAI GPT OSS 120B', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 2.92, + outputPerM: 2.92, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'speakleash/Bielik-11B-v2.6-Instruct', + displayName: 'Bielik 11B v2.6 Instruct', + maxInputTokens: 32000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.67, + outputPerM: 0.67, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'speakleash/Bielik-11B-v3.0-Instruct', + displayName: 'Bielik 11B v3.0 Instruct', + maxInputTokens: 32000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.67, + outputPerM: 0.67, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + 'cloudflare-ai-gateway': [ + { + name: 'anthropic/claude-3-5-haiku', + displayName: 'Claude Haiku 3.5 (latest)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0.8, + outputPerM: 4, + cacheReadPerM: 0.08, + cacheWritePerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-3-haiku', + displayName: 'Claude Haiku 3', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0.25, + outputPerM: 1.25, + cacheReadPerM: 0.03, + cacheWritePerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-3-opus', + displayName: 'Claude Opus 3', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 15, + outputPerM: 75, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-3-sonnet', + displayName: 'Claude Sonnet 3', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-3.5-haiku', + displayName: 'Claude Haiku 3.5 (latest)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0.8, + outputPerM: 4, + cacheReadPerM: 0.08, + cacheWritePerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-3.5-sonnet', + displayName: 'Claude Sonnet 3.5 v2', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-haiku-4-5', + displayName: 'Claude Haiku 4.5 (latest)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1, + outputPerM: 5, + cacheReadPerM: 0.1, + cacheWritePerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-opus-4', + displayName: 'Claude Opus 4 (latest)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 15, + outputPerM: 75, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-opus-4-1', + displayName: 'Claude Opus 4.1 (latest)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 15, + outputPerM: 75, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-opus-4-5', + displayName: 'Claude Opus 4.5 (latest)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-opus-4-6', + displayName: 'Claude Opus 4.6 (latest)', + maxInputTokens: 1000000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-sonnet-4', + displayName: 'Claude Sonnet 4 (latest)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-sonnet-4-5', + displayName: 'Claude Sonnet 4.5 (latest)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-sonnet-4-6', + displayName: 'Claude Sonnet 4.6', + maxInputTokens: 1000000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-3.5-turbo', + displayName: 'GPT-3.5-turbo', + maxInputTokens: 16385, + supportedFileTypes: [], + pricing: { + inputPerM: 0.5, + outputPerM: 1.5, + cacheReadPerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4', + displayName: 'GPT-4', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 30, + outputPerM: 60, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4-turbo', + displayName: 'GPT-4 Turbo', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 10, + outputPerM: 30, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4o', + displayName: 'GPT-4o', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2.5, + outputPerM: 10, + cacheReadPerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4o-mini', + displayName: 'GPT-4o mini', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + cacheReadPerM: 0.08, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.1', + displayName: 'GPT-5.1', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.13, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.1-codex', + displayName: 'GPT-5.1 Codex', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.2', + displayName: 'GPT-5.2', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.75, + outputPerM: 14, + cacheReadPerM: 0.175, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/o1', + displayName: 'o1', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 15, + outputPerM: 60, + cacheReadPerM: 7.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/o3', + displayName: 'o3', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2, + outputPerM: 8, + cacheReadPerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/o3-mini', + displayName: 'o3-mini', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 1.1, + outputPerM: 4.4, + cacheReadPerM: 0.55, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/o3-pro', + displayName: 'o3-pro', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 20, + outputPerM: 80, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/o4-mini', + displayName: 'o4-mini', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.1, + outputPerM: 4.4, + cacheReadPerM: 0.28, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/ai4bharat/indictrans2-en-indic-1B', + displayName: 'IndicTrans2 EN-Indic 1B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.34, + outputPerM: 0.34, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/aisingapore/gemma-sea-lion-v4-27b-it', + displayName: 'Gemma SEA-LION v4 27B IT', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.35, + outputPerM: 0.56, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/baai/bge-base-en-v1.5', + displayName: 'BGE Base EN v1.5', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.067, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/baai/bge-large-en-v1.5', + displayName: 'BGE Large EN v1.5', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/baai/bge-m3', + displayName: 'BGE M3', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.012, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/baai/bge-reranker-base', + displayName: 'BGE Reranker Base', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.0031, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/baai/bge-small-en-v1.5', + displayName: 'BGE Small EN v1.5', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.02, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/deepgram/aura-2-en', + displayName: 'Deepgram Aura 2 (EN)', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/deepgram/aura-2-es', + displayName: 'Deepgram Aura 2 (ES)', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/deepgram/nova-3', + displayName: 'Deepgram Nova 3', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/deepseek-ai/deepseek-r1-distill-qwen-32b', + displayName: 'DeepSeek R1 Distill Qwen 32B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.5, + outputPerM: 4.88, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/facebook/bart-large-cnn', + displayName: 'BART Large CNN', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/google/gemma-3-12b-it', + displayName: 'Gemma 3 12B IT', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.35, + outputPerM: 0.56, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/huggingface/distilbert-sst-2-int8', + displayName: 'DistilBERT SST-2 INT8', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.026, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/ibm-granite/granite-4.0-h-micro', + displayName: 'IBM Granite 4.0 H Micro', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.017, + outputPerM: 0.11, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/meta/llama-2-7b-chat-fp16', + displayName: 'Llama 2 7B Chat FP16', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.56, + outputPerM: 6.67, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/meta/llama-3-8b-instruct', + displayName: 'Llama 3 8B Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.28, + outputPerM: 0.83, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/meta/llama-3-8b-instruct-awq', + displayName: 'Llama 3 8B Instruct AWQ', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.12, + outputPerM: 0.27, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/meta/llama-3.1-8b-instruct', + displayName: 'Llama 3.1 8B Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.28, + outputPerM: 0.8299999999999998, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/meta/llama-3.1-8b-instruct-awq', + displayName: 'Llama 3.1 8B Instruct AWQ', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.12, + outputPerM: 0.27, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/meta/llama-3.1-8b-instruct-fp8', + displayName: 'Llama 3.1 8B Instruct FP8', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0.29, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/meta/llama-3.2-11b-vision-instruct', + displayName: 'Llama 3.2 11B Vision Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.049, + outputPerM: 0.68, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/meta/llama-3.2-1b-instruct', + displayName: 'Llama 3.2 1B Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.027, + outputPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/meta/llama-3.2-3b-instruct', + displayName: 'Llama 3.2 3B Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.051, + outputPerM: 0.34, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/meta/llama-3.3-70b-instruct-fp8-fast', + displayName: 'Llama 3.3 70B Instruct FP8 Fast', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.29, + outputPerM: 2.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/meta/llama-4-scout-17b-16e-instruct', + displayName: 'Llama 4 Scout 17B 16E Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.27, + outputPerM: 0.85, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/meta/llama-guard-3-8b', + displayName: 'Llama Guard 3 8B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.48, + outputPerM: 0.03, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/meta/m2m100-1.2b', + displayName: 'M2M100 1.2B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.34, + outputPerM: 0.34, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/mistral/mistral-7b-instruct-v0.1', + displayName: 'Mistral 7B Instruct v0.1', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.11, + outputPerM: 0.19, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/mistralai/mistral-small-3.1-24b-instruct', + displayName: 'Mistral Small 3.1 24B Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.35, + outputPerM: 0.56, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/myshell-ai/melotts', + displayName: 'MyShell MeloTTS', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/openai/gpt-oss-120b', + displayName: 'GPT OSS 120B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.35, + outputPerM: 0.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/openai/gpt-oss-20b', + displayName: 'GPT OSS 20B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/pfnet/plamo-embedding-1b', + displayName: 'PLaMo Embedding 1B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.019, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/pipecat-ai/smart-turn-v2', + displayName: 'Pipecat Smart Turn v2', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/qwen/qwen2.5-coder-32b-instruct', + displayName: 'Qwen 2.5 Coder 32B Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.66, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/qwen/qwen3-30b-a3b-fp8', + displayName: 'Qwen3 30B A3B FP8', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.051, + outputPerM: 0.34, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/qwen/qwen3-embedding-0.6b', + displayName: 'Qwen3 Embedding 0.6B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.012, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'workers-ai/@cf/qwen/qwq-32b', + displayName: 'QwQ 32B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.66, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + 'cloudflare-workers-ai': [ + { + name: '@cf/ai4bharat/indictrans2-en-indic-1B', + displayName: 'IndicTrans2 EN-Indic 1B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.34, + outputPerM: 0.34, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/aisingapore/gemma-sea-lion-v4-27b-it', + displayName: 'Gemma SEA-LION v4 27B IT', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.35, + outputPerM: 0.56, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/baai/bge-base-en-v1.5', + displayName: 'BGE Base EN v1.5', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.067, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/baai/bge-large-en-v1.5', + displayName: 'BGE Large EN v1.5', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/baai/bge-m3', + displayName: 'BGE M3', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.012, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/baai/bge-reranker-base', + displayName: 'BGE Reranker Base', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.0031, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/baai/bge-small-en-v1.5', + displayName: 'BGE Small EN v1.5', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.02, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/deepgram/aura-2-en', + displayName: 'Deepgram Aura 2 (EN)', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/deepgram/aura-2-es', + displayName: 'Deepgram Aura 2 (ES)', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/deepgram/nova-3', + displayName: 'Deepgram Nova 3', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/deepseek-ai/deepseek-r1-distill-qwen-32b', + displayName: 'DeepSeek R1 Distill Qwen 32B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.5, + outputPerM: 4.88, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/facebook/bart-large-cnn', + displayName: 'BART Large CNN', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/google/gemma-3-12b-it', + displayName: 'Gemma 3 12B IT', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.35, + outputPerM: 0.56, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/huggingface/distilbert-sst-2-int8', + displayName: 'DistilBERT SST-2 INT8', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.026, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/ibm-granite/granite-4.0-h-micro', + displayName: 'IBM Granite 4.0 H Micro', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.017, + outputPerM: 0.11, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/meta/llama-2-7b-chat-fp16', + displayName: 'Llama 2 7B Chat FP16', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.56, + outputPerM: 6.67, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/meta/llama-3-8b-instruct', + displayName: 'Llama 3 8B Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.28, + outputPerM: 0.83, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/meta/llama-3-8b-instruct-awq', + displayName: 'Llama 3 8B Instruct AWQ', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.12, + outputPerM: 0.27, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/meta/llama-3.1-8b-instruct', + displayName: 'Llama 3.1 8B Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.28, + outputPerM: 0.8299999999999998, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/meta/llama-3.1-8b-instruct-awq', + displayName: 'Llama 3.1 8B Instruct AWQ', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.12, + outputPerM: 0.27, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/meta/llama-3.1-8b-instruct-fp8', + displayName: 'Llama 3.1 8B Instruct FP8', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0.29, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/meta/llama-3.2-11b-vision-instruct', + displayName: 'Llama 3.2 11B Vision Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.049, + outputPerM: 0.68, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/meta/llama-3.2-1b-instruct', + displayName: 'Llama 3.2 1B Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.027, + outputPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/meta/llama-3.2-3b-instruct', + displayName: 'Llama 3.2 3B Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.051, + outputPerM: 0.34, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/meta/llama-3.3-70b-instruct-fp8-fast', + displayName: 'Llama 3.3 70B Instruct FP8 Fast', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.29, + outputPerM: 2.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/meta/llama-4-scout-17b-16e-instruct', + displayName: 'Llama 4 Scout 17B 16E Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.27, + outputPerM: 0.85, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/meta/llama-guard-3-8b', + displayName: 'Llama Guard 3 8B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.48, + outputPerM: 0.03, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/meta/m2m100-1.2b', + displayName: 'M2M100 1.2B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.34, + outputPerM: 0.34, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/mistral/mistral-7b-instruct-v0.1', + displayName: 'Mistral 7B Instruct v0.1', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.11, + outputPerM: 0.19, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/mistralai/mistral-small-3.1-24b-instruct', + displayName: 'Mistral Small 3.1 24B Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.35, + outputPerM: 0.56, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/myshell-ai/melotts', + displayName: 'MyShell MeloTTS', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/openai/gpt-oss-120b', + displayName: 'GPT OSS 120B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.35, + outputPerM: 0.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/openai/gpt-oss-20b', + displayName: 'GPT OSS 20B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/pfnet/plamo-embedding-1b', + displayName: 'PLaMo Embedding 1B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.019, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/pipecat-ai/smart-turn-v2', + displayName: 'Pipecat Smart Turn v2', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/qwen/qwen2.5-coder-32b-instruct', + displayName: 'Qwen 2.5 Coder 32B Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.66, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/qwen/qwen3-30b-a3b-fp8', + displayName: 'Qwen3 30B A3B FP8', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.051, + outputPerM: 0.34, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/qwen/qwen3-embedding-0.6b', + displayName: 'Qwen3 Embedding 0.6B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.012, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: '@cf/qwen/qwq-32b', + displayName: 'QwQ 32B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.66, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + cohere: [ + { + name: 'command-a-03-2025', + displayName: 'Command A', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 2.5, + outputPerM: 10, + currency: 'USD', + unit: 'per_million_tokens', + }, + default: true, + }, + { + name: 'command-a-reasoning-08-2025', + displayName: 'Command A Reasoning', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 2.5, + outputPerM: 10, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'command-a-translate-08-2025', + displayName: 'Command A Translate', + maxInputTokens: 8000, + supportedFileTypes: [], + pricing: { + inputPerM: 2.5, + outputPerM: 10, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'command-a-vision-07-2025', + displayName: 'Command A Vision', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2.5, + outputPerM: 10, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'command-r-08-2024', + displayName: 'Command R', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'command-r-plus-08-2024', + displayName: 'Command R+', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 2.5, + outputPerM: 10, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'command-r7b-12-2024', + displayName: 'Command R7B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.0375, + outputPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'command-r7b-arabic-02-2025', + displayName: 'Command R7B Arabic', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.0375, + outputPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + cortecs: [ + { + name: 'claude-4-5-sonnet', + displayName: 'Claude 4.5 Sonnet', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3.259, + outputPerM: 16.296, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-sonnet-4', + displayName: 'Claude Sonnet 4', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3.307, + outputPerM: 16.536, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-v3-0324', + displayName: 'DeepSeek V3 0324', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.551, + outputPerM: 1.654, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'devstral-2512', + displayName: 'Devstral 2 2512', + maxInputTokens: 262000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'devstral-small-2512', + displayName: 'Devstral Small 2 2512', + maxInputTokens: 262000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-pro', + displayName: 'Gemini 2.5 Pro', + maxInputTokens: 1048576, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.654, + outputPerM: 11.024, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-4p5', + displayName: 'GLM 4.5', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.67, + outputPerM: 2.46, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-4p5-air', + displayName: 'GLM 4.5 Air', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.22, + outputPerM: 1.34, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-4p7', + displayName: 'GLM 4.7', + maxInputTokens: 198000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.45, + outputPerM: 2.23, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4.1', + displayName: 'GPT 4.1', + maxInputTokens: 1047576, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2.354, + outputPerM: 9.417, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-oss-120b', + displayName: 'GPT Oss 120b', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'intellect-3', + displayName: 'INTELLECT 3', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.219, + outputPerM: 1.202, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2-instruct', + displayName: 'Kimi K2 Instruct', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.551, + outputPerM: 2.646, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2-thinking', + displayName: 'Kimi K2 Thinking', + maxInputTokens: 262000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.656, + outputPerM: 2.731, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'llama-3.1-405b-instruct', + displayName: 'Llama 3.1 405B Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'minimax-m2', + displayName: 'MiniMax-M2', + maxInputTokens: 400000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.39, + outputPerM: 1.57, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'minimax-m2p1', + displayName: 'MiniMax-M2.1', + maxInputTokens: 196000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.34, + outputPerM: 1.34, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nova-pro-v1', + displayName: 'Nova Pro 1.0', + maxInputTokens: 300000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.016, + outputPerM: 4.061, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen3-32b', + displayName: 'Qwen3 32B', + maxInputTokens: 16384, + supportedFileTypes: [], + pricing: { + inputPerM: 0.099, + outputPerM: 0.33, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen3-coder-480b-a35b-instruct', + displayName: 'Qwen3 Coder 480B A35B Instruct', + maxInputTokens: 262000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.441, + outputPerM: 1.984, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen3-next-80b-a3b-thinking', + displayName: 'Qwen3 Next 80B A3B Thinking', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.164, + outputPerM: 1.311, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + deepinfra: [ + { + name: 'anthropic/claude-3-7-sonnet-latest', + displayName: 'Claude Sonnet 3.7 (Latest)', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 3.3, + outputPerM: 16.5, + cacheReadPerM: 0.33, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-4-opus', + displayName: 'Claude Opus 4', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 16.5, + outputPerM: 82.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/DeepSeek-R1-0528', + displayName: 'DeepSeek-R1-0528', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.5, + outputPerM: 2.15, + cacheReadPerM: 0.35, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/DeepSeek-V3.2', + displayName: 'DeepSeek-V3.2', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.26, + outputPerM: 0.38, + cacheReadPerM: 0.13, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'MiniMaxAI/MiniMax-M2', + displayName: 'MiniMax M2', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.254, + outputPerM: 1.02, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'MiniMaxAI/MiniMax-M2.1', + displayName: 'MiniMax M2.1', + maxInputTokens: 196608, + supportedFileTypes: [], + pricing: { + inputPerM: 0.28, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/Kimi-K2-Instruct', + displayName: 'Kimi K2', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.5, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/Kimi-K2-Thinking', + displayName: 'Kimi K2 Thinking', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.47, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/Kimi-K2.5', + displayName: 'Kimi K2.5', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.5, + outputPerM: 2.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-120b', + displayName: 'GPT OSS 120B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.05, + outputPerM: 0.24, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-20b', + displayName: 'GPT OSS 20B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.03, + outputPerM: 0.14, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-Coder-480B-A35B-Instruct', + displayName: 'Qwen3 Coder 480B A35B Instruct', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.4, + outputPerM: 1.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-Coder-480B-A35B-Instruct-Turbo', + displayName: 'Qwen3 Coder 480B A35B Instruct Turbo', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-4.5', + displayName: 'GLM-4.5', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-4.7', + displayName: 'GLM-4.7', + maxInputTokens: 202752, + supportedFileTypes: [], + pricing: { + inputPerM: 0.43, + outputPerM: 1.75, + cacheReadPerM: 0.08, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-4.7-Flash', + displayName: 'GLM-4.7-Flash', + maxInputTokens: 202752, + supportedFileTypes: [], + pricing: { + inputPerM: 0.06, + outputPerM: 0.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + deepseek: [ + { + name: 'deepseek-chat', + displayName: 'DeepSeek Chat', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.28, + outputPerM: 0.42, + cacheReadPerM: 0.028, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-reasoner', + displayName: 'DeepSeek Reasoner', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.28, + outputPerM: 0.42, + cacheReadPerM: 0.028, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + evroc: [ + { + name: 'intfloat/multilingual-e5-large-instruct', + displayName: 'E5 Multi-Lingual Large Embeddings 0.6B', + maxInputTokens: 512, + supportedFileTypes: [], + pricing: { + inputPerM: 0.12, + outputPerM: 0.12, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'KBLab/kb-whisper-large', + displayName: 'KB Whisper', + maxInputTokens: 448, + supportedFileTypes: ['audio'], + pricing: { + inputPerM: 0.00236, + outputPerM: 0.00236, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'microsoft/Phi-4-multimodal-instruct', + displayName: 'Phi-4 15B', + maxInputTokens: 32000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.24, + outputPerM: 0.47, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/devstral-small-2-24b-instruct-2512', + displayName: 'Devstral Small 2 24B Instruct 2512', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.12, + outputPerM: 0.47, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/Magistral-Small-2509', + displayName: 'Magistral Small 1.2 24B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.59, + outputPerM: 2.36, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/Voxtral-Small-24B-2507', + displayName: 'Voxtral Small 24B', + maxInputTokens: 32000, + supportedFileTypes: ['audio'], + pricing: { + inputPerM: 0.00236, + outputPerM: 0.00236, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/Kimi-K2.5', + displayName: 'Kimi K2.5', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.47, + outputPerM: 5.9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nvidia/Llama-3.3-70B-Instruct-FP8', + displayName: 'Llama 3.3 70B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 1.18, + outputPerM: 1.18, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-120b', + displayName: 'GPT OSS 120B', + maxInputTokens: 65536, + supportedFileTypes: [], + pricing: { + inputPerM: 0.24, + outputPerM: 0.94, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/whisper-large-v3', + displayName: 'Whisper 3 Large', + maxInputTokens: 448, + supportedFileTypes: ['audio'], + pricing: { + inputPerM: 0.00236, + outputPerM: 0.00236, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-30B-A3B-Instruct-2507-FP8', + displayName: 'Qwen3 30B 2507', + maxInputTokens: 64000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.35, + outputPerM: 1.42, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-Embedding-8B', + displayName: 'Qwen3 Embedding 8B', + maxInputTokens: 40960, + supportedFileTypes: [], + pricing: { + inputPerM: 0.12, + outputPerM: 0.12, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-VL-30B-A3B-Instruct', + displayName: 'Qwen3 VL 30B', + maxInputTokens: 100000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.24, + outputPerM: 0.94, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + fastrouter: [ + { + name: 'anthropic/claude-opus-4.1', + displayName: 'Claude Opus 4.1', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 15, + outputPerM: 75, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-sonnet-4', + displayName: 'Claude Sonnet 4', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/deepseek-r1-distill-llama-70b', + displayName: 'DeepSeek R1 Distill Llama 70B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.03, + outputPerM: 0.14, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.5-flash', + displayName: 'Gemini 2.5 Flash', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0.3, + outputPerM: 2.5, + cacheReadPerM: 0.0375, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.5-pro', + displayName: 'Gemini 2.5 Pro', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.31, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2', + displayName: 'Kimi K2', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.55, + outputPerM: 2.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4.1', + displayName: 'GPT-4.1', + maxInputTokens: 1047576, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2, + outputPerM: 8, + cacheReadPerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5', + displayName: 'GPT-5', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5-mini', + displayName: 'GPT-5 Mini', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.25, + outputPerM: 2, + cacheReadPerM: 0.025, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5-nano', + displayName: 'GPT-5 Nano', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.05, + outputPerM: 0.4, + cacheReadPerM: 0.005, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-120b', + displayName: 'GPT OSS 120B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-20b', + displayName: 'GPT OSS 20B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.05, + outputPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-coder', + displayName: 'Qwen3 Coder', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'x-ai/grok-4', + displayName: 'Grok 4', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.75, + cacheWritePerM: 15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + 'fireworks-ai': [ + { + name: 'accounts/fireworks/models/deepseek-v3p1', + displayName: 'DeepSeek V3.1', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.56, + outputPerM: 1.68, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'accounts/fireworks/models/deepseek-v3p2', + displayName: 'DeepSeek V3.2', + maxInputTokens: 160000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.56, + outputPerM: 1.68, + cacheReadPerM: 0.28, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'accounts/fireworks/models/glm-4p5', + displayName: 'GLM 4.5', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.55, + outputPerM: 2.19, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'accounts/fireworks/models/glm-4p5-air', + displayName: 'GLM 4.5 Air', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.22, + outputPerM: 0.88, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'accounts/fireworks/models/glm-4p7', + displayName: 'GLM 4.7', + maxInputTokens: 198000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.2, + cacheReadPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'accounts/fireworks/models/glm-5', + displayName: 'GLM 5', + maxInputTokens: 202752, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 3.2, + cacheReadPerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'accounts/fireworks/models/gpt-oss-120b', + displayName: 'GPT OSS 120B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'accounts/fireworks/models/gpt-oss-20b', + displayName: 'GPT OSS 20B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.05, + outputPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'accounts/fireworks/models/kimi-k2-instruct', + displayName: 'Kimi K2 Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'accounts/fireworks/models/kimi-k2-thinking', + displayName: 'Kimi K2 Thinking', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.5, + cacheReadPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'accounts/fireworks/models/kimi-k2p5', + displayName: 'Kimi K2.5', + maxInputTokens: 256000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.6, + outputPerM: 3, + cacheReadPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'accounts/fireworks/models/minimax-m2p1', + displayName: 'MiniMax-M2.1', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + cacheReadPerM: 0.03, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'accounts/fireworks/models/minimax-m2p5', + displayName: 'MiniMax-M2.5', + maxInputTokens: 196608, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + cacheReadPerM: 0.03, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + firmware: [ + { + name: 'claude-haiku-4-5', + displayName: 'Claude Haiku 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1, + outputPerM: 5, + cacheReadPerM: 0.1, + cacheWritePerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-opus-4-5', + displayName: 'Claude Opus 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-opus-4-6', + displayName: 'Claude Opus 4.6', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-sonnet-4-5', + displayName: 'Claude Sonnet 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-sonnet-4-6', + displayName: 'Claude Sonnet 4.6', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-flash', + displayName: 'Gemini 2.5 Flash', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.3, + outputPerM: 2.5, + cacheReadPerM: 0.075, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-pro', + displayName: 'Gemini 2.5 Pro', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.31, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-3-flash-preview', + displayName: 'Gemini 3 Flash Preview', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.5, + outputPerM: 3, + cacheReadPerM: 0.05, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-3-pro-preview', + displayName: 'Gemini 3 Pro Preview', + maxInputTokens: 1000000, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 2, + outputPerM: 12, + cacheReadPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4o', + displayName: 'GPT-4o', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2.5, + outputPerM: 10, + cacheReadPerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5', + displayName: 'GPT-5', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.13, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5-mini', + displayName: 'GPT-5 Mini', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.25, + outputPerM: 2, + cacheReadPerM: 0.03, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5-nano', + displayName: 'GPT-5 Nano', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.05, + outputPerM: 0.4, + cacheReadPerM: 0.01, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.2', + displayName: 'GPT-5.2', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.75, + outputPerM: 14, + cacheReadPerM: 0.175, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-oss-120b', + displayName: 'GPT OSS 120B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-oss-20b', + displayName: 'GPT OSS 20B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.07, + outputPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + friendli: [ + { + name: 'LGAI-EXAONE/EXAONE-4.0.1-32B', + displayName: 'EXAONE 4.0.1 32B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'LGAI-EXAONE/K-EXAONE-236B-A23B', + displayName: 'K EXAONE 236B A23B', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/Llama-3.1-8B-Instruct', + displayName: 'Llama 3.1 8B Instruct', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/Llama-3.3-70B-Instruct', + displayName: 'Llama 3.3 70B Instruct', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'MiniMaxAI/MiniMax-M2.1', + displayName: 'MiniMax M2.1', + maxInputTokens: 196608, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-235B-A22B-Instruct-2507', + displayName: 'Qwen3 235B A22B Instruct 2507', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-4.7', + displayName: 'GLM 4.7', + maxInputTokens: 202752, + supportedFileTypes: [], + }, + { + name: 'zai-org/GLM-5', + displayName: 'GLM 5', + maxInputTokens: 202752, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 3.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + 'github-copilot': [ + { + name: 'claude-haiku-4.5', + displayName: 'Claude Haiku 4.5', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-opus-4.5', + displayName: 'Claude Opus 4.5', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-opus-4.6', + displayName: 'Claude Opus 4.6', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-opus-41', + displayName: 'Claude Opus 4.1', + maxInputTokens: 80000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-sonnet-4', + displayName: 'Claude Sonnet 4', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-sonnet-4.5', + displayName: 'Claude Sonnet 4.5', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-sonnet-4.6', + displayName: 'Claude Sonnet 4.6', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-pro', + displayName: 'Gemini 2.5 Pro', + maxInputTokens: 128000, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-3-flash-preview', + displayName: 'Gemini 3 Flash', + maxInputTokens: 128000, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-3-pro-preview', + displayName: 'Gemini 3 Pro Preview', + maxInputTokens: 128000, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-3.1-pro-preview', + displayName: 'Gemini 3.1 Pro Preview', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4.1', + displayName: 'GPT-4.1', + maxInputTokens: 64000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4o', + displayName: 'GPT-4o', + maxInputTokens: 64000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5', + displayName: 'GPT-5', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5-mini', + displayName: 'GPT-5-mini', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.1', + displayName: 'GPT-5.1', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.1-codex', + displayName: 'GPT-5.1-Codex', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.1-codex-max', + displayName: 'GPT-5.1-Codex-max', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.1-codex-mini', + displayName: 'GPT-5.1-Codex-mini', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.2', + displayName: 'GPT-5.2', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.2-codex', + displayName: 'GPT-5.2-Codex', + maxInputTokens: 272000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'grok-code-fast-1', + displayName: 'Grok Code Fast 1', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + 'github-models': [ + { + name: 'ai21-labs/ai21-jamba-1.5-large', + displayName: 'AI21 Jamba 1.5 Large', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'ai21-labs/ai21-jamba-1.5-mini', + displayName: 'AI21 Jamba 1.5 Mini', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'cohere/cohere-command-a', + displayName: 'Cohere Command A', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'cohere/cohere-command-r', + displayName: 'Cohere Command R', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'cohere/cohere-command-r-08-2024', + displayName: 'Cohere Command R 08-2024', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'cohere/cohere-command-r-plus', + displayName: 'Cohere Command R+', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'cohere/cohere-command-r-plus-08-2024', + displayName: 'Cohere Command R+ 08-2024', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'core42/jais-30b-chat', + displayName: 'JAIS 30b Chat', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-r1', + displayName: 'DeepSeek-R1', + maxInputTokens: 65536, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-r1-0528', + displayName: 'DeepSeek-R1-0528', + maxInputTokens: 65536, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-v3-0324', + displayName: 'DeepSeek-V3-0324', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta/llama-3.2-11b-vision-instruct', + displayName: 'Llama-3.2-11B-Vision-Instruct', + maxInputTokens: 128000, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta/llama-3.2-90b-vision-instruct', + displayName: 'Llama-3.2-90B-Vision-Instruct', + maxInputTokens: 128000, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta/llama-3.3-70b-instruct', + displayName: 'Llama-3.3-70B-Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta/llama-4-maverick-17b-128e-instruct-fp8', + displayName: 'Llama 4 Maverick 17B 128E Instruct FP8', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta/llama-4-scout-17b-16e-instruct', + displayName: 'Llama 4 Scout 17B 16E Instruct', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta/meta-llama-3-70b-instruct', + displayName: 'Meta-Llama-3-70B-Instruct', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta/meta-llama-3-8b-instruct', + displayName: 'Meta-Llama-3-8B-Instruct', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta/meta-llama-3.1-405b-instruct', + displayName: 'Meta-Llama-3.1-405B-Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta/meta-llama-3.1-70b-instruct', + displayName: 'Meta-Llama-3.1-70B-Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta/meta-llama-3.1-8b-instruct', + displayName: 'Meta-Llama-3.1-8B-Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'microsoft/mai-ds-r1', + displayName: 'MAI-DS-R1', + maxInputTokens: 65536, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'microsoft/phi-3-medium-128k-instruct', + displayName: 'Phi-3-medium instruct (128k)', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'microsoft/phi-3-medium-4k-instruct', + displayName: 'Phi-3-medium instruct (4k)', + maxInputTokens: 4096, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'microsoft/phi-3-mini-128k-instruct', + displayName: 'Phi-3-mini instruct (128k)', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'microsoft/phi-3-mini-4k-instruct', + displayName: 'Phi-3-mini instruct (4k)', + maxInputTokens: 4096, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'microsoft/phi-3-small-128k-instruct', + displayName: 'Phi-3-small instruct (128k)', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'microsoft/phi-3-small-8k-instruct', + displayName: 'Phi-3-small instruct (8k)', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'microsoft/phi-3.5-mini-instruct', + displayName: 'Phi-3.5-mini instruct (128k)', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'microsoft/phi-3.5-moe-instruct', + displayName: 'Phi-3.5-MoE instruct (128k)', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'microsoft/phi-3.5-vision-instruct', + displayName: 'Phi-3.5-vision instruct (128k)', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'microsoft/phi-4', + displayName: 'Phi-4', + maxInputTokens: 16000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'microsoft/phi-4-mini-instruct', + displayName: 'Phi-4-mini-instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'microsoft/phi-4-mini-reasoning', + displayName: 'Phi-4-mini-reasoning', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'microsoft/phi-4-multimodal-instruct', + displayName: 'Phi-4-multimodal-instruct', + maxInputTokens: 128000, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'microsoft/phi-4-reasoning', + displayName: 'Phi-4-Reasoning', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral-ai/codestral-2501', + displayName: 'Codestral 25.01', + maxInputTokens: 32000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral-ai/ministral-3b', + displayName: 'Ministral 3B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral-ai/mistral-large-2411', + displayName: 'Mistral Large 24.11', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral-ai/mistral-medium-2505', + displayName: 'Mistral Medium 3 (25.05)', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral-ai/mistral-nemo', + displayName: 'Mistral Nemo', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral-ai/mistral-small-2503', + displayName: 'Mistral Small 3.1', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4.1', + displayName: 'GPT-4.1', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4.1-mini', + displayName: 'GPT-4.1-mini', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4.1-nano', + displayName: 'GPT-4.1-nano', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4o', + displayName: 'GPT-4o', + maxInputTokens: 128000, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4o-mini', + displayName: 'GPT-4o mini', + maxInputTokens: 128000, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/o1', + displayName: 'OpenAI o1', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/o1-mini', + displayName: 'OpenAI o1-mini', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/o1-preview', + displayName: 'OpenAI o1-preview', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/o3', + displayName: 'OpenAI o3', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/o3-mini', + displayName: 'OpenAI o3-mini', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/o4-mini', + displayName: 'OpenAI o4-mini', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'xai/grok-3', + displayName: 'Grok 3', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'xai/grok-3-mini', + displayName: 'Grok 3 Mini', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + gitlab: [ + { + name: 'duo-chat-gpt-5-1', + displayName: 'Agentic Chat (GPT-5.1)', + maxInputTokens: 272000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'duo-chat-gpt-5-2', + displayName: 'Agentic Chat (GPT-5.2)', + maxInputTokens: 272000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'duo-chat-gpt-5-2-codex', + displayName: 'Agentic Chat (GPT-5.2 Codex)', + maxInputTokens: 272000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'duo-chat-gpt-5-codex', + displayName: 'Agentic Chat (GPT-5 Codex)', + maxInputTokens: 272000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'duo-chat-gpt-5-mini', + displayName: 'Agentic Chat (GPT-5 Mini)', + maxInputTokens: 272000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'duo-chat-haiku-4-5', + displayName: 'Agentic Chat (Claude Haiku 4.5)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'duo-chat-opus-4-5', + displayName: 'Agentic Chat (Claude Opus 4.5)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'duo-chat-opus-4-6', + displayName: 'Agentic Chat (Claude Opus 4.6)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'duo-chat-sonnet-4-5', + displayName: 'Agentic Chat (Claude Sonnet 4.5)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'duo-chat-sonnet-4-6', + displayName: 'Agentic Chat (Claude Sonnet 4.6)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + google: [ + { + name: 'gemini-1.5-flash', + displayName: 'Gemini 1.5 Flash', + maxInputTokens: 1000000, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0.075, + outputPerM: 0.3, + cacheReadPerM: 0.01875, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-1.5-flash-8b', + displayName: 'Gemini 1.5 Flash-8B', + maxInputTokens: 1000000, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0.0375, + outputPerM: 0.15, + cacheReadPerM: 0.01, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-1.5-pro', + displayName: 'Gemini 1.5 Pro', + maxInputTokens: 1000000, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 1.25, + outputPerM: 5, + cacheReadPerM: 0.3125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.0-flash', + displayName: 'Gemini 2.0 Flash', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.4, + cacheReadPerM: 0.025, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.0-flash-lite', + displayName: 'Gemini 2.0 Flash Lite', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.075, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-flash', + displayName: 'Gemini 2.5 Flash', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.3, + outputPerM: 2.5, + cacheReadPerM: 0.075, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-flash-image', + displayName: 'Gemini 2.5 Flash Image', + maxInputTokens: 32768, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.3, + outputPerM: 30, + cacheReadPerM: 0.075, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-flash-image-preview', + displayName: 'Gemini 2.5 Flash Image (Preview)', + maxInputTokens: 32768, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.3, + outputPerM: 30, + cacheReadPerM: 0.075, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-flash-lite', + displayName: 'Gemini 2.5 Flash Lite', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.4, + cacheReadPerM: 0.025, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-flash-lite-preview-06-17', + displayName: 'Gemini 2.5 Flash Lite Preview 06-17', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.4, + cacheReadPerM: 0.025, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-flash-lite-preview-09-2025', + displayName: 'Gemini 2.5 Flash Lite Preview 09-25', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.4, + cacheReadPerM: 0.025, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-flash-preview-04-17', + displayName: 'Gemini 2.5 Flash Preview 04-17', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + cacheReadPerM: 0.0375, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-flash-preview-05-20', + displayName: 'Gemini 2.5 Flash Preview 05-20', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + cacheReadPerM: 0.0375, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-flash-preview-09-2025', + displayName: 'Gemini 2.5 Flash Preview 09-25', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.3, + outputPerM: 2.5, + cacheReadPerM: 0.075, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-flash-preview-tts', + displayName: 'Gemini 2.5 Flash Preview TTS', + maxInputTokens: 8000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.5, + outputPerM: 10, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-pro', + displayName: 'Gemini 2.5 Pro', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.31, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-pro-preview-05-06', + displayName: 'Gemini 2.5 Pro Preview 05-06', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.31, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-pro-preview-06-05', + displayName: 'Gemini 2.5 Pro Preview 06-05', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.31, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-pro-preview-tts', + displayName: 'Gemini 2.5 Pro Preview TTS', + maxInputTokens: 8000, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 20, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-3-flash-preview', + displayName: 'Gemini 3 Flash Preview', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.5, + outputPerM: 3, + cacheReadPerM: 0.05, + currency: 'USD', + unit: 'per_million_tokens', + }, + default: true, + }, + { + name: 'gemini-3-pro-preview', + displayName: 'Gemini 3 Pro Preview', + maxInputTokens: 1000000, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 2, + outputPerM: 12, + cacheReadPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-3.1-pro-preview', + displayName: 'Gemini 3.1 Pro Preview', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 2, + outputPerM: 12, + cacheReadPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-3.1-pro-preview-customtools', + displayName: 'Gemini 3.1 Pro Preview Custom Tools', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 2, + outputPerM: 12, + cacheReadPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-embedding-001', + displayName: 'Gemini Embedding 001', + maxInputTokens: 2048, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-flash-latest', + displayName: 'Gemini Flash Latest', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.3, + outputPerM: 2.5, + cacheReadPerM: 0.075, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-flash-lite-latest', + displayName: 'Gemini Flash-Lite Latest', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.4, + cacheReadPerM: 0.025, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-live-2.5-flash', + displayName: 'Gemini Live 2.5 Flash', + maxInputTokens: 128000, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0.5, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-live-2.5-flash-preview-native-audio', + displayName: 'Gemini Live 2.5 Flash Preview Native Audio', + maxInputTokens: 131072, + supportedFileTypes: ['audio'], + pricing: { + inputPerM: 0.5, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + 'google-vertex': [ + { + name: 'deepseek-ai/deepseek-v3.1-maas', + displayName: 'DeepSeek V3.1', + maxInputTokens: 163840, + supportedFileTypes: ['pdf'], + pricing: { + inputPerM: 0.6, + outputPerM: 1.7, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.0-flash', + displayName: 'Gemini 2.0 Flash', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + cacheReadPerM: 0.025, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.0-flash-lite', + displayName: 'Gemini 2.0 Flash Lite', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.075, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-flash', + displayName: 'Gemini 2.5 Flash', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.3, + outputPerM: 2.5, + cacheReadPerM: 0.075, + cacheWritePerM: 0.383, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-flash-lite', + displayName: 'Gemini 2.5 Flash Lite', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.4, + cacheReadPerM: 0.025, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-flash-lite-preview-06-17', + displayName: 'Gemini 2.5 Flash Lite Preview 06-17', + maxInputTokens: 65536, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.4, + cacheReadPerM: 0.025, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-flash-lite-preview-09-2025', + displayName: 'Gemini 2.5 Flash Lite Preview 09-25', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.4, + cacheReadPerM: 0.025, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-flash-preview-04-17', + displayName: 'Gemini 2.5 Flash Preview 04-17', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + cacheReadPerM: 0.0375, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-flash-preview-05-20', + displayName: 'Gemini 2.5 Flash Preview 05-20', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + cacheReadPerM: 0.0375, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-flash-preview-09-2025', + displayName: 'Gemini 2.5 Flash Preview 09-25', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.3, + outputPerM: 2.5, + cacheReadPerM: 0.075, + cacheWritePerM: 0.383, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-pro', + displayName: 'Gemini 2.5 Pro', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.31, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-pro-preview-05-06', + displayName: 'Gemini 2.5 Pro Preview 05-06', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.31, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-pro-preview-06-05', + displayName: 'Gemini 2.5 Pro Preview 06-05', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.31, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-3-flash-preview', + displayName: 'Gemini 3 Flash Preview', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.5, + outputPerM: 3, + cacheReadPerM: 0.05, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-3-pro-preview', + displayName: 'Gemini 3 Pro Preview', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 2, + outputPerM: 12, + cacheReadPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-3.1-pro-preview', + displayName: 'Gemini 3.1 Pro Preview', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 2, + outputPerM: 12, + cacheReadPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-3.1-pro-preview-customtools', + displayName: 'Gemini 3.1 Pro Preview Custom Tools', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 2, + outputPerM: 12, + cacheReadPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-embedding-001', + displayName: 'Gemini Embedding 001', + maxInputTokens: 2048, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-flash-latest', + displayName: 'Gemini Flash Latest', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.3, + outputPerM: 2.5, + cacheReadPerM: 0.075, + cacheWritePerM: 0.383, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-flash-lite-latest', + displayName: 'Gemini Flash-Lite Latest', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.4, + cacheReadPerM: 0.025, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta/llama-3.3-70b-instruct-maas', + displayName: 'Llama 3.3 70B Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.72, + outputPerM: 0.72, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta/llama-4-maverick-17b-128e-instruct-maas', + displayName: 'Llama 4 Maverick 17B 128E Instruct', + maxInputTokens: 524288, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.35, + outputPerM: 1.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-120b-maas', + displayName: 'GPT OSS 120B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.09, + outputPerM: 0.36, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-20b-maas', + displayName: 'GPT OSS 20B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.07, + outputPerM: 0.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-235b-a22b-instruct-2507-maas', + displayName: 'Qwen3 235B A22B Instruct', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.22, + outputPerM: 0.88, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/glm-4.7-maas', + displayName: 'GLM-4.7', + maxInputTokens: 200000, + supportedFileTypes: ['pdf'], + pricing: { + inputPerM: 0.6, + outputPerM: 2.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/glm-5-maas', + displayName: 'GLM-5', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 3.2, + cacheReadPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + 'google-vertex-anthropic': [ + { + name: 'claude-3-5-haiku@20241022', + displayName: 'Claude Haiku 3.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0.8, + outputPerM: 4, + cacheReadPerM: 0.08, + cacheWritePerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-3-5-sonnet@20241022', + displayName: 'Claude Sonnet 3.5 v2', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-3-7-sonnet@20250219', + displayName: 'Claude Sonnet 3.7', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-haiku-4-5@20251001', + displayName: 'Claude Haiku 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1, + outputPerM: 5, + cacheReadPerM: 0.1, + cacheWritePerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-opus-4-1@20250805', + displayName: 'Claude Opus 4.1', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 15, + outputPerM: 75, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-opus-4-5@20251101', + displayName: 'Claude Opus 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-opus-4-6@default', + displayName: 'Claude Opus 4.6', + maxInputTokens: 1000000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-opus-4@20250514', + displayName: 'Claude Opus 4', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 15, + outputPerM: 75, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-sonnet-4-5@20250929', + displayName: 'Claude Sonnet 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-sonnet-4-6@default', + displayName: 'Claude Sonnet 4.6', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-sonnet-4@20250514', + displayName: 'Claude Sonnet 4', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + groq: [ + { + name: 'deepseek-r1-distill-llama-70b', + displayName: 'DeepSeek R1 Distill Llama 70B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.75, + outputPerM: 0.99, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemma2-9b-it', + displayName: 'Gemma 2 9B', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'llama-3.1-8b-instant', + displayName: 'Llama 3.1 8B Instant', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.05, + outputPerM: 0.08, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'llama-3.3-70b-versatile', + displayName: 'Llama 3.3 70B Versatile', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.59, + outputPerM: 0.79, + currency: 'USD', + unit: 'per_million_tokens', + }, + default: true, + }, + { + name: 'llama-guard-3-8b', + displayName: 'Llama Guard 3 8B', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'llama3-70b-8192', + displayName: 'Llama 3 70B', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0.59, + outputPerM: 0.79, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'llama3-8b-8192', + displayName: 'Llama 3 8B', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0.05, + outputPerM: 0.08, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/llama-4-maverick-17b-128e-instruct', + displayName: 'Llama 4 Maverick 17B', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.2, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/llama-4-scout-17b-16e-instruct', + displayName: 'Llama 4 Scout 17B', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.11, + outputPerM: 0.34, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/llama-guard-4-12b', + displayName: 'Llama Guard 4 12B', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.2, + outputPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral-saba-24b', + displayName: 'Mistral Saba 24B', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.79, + outputPerM: 0.79, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2-instruct', + displayName: 'Kimi K2 Instruct', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2-instruct-0905', + displayName: 'Kimi K2 Instruct 0905', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-120b', + displayName: 'GPT OSS 120B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-20b', + displayName: 'GPT OSS 20B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.075, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen-qwq-32b', + displayName: 'Qwen QwQ 32B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.29, + outputPerM: 0.39, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-32b', + displayName: 'Qwen3 32B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.29, + outputPerM: 0.59, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + helicone: [ + { + name: 'chatgpt-4o-latest', + displayName: 'OpenAI ChatGPT-4o', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 5, + outputPerM: 20, + cacheReadPerM: 2.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-3-haiku-20240307', + displayName: 'Anthropic: Claude 3 Haiku', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.25, + outputPerM: 1.25, + cacheReadPerM: 0.03, + cacheWritePerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-3.5-haiku', + displayName: 'Anthropic: Claude 3.5 Haiku', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.7999999999999999, + outputPerM: 4, + cacheReadPerM: 0.08, + cacheWritePerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-3.5-sonnet-v2', + displayName: 'Anthropic: Claude 3.5 Sonnet v2', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.30000000000000004, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-3.7-sonnet', + displayName: 'Anthropic: Claude 3.7 Sonnet', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.30000000000000004, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-4.5-haiku', + displayName: 'Anthropic: Claude 4.5 Haiku', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1, + outputPerM: 5, + cacheReadPerM: 0.09999999999999999, + cacheWritePerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-4.5-opus', + displayName: 'Anthropic: Claude Opus 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-4.5-sonnet', + displayName: 'Anthropic: Claude Sonnet 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.30000000000000004, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-haiku-4-5-20251001', + displayName: 'Anthropic: Claude 4.5 Haiku (20251001)', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1, + outputPerM: 5, + cacheReadPerM: 0.09999999999999999, + cacheWritePerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-opus-4', + displayName: 'Anthropic: Claude Opus 4', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 15, + outputPerM: 75, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-opus-4-1', + displayName: 'Anthropic: Claude Opus 4.1', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 15, + outputPerM: 75, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-opus-4-1-20250805', + displayName: 'Anthropic: Claude Opus 4.1 (20250805)', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 15, + outputPerM: 75, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-sonnet-4', + displayName: 'Anthropic: Claude Sonnet 4', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.30000000000000004, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-sonnet-4-5-20250929', + displayName: 'Anthropic: Claude Sonnet 4.5 (20250929)', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.30000000000000004, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'codex-mini-latest', + displayName: 'OpenAI Codex Mini Latest', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.5, + outputPerM: 6, + cacheReadPerM: 0.375, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-r1-distill-llama-70b', + displayName: 'DeepSeek R1 Distill Llama 70B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.03, + outputPerM: 0.13, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-reasoner', + displayName: 'DeepSeek Reasoner', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.56, + outputPerM: 1.68, + cacheReadPerM: 0.07, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-tng-r1t2-chimera', + displayName: 'DeepSeek TNG R1T2 Chimera', + maxInputTokens: 130000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-v3', + displayName: 'DeepSeek V3', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.56, + outputPerM: 1.68, + cacheReadPerM: 0.07, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-v3.1-terminus', + displayName: 'DeepSeek V3.1 Terminus', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.27, + outputPerM: 1, + cacheReadPerM: 0.21600000000000003, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-v3.2', + displayName: 'DeepSeek V3.2', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.27, + outputPerM: 0.41, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'ernie-4.5-21b-a3b-thinking', + displayName: 'Baidu Ernie 4.5 21B A3B Thinking', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.07, + outputPerM: 0.28, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-flash', + displayName: 'Google Gemini 2.5 Flash', + maxInputTokens: 1048576, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.3, + outputPerM: 2.5, + cacheReadPerM: 0.075, + cacheWritePerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-flash-lite', + displayName: 'Google Gemini 2.5 Flash Lite', + maxInputTokens: 1048576, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.09999999999999999, + outputPerM: 0.39999999999999997, + cacheReadPerM: 0.024999999999999998, + cacheWritePerM: 0.09999999999999999, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-pro', + displayName: 'Google Gemini 2.5 Pro', + maxInputTokens: 1048576, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.3125, + cacheWritePerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-3-pro-preview', + displayName: 'Google Gemini 3 Pro Preview', + maxInputTokens: 1048576, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 2, + outputPerM: 12, + cacheReadPerM: 0.19999999999999998, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemma-3-12b-it', + displayName: 'Google Gemma 3 12B', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.049999999999999996, + outputPerM: 0.09999999999999999, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemma2-9b-it', + displayName: 'Google Gemma 2', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0.01, + outputPerM: 0.03, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-4.6', + displayName: 'Zai GLM-4.6', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.44999999999999996, + outputPerM: 1.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4.1', + displayName: 'OpenAI GPT-4.1', + maxInputTokens: 1047576, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2, + outputPerM: 8, + cacheReadPerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4.1-mini', + displayName: 'OpenAI GPT-4.1 Mini', + maxInputTokens: 1047576, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.39999999999999997, + outputPerM: 1.5999999999999999, + cacheReadPerM: 0.09999999999999999, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4.1-mini-2025-04-14', + displayName: 'OpenAI GPT-4.1 Mini', + maxInputTokens: 1047576, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.39999999999999997, + outputPerM: 1.5999999999999999, + cacheReadPerM: 0.09999999999999999, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4.1-nano', + displayName: 'OpenAI GPT-4.1 Nano', + maxInputTokens: 1047576, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.09999999999999999, + outputPerM: 0.39999999999999997, + cacheReadPerM: 0.024999999999999998, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4o', + displayName: 'OpenAI GPT-4o', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2.5, + outputPerM: 10, + cacheReadPerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4o-mini', + displayName: 'OpenAI GPT-4o-mini', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + cacheReadPerM: 0.075, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5', + displayName: 'OpenAI GPT-5', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.12500000000000003, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5-chat-latest', + displayName: 'OpenAI GPT-5 Chat Latest', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.12500000000000003, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5-codex', + displayName: 'OpenAI: GPT-5 Codex', + maxInputTokens: 400000, + supportedFileTypes: [], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.12500000000000003, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5-mini', + displayName: 'OpenAI GPT-5 Mini', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.25, + outputPerM: 2, + cacheReadPerM: 0.024999999999999998, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5-nano', + displayName: 'OpenAI GPT-5 Nano', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.049999999999999996, + outputPerM: 0.39999999999999997, + cacheReadPerM: 0.005, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5-pro', + displayName: 'OpenAI: GPT-5 Pro', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 15, + outputPerM: 120, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.1', + displayName: 'OpenAI GPT-5.1', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.12500000000000003, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.1-chat-latest', + displayName: 'OpenAI GPT-5.1 Chat', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.12500000000000003, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.1-codex', + displayName: 'OpenAI: GPT-5.1 Codex', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.12500000000000003, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.1-codex-mini', + displayName: 'OpenAI: GPT-5.1 Codex Mini', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.25, + outputPerM: 2, + cacheReadPerM: 0.024999999999999998, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-oss-120b', + displayName: 'OpenAI GPT-OSS 120b', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.04, + outputPerM: 0.16, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-oss-20b', + displayName: 'OpenAI GPT-OSS 20b', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.049999999999999996, + outputPerM: 0.19999999999999998, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'grok-3', + displayName: 'xAI Grok 3', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'grok-3-mini', + displayName: 'xAI Grok 3 Mini', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 0.5, + cacheReadPerM: 0.075, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'grok-4', + displayName: 'xAI Grok 4', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'grok-4-1-fast-non-reasoning', + displayName: 'xAI Grok 4.1 Fast Non-Reasoning', + maxInputTokens: 2000000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.19999999999999998, + outputPerM: 0.5, + cacheReadPerM: 0.049999999999999996, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'grok-4-1-fast-reasoning', + displayName: 'xAI Grok 4.1 Fast Reasoning', + maxInputTokens: 2000000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.19999999999999998, + outputPerM: 0.5, + cacheReadPerM: 0.049999999999999996, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'grok-4-fast-non-reasoning', + displayName: 'xAI Grok 4 Fast Non-Reasoning', + maxInputTokens: 2000000, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0.19999999999999998, + outputPerM: 0.5, + cacheReadPerM: 0.049999999999999996, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'grok-4-fast-reasoning', + displayName: 'xAI: Grok 4 Fast Reasoning', + maxInputTokens: 2000000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.19999999999999998, + outputPerM: 0.5, + cacheReadPerM: 0.049999999999999996, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'grok-code-fast-1', + displayName: 'xAI Grok Code Fast 1', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.19999999999999998, + outputPerM: 1.5, + cacheReadPerM: 0.02, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'hermes-2-pro-llama-3-8b', + displayName: 'Hermes 2 Pro Llama 3 8B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.14, + outputPerM: 0.14, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2-0711', + displayName: 'Kimi K2 (07/11)', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.5700000000000001, + outputPerM: 2.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2-0905', + displayName: 'Kimi K2 (09/05)', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.5, + outputPerM: 2, + cacheReadPerM: 0.39999999999999997, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2-thinking', + displayName: 'Kimi K2 Thinking', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.48, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'llama-3.1-8b-instant', + displayName: 'Meta Llama 3.1 8B Instant', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.049999999999999996, + outputPerM: 0.08, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'llama-3.1-8b-instruct', + displayName: 'Meta Llama 3.1 8B Instruct', + maxInputTokens: 16384, + supportedFileTypes: [], + pricing: { + inputPerM: 0.02, + outputPerM: 0.049999999999999996, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'llama-3.1-8b-instruct-turbo', + displayName: 'Meta Llama 3.1 8B Instruct Turbo', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.02, + outputPerM: 0.03, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'llama-3.3-70b-instruct', + displayName: 'Meta Llama 3.3 70B Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.13, + outputPerM: 0.39, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'llama-3.3-70b-versatile', + displayName: 'Meta Llama 3.3 70B Versatile', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.59, + outputPerM: 0.7899999999999999, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'llama-4-maverick', + displayName: 'Meta Llama 4 Maverick 17B 128E', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'llama-4-scout', + displayName: 'Meta Llama 4 Scout 17B 16E', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.08, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'llama-guard-4', + displayName: 'Meta Llama Guard 4 12B', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.21, + outputPerM: 0.21, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'llama-prompt-guard-2-22m', + displayName: 'Meta Llama Prompt Guard 2 22M', + maxInputTokens: 512, + supportedFileTypes: [], + pricing: { + inputPerM: 0.01, + outputPerM: 0.01, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'llama-prompt-guard-2-86m', + displayName: 'Meta Llama Prompt Guard 2 86M', + maxInputTokens: 512, + supportedFileTypes: [], + pricing: { + inputPerM: 0.01, + outputPerM: 0.01, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral-large-2411', + displayName: 'Mistral-Large', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 2, + outputPerM: 6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral-nemo', + displayName: 'Mistral Nemo', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 20, + outputPerM: 40, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral-small', + displayName: 'Mistral Small', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 75, + outputPerM: 200, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'o1', + displayName: 'OpenAI: o1', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 15, + outputPerM: 60, + cacheReadPerM: 7.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'o1-mini', + displayName: 'OpenAI: o1-mini', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 1.1, + outputPerM: 4.4, + cacheReadPerM: 0.55, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'o3', + displayName: 'OpenAI o3', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2, + outputPerM: 8, + cacheReadPerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'o3-mini', + displayName: 'OpenAI o3 Mini', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 1.1, + outputPerM: 4.4, + cacheReadPerM: 0.55, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'o3-pro', + displayName: 'OpenAI o3 Pro', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 20, + outputPerM: 80, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'o4-mini', + displayName: 'OpenAI o4 Mini', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.1, + outputPerM: 4.4, + cacheReadPerM: 0.275, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen2.5-coder-7b-fast', + displayName: 'Qwen2.5 Coder 7B fast', + maxInputTokens: 32000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.03, + outputPerM: 0.09, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen3-235b-a22b-thinking', + displayName: 'Qwen3 235B A22B Thinking', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.3, + outputPerM: 2.9000000000000004, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen3-30b-a3b', + displayName: 'Qwen3 30B A3B', + maxInputTokens: 41000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.08, + outputPerM: 0.29, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen3-32b', + displayName: 'Qwen3 32B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.29, + outputPerM: 0.59, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen3-coder', + displayName: 'Qwen3 Coder 480B A35B Instruct Turbo', + maxInputTokens: 262144, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0.22, + outputPerM: 0.95, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen3-coder-30b-a3b-instruct', + displayName: 'Qwen3 Coder 30B A3B Instruct', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.09999999999999999, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen3-next-80b-a3b-instruct', + displayName: 'Qwen3 Next 80B A3B Instruct', + maxInputTokens: 262000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.14, + outputPerM: 1.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen3-vl-235b-a22b-instruct', + displayName: 'Qwen3 VL 235B A22B Instruct', + maxInputTokens: 256000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.3, + outputPerM: 1.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'sonar', + displayName: 'Perplexity Sonar', + maxInputTokens: 127000, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'sonar-deep-research', + displayName: 'Perplexity Sonar Deep Research', + maxInputTokens: 127000, + supportedFileTypes: [], + pricing: { + inputPerM: 2, + outputPerM: 8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'sonar-pro', + displayName: 'Perplexity Sonar Pro', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 3, + outputPerM: 15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'sonar-reasoning', + displayName: 'Perplexity Sonar Reasoning', + maxInputTokens: 127000, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'sonar-reasoning-pro', + displayName: 'Perplexity Sonar Reasoning Pro', + maxInputTokens: 127000, + supportedFileTypes: [], + pricing: { + inputPerM: 2, + outputPerM: 8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + huggingface: [ + { + name: 'deepseek-ai/DeepSeek-R1-0528', + displayName: 'DeepSeek-R1-0528', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 3, + outputPerM: 5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/DeepSeek-V3.2', + displayName: 'DeepSeek-V3.2', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.28, + outputPerM: 0.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'MiniMaxAI/MiniMax-M2.1', + displayName: 'MiniMax-M2.1', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'MiniMaxAI/MiniMax-M2.5', + displayName: 'MiniMax-M2.5', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + cacheReadPerM: 0.03, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/Kimi-K2-Instruct', + displayName: 'Kimi-K2-Instruct', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/Kimi-K2-Instruct-0905', + displayName: 'Kimi-K2-Instruct-0905', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/Kimi-K2-Thinking', + displayName: 'Kimi-K2-Thinking', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.5, + cacheReadPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/Kimi-K2.5', + displayName: 'Kimi-K2.5', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.6, + outputPerM: 3, + cacheReadPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-235B-A22B-Thinking-2507', + displayName: 'Qwen3-235B-A22B-Thinking-2507', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-Coder-480B-A35B-Instruct', + displayName: 'Qwen3-Coder-480B-A35B-Instruct', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 2, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-Coder-Next', + displayName: 'Qwen3-Coder-Next', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 1.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-Embedding-4B', + displayName: 'Qwen 3 Embedding 4B', + maxInputTokens: 32000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.01, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-Embedding-8B', + displayName: 'Qwen 3 Embedding 8B', + maxInputTokens: 32000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.01, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-Next-80B-A3B-Instruct', + displayName: 'Qwen3-Next-80B-A3B-Instruct', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.25, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-Next-80B-A3B-Thinking', + displayName: 'Qwen3-Next-80B-A3B-Thinking', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3.5-397B-A17B', + displayName: 'Qwen3.5-397B-A17B', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.6, + outputPerM: 3.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'XiaomiMiMo/MiMo-V2-Flash', + displayName: 'MiMo-V2-Flash', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-4.7', + displayName: 'GLM-4.7', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.2, + cacheReadPerM: 0.11, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-4.7-Flash', + displayName: 'GLM-4.7-Flash', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-5', + displayName: 'GLM-5', + maxInputTokens: 202752, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 3.2, + cacheReadPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + iflowcn: [ + { + name: 'deepseek-r1', + displayName: 'DeepSeek-R1', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-v3', + displayName: 'DeepSeek-V3', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-v3.2', + displayName: 'DeepSeek-V3.2-Exp', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-4.6', + displayName: 'GLM-4.6', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2', + displayName: 'Kimi-K2', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2-0905', + displayName: 'Kimi-K2-0905', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen3-235b', + displayName: 'Qwen3-235B-A22B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen3-235b-a22b-instruct', + displayName: 'Qwen3-235B-A22B-Instruct', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen3-235b-a22b-thinking-2507', + displayName: 'Qwen3-235B-A22B-Thinking', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen3-32b', + displayName: 'Qwen3-32B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen3-coder-plus', + displayName: 'Qwen3-Coder-Plus', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen3-max', + displayName: 'Qwen3-Max', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen3-max-preview', + displayName: 'Qwen3-Max-Preview', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen3-vl-plus', + displayName: 'Qwen3-VL-Plus', + maxInputTokens: 256000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + inception: [ + { + name: 'mercury', + displayName: 'Mercury', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.25, + outputPerM: 1, + cacheReadPerM: 0.25, + cacheWritePerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mercury-coder', + displayName: 'Mercury Coder', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.25, + outputPerM: 1, + cacheReadPerM: 0.25, + cacheWritePerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + inference: [ + { + name: 'google/gemma-3', + displayName: 'Google Gemma 3', + maxInputTokens: 125000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.15, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta/llama-3.1-8b-instruct', + displayName: 'Llama 3.1 8B Instruct', + maxInputTokens: 16000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.025, + outputPerM: 0.025, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta/llama-3.2-11b-vision-instruct', + displayName: 'Llama 3.2 11B Vision Instruct', + maxInputTokens: 16000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.055, + outputPerM: 0.055, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta/llama-3.2-1b-instruct', + displayName: 'Llama 3.2 1B Instruct', + maxInputTokens: 16000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.01, + outputPerM: 0.01, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta/llama-3.2-3b-instruct', + displayName: 'Llama 3.2 3B Instruct', + maxInputTokens: 16000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.02, + outputPerM: 0.02, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral/mistral-nemo-12b-instruct', + displayName: 'Mistral Nemo 12B Instruct', + maxInputTokens: 16000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.038, + outputPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'osmosis/osmosis-structure-0.6b', + displayName: 'Osmosis Structure 0.6B', + maxInputTokens: 4000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen-2.5-7b-vision-instruct', + displayName: 'Qwen 2.5 7B Vision Instruct', + maxInputTokens: 125000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.2, + outputPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-embedding-4b', + displayName: 'Qwen 3 Embedding 4B', + maxInputTokens: 32000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.01, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + 'io-net': [ + { + name: 'deepseek-ai/DeepSeek-R1-0528', + displayName: 'DeepSeek R1', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 2, + outputPerM: 8.75, + cacheReadPerM: 1, + cacheWritePerM: 4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Intel/Qwen3-Coder-480B-A35B-Instruct-int4-mixed-ar', + displayName: 'Qwen 3 Coder 480B', + maxInputTokens: 106000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.22, + outputPerM: 0.95, + cacheReadPerM: 0.11, + cacheWritePerM: 0.44, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/Llama-3.2-90B-Vision-Instruct', + displayName: 'Llama 3.2 90B Vision Instruct', + maxInputTokens: 16000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.35, + outputPerM: 0.4, + cacheReadPerM: 0.175, + cacheWritePerM: 0.7, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/Llama-3.3-70B-Instruct', + displayName: 'Llama 3.3 70B Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.13, + outputPerM: 0.38, + cacheReadPerM: 0.065, + cacheWritePerM: 0.26, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/Llama-4-Maverick-17B-128E-Instruct-FP8', + displayName: 'Llama 4 Maverick 17B 128E Instruct', + maxInputTokens: 430000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + cacheReadPerM: 0.075, + cacheWritePerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/Devstral-Small-2505', + displayName: 'Devstral Small 2505', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.05, + outputPerM: 0.22, + cacheReadPerM: 0.025, + cacheWritePerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/Magistral-Small-2506', + displayName: 'Magistral Small 2506', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.5, + outputPerM: 1.5, + cacheReadPerM: 0.25, + cacheWritePerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/Mistral-Large-Instruct-2411', + displayName: 'Mistral Large Instruct 2411', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2, + outputPerM: 6, + cacheReadPerM: 1, + cacheWritePerM: 4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/Mistral-Nemo-Instruct-2407', + displayName: 'Mistral Nemo Instruct 2407', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.02, + outputPerM: 0.04, + cacheReadPerM: 0.01, + cacheWritePerM: 0.04, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/Kimi-K2-Instruct-0905', + displayName: 'Kimi K2 Instruct', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.39, + outputPerM: 1.9, + cacheReadPerM: 0.195, + cacheWritePerM: 0.78, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/Kimi-K2-Thinking', + displayName: 'Kimi K2 Thinking', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.55, + outputPerM: 2.25, + cacheReadPerM: 0.275, + cacheWritePerM: 1.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-120b', + displayName: 'GPT-OSS 120B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.04, + outputPerM: 0.4, + cacheReadPerM: 0.02, + cacheWritePerM: 0.08, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-20b', + displayName: 'GPT-OSS 20B', + maxInputTokens: 64000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.03, + outputPerM: 0.14, + cacheReadPerM: 0.015, + cacheWritePerM: 0.06, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen2.5-VL-32B-Instruct', + displayName: 'Qwen 2.5 VL 32B Instruct', + maxInputTokens: 32000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.05, + outputPerM: 0.22, + cacheReadPerM: 0.025, + cacheWritePerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-235B-A22B-Thinking-2507', + displayName: 'Qwen 3 235B Thinking', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.11, + outputPerM: 0.6, + cacheReadPerM: 0.055, + cacheWritePerM: 0.22, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-Next-80B-A3B-Instruct', + displayName: 'Qwen 3 Next 80B Instruct', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.8, + cacheReadPerM: 0.05, + cacheWritePerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-4.6', + displayName: 'GLM 4.6', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.4, + outputPerM: 1.75, + cacheReadPerM: 0.2, + cacheWritePerM: 0.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + jiekou: [ + { + name: 'baidu/ernie-4.5-300b-a47b-paddle', + displayName: 'ERNIE 4.5 300B A47B', + maxInputTokens: 123000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.28, + outputPerM: 1.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'baidu/ernie-4.5-vl-424b-a47b', + displayName: 'ERNIE 4.5 VL 424B A47B', + maxInputTokens: 123000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.42, + outputPerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-haiku-4-5-20251001', + displayName: 'claude-haiku-4-5-20251001', + maxInputTokens: 20000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.9, + outputPerM: 4.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-opus-4-1-20250805', + displayName: 'claude-opus-4-1-20250805', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 13.5, + outputPerM: 67.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-opus-4-20250514', + displayName: 'claude-opus-4-20250514', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 13.5, + outputPerM: 67.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-opus-4-5-20251101', + displayName: 'claude-opus-4-5-20251101', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 4.5, + outputPerM: 22.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-opus-4-6', + displayName: 'claude-opus-4-6', + maxInputTokens: 1000000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 5, + outputPerM: 25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-sonnet-4-20250514', + displayName: 'claude-sonnet-4-20250514', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2.7, + outputPerM: 13.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-sonnet-4-5-20250929', + displayName: 'claude-sonnet-4-5-20250929', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2.7, + outputPerM: 13.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-r1-0528', + displayName: 'DeepSeek R1 0528', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.7, + outputPerM: 2.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-v3-0324', + displayName: 'DeepSeek V3 0324', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.28, + outputPerM: 1.14, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-v3.1', + displayName: 'DeepSeek V3.1', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.27, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-flash', + displayName: 'gemini-2.5-flash', + maxInputTokens: 1048576, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0.27, + outputPerM: 2.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-flash-lite', + displayName: 'gemini-2.5-flash-lite', + maxInputTokens: 1048576, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0.09, + outputPerM: 0.36, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-flash-lite-preview-06-17', + displayName: 'gemini-2.5-flash-lite-preview-06-17', + maxInputTokens: 1048576, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0.09, + outputPerM: 0.36, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-flash-lite-preview-09-2025', + displayName: 'gemini-2.5-flash-lite-preview-09-2025', + maxInputTokens: 1048576, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0.09, + outputPerM: 0.36, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-flash-preview-05-20', + displayName: 'gemini-2.5-flash-preview-05-20', + maxInputTokens: 1048576, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0.135, + outputPerM: 3.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-pro', + displayName: 'gemini-2.5-pro', + maxInputTokens: 1048576, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 1.125, + outputPerM: 9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-pro-preview-06-05', + displayName: 'gemini-2.5-pro-preview-06-05', + maxInputTokens: 1048576, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 1.125, + outputPerM: 9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-3-flash-preview', + displayName: 'gemini-3-flash-preview', + maxInputTokens: 1048576, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0.5, + outputPerM: 3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-3-pro-preview', + displayName: 'gemini-3-pro-preview', + maxInputTokens: 1048576, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 1.8, + outputPerM: 10.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5-chat-latest', + displayName: 'gpt-5-chat-latest', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.125, + outputPerM: 9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5-codex', + displayName: 'gpt-5-codex', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.125, + outputPerM: 9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5-mini', + displayName: 'gpt-5-mini', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.225, + outputPerM: 1.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5-nano', + displayName: 'gpt-5-nano', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.045, + outputPerM: 0.36, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5-pro', + displayName: 'gpt-5-pro', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 13.5, + outputPerM: 108, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.1', + displayName: 'gpt-5.1', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.125, + outputPerM: 9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.1-codex', + displayName: 'gpt-5.1-codex', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.125, + outputPerM: 9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.1-codex-max', + displayName: 'gpt-5.1-codex-max', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.125, + outputPerM: 9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.1-codex-mini', + displayName: 'gpt-5.1-codex-mini', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.225, + outputPerM: 1.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.2', + displayName: 'gpt-5.2', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.575, + outputPerM: 12.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.2-codex', + displayName: 'gpt-5.2-codex', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.75, + outputPerM: 14, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.2-pro', + displayName: 'gpt-5.2-pro', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 18.9, + outputPerM: 151.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'grok-4-0709', + displayName: 'grok-4-0709', + maxInputTokens: 256000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2.7, + outputPerM: 13.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'grok-4-1-fast-non-reasoning', + displayName: 'grok-4-1-fast-non-reasoning', + maxInputTokens: 2000000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.18, + outputPerM: 0.45, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'grok-4-1-fast-reasoning', + displayName: 'grok-4-1-fast-reasoning', + maxInputTokens: 2000000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.18, + outputPerM: 0.45, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'grok-4-fast-non-reasoning', + displayName: 'grok-4-fast-non-reasoning', + maxInputTokens: 2000000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.18, + outputPerM: 0.45, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'grok-4-fast-reasoning', + displayName: 'grok-4-fast-reasoning', + maxInputTokens: 2000000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.18, + outputPerM: 0.45, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'grok-code-fast-1', + displayName: 'grok-code-fast-1', + maxInputTokens: 256000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.18, + outputPerM: 1.35, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'minimax/minimax-m2.1', + displayName: 'Minimax M2.1', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'minimaxai/minimax-m1-80k', + displayName: 'MiniMax M1', + maxInputTokens: 1000000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.55, + outputPerM: 2.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2-0905', + displayName: 'Kimi K2 0905', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2-instruct', + displayName: 'Kimi K2 Instruct', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.57, + outputPerM: 2.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2.5', + displayName: 'Kimi K2.5', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.6, + outputPerM: 3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'o3', + displayName: 'o3', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 10, + outputPerM: 40, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'o3-mini', + displayName: 'o3-mini', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.1, + outputPerM: 4.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'o4-mini', + displayName: 'o4-mini', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.1, + outputPerM: 4.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-235b-a22b-fp8', + displayName: 'Qwen3 235B A22B', + maxInputTokens: 40960, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-235b-a22b-instruct-2507', + displayName: 'Qwen3 235B A22B Instruct 2507', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-235b-a22b-thinking-2507', + displayName: 'Qwen3 235B A22b Thinking 2507', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-30b-a3b-fp8', + displayName: 'Qwen3 30B A3B', + maxInputTokens: 40960, + supportedFileTypes: [], + pricing: { + inputPerM: 0.09, + outputPerM: 0.45, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-32b-fp8', + displayName: 'Qwen3 32B', + maxInputTokens: 40960, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.45, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-coder-480b-a35b-instruct', + displayName: 'Qwen3 Coder 480B A35B Instruct', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.29, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-coder-next', + displayName: 'qwen/qwen3-coder-next', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 1.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-next-80b-a3b-instruct', + displayName: 'Qwen3 Next 80B A3B Instruct', + maxInputTokens: 65536, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 1.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-next-80b-a3b-thinking', + displayName: 'Qwen3 Next 80B A3B Thinking', + maxInputTokens: 65536, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 1.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'xiaomimimo/mimo-v2-flash', + displayName: 'XiaomiMiMo/MiMo-V2-Flash', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/glm-4.5', + displayName: 'GLM-4.5', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/glm-4.5v', + displayName: 'GLM 4.5V', + maxInputTokens: 65536, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.6, + outputPerM: 1.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/glm-4.7', + displayName: 'GLM-4.7', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/glm-4.7-flash', + displayName: 'GLM-4.7-Flash', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.07, + outputPerM: 0.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + kilo: [ + { + name: 'allenai/molmo-2-8b', + displayName: 'AllenAI: Molmo2 8B', + maxInputTokens: 36864, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.2, + outputPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'amazon/nova-2-lite-v1', + displayName: 'Amazon: Nova 2 Lite', + maxInputTokens: 1000000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.3, + outputPerM: 2.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'amazon/nova-pro-v1', + displayName: 'Amazon: Nova Pro 1.0', + maxInputTokens: 300000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.8, + outputPerM: 3.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-3-haiku', + displayName: 'Anthropic: Claude 3 Haiku', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.25, + outputPerM: 1.25, + cacheReadPerM: 0.03, + cacheWritePerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-3.5-haiku', + displayName: 'Anthropic: Claude 3.5 Haiku', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.8, + outputPerM: 4, + cacheReadPerM: 0.08, + cacheWritePerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-3.5-sonnet', + displayName: 'Anthropic: Claude 3.5 Sonnet', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 6, + outputPerM: 30, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-3.7-sonnet', + displayName: 'Anthropic: Claude 3.7 Sonnet', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-3.7-sonnet:thinking', + displayName: 'Anthropic: Claude 3.7 Sonnet (thinking)', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-haiku-4.5', + displayName: 'Anthropic: Claude Haiku 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1, + outputPerM: 5, + cacheReadPerM: 0.1, + cacheWritePerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-opus-4', + displayName: 'Anthropic: Claude Opus 4', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 15, + outputPerM: 75, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-opus-4.1', + displayName: 'Anthropic: Claude Opus 4.1', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 15, + outputPerM: 75, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-opus-4.5', + displayName: 'Anthropic: Claude Opus 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-opus-4.6', + displayName: 'Anthropic: Claude Opus 4.6', + maxInputTokens: 1000000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-sonnet-4', + displayName: 'Anthropic: Claude Sonnet 4', + maxInputTokens: 1000000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-sonnet-4.5', + displayName: 'Anthropic: Claude Sonnet 4.5', + maxInputTokens: 1000000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'arcee-ai/trinity-large-preview:free', + displayName: 'Arcee AI: Trinity Large Preview (free)', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'arcee-ai/trinity-mini', + displayName: 'Arcee AI: Trinity Mini', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.045, + outputPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'arcee-ai/trinity-mini:free', + displayName: 'Arcee AI: Trinity Mini (free)', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'baidu/ernie-4.5-21b-a3b', + displayName: 'Baidu: ERNIE 4.5 21B A3B', + maxInputTokens: 120000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.07, + outputPerM: 0.28, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'baidu/ernie-4.5-21b-a3b-thinking', + displayName: 'Baidu: ERNIE 4.5 21B A3B Thinking', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.07, + outputPerM: 0.28, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'baidu/ernie-4.5-300b-a47b', + displayName: 'Baidu: ERNIE 4.5 300B A47B ', + maxInputTokens: 123000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.28, + outputPerM: 1.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'baidu/ernie-4.5-vl-28b-a3b', + displayName: 'Baidu: ERNIE 4.5 VL 28B A3B', + maxInputTokens: 30000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.14, + outputPerM: 0.56, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'baidu/ernie-4.5-vl-424b-a47b', + displayName: 'Baidu: ERNIE 4.5 VL 424B A47B ', + maxInputTokens: 123000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.42, + outputPerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'bytedance-seed/seed-1.6', + displayName: 'ByteDance Seed: Seed 1.6', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.25, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'cognitivecomputations/dolphin-mistral-24b-venice-edition:free', + displayName: 'Venice: Uncensored (free)', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'cohere/command-a', + displayName: 'Cohere: Command A', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 2.5, + outputPerM: 10, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'cohere/command-r-08-2024', + displayName: 'Cohere: Command R (08-2024)', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'cohere/command-r-plus-08-2024', + displayName: 'Cohere: Command R+ (08-2024)', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 2.5, + outputPerM: 10, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'cohere/command-r7b-12-2024', + displayName: 'Cohere: Command R7B (12-2024)', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.0375, + outputPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-chat', + displayName: 'DeepSeek: DeepSeek V3', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + cacheReadPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-chat-v3-0324', + displayName: 'DeepSeek: DeepSeek V3 0324', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.19, + outputPerM: 0.87, + cacheReadPerM: 0.095, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-chat-v3.1', + displayName: 'DeepSeek: DeepSeek V3.1', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-r1', + displayName: 'DeepSeek: R1', + maxInputTokens: 64000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.7, + outputPerM: 2.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-r1-0528', + displayName: 'DeepSeek: R1 0528', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.4, + outputPerM: 1.75, + cacheReadPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-r1-0528:free', + displayName: 'DeepSeek: R1 0528 (free)', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-r1-distill-llama-70b', + displayName: 'DeepSeek: R1 Distill Llama 70B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.03, + outputPerM: 0.11, + cacheReadPerM: 0.015, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-r1-distill-qwen-32b', + displayName: 'DeepSeek: R1 Distill Qwen 32B', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.29, + outputPerM: 0.29, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-v3.1-terminus', + displayName: 'DeepSeek: DeepSeek V3.1 Terminus', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.21, + outputPerM: 0.79, + cacheReadPerM: 0.13, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-v3.1-terminus:exacto', + displayName: 'DeepSeek: DeepSeek V3.1 Terminus (exacto)', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.21, + outputPerM: 0.79, + cacheReadPerM: 0.168, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-v3.2', + displayName: 'DeepSeek: DeepSeek V3.2', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.25, + outputPerM: 0.38, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-v3.2-exp', + displayName: 'DeepSeek: DeepSeek V3.2 Exp', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.27, + outputPerM: 0.41, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-v3.2-speciale', + displayName: 'DeepSeek: DeepSeek V3.2 Speciale', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.27, + outputPerM: 0.41, + cacheReadPerM: 0.135, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'essentialai/rnj-1-instruct', + displayName: 'EssentialAI: Rnj 1 Instruct', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.0-flash-001', + displayName: 'Google: Gemini 2.0 Flash', + maxInputTokens: 1048576, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.4, + cacheReadPerM: 0.025, + cacheWritePerM: 0.083333, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.0-flash-lite-001', + displayName: 'Google: Gemini 2.0 Flash Lite', + maxInputTokens: 1048576, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0.075, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.5-flash', + displayName: 'Google: Gemini 2.5 Flash', + maxInputTokens: 1048576, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0.3, + outputPerM: 2.5, + cacheReadPerM: 0.03, + cacheWritePerM: 0.083333, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.5-flash-lite', + displayName: 'Google: Gemini 2.5 Flash Lite', + maxInputTokens: 1048576, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.4, + cacheReadPerM: 0.01, + cacheWritePerM: 0.083333, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.5-flash-lite-preview-09-2025', + displayName: 'Google: Gemini 2.5 Flash Lite Preview 09-2025', + maxInputTokens: 1048576, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.4, + cacheReadPerM: 0.01, + cacheWritePerM: 0.083333, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.5-flash-preview-09-2025', + displayName: 'Google: Gemini 2.5 Flash Preview 09-2025', + maxInputTokens: 1048576, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0.3, + outputPerM: 2.5, + cacheReadPerM: 0.03, + cacheWritePerM: 0.083333, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.5-pro', + displayName: 'Google: Gemini 2.5 Pro', + maxInputTokens: 1048576, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.125, + cacheWritePerM: 0.375, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.5-pro-preview', + displayName: 'Google: Gemini 2.5 Pro Preview 06-05', + maxInputTokens: 1048576, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.125, + cacheWritePerM: 0.375, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.5-pro-preview-05-06', + displayName: 'Google: Gemini 2.5 Pro Preview 05-06', + maxInputTokens: 1048576, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.125, + cacheWritePerM: 0.375, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-3-flash-preview', + displayName: 'Google: Gemini 3 Flash Preview', + maxInputTokens: 1048576, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0.5, + outputPerM: 3, + cacheReadPerM: 0.05, + cacheWritePerM: 0.083333, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-3-pro-preview', + displayName: 'Google: Gemini 3 Pro Preview', + maxInputTokens: 1048576, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 2, + outputPerM: 12, + cacheReadPerM: 0.2, + cacheWritePerM: 0.375, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-2-27b-it', + displayName: 'Google: Gemma 2 27B', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0.65, + outputPerM: 0.65, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-2-9b-it', + displayName: 'Google: Gemma 2 9B', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0.03, + outputPerM: 0.09, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-3-12b-it', + displayName: 'Google: Gemma 3 12B', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.03, + outputPerM: 0.1, + cacheReadPerM: 0.015, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-3-12b-it:free', + displayName: 'Google: Gemma 3 12B (free)', + maxInputTokens: 32768, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-3-27b-it', + displayName: 'Google: Gemma 3 27B', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.04, + outputPerM: 0.15, + cacheReadPerM: 0.02, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-3-27b-it:free', + displayName: 'Google: Gemma 3 27B (free)', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-3-4b-it', + displayName: 'Google: Gemma 3 4B', + maxInputTokens: 96000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.01703, + outputPerM: 0.068154, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-3-4b-it:free', + displayName: 'Google: Gemma 3 4B (free)', + maxInputTokens: 32768, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-3n-e2b-it:free', + displayName: 'Google: Gemma 3n 2B (free)', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-3n-e4b-it', + displayName: 'Google: Gemma 3n 4B', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.02, + outputPerM: 0.04, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-3n-e4b-it:free', + displayName: 'Google: Gemma 3n 4B (free)', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gryphe/mythomax-l2-13b', + displayName: 'MythoMax 13B', + maxInputTokens: 4096, + supportedFileTypes: [], + pricing: { + inputPerM: 0.06, + outputPerM: 0.06, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'inception/mercury', + displayName: 'Inception: Mercury', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.25, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'inception/mercury-coder', + displayName: 'Inception: Mercury Coder', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.25, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kilo/auto', + displayName: 'Kilo: Auto', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kwaipilot/kat-coder-pro', + displayName: 'Kwaipilot: KAT-Coder-Pro V1', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.207, + outputPerM: 0.828, + cacheReadPerM: 0.0414, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'liquid/lfm-2.5-1.2b-instruct:free', + displayName: 'LiquidAI: LFM2.5-1.2B-Instruct (free)', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'liquid/lfm-2.5-1.2b-thinking:free', + displayName: 'LiquidAI: LFM2.5-1.2B-Thinking (free)', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meituan/longcat-flash-chat', + displayName: 'Meituan: LongCat Flash Chat', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.8, + cacheReadPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/llama-3-70b-instruct', + displayName: 'Meta: Llama 3 70B Instruct', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0.51, + outputPerM: 0.74, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/llama-3-8b-instruct', + displayName: 'Meta: Llama 3 8B Instruct', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0.03, + outputPerM: 0.04, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/llama-3.1-405b-instruct', + displayName: 'Meta: Llama 3.1 405B Instruct', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 4, + outputPerM: 4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/llama-3.1-70b-instruct', + displayName: 'Meta: Llama 3.1 70B Instruct', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.4, + outputPerM: 0.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/llama-3.1-8b-instruct', + displayName: 'Meta: Llama 3.1 8B Instruct', + maxInputTokens: 16384, + supportedFileTypes: [], + pricing: { + inputPerM: 0.02, + outputPerM: 0.05, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/llama-3.2-11b-vision-instruct', + displayName: 'Meta: Llama 3.2 11B Vision Instruct', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.049, + outputPerM: 0.049, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/llama-3.2-1b-instruct', + displayName: 'Meta: Llama 3.2 1B Instruct', + maxInputTokens: 60000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.027, + outputPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/llama-3.2-3b-instruct', + displayName: 'Meta: Llama 3.2 3B Instruct', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.02, + outputPerM: 0.02, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/llama-3.2-3b-instruct:free', + displayName: 'Meta: Llama 3.2 3B Instruct (free)', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/llama-3.3-70b-instruct', + displayName: 'Meta: Llama 3.3 70B Instruct', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.32, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/llama-3.3-70b-instruct:free', + displayName: 'Meta: Llama 3.3 70B Instruct (free)', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/llama-4-maverick', + displayName: 'Meta: Llama 4 Maverick', + maxInputTokens: 1048576, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/llama-4-scout', + displayName: 'Meta: Llama 4 Scout', + maxInputTokens: 327680, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.08, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/llama-guard-3-8b', + displayName: 'Llama Guard 3 8B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.02, + outputPerM: 0.06, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/llama-guard-4-12b', + displayName: 'Meta: Llama Guard 4 12B', + maxInputTokens: 163840, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.18, + outputPerM: 0.18, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'microsoft/phi-4', + displayName: 'Microsoft: Phi 4', + maxInputTokens: 16384, + supportedFileTypes: [], + pricing: { + inputPerM: 0.06, + outputPerM: 0.14, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'microsoft/wizardlm-2-8x22b', + displayName: 'WizardLM-2 8x22B', + maxInputTokens: 65535, + supportedFileTypes: [], + pricing: { + inputPerM: 0.62, + outputPerM: 0.62, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'minimax/minimax-01', + displayName: 'MiniMax: MiniMax-01', + maxInputTokens: 1000192, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.2, + outputPerM: 1.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'minimax/minimax-m1', + displayName: 'MiniMax: MiniMax M1', + maxInputTokens: 1000000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.4, + outputPerM: 2.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'minimax/minimax-m2', + displayName: 'MiniMax: MiniMax M2', + maxInputTokens: 196608, + supportedFileTypes: [], + pricing: { + inputPerM: 0.255, + outputPerM: 1, + cacheReadPerM: 0.03, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'minimax/minimax-m2.1', + displayName: 'MiniMax: MiniMax M2.1', + maxInputTokens: 196608, + supportedFileTypes: [], + pricing: { + inputPerM: 0.27, + outputPerM: 0.95, + cacheReadPerM: 0.03, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'minimax/minimax-m2.5', + displayName: 'MiniMax: MiniMax M2.5', + maxInputTokens: 196608, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + cacheReadPerM: 0.029, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'minimax/minimax-m2.5:free', + displayName: 'MiniMax: MiniMax M2.5 (free)', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/codestral-2508', + displayName: 'Mistral: Codestral 2508', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 0.9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/devstral-2512', + displayName: 'Mistral: Devstral 2 2512', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.05, + outputPerM: 0.22, + cacheReadPerM: 0.025, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/devstral-medium', + displayName: 'Mistral: Devstral Medium', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.4, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/devstral-small', + displayName: 'Mistral: Devstral Small 1.1', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/ministral-14b-2512', + displayName: 'Mistral: Ministral 3 14B 2512', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.2, + outputPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/mistral-7b-instruct', + displayName: 'Mistral: Mistral 7B Instruct', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/mistral-7b-instruct-v0.1', + displayName: 'Mistral: Mistral 7B Instruct v0.1', + maxInputTokens: 2824, + supportedFileTypes: [], + pricing: { + inputPerM: 0.11, + outputPerM: 0.19, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/mistral-7b-instruct-v0.3', + displayName: 'Mistral: Mistral 7B Instruct v0.3', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/mistral-large', + displayName: 'Mistral Large', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 2, + outputPerM: 6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/mistral-large-2411', + displayName: 'Mistral Large 2411', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 2, + outputPerM: 6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/mistral-large-2512', + displayName: 'Mistral: Mistral Large 3 2512', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.5, + outputPerM: 1.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/mistral-medium-3', + displayName: 'Mistral: Mistral Medium 3', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.4, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/mistral-medium-3.1', + displayName: 'Mistral: Mistral Medium 3.1', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.4, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/mistral-nemo', + displayName: 'Mistral: Mistral Nemo', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.02, + outputPerM: 0.04, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/mistral-small-24b-instruct-2501', + displayName: 'Mistral: Mistral Small 3', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.05, + outputPerM: 0.08, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/mistral-small-3.1-24b-instruct', + displayName: 'Mistral: Mistral Small 3.1 24B', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.03, + outputPerM: 0.11, + cacheReadPerM: 0.015, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/mistral-small-3.1-24b-instruct:free', + displayName: 'Mistral: Mistral Small 3.1 24B (free)', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/mistral-small-3.2-24b-instruct', + displayName: 'Mistral: Mistral Small 3.2 24B', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.06, + outputPerM: 0.18, + cacheReadPerM: 0.03, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/mixtral-8x22b-instruct', + displayName: 'Mistral: Mixtral 8x22B Instruct', + maxInputTokens: 65536, + supportedFileTypes: [], + pricing: { + inputPerM: 2, + outputPerM: 6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/voxtral-small-24b-2507', + displayName: 'Mistral: Voxtral Small 24B 2507', + maxInputTokens: 32000, + supportedFileTypes: ['audio'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2', + displayName: 'MoonshotAI: Kimi K2 0711', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.5, + outputPerM: 2.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2-0905', + displayName: 'MoonshotAI: Kimi K2 0905', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.4, + outputPerM: 2, + cacheReadPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2-0905:exacto', + displayName: 'MoonshotAI: Kimi K2 0905 (exacto)', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2-thinking', + displayName: 'MoonshotAI: Kimi K2 Thinking', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.4, + outputPerM: 1.75, + cacheReadPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2.5', + displayName: 'MoonshotAI: Kimi K2.5', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.23, + outputPerM: 3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'morph/morph-v3-fast', + displayName: 'Morph: Morph V3 Fast', + maxInputTokens: 81920, + supportedFileTypes: [], + pricing: { + inputPerM: 0.8, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'morph/morph-v3-large', + displayName: 'Morph: Morph V3 Large', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.9, + outputPerM: 1.9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nex-agi/deepseek-v3.1-nex-n1', + displayName: 'Nex AGI: DeepSeek V3.1 Nex N1', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.27, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nousresearch/deephermes-3-mistral-24b-preview', + displayName: 'Nous: DeepHermes 3 Mistral 24B Preview', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.02, + outputPerM: 0.1, + cacheReadPerM: 0.01, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nousresearch/hermes-2-pro-llama-3-8b', + displayName: 'NousResearch: Hermes 2 Pro - Llama-3 8B', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0.14, + outputPerM: 0.14, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nousresearch/hermes-3-llama-3.1-405b', + displayName: 'Nous: Hermes 3 405B Instruct', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nousresearch/hermes-3-llama-3.1-405b:free', + displayName: 'Nous: Hermes 3 405B Instruct (free)', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nousresearch/hermes-4-405b', + displayName: 'Nous: Hermes 4 405B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nousresearch/hermes-4-70b', + displayName: 'Nous: Hermes 4 70B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.11, + outputPerM: 0.38, + cacheReadPerM: 0.055, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nvidia/llama-3.1-nemotron-70b-instruct', + displayName: 'NVIDIA: Llama 3.1 Nemotron 70B Instruct', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 1.2, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nvidia/llama-3.1-nemotron-ultra-253b-v1', + displayName: 'NVIDIA: Llama 3.1 Nemotron Ultra 253B v1', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 1.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nvidia/llama-3.3-nemotron-super-49b-v1.5', + displayName: 'NVIDIA: Llama 3.3 Nemotron Super 49B V1.5', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nvidia/nemotron-3-nano-30b-a3b', + displayName: 'NVIDIA: Nemotron 3 Nano 30B A3B', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.05, + outputPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nvidia/nemotron-3-nano-30b-a3b:free', + displayName: 'NVIDIA: Nemotron 3 Nano 30B A3B (free)', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nvidia/nemotron-nano-12b-v2-vl', + displayName: 'NVIDIA: Nemotron Nano 12B 2 VL', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.2, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nvidia/nemotron-nano-12b-v2-vl:free', + displayName: 'NVIDIA: Nemotron Nano 12B 2 VL (free)', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nvidia/nemotron-nano-9b-v2', + displayName: 'NVIDIA: Nemotron Nano 9B V2', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.04, + outputPerM: 0.16, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nvidia/nemotron-nano-9b-v2:free', + displayName: 'NVIDIA: Nemotron Nano 9B V2 (free)', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/chatgpt-4o-latest', + displayName: 'OpenAI: ChatGPT-4o', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 5, + outputPerM: 15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-3.5-turbo', + displayName: 'OpenAI: GPT-3.5 Turbo', + maxInputTokens: 16385, + supportedFileTypes: [], + pricing: { + inputPerM: 0.5, + outputPerM: 1.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-3.5-turbo-0613', + displayName: 'OpenAI: GPT-3.5 Turbo (older v0613)', + maxInputTokens: 4095, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-3.5-turbo-instruct', + displayName: 'OpenAI: GPT-3.5 Turbo Instruct', + maxInputTokens: 4095, + supportedFileTypes: [], + pricing: { + inputPerM: 1.5, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4', + displayName: 'OpenAI: GPT-4', + maxInputTokens: 8191, + supportedFileTypes: [], + pricing: { + inputPerM: 30, + outputPerM: 60, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4-turbo', + displayName: 'OpenAI: GPT-4 Turbo', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 10, + outputPerM: 30, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4.1', + displayName: 'OpenAI: GPT-4.1', + maxInputTokens: 1047576, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2, + outputPerM: 8, + cacheReadPerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4.1-mini', + displayName: 'OpenAI: GPT-4.1 Mini', + maxInputTokens: 1047576, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.4, + outputPerM: 1.6, + cacheReadPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4.1-nano', + displayName: 'OpenAI: GPT-4.1 Nano', + maxInputTokens: 1047576, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.4, + cacheReadPerM: 0.025, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4o', + displayName: 'OpenAI: GPT-4o', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2.5, + outputPerM: 10, + cacheReadPerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4o-2024-05-13', + displayName: 'OpenAI: GPT-4o (2024-05-13)', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 5, + outputPerM: 15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4o-2024-08-06', + displayName: 'OpenAI: GPT-4o (2024-08-06)', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2.5, + outputPerM: 10, + cacheReadPerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4o-2024-11-20', + displayName: 'OpenAI: GPT-4o (2024-11-20)', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2.5, + outputPerM: 10, + cacheReadPerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4o-mini', + displayName: 'OpenAI: GPT-4o-mini', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + cacheReadPerM: 0.075, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4o-mini-search-preview', + displayName: 'OpenAI: GPT-4o-mini Search Preview', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4o:extended', + displayName: 'OpenAI: GPT-4o (extended)', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 6, + outputPerM: 18, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5', + displayName: 'OpenAI: GPT-5', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5-chat', + displayName: 'OpenAI: GPT-5 Chat', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5-codex', + displayName: 'OpenAI: GPT-5 Codex', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5-mini', + displayName: 'OpenAI: GPT-5 Mini', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.25, + outputPerM: 2, + cacheReadPerM: 0.025, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5-nano', + displayName: 'OpenAI: GPT-5 Nano', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.05, + outputPerM: 0.4, + cacheReadPerM: 0.005, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5-pro', + displayName: 'OpenAI: GPT-5 Pro', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 15, + outputPerM: 120, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.1', + displayName: 'OpenAI: GPT-5.1', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.1-chat', + displayName: 'OpenAI: GPT-5.1 Chat', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.1-codex', + displayName: 'OpenAI: GPT-5.1-Codex', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.1-codex-max', + displayName: 'OpenAI: GPT-5.1-Codex-Max', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.1-codex-mini', + displayName: 'OpenAI: GPT-5.1-Codex-Mini', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.25, + outputPerM: 2, + cacheReadPerM: 0.025, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.2', + displayName: 'OpenAI: GPT-5.2', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.75, + outputPerM: 14, + cacheReadPerM: 0.175, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.2-chat', + displayName: 'OpenAI: GPT-5.2 Chat', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.75, + outputPerM: 14, + cacheReadPerM: 0.175, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.2-codex', + displayName: 'OpenAI: GPT-5.2-Codex', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.75, + outputPerM: 14, + cacheReadPerM: 0.175, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.2-pro', + displayName: 'OpenAI: GPT-5.2 Pro', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 21, + outputPerM: 168, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-120b', + displayName: 'OpenAI: gpt-oss-120b', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.039, + outputPerM: 0.19, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-120b:exacto', + displayName: 'OpenAI: gpt-oss-120b (exacto)', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.039, + outputPerM: 0.19, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-120b:free', + displayName: 'OpenAI: gpt-oss-120b (free)', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-20b', + displayName: 'OpenAI: gpt-oss-20b', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.03, + outputPerM: 0.14, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-20b:free', + displayName: 'OpenAI: gpt-oss-20b (free)', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-safeguard-20b', + displayName: 'OpenAI: gpt-oss-safeguard-20b', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.075, + outputPerM: 0.3, + cacheReadPerM: 0.037, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/o1', + displayName: 'OpenAI: o1', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 15, + outputPerM: 60, + cacheReadPerM: 7.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/o1-pro', + displayName: 'OpenAI: o1-pro', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 150, + outputPerM: 600, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/o3', + displayName: 'OpenAI: o3', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2, + outputPerM: 8, + cacheReadPerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/o3-deep-research', + displayName: 'OpenAI: o3 Deep Research', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 10, + outputPerM: 40, + cacheReadPerM: 2.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/o3-mini', + displayName: 'OpenAI: o3 Mini', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 1.1, + outputPerM: 4.4, + cacheReadPerM: 0.55, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/o3-mini-high', + displayName: 'OpenAI: o3 Mini High', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 1.1, + outputPerM: 4.4, + cacheReadPerM: 0.55, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/o3-pro', + displayName: 'OpenAI: o3 Pro', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 20, + outputPerM: 80, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/o4-mini', + displayName: 'OpenAI: o4 Mini', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.1, + outputPerM: 4.4, + cacheReadPerM: 0.275, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/o4-mini-deep-research', + displayName: 'OpenAI: o4 Mini Deep Research', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2, + outputPerM: 8, + cacheReadPerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openrouter/aurora-alpha', + displayName: 'Aurora Alpha (free)', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'perplexity/sonar', + displayName: 'Perplexity: Sonar', + maxInputTokens: 127072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'perplexity/sonar-deep-research', + displayName: 'Perplexity: Sonar Deep Research', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 2, + outputPerM: 8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'perplexity/sonar-pro', + displayName: 'Perplexity: Sonar Pro', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'perplexity/sonar-reasoning-pro', + displayName: 'Perplexity: Sonar Reasoning Pro', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2, + outputPerM: 8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'prime-intellect/intellect-3', + displayName: 'Prime Intellect: INTELLECT-3', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 1.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen-2.5-72b-instruct', + displayName: 'Qwen2.5 72B Instruct', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.12, + outputPerM: 0.39, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen-2.5-7b-instruct', + displayName: 'Qwen: Qwen2.5 7B Instruct', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.04, + outputPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen-2.5-coder-32b-instruct', + displayName: 'Qwen2.5 Coder 32B Instruct', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.03, + outputPerM: 0.11, + cacheReadPerM: 0.015, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen-2.5-vl-7b-instruct', + displayName: 'Qwen: Qwen2.5-VL 7B Instruct', + maxInputTokens: 32768, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.2, + outputPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen-max', + displayName: 'Qwen: Qwen-Max ', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 1.6, + outputPerM: 6.4, + cacheReadPerM: 0.32, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen-plus', + displayName: 'Qwen: Qwen-Plus', + maxInputTokens: 1000000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.4, + outputPerM: 1.2, + cacheReadPerM: 0.08, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen-turbo', + displayName: 'Qwen: Qwen-Turbo', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.05, + outputPerM: 0.2, + cacheReadPerM: 0.01, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen-vl-max', + displayName: 'Qwen: Qwen VL Max', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.8, + outputPerM: 3.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen-vl-plus', + displayName: 'Qwen: Qwen VL Plus', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.21, + outputPerM: 0.63, + cacheReadPerM: 0.042, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen2.5-coder-7b-instruct', + displayName: 'Qwen: Qwen2.5 Coder 7B Instruct', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.03, + outputPerM: 0.09, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen2.5-vl-32b-instruct', + displayName: 'Qwen: Qwen2.5 VL 32B Instruct', + maxInputTokens: 16384, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.05, + outputPerM: 0.22, + cacheReadPerM: 0.025, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen2.5-vl-72b-instruct', + displayName: 'Qwen: Qwen2.5 VL 72B Instruct', + maxInputTokens: 32768, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + cacheReadPerM: 0.075, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-14b', + displayName: 'Qwen: Qwen3 14B', + maxInputTokens: 40960, + supportedFileTypes: [], + pricing: { + inputPerM: 0.05, + outputPerM: 0.22, + cacheReadPerM: 0.025, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-235b-a22b', + displayName: 'Qwen: Qwen3 235B A22B', + maxInputTokens: 40960, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + cacheReadPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-235b-a22b-2507', + displayName: 'Qwen: Qwen3 235B A22B Instruct 2507', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.071, + outputPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-235b-a22b-thinking-2507', + displayName: 'Qwen: Qwen3 235B A22B Thinking 2507', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-30b-a3b', + displayName: 'Qwen: Qwen3 30B A3B', + maxInputTokens: 40960, + supportedFileTypes: [], + pricing: { + inputPerM: 0.06, + outputPerM: 0.22, + cacheReadPerM: 0.03, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-30b-a3b-instruct-2507', + displayName: 'Qwen: Qwen3 30B A3B Instruct 2507', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.08, + outputPerM: 0.33, + cacheReadPerM: 0.04, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-30b-a3b-thinking-2507', + displayName: 'Qwen: Qwen3 30B A3B Thinking 2507', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.051, + outputPerM: 0.34, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-32b', + displayName: 'Qwen: Qwen3 32B', + maxInputTokens: 40960, + supportedFileTypes: [], + pricing: { + inputPerM: 0.08, + outputPerM: 0.24, + cacheReadPerM: 0.04, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-4b', + displayName: 'Qwen: Qwen3 4B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.0715, + outputPerM: 0.273, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-4b:free', + displayName: 'Qwen: Qwen3 4B (free)', + maxInputTokens: 40960, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-8b', + displayName: 'Qwen: Qwen3 8B', + maxInputTokens: 32000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.05, + outputPerM: 0.4, + cacheReadPerM: 0.05, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-coder', + displayName: 'Qwen: Qwen3 Coder 480B A35B', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.22, + outputPerM: 1, + cacheReadPerM: 0.022, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-coder-30b-a3b-instruct', + displayName: 'Qwen: Qwen3 Coder 30B A3B Instruct', + maxInputTokens: 160000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.07, + outputPerM: 0.27, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-coder-flash', + displayName: 'Qwen: Qwen3 Coder Flash', + maxInputTokens: 1000000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.5, + cacheReadPerM: 0.06, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-coder-next', + displayName: 'Qwen: Qwen3 Coder Next', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.07, + outputPerM: 0.3, + cacheReadPerM: 0.035, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-coder-plus', + displayName: 'Qwen: Qwen3 Coder Plus', + maxInputTokens: 1000000, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 5, + cacheReadPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-coder:exacto', + displayName: 'Qwen: Qwen3 Coder 480B A35B (exacto)', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.22, + outputPerM: 1.8, + cacheReadPerM: 0.022, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-coder:free', + displayName: 'Qwen: Qwen3 Coder 480B A35B (free)', + maxInputTokens: 262000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-max', + displayName: 'Qwen: Qwen3 Max', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 1.2, + outputPerM: 6, + cacheReadPerM: 0.24, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-max-thinking', + displayName: 'Qwen: Qwen3 Max Thinking', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 1.2, + outputPerM: 6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-next-80b-a3b-instruct', + displayName: 'Qwen: Qwen3 Next 80B A3B Instruct', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.09, + outputPerM: 1.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-next-80b-a3b-instruct:free', + displayName: 'Qwen: Qwen3 Next 80B A3B Instruct (free)', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-next-80b-a3b-thinking', + displayName: 'Qwen: Qwen3 Next 80B A3B Thinking', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-vl-235b-a22b-instruct', + displayName: 'Qwen: Qwen3 VL 235B A22B Instruct', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.2, + outputPerM: 0.88, + cacheReadPerM: 0.11, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-vl-235b-a22b-thinking', + displayName: 'Qwen: Qwen3 VL 235B A22B Thinking', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-vl-30b-a3b-instruct', + displayName: 'Qwen: Qwen3 VL 30B A3B Instruct', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.13, + outputPerM: 0.52, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-vl-30b-a3b-thinking', + displayName: 'Qwen: Qwen3 VL 30B A3B Thinking', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-vl-32b-instruct', + displayName: 'Qwen: Qwen3 VL 32B Instruct', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.104, + outputPerM: 0.416, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-vl-8b-instruct', + displayName: 'Qwen: Qwen3 VL 8B Instruct', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.08, + outputPerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-vl-8b-thinking', + displayName: 'Qwen: Qwen3 VL 8B Thinking', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.117, + outputPerM: 1.365, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3.5-397b-a17b', + displayName: 'Qwen: Qwen3.5 397B A17B', + maxInputTokens: 256000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.6, + outputPerM: 3.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3.5-plus-02-15', + displayName: 'Qwen: Qwen3.5 Plus 2026-02-15', + maxInputTokens: 1000000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.4, + outputPerM: 2.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwq-32b', + displayName: 'Qwen: QwQ 32B', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'stepfun/step-3.5-flash', + displayName: 'StepFun: Step 3.5 Flash', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.3, + cacheReadPerM: 0.02, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'stepfun/step-3.5-flash:free', + displayName: 'StepFun: Step 3.5 Flash (free)', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'tencent/hunyuan-a13b-instruct', + displayName: 'Tencent: Hunyuan A13B Instruct', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.14, + outputPerM: 0.57, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'tngtech/deepseek-r1t-chimera', + displayName: 'TNG: DeepSeek R1T Chimera', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + cacheReadPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'tngtech/deepseek-r1t2-chimera', + displayName: 'TNG: DeepSeek R1T2 Chimera', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.25, + outputPerM: 0.85, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'tngtech/tng-r1t-chimera', + displayName: 'TNG: R1T Chimera', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.25, + outputPerM: 0.85, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'writer/palmyra-x5', + displayName: 'Writer: Palmyra X5', + maxInputTokens: 1040000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'x-ai/grok-3', + displayName: 'xAI: Grok 3', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'x-ai/grok-3-beta', + displayName: 'xAI: Grok 3 Beta', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'x-ai/grok-3-mini', + displayName: 'xAI: Grok 3 Mini', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 0.5, + cacheReadPerM: 0.075, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'x-ai/grok-3-mini-beta', + displayName: 'xAI: Grok 3 Mini Beta', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 0.5, + cacheReadPerM: 0.075, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'x-ai/grok-4', + displayName: 'xAI: Grok 4', + maxInputTokens: 256000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'x-ai/grok-4-fast', + displayName: 'xAI: Grok 4 Fast', + maxInputTokens: 2000000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.2, + outputPerM: 0.5, + cacheReadPerM: 0.05, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'x-ai/grok-4.1-fast', + displayName: 'xAI: Grok 4.1 Fast', + maxInputTokens: 2000000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.2, + outputPerM: 0.5, + cacheReadPerM: 0.05, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'x-ai/grok-code-fast-1', + displayName: 'xAI: Grok Code Fast 1', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 1.5, + cacheReadPerM: 0.02, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'xiaomi/mimo-v2-flash', + displayName: 'Xiaomi: MiMo-V2-Flash', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.09, + outputPerM: 0.29, + cacheReadPerM: 0.045, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'z-ai/glm-4.5', + displayName: 'Z.ai: GLM 4.5', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.35, + outputPerM: 1.55, + cacheReadPerM: 0.175, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'z-ai/glm-4.5-air', + displayName: 'Z.ai: GLM 4.5 Air', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.13, + outputPerM: 0.85, + cacheReadPerM: 0.025, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'z-ai/glm-4.5-air:free', + displayName: 'Z.ai: GLM 4.5 Air (free)', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'z-ai/glm-4.5v', + displayName: 'Z.ai: GLM 4.5V', + maxInputTokens: 65536, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.6, + outputPerM: 1.8, + cacheReadPerM: 0.11, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'z-ai/glm-4.6', + displayName: 'Z.ai: GLM 4.6', + maxInputTokens: 202752, + supportedFileTypes: [], + pricing: { + inputPerM: 0.35, + outputPerM: 1.5, + cacheReadPerM: 0.175, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'z-ai/glm-4.6:exacto', + displayName: 'Z.ai: GLM 4.6 (exacto)', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.44, + outputPerM: 1.76, + cacheReadPerM: 0.11, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'z-ai/glm-4.6v', + displayName: 'Z.ai: GLM 4.6V', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.3, + outputPerM: 0.9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'z-ai/glm-4.7', + displayName: 'Z.ai: GLM 4.7', + maxInputTokens: 202752, + supportedFileTypes: [], + pricing: { + inputPerM: 0.4, + outputPerM: 1.5, + cacheReadPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'z-ai/glm-4.7-flash', + displayName: 'Z.ai: GLM 4.7 Flash', + maxInputTokens: 202752, + supportedFileTypes: [], + pricing: { + inputPerM: 0.06, + outputPerM: 0.4, + cacheReadPerM: 0.01, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'z-ai/glm-5', + displayName: 'Z.ai: GLM 5', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 2.55, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'z-ai/glm-5:free', + displayName: 'Z.ai: GLM 5 (free)', + maxInputTokens: 202800, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + 'kimi-for-coding': [ + { + name: 'k2p5', + displayName: 'Kimi K2.5', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2-thinking', + displayName: 'Kimi K2 Thinking', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + 'kuae-cloud-coding-plan': [ + { + name: 'GLM-4.7', + displayName: 'GLM-4.7', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + llama: [ + { + name: 'cerebras-llama-4-maverick-17b-128e-instruct', + displayName: 'Cerebras-Llama-4-Maverick-17B-128E-Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'cerebras-llama-4-scout-17b-16e-instruct', + displayName: 'Cerebras-Llama-4-Scout-17B-16E-Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'groq-llama-4-maverick-17b-128e-instruct', + displayName: 'Groq-Llama-4-Maverick-17B-128E-Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'llama-3.3-70b-instruct', + displayName: 'Llama-3.3-70B-Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'llama-3.3-8b-instruct', + displayName: 'Llama-3.3-8B-Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'llama-4-maverick-17b-128e-instruct-fp8', + displayName: 'Llama-4-Maverick-17B-128E-Instruct-FP8', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'llama-4-scout-17b-16e-instruct-fp8', + displayName: 'Llama-4-Scout-17B-16E-Instruct-FP8', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + lmstudio: [ + { + name: 'openai/gpt-oss-20b', + displayName: 'GPT OSS 20B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-30b-a3b-2507', + displayName: 'Qwen3 30B A3B 2507', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-coder-30b', + displayName: 'Qwen3 Coder 30B', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + lucidquery: [ + { + name: 'lucidnova-rf1-100b', + displayName: 'LucidNova RF1 100B', + maxInputTokens: 120000, + supportedFileTypes: [], + pricing: { + inputPerM: 2, + outputPerM: 5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'lucidquery-nexus-coder', + displayName: 'LucidQuery Nexus Coder', + maxInputTokens: 250000, + supportedFileTypes: [], + pricing: { + inputPerM: 2, + outputPerM: 5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + meganova: [ + { + name: 'deepseek-ai/DeepSeek-R1-0528', + displayName: 'DeepSeek R1 0528', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.5, + outputPerM: 2.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/DeepSeek-V3-0324', + displayName: 'DeepSeek V3 0324', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.25, + outputPerM: 0.88, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/DeepSeek-V3.1', + displayName: 'DeepSeek V3.1', + maxInputTokens: 164000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.27, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/DeepSeek-V3.2', + displayName: 'DeepSeek V3.2', + maxInputTokens: 164000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.26, + outputPerM: 0.38, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/DeepSeek-V3.2-Exp', + displayName: 'DeepSeek V3.2 Exp', + maxInputTokens: 164000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.27, + outputPerM: 0.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/Llama-3.3-70B-Instruct', + displayName: 'Llama 3.3 70B Instruct', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'MiniMaxAI/MiniMax-M2.1', + displayName: 'MiniMax M2.1', + maxInputTokens: 196608, + supportedFileTypes: [], + pricing: { + inputPerM: 0.28, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'MiniMaxAI/MiniMax-M2.5', + displayName: 'MiniMax M2.5', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/Mistral-Nemo-Instruct-2407', + displayName: 'Mistral Nemo Instruct 2407', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.02, + outputPerM: 0.04, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/Mistral-Small-3.2-24B-Instruct-2506', + displayName: 'Mistral Small 3.2 24B Instruct', + maxInputTokens: 32768, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/Kimi-K2-Thinking', + displayName: 'Kimi K2 Thinking', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/Kimi-K2.5', + displayName: 'Kimi K2.5', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.45, + outputPerM: 2.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen2.5-VL-32B-Instruct', + displayName: 'Qwen2.5 VL 32B Instruct', + maxInputTokens: 16384, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.2, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-235B-A22B-Instruct-2507', + displayName: 'Qwen3 235B A22B Instruct 2507', + maxInputTokens: 262000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.09, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3.5-Plus', + displayName: 'Qwen3.5 Plus', + maxInputTokens: 1000000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.4, + outputPerM: 2.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'XiaomiMiMo/MiMo-V2-Flash', + displayName: 'MiMo V2 Flash', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-4.6', + displayName: 'GLM-4.6', + maxInputTokens: 202752, + supportedFileTypes: [], + pricing: { + inputPerM: 0.45, + outputPerM: 1.9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-4.7', + displayName: 'GLM-4.7', + maxInputTokens: 202752, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-5', + displayName: 'GLM-5', + maxInputTokens: 202752, + supportedFileTypes: [], + pricing: { + inputPerM: 0.8, + outputPerM: 2.56, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + minimax: [ + { + name: 'MiniMax-M2', + displayName: 'MiniMax-M2', + maxInputTokens: 196608, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'MiniMax-M2.1', + displayName: 'MiniMax-M2.1', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + default: true, + }, + { + name: 'MiniMax-M2.5', + displayName: 'MiniMax-M2.5', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + cacheReadPerM: 0.03, + cacheWritePerM: 0.375, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'MiniMax-M2.5-highspeed', + displayName: 'MiniMax-M2.5-highspeed', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.4, + cacheReadPerM: 0.06, + cacheWritePerM: 0.375, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + 'minimax-cn': [ + { + name: 'MiniMax-M2', + displayName: 'MiniMax-M2', + maxInputTokens: 196608, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'MiniMax-M2.1', + displayName: 'MiniMax-M2.1', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'MiniMax-M2.5', + displayName: 'MiniMax-M2.5', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + cacheReadPerM: 0.03, + cacheWritePerM: 0.375, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'MiniMax-M2.5-highspeed', + displayName: 'MiniMax-M2.5-highspeed', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.4, + cacheReadPerM: 0.06, + cacheWritePerM: 0.375, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + 'minimax-cn-coding-plan': [ + { + name: 'MiniMax-M2', + displayName: 'MiniMax-M2', + maxInputTokens: 196608, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'MiniMax-M2.1', + displayName: 'MiniMax-M2.1', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'MiniMax-M2.5', + displayName: 'MiniMax-M2.5', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'MiniMax-M2.5-highspeed', + displayName: 'MiniMax-M2.5-highspeed', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + 'minimax-coding-plan': [ + { + name: 'MiniMax-M2', + displayName: 'MiniMax-M2', + maxInputTokens: 196608, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'MiniMax-M2.1', + displayName: 'MiniMax-M2.1', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'MiniMax-M2.5', + displayName: 'MiniMax-M2.5', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'MiniMax-M2.5-highspeed', + displayName: 'MiniMax-M2.5-highspeed', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + mistral: [ + { + name: 'codestral-latest', + displayName: 'Codestral', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 0.9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'devstral-2512', + displayName: 'Devstral 2', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.4, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'devstral-medium-2507', + displayName: 'Devstral Medium', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.4, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'devstral-medium-latest', + displayName: 'Devstral 2', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.4, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'devstral-small-2505', + displayName: 'Devstral Small 2505', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'devstral-small-2507', + displayName: 'Devstral Small', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'labs-devstral-small-2512', + displayName: 'Devstral Small 2', + maxInputTokens: 256000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'magistral-medium-latest', + displayName: 'Magistral Medium', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 2, + outputPerM: 5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'magistral-small', + displayName: 'Magistral Small', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.5, + outputPerM: 1.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'ministral-3b-latest', + displayName: 'Ministral 3B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.04, + outputPerM: 0.04, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'ministral-8b-latest', + displayName: 'Ministral 8B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral-embed', + displayName: 'Mistral Embed', + maxInputTokens: 8000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral-large-2411', + displayName: 'Mistral Large 2.1', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 2, + outputPerM: 6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral-large-2512', + displayName: 'Mistral Large 3', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.5, + outputPerM: 1.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral-large-latest', + displayName: 'Mistral Large', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.5, + outputPerM: 1.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral-medium-2505', + displayName: 'Mistral Medium 3', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.4, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral-medium-2508', + displayName: 'Mistral Medium 3.1', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.4, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral-medium-latest', + displayName: 'Mistral Medium', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.4, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral-nemo', + displayName: 'Mistral Nemo', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral-small-2506', + displayName: 'Mistral Small 3.2', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral-small-latest', + displayName: 'Mistral Small', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'open-mistral-7b', + displayName: 'Mistral 7B', + maxInputTokens: 8000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.25, + outputPerM: 0.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'open-mixtral-8x22b', + displayName: 'Mixtral 8x22B', + maxInputTokens: 64000, + supportedFileTypes: [], + pricing: { + inputPerM: 2, + outputPerM: 6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'open-mixtral-8x7b', + displayName: 'Mixtral 8x7B', + maxInputTokens: 32000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.7, + outputPerM: 0.7, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'pixtral-12b', + displayName: 'Pixtral 12B', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.15, + outputPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'pixtral-large-latest', + displayName: 'Pixtral Large', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2, + outputPerM: 6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + moark: [ + { + name: 'GLM-4.7', + displayName: 'GLM-4.7', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 3.5, + outputPerM: 14, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'MiniMax-M2.1', + displayName: 'MiniMax-M2.1', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 2.1, + outputPerM: 8.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + modelscope: [ + { + name: 'Qwen/Qwen3-235B-A22B-Instruct-2507', + displayName: 'Qwen3 235B A22B Instruct 2507', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-235B-A22B-Thinking-2507', + displayName: 'Qwen3-235B-A22B-Thinking-2507', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-30B-A3B-Instruct-2507', + displayName: 'Qwen3 30B A3B Instruct 2507', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-30B-A3B-Thinking-2507', + displayName: 'Qwen3 30B A3B Thinking 2507', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-Coder-30B-A3B-Instruct', + displayName: 'Qwen3 Coder 30B A3B Instruct', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'ZhipuAI/GLM-4.5', + displayName: 'GLM-4.5', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'ZhipuAI/GLM-4.6', + displayName: 'GLM-4.6', + maxInputTokens: 202752, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + moonshotai: [ + { + name: 'kimi-k2-0711-preview', + displayName: 'Kimi K2 0711', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.5, + cacheReadPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2-0905-preview', + displayName: 'Kimi K2 0905', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.5, + cacheReadPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2-thinking', + displayName: 'Kimi K2 Thinking', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.5, + cacheReadPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2-thinking-turbo', + displayName: 'Kimi K2 Thinking Turbo', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 1.15, + outputPerM: 8, + cacheReadPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2-turbo-preview', + displayName: 'Kimi K2 Turbo', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 2.4, + outputPerM: 10, + cacheReadPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2.5', + displayName: 'Kimi K2.5', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.6, + outputPerM: 3, + cacheReadPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + default: true, + }, + ], + 'moonshotai-cn': [ + { + name: 'kimi-k2-0711-preview', + displayName: 'Kimi K2 0711', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.5, + cacheReadPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2-0905-preview', + displayName: 'Kimi K2 0905', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.5, + cacheReadPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2-thinking', + displayName: 'Kimi K2 Thinking', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.5, + cacheReadPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2-thinking-turbo', + displayName: 'Kimi K2 Thinking Turbo', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 1.15, + outputPerM: 8, + cacheReadPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2-turbo-preview', + displayName: 'Kimi K2 Turbo', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 2.4, + outputPerM: 10, + cacheReadPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2.5', + displayName: 'Kimi K2.5', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.6, + outputPerM: 3, + cacheReadPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + morph: [ + { + name: 'auto', + displayName: 'Auto', + maxInputTokens: 32000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.85, + outputPerM: 1.55, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'morph-v3-fast', + displayName: 'Morph v3 Fast', + maxInputTokens: 16000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.8, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'morph-v3-large', + displayName: 'Morph v3 Large', + maxInputTokens: 32000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.9, + outputPerM: 1.9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + 'nano-gpt': [ + { + name: 'deepseek/deepseek-r1', + displayName: 'Deepseek R1', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-v3.2:thinking', + displayName: 'Deepseek V3.2 Thinking', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/llama-3.3-70b-instruct', + displayName: 'Llama 3.3 70b Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/llama-4-maverick', + displayName: 'Llama 4 Maverick', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'minimax/minimax-m2.1', + displayName: 'Minimax M2.1', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'minimax/minimax-m2.5', + displayName: 'MiniMax M2.5', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'minimax/minimax-m2.5-official', + displayName: 'MiniMax M2.5', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/devstral-2-123b-instruct-2512', + displayName: 'Devstral 2 123b Instruct 2512', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/ministral-14b-instruct-2512', + displayName: 'Ministral 14b Instruct 2512', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/mistral-large-3-675b-instruct-2512', + displayName: 'Mistral Large 3 675b Instruct 2512', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2-instruct', + displayName: 'Kimi K2 Instruct', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2-thinking', + displayName: 'Kimi K2 Thinking', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2.5', + displayName: 'Kimi K2.5', + maxInputTokens: 256000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.3, + outputPerM: 1.9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2.5-thinking', + displayName: 'Kimi K2.5 Thinking', + maxInputTokens: 256000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.3, + outputPerM: 1.9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nousresearch/hermes-4-405b:thinking', + displayName: 'Hermes 4 405b Thinking', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nvidia/llama-3_3-nemotron-super-49b-v1_5', + displayName: 'Llama 3 3 Nemotron Super 49B V1 5', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-120b', + displayName: 'GPT Oss 120b', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-235b-a22b-thinking-2507', + displayName: 'Qwen3 235B A22B Thinking 2507', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-coder', + displayName: 'Qwen3 Coder', + maxInputTokens: 106000, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3.5-397b-a17b', + displayName: 'Qwen3.5 397B A17B', + maxInputTokens: 258000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.6, + outputPerM: 3.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3.5-397b-a17b-thinking', + displayName: 'Qwen3.5 397B A17B Thinking', + maxInputTokens: 258000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.6, + outputPerM: 3.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3.5-plus', + displayName: 'Qwen3.5 Plus', + maxInputTokens: 983600, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.4, + outputPerM: 2.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3.5-plus-thinking', + displayName: 'Qwen3.5 Plus Thinking', + maxInputTokens: 983600, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.4, + outputPerM: 2.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/glm-4.5-air', + displayName: 'GLM 4.5 Air', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/glm-4.5-air:thinking', + displayName: 'GLM 4.5 Air Thinking', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/glm-4.6', + displayName: 'GLM 4.6', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/glm-4.6:thinking', + displayName: 'GLM 4.6 Thinking', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/glm-4.7', + displayName: 'GLM 4.7', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/glm-4.7:thinking', + displayName: 'GLM 4.7 Thinking', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/glm-5', + displayName: 'GLM 5', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.8, + outputPerM: 2.56, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/glm-5-original', + displayName: 'GLM 5 Original', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.8, + outputPerM: 2.56, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/glm-5-original:thinking', + displayName: 'GLM 5 Original Thinking', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.8, + outputPerM: 2.56, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/glm-5:thinking', + displayName: 'GLM 5 Thinking', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.8, + outputPerM: 2.56, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + nebius: [ + { + name: 'BAAI/bge-en-icl', + displayName: 'BGE-ICL', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.01, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'BAAI/bge-multilingual-gemma2', + displayName: 'bge-multilingual-gemma2', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0.01, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'black-forest-labs/flux-dev', + displayName: 'FLUX.1-dev', + maxInputTokens: 77, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'black-forest-labs/flux-schnell', + displayName: 'FLUX.1-schnell', + maxInputTokens: 77, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/deepseek-r1-0528', + displayName: 'DeepSeek-R1-0528', + maxInputTokens: 120000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.8, + outputPerM: 2.4, + cacheReadPerM: 0.08, + cacheWritePerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/deepseek-r1-0528-fast', + displayName: 'DeepSeek R1 0528 Fast', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 2, + outputPerM: 6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/deepseek-v3-0324', + displayName: 'DeepSeek-V3-0324', + maxInputTokens: 120000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.5, + outputPerM: 1.5, + cacheReadPerM: 0.05, + cacheWritePerM: 0.1875, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/deepseek-v3-0324-fast', + displayName: 'DeepSeek-V3-0324 (Fast)', + maxInputTokens: 120000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.75, + outputPerM: 2.25, + cacheReadPerM: 0.075, + cacheWritePerM: 0.28125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/deepseek-v3.2', + displayName: 'DeepSeek-V3.2', + maxInputTokens: 120000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 0.45, + cacheReadPerM: 0.03, + cacheWritePerM: 0.375, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-2-2b-it', + displayName: 'Gemma-2-2b-it', + maxInputTokens: 8000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.02, + outputPerM: 0.06, + cacheReadPerM: 0.002, + cacheWritePerM: 0.025, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-2-9b-it-fast', + displayName: 'Gemma-2-9b-it (Fast)', + maxInputTokens: 8000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.03, + outputPerM: 0.09, + cacheReadPerM: 0.003, + cacheWritePerM: 0.0375, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-3-27b-it', + displayName: 'Gemma-3-27b-it', + maxInputTokens: 120000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.3, + cacheReadPerM: 0.01, + cacheWritePerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-3-27b-it-fast', + displayName: 'Gemma-3-27b-it (Fast)', + maxInputTokens: 120000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.2, + outputPerM: 0.6, + cacheReadPerM: 0.02, + cacheWritePerM: 0.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'intfloat/e5-mistral-7b-instruct', + displayName: 'e5-mistral-7b-instruct', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.01, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/Llama-3.3-70B-Instruct', + displayName: 'Llama-3.3-70B-Instruct', + maxInputTokens: 120000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.13, + outputPerM: 0.4, + cacheReadPerM: 0.013, + cacheWritePerM: 0.16, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/llama-3.3-70b-instruct-fast', + displayName: 'Llama-3.3-70B-Instruct (Fast)', + maxInputTokens: 120000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.25, + outputPerM: 0.75, + cacheReadPerM: 0.025, + cacheWritePerM: 0.31, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/llama-guard-3-8b', + displayName: 'Llama-Guard-3-8B', + maxInputTokens: 8000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.02, + outputPerM: 0.06, + cacheReadPerM: 0.002, + cacheWritePerM: 0.025, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/meta-llama-3.1-8b-instruct', + displayName: 'Meta-Llama-3.1-8B-Instruct', + maxInputTokens: 120000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.02, + outputPerM: 0.06, + cacheReadPerM: 0.002, + cacheWritePerM: 0.025, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/meta-llama-3.1-8b-instruct-fast', + displayName: 'Meta-Llama-3.1-8B-Instruct (Fast)', + maxInputTokens: 120000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.03, + outputPerM: 0.09, + cacheReadPerM: 0.003, + cacheWritePerM: 0.03, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'MiniMaxAI/minimax-m2.1', + displayName: 'MiniMax-M2.1', + maxInputTokens: 120000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + cacheReadPerM: 0.03, + cacheWritePerM: 0.375, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2-instruct', + displayName: 'Kimi-K2-Instruct', + maxInputTokens: 190000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.5, + outputPerM: 2.4, + cacheReadPerM: 0.05, + cacheWritePerM: 0.625, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2-thinking', + displayName: 'Kimi-K2-Thinking', + maxInputTokens: 120000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.5, + cacheReadPerM: 0.06, + cacheWritePerM: 0.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/Kimi-K2.5', + displayName: 'Kimi-K2.5', + maxInputTokens: 250000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.5, + outputPerM: 2.5, + cacheReadPerM: 0.05, + cacheWritePerM: 0.625, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'NousResearch/hermes-4-405b', + displayName: 'Hermes-4-405B', + maxInputTokens: 120000, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 3, + cacheReadPerM: 0.1, + cacheWritePerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'NousResearch/hermes-4-70b', + displayName: 'Hermes-4-70B', + maxInputTokens: 120000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.13, + outputPerM: 0.4, + cacheReadPerM: 0.013, + cacheWritePerM: 0.16, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nvidia/llama-3_1-nemotron-ultra-253b-v1', + displayName: 'Llama-3.1-Nemotron-Ultra-253B-v1', + maxInputTokens: 120000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 1.8, + cacheReadPerM: 0.06, + cacheWritePerM: 0.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nvidia/nemotron-nano-v2-12b', + displayName: 'Nemotron-Nano-V2-12b', + maxInputTokens: 30000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.07, + outputPerM: 0.2, + cacheReadPerM: 0.007, + cacheWritePerM: 0.08, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nvidia/nvidia-nemotron-3-nano-30b-a3b', + displayName: 'Nemotron-3-Nano-30B-A3B', + maxInputTokens: 30000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.06, + outputPerM: 0.24, + cacheReadPerM: 0.006, + cacheWritePerM: 0.075, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-120b', + displayName: 'gpt-oss-120b', + maxInputTokens: 124000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + cacheReadPerM: 0.015, + cacheWritePerM: 0.18, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-20b', + displayName: 'gpt-oss-20b', + maxInputTokens: 124000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.05, + outputPerM: 0.2, + cacheReadPerM: 0.005, + cacheWritePerM: 0.06, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'PrimeIntellect/intellect-3', + displayName: 'INTELLECT-3', + maxInputTokens: 120000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 1.1, + cacheReadPerM: 0.02, + cacheWritePerM: 0.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen2.5-coder-7b-fast', + displayName: 'Qwen2.5-Coder-7B (Fast)', + maxInputTokens: 120000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.03, + outputPerM: 0.09, + cacheReadPerM: 0.003, + cacheWritePerM: 0.03, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen2.5-vl-72b-instruct', + displayName: 'Qwen2.5-VL-72B-Instruct', + maxInputTokens: 120000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.25, + outputPerM: 0.75, + cacheReadPerM: 0.025, + cacheWritePerM: 0.31, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-235b-a22b-instruct-2507', + displayName: 'Qwen3 235B A22B Instruct 2507', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-235b-a22b-thinking-2507', + displayName: 'Qwen3 235B A22B Thinking 2507', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-30b-a3b-instruct-2507', + displayName: 'Qwen3-30B-A3B-Instruct-2507', + maxInputTokens: 120000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.3, + cacheReadPerM: 0.01, + cacheWritePerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-30b-a3b-thinking-2507', + displayName: 'Qwen3-30B-A3B-Thinking-2507', + maxInputTokens: 120000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.3, + cacheReadPerM: 0.01, + cacheWritePerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-32b', + displayName: 'Qwen3-32B', + maxInputTokens: 120000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.3, + cacheReadPerM: 0.01, + cacheWritePerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-32b-fast', + displayName: 'Qwen3-32B (Fast)', + maxInputTokens: 120000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.6, + cacheReadPerM: 0.02, + cacheWritePerM: 0.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-coder-30b-a3b-instruct', + displayName: 'Qwen3-Coder-30B-A3B-Instruct', + maxInputTokens: 120000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.3, + cacheReadPerM: 0.01, + cacheWritePerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-coder-480b-a35b-instruct', + displayName: 'Qwen3 Coder 480B A35B Instruct', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.4, + outputPerM: 1.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-embedding-8b', + displayName: 'Qwen3-Embedding-8B', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.01, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-next-80b-a3b-thinking', + displayName: 'Qwen3-Next-80B-A3B-Thinking', + maxInputTokens: 120000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 1.2, + cacheReadPerM: 0.015, + cacheWritePerM: 0.18, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/glm-4.5', + displayName: 'GLM-4.5', + maxInputTokens: 124000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.2, + cacheReadPerM: 0.06, + cacheWritePerM: 0.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/glm-4.5-air', + displayName: 'GLM-4.5-Air', + maxInputTokens: 124000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 1.2, + cacheReadPerM: 0.02, + cacheWritePerM: 0.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/glm-4.7-fp8', + displayName: 'GLM-4.7 (FP8)', + maxInputTokens: 124000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.4, + outputPerM: 2, + cacheReadPerM: 0.04, + cacheWritePerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + nova: [ + { + name: 'nova-2-lite-v1', + displayName: 'Nova 2 Lite', + maxInputTokens: 1000000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nova-2-pro-v1', + displayName: 'Nova 2 Pro', + maxInputTokens: 1000000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + 'novita-ai': [ + { + name: 'baichuan/baichuan-m2-32b', + displayName: 'baichuan-m2-32b', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.07, + outputPerM: 0.07, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'baidu/ernie-4.5-21B-a3b', + displayName: 'ERNIE 4.5 21B A3B', + maxInputTokens: 120000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.07, + outputPerM: 0.28, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'baidu/ernie-4.5-21B-a3b-thinking', + displayName: 'ERNIE-4.5-21B-A3B-Thinking', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.07, + outputPerM: 0.28, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'baidu/ernie-4.5-300b-a47b-paddle', + displayName: 'ERNIE 4.5 300B A47B', + maxInputTokens: 123000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.28, + outputPerM: 1.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'baidu/ernie-4.5-vl-28b-a3b', + displayName: 'ERNIE 4.5 VL 28B A3B', + maxInputTokens: 30000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.4, + outputPerM: 5.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'baidu/ernie-4.5-vl-28b-a3b-thinking', + displayName: 'ERNIE-4.5-VL-28B-A3B-Thinking', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.39, + outputPerM: 0.39, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'baidu/ernie-4.5-vl-424b-a47b', + displayName: 'ERNIE 4.5 VL 424B A47B', + maxInputTokens: 123000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.42, + outputPerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-ocr', + displayName: 'DeepSeek-OCR', + maxInputTokens: 8192, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.03, + outputPerM: 0.03, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-ocr-2', + displayName: 'deepseek/deepseek-ocr-2', + maxInputTokens: 8192, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.03, + outputPerM: 0.03, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-prover-v2-671b', + displayName: 'Deepseek Prover V2 671B', + maxInputTokens: 160000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.7, + outputPerM: 2.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-r1-0528', + displayName: 'DeepSeek R1 0528', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.7, + outputPerM: 2.5, + cacheReadPerM: 0.35, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-r1-0528-qwen3-8b', + displayName: 'DeepSeek R1 0528 Qwen3 8B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.06, + outputPerM: 0.09, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-r1-distill-llama-70b', + displayName: 'DeepSeek R1 Distill LLama 70B', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0.8, + outputPerM: 0.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-r1-turbo', + displayName: 'DeepSeek R1 (Turbo)\t', + maxInputTokens: 64000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.7, + outputPerM: 2.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-v3-0324', + displayName: 'DeepSeek V3 0324', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.27, + outputPerM: 1.12, + cacheReadPerM: 0.135, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-v3-turbo', + displayName: 'DeepSeek V3 (Turbo)\t', + maxInputTokens: 64000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.4, + outputPerM: 1.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-v3.1', + displayName: 'DeepSeek V3.1', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.27, + outputPerM: 1, + cacheReadPerM: 0.135, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-v3.1-terminus', + displayName: 'Deepseek V3.1 Terminus', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.27, + outputPerM: 1, + cacheReadPerM: 0.135, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-v3.2', + displayName: 'Deepseek V3.2', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.269, + outputPerM: 0.4, + cacheReadPerM: 0.1345, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-v3.2-exp', + displayName: 'Deepseek V3.2 Exp', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.27, + outputPerM: 0.41, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-3-27b-it', + displayName: 'Gemma 3 27B', + maxInputTokens: 98304, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.119, + outputPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gryphe/mythomax-l2-13b', + displayName: 'Mythomax L2 13B', + maxInputTokens: 4096, + supportedFileTypes: [], + pricing: { + inputPerM: 0.09, + outputPerM: 0.09, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kwaipilot/kat-coder', + displayName: 'KAT-Coder-Pro V1(Free)', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kwaipilot/kat-coder-pro', + displayName: 'Kat Coder Pro', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + cacheReadPerM: 0.06, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/llama-3-70b-instruct', + displayName: 'Llama3 70B Instruct', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0.51, + outputPerM: 0.74, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/llama-3-8b-instruct', + displayName: 'Llama 3 8B Instruct', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0.04, + outputPerM: 0.04, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/llama-3.1-8b-instruct', + displayName: 'Llama 3.1 8B Instruct', + maxInputTokens: 16384, + supportedFileTypes: [], + pricing: { + inputPerM: 0.02, + outputPerM: 0.05, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/llama-3.3-70b-instruct', + displayName: 'Llama 3.3 70B Instruct', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.135, + outputPerM: 0.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/llama-4-maverick-17b-128e-instruct-fp8', + displayName: 'Llama 4 Maverick Instruct', + maxInputTokens: 1048576, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.27, + outputPerM: 0.85, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/llama-4-scout-17b-16e-instruct', + displayName: 'Llama 4 Scout Instruct', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.18, + outputPerM: 0.59, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'microsoft/wizardlm-2-8x22b', + displayName: 'Wizardlm 2 8x22B', + maxInputTokens: 65535, + supportedFileTypes: [], + pricing: { + inputPerM: 0.62, + outputPerM: 0.62, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'minimax/minimax-m2', + displayName: 'MiniMax-M2', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + cacheReadPerM: 0.03, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'minimax/minimax-m2.1', + displayName: 'Minimax M2.1', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + cacheReadPerM: 0.03, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'minimax/minimax-m2.5', + displayName: 'MiniMax M2.5', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + cacheReadPerM: 0.03, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'minimaxai/minimax-m1-80k', + displayName: 'MiniMax M1', + maxInputTokens: 1000000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.55, + outputPerM: 2.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/mistral-nemo', + displayName: 'Mistral Nemo', + maxInputTokens: 60288, + supportedFileTypes: [], + pricing: { + inputPerM: 0.04, + outputPerM: 0.17, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2-0905', + displayName: 'Kimi K2 0905', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2-instruct', + displayName: 'Kimi K2 Instruct', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.57, + outputPerM: 2.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2-thinking', + displayName: 'Kimi K2 Thinking', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2.5', + displayName: 'Kimi K2.5', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.6, + outputPerM: 3, + cacheReadPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nousresearch/hermes-2-pro-llama-3-8b', + displayName: 'Hermes 2 Pro Llama 3 8B', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0.14, + outputPerM: 0.14, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-120b', + displayName: 'OpenAI GPT OSS 120B', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.05, + outputPerM: 0.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-20b', + displayName: 'OpenAI: GPT OSS 20B', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.04, + outputPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'paddlepaddle/paddleocr-vl', + displayName: 'PaddleOCR-VL', + maxInputTokens: 16384, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.02, + outputPerM: 0.02, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen-2.5-72b-instruct', + displayName: 'Qwen 2.5 72B Instruct', + maxInputTokens: 32000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.38, + outputPerM: 0.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen-mt-plus', + displayName: 'Qwen MT Plus', + maxInputTokens: 16384, + supportedFileTypes: [], + pricing: { + inputPerM: 0.25, + outputPerM: 0.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen2.5-7b-instruct', + displayName: 'Qwen2.5 7B Instruct', + maxInputTokens: 32000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.07, + outputPerM: 0.07, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen2.5-vl-72b-instruct', + displayName: 'Qwen2.5 VL 72B Instruct', + maxInputTokens: 32768, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.8, + outputPerM: 0.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-235b-a22b-fp8', + displayName: 'Qwen3 235B A22B', + maxInputTokens: 40960, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-235b-a22b-instruct-2507', + displayName: 'Qwen3 235B A22B Instruct 2507', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.09, + outputPerM: 0.58, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-235b-a22b-thinking-2507', + displayName: 'Qwen3 235B A22b Thinking 2507', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-30b-a3b-fp8', + displayName: 'Qwen3 30B A3B', + maxInputTokens: 40960, + supportedFileTypes: [], + pricing: { + inputPerM: 0.09, + outputPerM: 0.45, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-32b-fp8', + displayName: 'Qwen3 32B', + maxInputTokens: 40960, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.45, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-4b-fp8', + displayName: 'Qwen3 4B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.03, + outputPerM: 0.03, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-8b-fp8', + displayName: 'Qwen3 8B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.035, + outputPerM: 0.138, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-coder-30b-a3b-instruct', + displayName: 'Qwen3 Coder 30b A3B Instruct', + maxInputTokens: 160000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.07, + outputPerM: 0.27, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-coder-480b-a35b-instruct', + displayName: 'Qwen3 Coder 480B A35B Instruct', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-coder-next', + displayName: 'Qwen3 Coder Next', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 1.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-max', + displayName: 'Qwen3 Max', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 2.11, + outputPerM: 8.45, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-next-80b-a3b-instruct', + displayName: 'Qwen3 Next 80B A3B Instruct', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 1.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-next-80b-a3b-thinking', + displayName: 'Qwen3 Next 80B A3B Thinking', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 1.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-omni-30b-a3b-instruct', + displayName: 'Qwen3 Omni 30B A3B Instruct', + maxInputTokens: 65536, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0.25, + outputPerM: 0.97, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-omni-30b-a3b-thinking', + displayName: 'Qwen3 Omni 30B A3B Thinking', + maxInputTokens: 65536, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0.25, + outputPerM: 0.97, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-vl-235b-a22b-instruct', + displayName: 'Qwen3 VL 235B A22B Instruct', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.3, + outputPerM: 1.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-vl-235b-a22b-thinking', + displayName: 'Qwen3 VL 235B A22B Thinking', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.98, + outputPerM: 3.95, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-vl-30b-a3b-instruct', + displayName: 'qwen/qwen3-vl-30b-a3b-instruct', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.2, + outputPerM: 0.7, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-vl-30b-a3b-thinking', + displayName: 'qwen/qwen3-vl-30b-a3b-thinking', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.2, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-vl-8b-instruct', + displayName: 'qwen/qwen3-vl-8b-instruct', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.08, + outputPerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3.5-397b-a17b', + displayName: 'Qwen3.5-397B-A17B', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.6, + outputPerM: 3.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'sao10k/l3-70b-euryale-v2.1', + displayName: 'L3 70B Euryale V2.1\t', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 1.48, + outputPerM: 1.48, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'sao10k/l3-8b-lunaris', + displayName: 'Sao10k L3 8B Lunaris\t', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0.05, + outputPerM: 0.05, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'sao10k/L3-8B-Stheno-v3.2', + displayName: 'L3 8B Stheno V3.2', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0.05, + outputPerM: 0.05, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'sao10k/l31-70b-euryale-v2.2', + displayName: 'L31 70B Euryale V2.2', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 1.48, + outputPerM: 1.48, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'skywork/r1v4-lite', + displayName: 'Skywork R1V4-Lite', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.2, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'xiaomimimo/mimo-v2-flash', + displayName: 'XiaomiMiMo/MiMo-V2-Flash', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.3, + cacheReadPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/autoglm-phone-9b-multilingual', + displayName: 'AutoGLM-Phone-9B-Multilingual', + maxInputTokens: 65536, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.035, + outputPerM: 0.138, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/glm-4.5', + displayName: 'GLM-4.5', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.2, + cacheReadPerM: 0.11, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/glm-4.5-air', + displayName: 'GLM 4.5 Air', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.13, + outputPerM: 0.85, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/glm-4.5v', + displayName: 'GLM 4.5V', + maxInputTokens: 65536, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.6, + outputPerM: 1.8, + cacheReadPerM: 0.11, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/glm-4.6', + displayName: 'GLM 4.6', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.55, + outputPerM: 2.2, + cacheReadPerM: 0.11, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/glm-4.6v', + displayName: 'GLM 4.6V', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.3, + outputPerM: 0.9, + cacheReadPerM: 0.055, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/glm-4.7', + displayName: 'GLM-4.7', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.2, + cacheReadPerM: 0.11, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/glm-4.7-flash', + displayName: 'GLM-4.7-Flash', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.07, + outputPerM: 0.4, + cacheReadPerM: 0.01, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/glm-5', + displayName: 'GLM-5', + maxInputTokens: 202800, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 3.2, + cacheReadPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + nvidia: [ + { + name: 'black-forest-labs/flux.1-dev', + displayName: 'FLUX.1-dev', + maxInputTokens: 4096, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/deepseek-coder-6.7b-instruct', + displayName: 'Deepseek Coder 6.7b Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/deepseek-r1', + displayName: 'Deepseek R1', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/deepseek-r1-0528', + displayName: 'Deepseek R1 0528', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/deepseek-v3.1', + displayName: 'DeepSeek V3.1', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/deepseek-v3.1-terminus', + displayName: 'DeepSeek V3.1 Terminus', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/deepseek-v3.2', + displayName: 'DeepSeek V3.2', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/codegemma-1.1-7b', + displayName: 'Codegemma 1.1 7b', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/codegemma-7b', + displayName: 'Codegemma 7b', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-2-27b-it', + displayName: 'Gemma 2 27b It', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-2-2b-it', + displayName: 'Gemma 2 2b It', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-3-12b-it', + displayName: 'Gemma 3 12b It', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-3-1b-it', + displayName: 'Gemma 3 1b It', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-3-27b-it', + displayName: 'Gemma-3-27B-IT', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-3n-e2b-it', + displayName: 'Gemma 3n E2b It', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-3n-e4b-it', + displayName: 'Gemma 3n E4b It', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta/codellama-70b', + displayName: 'Codellama 70b', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta/llama-3.1-405b-instruct', + displayName: 'Llama 3.1 405b Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta/llama-3.1-70b-instruct', + displayName: 'Llama 3.1 70b Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta/llama-3.2-11b-vision-instruct', + displayName: 'Llama 3.2 11b Vision Instruct', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta/llama-3.2-1b-instruct', + displayName: 'Llama 3.2 1b Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta/llama-3.3-70b-instruct', + displayName: 'Llama 3.3 70b Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta/llama-4-maverick-17b-128e-instruct', + displayName: 'Llama 4 Maverick 17b 128e Instruct', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta/llama-4-scout-17b-16e-instruct', + displayName: 'Llama 4 Scout 17b 16e Instruct', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta/llama3-70b-instruct', + displayName: 'Llama3 70b Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta/llama3-8b-instruct', + displayName: 'Llama3 8b Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'microsoft/phi-3-medium-128k-instruct', + displayName: 'Phi 3 Medium 128k Instruct', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'microsoft/phi-3-medium-4k-instruct', + displayName: 'Phi 3 Medium 4k Instruct', + maxInputTokens: 4000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'microsoft/phi-3-small-128k-instruct', + displayName: 'Phi 3 Small 128k Instruct', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'microsoft/phi-3-small-8k-instruct', + displayName: 'Phi 3 Small 8k Instruct', + maxInputTokens: 8000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'microsoft/phi-3-vision-128k-instruct', + displayName: 'Phi 3 Vision 128k Instruct', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'microsoft/phi-3.5-moe-instruct', + displayName: 'Phi 3.5 Moe Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'microsoft/phi-3.5-vision-instruct', + displayName: 'Phi 3.5 Vision Instruct', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'microsoft/phi-4-mini-instruct', + displayName: 'Phi-4-Mini', + maxInputTokens: 131072, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'minimaxai/minimax-m2', + displayName: 'MiniMax-M2', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'minimaxai/minimax-m2.1', + displayName: 'MiniMax-M2.1', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/codestral-22b-instruct-v0.1', + displayName: 'Codestral 22b Instruct V0.1', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/devstral-2-123b-instruct-2512', + displayName: 'Devstral-2-123B-Instruct-2512', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/mamba-codestral-7b-v0.1', + displayName: 'Mamba Codestral 7b V0.1', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/ministral-14b-instruct-2512', + displayName: 'Ministral 3 14B Instruct 2512', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/mistral-large-2-instruct', + displayName: 'Mistral Large 2 Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/mistral-large-3-675b-instruct-2512', + displayName: 'Mistral Large 3 675B Instruct 2512', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/mistral-small-3.1-24b-instruct-2503', + displayName: 'Mistral Small 3.1 24b Instruct 2503', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2-instruct', + displayName: 'Kimi K2 Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2-instruct-0905', + displayName: 'Kimi K2 0905', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2-thinking', + displayName: 'Kimi K2 Thinking', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2.5', + displayName: 'Kimi K2.5', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nvidia/cosmos-nemotron-34b', + displayName: 'Cosmos Nemotron 34B', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nvidia/llama-3.1-nemotron-51b-instruct', + displayName: 'Llama 3.1 Nemotron 51b Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nvidia/llama-3.1-nemotron-70b-instruct', + displayName: 'Llama 3.1 Nemotron 70b Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nvidia/llama-3.1-nemotron-ultra-253b-v1', + displayName: 'Llama-3.1-Nemotron-Ultra-253B-v1', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nvidia/llama-3.3-nemotron-super-49b-v1', + displayName: 'Llama 3.3 Nemotron Super 49b V1', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nvidia/llama-3.3-nemotron-super-49b-v1.5', + displayName: 'Llama 3.3 Nemotron Super 49b V1.5', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nvidia/llama-embed-nemotron-8b', + displayName: 'Llama Embed Nemotron 8B', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nvidia/llama3-chatqa-1.5-70b', + displayName: 'Llama3 Chatqa 1.5 70b', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nvidia/nemoretriever-ocr-v1', + displayName: 'NeMo Retriever OCR v1', + maxInputTokens: 0, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nvidia/nemotron-3-nano-30b-a3b', + displayName: 'nemotron-3-nano-30b-a3b', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nvidia/nemotron-4-340b-instruct', + displayName: 'Nemotron 4 340b Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nvidia/nvidia-nemotron-nano-9b-v2', + displayName: 'nvidia-nemotron-nano-9b-v2', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nvidia/parakeet-tdt-0.6b-v2', + displayName: 'Parakeet TDT 0.6B v2', + maxInputTokens: 0, + supportedFileTypes: ['audio'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-120b', + displayName: 'GPT-OSS-120B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/whisper-large-v3', + displayName: 'Whisper Large v3', + maxInputTokens: 0, + supportedFileTypes: ['audio'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen2.5-coder-32b-instruct', + displayName: 'Qwen2.5 Coder 32b Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen2.5-coder-7b-instruct', + displayName: 'Qwen2.5 Coder 7b Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-235b-a22b', + displayName: 'Qwen3-235B-A22B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-coder-480b-a35b-instruct', + displayName: 'Qwen3 Coder 480B A35B Instruct', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-next-80b-a3b-instruct', + displayName: 'Qwen3-Next-80B-A3B-Instruct', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-next-80b-a3b-thinking', + displayName: 'Qwen3-Next-80B-A3B-Thinking', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwq-32b', + displayName: 'Qwq 32b', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'z-ai/glm4.7', + displayName: 'GLM-4.7', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'z-ai/glm5', + displayName: 'GLM5', + maxInputTokens: 202752, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + 'ollama-cloud': [ + { + name: 'cogito-2.1:671b', + displayName: 'cogito-2.1:671b', + maxInputTokens: 163840, + supportedFileTypes: [], + }, + { + name: 'deepseek-v3.1:671b', + displayName: 'deepseek-v3.1:671b', + maxInputTokens: 163840, + supportedFileTypes: [], + }, + { + name: 'deepseek-v3.2', + displayName: 'deepseek-v3.2', + maxInputTokens: 163840, + supportedFileTypes: [], + }, + { + name: 'devstral-2:123b', + displayName: 'devstral-2:123b', + maxInputTokens: 262144, + supportedFileTypes: [], + }, + { + name: 'devstral-small-2:24b', + displayName: 'devstral-small-2:24b', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + }, + { + name: 'gemini-3-flash-preview', + displayName: 'gemini-3-flash-preview', + maxInputTokens: 1048576, + supportedFileTypes: [], + }, + { + name: 'gemini-3-pro-preview', + displayName: 'gemini-3-pro-preview', + maxInputTokens: 1048576, + supportedFileTypes: ['image'], + }, + { + name: 'gemma3:12b', + displayName: 'gemma3:12b', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + }, + { + name: 'gemma3:27b', + displayName: 'gemma3:27b', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + }, + { + name: 'gemma3:4b', + displayName: 'gemma3:4b', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + }, + { + name: 'glm-4.6', + displayName: 'glm-4.6', + maxInputTokens: 202752, + supportedFileTypes: [], + }, + { + name: 'glm-4.7', + displayName: 'glm-4.7', + maxInputTokens: 202752, + supportedFileTypes: [], + }, + { + name: 'glm-5', + displayName: 'glm-5', + maxInputTokens: 202752, + supportedFileTypes: [], + }, + { + name: 'gpt-oss:120b', + displayName: 'gpt-oss:120b', + maxInputTokens: 131072, + supportedFileTypes: [], + }, + { + name: 'gpt-oss:20b', + displayName: 'gpt-oss:20b', + maxInputTokens: 131072, + supportedFileTypes: [], + }, + { + name: 'kimi-k2-thinking', + displayName: 'kimi-k2-thinking', + maxInputTokens: 262144, + supportedFileTypes: [], + }, + { + name: 'kimi-k2:1t', + displayName: 'kimi-k2:1t', + maxInputTokens: 262144, + supportedFileTypes: [], + }, + { + name: 'kimi-k2.5', + displayName: 'kimi-k2.5', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + }, + { + name: 'minimax-m2', + displayName: 'minimax-m2', + maxInputTokens: 204800, + supportedFileTypes: [], + }, + { + name: 'minimax-m2.1', + displayName: 'minimax-m2.1', + maxInputTokens: 204800, + supportedFileTypes: [], + }, + { + name: 'minimax-m2.5', + displayName: 'minimax-m2.5', + maxInputTokens: 204800, + supportedFileTypes: [], + }, + { + name: 'ministral-3:14b', + displayName: 'ministral-3:14b', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + }, + { + name: 'ministral-3:3b', + displayName: 'ministral-3:3b', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + }, + { + name: 'ministral-3:8b', + displayName: 'ministral-3:8b', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + }, + { + name: 'mistral-large-3:675b', + displayName: 'mistral-large-3:675b', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + }, + { + name: 'nemotron-3-nano:30b', + displayName: 'nemotron-3-nano:30b', + maxInputTokens: 1048576, + supportedFileTypes: [], + }, + { + name: 'qwen3-coder-next', + displayName: 'qwen3-coder-next', + maxInputTokens: 262144, + supportedFileTypes: [], + }, + { + name: 'qwen3-coder:480b', + displayName: 'qwen3-coder:480b', + maxInputTokens: 262144, + supportedFileTypes: [], + }, + { + name: 'qwen3-next:80b', + displayName: 'qwen3-next:80b', + maxInputTokens: 262144, + supportedFileTypes: [], + }, + { + name: 'qwen3-vl:235b', + displayName: 'qwen3-vl:235b', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + }, + { + name: 'qwen3-vl:235b-instruct', + displayName: 'qwen3-vl:235b-instruct', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + }, + { + name: 'qwen3.5:397b', + displayName: 'qwen3.5:397b', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + }, + { + name: 'rnj-1:8b', + displayName: 'rnj-1:8b', + maxInputTokens: 32768, + supportedFileTypes: [], + }, + ], + openai: [ + { + name: 'gpt-3.5-turbo', + displayName: 'GPT-3.5-turbo', + maxInputTokens: 16385, + supportedFileTypes: [], + pricing: { + inputPerM: 0.5, + outputPerM: 1.5, + cacheReadPerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4', + displayName: 'GPT-4', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 30, + outputPerM: 60, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4-turbo', + displayName: 'GPT-4 Turbo', + maxInputTokens: 128000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 10, + outputPerM: 30, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4.1', + displayName: 'GPT-4.1', + maxInputTokens: 1047576, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 2, + outputPerM: 8, + cacheReadPerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4.1-mini', + displayName: 'GPT-4.1 mini', + maxInputTokens: 1047576, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0.4, + outputPerM: 1.6, + cacheReadPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4.1-nano', + displayName: 'GPT-4.1 nano', + maxInputTokens: 1047576, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.4, + cacheReadPerM: 0.03, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4o', + displayName: 'GPT-4o', + maxInputTokens: 128000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 2.5, + outputPerM: 10, + cacheReadPerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4o-2024-05-13', + displayName: 'GPT-4o (2024-05-13)', + maxInputTokens: 128000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 5, + outputPerM: 15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4o-2024-08-06', + displayName: 'GPT-4o (2024-08-06)', + maxInputTokens: 128000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 2.5, + outputPerM: 10, + cacheReadPerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4o-2024-11-20', + displayName: 'GPT-4o (2024-11-20)', + maxInputTokens: 128000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 2.5, + outputPerM: 10, + cacheReadPerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-4o-mini', + displayName: 'GPT-4o mini', + maxInputTokens: 128000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + cacheReadPerM: 0.08, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5', + displayName: 'GPT-5', + maxInputTokens: 272000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5-chat-latest', + displayName: 'GPT-5 Chat (latest)', + maxInputTokens: 272000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5-codex', + displayName: 'GPT-5-Codex', + maxInputTokens: 272000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5-mini', + displayName: 'GPT-5 Mini', + maxInputTokens: 272000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0.25, + outputPerM: 2, + cacheReadPerM: 0.025, + currency: 'USD', + unit: 'per_million_tokens', + }, + default: true, + }, + { + name: 'gpt-5-nano', + displayName: 'GPT-5 Nano', + maxInputTokens: 272000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0.05, + outputPerM: 0.4, + cacheReadPerM: 0.005, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5-pro', + displayName: 'GPT-5 Pro', + maxInputTokens: 272000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 15, + outputPerM: 120, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.1', + displayName: 'GPT-5.1', + maxInputTokens: 272000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.13, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.1-chat-latest', + displayName: 'GPT-5.1 Chat', + maxInputTokens: 128000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.1-codex', + displayName: 'GPT-5.1 Codex', + maxInputTokens: 272000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.1-codex-max', + displayName: 'GPT-5.1 Codex Max', + maxInputTokens: 272000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.1-codex-mini', + displayName: 'GPT-5.1 Codex mini', + maxInputTokens: 272000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0.25, + outputPerM: 2, + cacheReadPerM: 0.025, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.2', + displayName: 'GPT-5.2', + maxInputTokens: 272000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1.75, + outputPerM: 14, + cacheReadPerM: 0.175, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.2-chat-latest', + displayName: 'GPT-5.2 Chat', + maxInputTokens: 128000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1.75, + outputPerM: 14, + cacheReadPerM: 0.175, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.2-codex', + displayName: 'GPT-5.2 Codex', + maxInputTokens: 272000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1.75, + outputPerM: 14, + cacheReadPerM: 0.175, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.2-pro', + displayName: 'GPT-5.2 Pro', + maxInputTokens: 272000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 21, + outputPerM: 168, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.3-codex', + displayName: 'GPT-5.3 Codex', + maxInputTokens: 272000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1.75, + outputPerM: 14, + cacheReadPerM: 0.175, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.3-codex-spark', + displayName: 'GPT-5.3 Codex Spark', + maxInputTokens: 100000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1.75, + outputPerM: 14, + cacheReadPerM: 0.175, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'o1', + displayName: 'o1', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 15, + outputPerM: 60, + cacheReadPerM: 7.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'o1-mini', + displayName: 'o1-mini', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 1.1, + outputPerM: 4.4, + cacheReadPerM: 0.55, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'o1-preview', + displayName: 'o1-preview', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 15, + outputPerM: 60, + cacheReadPerM: 7.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'o1-pro', + displayName: 'o1-pro', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 150, + outputPerM: 600, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'o3', + displayName: 'o3', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 2, + outputPerM: 8, + cacheReadPerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'o3-deep-research', + displayName: 'o3-deep-research', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 10, + outputPerM: 40, + cacheReadPerM: 2.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'o3-mini', + displayName: 'o3-mini', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 1.1, + outputPerM: 4.4, + cacheReadPerM: 0.55, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'o3-pro', + displayName: 'o3-pro', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 20, + outputPerM: 80, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'o4-mini', + displayName: 'o4-mini', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1.1, + outputPerM: 4.4, + cacheReadPerM: 0.28, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'o4-mini-deep-research', + displayName: 'o4-mini-deep-research', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 2, + outputPerM: 8, + cacheReadPerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + opencode: [ + { + name: 'big-pickle', + displayName: 'Big Pickle', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-3-5-haiku', + displayName: 'Claude Haiku 3.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0.8, + outputPerM: 4, + cacheReadPerM: 0.08, + cacheWritePerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-haiku-4-5', + displayName: 'Claude Haiku 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1, + outputPerM: 5, + cacheReadPerM: 0.1, + cacheWritePerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-opus-4-1', + displayName: 'Claude Opus 4.1', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 15, + outputPerM: 75, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-opus-4-5', + displayName: 'Claude Opus 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-opus-4-6', + displayName: 'Claude Opus 4.6', + maxInputTokens: 1000000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-sonnet-4', + displayName: 'Claude Sonnet 4', + maxInputTokens: 1000000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-sonnet-4-5', + displayName: 'Claude Sonnet 4.5', + maxInputTokens: 1000000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-sonnet-4-6', + displayName: 'Claude Sonnet 4.6', + maxInputTokens: 1000000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-3-flash', + displayName: 'Gemini 3 Flash', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.5, + outputPerM: 3, + cacheReadPerM: 0.05, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-3-pro', + displayName: 'Gemini 3 Pro', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 2, + outputPerM: 12, + cacheReadPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-3.1-pro', + displayName: 'Gemini 3.1 Pro Preview', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 2, + outputPerM: 12, + cacheReadPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-4.6', + displayName: 'GLM-4.6', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.2, + cacheReadPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-4.7', + displayName: 'GLM-4.7', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.2, + cacheReadPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-4.7-free', + displayName: 'GLM-4.7 Free', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-5', + displayName: 'GLM-5', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 3.2, + cacheReadPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-5-free', + displayName: 'GLM-5 Free', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5', + displayName: 'GPT-5', + maxInputTokens: 272000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.07, + outputPerM: 8.5, + cacheReadPerM: 0.107, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5-codex', + displayName: 'GPT-5 Codex', + maxInputTokens: 272000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.07, + outputPerM: 8.5, + cacheReadPerM: 0.107, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5-nano', + displayName: 'GPT-5 Nano', + maxInputTokens: 272000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.1', + displayName: 'GPT-5.1', + maxInputTokens: 272000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.07, + outputPerM: 8.5, + cacheReadPerM: 0.107, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.1-codex', + displayName: 'GPT-5.1 Codex', + maxInputTokens: 272000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.07, + outputPerM: 8.5, + cacheReadPerM: 0.107, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.1-codex-max', + displayName: 'GPT-5.1 Codex Max', + maxInputTokens: 272000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.1-codex-mini', + displayName: 'GPT-5.1 Codex Mini', + maxInputTokens: 272000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.25, + outputPerM: 2, + cacheReadPerM: 0.025, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.2', + displayName: 'GPT-5.2', + maxInputTokens: 272000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.75, + outputPerM: 14, + cacheReadPerM: 0.175, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.2-codex', + displayName: 'GPT-5.2 Codex', + maxInputTokens: 272000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1.75, + outputPerM: 14, + cacheReadPerM: 0.175, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'grok-code', + displayName: 'Grok Code Fast 1', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2', + displayName: 'Kimi K2', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.4, + outputPerM: 2.5, + cacheReadPerM: 0.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2-thinking', + displayName: 'Kimi K2 Thinking', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.4, + outputPerM: 2.5, + cacheReadPerM: 0.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2.5', + displayName: 'Kimi K2.5', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.6, + outputPerM: 3, + cacheReadPerM: 0.08, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2.5-free', + displayName: 'Kimi K2.5 Free', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'minimax-m2.1', + displayName: 'MiniMax M2.1', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + cacheReadPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'minimax-m2.1-free', + displayName: 'MiniMax M2.1 Free', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'minimax-m2.5', + displayName: 'MiniMax M2.5', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + cacheReadPerM: 0.06, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'minimax-m2.5-free', + displayName: 'MiniMax M2.5 Free', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen3-coder', + displayName: 'Qwen3 Coder', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.45, + outputPerM: 1.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'trinity-large-preview-free', + displayName: 'Trinity Large Preview', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + openrouter: [ + { + name: 'allenai/molmo-2-8b:free', + displayName: 'Molmo2 8B (free)', + maxInputTokens: 36864, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-3.5-haiku', + displayName: 'Claude Haiku 3.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0.8, + outputPerM: 4, + cacheReadPerM: 0.08, + cacheWritePerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-3.7-sonnet', + displayName: 'Claude Sonnet 3.7', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 15, + outputPerM: 75, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-haiku-4.5', + displayName: 'Claude Haiku 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1, + outputPerM: 5, + cacheReadPerM: 0.1, + cacheWritePerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-opus-4', + displayName: 'Claude Opus 4', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 15, + outputPerM: 75, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-opus-4.1', + displayName: 'Claude Opus 4.1', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 15, + outputPerM: 75, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-opus-4.5', + displayName: 'Claude Opus 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-opus-4.6', + displayName: 'Claude Opus 4.6', + maxInputTokens: 1000000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-sonnet-4', + displayName: 'Claude Sonnet 4', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-sonnet-4.5', + displayName: 'Claude Sonnet 4.5', + maxInputTokens: 1000000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-sonnet-4.6', + displayName: 'Claude Sonnet 4.6', + maxInputTokens: 1000000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'arcee-ai/trinity-large-preview:free', + displayName: 'Trinity Large Preview', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'arcee-ai/trinity-mini:free', + displayName: 'Trinity Mini', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'black-forest-labs/flux.2-flex', + displayName: 'FLUX.2 Flex', + maxInputTokens: 67344, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'black-forest-labs/flux.2-klein-4b', + displayName: 'FLUX.2 Klein 4B', + maxInputTokens: 40960, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'black-forest-labs/flux.2-max', + displayName: 'FLUX.2 Max', + maxInputTokens: 46864, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'black-forest-labs/flux.2-pro', + displayName: 'FLUX.2 Pro', + maxInputTokens: 46864, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'bytedance-seed/seedream-4.5', + displayName: 'Seedream 4.5', + maxInputTokens: 4096, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'cognitivecomputations/dolphin-mistral-24b-venice-edition:free', + displayName: 'Uncensored (free)', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'cognitivecomputations/dolphin3.0-mistral-24b', + displayName: 'Dolphin3.0 Mistral 24B', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'cognitivecomputations/dolphin3.0-r1-mistral-24b', + displayName: 'Dolphin3.0 R1 Mistral 24B', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-chat-v3-0324', + displayName: 'DeepSeek V3 0324', + maxInputTokens: 16384, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-chat-v3.1', + displayName: 'DeepSeek-V3.1', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-r1-0528-qwen3-8b:free', + displayName: 'Deepseek R1 0528 Qwen3 8B (free)', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-r1-0528:free', + displayName: 'R1 0528 (free)', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-r1-distill-llama-70b', + displayName: 'DeepSeek R1 Distill Llama 70B', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-r1-distill-qwen-14b', + displayName: 'DeepSeek R1 Distill Qwen 14B', + maxInputTokens: 64000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-r1:free', + displayName: 'R1 (free)', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-v3-base:free', + displayName: 'DeepSeek V3 Base (free)', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-v3.1-terminus', + displayName: 'DeepSeek V3.1 Terminus', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.27, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-v3.1-terminus:exacto', + displayName: 'DeepSeek V3.1 Terminus (exacto)', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.27, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-v3.2', + displayName: 'DeepSeek V3.2', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.28, + outputPerM: 0.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-v3.2-speciale', + displayName: 'DeepSeek V3.2 Speciale', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.27, + outputPerM: 0.41, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'featherless/qwerky-72b', + displayName: 'Qwerky 72B', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.0-flash-001', + displayName: 'Gemini 2.0 Flash', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.4, + cacheReadPerM: 0.025, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.0-flash-exp:free', + displayName: 'Gemini 2.0 Flash Experimental (free)', + maxInputTokens: 1048576, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.5-flash', + displayName: 'Gemini 2.5 Flash', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.3, + outputPerM: 2.5, + cacheReadPerM: 0.0375, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.5-flash-lite', + displayName: 'Gemini 2.5 Flash Lite', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.4, + cacheReadPerM: 0.025, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.5-flash-lite-preview-09-2025', + displayName: 'Gemini 2.5 Flash Lite Preview 09-25', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.4, + cacheReadPerM: 0.025, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.5-flash-preview-09-2025', + displayName: 'Gemini 2.5 Flash Preview 09-25', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.3, + outputPerM: 2.5, + cacheReadPerM: 0.031, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.5-pro', + displayName: 'Gemini 2.5 Pro', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.31, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.5-pro-preview-05-06', + displayName: 'Gemini 2.5 Pro Preview 05-06', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.31, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.5-pro-preview-06-05', + displayName: 'Gemini 2.5 Pro Preview 06-05', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.31, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-3-flash-preview', + displayName: 'Gemini 3 Flash Preview', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.5, + outputPerM: 3, + cacheReadPerM: 0.05, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-3-pro-preview', + displayName: 'Gemini 3 Pro Preview', + maxInputTokens: 1050000, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 2, + outputPerM: 12, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-3.1-pro-preview', + displayName: 'Gemini 3.1 Pro Preview', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 2, + outputPerM: 12, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-2-9b-it', + displayName: 'Gemma 2 9B', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0.03, + outputPerM: 0.09, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-3-12b-it', + displayName: 'Gemma 3 12B', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.03, + outputPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-3-12b-it:free', + displayName: 'Gemma 3 12B (free)', + maxInputTokens: 32768, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-3-27b-it', + displayName: 'Gemma 3 27B', + maxInputTokens: 96000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.04, + outputPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-3-27b-it:free', + displayName: 'Gemma 3 27B (free)', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-3-4b-it', + displayName: 'Gemma 3 4B', + maxInputTokens: 96000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.01703, + outputPerM: 0.06815, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-3-4b-it:free', + displayName: 'Gemma 3 4B (free)', + maxInputTokens: 32768, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-3n-e2b-it:free', + displayName: 'Gemma 3n 2B (free)', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-3n-e4b-it', + displayName: 'Gemma 3n 4B', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.02, + outputPerM: 0.04, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-3n-e4b-it:free', + displayName: 'Gemma 3n 4B (free)', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kwaipilot/kat-coder-pro:free', + displayName: 'Kat Coder Pro (free)', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'liquid/lfm-2.5-1.2b-instruct:free', + displayName: 'LFM2.5-1.2B-Instruct (free)', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'liquid/lfm-2.5-1.2b-thinking:free', + displayName: 'LFM2.5-1.2B-Thinking (free)', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/llama-3.1-405b-instruct:free', + displayName: 'Llama 3.1 405B Instruct (free)', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/llama-3.2-11b-vision-instruct', + displayName: 'Llama 3.2 11B Vision Instruct', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/llama-3.2-3b-instruct:free', + displayName: 'Llama 3.2 3B Instruct (free)', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/llama-3.3-70b-instruct:free', + displayName: 'Llama 3.3 70B Instruct (free)', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/llama-4-scout:free', + displayName: 'Llama 4 Scout (free)', + maxInputTokens: 64000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'microsoft/mai-ds-r1:free', + displayName: 'MAI DS R1 (free)', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'minimax/minimax-01', + displayName: 'MiniMax-01', + maxInputTokens: 1000000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.2, + outputPerM: 1.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'minimax/minimax-m1', + displayName: 'MiniMax M1', + maxInputTokens: 1000000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.4, + outputPerM: 2.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'minimax/minimax-m2', + displayName: 'MiniMax M2', + maxInputTokens: 196600, + supportedFileTypes: [], + pricing: { + inputPerM: 0.28, + outputPerM: 1.15, + cacheReadPerM: 0.28, + cacheWritePerM: 1.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'minimax/minimax-m2.1', + displayName: 'MiniMax M2.1', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'minimax/minimax-m2.5', + displayName: 'MiniMax M2.5', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + cacheReadPerM: 0.03, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/codestral-2508', + displayName: 'Codestral 2508', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 0.9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/devstral-2512', + displayName: 'Devstral 2 2512', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/devstral-2512:free', + displayName: 'Devstral 2 2512 (free)', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/devstral-medium-2507', + displayName: 'Devstral Medium', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.4, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/devstral-small-2505', + displayName: 'Devstral Small', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.06, + outputPerM: 0.12, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/devstral-small-2505:free', + displayName: 'Devstral Small 2505 (free)', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/devstral-small-2507', + displayName: 'Devstral Small 1.1', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/mistral-7b-instruct:free', + displayName: 'Mistral 7B Instruct (free)', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/mistral-medium-3', + displayName: 'Mistral Medium 3', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.4, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/mistral-medium-3.1', + displayName: 'Mistral Medium 3.1', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.4, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/mistral-nemo:free', + displayName: 'Mistral Nemo (free)', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/mistral-small-3.1-24b-instruct', + displayName: 'Mistral Small 3.1 24B Instruct', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/mistral-small-3.2-24b-instruct', + displayName: 'Mistral Small 3.2 24B Instruct', + maxInputTokens: 96000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistralai/mistral-small-3.2-24b-instruct:free', + displayName: 'Mistral Small 3.2 24B (free)', + maxInputTokens: 96000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-dev-72b:free', + displayName: 'Kimi Dev 72b (free)', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2', + displayName: 'Kimi K2', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.55, + outputPerM: 2.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2-0905', + displayName: 'Kimi K2 Instruct 0905', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2-0905:exacto', + displayName: 'Kimi K2 Instruct 0905 (exacto)', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2-thinking', + displayName: 'Kimi K2 Thinking', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.5, + cacheReadPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2:free', + displayName: 'Kimi K2 (free)', + maxInputTokens: 32800, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2.5', + displayName: 'Kimi K2.5', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.6, + outputPerM: 3, + cacheReadPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nousresearch/deephermes-3-llama-3-8b-preview', + displayName: 'DeepHermes 3 Llama 3 8B Preview', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nousresearch/hermes-3-llama-3.1-405b:free', + displayName: 'Hermes 3 405B Instruct (free)', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nousresearch/hermes-4-405b', + displayName: 'Hermes 4 405B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nousresearch/hermes-4-70b', + displayName: 'Hermes 4 70B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.13, + outputPerM: 0.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nvidia/nemotron-3-nano-30b-a3b:free', + displayName: 'Nemotron 3 Nano 30B A3B (free)', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nvidia/nemotron-nano-12b-v2-vl:free', + displayName: 'Nemotron Nano 12B 2 VL (free)', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nvidia/nemotron-nano-9b-v2', + displayName: 'nvidia-nemotron-nano-9b-v2', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.04, + outputPerM: 0.16, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nvidia/nemotron-nano-9b-v2:free', + displayName: 'Nemotron Nano 9B V2 (free)', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4.1', + displayName: 'GPT-4.1', + maxInputTokens: 1047576, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2, + outputPerM: 8, + cacheReadPerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4.1-mini', + displayName: 'GPT-4.1 Mini', + maxInputTokens: 1047576, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.4, + outputPerM: 1.6, + cacheReadPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4o-mini', + displayName: 'GPT-4o-mini', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + cacheReadPerM: 0.08, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5', + displayName: 'GPT-5', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5-chat', + displayName: 'GPT-5 Chat (latest)', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5-codex', + displayName: 'GPT-5 Codex', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5-image', + displayName: 'GPT-5 Image', + maxInputTokens: 400000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 5, + outputPerM: 10, + cacheReadPerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5-mini', + displayName: 'GPT-5 Mini', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.25, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5-nano', + displayName: 'GPT-5 Nano', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.05, + outputPerM: 0.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5-pro', + displayName: 'GPT-5 Pro', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 15, + outputPerM: 120, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.1', + displayName: 'GPT-5.1', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.1-chat', + displayName: 'GPT-5.1 Chat', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.1-codex', + displayName: 'GPT-5.1-Codex', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.1-codex-max', + displayName: 'GPT-5.1-Codex-Max', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.1, + outputPerM: 9, + cacheReadPerM: 0.11, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.1-codex-mini', + displayName: 'GPT-5.1-Codex-Mini', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.25, + outputPerM: 2, + cacheReadPerM: 0.025, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.2', + displayName: 'GPT-5.2', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.75, + outputPerM: 14, + cacheReadPerM: 0.175, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.2-chat', + displayName: 'GPT-5.2 Chat', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.75, + outputPerM: 14, + cacheReadPerM: 0.175, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.2-codex', + displayName: 'GPT-5.2-Codex', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.75, + outputPerM: 14, + cacheReadPerM: 0.175, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.2-pro', + displayName: 'GPT-5.2 Pro', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 21, + outputPerM: 168, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-120b', + displayName: 'GPT OSS 120B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.072, + outputPerM: 0.28, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-120b:exacto', + displayName: 'GPT OSS 120B (exacto)', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.05, + outputPerM: 0.24, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-120b:free', + displayName: 'gpt-oss-120b (free)', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-20b', + displayName: 'GPT OSS 20B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.05, + outputPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-20b:free', + displayName: 'gpt-oss-20b (free)', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-safeguard-20b', + displayName: 'GPT OSS Safeguard 20B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.075, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/o4-mini', + displayName: 'o4 Mini', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.1, + outputPerM: 4.4, + cacheReadPerM: 0.28, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openrouter/aurora-alpha', + displayName: 'Aurora Alpha', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openrouter/sherlock-dash-alpha', + displayName: 'Sherlock Dash Alpha', + maxInputTokens: 1840000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openrouter/sherlock-think-alpha', + displayName: 'Sherlock Think Alpha', + maxInputTokens: 1840000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'prime-intellect/intellect-3', + displayName: 'Intellect 3', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 1.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen-2.5-coder-32b-instruct', + displayName: 'Qwen2.5 Coder 32B Instruct', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen-2.5-vl-7b-instruct:free', + displayName: 'Qwen2.5-VL 7B Instruct (free)', + maxInputTokens: 32768, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen2.5-vl-32b-instruct:free', + displayName: 'Qwen2.5 VL 32B Instruct (free)', + maxInputTokens: 8192, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen2.5-vl-72b-instruct', + displayName: 'Qwen2.5 VL 72B Instruct', + maxInputTokens: 32768, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen2.5-vl-72b-instruct:free', + displayName: 'Qwen2.5 VL 72B Instruct (free)', + maxInputTokens: 32768, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-14b:free', + displayName: 'Qwen3 14B (free)', + maxInputTokens: 40960, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-235b-a22b-07-25', + displayName: 'Qwen3 235B A22B Instruct 2507', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0.85, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-235b-a22b-07-25:free', + displayName: 'Qwen3 235B A22B Instruct 2507 (free)', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-235b-a22b-thinking-2507', + displayName: 'Qwen3 235B A22B Thinking 2507', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.078, + outputPerM: 0.312, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-235b-a22b:free', + displayName: 'Qwen3 235B A22B (free)', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-30b-a3b-instruct-2507', + displayName: 'Qwen3 30B A3B Instruct 2507', + maxInputTokens: 262000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-30b-a3b-thinking-2507', + displayName: 'Qwen3 30B A3B Thinking 2507', + maxInputTokens: 262000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-30b-a3b:free', + displayName: 'Qwen3 30B A3B (free)', + maxInputTokens: 40960, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-32b:free', + displayName: 'Qwen3 32B (free)', + maxInputTokens: 40960, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-4b:free', + displayName: 'Qwen3 4B (free)', + maxInputTokens: 40960, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-8b:free', + displayName: 'Qwen3 8B (free)', + maxInputTokens: 40960, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-coder', + displayName: 'Qwen3 Coder', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-coder-30b-a3b-instruct', + displayName: 'Qwen3 Coder 30B A3B Instruct', + maxInputTokens: 160000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.07, + outputPerM: 0.27, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-coder-flash', + displayName: 'Qwen3 Coder Flash', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-coder:exacto', + displayName: 'Qwen3 Coder (exacto)', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.38, + outputPerM: 1.53, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-coder:free', + displayName: 'Qwen3 Coder 480B A35B Instruct (free)', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-max', + displayName: 'Qwen3 Max', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 1.2, + outputPerM: 6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-next-80b-a3b-instruct', + displayName: 'Qwen3 Next 80B A3B Instruct', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.14, + outputPerM: 1.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-next-80b-a3b-instruct:free', + displayName: 'Qwen3 Next 80B A3B Instruct (free)', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3-next-80b-a3b-thinking', + displayName: 'Qwen3 Next 80B A3B Thinking', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.14, + outputPerM: 1.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3.5-397b-a17b', + displayName: 'Qwen3.5 397B A17B', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.6, + outputPerM: 3.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwen3.5-plus-02-15', + displayName: 'Qwen3.5 Plus 2026-02-15', + maxInputTokens: 1000000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.4, + outputPerM: 2.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen/qwq-32b:free', + displayName: 'QwQ 32B (free)', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'rekaai/reka-flash-3', + displayName: 'Reka Flash 3', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'sarvamai/sarvam-m:free', + displayName: 'Sarvam-M (free)', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'sourceful/riverflow-v2-fast-preview', + displayName: 'Riverflow V2 Fast Preview', + maxInputTokens: 8192, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'sourceful/riverflow-v2-max-preview', + displayName: 'Riverflow V2 Max Preview', + maxInputTokens: 8192, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'sourceful/riverflow-v2-standard-preview', + displayName: 'Riverflow V2 Standard Preview', + maxInputTokens: 8192, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'stepfun/step-3.5-flash', + displayName: 'Step 3.5 Flash', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.3, + cacheReadPerM: 0.02, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'stepfun/step-3.5-flash:free', + displayName: 'Step 3.5 Flash (free)', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'thudm/glm-z1-32b:free', + displayName: 'GLM Z1 32B (free)', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'tngtech/deepseek-r1t2-chimera:free', + displayName: 'DeepSeek R1T2 Chimera (free)', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'tngtech/tng-r1t-chimera:free', + displayName: 'R1T Chimera (free)', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'x-ai/grok-3', + displayName: 'Grok 3', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.75, + cacheWritePerM: 15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'x-ai/grok-3-beta', + displayName: 'Grok 3 Beta', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.75, + cacheWritePerM: 15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'x-ai/grok-3-mini', + displayName: 'Grok 3 Mini', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 0.5, + cacheReadPerM: 0.075, + cacheWritePerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'x-ai/grok-3-mini-beta', + displayName: 'Grok 3 Mini Beta', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 0.5, + cacheReadPerM: 0.075, + cacheWritePerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'x-ai/grok-4', + displayName: 'Grok 4', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.75, + cacheWritePerM: 15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'x-ai/grok-4-fast', + displayName: 'Grok 4 Fast', + maxInputTokens: 2000000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.2, + outputPerM: 0.5, + cacheReadPerM: 0.05, + cacheWritePerM: 0.05, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'x-ai/grok-4.1-fast', + displayName: 'Grok 4.1 Fast', + maxInputTokens: 2000000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.2, + outputPerM: 0.5, + cacheReadPerM: 0.05, + cacheWritePerM: 0.05, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'x-ai/grok-code-fast-1', + displayName: 'Grok Code Fast 1', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 1.5, + cacheReadPerM: 0.02, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'xiaomi/mimo-v2-flash', + displayName: 'MiMo-V2-Flash', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.3, + cacheReadPerM: 0.01, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'z-ai/glm-4.5', + displayName: 'GLM 4.5', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'z-ai/glm-4.5-air', + displayName: 'GLM 4.5 Air', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 1.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'z-ai/glm-4.5-air:free', + displayName: 'GLM 4.5 Air (free)', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'z-ai/glm-4.5v', + displayName: 'GLM 4.5V', + maxInputTokens: 64000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.6, + outputPerM: 1.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'z-ai/glm-4.6', + displayName: 'GLM 4.6', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.2, + cacheReadPerM: 0.11, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'z-ai/glm-4.6:exacto', + displayName: 'GLM 4.6 (exacto)', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 1.9, + cacheReadPerM: 0.11, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'z-ai/glm-4.7', + displayName: 'GLM-4.7', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.2, + cacheReadPerM: 0.11, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'z-ai/glm-4.7-flash', + displayName: 'GLM-4.7-Flash', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.07, + outputPerM: 0.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'z-ai/glm-5', + displayName: 'GLM-5', + maxInputTokens: 202752, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 3.2, + cacheReadPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + ovhcloud: [ + { + name: 'deepseek-r1-distill-llama-70b', + displayName: 'DeepSeek-R1-Distill-Llama-70B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.74, + outputPerM: 0.74, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-oss-120b', + displayName: 'gpt-oss-120b', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.09, + outputPerM: 0.47, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-oss-20b', + displayName: 'gpt-oss-20b', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.05, + outputPerM: 0.18, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'llama-3.1-8b-instruct', + displayName: 'Llama-3.1-8B-Instruct', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.11, + outputPerM: 0.11, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama-3_3-70b-instruct', + displayName: 'Meta-Llama-3_3-70B-Instruct', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.74, + outputPerM: 0.74, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral-7b-instruct-v0.3', + displayName: 'Mistral-7B-Instruct-v0.3', + maxInputTokens: 65536, + supportedFileTypes: [], + pricing: { + inputPerM: 0.11, + outputPerM: 0.11, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral-nemo-instruct-2407', + displayName: 'Mistral-Nemo-Instruct-2407', + maxInputTokens: 65536, + supportedFileTypes: [], + pricing: { + inputPerM: 0.14, + outputPerM: 0.14, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral-small-3.2-24b-instruct-2506', + displayName: 'Mistral-Small-3.2-24B-Instruct-2506', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.31, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mixtral-8x7b-instruct-v0.1', + displayName: 'Mixtral-8x7B-Instruct-v0.1', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.7, + outputPerM: 0.7, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen2.5-coder-32b-instruct', + displayName: 'Qwen2.5-Coder-32B-Instruct', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.96, + outputPerM: 0.96, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen2.5-vl-72b-instruct', + displayName: 'Qwen2.5-VL-72B-Instruct', + maxInputTokens: 32768, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.01, + outputPerM: 1.01, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen3-32b', + displayName: 'Qwen3-32B', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.09, + outputPerM: 0.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen3-coder-30b-a3b-instruct', + displayName: 'Qwen3-Coder-30B-A3B-Instruct', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.07, + outputPerM: 0.26, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + perplexity: [ + { + name: 'sonar', + displayName: 'Sonar', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'sonar-deep-research', + displayName: 'Perplexity Sonar Deep Research', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 2, + outputPerM: 8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'sonar-pro', + displayName: 'Sonar Pro', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'sonar-reasoning-pro', + displayName: 'Sonar Reasoning Pro', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2, + outputPerM: 8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + poe: [ + { + name: 'anthropic/claude-haiku-3', + displayName: 'Claude-Haiku-3', + maxInputTokens: 189096, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0.21, + outputPerM: 1.1, + cacheReadPerM: 0.021, + cacheWritePerM: 0.26, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-haiku-3.5', + displayName: 'Claude-Haiku-3.5', + maxInputTokens: 189096, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0.68, + outputPerM: 3.4, + cacheReadPerM: 0.068, + cacheWritePerM: 0.85, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-haiku-4.5', + displayName: 'Claude-Haiku-4.5', + maxInputTokens: 192000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0.85, + outputPerM: 4.3, + cacheReadPerM: 0.085, + cacheWritePerM: 1.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-opus-4', + displayName: 'Claude-Opus-4', + maxInputTokens: 192512, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 13, + outputPerM: 64, + cacheReadPerM: 1.3, + cacheWritePerM: 16, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-opus-4.1', + displayName: 'Claude-Opus-4.1', + maxInputTokens: 196608, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 13, + outputPerM: 64, + cacheReadPerM: 1.3, + cacheWritePerM: 16, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-opus-4.5', + displayName: 'Claude-Opus-4.5', + maxInputTokens: 196608, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 4.3, + outputPerM: 21, + cacheReadPerM: 0.43, + cacheWritePerM: 5.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-opus-4.6', + displayName: 'Claude-Opus-4.6', + maxInputTokens: 983040, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 4.3, + outputPerM: 21, + cacheReadPerM: 0.43, + cacheWritePerM: 5.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-sonnet-3.5', + displayName: 'Claude-Sonnet-3.5', + maxInputTokens: 189096, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 2.6, + outputPerM: 13, + cacheReadPerM: 0.26, + cacheWritePerM: 3.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-sonnet-3.5-june', + displayName: 'Claude-Sonnet-3.5-June', + maxInputTokens: 189096, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 2.6, + outputPerM: 13, + cacheReadPerM: 0.26, + cacheWritePerM: 3.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-sonnet-3.7', + displayName: 'Claude-Sonnet-3.7', + maxInputTokens: 196608, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 2.6, + outputPerM: 13, + cacheReadPerM: 0.26, + cacheWritePerM: 3.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-sonnet-4', + displayName: 'Claude-Sonnet-4', + maxInputTokens: 983040, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 2.6, + outputPerM: 13, + cacheReadPerM: 0.26, + cacheWritePerM: 3.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-sonnet-4.5', + displayName: 'Claude-Sonnet-4.5', + maxInputTokens: 983040, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 2.6, + outputPerM: 13, + cacheReadPerM: 0.26, + cacheWritePerM: 3.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-sonnet-4.6', + displayName: 'Claude-Sonnet-4.6', + maxInputTokens: 983040, + supportedFileTypes: ['pdf'], + pricing: { + inputPerM: 2.6, + outputPerM: 13, + cacheReadPerM: 0.26, + cacheWritePerM: 3.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'cerebras/gpt-oss-120b-cs', + displayName: 'gpt-oss-120b-cs', + maxInputTokens: 0, + supportedFileTypes: [], + }, + { + name: 'cerebras/llama-3.1-8b-cs', + displayName: 'llama-3.1-8b-cs', + maxInputTokens: 0, + supportedFileTypes: [], + }, + { + name: 'cerebras/llama-3.3-70b-cs', + displayName: 'llama-3.3-70b-cs', + maxInputTokens: 0, + supportedFileTypes: [], + }, + { + name: 'cerebras/qwen3-235b-2507-cs', + displayName: 'qwen3-235b-2507-cs', + maxInputTokens: 0, + supportedFileTypes: [], + }, + { + name: 'cerebras/qwen3-32b-cs', + displayName: 'qwen3-32b-cs', + maxInputTokens: 0, + supportedFileTypes: [], + }, + { + name: 'elevenlabs/elevenlabs-music', + displayName: 'ElevenLabs-Music', + maxInputTokens: 2000, + supportedFileTypes: [], + }, + { + name: 'elevenlabs/elevenlabs-v2.5-turbo', + displayName: 'ElevenLabs-v2.5-Turbo', + maxInputTokens: 128000, + supportedFileTypes: [], + }, + { + name: 'elevenlabs/elevenlabs-v3', + displayName: 'ElevenLabs-v3', + maxInputTokens: 128000, + supportedFileTypes: [], + }, + { + name: 'google/gemini-2.0-flash', + displayName: 'Gemini-2.0-Flash', + maxInputTokens: 990000, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.42, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.0-flash-lite', + displayName: 'Gemini-2.0-Flash-Lite', + maxInputTokens: 990000, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0.052, + outputPerM: 0.21, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.5-flash', + displayName: 'Gemini-2.5-Flash', + maxInputTokens: 1065535, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0.21, + outputPerM: 1.8, + cacheReadPerM: 0.021, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.5-flash-lite', + displayName: 'Gemini-2.5-Flash-Lite', + maxInputTokens: 1024000, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0.07, + outputPerM: 0.28, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.5-pro', + displayName: 'Gemini-2.5-Pro', + maxInputTokens: 1065535, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0.87, + outputPerM: 7, + cacheReadPerM: 0.087, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-3-flash', + displayName: 'Gemini-3-Flash', + maxInputTokens: 1048576, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0.4, + outputPerM: 2.4, + cacheReadPerM: 0.04, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-3-pro', + displayName: 'Gemini-3-Pro', + maxInputTokens: 1048576, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 1.6, + outputPerM: 9.6, + cacheReadPerM: 0.16, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-deep-research', + displayName: 'gemini-deep-research', + maxInputTokens: 1048576, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.6, + outputPerM: 9.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/imagen-3', + displayName: 'Imagen-3', + maxInputTokens: 480, + supportedFileTypes: [], + }, + { + name: 'google/imagen-3-fast', + displayName: 'Imagen-3-Fast', + maxInputTokens: 480, + supportedFileTypes: [], + }, + { + name: 'google/imagen-4', + displayName: 'Imagen-4', + maxInputTokens: 480, + supportedFileTypes: [], + }, + { + name: 'google/imagen-4-fast', + displayName: 'Imagen-4-Fast', + maxInputTokens: 480, + supportedFileTypes: [], + }, + { + name: 'google/imagen-4-ultra', + displayName: 'Imagen-4-Ultra', + maxInputTokens: 480, + supportedFileTypes: [], + }, + { + name: 'google/lyria', + displayName: 'Lyria', + maxInputTokens: 0, + supportedFileTypes: [], + }, + { + name: 'google/nano-banana', + displayName: 'Nano-Banana', + maxInputTokens: 65536, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.21, + outputPerM: 1.8, + cacheReadPerM: 0.021, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/nano-banana-pro', + displayName: 'Nano-Banana-Pro', + maxInputTokens: 65536, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2, + outputPerM: 12, + cacheReadPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/veo-2', + displayName: 'Veo-2', + maxInputTokens: 480, + supportedFileTypes: [], + }, + { + name: 'google/veo-3', + displayName: 'Veo-3', + maxInputTokens: 480, + supportedFileTypes: [], + }, + { + name: 'google/veo-3-fast', + displayName: 'Veo-3-Fast', + maxInputTokens: 480, + supportedFileTypes: [], + }, + { + name: 'google/veo-3.1', + displayName: 'Veo-3.1', + maxInputTokens: 480, + supportedFileTypes: [], + }, + { + name: 'google/veo-3.1-fast', + displayName: 'Veo-3.1-Fast', + maxInputTokens: 480, + supportedFileTypes: ['image'], + }, + { + name: 'ideogramai/ideogram', + displayName: 'Ideogram', + maxInputTokens: 150, + supportedFileTypes: ['image'], + }, + { + name: 'ideogramai/ideogram-v2', + displayName: 'Ideogram-v2', + maxInputTokens: 150, + supportedFileTypes: ['image'], + }, + { + name: 'ideogramai/ideogram-v2a', + displayName: 'Ideogram-v2a', + maxInputTokens: 150, + supportedFileTypes: [], + }, + { + name: 'ideogramai/ideogram-v2a-turbo', + displayName: 'Ideogram-v2a-Turbo', + maxInputTokens: 150, + supportedFileTypes: [], + }, + { + name: 'lumalabs/ray2', + displayName: 'Ray2', + maxInputTokens: 5000, + supportedFileTypes: ['image'], + }, + { + name: 'novita/glm-4.6', + displayName: 'GLM-4.6', + maxInputTokens: 0, + supportedFileTypes: [], + }, + { + name: 'novita/glm-4.6v', + displayName: 'glm-4.6v', + maxInputTokens: 131000, + supportedFileTypes: ['image'], + }, + { + name: 'novita/glm-4.7', + displayName: 'glm-4.7', + maxInputTokens: 205000, + supportedFileTypes: [], + }, + { + name: 'novita/glm-4.7-flash', + displayName: 'glm-4.7-flash', + maxInputTokens: 200000, + supportedFileTypes: [], + }, + { + name: 'novita/glm-4.7-n', + displayName: 'glm-4.7-n', + maxInputTokens: 205000, + supportedFileTypes: [], + }, + { + name: 'novita/kimi-k2-thinking', + displayName: 'kimi-k2-thinking', + maxInputTokens: 256000, + supportedFileTypes: [], + }, + { + name: 'novita/kimi-k2.5', + displayName: 'kimi-k2.5', + maxInputTokens: 256000, + supportedFileTypes: ['image'], + }, + { + name: 'novita/minimax-m2.1', + displayName: 'minimax-m2.1', + maxInputTokens: 205000, + supportedFileTypes: [], + }, + { + name: 'openai/chatgpt-4o-latest', + displayName: 'ChatGPT-4o-Latest', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 4.5, + outputPerM: 14, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/dall-e-3', + displayName: 'DALL-E-3', + maxInputTokens: 800, + supportedFileTypes: [], + }, + { + name: 'openai/gpt-3.5-turbo', + displayName: 'GPT-3.5-Turbo', + maxInputTokens: 16384, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.45, + outputPerM: 1.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-3.5-turbo-instruct', + displayName: 'GPT-3.5-Turbo-Instruct', + maxInputTokens: 3500, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.4, + outputPerM: 1.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-3.5-turbo-raw', + displayName: 'GPT-3.5-Turbo-Raw', + maxInputTokens: 4524, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.45, + outputPerM: 1.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4-classic', + displayName: 'GPT-4-Classic', + maxInputTokens: 8192, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 27, + outputPerM: 54, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4-classic-0314', + displayName: 'GPT-4-Classic-0314', + maxInputTokens: 8192, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 27, + outputPerM: 54, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4-turbo', + displayName: 'GPT-4-Turbo', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 9, + outputPerM: 27, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4.1', + displayName: 'GPT-4.1', + maxInputTokens: 1047576, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.8, + outputPerM: 7.2, + cacheReadPerM: 0.45, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4.1-mini', + displayName: 'GPT-4.1-mini', + maxInputTokens: 1047576, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.36, + outputPerM: 1.4, + cacheReadPerM: 0.09, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4.1-nano', + displayName: 'GPT-4.1-nano', + maxInputTokens: 1047576, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.09, + outputPerM: 0.36, + cacheReadPerM: 0.022, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4o', + displayName: 'GPT-4o', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + }, + { + name: 'openai/gpt-4o-aug', + displayName: 'GPT-4o-Aug', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2.2, + outputPerM: 9, + cacheReadPerM: 1.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4o-mini', + displayName: 'GPT-4o-mini', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.14, + outputPerM: 0.54, + cacheReadPerM: 0.068, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4o-mini-search', + displayName: 'GPT-4o-mini-Search', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.14, + outputPerM: 0.54, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4o-search', + displayName: 'GPT-4o-Search', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 2.2, + outputPerM: 9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5', + displayName: 'GPT-5', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.1, + outputPerM: 9, + cacheReadPerM: 0.11, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5-chat', + displayName: 'GPT-5-Chat', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.1, + outputPerM: 9, + cacheReadPerM: 0.11, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5-codex', + displayName: 'GPT-5-Codex', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.1, + outputPerM: 9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5-mini', + displayName: 'GPT-5-mini', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.22, + outputPerM: 1.8, + cacheReadPerM: 0.022, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5-nano', + displayName: 'GPT-5-nano', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.045, + outputPerM: 0.36, + cacheReadPerM: 0.0045, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5-pro', + displayName: 'GPT-5-Pro', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 14, + outputPerM: 110, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.1', + displayName: 'GPT-5.1', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.1, + outputPerM: 9, + cacheReadPerM: 0.11, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.1-codex', + displayName: 'GPT-5.1-Codex', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.1, + outputPerM: 9, + cacheReadPerM: 0.11, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.1-codex-max', + displayName: 'GPT-5.1-Codex-Max', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.1, + outputPerM: 9, + cacheReadPerM: 0.11, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.1-codex-mini', + displayName: 'GPT-5.1-Codex-Mini', + maxInputTokens: 400000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.22, + outputPerM: 1.8, + cacheReadPerM: 0.022, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.1-instant', + displayName: 'GPT-5.1-Instant', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.1, + outputPerM: 9, + cacheReadPerM: 0.11, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.2', + displayName: 'GPT-5.2', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.6, + outputPerM: 13, + cacheReadPerM: 0.16, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.2-codex', + displayName: 'GPT-5.2-Codex', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.6, + outputPerM: 13, + cacheReadPerM: 0.16, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.2-instant', + displayName: 'GPT-5.2-Instant', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.6, + outputPerM: 13, + cacheReadPerM: 0.16, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.2-pro', + displayName: 'GPT-5.2-Pro', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 19, + outputPerM: 150, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-image-1', + displayName: 'GPT-Image-1', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + }, + { + name: 'openai/gpt-image-1-mini', + displayName: 'GPT-Image-1-Mini', + maxInputTokens: 0, + supportedFileTypes: ['image'], + }, + { + name: 'openai/gpt-image-1.5', + displayName: 'gpt-image-1.5', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + }, + { + name: 'openai/o1', + displayName: 'o1', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 14, + outputPerM: 54, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/o1-pro', + displayName: 'o1-pro', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 140, + outputPerM: 540, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/o3', + displayName: 'o3', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.8, + outputPerM: 7.2, + cacheReadPerM: 0.45, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/o3-deep-research', + displayName: 'o3-deep-research', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 9, + outputPerM: 36, + cacheReadPerM: 2.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/o3-mini', + displayName: 'o3-mini', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.99, + outputPerM: 4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/o3-mini-high', + displayName: 'o3-mini-high', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.99, + outputPerM: 4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/o3-pro', + displayName: 'o3-pro', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 18, + outputPerM: 72, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/o4-mini', + displayName: 'o4-mini', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.99, + outputPerM: 4, + cacheReadPerM: 0.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/o4-mini-deep-research', + displayName: 'o4-mini-deep-research', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 1.8, + outputPerM: 7.2, + cacheReadPerM: 0.45, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/sora-2', + displayName: 'Sora-2', + maxInputTokens: 0, + supportedFileTypes: ['image'], + }, + { + name: 'openai/sora-2-pro', + displayName: 'Sora-2-Pro', + maxInputTokens: 0, + supportedFileTypes: ['image'], + }, + { + name: 'poetools/claude-code', + displayName: 'claude-code', + maxInputTokens: 0, + supportedFileTypes: [], + }, + { + name: 'runwayml/runway', + displayName: 'Runway', + maxInputTokens: 256, + supportedFileTypes: ['image'], + }, + { + name: 'runwayml/runway-gen-4-turbo', + displayName: 'Runway-Gen-4-Turbo', + maxInputTokens: 256, + supportedFileTypes: ['image'], + }, + { + name: 'stabilityai/stablediffusionxl', + displayName: 'StableDiffusionXL', + maxInputTokens: 200, + supportedFileTypes: ['image'], + }, + { + name: 'topazlabs-co/topazlabs', + displayName: 'TopazLabs', + maxInputTokens: 204, + supportedFileTypes: [], + }, + { + name: 'trytako/tako', + displayName: 'Tako', + maxInputTokens: 2048, + supportedFileTypes: [], + }, + { + name: 'xai/grok-3', + displayName: 'Grok 3', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'xai/grok-3-mini', + displayName: 'Grok 3 Mini', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 0.5, + cacheReadPerM: 0.075, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'xai/grok-4', + displayName: 'Grok-4', + maxInputTokens: 256000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'xai/grok-4-fast-non-reasoning', + displayName: 'Grok-4-Fast-Non-Reasoning', + maxInputTokens: 2000000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.2, + outputPerM: 0.5, + cacheReadPerM: 0.05, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'xai/grok-4-fast-reasoning', + displayName: 'Grok-4-Fast-Reasoning', + maxInputTokens: 2000000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.2, + outputPerM: 0.5, + cacheReadPerM: 0.05, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'xai/grok-4.1-fast-non-reasoning', + displayName: 'Grok-4.1-Fast-Non-Reasoning', + maxInputTokens: 2000000, + supportedFileTypes: ['image'], + }, + { + name: 'xai/grok-4.1-fast-reasoning', + displayName: 'Grok-4.1-Fast-Reasoning', + maxInputTokens: 2000000, + supportedFileTypes: ['image'], + }, + { + name: 'xai/grok-code-fast-1', + displayName: 'Grok Code Fast 1', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 1.5, + cacheReadPerM: 0.02, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + 'privatemode-ai': [ + { + name: 'gemma-3-27b', + displayName: 'Gemma 3 27B', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-oss-120b', + displayName: 'gpt-oss-120b', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen3-coder-30b-a3b', + displayName: 'Qwen3-Coder 30B-A3B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen3-embedding-4b', + displayName: 'Qwen3-Embedding 4B', + maxInputTokens: 32000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'whisper-large-v3', + displayName: 'Whisper large-v3', + maxInputTokens: 0, + supportedFileTypes: ['audio'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + 'qihang-ai': [ + { + name: 'claude-haiku-4-5-20251001', + displayName: 'Claude Haiku 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0.14, + outputPerM: 0.71, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-opus-4-5-20251101', + displayName: 'Claude Opus 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.71, + outputPerM: 3.57, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-sonnet-4-5-20250929', + displayName: 'Claude Sonnet 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0.43, + outputPerM: 2.14, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-flash', + displayName: 'Gemini 2.5 Flash', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.09, + outputPerM: 0.71, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-3-flash-preview', + displayName: 'Gemini 3 Flash Preview', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.07, + outputPerM: 0.43, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-3-pro-preview', + displayName: 'Gemini 3 Pro Preview', + maxInputTokens: 1000000, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0.57, + outputPerM: 3.43, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5-mini', + displayName: 'GPT-5-Mini', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.04, + outputPerM: 0.29, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.2', + displayName: 'GPT-5.2', + maxInputTokens: 272000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.25, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5.2-codex', + displayName: 'GPT-5.2 Codex', + maxInputTokens: 272000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.14, + outputPerM: 1.14, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + 'qiniu-ai': [ + { + name: 'claude-3.5-haiku', + displayName: 'Claude 3.5 Haiku', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + }, + { + name: 'claude-3.5-sonnet', + displayName: 'Claude 3.5 Sonnet', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + }, + { + name: 'claude-3.7-sonnet', + displayName: 'Claude 3.7 Sonnet', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + }, + { + name: 'claude-4.0-opus', + displayName: 'Claude 4.0 Opus', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + }, + { + name: 'claude-4.0-sonnet', + displayName: 'Claude 4.0 Sonnet', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + }, + { + name: 'claude-4.1-opus', + displayName: 'Claude 4.1 Opus', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + }, + { + name: 'claude-4.5-haiku', + displayName: 'Claude 4.5 Haiku', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + }, + { + name: 'claude-4.5-opus', + displayName: 'Claude 4.5 Opus', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + }, + { + name: 'claude-4.5-sonnet', + displayName: 'Claude 4.5 Sonnet', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + }, + { + name: 'deepseek-r1', + displayName: 'DeepSeek-R1', + maxInputTokens: 128000, + supportedFileTypes: [], + }, + { + name: 'deepseek-r1-0528', + displayName: 'DeepSeek-R1-0528', + maxInputTokens: 128000, + supportedFileTypes: [], + }, + { + name: 'deepseek-v3', + displayName: 'DeepSeek-V3', + maxInputTokens: 128000, + supportedFileTypes: [], + }, + { + name: 'deepseek-v3-0324', + displayName: 'DeepSeek-V3-0324', + maxInputTokens: 128000, + supportedFileTypes: [], + }, + { + name: 'deepseek-v3.1', + displayName: 'DeepSeek-V3.1', + maxInputTokens: 128000, + supportedFileTypes: [], + }, + { + name: 'deepseek/deepseek-math-v2', + displayName: 'Deepseek/Deepseek-Math-V2', + maxInputTokens: 160000, + supportedFileTypes: [], + }, + { + name: 'deepseek/deepseek-v3.1-terminus', + displayName: 'DeepSeek/DeepSeek-V3.1-Terminus', + maxInputTokens: 128000, + supportedFileTypes: [], + }, + { + name: 'deepseek/deepseek-v3.1-terminus-thinking', + displayName: 'DeepSeek/DeepSeek-V3.1-Terminus-Thinking', + maxInputTokens: 128000, + supportedFileTypes: [], + }, + { + name: 'deepseek/deepseek-v3.2-251201', + displayName: 'Deepseek/DeepSeek-V3.2', + maxInputTokens: 128000, + supportedFileTypes: [], + }, + { + name: 'deepseek/deepseek-v3.2-exp', + displayName: 'DeepSeek/DeepSeek-V3.2-Exp', + maxInputTokens: 128000, + supportedFileTypes: [], + }, + { + name: 'deepseek/deepseek-v3.2-exp-thinking', + displayName: 'DeepSeek/DeepSeek-V3.2-Exp-Thinking', + maxInputTokens: 128000, + supportedFileTypes: [], + }, + { + name: 'doubao-1.5-pro-32k', + displayName: 'Doubao 1.5 Pro 32k', + maxInputTokens: 128000, + supportedFileTypes: [], + }, + { + name: 'doubao-1.5-thinking-pro', + displayName: 'Doubao 1.5 Thinking Pro', + maxInputTokens: 128000, + supportedFileTypes: [], + }, + { + name: 'doubao-1.5-vision-pro', + displayName: 'Doubao 1.5 Vision Pro', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + }, + { + name: 'doubao-seed-1.6', + displayName: 'Doubao-Seed 1.6', + maxInputTokens: 256000, + supportedFileTypes: ['image'], + }, + { + name: 'doubao-seed-1.6-flash', + displayName: 'Doubao-Seed 1.6 Flash', + maxInputTokens: 256000, + supportedFileTypes: ['image'], + }, + { + name: 'doubao-seed-1.6-thinking', + displayName: 'Doubao-Seed 1.6 Thinking', + maxInputTokens: 256000, + supportedFileTypes: ['image'], + }, + { + name: 'gemini-2.0-flash', + displayName: 'Gemini 2.0 Flash', + maxInputTokens: 1048576, + supportedFileTypes: ['image', 'audio'], + }, + { + name: 'gemini-2.0-flash-lite', + displayName: 'Gemini 2.0 Flash Lite', + maxInputTokens: 1048576, + supportedFileTypes: ['image', 'audio'], + }, + { + name: 'gemini-2.5-flash', + displayName: 'Gemini 2.5 Flash', + maxInputTokens: 1048576, + supportedFileTypes: ['image', 'audio'], + }, + { + name: 'gemini-2.5-flash-image', + displayName: 'Gemini 2.5 Flash Image', + maxInputTokens: 32768, + supportedFileTypes: ['image'], + }, + { + name: 'gemini-2.5-flash-lite', + displayName: 'Gemini 2.5 Flash Lite', + maxInputTokens: 1048576, + supportedFileTypes: ['image', 'audio'], + }, + { + name: 'gemini-2.5-pro', + displayName: 'Gemini 2.5 Pro', + maxInputTokens: 1048576, + supportedFileTypes: ['image', 'audio'], + }, + { + name: 'gemini-3.0-flash-preview', + displayName: 'Gemini 3.0 Flash Preview', + maxInputTokens: 1000000, + supportedFileTypes: ['pdf', 'image', 'audio'], + }, + { + name: 'gemini-3.0-pro-image-preview', + displayName: 'Gemini 3.0 Pro Image Preview', + maxInputTokens: 32768, + supportedFileTypes: ['image'], + }, + { + name: 'gemini-3.0-pro-preview', + displayName: 'Gemini 3.0 Pro Preview', + maxInputTokens: 1000000, + supportedFileTypes: ['pdf', 'image', 'audio'], + }, + { + name: 'glm-4.5', + displayName: 'GLM 4.5', + maxInputTokens: 131072, + supportedFileTypes: [], + }, + { + name: 'glm-4.5-air', + displayName: 'GLM 4.5 Air', + maxInputTokens: 131000, + supportedFileTypes: [], + }, + { + name: 'gpt-oss-120b', + displayName: 'gpt-oss-120b', + maxInputTokens: 128000, + supportedFileTypes: [], + }, + { + name: 'gpt-oss-20b', + displayName: 'gpt-oss-20b', + maxInputTokens: 128000, + supportedFileTypes: [], + }, + { + name: 'kimi-k2', + displayName: 'Kimi K2', + maxInputTokens: 128000, + supportedFileTypes: [], + }, + { + name: 'kling-v2-6', + displayName: 'Kling-V2 6', + maxInputTokens: 99999999, + supportedFileTypes: ['image'], + }, + { + name: 'meituan/longcat-flash-chat', + displayName: 'Meituan/Longcat-Flash-Chat', + maxInputTokens: 131072, + supportedFileTypes: [], + }, + { + name: 'mimo-v2-flash', + displayName: 'Mimo-V2-Flash', + maxInputTokens: 256000, + supportedFileTypes: [], + }, + { + name: 'MiniMax-M1', + displayName: 'MiniMax M1', + maxInputTokens: 1000000, + supportedFileTypes: [], + }, + { + name: 'minimax/minimax-m2', + displayName: 'Minimax/Minimax-M2', + maxInputTokens: 200000, + supportedFileTypes: [], + }, + { + name: 'minimax/minimax-m2.1', + displayName: 'Minimax/Minimax-M2.1', + maxInputTokens: 204800, + supportedFileTypes: [], + }, + { + name: 'moonshotai/kimi-k2-0905', + displayName: 'Kimi K2 0905', + maxInputTokens: 256000, + supportedFileTypes: [], + }, + { + name: 'moonshotai/kimi-k2-thinking', + displayName: 'Kimi K2 Thinking', + maxInputTokens: 256000, + supportedFileTypes: [], + }, + { + name: 'openai/gpt-5', + displayName: 'OpenAI/GPT-5', + maxInputTokens: 400000, + supportedFileTypes: [], + }, + { + name: 'openai/gpt-5.2', + displayName: 'OpenAI/GPT-5.2', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + }, + { + name: 'qwen-max-2025-01-25', + displayName: 'Qwen2.5-Max-2025-01-25', + maxInputTokens: 128000, + supportedFileTypes: [], + }, + { + name: 'qwen-turbo', + displayName: 'Qwen-Turbo', + maxInputTokens: 1000000, + supportedFileTypes: [], + }, + { + name: 'qwen-vl-max-2025-01-25', + displayName: 'Qwen VL-MAX-2025-01-25', + maxInputTokens: 128000, + supportedFileTypes: ['image', 'audio'], + }, + { + name: 'qwen2.5-vl-72b-instruct', + displayName: 'Qwen 2.5 VL 72B Instruct', + maxInputTokens: 128000, + supportedFileTypes: ['image', 'audio'], + }, + { + name: 'qwen2.5-vl-7b-instruct', + displayName: 'Qwen 2.5 VL 7B Instruct', + maxInputTokens: 128000, + supportedFileTypes: ['image', 'audio'], + }, + { + name: 'qwen3-235b-a22b', + displayName: 'Qwen 3 235B A22B', + maxInputTokens: 128000, + supportedFileTypes: [], + }, + { + name: 'qwen3-235b-a22b-instruct-2507', + displayName: 'Qwen3 235b A22B Instruct 2507', + maxInputTokens: 262144, + supportedFileTypes: [], + }, + { + name: 'qwen3-235b-a22b-thinking-2507', + displayName: 'Qwen3 235B A22B Thinking 2507', + maxInputTokens: 262144, + supportedFileTypes: [], + }, + { + name: 'qwen3-30b-a3b', + displayName: 'Qwen3 30B A3B', + maxInputTokens: 40000, + supportedFileTypes: [], + }, + { + name: 'qwen3-32b', + displayName: 'Qwen3 32B', + maxInputTokens: 40000, + supportedFileTypes: [], + }, + { + name: 'qwen3-coder-480b-a35b-instruct', + displayName: 'Qwen3 Coder 480B A35B Instruct', + maxInputTokens: 262000, + supportedFileTypes: [], + }, + { + name: 'qwen3-max', + displayName: 'Qwen3 Max', + maxInputTokens: 262144, + supportedFileTypes: [], + }, + { + name: 'qwen3-max-preview', + displayName: 'Qwen3 Max Preview', + maxInputTokens: 256000, + supportedFileTypes: [], + }, + { + name: 'qwen3-next-80b-a3b-instruct', + displayName: 'Qwen3 Next 80B A3B Instruct', + maxInputTokens: 131072, + supportedFileTypes: [], + }, + { + name: 'qwen3-next-80b-a3b-thinking', + displayName: 'Qwen3 Next 80B A3B Thinking', + maxInputTokens: 131072, + supportedFileTypes: [], + }, + { + name: 'stepfun-ai/gelab-zero-4b-preview', + displayName: 'Stepfun-Ai/Gelab Zero 4b Preview', + maxInputTokens: 8192, + supportedFileTypes: ['image'], + }, + { + name: 'x-ai/grok-4-fast', + displayName: 'x-AI/Grok-4-Fast', + maxInputTokens: 2000000, + supportedFileTypes: ['image', 'audio'], + }, + { + name: 'x-ai/grok-4-fast-non-reasoning', + displayName: 'X-Ai/Grok-4-Fast-Non-Reasoning', + maxInputTokens: 2000000, + supportedFileTypes: ['image', 'audio'], + }, + { + name: 'x-ai/grok-4-fast-reasoning', + displayName: 'X-Ai/Grok-4-Fast-Reasoning', + maxInputTokens: 2000000, + supportedFileTypes: ['image', 'audio'], + }, + { + name: 'x-ai/grok-4.1-fast', + displayName: 'x-AI/Grok-4.1-Fast', + maxInputTokens: 2000000, + supportedFileTypes: [], + }, + { + name: 'x-ai/grok-4.1-fast-non-reasoning', + displayName: 'X-Ai/Grok 4.1 Fast Non Reasoning', + maxInputTokens: 2000000, + supportedFileTypes: ['image', 'audio'], + }, + { + name: 'x-ai/grok-4.1-fast-reasoning', + displayName: 'X-Ai/Grok 4.1 Fast Reasoning', + maxInputTokens: 20000000, + supportedFileTypes: ['image', 'audio'], + }, + { + name: 'x-ai/grok-code-fast-1', + displayName: 'x-AI/Grok-Code-Fast 1', + maxInputTokens: 256000, + supportedFileTypes: [], + }, + { + name: 'z-ai/autoglm-phone-9b', + displayName: 'Z-Ai/Autoglm Phone 9b', + maxInputTokens: 12800, + supportedFileTypes: ['image'], + }, + { + name: 'z-ai/glm-4.6', + displayName: 'Z-AI/GLM 4.6', + maxInputTokens: 200000, + supportedFileTypes: [], + }, + { + name: 'z-ai/glm-4.7', + displayName: 'Z-Ai/GLM 4.7', + maxInputTokens: 200000, + supportedFileTypes: [], + }, + ], + requesty: [ + { + name: 'anthropic/claude-3-7-sonnet', + displayName: 'Claude Sonnet 3.7', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-haiku-4-5', + displayName: 'Claude Haiku 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1, + outputPerM: 5, + cacheReadPerM: 0.1, + cacheWritePerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-opus-4', + displayName: 'Claude Opus 4', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 15, + outputPerM: 75, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-opus-4-1', + displayName: 'Claude Opus 4.1', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 15, + outputPerM: 75, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-opus-4-5', + displayName: 'Claude Opus 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-sonnet-4', + displayName: 'Claude Sonnet 4', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-sonnet-4-5', + displayName: 'Claude Sonnet 4.5', + maxInputTokens: 1000000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.5-flash', + displayName: 'Gemini 2.5 Flash', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.3, + outputPerM: 2.5, + cacheReadPerM: 0.075, + cacheWritePerM: 0.55, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.5-pro', + displayName: 'Gemini 2.5 Pro', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.31, + cacheWritePerM: 2.375, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-3-flash-preview', + displayName: 'Gemini 3 Flash', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.5, + outputPerM: 3, + cacheReadPerM: 0.05, + cacheWritePerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-3-pro-preview', + displayName: 'Gemini 3 Pro', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 2, + outputPerM: 12, + cacheReadPerM: 0.2, + cacheWritePerM: 4.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4.1', + displayName: 'GPT-4.1', + maxInputTokens: 1047576, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2, + outputPerM: 8, + cacheReadPerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4.1-mini', + displayName: 'GPT-4.1 Mini', + maxInputTokens: 1047576, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.4, + outputPerM: 1.6, + cacheReadPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4o-mini', + displayName: 'GPT-4o Mini', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + cacheReadPerM: 0.08, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5', + displayName: 'GPT-5', + maxInputTokens: 400000, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.13, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5-mini', + displayName: 'GPT-5 Mini', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.25, + outputPerM: 2, + cacheReadPerM: 0.03, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5-nano', + displayName: 'GPT-5 Nano', + maxInputTokens: 16000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.05, + outputPerM: 0.4, + cacheReadPerM: 0.01, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/o4-mini', + displayName: 'o4 Mini', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.1, + outputPerM: 4.4, + cacheReadPerM: 0.28, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'xai/grok-4', + displayName: 'Grok 4', + maxInputTokens: 256000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.75, + cacheWritePerM: 3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'xai/grok-4-fast', + displayName: 'Grok 4 Fast', + maxInputTokens: 2000000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.5, + cacheReadPerM: 0.05, + cacheWritePerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + 'sap-ai-core': [ + { + name: 'anthropic--claude-3-haiku', + displayName: 'anthropic--claude-3-haiku', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0.25, + outputPerM: 1.25, + cacheReadPerM: 0.03, + cacheWritePerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic--claude-3-opus', + displayName: 'anthropic--claude-3-opus', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 15, + outputPerM: 75, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic--claude-3-sonnet', + displayName: 'anthropic--claude-3-sonnet', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic--claude-3.5-sonnet', + displayName: 'anthropic--claude-3.5-sonnet', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic--claude-3.7-sonnet', + displayName: 'anthropic--claude-3.7-sonnet', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic--claude-4-opus', + displayName: 'anthropic--claude-4-opus', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 15, + outputPerM: 75, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic--claude-4-sonnet', + displayName: 'anthropic--claude-4-sonnet', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic--claude-4.5-haiku', + displayName: 'anthropic--claude-4.5-haiku', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1, + outputPerM: 5, + cacheReadPerM: 0.1, + cacheWritePerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic--claude-4.5-opus', + displayName: 'anthropic--claude-4.5-opus', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic--claude-4.5-sonnet', + displayName: 'anthropic--claude-4.5-sonnet', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-flash', + displayName: 'gemini-2.5-flash', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.3, + outputPerM: 2.5, + cacheReadPerM: 0.03, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-2.5-pro', + displayName: 'gemini-2.5-pro', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5', + displayName: 'gpt-5', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.13, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5-mini', + displayName: 'gpt-5-mini', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.25, + outputPerM: 2, + cacheReadPerM: 0.025, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-5-nano', + displayName: 'gpt-5-nano', + maxInputTokens: 400000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.05, + outputPerM: 0.4, + cacheReadPerM: 0.01, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + scaleway: [ + { + name: 'bge-multilingual-gemma2', + displayName: 'BGE Multilingual Gemma2', + maxInputTokens: 8191, + supportedFileTypes: [], + pricing: { + inputPerM: 0.13, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-r1-distill-llama-70b', + displayName: 'DeepSeek R1 Distill Llama 70B', + maxInputTokens: 32000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.9, + outputPerM: 0.9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'devstral-2-123b-instruct-2512', + displayName: 'Devstral 2 123B Instruct (2512)', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.4, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemma-3-27b-it', + displayName: 'Gemma-3-27B-IT', + maxInputTokens: 40000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.25, + outputPerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gpt-oss-120b', + displayName: 'GPT-OSS 120B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'llama-3.1-8b-instruct', + displayName: 'Llama 3.1 8B Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'llama-3.3-70b-instruct', + displayName: 'Llama-3.3-70B-Instruct', + maxInputTokens: 100000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.9, + outputPerM: 0.9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral-nemo-instruct-2407', + displayName: 'Mistral Nemo Instruct 2407', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral-small-3.2-24b-instruct-2506', + displayName: 'Mistral Small 3.2 24B Instruct (2506)', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.15, + outputPerM: 0.35, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'pixtral-12b-2409', + displayName: 'Pixtral 12B 2409', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.2, + outputPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen3-235b-a22b-instruct-2507', + displayName: 'Qwen3 235B A22B Instruct 2507', + maxInputTokens: 260000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.75, + outputPerM: 2.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen3-coder-30b-a3b-instruct', + displayName: 'Qwen3-Coder 30B-A3B Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'voxtral-small-24b-2507', + displayName: 'Voxtral Small 24B 2507', + maxInputTokens: 32000, + supportedFileTypes: ['audio'], + pricing: { + inputPerM: 0.15, + outputPerM: 0.35, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'whisper-large-v3', + displayName: 'Whisper Large v3', + maxInputTokens: 0, + supportedFileTypes: ['audio'], + pricing: { + inputPerM: 0.003, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + siliconflow: [ + { + name: 'baidu/ERNIE-4.5-300B-A47B', + displayName: 'baidu/ERNIE-4.5-300B-A47B', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.28, + outputPerM: 1.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'ByteDance-Seed/Seed-OSS-36B-Instruct', + displayName: 'ByteDance-Seed/Seed-OSS-36B-Instruct', + maxInputTokens: 262000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.21, + outputPerM: 0.57, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/DeepSeek-R1', + displayName: 'deepseek-ai/DeepSeek-R1', + maxInputTokens: 164000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.5, + outputPerM: 2.18, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/DeepSeek-R1-Distill-Qwen-14B', + displayName: 'deepseek-ai/DeepSeek-R1-Distill-Qwen-14B', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/DeepSeek-R1-Distill-Qwen-32B', + displayName: 'deepseek-ai/DeepSeek-R1-Distill-Qwen-32B', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.18, + outputPerM: 0.18, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/DeepSeek-V3', + displayName: 'deepseek-ai/DeepSeek-V3', + maxInputTokens: 164000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.25, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/DeepSeek-V3.1', + displayName: 'deepseek-ai/DeepSeek-V3.1', + maxInputTokens: 164000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.27, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/DeepSeek-V3.1-Terminus', + displayName: 'deepseek-ai/DeepSeek-V3.1-Terminus', + maxInputTokens: 164000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.27, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/DeepSeek-V3.2', + displayName: 'deepseek-ai/DeepSeek-V3.2', + maxInputTokens: 164000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.27, + outputPerM: 0.42, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/DeepSeek-V3.2-Exp', + displayName: 'deepseek-ai/DeepSeek-V3.2-Exp', + maxInputTokens: 164000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.27, + outputPerM: 0.41, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/deepseek-vl2', + displayName: 'deepseek-ai/deepseek-vl2', + maxInputTokens: 4000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.15, + outputPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'inclusionAI/Ling-flash-2.0', + displayName: 'inclusionAI/Ling-flash-2.0', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.14, + outputPerM: 0.57, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'inclusionAI/Ling-mini-2.0', + displayName: 'inclusionAI/Ling-mini-2.0', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.07, + outputPerM: 0.28, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'inclusionAI/Ring-flash-2.0', + displayName: 'inclusionAI/Ring-flash-2.0', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.14, + outputPerM: 0.57, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/Meta-Llama-3.1-8B-Instruct', + displayName: 'meta-llama/Meta-Llama-3.1-8B-Instruct', + maxInputTokens: 33000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.06, + outputPerM: 0.06, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'MiniMaxAI/MiniMax-M2.1', + displayName: 'MiniMaxAI/MiniMax-M2.1', + maxInputTokens: 197000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/Kimi-K2-Instruct', + displayName: 'moonshotai/Kimi-K2-Instruct', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.58, + outputPerM: 2.29, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/Kimi-K2-Instruct-0905', + displayName: 'moonshotai/Kimi-K2-Instruct-0905', + maxInputTokens: 262000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.4, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/Kimi-K2-Thinking', + displayName: 'moonshotai/Kimi-K2-Thinking', + maxInputTokens: 262000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.55, + outputPerM: 2.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/Kimi-K2.5', + displayName: 'moonshotai/Kimi-K2.5', + maxInputTokens: 262000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.55, + outputPerM: 3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nex-agi/DeepSeek-V3.1-Nex-N1', + displayName: 'nex-agi/DeepSeek-V3.1-Nex-N1', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.5, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-120b', + displayName: 'openai/gpt-oss-120b', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.05, + outputPerM: 0.45, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-20b', + displayName: 'openai/gpt-oss-20b', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.04, + outputPerM: 0.18, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen2.5-14B-Instruct', + displayName: 'Qwen/Qwen2.5-14B-Instruct', + maxInputTokens: 33000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen2.5-32B-Instruct', + displayName: 'Qwen/Qwen2.5-32B-Instruct', + maxInputTokens: 33000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.18, + outputPerM: 0.18, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen2.5-72B-Instruct', + displayName: 'Qwen/Qwen2.5-72B-Instruct', + maxInputTokens: 33000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.59, + outputPerM: 0.59, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen2.5-72B-Instruct-128K', + displayName: 'Qwen/Qwen2.5-72B-Instruct-128K', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.59, + outputPerM: 0.59, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen2.5-7B-Instruct', + displayName: 'Qwen/Qwen2.5-7B-Instruct', + maxInputTokens: 33000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.05, + outputPerM: 0.05, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen2.5-Coder-32B-Instruct', + displayName: 'Qwen/Qwen2.5-Coder-32B-Instruct', + maxInputTokens: 33000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.18, + outputPerM: 0.18, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen2.5-VL-32B-Instruct', + displayName: 'Qwen/Qwen2.5-VL-32B-Instruct', + maxInputTokens: 131000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.27, + outputPerM: 0.27, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen2.5-VL-72B-Instruct', + displayName: 'Qwen/Qwen2.5-VL-72B-Instruct', + maxInputTokens: 131000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.59, + outputPerM: 0.59, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen2.5-VL-7B-Instruct', + displayName: 'Qwen/Qwen2.5-VL-7B-Instruct', + maxInputTokens: 33000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.05, + outputPerM: 0.05, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-14B', + displayName: 'Qwen/Qwen3-14B', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.07, + outputPerM: 0.28, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-235B-A22B', + displayName: 'Qwen/Qwen3-235B-A22B', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.35, + outputPerM: 1.42, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-235B-A22B-Instruct-2507', + displayName: 'Qwen/Qwen3-235B-A22B-Instruct-2507', + maxInputTokens: 262000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.09, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-235B-A22B-Thinking-2507', + displayName: 'Qwen/Qwen3-235B-A22B-Thinking-2507', + maxInputTokens: 262000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.13, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-30B-A3B-Instruct-2507', + displayName: 'Qwen/Qwen3-30B-A3B-Instruct-2507', + maxInputTokens: 262000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.09, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-30B-A3B-Thinking-2507', + displayName: 'Qwen/Qwen3-30B-A3B-Thinking-2507', + maxInputTokens: 262000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.09, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-32B', + displayName: 'Qwen/Qwen3-32B', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.14, + outputPerM: 0.57, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-8B', + displayName: 'Qwen/Qwen3-8B', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.06, + outputPerM: 0.06, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-Coder-30B-A3B-Instruct', + displayName: 'Qwen/Qwen3-Coder-30B-A3B-Instruct', + maxInputTokens: 262000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.07, + outputPerM: 0.28, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-Coder-480B-A35B-Instruct', + displayName: 'Qwen/Qwen3-Coder-480B-A35B-Instruct', + maxInputTokens: 262000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.25, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-Next-80B-A3B-Instruct', + displayName: 'Qwen/Qwen3-Next-80B-A3B-Instruct', + maxInputTokens: 262000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.14, + outputPerM: 1.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-Next-80B-A3B-Thinking', + displayName: 'Qwen/Qwen3-Next-80B-A3B-Thinking', + maxInputTokens: 262000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.14, + outputPerM: 0.57, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-Omni-30B-A3B-Captioner', + displayName: 'Qwen/Qwen3-Omni-30B-A3B-Captioner', + maxInputTokens: 66000, + supportedFileTypes: ['audio'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-Omni-30B-A3B-Instruct', + displayName: 'Qwen/Qwen3-Omni-30B-A3B-Instruct', + maxInputTokens: 66000, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-Omni-30B-A3B-Thinking', + displayName: 'Qwen/Qwen3-Omni-30B-A3B-Thinking', + maxInputTokens: 66000, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-VL-235B-A22B-Instruct', + displayName: 'Qwen/Qwen3-VL-235B-A22B-Instruct', + maxInputTokens: 262000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.3, + outputPerM: 1.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-VL-235B-A22B-Thinking', + displayName: 'Qwen/Qwen3-VL-235B-A22B-Thinking', + maxInputTokens: 262000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.45, + outputPerM: 3.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-VL-30B-A3B-Instruct', + displayName: 'Qwen/Qwen3-VL-30B-A3B-Instruct', + maxInputTokens: 262000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.29, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-VL-30B-A3B-Thinking', + displayName: 'Qwen/Qwen3-VL-30B-A3B-Thinking', + maxInputTokens: 262000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.29, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-VL-32B-Instruct', + displayName: 'Qwen/Qwen3-VL-32B-Instruct', + maxInputTokens: 262000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.2, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-VL-32B-Thinking', + displayName: 'Qwen/Qwen3-VL-32B-Thinking', + maxInputTokens: 262000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.2, + outputPerM: 1.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-VL-8B-Instruct', + displayName: 'Qwen/Qwen3-VL-8B-Instruct', + maxInputTokens: 262000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.18, + outputPerM: 0.68, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-VL-8B-Thinking', + displayName: 'Qwen/Qwen3-VL-8B-Thinking', + maxInputTokens: 262000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.18, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/QwQ-32B', + displayName: 'Qwen/QwQ-32B', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0.58, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'stepfun-ai/Step-3.5-Flash', + displayName: 'stepfun-ai/Step-3.5-Flash', + maxInputTokens: 262000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'tencent/Hunyuan-A13B-Instruct', + displayName: 'tencent/Hunyuan-A13B-Instruct', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.14, + outputPerM: 0.57, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'tencent/Hunyuan-MT-7B', + displayName: 'tencent/Hunyuan-MT-7B', + maxInputTokens: 33000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'THUDM/GLM-4-32B-0414', + displayName: 'THUDM/GLM-4-32B-0414', + maxInputTokens: 33000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.27, + outputPerM: 0.27, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'THUDM/GLM-4-9B-0414', + displayName: 'THUDM/GLM-4-9B-0414', + maxInputTokens: 33000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.086, + outputPerM: 0.086, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'THUDM/GLM-Z1-32B-0414', + displayName: 'THUDM/GLM-Z1-32B-0414', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.14, + outputPerM: 0.57, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'THUDM/GLM-Z1-9B-0414', + displayName: 'THUDM/GLM-Z1-9B-0414', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.086, + outputPerM: 0.086, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-4.5', + displayName: 'zai-org/GLM-4.5', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.4, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-4.5-Air', + displayName: 'zai-org/GLM-4.5-Air', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.14, + outputPerM: 0.86, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-4.5V', + displayName: 'zai-org/GLM-4.5V', + maxInputTokens: 66000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.14, + outputPerM: 0.86, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-4.6', + displayName: 'zai-org/GLM-4.6', + maxInputTokens: 205000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.5, + outputPerM: 1.9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-4.6V', + displayName: 'zai-org/GLM-4.6V', + maxInputTokens: 131000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.3, + outputPerM: 0.9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-4.7', + displayName: 'zai-org/GLM-4.7', + maxInputTokens: 205000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-5', + displayName: 'zai-org/GLM-5', + maxInputTokens: 205000, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 3.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + 'siliconflow-cn': [ + { + name: 'ascend-tribe/pangu-pro-moe', + displayName: 'ascend-tribe/pangu-pro-moe', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'baidu/ERNIE-4.5-300B-A47B', + displayName: 'baidu/ERNIE-4.5-300B-A47B', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.28, + outputPerM: 1.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'ByteDance-Seed/Seed-OSS-36B-Instruct', + displayName: 'ByteDance-Seed/Seed-OSS-36B-Instruct', + maxInputTokens: 262000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.21, + outputPerM: 0.57, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/DeepSeek-R1', + displayName: 'deepseek-ai/DeepSeek-R1', + maxInputTokens: 164000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.5, + outputPerM: 2.18, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/DeepSeek-R1-Distill-Qwen-14B', + displayName: 'deepseek-ai/DeepSeek-R1-Distill-Qwen-14B', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/DeepSeek-R1-Distill-Qwen-32B', + displayName: 'deepseek-ai/DeepSeek-R1-Distill-Qwen-32B', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.18, + outputPerM: 0.18, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/DeepSeek-V3', + displayName: 'deepseek-ai/DeepSeek-V3', + maxInputTokens: 164000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.25, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/DeepSeek-V3.1-Terminus', + displayName: 'deepseek-ai/DeepSeek-V3.1-Terminus', + maxInputTokens: 164000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.27, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/DeepSeek-V3.2', + displayName: 'deepseek-ai/DeepSeek-V3.2', + maxInputTokens: 164000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.27, + outputPerM: 0.42, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/deepseek-vl2', + displayName: 'deepseek-ai/deepseek-vl2', + maxInputTokens: 4000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.15, + outputPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'inclusionAI/Ling-flash-2.0', + displayName: 'inclusionAI/Ling-flash-2.0', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.14, + outputPerM: 0.57, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'inclusionAI/Ling-mini-2.0', + displayName: 'inclusionAI/Ling-mini-2.0', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.07, + outputPerM: 0.28, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'inclusionAI/Ring-flash-2.0', + displayName: 'inclusionAI/Ring-flash-2.0', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.14, + outputPerM: 0.57, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Kwaipilot/KAT-Dev', + displayName: 'Kwaipilot/KAT-Dev', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/Kimi-K2-Instruct-0905', + displayName: 'moonshotai/Kimi-K2-Instruct-0905', + maxInputTokens: 262000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.4, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/Kimi-K2-Thinking', + displayName: 'moonshotai/Kimi-K2-Thinking', + maxInputTokens: 262000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.55, + outputPerM: 2.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Pro/deepseek-ai/DeepSeek-R1', + displayName: 'Pro/deepseek-ai/DeepSeek-R1', + maxInputTokens: 164000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.5, + outputPerM: 2.18, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Pro/deepseek-ai/DeepSeek-V3', + displayName: 'Pro/deepseek-ai/DeepSeek-V3', + maxInputTokens: 164000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.25, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Pro/deepseek-ai/DeepSeek-V3.1-Terminus', + displayName: 'Pro/deepseek-ai/DeepSeek-V3.1-Terminus', + maxInputTokens: 164000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.27, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Pro/deepseek-ai/DeepSeek-V3.2', + displayName: 'Pro/deepseek-ai/DeepSeek-V3.2', + maxInputTokens: 164000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.27, + outputPerM: 0.42, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Pro/MiniMaxAI/MiniMax-M2.1', + displayName: 'Pro/MiniMaxAI/MiniMax-M2.1', + maxInputTokens: 197000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Pro/moonshotai/Kimi-K2-Instruct-0905', + displayName: 'Pro/moonshotai/Kimi-K2-Instruct-0905', + maxInputTokens: 262000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.4, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Pro/moonshotai/Kimi-K2-Thinking', + displayName: 'Pro/moonshotai/Kimi-K2-Thinking', + maxInputTokens: 262000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.55, + outputPerM: 2.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Pro/moonshotai/Kimi-K2.5', + displayName: 'Pro/moonshotai/Kimi-K2.5', + maxInputTokens: 262000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.55, + outputPerM: 3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Pro/zai-org/GLM-4.7', + displayName: 'Pro/zai-org/GLM-4.7', + maxInputTokens: 205000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Pro/zai-org/GLM-5', + displayName: 'Pro/zai-org/GLM-5', + maxInputTokens: 205000, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 3.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen2.5-14B-Instruct', + displayName: 'Qwen/Qwen2.5-14B-Instruct', + maxInputTokens: 33000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen2.5-32B-Instruct', + displayName: 'Qwen/Qwen2.5-32B-Instruct', + maxInputTokens: 33000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.18, + outputPerM: 0.18, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen2.5-72B-Instruct', + displayName: 'Qwen/Qwen2.5-72B-Instruct', + maxInputTokens: 33000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.59, + outputPerM: 0.59, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen2.5-72B-Instruct-128K', + displayName: 'Qwen/Qwen2.5-72B-Instruct-128K', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.59, + outputPerM: 0.59, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen2.5-7B-Instruct', + displayName: 'Qwen/Qwen2.5-7B-Instruct', + maxInputTokens: 33000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.05, + outputPerM: 0.05, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen2.5-Coder-32B-Instruct', + displayName: 'Qwen/Qwen2.5-Coder-32B-Instruct', + maxInputTokens: 33000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.18, + outputPerM: 0.18, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen2.5-VL-32B-Instruct', + displayName: 'Qwen/Qwen2.5-VL-32B-Instruct', + maxInputTokens: 131000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.27, + outputPerM: 0.27, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen2.5-VL-72B-Instruct', + displayName: 'Qwen/Qwen2.5-VL-72B-Instruct', + maxInputTokens: 131000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.59, + outputPerM: 0.59, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-14B', + displayName: 'Qwen/Qwen3-14B', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.07, + outputPerM: 0.28, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-235B-A22B-Instruct-2507', + displayName: 'Qwen/Qwen3-235B-A22B-Instruct-2507', + maxInputTokens: 262000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.09, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-235B-A22B-Thinking-2507', + displayName: 'Qwen/Qwen3-235B-A22B-Thinking-2507', + maxInputTokens: 262000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.13, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-30B-A3B-Instruct-2507', + displayName: 'Qwen/Qwen3-30B-A3B-Instruct-2507', + maxInputTokens: 262000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.09, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-30B-A3B-Thinking-2507', + displayName: 'Qwen/Qwen3-30B-A3B-Thinking-2507', + maxInputTokens: 262000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.09, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-32B', + displayName: 'Qwen/Qwen3-32B', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.14, + outputPerM: 0.57, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-8B', + displayName: 'Qwen/Qwen3-8B', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.06, + outputPerM: 0.06, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-Coder-30B-A3B-Instruct', + displayName: 'Qwen/Qwen3-Coder-30B-A3B-Instruct', + maxInputTokens: 262000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.07, + outputPerM: 0.28, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-Coder-480B-A35B-Instruct', + displayName: 'Qwen/Qwen3-Coder-480B-A35B-Instruct', + maxInputTokens: 262000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.25, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-Next-80B-A3B-Instruct', + displayName: 'Qwen/Qwen3-Next-80B-A3B-Instruct', + maxInputTokens: 262000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.14, + outputPerM: 1.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-Next-80B-A3B-Thinking', + displayName: 'Qwen/Qwen3-Next-80B-A3B-Thinking', + maxInputTokens: 262000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.14, + outputPerM: 0.57, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-Omni-30B-A3B-Captioner', + displayName: 'Qwen/Qwen3-Omni-30B-A3B-Captioner', + maxInputTokens: 66000, + supportedFileTypes: ['audio'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-Omni-30B-A3B-Instruct', + displayName: 'Qwen/Qwen3-Omni-30B-A3B-Instruct', + maxInputTokens: 66000, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-Omni-30B-A3B-Thinking', + displayName: 'Qwen/Qwen3-Omni-30B-A3B-Thinking', + maxInputTokens: 66000, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-VL-235B-A22B-Instruct', + displayName: 'Qwen/Qwen3-VL-235B-A22B-Instruct', + maxInputTokens: 262000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.3, + outputPerM: 1.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-VL-235B-A22B-Thinking', + displayName: 'Qwen/Qwen3-VL-235B-A22B-Thinking', + maxInputTokens: 262000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.45, + outputPerM: 3.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-VL-30B-A3B-Instruct', + displayName: 'Qwen/Qwen3-VL-30B-A3B-Instruct', + maxInputTokens: 262000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.29, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-VL-30B-A3B-Thinking', + displayName: 'Qwen/Qwen3-VL-30B-A3B-Thinking', + maxInputTokens: 262000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.29, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-VL-32B-Instruct', + displayName: 'Qwen/Qwen3-VL-32B-Instruct', + maxInputTokens: 262000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.2, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-VL-32B-Thinking', + displayName: 'Qwen/Qwen3-VL-32B-Thinking', + maxInputTokens: 262000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.2, + outputPerM: 1.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-VL-8B-Instruct', + displayName: 'Qwen/Qwen3-VL-8B-Instruct', + maxInputTokens: 262000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.18, + outputPerM: 0.68, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-VL-8B-Thinking', + displayName: 'Qwen/Qwen3-VL-8B-Thinking', + maxInputTokens: 262000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.18, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/QwQ-32B', + displayName: 'Qwen/QwQ-32B', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0.58, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'stepfun-ai/Step-3.5-Flash', + displayName: 'stepfun-ai/Step-3.5-Flash', + maxInputTokens: 262000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'tencent/Hunyuan-A13B-Instruct', + displayName: 'tencent/Hunyuan-A13B-Instruct', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.14, + outputPerM: 0.57, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'tencent/Hunyuan-MT-7B', + displayName: 'tencent/Hunyuan-MT-7B', + maxInputTokens: 33000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'THUDM/GLM-4-32B-0414', + displayName: 'THUDM/GLM-4-32B-0414', + maxInputTokens: 33000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.27, + outputPerM: 0.27, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'THUDM/GLM-4-9B-0414', + displayName: 'THUDM/GLM-4-9B-0414', + maxInputTokens: 33000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.086, + outputPerM: 0.086, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'THUDM/GLM-Z1-32B-0414', + displayName: 'THUDM/GLM-Z1-32B-0414', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.14, + outputPerM: 0.57, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'THUDM/GLM-Z1-9B-0414', + displayName: 'THUDM/GLM-Z1-9B-0414', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.086, + outputPerM: 0.086, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-4.5-Air', + displayName: 'zai-org/GLM-4.5-Air', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.14, + outputPerM: 0.86, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-4.5V', + displayName: 'zai-org/GLM-4.5V', + maxInputTokens: 66000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.14, + outputPerM: 0.86, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-4.6', + displayName: 'zai-org/GLM-4.6', + maxInputTokens: 205000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.5, + outputPerM: 1.9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-4.6V', + displayName: 'zai-org/GLM-4.6V', + maxInputTokens: 131000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.3, + outputPerM: 0.9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + stackit: [ + { + name: 'cortecs/Llama-3.3-70B-Instruct-FP8-Dynamic', + displayName: 'Llama 3.3 70B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.49, + outputPerM: 0.71, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemma-3-27b-it', + displayName: 'Gemma 3 27B', + maxInputTokens: 37000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.49, + outputPerM: 0.71, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'intfloat/e5-mistral-7b-instruct', + displayName: 'E5 Mistral 7B', + maxInputTokens: 4096, + supportedFileTypes: [], + pricing: { + inputPerM: 0.02, + outputPerM: 0.02, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'neuralmagic/Meta-Llama-3.1-8B-Instruct-FP8', + displayName: 'Llama 3.1 8B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.16, + outputPerM: 0.27, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'neuralmagic/Mistral-Nemo-Instruct-2407-FP8', + displayName: 'Mistral Nemo', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.49, + outputPerM: 0.71, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-120b', + displayName: 'GPT-OSS 120B', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.49, + outputPerM: 0.71, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-VL-235B-A22B-Instruct-FP8', + displayName: 'Qwen3-VL 235B', + maxInputTokens: 218000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.64, + outputPerM: 1.91, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-VL-Embedding-8B', + displayName: 'Qwen3-VL Embedding 8B', + maxInputTokens: 32000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.09, + outputPerM: 0.09, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + stepfun: [ + { + name: 'step-1-32k', + displayName: 'Step 1 (32K)', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 2.05, + outputPerM: 9.59, + cacheReadPerM: 0.41, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'step-2-16k', + displayName: 'Step 2 (16K)', + maxInputTokens: 16384, + supportedFileTypes: [], + pricing: { + inputPerM: 5.21, + outputPerM: 16.44, + cacheReadPerM: 1.04, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'step-3.5-flash', + displayName: 'Step 3.5 Flash', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.096, + outputPerM: 0.288, + cacheReadPerM: 0.019, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + submodel: [ + { + name: 'deepseek-ai/DeepSeek-R1-0528', + displayName: 'DeepSeek R1 0528', + maxInputTokens: 75000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.5, + outputPerM: 2.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/DeepSeek-V3-0324', + displayName: 'DeepSeek V3 0324', + maxInputTokens: 75000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/DeepSeek-V3.1', + displayName: 'DeepSeek V3.1', + maxInputTokens: 75000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-120b', + displayName: 'GPT OSS 120B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-235B-A22B-Instruct-2507', + displayName: 'Qwen3 235B A22B Instruct 2507', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-235B-A22B-Thinking-2507', + displayName: 'Qwen3 235B A22B Thinking 2507', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-Coder-480B-A35B-Instruct-FP8', + displayName: 'Qwen3 Coder 480B A35B Instruct', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-4.5-Air', + displayName: 'GLM 4.5 Air', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-4.5-FP8', + displayName: 'GLM 4.5 FP8', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + synthetic: [ + { + name: 'hf:deepseek-ai/DeepSeek-R1', + displayName: 'DeepSeek R1', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.55, + outputPerM: 2.19, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'hf:deepseek-ai/DeepSeek-R1-0528', + displayName: 'DeepSeek R1 (0528)', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 3, + outputPerM: 8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'hf:deepseek-ai/DeepSeek-V3', + displayName: 'DeepSeek V3', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 1.25, + outputPerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'hf:deepseek-ai/DeepSeek-V3-0324', + displayName: 'DeepSeek V3 (0324)', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 1.2, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'hf:deepseek-ai/DeepSeek-V3.1', + displayName: 'DeepSeek V3.1', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.56, + outputPerM: 1.68, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'hf:deepseek-ai/DeepSeek-V3.1-Terminus', + displayName: 'DeepSeek V3.1 Terminus', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 1.2, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'hf:deepseek-ai/DeepSeek-V3.2', + displayName: 'DeepSeek V3.2', + maxInputTokens: 162816, + supportedFileTypes: [], + pricing: { + inputPerM: 0.27, + outputPerM: 0.4, + cacheReadPerM: 0.27, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'hf:meta-llama/Llama-3.1-405B-Instruct', + displayName: 'Llama-3.1-405B-Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 3, + outputPerM: 3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'hf:meta-llama/Llama-3.1-70B-Instruct', + displayName: 'Llama-3.1-70B-Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.9, + outputPerM: 0.9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'hf:meta-llama/Llama-3.1-8B-Instruct', + displayName: 'Llama-3.1-8B-Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'hf:meta-llama/Llama-3.3-70B-Instruct', + displayName: 'Llama-3.3-70B-Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.9, + outputPerM: 0.9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'hf:meta-llama/Llama-4-Maverick-17B-128E-Instruct-FP8', + displayName: 'Llama-4-Maverick-17B-128E-Instruct-FP8', + maxInputTokens: 524000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.22, + outputPerM: 0.88, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'hf:meta-llama/Llama-4-Scout-17B-16E-Instruct', + displayName: 'Llama-4-Scout-17B-16E-Instruct', + maxInputTokens: 328000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'hf:MiniMaxAI/MiniMax-M2', + displayName: 'MiniMax-M2', + maxInputTokens: 196608, + supportedFileTypes: [], + pricing: { + inputPerM: 0.55, + outputPerM: 2.19, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'hf:MiniMaxAI/MiniMax-M2.1', + displayName: 'MiniMax-M2.1', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.55, + outputPerM: 2.19, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'hf:moonshotai/Kimi-K2-Instruct-0905', + displayName: 'Kimi K2 0905', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 1.2, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'hf:moonshotai/Kimi-K2-Thinking', + displayName: 'Kimi K2 Thinking', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.55, + outputPerM: 2.19, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'hf:moonshotai/Kimi-K2.5', + displayName: 'Kimi K2.5', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.55, + outputPerM: 2.19, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'hf:nvidia/Kimi-K2.5-NVFP4', + displayName: 'Kimi K2.5 (NVFP4)', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.55, + outputPerM: 2.19, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'hf:openai/gpt-oss-120b', + displayName: 'GPT OSS 120B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'hf:Qwen/Qwen2.5-Coder-32B-Instruct', + displayName: 'Qwen2.5-Coder-32B-Instruct', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.8, + outputPerM: 0.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'hf:Qwen/Qwen3-235B-A22B-Instruct-2507', + displayName: 'Qwen 3 235B Instruct', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'hf:Qwen/Qwen3-235B-A22B-Thinking-2507', + displayName: 'Qwen3 235B A22B Thinking 2507', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.65, + outputPerM: 3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'hf:Qwen/Qwen3-Coder-480B-A35B-Instruct', + displayName: 'Qwen 3 Coder 480B', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 2, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'hf:zai-org/GLM-4.6', + displayName: 'GLM 4.6', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.55, + outputPerM: 2.19, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'hf:zai-org/GLM-4.7', + displayName: 'GLM 4.7', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.55, + outputPerM: 2.19, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + togetherai: [ + { + name: 'deepseek-ai/DeepSeek-R1', + displayName: 'DeepSeek R1', + maxInputTokens: 163839, + supportedFileTypes: [], + pricing: { + inputPerM: 3, + outputPerM: 7, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/DeepSeek-V3', + displayName: 'DeepSeek V3', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 1.25, + outputPerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-ai/DeepSeek-V3-1', + displayName: 'DeepSeek V3.1', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 1.7, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'essentialai/Rnj-1-Instruct', + displayName: 'Rnj-1 Instruct', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta-llama/Llama-3.3-70B-Instruct-Turbo', + displayName: 'Llama 3.3 70B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.88, + outputPerM: 0.88, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'MiniMaxAI/MiniMax-M2.5', + displayName: 'MiniMax-M2.5', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/Kimi-K2-Instruct', + displayName: 'Kimi K2 Instruct', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/Kimi-K2-Instruct-0905', + displayName: 'Kimi K2 Instruct-0905', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/Kimi-K2-Thinking', + displayName: 'Kimi K2 Thinking', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 1.2, + outputPerM: 4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/Kimi-K2.5', + displayName: 'Kimi K2.5', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.5, + outputPerM: 2.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-120b', + displayName: 'GPT OSS 120B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-235B-A22B-Instruct-2507-tput', + displayName: 'Qwen3 235B A22B Instruct 2507 FP8', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-Coder-480B-A35B-Instruct-FP8', + displayName: 'Qwen3 Coder 480B A35B Instruct', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 2, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-Coder-Next-FP8', + displayName: 'Qwen3 Coder Next FP8', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.5, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3-Next-80B-A3B-Instruct', + displayName: 'Qwen3-Next-80B-A3B-Instruct', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 1.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'Qwen/Qwen3.5-397B-A17B', + displayName: 'Qwen3.5 397B A17B', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.6, + outputPerM: 3.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-4.6', + displayName: 'GLM 4.6', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-4.7', + displayName: 'GLM-4.7', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.45, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org/GLM-5', + displayName: 'GLM-5', + maxInputTokens: 202752, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 3.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + upstage: [ + { + name: 'solar-mini', + displayName: 'solar-mini', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'solar-pro2', + displayName: 'solar-pro2', + maxInputTokens: 65536, + supportedFileTypes: [], + pricing: { + inputPerM: 0.25, + outputPerM: 0.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'solar-pro3', + displayName: 'solar-pro3', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.25, + outputPerM: 0.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + v0: [ + { + name: 'v0-1.0-md', + displayName: 'v0-1.0-md', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'v0-1.5-lg', + displayName: 'v0-1.5-lg', + maxInputTokens: 512000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 15, + outputPerM: 75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'v0-1.5-md', + displayName: 'v0-1.5-md', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + venice: [ + { + name: 'claude-opus-4-6', + displayName: 'Claude Opus 4.6', + maxInputTokens: 1000000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 6, + outputPerM: 30, + cacheReadPerM: 0.6, + cacheWritePerM: 7.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-opus-45', + displayName: 'Claude Opus 4.5', + maxInputTokens: 198000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 6, + outputPerM: 30, + cacheReadPerM: 0.6, + cacheWritePerM: 7.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-sonnet-4-6', + displayName: 'Claude Sonnet 4.6', + maxInputTokens: 1000000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 3.75, + outputPerM: 18.75, + cacheReadPerM: 0.375, + cacheWritePerM: 4.69, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'claude-sonnet-45', + displayName: 'Claude Sonnet 4.5', + maxInputTokens: 198000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 3.75, + outputPerM: 18.75, + cacheReadPerM: 0.375, + cacheWritePerM: 4.69, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek-v3.2', + displayName: 'DeepSeek V3.2', + maxInputTokens: 160000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.4, + outputPerM: 1, + cacheReadPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-3-1-pro-preview', + displayName: 'Gemini 3.1 Pro Preview', + maxInputTokens: 1000000, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 2.5, + outputPerM: 15, + cacheReadPerM: 0.5, + cacheWritePerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-3-flash-preview', + displayName: 'Gemini 3 Flash Preview', + maxInputTokens: 256000, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.7, + outputPerM: 3.75, + cacheReadPerM: 0.07, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'gemini-3-pro-preview', + displayName: 'Gemini 3 Pro Preview', + maxInputTokens: 198000, + supportedFileTypes: ['image', 'audio'], + pricing: { + inputPerM: 2.5, + outputPerM: 15, + cacheReadPerM: 0.625, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google-gemma-3-27b-it', + displayName: 'Google Gemma 3 27B Instruct', + maxInputTokens: 198000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.12, + outputPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'grok-41-fast', + displayName: 'Grok 4.1 Fast', + maxInputTokens: 256000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.5, + outputPerM: 1.25, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'grok-code-fast-1', + displayName: 'Grok Code Fast 1', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.25, + outputPerM: 1.87, + cacheReadPerM: 0.03, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'hermes-3-llama-3.1-405b', + displayName: 'Hermes 3 Llama 3.1 405b', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 1.1, + outputPerM: 3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2-5', + displayName: 'Kimi K2.5', + maxInputTokens: 256000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.75, + outputPerM: 3.75, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kimi-k2-thinking', + displayName: 'Kimi K2 Thinking', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.75, + outputPerM: 3.2, + cacheReadPerM: 0.375, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'llama-3.2-3b', + displayName: 'Llama 3.2 3B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'llama-3.3-70b', + displayName: 'Llama 3.3 70B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.7, + outputPerM: 2.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'minimax-m21', + displayName: 'MiniMax M2.1', + maxInputTokens: 198000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.4, + outputPerM: 1.6, + cacheReadPerM: 0.04, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'minimax-m25', + displayName: 'MiniMax M2.5', + maxInputTokens: 198000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.4, + outputPerM: 1.6, + cacheReadPerM: 0.04, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral-31-24b', + displayName: 'Venice Medium', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.5, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'olafangensan-glm-4.7-flash-heretic', + displayName: 'GLM 4.7 Flash Heretic', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.14, + outputPerM: 0.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai-gpt-52', + displayName: 'GPT-5.2', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 2.19, + outputPerM: 17.5, + cacheReadPerM: 0.219, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai-gpt-52-codex', + displayName: 'GPT-5.2 Codex', + maxInputTokens: 256000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2.19, + outputPerM: 17.5, + cacheReadPerM: 0.219, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai-gpt-oss-120b', + displayName: 'OpenAI GPT OSS 120B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.07, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen3-235b-a22b-instruct-2507', + displayName: 'Qwen 3 235B A22B Instruct 2507', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen3-235b-a22b-thinking-2507', + displayName: 'Qwen 3 235B A22B Thinking 2507', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.45, + outputPerM: 3.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen3-4b', + displayName: 'Venice Small', + maxInputTokens: 32000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.05, + outputPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen3-coder-480b-a35b-instruct', + displayName: 'Qwen 3 Coder 480b', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.75, + outputPerM: 3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen3-next-80b', + displayName: 'Qwen 3 Next 80b', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.35, + outputPerM: 1.9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'qwen3-vl-235b-a22b', + displayName: 'Qwen3 VL 235B', + maxInputTokens: 256000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.25, + outputPerM: 1.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'venice-uncensored', + displayName: 'Venice Uncensored 1.1', + maxInputTokens: 32000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org-glm-4.7', + displayName: 'GLM 4.7', + maxInputTokens: 198000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.55, + outputPerM: 2.65, + cacheReadPerM: 0.11, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org-glm-4.7-flash', + displayName: 'GLM 4.7 Flash', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.125, + outputPerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai-org-glm-5', + displayName: 'GLM 5', + maxInputTokens: 198000, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 3.2, + cacheReadPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + ], + vercel: [ + { + name: 'alibaba/qwen-3-14b', + displayName: 'Qwen3-14B', + maxInputTokens: 40960, + supportedFileTypes: [], + pricing: { + inputPerM: 0.06, + outputPerM: 0.24, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'alibaba/qwen-3-235b', + displayName: 'Qwen3 235B A22B Instruct 2507', + maxInputTokens: 40960, + supportedFileTypes: [], + pricing: { + inputPerM: 0.13, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'alibaba/qwen-3-30b', + displayName: 'Qwen3-30B-A3B', + maxInputTokens: 40960, + supportedFileTypes: [], + pricing: { + inputPerM: 0.08, + outputPerM: 0.29, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'alibaba/qwen-3-32b', + displayName: 'Qwen 3.32B', + maxInputTokens: 40960, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'alibaba/qwen3-235b-a22b-thinking', + displayName: 'Qwen3 235B A22B Thinking 2507', + maxInputTokens: 262114, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0.3, + outputPerM: 2.9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'alibaba/qwen3-coder', + displayName: 'Qwen3 Coder 480B A35B Instruct', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.38, + outputPerM: 1.53, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'alibaba/qwen3-coder-30b-a3b', + displayName: 'Qwen 3 Coder 30B A3B Instruct', + maxInputTokens: 160000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.07, + outputPerM: 0.27, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'alibaba/qwen3-coder-next', + displayName: 'Qwen3 Coder Next', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.5, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'alibaba/qwen3-coder-plus', + displayName: 'Qwen3 Coder Plus', + maxInputTokens: 1000000, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'alibaba/qwen3-embedding-0.6b', + displayName: 'Qwen3 Embedding 0.6B', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.01, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'alibaba/qwen3-embedding-4b', + displayName: 'Qwen3 Embedding 4B', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.02, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'alibaba/qwen3-embedding-8b', + displayName: 'Qwen3 Embedding 8B', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.05, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'alibaba/qwen3-max', + displayName: 'Qwen3 Max', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 1.2, + outputPerM: 6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'alibaba/qwen3-max-preview', + displayName: 'Qwen3 Max Preview', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 1.2, + outputPerM: 6, + cacheReadPerM: 0.24, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'alibaba/qwen3-max-thinking', + displayName: 'Qwen 3 Max Thinking', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 1.2, + outputPerM: 6, + cacheReadPerM: 0.24, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'alibaba/qwen3-next-80b-a3b-instruct', displayName: 'Qwen3 Next 80B A3B Instruct', maxInputTokens: 262144, supportedFileTypes: [], pricing: { - inputPerM: 0.14, - outputPerM: 1.4, + inputPerM: 0.09, + outputPerM: 1.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'alibaba/qwen3-next-80b-a3b-thinking', + displayName: 'Qwen3 Next 80B A3B Thinking', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 1.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'alibaba/qwen3-vl-instruct', + displayName: 'Qwen3 VL Instruct', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.7, + outputPerM: 2.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'alibaba/qwen3-vl-thinking', + displayName: 'Qwen3 VL Thinking', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.7, + outputPerM: 8.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'alibaba/qwen3.5-plus', + displayName: 'Qwen 3.5 Plus', + maxInputTokens: 1000000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0.4, + outputPerM: 2.4, + cacheReadPerM: 0.04, + cacheWritePerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'amazon/nova-2-lite', + displayName: 'Nova 2 Lite', + maxInputTokens: 1000000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.3, + outputPerM: 2.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'amazon/nova-lite', + displayName: 'Nova Lite', + maxInputTokens: 300000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.06, + outputPerM: 0.24, + cacheReadPerM: 0.015, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'amazon/nova-micro', + displayName: 'Nova Micro', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.035, + outputPerM: 0.14, + cacheReadPerM: 0.00875, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'amazon/nova-pro', + displayName: 'Nova Pro', + maxInputTokens: 300000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.8, + outputPerM: 3.2, + cacheReadPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'amazon/titan-embed-text-v2', + displayName: 'Titan Text Embeddings V2', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0.02, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-3-haiku', + displayName: 'Claude Haiku 3', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0.25, + outputPerM: 1.25, + cacheReadPerM: 0.03, + cacheWritePerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-3-opus', + displayName: 'Claude Opus 3', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 15, + outputPerM: 75, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-3.5-haiku', + displayName: 'Claude Haiku 3.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0.8, + outputPerM: 4, + cacheReadPerM: 0.08, + cacheWritePerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-3.5-sonnet', + displayName: 'Claude Sonnet 3.5 v2', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-3.5-sonnet-20240620', + displayName: 'Claude 3.5 Sonnet (2024-06-20)', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-3.7-sonnet', + displayName: 'Claude Sonnet 3.7', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-haiku-4.5', + displayName: 'Claude Haiku 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1, + outputPerM: 5, + cacheReadPerM: 0.1, + cacheWritePerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-opus-4', + displayName: 'Claude Opus 4', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 15, + outputPerM: 75, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-opus-4.1', + displayName: 'Claude Opus 4', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 15, + outputPerM: 75, + cacheReadPerM: 1.5, + cacheWritePerM: 18.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-opus-4.5', + displayName: 'Claude Opus 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 18.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-opus-4.6', + displayName: 'Claude Opus 4.6', + maxInputTokens: 1000000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 0.5, + cacheWritePerM: 6.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-sonnet-4', + displayName: 'Claude Sonnet 4', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-sonnet-4.5', + displayName: 'Claude Sonnet 4.5', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'anthropic/claude-sonnet-4.6', + displayName: 'Claude Sonnet 4.6', + maxInputTokens: 1000000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'arcee-ai/trinity-large-preview', + displayName: 'Trinity Large Preview', + maxInputTokens: 131000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.25, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'arcee-ai/trinity-mini', + displayName: 'Trinity Mini', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.05, + outputPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'bfl/flux-kontext-max', + displayName: 'FLUX.1 Kontext Max', + maxInputTokens: 512, + supportedFileTypes: [], + }, + { + name: 'bfl/flux-kontext-pro', + displayName: 'FLUX.1 Kontext Pro', + maxInputTokens: 512, + supportedFileTypes: [], + }, + { + name: 'bfl/flux-pro-1.0-fill', + displayName: 'FLUX.1 Fill [pro]', + maxInputTokens: 512, + supportedFileTypes: [], + }, + { + name: 'bfl/flux-pro-1.1', + displayName: 'FLUX1.1 [pro]', + maxInputTokens: 512, + supportedFileTypes: [], + }, + { + name: 'bfl/flux-pro-1.1-ultra', + displayName: 'FLUX1.1 [pro] Ultra', + maxInputTokens: 512, + supportedFileTypes: [], + }, + { + name: 'bytedance/seed-1.6', + displayName: 'Seed 1.6', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.25, + outputPerM: 2, + cacheReadPerM: 0.05, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'bytedance/seed-1.8', + displayName: 'Seed 1.8', + maxInputTokens: 256000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.25, + outputPerM: 2, + cacheReadPerM: 0.05, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'cohere/command-a', + displayName: 'Command A', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 2.5, + outputPerM: 10, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'cohere/embed-v4.0', + displayName: 'Embed v4.0', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0.12, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-r1', + displayName: 'DeepSeek-R1', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 1.35, + outputPerM: 5.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-v3', + displayName: 'DeepSeek V3 0324', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.77, + outputPerM: 0.77, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-v3.1', + displayName: 'DeepSeek-V3.1', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-v3.1-terminus', + displayName: 'DeepSeek V3.1 Terminus', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.27, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-v3.2', + displayName: 'DeepSeek V3.2', + maxInputTokens: 163842, + supportedFileTypes: [], + pricing: { + inputPerM: 0.27, + outputPerM: 0.4, + cacheReadPerM: 0.22, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-v3.2-exp', + displayName: 'DeepSeek V3.2 Exp', + maxInputTokens: 163840, + supportedFileTypes: [], + pricing: { + inputPerM: 0.27, + outputPerM: 0.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-v3.2-thinking', + displayName: 'DeepSeek V3.2 Thinking', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.28, + outputPerM: 0.42, + cacheReadPerM: 0.03, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.0-flash', + displayName: 'Gemini 2.0 Flash', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.4, + cacheReadPerM: 0.025, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.0-flash-lite', + displayName: 'Gemini 2.0 Flash Lite', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.075, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.5-flash', + displayName: 'Gemini 2.5 Flash', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.3, + outputPerM: 2.5, + cacheReadPerM: 0.075, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.5-flash-image', + displayName: 'Nano Banana (Gemini 2.5 Flash Image)', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 2.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.5-flash-image-preview', + displayName: 'Nano Banana Preview (Gemini 2.5 Flash Image Preview)', + maxInputTokens: 32768, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 2.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.5-flash-lite', + displayName: 'Gemini 2.5 Flash Lite', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.4, + cacheReadPerM: 0.01, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.5-flash-lite-preview-09-2025', + displayName: 'Gemini 2.5 Flash Lite Preview 09-25', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.4, + cacheReadPerM: 0.01, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.5-flash-preview-09-2025', + displayName: 'Gemini 2.5 Flash Preview 09-25', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.3, + outputPerM: 2.5, + cacheReadPerM: 0.03, + cacheWritePerM: 0.383, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.5-pro', + displayName: 'Gemini 2.5 Pro', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.31, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-3-flash', + displayName: 'Gemini 3 Flash', + maxInputTokens: 1000000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0.5, + outputPerM: 3, + cacheReadPerM: 0.05, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-3-pro-image', + displayName: 'Nano Banana Pro (Gemini 3 Pro Image)', + maxInputTokens: 65536, + supportedFileTypes: [], + pricing: { + inputPerM: 2, + outputPerM: 120, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-3-pro-preview', + displayName: 'Gemini 3 Pro Preview', + maxInputTokens: 1000000, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 2, + outputPerM: 12, + cacheReadPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-embedding-001', + displayName: 'Gemini Embedding 001', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/imagen-4.0-fast-generate-001', + displayName: 'Imagen 4 Fast', + maxInputTokens: 480, + supportedFileTypes: [], + }, + { + name: 'google/imagen-4.0-generate-001', + displayName: 'Imagen 4', + maxInputTokens: 480, + supportedFileTypes: [], + }, + { + name: 'google/imagen-4.0-ultra-generate-001', + displayName: 'Imagen 4 Ultra', + maxInputTokens: 480, + supportedFileTypes: [], + }, + { + name: 'google/text-embedding-005', + displayName: 'Text Embedding 005', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0.03, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/text-multilingual-embedding-002', + displayName: 'Text Multilingual Embedding 002', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0.03, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'inception/mercury-coder-small', + displayName: 'Mercury Coder Small Beta', + maxInputTokens: 32000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.25, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'kwaipilot/kat-coder-pro-v1', + displayName: 'KAT-Coder-Pro V1', + maxInputTokens: 256000, + supportedFileTypes: [], + }, + { + name: 'meituan/longcat-flash-chat', + displayName: 'LongCat Flash Chat', + maxInputTokens: 128000, + supportedFileTypes: [], + }, + { + name: 'meituan/longcat-flash-thinking', + displayName: 'LongCat Flash Thinking', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 1.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta/llama-3.1-70b', + displayName: 'Llama 3.1 70B Instruct', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.4, + outputPerM: 0.4, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta/llama-3.1-8b', + displayName: 'Llama 3.1 8B Instruct', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.03, + outputPerM: 0.05, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta/llama-3.2-11b', + displayName: 'Llama 3.2 11B Vision Instruct', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.16, + outputPerM: 0.16, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta/llama-3.2-1b', + displayName: 'Llama 3.2 1B Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta/llama-3.2-3b', + displayName: 'Llama 3.2 3B Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta/llama-3.2-90b', + displayName: 'Llama 3.2 90B Vision Instruct', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.72, + outputPerM: 0.72, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta/llama-3.3-70b', + displayName: 'Llama-3.3-70B-Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta/llama-4-maverick', + displayName: 'Llama-4-Maverick-17B-128E-Instruct-FP8', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'meta/llama-4-scout', + displayName: 'Llama-4-Scout-17B-16E-Instruct-FP8', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'minimax/minimax-m2', + displayName: 'MiniMax M2', + maxInputTokens: 262114, + supportedFileTypes: [], + pricing: { + inputPerM: 0.27, + outputPerM: 1.15, + cacheReadPerM: 0.03, + cacheWritePerM: 0.38, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'minimax/minimax-m2.1', + displayName: 'MiniMax M2.1', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + cacheReadPerM: 0.03, + cacheWritePerM: 0.38, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'minimax/minimax-m2.1-lightning', + displayName: 'MiniMax M2.1 Lightning', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 2.4, + cacheReadPerM: 0.03, + cacheWritePerM: 0.38, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'minimax/minimax-m2.5', + displayName: 'MiniMax M2.5', + maxInputTokens: 204800, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 1.2, + cacheReadPerM: 0.03, + cacheWritePerM: 0.375, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral/codestral', + displayName: 'Codestral', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 0.9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral/codestral-embed', + displayName: 'Codestral Embed', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral/devstral-2', + displayName: 'Devstral 2', + maxInputTokens: 256000, + supportedFileTypes: [], + }, + { + name: 'mistral/devstral-small', + displayName: 'Devstral Small 1.1', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral/devstral-small-2', + displayName: 'Devstral Small 2', + maxInputTokens: 256000, + supportedFileTypes: [], + }, + { + name: 'mistral/magistral-medium', + displayName: 'Magistral Medium', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 2, + outputPerM: 5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral/magistral-small', + displayName: 'Magistral Small', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.5, + outputPerM: 1.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral/ministral-14b', + displayName: 'Ministral 14B', + maxInputTokens: 256000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0.2, + outputPerM: 0.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral/ministral-3b', + displayName: 'Ministral 3B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.04, + outputPerM: 0.04, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral/ministral-8b', + displayName: 'Ministral 8B', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral/mistral-embed', + displayName: 'Mistral Embed', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral/mistral-large-3', + displayName: 'Mistral Large 3', + maxInputTokens: 256000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.5, + outputPerM: 1.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral/mistral-medium', + displayName: 'Mistral Medium 3.1', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.4, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral/mistral-nemo', + displayName: 'Mistral Nemo', + maxInputTokens: 60288, + supportedFileTypes: [], + pricing: { + inputPerM: 0.04, + outputPerM: 0.17, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral/mistral-small', + displayName: 'Mistral Small', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral/mixtral-8x22b-instruct', + displayName: 'Mixtral 8x22B', + maxInputTokens: 64000, + supportedFileTypes: [], + pricing: { + inputPerM: 2, + outputPerM: 6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral/pixtral-12b', + displayName: 'Pixtral 12B', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.15, + outputPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'mistral/pixtral-large', + displayName: 'Pixtral Large', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2, + outputPerM: 6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2', + displayName: 'Kimi K2 Instruct', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2-0905', + displayName: 'Kimi K2 0905', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2-thinking', + displayName: 'Kimi K2 Thinking', + maxInputTokens: 216144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.47, + outputPerM: 2, + cacheReadPerM: 0.14, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2-thinking-turbo', + displayName: 'Kimi K2 Thinking Turbo', + maxInputTokens: 262114, + supportedFileTypes: [], + pricing: { + inputPerM: 1.15, + outputPerM: 8, + cacheReadPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2-turbo', + displayName: 'Kimi K2 Turbo', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 2.4, + outputPerM: 10, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'moonshotai/kimi-k2.5', + displayName: 'Kimi K2.5', + maxInputTokens: 262144, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.6, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'morph/morph-v3-fast', + displayName: 'Morph v3 Fast', + maxInputTokens: 16000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.8, + outputPerM: 1.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'morph/morph-v3-large', + displayName: 'Morph v3 Large', + maxInputTokens: 32000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.9, + outputPerM: 1.9, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nvidia/nemotron-3-nano-30b-a3b', + displayName: 'Nemotron 3 Nano 30B A3B', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.06, + outputPerM: 0.24, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nvidia/nemotron-nano-12b-v2-vl', + displayName: 'Nvidia Nemotron Nano 12B V2 VL', + maxInputTokens: 131072, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.2, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'nvidia/nemotron-nano-9b-v2', + displayName: 'Nvidia Nemotron Nano 9B V2', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.04, + outputPerM: 0.16, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/codex-mini', + displayName: 'Codex Mini', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1.5, + outputPerM: 6, + cacheReadPerM: 0.38, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-3.5-turbo', + displayName: 'GPT-3.5 Turbo', + maxInputTokens: 16385, + supportedFileTypes: [], + pricing: { + inputPerM: 0.5, + outputPerM: 1.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-3.5-turbo-instruct', + displayName: 'GPT-3.5 Turbo Instruct', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 1.5, + outputPerM: 2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4-turbo', + displayName: 'GPT-4 Turbo', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 10, + outputPerM: 30, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4.1', + displayName: 'GPT-4.1', + maxInputTokens: 1047576, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2, + outputPerM: 8, + cacheReadPerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4.1-mini', + displayName: 'GPT-4.1 mini', + maxInputTokens: 1047576, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.4, + outputPerM: 1.6, + cacheReadPerM: 0.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4.1-nano', + displayName: 'GPT-4.1 nano', + maxInputTokens: 1047576, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.4, + cacheReadPerM: 0.03, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4o', + displayName: 'GPT-4o', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2.5, + outputPerM: 10, + cacheReadPerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4o-mini', + displayName: 'GPT-4o mini', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + cacheReadPerM: 0.08, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-4o-mini-search-preview', + displayName: 'GPT 4o Mini Search Preview', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.15, + outputPerM: 0.6, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5', + displayName: 'GPT-5', + maxInputTokens: 272000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5-chat', + displayName: 'GPT-5 Chat', + maxInputTokens: 128000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.13, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5-codex', + displayName: 'GPT-5-Codex', + maxInputTokens: 272000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.125, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5-mini', + displayName: 'GPT-5 Mini', + maxInputTokens: 272000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.25, + outputPerM: 2, + cacheReadPerM: 0.025, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5-nano', + displayName: 'GPT-5 Nano', + maxInputTokens: 272000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.05, + outputPerM: 0.4, + cacheReadPerM: 0.005, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5-pro', + displayName: 'GPT-5 pro', + maxInputTokens: 400000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 15, + outputPerM: 120, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.1-codex', + displayName: 'GPT-5.1-Codex', + maxInputTokens: 400000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.13, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.1-codex-max', + displayName: 'GPT 5.1 Codex Max', + maxInputTokens: 400000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.13, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.1-codex-mini', + displayName: 'GPT-5.1 Codex mini', + maxInputTokens: 400000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 0.25, + outputPerM: 2, + cacheReadPerM: 0.03, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.1-instant', + displayName: 'GPT-5.1 Instant', + maxInputTokens: 128000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.13, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.1-thinking', + displayName: 'GPT 5.1 Thinking', + maxInputTokens: 400000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.13, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.2', + displayName: 'GPT-5.2', + maxInputTokens: 400000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1.75, + outputPerM: 14, + cacheReadPerM: 0.18, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.2-chat', + displayName: 'GPT-5.2 Chat', + maxInputTokens: 128000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1.75, + outputPerM: 14, + cacheReadPerM: 0.18, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.2-codex', + displayName: 'GPT-5.2-Codex', + maxInputTokens: 400000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 1.75, + outputPerM: 14, + cacheReadPerM: 0.175, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-5.2-pro', + displayName: 'GPT 5.2 ', + maxInputTokens: 400000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 21, + outputPerM: 168, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-120b', + displayName: 'GPT OSS 120B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-20b', + displayName: 'GPT OSS 20B', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.07, + outputPerM: 0.3, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/gpt-oss-safeguard-20b', + displayName: 'gpt-oss-safeguard-20b', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.08, + outputPerM: 0.3, + cacheReadPerM: 0.04, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/o1', + displayName: 'o1', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 15, + outputPerM: 60, + cacheReadPerM: 7.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/o3', + displayName: 'o3', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 2, + outputPerM: 8, + cacheReadPerM: 0.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/o3-deep-research', + displayName: 'o3-deep-research', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 10, + outputPerM: 40, + cacheReadPerM: 2.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/o3-mini', + displayName: 'o3-mini', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 1.1, + outputPerM: 4.4, + cacheReadPerM: 0.55, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/o3-pro', + displayName: 'o3 Pro', + maxInputTokens: 200000, + supportedFileTypes: ['pdf', 'image'], + pricing: { + inputPerM: 20, + outputPerM: 80, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/o4-mini', + displayName: 'o4-mini', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1.1, + outputPerM: 4.4, + cacheReadPerM: 0.28, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/text-embedding-3-large', + displayName: 'text-embedding-3-large', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0.13, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/text-embedding-3-small', + displayName: 'text-embedding-3-small', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0.02, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'openai/text-embedding-ada-002', + displayName: 'text-embedding-ada-002', + maxInputTokens: 8192, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'perplexity/sonar', + displayName: 'Sonar', + maxInputTokens: 127000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 1, + outputPerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'perplexity/sonar-pro', + displayName: 'Sonar Pro', + maxInputTokens: 200000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'perplexity/sonar-reasoning', + displayName: 'Sonar Reasoning', + maxInputTokens: 127000, + supportedFileTypes: [], + pricing: { + inputPerM: 1, + outputPerM: 5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'perplexity/sonar-reasoning-pro', + displayName: 'Sonar Reasoning Pro', + maxInputTokens: 127000, + supportedFileTypes: [], + pricing: { + inputPerM: 2, + outputPerM: 8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'prime-intellect/intellect-3', + displayName: 'INTELLECT 3', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 1.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'recraft/recraft-v2', + displayName: 'Recraft V2', + maxInputTokens: 512, + supportedFileTypes: [], + }, + { + name: 'recraft/recraft-v3', + displayName: 'Recraft V3', + maxInputTokens: 512, + supportedFileTypes: [], + }, + { + name: 'vercel/v0-1.0-md', + displayName: 'v0-1.0-md', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 3, + outputPerM: 15, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'qwen/qwen3-next-80b-a3b-instruct:free', - displayName: 'Qwen3 Next 80B A3B Instruct (free)', - maxInputTokens: 262144, + name: 'vercel/v0-1.5-md', + displayName: 'v0-1.5-md', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 3, + outputPerM: 15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'voyage/voyage-3-large', + displayName: 'voyage-3-large', + maxInputTokens: 8192, supportedFileTypes: [], pricing: { - inputPerM: 0, + inputPerM: 0.18, outputPerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'qwen/qwen3-next-80b-a3b-thinking', - displayName: 'Qwen3 Next 80B A3B Thinking', - maxInputTokens: 262144, + name: 'voyage/voyage-3.5', + displayName: 'voyage-3.5', + maxInputTokens: 8192, supportedFileTypes: [], pricing: { - inputPerM: 0.14, - outputPerM: 1.4, + inputPerM: 0.06, + outputPerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'qwen/qwen3.5-397b-a17b', - displayName: 'Qwen3.5 397B A17B', - maxInputTokens: 262144, - supportedFileTypes: ['image'], + name: 'voyage/voyage-3.5-lite', + displayName: 'voyage-3.5-lite', + maxInputTokens: 8192, + supportedFileTypes: [], pricing: { - inputPerM: 0.6, - outputPerM: 3.6, + inputPerM: 0.02, + outputPerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'qwen/qwen3.5-plus-02-15', - displayName: 'Qwen3.5 Plus 2026-02-15', - maxInputTokens: 1000000, - supportedFileTypes: ['image'], + name: 'voyage/voyage-code-2', + displayName: 'voyage-code-2', + maxInputTokens: 8192, + supportedFileTypes: [], pricing: { - inputPerM: 0.4, - outputPerM: 2.4, + inputPerM: 0.12, + outputPerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'qwen/qwq-32b:free', - displayName: 'QwQ 32B (free)', - maxInputTokens: 32768, + name: 'voyage/voyage-code-3', + displayName: 'voyage-code-3', + maxInputTokens: 8192, supportedFileTypes: [], pricing: { - inputPerM: 0, + inputPerM: 0.18, outputPerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'rekaai/reka-flash-3', - displayName: 'Reka Flash 3', - maxInputTokens: 32768, + name: 'voyage/voyage-finance-2', + displayName: 'voyage-finance-2', + maxInputTokens: 8192, supportedFileTypes: [], pricing: { - inputPerM: 0, + inputPerM: 0.12, outputPerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'sarvamai/sarvam-m:free', - displayName: 'Sarvam-M (free)', - maxInputTokens: 32768, + name: 'voyage/voyage-law-2', + displayName: 'voyage-law-2', + maxInputTokens: 8192, supportedFileTypes: [], pricing: { - inputPerM: 0, + inputPerM: 0.12, outputPerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'sourceful/riverflow-v2-fast-preview', - displayName: 'Riverflow V2 Fast Preview', + name: 'xai/grok-2-vision', + displayName: 'Grok 2 Vision', maxInputTokens: 8192, supportedFileTypes: ['image'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 2, + outputPerM: 10, + cacheReadPerM: 2, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'sourceful/riverflow-v2-max-preview', - displayName: 'Riverflow V2 Max Preview', - maxInputTokens: 8192, + name: 'xai/grok-3', + displayName: 'Grok 3', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'xai/grok-3-fast', + displayName: 'Grok 3 Fast', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 1.25, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'xai/grok-3-mini', + displayName: 'Grok 3 Mini', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.3, + outputPerM: 0.5, + cacheReadPerM: 0.075, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'xai/grok-3-mini-fast', + displayName: 'Grok 3 Mini Fast', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 4, + cacheReadPerM: 0.15, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'xai/grok-4', + displayName: 'Grok 4', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.75, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'xai/grok-4-fast-non-reasoning', + displayName: 'Grok 4 Fast (Non-Reasoning)', + maxInputTokens: 2000000, supportedFileTypes: ['image'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.2, + outputPerM: 0.5, + cacheReadPerM: 0.05, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'xai/grok-4-fast-reasoning', + displayName: 'Grok 4 Fast Reasoning', + maxInputTokens: 2000000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.5, + cacheReadPerM: 0.05, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'xai/grok-4.1-fast-non-reasoning', + displayName: 'Grok 4.1 Fast Non-Reasoning', + maxInputTokens: 2000000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.5, + cacheReadPerM: 0.05, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'xai/grok-4.1-fast-reasoning', + displayName: 'Grok 4.1 Fast Reasoning', + maxInputTokens: 2000000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 0.5, + cacheReadPerM: 0.05, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'xai/grok-code-fast-1', + displayName: 'Grok Code Fast 1', + maxInputTokens: 256000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 1.5, + cacheReadPerM: 0.02, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'xai/grok-imagine-image', + displayName: 'Grok Imagine Image', + maxInputTokens: 0, + supportedFileTypes: [], + }, + { + name: 'xai/grok-imagine-image-pro', + displayName: 'Grok Imagine Image Pro', + maxInputTokens: 0, + supportedFileTypes: [], + }, + { + name: 'xiaomi/mimo-v2-flash', + displayName: 'MiMo V2 Flash', + maxInputTokens: 262144, + supportedFileTypes: [], + pricing: { + inputPerM: 0.1, + outputPerM: 0.29, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai/glm-4.5', + displayName: 'GLM 4.5', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0.6, + outputPerM: 2.2, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai/glm-4.5-air', + displayName: 'GLM 4.5 Air', + maxInputTokens: 128000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.2, + outputPerM: 1.1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai/glm-4.5v', + displayName: 'GLM 4.5V', + maxInputTokens: 66000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.6, + outputPerM: 1.8, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'zai/glm-4.6', + displayName: 'GLM 4.6', + maxInputTokens: 200000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.45, + outputPerM: 1.8, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'sourceful/riverflow-v2-standard-preview', - displayName: 'Riverflow V2 Standard Preview', - maxInputTokens: 8192, - supportedFileTypes: ['image'], + name: 'zai/glm-4.6v', + displayName: 'GLM-4.6V', + maxInputTokens: 128000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.3, + outputPerM: 0.9, + cacheReadPerM: 0.05, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'stepfun/step-3.5-flash', - displayName: 'Step 3.5 Flash', - maxInputTokens: 256000, - supportedFileTypes: [], - pricing: { - inputPerM: 0.1, - outputPerM: 0.3, - cacheReadPerM: 0.02, - currency: 'USD', - unit: 'per_million_tokens', - }, + name: 'zai/glm-4.6v-flash', + displayName: 'GLM-4.6V-Flash', + maxInputTokens: 128000, + supportedFileTypes: ['pdf', 'image'], }, { - name: 'stepfun/step-3.5-flash:free', - displayName: 'Step 3.5 Flash (free)', - maxInputTokens: 256000, + name: 'zai/glm-4.7', + displayName: 'GLM 4.7', + maxInputTokens: 202752, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.43, + outputPerM: 1.75, + cacheReadPerM: 0.08, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'thudm/glm-z1-32b:free', - displayName: 'GLM Z1 32B (free)', - maxInputTokens: 32768, + name: 'zai/glm-4.7-flashx', + displayName: 'GLM 4.7 FlashX', + maxInputTokens: 200000, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.06, + outputPerM: 0.4, + cacheReadPerM: 0.01, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'tngtech/deepseek-r1t2-chimera:free', - displayName: 'DeepSeek R1T2 Chimera (free)', - maxInputTokens: 163840, + name: 'zai/glm-5', + displayName: 'GLM-5', + maxInputTokens: 202800, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 1, + outputPerM: 3.2, + cacheReadPerM: 0.2, currency: 'USD', unit: 'per_million_tokens', }, }, + ], + vivgrid: [ { - name: 'tngtech/tng-r1t-chimera:free', - displayName: 'R1T Chimera (free)', - maxInputTokens: 163840, + name: 'deepseek-v3.2', + displayName: 'DeepSeek-V3.2', + maxInputTokens: 128000, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.28, + outputPerM: 0.42, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'x-ai/grok-3', - displayName: 'Grok 3', - maxInputTokens: 131072, - supportedFileTypes: [], + name: 'gemini-3-flash-preview', + displayName: 'Gemini 3 Flash Preview', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], pricing: { - inputPerM: 3, - outputPerM: 15, - cacheReadPerM: 0.75, - cacheWritePerM: 15, + inputPerM: 0.5, + outputPerM: 3, + cacheReadPerM: 0.05, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'x-ai/grok-3-beta', - displayName: 'Grok 3 Beta', - maxInputTokens: 131072, - supportedFileTypes: [], + name: 'gemini-3-pro-preview', + displayName: 'Gemini 3 Pro Preview', + maxInputTokens: 1048576, + supportedFileTypes: ['pdf', 'image', 'audio'], pricing: { - inputPerM: 3, - outputPerM: 15, - cacheReadPerM: 0.75, - cacheWritePerM: 15, + inputPerM: 2, + outputPerM: 12, + cacheReadPerM: 0.2, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'x-ai/grok-3-mini', - displayName: 'Grok 3 Mini', - maxInputTokens: 131072, + name: 'glm-5', + displayName: 'GLM-5', + maxInputTokens: 202752, supportedFileTypes: [], pricing: { - inputPerM: 0.3, - outputPerM: 0.5, - cacheReadPerM: 0.075, - cacheWritePerM: 0.5, + inputPerM: 1, + outputPerM: 3.2, + cacheReadPerM: 0.2, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'x-ai/grok-3-mini-beta', - displayName: 'Grok 3 Mini Beta', - maxInputTokens: 131072, - supportedFileTypes: [], + name: 'gpt-5-mini', + displayName: 'GPT-5 Mini', + maxInputTokens: 272000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.3, - outputPerM: 0.5, - cacheReadPerM: 0.075, - cacheWritePerM: 0.5, + inputPerM: 0.25, + outputPerM: 2, + cacheReadPerM: 0.03, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'x-ai/grok-4', - displayName: 'Grok 4', - maxInputTokens: 256000, - supportedFileTypes: [], + name: 'gpt-5.1-codex', + displayName: 'GPT-5.1 Codex', + maxInputTokens: 400000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 3, - outputPerM: 15, - cacheReadPerM: 0.75, - cacheWritePerM: 15, + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.125, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'x-ai/grok-4-fast', - displayName: 'Grok 4 Fast', - maxInputTokens: 2000000, + name: 'gpt-5.1-codex-max', + displayName: 'GPT-5.1 Codex Max', + maxInputTokens: 400000, supportedFileTypes: ['image'], pricing: { - inputPerM: 0.2, - outputPerM: 0.5, - cacheReadPerM: 0.05, - cacheWritePerM: 0.05, + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.125, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'x-ai/grok-4.1-fast', - displayName: 'Grok 4.1 Fast', - maxInputTokens: 2000000, + name: 'gpt-5.2-codex', + displayName: 'GPT-5.2 Codex', + maxInputTokens: 400000, supportedFileTypes: ['image'], pricing: { - inputPerM: 0.2, - outputPerM: 0.5, - cacheReadPerM: 0.05, - cacheWritePerM: 0.05, + inputPerM: 1.75, + outputPerM: 14, + cacheReadPerM: 0.175, currency: 'USD', unit: 'per_million_tokens', }, }, + ], + vultr: [ { - name: 'x-ai/grok-code-fast-1', - displayName: 'Grok Code Fast 1', - maxInputTokens: 256000, + name: 'deepseek-r1-distill-llama-70b', + displayName: 'DeepSeek R1 Distill Llama 70B', + maxInputTokens: 121808, supportedFileTypes: [], pricing: { inputPerM: 0.2, - outputPerM: 1.5, - cacheReadPerM: 0.02, + outputPerM: 0.2, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'xiaomi/mimo-v2-flash', - displayName: 'MiMo-V2-Flash', - maxInputTokens: 262144, + name: 'deepseek-r1-distill-qwen-32b', + displayName: 'DeepSeek R1 Distill Qwen 32B', + maxInputTokens: 121808, supportedFileTypes: [], pricing: { - inputPerM: 0.1, - outputPerM: 0.3, - cacheReadPerM: 0.01, + inputPerM: 0.2, + outputPerM: 0.2, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'z-ai/glm-4.5', - displayName: 'GLM 4.5', - maxInputTokens: 128000, + name: 'gpt-oss-120b', + displayName: 'GPT OSS 120B', + maxInputTokens: 121808, supportedFileTypes: [], pricing: { - inputPerM: 0.6, - outputPerM: 2.2, + inputPerM: 0.2, + outputPerM: 0.2, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'z-ai/glm-4.5-air', - displayName: 'GLM 4.5 Air', - maxInputTokens: 128000, + name: 'kimi-k2-instruct', + displayName: 'Kimi K2 Instruct', + maxInputTokens: 58904, supportedFileTypes: [], pricing: { inputPerM: 0.2, - outputPerM: 1.1, + outputPerM: 0.2, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'z-ai/glm-4.5-air:free', - displayName: 'GLM 4.5 Air (free)', - maxInputTokens: 128000, + name: 'qwen2.5-coder-32b-instruct', + displayName: 'Qwen2.5 Coder 32B Instruct', + maxInputTokens: 12952, supportedFileTypes: [], pricing: { - inputPerM: 0, - outputPerM: 0, + inputPerM: 0.2, + outputPerM: 0.2, currency: 'USD', unit: 'per_million_tokens', }, }, + ], + wandb: [ { - name: 'z-ai/glm-4.5v', - displayName: 'GLM 4.5V', - maxInputTokens: 64000, - supportedFileTypes: ['image'], + name: 'deepseek-ai/DeepSeek-R1-0528', + displayName: 'DeepSeek-R1-0528', + maxInputTokens: 161000, + supportedFileTypes: [], pricing: { - inputPerM: 0.6, - outputPerM: 1.8, + inputPerM: 1.35, + outputPerM: 5.4, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'z-ai/glm-4.6', - displayName: 'GLM 4.6', - maxInputTokens: 200000, + name: 'deepseek-ai/DeepSeek-V3-0324', + displayName: 'DeepSeek-V3-0324', + maxInputTokens: 161000, supportedFileTypes: [], pricing: { - inputPerM: 0.6, - outputPerM: 2.2, - cacheReadPerM: 0.11, + inputPerM: 1.14, + outputPerM: 2.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'z-ai/glm-4.6:exacto', - displayName: 'GLM 4.6 (exacto)', - maxInputTokens: 200000, + name: 'meta-llama/Llama-3.1-8B-Instruct', + displayName: 'Meta-Llama-3.1-8B-Instruct', + maxInputTokens: 128000, supportedFileTypes: [], pricing: { - inputPerM: 0.6, - outputPerM: 1.9, - cacheReadPerM: 0.11, + inputPerM: 0.22, + outputPerM: 0.22, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'z-ai/glm-4.7', - displayName: 'GLM-4.7', - maxInputTokens: 204800, + name: 'meta-llama/Llama-3.3-70B-Instruct', + displayName: 'Llama-3.3-70B-Instruct', + maxInputTokens: 128000, supportedFileTypes: [], pricing: { - inputPerM: 0.6, - outputPerM: 2.2, - cacheReadPerM: 0.11, + inputPerM: 0.71, + outputPerM: 0.71, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'z-ai/glm-4.7-flash', - displayName: 'GLM-4.7-Flash', - maxInputTokens: 200000, - supportedFileTypes: [], + name: 'meta-llama/Llama-4-Scout-17B-16E-Instruct', + displayName: 'Llama 4 Scout 17B 16E Instruct', + maxInputTokens: 64000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.07, - outputPerM: 0.4, + inputPerM: 0.17, + outputPerM: 0.66, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'z-ai/glm-5', - displayName: 'GLM-5', - maxInputTokens: 202752, + name: 'microsoft/Phi-4-mini-instruct', + displayName: 'Phi-4-mini-instruct', + maxInputTokens: 128000, supportedFileTypes: [], pricing: { - inputPerM: 1, - outputPerM: 3.2, - cacheReadPerM: 0.2, + inputPerM: 0.08, + outputPerM: 0.35, currency: 'USD', unit: 'per_million_tokens', }, }, - ], - litellm: [], - glama: [], - vertex: [ { - name: 'claude-3-5-haiku@20241022', - displayName: 'Claude Haiku 3.5', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'moonshotai/Kimi-K2-Instruct', + displayName: 'Kimi-K2-Instruct', + maxInputTokens: 128000, + supportedFileTypes: [], pricing: { - inputPerM: 0.8, + inputPerM: 1.35, outputPerM: 4, - cacheReadPerM: 0.08, - cacheWritePerM: 1, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'claude-3-5-sonnet@20241022', - displayName: 'Claude Sonnet 3.5 v2', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'Qwen/Qwen3-235B-A22B-Instruct-2507', + displayName: 'Qwen3 235B A22B Instruct 2507', + maxInputTokens: 262144, + supportedFileTypes: [], pricing: { - inputPerM: 3, - outputPerM: 15, - cacheReadPerM: 0.3, - cacheWritePerM: 3.75, + inputPerM: 0.1, + outputPerM: 0.1, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'claude-3-7-sonnet@20250219', - displayName: 'Claude Sonnet 3.7', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'Qwen/Qwen3-235B-A22B-Thinking-2507', + displayName: 'Qwen3-235B-A22B-Thinking-2507', + maxInputTokens: 262144, + supportedFileTypes: [], pricing: { - inputPerM: 3, - outputPerM: 15, - cacheReadPerM: 0.3, - cacheWritePerM: 3.75, + inputPerM: 0.1, + outputPerM: 0.1, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'claude-haiku-4-5@20251001', - displayName: 'Claude Haiku 4.5', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'Qwen/Qwen3-Coder-480B-A35B-Instruct', + displayName: 'Qwen3-Coder-480B-A35B-Instruct', + maxInputTokens: 262144, + supportedFileTypes: [], pricing: { inputPerM: 1, - outputPerM: 5, - cacheReadPerM: 0.1, - cacheWritePerM: 1.25, + outputPerM: 1.5, currency: 'USD', unit: 'per_million_tokens', }, }, + ], + xai: [ { - name: 'claude-opus-4-1@20250805', - displayName: 'Claude Opus 4.1', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'grok-2', + displayName: 'Grok 2', + maxInputTokens: 131072, + supportedFileTypes: [], pricing: { - inputPerM: 15, - outputPerM: 75, - cacheReadPerM: 1.5, - cacheWritePerM: 18.75, + inputPerM: 2, + outputPerM: 10, + cacheReadPerM: 2, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'claude-opus-4-5@20251101', - displayName: 'Claude Opus 4.5', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'grok-2-1212', + displayName: 'Grok 2 (1212)', + maxInputTokens: 131072, + supportedFileTypes: [], pricing: { - inputPerM: 5, - outputPerM: 25, - cacheReadPerM: 0.5, - cacheWritePerM: 6.25, + inputPerM: 2, + outputPerM: 10, + cacheReadPerM: 2, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'claude-opus-4-6@default', - displayName: 'Claude Opus 4.6', - maxInputTokens: 1000000, - supportedFileTypes: ['pdf', 'image'], + name: 'grok-2-latest', + displayName: 'Grok 2 Latest', + maxInputTokens: 131072, + supportedFileTypes: [], pricing: { - inputPerM: 5, - outputPerM: 25, - cacheReadPerM: 0.5, - cacheWritePerM: 6.25, + inputPerM: 2, + outputPerM: 10, + cacheReadPerM: 2, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'claude-opus-4@20250514', - displayName: 'Claude Opus 4', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'grok-2-vision', + displayName: 'Grok 2 Vision', + maxInputTokens: 8192, + supportedFileTypes: ['image'], pricing: { - inputPerM: 15, - outputPerM: 75, - cacheReadPerM: 1.5, - cacheWritePerM: 18.75, + inputPerM: 2, + outputPerM: 10, + cacheReadPerM: 2, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'claude-sonnet-4-5@20250929', - displayName: 'Claude Sonnet 4.5', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'grok-2-vision-1212', + displayName: 'Grok 2 Vision (1212)', + maxInputTokens: 8192, + supportedFileTypes: ['image'], pricing: { - inputPerM: 3, - outputPerM: 15, - cacheReadPerM: 0.3, - cacheWritePerM: 3.75, + inputPerM: 2, + outputPerM: 10, + cacheReadPerM: 2, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'claude-sonnet-4-6@default', - displayName: 'Claude Sonnet 4.6', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'grok-2-vision-latest', + displayName: 'Grok 2 Vision Latest', + maxInputTokens: 8192, + supportedFileTypes: ['image'], pricing: { - inputPerM: 3, - outputPerM: 15, - cacheReadPerM: 0.3, - cacheWritePerM: 3.75, + inputPerM: 2, + outputPerM: 10, + cacheReadPerM: 2, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'claude-sonnet-4@20250514', - displayName: 'Claude Sonnet 4', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'grok-3', + displayName: 'Grok 3', + maxInputTokens: 131072, + supportedFileTypes: [], pricing: { inputPerM: 3, outputPerM: 15, - cacheReadPerM: 0.3, - cacheWritePerM: 3.75, + cacheReadPerM: 0.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gemini-2.0-flash', - displayName: 'Gemini 2.0 Flash', - maxInputTokens: 1048576, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'grok-3-fast', + displayName: 'Grok 3 Fast', + maxInputTokens: 131072, + supportedFileTypes: [], pricing: { - inputPerM: 0.15, - outputPerM: 0.6, - cacheReadPerM: 0.025, + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 1.25, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gemini-2.0-flash-lite', - displayName: 'Gemini 2.0 Flash Lite', - maxInputTokens: 1048576, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'grok-3-fast-latest', + displayName: 'Grok 3 Fast Latest', + maxInputTokens: 131072, + supportedFileTypes: [], pricing: { - inputPerM: 0.075, - outputPerM: 0.3, + inputPerM: 5, + outputPerM: 25, + cacheReadPerM: 1.25, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gemini-2.5-flash', - displayName: 'Gemini 2.5 Flash', - maxInputTokens: 1048576, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'grok-3-latest', + displayName: 'Grok 3 Latest', + maxInputTokens: 131072, + supportedFileTypes: [], pricing: { - inputPerM: 0.3, - outputPerM: 2.5, - cacheReadPerM: 0.075, - cacheWritePerM: 0.383, + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gemini-2.5-flash-lite', - displayName: 'Gemini 2.5 Flash Lite', - maxInputTokens: 1048576, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'grok-3-mini', + displayName: 'Grok 3 Mini', + maxInputTokens: 131072, + supportedFileTypes: [], pricing: { - inputPerM: 0.1, - outputPerM: 0.4, - cacheReadPerM: 0.025, + inputPerM: 0.3, + outputPerM: 0.5, + cacheReadPerM: 0.075, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gemini-2.5-flash-lite-preview-06-17', - displayName: 'Gemini 2.5 Flash Lite Preview 06-17', - maxInputTokens: 65536, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'grok-3-mini-fast', + displayName: 'Grok 3 Mini Fast', + maxInputTokens: 131072, + supportedFileTypes: [], pricing: { - inputPerM: 0.1, - outputPerM: 0.4, - cacheReadPerM: 0.025, + inputPerM: 0.6, + outputPerM: 4, + cacheReadPerM: 0.15, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gemini-2.5-flash-lite-preview-09-2025', - displayName: 'Gemini 2.5 Flash Lite Preview 09-25', - maxInputTokens: 1048576, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'grok-3-mini-fast-latest', + displayName: 'Grok 3 Mini Fast Latest', + maxInputTokens: 131072, + supportedFileTypes: [], pricing: { - inputPerM: 0.1, - outputPerM: 0.4, - cacheReadPerM: 0.025, + inputPerM: 0.6, + outputPerM: 4, + cacheReadPerM: 0.15, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gemini-2.5-flash-preview-04-17', - displayName: 'Gemini 2.5 Flash Preview 04-17', - maxInputTokens: 1048576, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'grok-3-mini-latest', + displayName: 'Grok 3 Mini Latest', + maxInputTokens: 131072, + supportedFileTypes: [], pricing: { - inputPerM: 0.15, - outputPerM: 0.6, - cacheReadPerM: 0.0375, + inputPerM: 0.3, + outputPerM: 0.5, + cacheReadPerM: 0.075, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gemini-2.5-flash-preview-05-20', - displayName: 'Gemini 2.5 Flash Preview 05-20', - maxInputTokens: 1048576, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'grok-4', + displayName: 'Grok 4', + maxInputTokens: 256000, + supportedFileTypes: [], pricing: { - inputPerM: 0.15, - outputPerM: 0.6, - cacheReadPerM: 0.0375, + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.75, currency: 'USD', unit: 'per_million_tokens', }, + default: true, }, { - name: 'gemini-2.5-flash-preview-09-2025', - displayName: 'Gemini 2.5 Flash Preview 09-25', - maxInputTokens: 1048576, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'grok-4-1-fast', + displayName: 'Grok 4.1 Fast', + maxInputTokens: 2000000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.3, - outputPerM: 2.5, - cacheReadPerM: 0.075, - cacheWritePerM: 0.383, + inputPerM: 0.2, + outputPerM: 0.5, + cacheReadPerM: 0.05, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gemini-2.5-pro', - displayName: 'Gemini 2.5 Pro', - maxInputTokens: 1048576, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'grok-4-1-fast-non-reasoning', + displayName: 'Grok 4.1 Fast (Non-Reasoning)', + maxInputTokens: 2000000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 1.25, - outputPerM: 10, - cacheReadPerM: 0.31, + inputPerM: 0.2, + outputPerM: 0.5, + cacheReadPerM: 0.05, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gemini-2.5-pro-preview-05-06', - displayName: 'Gemini 2.5 Pro Preview 05-06', - maxInputTokens: 1048576, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'grok-4-fast', + displayName: 'Grok 4 Fast', + maxInputTokens: 2000000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 1.25, - outputPerM: 10, - cacheReadPerM: 0.31, + inputPerM: 0.2, + outputPerM: 0.5, + cacheReadPerM: 0.05, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gemini-2.5-pro-preview-06-05', - displayName: 'Gemini 2.5 Pro Preview 06-05', - maxInputTokens: 1048576, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'grok-4-fast-non-reasoning', + displayName: 'Grok 4 Fast (Non-Reasoning)', + maxInputTokens: 2000000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 1.25, - outputPerM: 10, - cacheReadPerM: 0.31, + inputPerM: 0.2, + outputPerM: 0.5, + cacheReadPerM: 0.05, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gemini-3-flash-preview', - displayName: 'Gemini 3 Flash Preview', - maxInputTokens: 1048576, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'grok-beta', + displayName: 'Grok Beta', + maxInputTokens: 131072, + supportedFileTypes: [], pricing: { - inputPerM: 0.5, - outputPerM: 3, - cacheReadPerM: 0.05, + inputPerM: 5, + outputPerM: 15, + cacheReadPerM: 5, currency: 'USD', unit: 'per_million_tokens', }, - default: true, }, { - name: 'gemini-3-pro-preview', - displayName: 'Gemini 3 Pro Preview', - maxInputTokens: 1048576, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'grok-code-fast-1', + displayName: 'Grok Code Fast 1', + maxInputTokens: 256000, + supportedFileTypes: [], pricing: { - inputPerM: 2, - outputPerM: 12, - cacheReadPerM: 0.2, + inputPerM: 0.2, + outputPerM: 1.5, + cacheReadPerM: 0.02, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'gemini-embedding-001', - displayName: 'Gemini Embedding 001', - maxInputTokens: 2048, - supportedFileTypes: [], + name: 'grok-vision-beta', + displayName: 'Grok Vision Beta', + maxInputTokens: 8192, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.15, - outputPerM: 0, + inputPerM: 5, + outputPerM: 15, + cacheReadPerM: 5, currency: 'USD', unit: 'per_million_tokens', }, }, + ], + xiaomi: [ { - name: 'gemini-flash-latest', - displayName: 'Gemini Flash Latest', - maxInputTokens: 1048576, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'mimo-v2-flash', + displayName: 'MiMo-V2-Flash', + maxInputTokens: 256000, + supportedFileTypes: [], pricing: { - inputPerM: 0.3, - outputPerM: 2.5, - cacheReadPerM: 0.075, - cacheWritePerM: 0.383, + inputPerM: 0.07, + outputPerM: 0.21, currency: 'USD', unit: 'per_million_tokens', }, }, + ], + zai: [ { - name: 'gemini-flash-lite-latest', - displayName: 'Gemini Flash-Lite Latest', - maxInputTokens: 1048576, - supportedFileTypes: ['pdf', 'image', 'audio'], + name: 'glm-4.5', + displayName: 'GLM-4.5', + maxInputTokens: 131072, + supportedFileTypes: [], pricing: { - inputPerM: 0.1, - outputPerM: 0.4, - cacheReadPerM: 0.025, + inputPerM: 0.6, + outputPerM: 2.2, + cacheReadPerM: 0.11, + cacheWritePerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openai/gpt-oss-120b-maas', - displayName: 'GPT OSS 120B', + name: 'glm-4.5-air', + displayName: 'GLM-4.5-Air', maxInputTokens: 131072, supportedFileTypes: [], pricing: { - inputPerM: 0.09, - outputPerM: 0.36, + inputPerM: 0.2, + outputPerM: 1.1, + cacheReadPerM: 0.03, + cacheWritePerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openai/gpt-oss-20b-maas', - displayName: 'GPT OSS 20B', + name: 'glm-4.5-flash', + displayName: 'GLM-4.5-Flash', maxInputTokens: 131072, supportedFileTypes: [], pricing: { - inputPerM: 0.07, - outputPerM: 0.25, + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'zai-org/glm-4.7-maas', - displayName: 'GLM-4.7', - maxInputTokens: 204800, - supportedFileTypes: [], + name: 'glm-4.5v', + displayName: 'GLM-4.5V', + maxInputTokens: 64000, + supportedFileTypes: ['image'], pricing: { inputPerM: 0.6, - outputPerM: 2.2, + outputPerM: 1.8, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'zai-org/glm-5-maas', - displayName: 'GLM-5', + name: 'glm-4.6', + displayName: 'GLM-4.6', maxInputTokens: 204800, supportedFileTypes: [], pricing: { - inputPerM: 1, - outputPerM: 3.2, - cacheReadPerM: 0.1, + inputPerM: 0.6, + outputPerM: 2.2, + cacheReadPerM: 0.11, + cacheWritePerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, - ], - bedrock: [ { - name: 'ai21.jamba-1-5-large-v1:0', - displayName: 'Jamba 1.5 Large', - maxInputTokens: 256000, - supportedFileTypes: [], + name: 'glm-4.6v', + displayName: 'GLM-4.6V', + maxInputTokens: 128000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 2, - outputPerM: 8, + inputPerM: 0.3, + outputPerM: 0.9, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'ai21.jamba-1-5-mini-v1:0', - displayName: 'Jamba 1.5 Mini', - maxInputTokens: 256000, + name: 'glm-4.7', + displayName: 'GLM-4.7', + maxInputTokens: 204800, supportedFileTypes: [], pricing: { - inputPerM: 0.2, - outputPerM: 0.4, + inputPerM: 0.6, + outputPerM: 2.2, + cacheReadPerM: 0.11, + cacheWritePerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'amazon.nova-2-lite-v1:0', - displayName: 'Nova 2 Lite', - maxInputTokens: 128000, - supportedFileTypes: ['image'], + name: 'glm-4.7-flash', + displayName: 'GLM-4.7-Flash', + maxInputTokens: 200000, + supportedFileTypes: [], pricing: { - inputPerM: 0.33, - outputPerM: 2.75, + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'amazon.nova-lite-v1:0', - displayName: 'Nova Lite', - maxInputTokens: 300000, - supportedFileTypes: ['image'], + name: 'glm-5', + displayName: 'GLM-5', + maxInputTokens: 204800, + supportedFileTypes: [], pricing: { - inputPerM: 0.06, - outputPerM: 0.24, - cacheReadPerM: 0.015, + inputPerM: 1, + outputPerM: 3.2, + cacheReadPerM: 0.2, + cacheWritePerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, + ], + 'zai-coding-plan': [ { - name: 'amazon.nova-micro-v1:0', - displayName: 'Nova Micro', - maxInputTokens: 128000, + name: 'glm-4.5', + displayName: 'GLM-4.5', + maxInputTokens: 131072, supportedFileTypes: [], pricing: { - inputPerM: 0.035, - outputPerM: 0.14, - cacheReadPerM: 0.00875, + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'amazon.nova-premier-v1:0', - displayName: 'Nova Premier', - maxInputTokens: 1000000, - supportedFileTypes: ['image'], + name: 'glm-4.5-air', + displayName: 'GLM-4.5-Air', + maxInputTokens: 131072, + supportedFileTypes: [], + pricing: { + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-4.5-flash', + displayName: 'GLM-4.5-Flash', + maxInputTokens: 131072, + supportedFileTypes: [], pricing: { - inputPerM: 2.5, - outputPerM: 12.5, + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'amazon.nova-pro-v1:0', - displayName: 'Nova Pro', - maxInputTokens: 300000, + name: 'glm-4.5v', + displayName: 'GLM-4.5V', + maxInputTokens: 64000, supportedFileTypes: ['image'], pricing: { - inputPerM: 0.8, - outputPerM: 3.2, - cacheReadPerM: 0.2, + inputPerM: 0, + outputPerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'amazon.titan-text-express-v1', - displayName: 'Titan Text G1 - Express', - maxInputTokens: 128000, + name: 'glm-4.6', + displayName: 'GLM-4.6', + maxInputTokens: 204800, supportedFileTypes: [], pricing: { - inputPerM: 0.2, - outputPerM: 0.6, + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'amazon.titan-text-express-v1:0:8k', - displayName: 'Titan Text G1 - Express', + name: 'glm-4.6v', + displayName: 'GLM-4.6V', maxInputTokens: 128000, - supportedFileTypes: [], + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.2, - outputPerM: 0.6, + inputPerM: 0, + outputPerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'anthropic.claude-3-5-haiku-20241022-v1:0', - displayName: 'Claude Haiku 3.5', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'glm-4.7', + displayName: 'GLM-4.7', + maxInputTokens: 204800, + supportedFileTypes: [], pricing: { - inputPerM: 0.8, - outputPerM: 4, - cacheReadPerM: 0.08, - cacheWritePerM: 1, + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'anthropic.claude-3-5-sonnet-20240620-v1:0', - displayName: 'Claude Sonnet 3.5', + name: 'glm-4.7-flash', + displayName: 'GLM-4.7-Flash', maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + supportedFileTypes: [], pricing: { - inputPerM: 3, - outputPerM: 15, - cacheReadPerM: 0.3, - cacheWritePerM: 3.75, + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'anthropic.claude-3-5-sonnet-20241022-v2:0', - displayName: 'Claude Sonnet 3.5 v2', + name: 'glm-4.7-flashx', + displayName: 'GLM-4.7-FlashX', maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + supportedFileTypes: [], pricing: { - inputPerM: 3, - outputPerM: 15, - cacheReadPerM: 0.3, - cacheWritePerM: 3.75, + inputPerM: 0.07, + outputPerM: 0.4, + cacheReadPerM: 0.01, + cacheWritePerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'anthropic.claude-3-7-sonnet-20250219-v1:0', - displayName: 'Claude Sonnet 3.7', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'glm-5', + displayName: 'GLM-5', + maxInputTokens: 204800, + supportedFileTypes: [], pricing: { - inputPerM: 3, - outputPerM: 15, - cacheReadPerM: 0.3, - cacheWritePerM: 3.75, + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, + ], + zenmux: [ { - name: 'anthropic.claude-3-haiku-20240307-v1:0', - displayName: 'Claude Haiku 3', + name: 'anthropic/claude-3.5-haiku', + displayName: 'Claude 3.5 Haiku', maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.25, - outputPerM: 1.25, + inputPerM: 0.8, + outputPerM: 4, + cacheReadPerM: 0.08, + cacheWritePerM: 1, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'anthropic.claude-3-opus-20240229-v1:0', - displayName: 'Claude Opus 3', + name: 'anthropic/claude-3.5-sonnet', + displayName: 'Claude 3.5 Sonnet (Retiring Soon)', maxInputTokens: 200000, supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 15, - outputPerM: 75, + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'anthropic.claude-3-sonnet-20240229-v1:0', - displayName: 'Claude Sonnet 3', + name: 'anthropic/claude-3.7-sonnet', + displayName: 'Claude 3.7 Sonnet', maxInputTokens: 200000, supportedFileTypes: ['pdf', 'image'], pricing: { inputPerM: 3, outputPerM: 15, + cacheReadPerM: 0.3, + cacheWritePerM: 3.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'anthropic.claude-haiku-4-5-20251001-v1:0', + name: 'anthropic/claude-haiku-4.5', displayName: 'Claude Haiku 4.5', maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + supportedFileTypes: ['image'], pricing: { inputPerM: 1, outputPerM: 5, @@ -5714,20 +35640,8 @@ export const MODELS_BY_PROVIDER = { }, }, { - name: 'anthropic.claude-instant-v1', - displayName: 'Claude Instant', - maxInputTokens: 100000, - supportedFileTypes: [], - pricing: { - inputPerM: 0.8, - outputPerM: 2.4, - currency: 'USD', - unit: 'per_million_tokens', - }, - }, - { - name: 'anthropic.claude-opus-4-1-20250805-v1:0', - displayName: 'Claude Opus 4.1', + name: 'anthropic/claude-opus-4', + displayName: 'Claude Opus 4', maxInputTokens: 200000, supportedFileTypes: ['pdf', 'image'], pricing: { @@ -5740,8 +35654,8 @@ export const MODELS_BY_PROVIDER = { }, }, { - name: 'anthropic.claude-opus-4-20250514-v1:0', - displayName: 'Claude Opus 4', + name: 'anthropic/claude-opus-4.1', + displayName: 'Claude Opus 4.1', maxInputTokens: 200000, supportedFileTypes: ['pdf', 'image'], pricing: { @@ -5754,7 +35668,7 @@ export const MODELS_BY_PROVIDER = { }, }, { - name: 'anthropic.claude-opus-4-5-20251101-v1:0', + name: 'anthropic/claude-opus-4.5', displayName: 'Claude Opus 4.5', maxInputTokens: 200000, supportedFileTypes: ['pdf', 'image'], @@ -5768,10 +35682,10 @@ export const MODELS_BY_PROVIDER = { }, }, { - name: 'anthropic.claude-opus-4-6-v1', + name: 'anthropic/claude-opus-4.6', displayName: 'Claude Opus 4.6', maxInputTokens: 1000000, - supportedFileTypes: ['pdf', 'image'], + supportedFileTypes: ['image'], pricing: { inputPerM: 5, outputPerM: 25, @@ -5782,9 +35696,9 @@ export const MODELS_BY_PROVIDER = { }, }, { - name: 'anthropic.claude-sonnet-4-20250514-v1:0', + name: 'anthropic/claude-sonnet-4', displayName: 'Claude Sonnet 4', - maxInputTokens: 200000, + maxInputTokens: 1000000, supportedFileTypes: ['pdf', 'image'], pricing: { inputPerM: 3, @@ -5796,9 +35710,9 @@ export const MODELS_BY_PROVIDER = { }, }, { - name: 'anthropic.claude-sonnet-4-5-20250929-v1:0', + name: 'anthropic/claude-sonnet-4.5', displayName: 'Claude Sonnet 4.5', - maxInputTokens: 200000, + maxInputTokens: 1000000, supportedFileTypes: ['pdf', 'image'], pricing: { inputPerM: 3, @@ -5808,13 +35722,12 @@ export const MODELS_BY_PROVIDER = { currency: 'USD', unit: 'per_million_tokens', }, - default: true, }, { - name: 'anthropic.claude-sonnet-4-6', + name: 'anthropic/claude-sonnet-4.6', displayName: 'Claude Sonnet 4.6', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + maxInputTokens: 1000000, + supportedFileTypes: ['image'], pricing: { inputPerM: 3, outputPerM: 15, @@ -5825,887 +35738,988 @@ export const MODELS_BY_PROVIDER = { }, }, { - name: 'anthropic.claude-v2', - displayName: 'Claude 2', - maxInputTokens: 100000, + name: 'baidu/ernie-5.0-thinking-preview', + displayName: 'ERNIE 5.0', + maxInputTokens: 128000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.84, + outputPerM: 3.37, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-chat', + displayName: 'DeepSeek-V3.2 (Non-thinking Mode)', + maxInputTokens: 128000, supportedFileTypes: [], pricing: { - inputPerM: 8, - outputPerM: 24, + inputPerM: 0.28, + outputPerM: 0.42, + cacheReadPerM: 0.03, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'anthropic.claude-v2:1', - displayName: 'Claude 2.1', - maxInputTokens: 200000, + name: 'deepseek/deepseek-v3.2', + displayName: 'DeepSeek V3.2', + maxInputTokens: 128000, supportedFileTypes: [], pricing: { - inputPerM: 8, - outputPerM: 24, + inputPerM: 0.28, + outputPerM: 0.43, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'deepseek/deepseek-v3.2-exp', + displayName: 'DeepSeek-V3.2-Exp', + maxInputTokens: 163000, + supportedFileTypes: [], + pricing: { + inputPerM: 0.22, + outputPerM: 0.33, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.5-flash', + displayName: 'Gemini 2.5 Flash', + maxInputTokens: 1048000, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.3, + outputPerM: 2.5, + cacheReadPerM: 0.07, + cacheWritePerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.5-flash-lite', + displayName: 'Gemini 2.5 Flash Lite', + maxInputTokens: 1048000, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.1, + outputPerM: 0.4, + cacheReadPerM: 0.03, + cacheWritePerM: 1, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-2.5-pro', + displayName: 'Gemini 2.5 Pro', + maxInputTokens: 1048000, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.31, + cacheWritePerM: 4.5, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'google/gemini-3-flash-preview', + displayName: 'Gemini 3 Flash Preview', + maxInputTokens: 1048000, + supportedFileTypes: ['pdf', 'image', 'audio'], + pricing: { + inputPerM: 0.5, + outputPerM: 3, + cacheReadPerM: 0.05, + cacheWritePerM: 1, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'cohere.command-light-text-v14', - displayName: 'Command Light', - maxInputTokens: 4096, - supportedFileTypes: [], + name: 'google/gemini-3-pro-preview', + displayName: 'Gemini 3 Pro Preview', + maxInputTokens: 1048000, + supportedFileTypes: ['pdf', 'image', 'audio'], pricing: { - inputPerM: 0.3, - outputPerM: 0.6, + inputPerM: 2, + outputPerM: 12, + cacheReadPerM: 0.2, + cacheWritePerM: 4.5, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'cohere.command-r-plus-v1:0', - displayName: 'Command R+', + name: 'inclusionai/ling-1t', + displayName: 'Ling-1T', maxInputTokens: 128000, supportedFileTypes: [], pricing: { - inputPerM: 3, - outputPerM: 15, + inputPerM: 0.56, + outputPerM: 2.24, + cacheReadPerM: 0.11, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'cohere.command-r-v1:0', - displayName: 'Command R', + name: 'inclusionai/ring-1t', + displayName: 'Ring-1T', maxInputTokens: 128000, supportedFileTypes: [], pricing: { - inputPerM: 0.5, - outputPerM: 1.5, + inputPerM: 0.56, + outputPerM: 2.24, + cacheReadPerM: 0.11, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'cohere.command-text-v14', - displayName: 'Command', - maxInputTokens: 4096, + name: 'kuaishou/kat-coder-pro-v1', + displayName: 'KAT-Coder-Pro-V1', + maxInputTokens: 256000, supportedFileTypes: [], pricing: { - inputPerM: 1.5, - outputPerM: 2, + inputPerM: 0.3, + outputPerM: 1.2, + cacheReadPerM: 0.06, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'deepseek.r1-v1:0', - displayName: 'DeepSeek-R1', - maxInputTokens: 128000, + name: 'kuaishou/kat-coder-pro-v1-free', + displayName: 'KAT-Coder-Pro-V1 Free', + maxInputTokens: 256000, supportedFileTypes: [], pricing: { - inputPerM: 1.35, - outputPerM: 5.4, + inputPerM: 0, + outputPerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'deepseek.v3-v1:0', - displayName: 'DeepSeek-V3.1', - maxInputTokens: 163840, + name: 'minimax/minimax-m2', + displayName: 'MiniMax M2', + maxInputTokens: 204000, supportedFileTypes: [], pricing: { - inputPerM: 0.58, - outputPerM: 1.68, + inputPerM: 0.3, + outputPerM: 1.2, + cacheReadPerM: 0.03, + cacheWritePerM: 0.38, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'deepseek.v3.2-v1:0', - displayName: 'DeepSeek-V3.2', - maxInputTokens: 163840, + name: 'minimax/minimax-m2.1', + displayName: 'MiniMax M2.1', + maxInputTokens: 204000, supportedFileTypes: [], pricing: { - inputPerM: 0.62, - outputPerM: 1.85, - currency: 'USD', - unit: 'per_million_tokens', - }, - }, - { - name: 'eu.anthropic.claude-haiku-4-5-20251001-v1:0', - displayName: 'Claude Haiku 4.5 (EU)', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], - pricing: { - inputPerM: 1, - outputPerM: 5, - cacheReadPerM: 0.1, - cacheWritePerM: 1.25, + inputPerM: 0.3, + outputPerM: 1.2, + cacheReadPerM: 0.03, + cacheWritePerM: 0.38, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'eu.anthropic.claude-opus-4-5-20251101-v1:0', - displayName: 'Claude Opus 4.5 (EU)', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'minimax/minimax-m2.5', + displayName: 'MiniMax M2.5', + maxInputTokens: 204800, + supportedFileTypes: [], pricing: { - inputPerM: 5, - outputPerM: 25, - cacheReadPerM: 0.5, - cacheWritePerM: 6.25, + inputPerM: 0.3, + outputPerM: 1.2, + cacheReadPerM: 0.03, + cacheWritePerM: 0.375, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'eu.anthropic.claude-opus-4-6-v1', - displayName: 'Claude Opus 4.6 (EU)', - maxInputTokens: 1000000, - supportedFileTypes: ['pdf', 'image'], + name: 'minimax/minimax-m2.5-lightning', + displayName: 'MiniMax: MiniMax M2.5 highspeed', + maxInputTokens: 204800, + supportedFileTypes: [], pricing: { - inputPerM: 5, - outputPerM: 25, - cacheReadPerM: 0.5, - cacheWritePerM: 6.25, + inputPerM: 0.6, + outputPerM: 4.8, + cacheReadPerM: 0.06, + cacheWritePerM: 0.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'eu.anthropic.claude-sonnet-4-20250514-v1:0', - displayName: 'Claude Sonnet 4 (EU)', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'moonshotai/kimi-k2-0905', + displayName: 'Kimi K2 0905', + maxInputTokens: 262000, + supportedFileTypes: [], pricing: { - inputPerM: 3, - outputPerM: 15, - cacheReadPerM: 0.3, - cacheWritePerM: 3.75, + inputPerM: 0.6, + outputPerM: 2.5, + cacheReadPerM: 0.15, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'eu.anthropic.claude-sonnet-4-5-20250929-v1:0', - displayName: 'Claude Sonnet 4.5 (EU)', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'moonshotai/kimi-k2-thinking', + displayName: 'Kimi K2 Thinking', + maxInputTokens: 262000, + supportedFileTypes: [], pricing: { - inputPerM: 3, - outputPerM: 15, - cacheReadPerM: 0.3, - cacheWritePerM: 3.75, + inputPerM: 0.6, + outputPerM: 2.5, + cacheReadPerM: 0.15, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'eu.anthropic.claude-sonnet-4-6', - displayName: 'Claude Sonnet 4.6 (EU)', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'moonshotai/kimi-k2-thinking-turbo', + displayName: 'Kimi K2 Thinking Turbo', + maxInputTokens: 262000, + supportedFileTypes: [], pricing: { - inputPerM: 3, - outputPerM: 15, - cacheReadPerM: 0.3, - cacheWritePerM: 3.75, + inputPerM: 1.15, + outputPerM: 8, + cacheReadPerM: 0.15, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'global.anthropic.claude-haiku-4-5-20251001-v1:0', - displayName: 'Claude Haiku 4.5 (Global)', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'moonshotai/kimi-k2.5', + displayName: 'Kimi K2.5', + maxInputTokens: 262000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 1, - outputPerM: 5, + inputPerM: 0.58, + outputPerM: 3.02, cacheReadPerM: 0.1, - cacheWritePerM: 1.25, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'global.anthropic.claude-opus-4-5-20251101-v1:0', - displayName: 'Claude Opus 4.5 (Global)', - maxInputTokens: 200000, + name: 'openai/gpt-5', + displayName: 'GPT-5', + maxInputTokens: 400000, supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 5, - outputPerM: 25, - cacheReadPerM: 0.5, - cacheWritePerM: 6.25, + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.12, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'global.anthropic.claude-opus-4-6-v1', - displayName: 'Claude Opus 4.6 (Global)', - maxInputTokens: 1000000, - supportedFileTypes: ['pdf', 'image'], + name: 'openai/gpt-5-codex', + displayName: 'GPT-5 Codex', + maxInputTokens: 400000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 5, - outputPerM: 25, - cacheReadPerM: 0.5, - cacheWritePerM: 6.25, + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.12, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'global.anthropic.claude-sonnet-4-20250514-v1:0', - displayName: 'Claude Sonnet 4 (Global)', - maxInputTokens: 200000, + name: 'openai/gpt-5.1', + displayName: 'GPT-5.1', + maxInputTokens: 400000, supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 3, - outputPerM: 15, - cacheReadPerM: 0.3, - cacheWritePerM: 3.75, + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.12, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'global.anthropic.claude-sonnet-4-5-20250929-v1:0', - displayName: 'Claude Sonnet 4.5 (Global)', - maxInputTokens: 200000, + name: 'openai/gpt-5.1-chat', + displayName: 'GPT-5.1 Chat', + maxInputTokens: 128000, supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 3, - outputPerM: 15, - cacheReadPerM: 0.3, - cacheWritePerM: 3.75, + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.12, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'global.anthropic.claude-sonnet-4-6', - displayName: 'Claude Sonnet 4.6 (Global)', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'openai/gpt-5.1-codex', + displayName: 'GPT-5.1-Codex', + maxInputTokens: 400000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 3, - outputPerM: 15, - cacheReadPerM: 0.3, - cacheWritePerM: 3.75, + inputPerM: 1.25, + outputPerM: 10, + cacheReadPerM: 0.12, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'google.gemma-3-12b-it', - displayName: 'Google Gemma 3 12B', - maxInputTokens: 131072, + name: 'openai/gpt-5.1-codex-mini', + displayName: 'GPT-5.1-Codex-Mini', + maxInputTokens: 400000, supportedFileTypes: ['image'], pricing: { - inputPerM: 0.049999999999999996, - outputPerM: 0.09999999999999999, + inputPerM: 0.25, + outputPerM: 2, + cacheReadPerM: 0.03, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'google.gemma-3-27b-it', - displayName: 'Google Gemma 3 27B Instruct', - maxInputTokens: 202752, - supportedFileTypes: ['image'], + name: 'openai/gpt-5.2', + displayName: 'GPT-5.2', + maxInputTokens: 400000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0.12, - outputPerM: 0.2, + inputPerM: 1.75, + outputPerM: 14, + cacheReadPerM: 0.17, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'google.gemma-3-4b-it', - displayName: 'Gemma 3 4B IT', - maxInputTokens: 128000, - supportedFileTypes: ['image'], + name: 'openai/gpt-5.2-codex', + displayName: 'GPT-5.2-Codex', + maxInputTokens: 400000, + supportedFileTypes: ['pdf', 'image'], pricing: { - inputPerM: 0.04, - outputPerM: 0.08, + inputPerM: 1.75, + outputPerM: 14, + cacheReadPerM: 0.17, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'meta.llama3-1-70b-instruct-v1:0', - displayName: 'Llama 3.1 70B Instruct', - maxInputTokens: 128000, + name: 'qwen/qwen3-coder-plus', + displayName: 'Qwen3-Coder-Plus', + maxInputTokens: 1000000, supportedFileTypes: [], pricing: { - inputPerM: 0.72, - outputPerM: 0.72, + inputPerM: 1, + outputPerM: 5, + cacheReadPerM: 0.1, + cacheWritePerM: 1.25, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'meta.llama3-1-8b-instruct-v1:0', - displayName: 'Llama 3.1 8B Instruct', - maxInputTokens: 128000, + name: 'qwen/qwen3-max', + displayName: 'Qwen3-Max-Thinking', + maxInputTokens: 256000, supportedFileTypes: [], pricing: { - inputPerM: 0.22, - outputPerM: 0.22, + inputPerM: 1.2, + outputPerM: 6, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'meta.llama3-2-11b-instruct-v1:0', - displayName: 'Llama 3.2 11B Instruct', - maxInputTokens: 128000, + name: 'stepfun/step-3', + displayName: 'Step-3', + maxInputTokens: 65536, supportedFileTypes: ['image'], pricing: { - inputPerM: 0.16, - outputPerM: 0.16, + inputPerM: 0.21, + outputPerM: 0.57, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'meta.llama3-2-1b-instruct-v1:0', - displayName: 'Llama 3.2 1B Instruct', - maxInputTokens: 131000, + name: 'stepfun/step-3.5-flash', + displayName: 'Step 3.5 Flash', + maxInputTokens: 256000, supportedFileTypes: [], pricing: { inputPerM: 0.1, - outputPerM: 0.1, + outputPerM: 0.3, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'meta.llama3-2-3b-instruct-v1:0', - displayName: 'Llama 3.2 3B Instruct', - maxInputTokens: 131000, + name: 'stepfun/step-3.5-flash-free', + displayName: 'Step 3.5 Flash (Free)', + maxInputTokens: 256000, supportedFileTypes: [], pricing: { - inputPerM: 0.15, - outputPerM: 0.15, + inputPerM: 0, + outputPerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'meta.llama3-2-90b-instruct-v1:0', - displayName: 'Llama 3.2 90B Instruct', - maxInputTokens: 128000, + name: 'volcengine/doubao-seed-1.8', + displayName: 'Doubao-Seed-1.8', + maxInputTokens: 256000, supportedFileTypes: ['image'], pricing: { - inputPerM: 0.72, - outputPerM: 0.72, - currency: 'USD', - unit: 'per_million_tokens', - }, - }, - { - name: 'meta.llama3-3-70b-instruct-v1:0', - displayName: 'Llama 3.3 70B Instruct', - maxInputTokens: 128000, - supportedFileTypes: [], - pricing: { - inputPerM: 0.72, - outputPerM: 0.72, + inputPerM: 0.11, + outputPerM: 0.28, + cacheReadPerM: 0.02, + cacheWritePerM: 0.0024, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'meta.llama3-70b-instruct-v1:0', - displayName: 'Llama 3 70B Instruct', - maxInputTokens: 8192, - supportedFileTypes: [], + name: 'volcengine/doubao-seed-2.0-lite', + displayName: 'Doubao-Seed-2.0-lite', + maxInputTokens: 256000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 2.65, - outputPerM: 3.5, + inputPerM: 0.09, + outputPerM: 0.51, + cacheReadPerM: 0.02, + cacheWritePerM: 0.0024, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'meta.llama3-8b-instruct-v1:0', - displayName: 'Llama 3 8B Instruct', - maxInputTokens: 8192, - supportedFileTypes: [], + name: 'volcengine/doubao-seed-2.0-mini', + displayName: 'Doubao-Seed-2.0-mini', + maxInputTokens: 256000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.3, - outputPerM: 0.6, + inputPerM: 0.03, + outputPerM: 0.28, + cacheReadPerM: 0.01, + cacheWritePerM: 0.0024, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'meta.llama4-maverick-17b-instruct-v1:0', - displayName: 'Llama 4 Maverick 17B Instruct', - maxInputTokens: 1000000, + name: 'volcengine/doubao-seed-2.0-pro', + displayName: 'Doubao-Seed-2.0-pro', + maxInputTokens: 256000, supportedFileTypes: ['image'], pricing: { - inputPerM: 0.24, - outputPerM: 0.97, + inputPerM: 0.45, + outputPerM: 2.24, + cacheReadPerM: 0.09, + cacheWritePerM: 0.0024, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'meta.llama4-scout-17b-instruct-v1:0', - displayName: 'Llama 4 Scout 17B Instruct', - maxInputTokens: 3500000, + name: 'volcengine/doubao-seed-code', + displayName: 'Doubao-Seed-Code', + maxInputTokens: 256000, supportedFileTypes: ['image'], pricing: { inputPerM: 0.17, - outputPerM: 0.66, + outputPerM: 1.12, + cacheReadPerM: 0.03, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'minimax.minimax-m2', - displayName: 'MiniMax M2', - maxInputTokens: 204608, - supportedFileTypes: [], + name: 'x-ai/grok-4', + displayName: 'Grok 4', + maxInputTokens: 256000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.3, - outputPerM: 1.2, + inputPerM: 3, + outputPerM: 15, + cacheReadPerM: 0.75, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'minimax.minimax-m2.1', - displayName: 'MiniMax M2.1', - maxInputTokens: 204800, - supportedFileTypes: [], + name: 'x-ai/grok-4-fast', + displayName: 'Grok 4 Fast', + maxInputTokens: 2000000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.3, - outputPerM: 1.2, + inputPerM: 0.2, + outputPerM: 0.5, + cacheReadPerM: 0.05, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'mistral.ministral-3-14b-instruct', - displayName: 'Ministral 14B 3.0', - maxInputTokens: 128000, - supportedFileTypes: [], + name: 'x-ai/grok-4.1-fast', + displayName: 'Grok 4.1 Fast', + maxInputTokens: 2000000, + supportedFileTypes: ['image'], pricing: { inputPerM: 0.2, - outputPerM: 0.2, + outputPerM: 0.5, + cacheReadPerM: 0.05, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'mistral.ministral-3-8b-instruct', - displayName: 'Ministral 3 8B', - maxInputTokens: 128000, - supportedFileTypes: [], + name: 'x-ai/grok-4.1-fast-non-reasoning', + displayName: 'Grok 4.1 Fast Non Reasoning', + maxInputTokens: 2000000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.15, - outputPerM: 0.15, + inputPerM: 0.2, + outputPerM: 0.5, + cacheReadPerM: 0.05, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'mistral.mistral-7b-instruct-v0:2', - displayName: 'Mistral-7B-Instruct-v0.3', - maxInputTokens: 127000, + name: 'x-ai/grok-code-fast-1', + displayName: 'Grok Code Fast 1', + maxInputTokens: 256000, supportedFileTypes: [], pricing: { - inputPerM: 0.11, - outputPerM: 0.11, + inputPerM: 0.2, + outputPerM: 1.5, + cacheReadPerM: 0.02, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'mistral.mistral-large-2402-v1:0', - displayName: 'Mistral Large (24.02)', - maxInputTokens: 128000, + name: 'xiaomi/mimo-v2-flash', + displayName: 'MiMo-V2-Flash', + maxInputTokens: 262000, supportedFileTypes: [], pricing: { - inputPerM: 0.5, - outputPerM: 1.5, + inputPerM: 0.1, + outputPerM: 0.3, + cacheReadPerM: 0.01, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'mistral.mixtral-8x7b-instruct-v0:1', - displayName: 'Mixtral-8x7B-Instruct-v0.1', - maxInputTokens: 32000, + name: 'xiaomi/mimo-v2-flash-free', + displayName: 'MiMo-V2-Flash Free', + maxInputTokens: 262000, supportedFileTypes: [], pricing: { - inputPerM: 0.7, - outputPerM: 0.7, + inputPerM: 0, + outputPerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'mistral.voxtral-mini-3b-2507', - displayName: 'Voxtral Mini 3B 2507', + name: 'z-ai/glm-4.5', + displayName: 'GLM 4.5', maxInputTokens: 128000, - supportedFileTypes: ['audio'], + supportedFileTypes: [], pricing: { - inputPerM: 0.04, - outputPerM: 0.04, + inputPerM: 0.35, + outputPerM: 1.54, + cacheReadPerM: 0.07, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'mistral.voxtral-small-24b-2507', - displayName: 'Voxtral Small 24B 2507', - maxInputTokens: 32000, - supportedFileTypes: ['audio'], + name: 'z-ai/glm-4.5-air', + displayName: 'GLM 4.5 Air', + maxInputTokens: 128000, + supportedFileTypes: [], pricing: { - inputPerM: 0.15, - outputPerM: 0.35, + inputPerM: 0.11, + outputPerM: 0.56, + cacheReadPerM: 0.02, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'moonshot.kimi-k2-thinking', - displayName: 'Kimi K2 Thinking', - maxInputTokens: 256000, + name: 'z-ai/glm-4.6', + displayName: 'GLM 4.6', + maxInputTokens: 200000, supportedFileTypes: [], pricing: { - inputPerM: 0.6, - outputPerM: 2.5, + inputPerM: 0.35, + outputPerM: 1.54, + cacheReadPerM: 0.07, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'moonshotai.kimi-k2.5', - displayName: 'Kimi K2.5', - maxInputTokens: 256000, + name: 'z-ai/glm-4.6v', + displayName: 'GLM 4.6V', + maxInputTokens: 200000, supportedFileTypes: ['image'], pricing: { - inputPerM: 0.6, - outputPerM: 3, + inputPerM: 0.14, + outputPerM: 0.42, + cacheReadPerM: 0.03, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'nvidia.nemotron-nano-12b-v2', - displayName: 'NVIDIA Nemotron Nano 12B v2 VL BF16', - maxInputTokens: 128000, + name: 'z-ai/glm-4.6v-flash', + displayName: 'GLM 4.6V FlashX', + maxInputTokens: 200000, supportedFileTypes: ['image'], pricing: { - inputPerM: 0.2, - outputPerM: 0.6, - currency: 'USD', - unit: 'per_million_tokens', - }, - }, - { - name: 'nvidia.nemotron-nano-9b-v2', - displayName: 'NVIDIA Nemotron Nano 9B v2', - maxInputTokens: 128000, - supportedFileTypes: [], - pricing: { - inputPerM: 0.06, - outputPerM: 0.23, + inputPerM: 0.02, + outputPerM: 0.21, + cacheReadPerM: 0.0043, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openai.gpt-oss-120b-1:0', - displayName: 'gpt-oss-120b', - maxInputTokens: 128000, - supportedFileTypes: [], + name: 'z-ai/glm-4.6v-flash-free', + displayName: 'GLM 4.6V Flash (Free)', + maxInputTokens: 200000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.15, - outputPerM: 0.6, + inputPerM: 0, + outputPerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openai.gpt-oss-20b-1:0', - displayName: 'gpt-oss-20b', - maxInputTokens: 128000, + name: 'z-ai/glm-4.7', + displayName: 'GLM 4.7', + maxInputTokens: 200000, supportedFileTypes: [], pricing: { - inputPerM: 0.07, - outputPerM: 0.3, + inputPerM: 0.28, + outputPerM: 1.14, + cacheReadPerM: 0.06, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openai.gpt-oss-safeguard-120b', - displayName: 'GPT OSS Safeguard 120B', - maxInputTokens: 128000, + name: 'z-ai/glm-4.7-flash-free', + displayName: 'GLM 4.7 Flash (Free)', + maxInputTokens: 200000, supportedFileTypes: [], pricing: { - inputPerM: 0.15, - outputPerM: 0.6, + inputPerM: 0, + outputPerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'openai.gpt-oss-safeguard-20b', - displayName: 'GPT OSS Safeguard 20B', - maxInputTokens: 128000, + name: 'z-ai/glm-4.7-flashx', + displayName: 'GLM 4.7 FlashX', + maxInputTokens: 200000, supportedFileTypes: [], pricing: { inputPerM: 0.07, - outputPerM: 0.2, + outputPerM: 0.42, + cacheReadPerM: 0.01, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'qwen.qwen3-235b-a22b-2507-v1:0', - displayName: 'Qwen3 235B A22B 2507', - maxInputTokens: 262144, + name: 'z-ai/glm-5', + displayName: 'GLM 5', + maxInputTokens: 200000, supportedFileTypes: [], pricing: { - inputPerM: 0.22, - outputPerM: 0.88, + inputPerM: 0.58, + outputPerM: 2.6, + cacheReadPerM: 0.14, currency: 'USD', unit: 'per_million_tokens', }, }, + ], + zhipuai: [ { - name: 'qwen.qwen3-32b-v1:0', - displayName: 'Qwen3 32B (dense)', - maxInputTokens: 16384, + name: 'glm-4.5', + displayName: 'GLM-4.5', + maxInputTokens: 131072, supportedFileTypes: [], pricing: { - inputPerM: 0.15, - outputPerM: 0.6, + inputPerM: 0.6, + outputPerM: 2.2, + cacheReadPerM: 0.11, + cacheWritePerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'qwen.qwen3-coder-30b-a3b-v1:0', - displayName: 'Qwen3 Coder 30B A3B Instruct', - maxInputTokens: 262144, + name: 'glm-4.5-air', + displayName: 'GLM-4.5-Air', + maxInputTokens: 131072, supportedFileTypes: [], pricing: { - inputPerM: 0.15, - outputPerM: 0.6, + inputPerM: 0.2, + outputPerM: 1.1, + cacheReadPerM: 0.03, + cacheWritePerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'qwen.qwen3-coder-480b-a35b-v1:0', - displayName: 'Qwen3 Coder 480B A35B Instruct', + name: 'glm-4.5-flash', + displayName: 'GLM-4.5-Flash', maxInputTokens: 131072, supportedFileTypes: [], pricing: { - inputPerM: 0.22, + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, + currency: 'USD', + unit: 'per_million_tokens', + }, + }, + { + name: 'glm-4.5v', + displayName: 'GLM-4.5V', + maxInputTokens: 64000, + supportedFileTypes: ['image'], + pricing: { + inputPerM: 0.6, outputPerM: 1.8, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'qwen.qwen3-next-80b-a3b', - displayName: 'Qwen/Qwen3-Next-80B-A3B-Instruct', - maxInputTokens: 262000, + name: 'glm-4.6', + displayName: 'GLM-4.6', + maxInputTokens: 204800, supportedFileTypes: [], pricing: { - inputPerM: 0.14, - outputPerM: 1.4, + inputPerM: 0.6, + outputPerM: 2.2, + cacheReadPerM: 0.11, + cacheWritePerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'qwen.qwen3-vl-235b-a22b', - displayName: 'Qwen/Qwen3-VL-235B-A22B-Instruct', - maxInputTokens: 262000, + name: 'glm-4.6v', + displayName: 'GLM-4.6V', + maxInputTokens: 128000, supportedFileTypes: ['image'], pricing: { inputPerM: 0.3, - outputPerM: 1.5, + outputPerM: 0.9, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'us.anthropic.claude-haiku-4-5-20251001-v1:0', - displayName: 'Claude Haiku 4.5 (US)', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'glm-4.7', + displayName: 'GLM-4.7', + maxInputTokens: 204800, + supportedFileTypes: [], pricing: { - inputPerM: 1, - outputPerM: 5, - cacheReadPerM: 0.1, - cacheWritePerM: 1.25, + inputPerM: 0.6, + outputPerM: 2.2, + cacheReadPerM: 0.11, + cacheWritePerM: 0, currency: 'USD', unit: 'per_million_tokens', }, + default: true, }, { - name: 'us.anthropic.claude-opus-4-1-20250805-v1:0', - displayName: 'Claude Opus 4.1 (US)', + name: 'glm-4.7-flash', + displayName: 'GLM-4.7-Flash', maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + supportedFileTypes: [], pricing: { - inputPerM: 15, - outputPerM: 75, - cacheReadPerM: 1.5, - cacheWritePerM: 18.75, + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'us.anthropic.claude-opus-4-20250514-v1:0', - displayName: 'Claude Opus 4 (US)', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'glm-5', + displayName: 'GLM-5', + maxInputTokens: 204800, + supportedFileTypes: [], pricing: { - inputPerM: 15, - outputPerM: 75, - cacheReadPerM: 1.5, - cacheWritePerM: 18.75, + inputPerM: 1, + outputPerM: 3.2, + cacheReadPerM: 0.2, + cacheWritePerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, + ], + 'zhipuai-coding-plan': [ { - name: 'us.anthropic.claude-opus-4-5-20251101-v1:0', - displayName: 'Claude Opus 4.5 (US)', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'glm-4.5', + displayName: 'GLM-4.5', + maxInputTokens: 131072, + supportedFileTypes: [], pricing: { - inputPerM: 5, - outputPerM: 25, - cacheReadPerM: 0.5, - cacheWritePerM: 6.25, + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'us.anthropic.claude-opus-4-6-v1', - displayName: 'Claude Opus 4.6 (US)', - maxInputTokens: 1000000, - supportedFileTypes: ['pdf', 'image'], + name: 'glm-4.5-air', + displayName: 'GLM-4.5-Air', + maxInputTokens: 131072, + supportedFileTypes: [], pricing: { - inputPerM: 5, - outputPerM: 25, - cacheReadPerM: 0.5, - cacheWritePerM: 6.25, + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'us.anthropic.claude-sonnet-4-20250514-v1:0', - displayName: 'Claude Sonnet 4 (US)', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'glm-4.5-flash', + displayName: 'GLM-4.5-Flash', + maxInputTokens: 131072, + supportedFileTypes: [], pricing: { - inputPerM: 3, - outputPerM: 15, - cacheReadPerM: 0.3, - cacheWritePerM: 3.75, + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'us.anthropic.claude-sonnet-4-5-20250929-v1:0', - displayName: 'Claude Sonnet 4.5 (US)', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'glm-4.5v', + displayName: 'GLM-4.5V', + maxInputTokens: 64000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 3, - outputPerM: 15, - cacheReadPerM: 0.3, - cacheWritePerM: 3.75, + inputPerM: 0, + outputPerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'us.anthropic.claude-sonnet-4-6', - displayName: 'Claude Sonnet 4.6 (US)', - maxInputTokens: 200000, - supportedFileTypes: ['pdf', 'image'], + name: 'glm-4.6', + displayName: 'GLM-4.6', + maxInputTokens: 204800, + supportedFileTypes: [], pricing: { - inputPerM: 3, - outputPerM: 15, - cacheReadPerM: 0.3, - cacheWritePerM: 3.75, + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'writer.palmyra-x4-v1:0', - displayName: 'Palmyra X4', - maxInputTokens: 122880, - supportedFileTypes: [], + name: 'glm-4.6v', + displayName: 'GLM-4.6V', + maxInputTokens: 128000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 2.5, - outputPerM: 10, + inputPerM: 0, + outputPerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'writer.palmyra-x5-v1:0', - displayName: 'Palmyra X5', - maxInputTokens: 1040000, - supportedFileTypes: [], + name: 'glm-4.6v-flash', + displayName: 'GLM-4.6V-Flash', + maxInputTokens: 128000, + supportedFileTypes: ['image'], pricing: { - inputPerM: 0.6, - outputPerM: 6, + inputPerM: 0, + outputPerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'zai.glm-4.7', + name: 'glm-4.7', displayName: 'GLM-4.7', maxInputTokens: 204800, supportedFileTypes: [], pricing: { - inputPerM: 0.6, - outputPerM: 2.2, + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, { - name: 'zai.glm-4.7-flash', - displayName: 'GLM-4.7-Flash', - maxInputTokens: 200000, + name: 'glm-5', + displayName: 'GLM-5', + maxInputTokens: 204800, supportedFileTypes: [], pricing: { - inputPerM: 0.07, - outputPerM: 0.4, + inputPerM: 0, + outputPerM: 0, + cacheReadPerM: 0, + cacheWritePerM: 0, currency: 'USD', unit: 'per_million_tokens', }, }, ], + 'dexto-nova': [], + 'openai-compatible': [], + litellm: [], + glama: [], local: [], ollama: [], - 'dexto-nova': [], } satisfies Record<LLMProvider, ModelInfo[]>; diff --git a/packages/core/src/llm/registry/models.manual.ts b/packages/core/src/llm/registry/models.manual.ts index 4f02e8b1c..ad8d79cf2 100644 --- a/packages/core/src/llm/registry/models.manual.ts +++ b/packages/core/src/llm/registry/models.manual.ts @@ -27,4 +27,4 @@ export const MANUAL_MODELS_BY_PROVIDER = { }, } satisfies ManualModelInfo, ], -} satisfies Partial<Record<LLMProvider, ModelInfo[]>>; +} as Partial<Record<LLMProvider, ModelInfo[]>>; diff --git a/packages/core/src/llm/registry/sync.ts b/packages/core/src/llm/registry/sync.ts index 4a398b0e3..8f3b620af 100644 --- a/packages/core/src/llm/registry/sync.ts +++ b/packages/core/src/llm/registry/sync.ts @@ -264,7 +264,16 @@ export function buildModelsByProviderFromParsedSources(params: { }): Record<LLMProvider, ModelInfo[]> { const { modelsDevApi } = params; - const defaults: Partial<Record<LLMProvider, string>> = { + const overlayProviderIds: LLMProvider[] = [ + 'dexto-nova', + 'openai-compatible', + 'litellm', + 'glama', + 'local', + 'ollama', + ]; + + const defaults: Partial<Record<string, string>> = { openai: 'gpt-5-mini', anthropic: 'claude-haiku-4-5-20251001', google: 'gemini-3-flash-preview', @@ -272,264 +281,47 @@ export function buildModelsByProviderFromParsedSources(params: { xai: 'grok-4', cohere: 'command-a-03-2025', minimax: 'MiniMax-M2.1', - 'minimax-cn': 'MiniMax-M2.1', - 'minimax-coding-plan': 'MiniMax-M2.1', - 'minimax-cn-coding-plan': 'MiniMax-M2.1', - glm: 'glm-4.7', zhipuai: 'glm-4.7', - 'zhipuai-coding-plan': 'glm-4.7', - zai: 'glm-4.7', - 'zai-coding-plan': 'glm-4.7', moonshotai: 'kimi-k2.5', - 'moonshotai-cn': 'kimi-k2.5', - 'kimi-for-coding': 'k2p5', - vertex: 'gemini-3-flash-preview', - bedrock: 'anthropic.claude-sonnet-4-5-20250929-v1:0', }; - const include = { - openai: (id: string) => id.startsWith('gpt-') || id.startsWith('o'), - anthropic: (id: string) => id.startsWith('claude-'), - google: (id: string) => id.startsWith('gemini-'), - groq: (_id: string) => true, - xai: (id: string) => id.startsWith('grok-'), - cohere: (id: string) => id.startsWith('command-'), - minimax: (_id: string) => true, - 'minimax-cn': (_id: string) => true, - 'minimax-coding-plan': (_id: string) => true, - 'minimax-cn-coding-plan': (_id: string) => true, - glm: (id: string) => id.startsWith('glm-'), - zhipuai: (id: string) => id.startsWith('glm-'), - 'zhipuai-coding-plan': (id: string) => id.startsWith('glm-'), - zai: (id: string) => id.startsWith('glm-'), - 'zai-coding-plan': (id: string) => id.startsWith('glm-'), - moonshotai: (_id: string) => true, - 'moonshotai-cn': (_id: string) => true, - 'kimi-for-coding': (_id: string) => true, - vertex: (_id: string) => true, - bedrock: (_id: string) => true, - openrouter: (_id: string) => true, - } as const; - - const modelsByProvider: Record<LLMProvider, ModelInfo[]> = { - openai: buildModelsFromModelsDevProvider({ - spec: { - provider: 'openai', - modelsDevProviderId: 'openai', - ...(defaults.openai ? { defaultModelId: defaults.openai } : {}), - includeModelId: include.openai, - }, - modelsDevApi, - }), - 'openai-compatible': [], - anthropic: buildModelsFromModelsDevProvider({ - spec: { - provider: 'anthropic', - modelsDevProviderId: 'anthropic', - ...(defaults.anthropic ? { defaultModelId: defaults.anthropic } : {}), - includeModelId: include.anthropic, - }, - modelsDevApi, - }), - google: buildModelsFromModelsDevProvider({ - spec: { - provider: 'google', - modelsDevProviderId: 'google', - ...(defaults.google ? { defaultModelId: defaults.google } : {}), - includeModelId: include.google, - }, - modelsDevApi, - }), - groq: buildModelsFromModelsDevProvider({ - spec: { - provider: 'groq', - modelsDevProviderId: 'groq', - ...(defaults.groq ? { defaultModelId: defaults.groq } : {}), - includeModelId: include.groq, - }, - modelsDevApi, - }), - xai: buildModelsFromModelsDevProvider({ - spec: { - provider: 'xai', - modelsDevProviderId: 'xai', - ...(defaults.xai ? { defaultModelId: defaults.xai } : {}), - includeModelId: include.xai, - }, - modelsDevApi, - }), - cohere: buildModelsFromModelsDevProvider({ - spec: { - provider: 'cohere', - modelsDevProviderId: 'cohere', - ...(defaults.cohere ? { defaultModelId: defaults.cohere } : {}), - includeModelId: include.cohere, - }, - modelsDevApi, - }), - minimax: buildModelsFromModelsDevProvider({ - spec: { - provider: 'minimax', - modelsDevProviderId: 'minimax', - ...(defaults.minimax ? { defaultModelId: defaults.minimax } : {}), - includeModelId: include.minimax, - }, - modelsDevApi, - }), - 'minimax-cn': buildModelsFromModelsDevProvider({ - spec: { - provider: 'minimax-cn', - modelsDevProviderId: 'minimax-cn', - ...(defaults['minimax-cn'] ? { defaultModelId: defaults['minimax-cn'] } : {}), - includeModelId: include['minimax-cn'], - }, - modelsDevApi, - }), - 'minimax-coding-plan': buildModelsFromModelsDevProvider({ - spec: { - provider: 'minimax-coding-plan', - modelsDevProviderId: 'minimax-coding-plan', - ...(defaults['minimax-coding-plan'] - ? { defaultModelId: defaults['minimax-coding-plan'] } - : {}), - includeModelId: include['minimax-coding-plan'], - }, - modelsDevApi, - }), - 'minimax-cn-coding-plan': buildModelsFromModelsDevProvider({ - spec: { - provider: 'minimax-cn-coding-plan', - modelsDevProviderId: 'minimax-cn-coding-plan', - ...(defaults['minimax-cn-coding-plan'] - ? { defaultModelId: defaults['minimax-cn-coding-plan'] } - : {}), - includeModelId: include['minimax-cn-coding-plan'], - }, - modelsDevApi, - }), - glm: buildModelsFromModelsDevProvider({ - spec: { - provider: 'glm', - modelsDevProviderId: 'zhipuai', - ...(defaults.glm ? { defaultModelId: defaults.glm } : {}), - includeModelId: include.glm, - }, - modelsDevApi, - }), - zhipuai: buildModelsFromModelsDevProvider({ - spec: { - provider: 'zhipuai', - modelsDevProviderId: 'zhipuai', - ...(defaults.zhipuai ? { defaultModelId: defaults.zhipuai } : {}), - includeModelId: include.zhipuai, - }, - modelsDevApi, - }), - 'zhipuai-coding-plan': buildModelsFromModelsDevProvider({ - spec: { - provider: 'zhipuai-coding-plan', - modelsDevProviderId: 'zhipuai-coding-plan', - ...(defaults['zhipuai-coding-plan'] - ? { defaultModelId: defaults['zhipuai-coding-plan'] } - : {}), - includeModelId: include['zhipuai-coding-plan'], - }, - modelsDevApi, - }), - zai: buildModelsFromModelsDevProvider({ - spec: { - provider: 'zai', - modelsDevProviderId: 'zai', - ...(defaults.zai ? { defaultModelId: defaults.zai } : {}), - includeModelId: include.zai, - }, - modelsDevApi, - }), - 'zai-coding-plan': buildModelsFromModelsDevProvider({ - spec: { - provider: 'zai-coding-plan', - modelsDevProviderId: 'zai-coding-plan', - ...(defaults['zai-coding-plan'] - ? { defaultModelId: defaults['zai-coding-plan'] } - : {}), - includeModelId: include['zai-coding-plan'], - }, - modelsDevApi, - }), - moonshotai: buildModelsFromModelsDevProvider({ - spec: { - provider: 'moonshotai', - modelsDevProviderId: 'moonshotai', - ...(defaults.moonshotai ? { defaultModelId: defaults.moonshotai } : {}), - includeModelId: include.moonshotai, - }, - modelsDevApi, - }), - 'moonshotai-cn': buildModelsFromModelsDevProvider({ - spec: { - provider: 'moonshotai-cn', - modelsDevProviderId: 'moonshotai-cn', - ...(defaults['moonshotai-cn'] ? { defaultModelId: defaults['moonshotai-cn'] } : {}), - includeModelId: include['moonshotai-cn'], - }, - modelsDevApi, - }), - 'kimi-for-coding': buildModelsFromModelsDevProvider({ - spec: { - provider: 'kimi-for-coding', - modelsDevProviderId: 'kimi-for-coding', - ...(defaults['kimi-for-coding'] - ? { defaultModelId: defaults['kimi-for-coding'] } - : {}), - includeModelId: include['kimi-for-coding'], - }, - modelsDevApi, - }), - openrouter: buildModelsFromModelsDevProvider({ - spec: { - provider: 'openrouter', - modelsDevProviderId: 'openrouter', - includeModelId: include.openrouter, - }, - modelsDevApi, - }), - litellm: [], - glama: [], - vertex: [ - ...buildModelsFromModelsDevProvider({ - spec: { - provider: 'vertex', - modelsDevProviderId: 'google-vertex', - ...(defaults.vertex ? { defaultModelId: defaults.vertex } : {}), - includeModelId: include.vertex, - }, - modelsDevApi, - }), - ...buildModelsFromModelsDevProvider({ - spec: { - provider: 'vertex', - modelsDevProviderId: 'google-vertex-anthropic', - includeModelId: include.vertex, - }, - modelsDevApi, - }), - ].sort((a, b) => a.name.localeCompare(b.name)), - bedrock: buildModelsFromModelsDevProvider({ + function includeModel(providerId: string, modelId: string): boolean { + if (providerId === 'openai') return modelId.startsWith('gpt-') || modelId.startsWith('o'); + if (providerId === 'anthropic') return modelId.startsWith('claude-'); + if (providerId === 'google') return modelId.startsWith('gemini-'); + if (providerId === 'xai') return modelId.startsWith('grok-'); + if (providerId === 'cohere') return modelId.startsWith('command-'); + return true; + } + + const providerIds = Object.keys(modelsDevApi).sort(); + const modelsByProvider = {} as Record<LLMProvider, ModelInfo[]>; + + for (const providerId of providerIds) { + const providerKey = providerId as LLMProvider; + const models = buildModelsFromModelsDevProvider({ spec: { - provider: 'bedrock', - modelsDevProviderId: 'amazon-bedrock', - ...(defaults.bedrock ? { defaultModelId: defaults.bedrock } : {}), - includeModelId: include.bedrock, + provider: providerKey, + modelsDevProviderId: providerId, + ...(defaults[providerId] ? { defaultModelId: defaults[providerId] } : {}), + includeModelId: (id) => includeModel(providerId, id), }, modelsDevApi, - }) - .map((m) => ({ ...m, name: m.name.replace(/^(eu\.|us\.|global\.)/i, '') })) - .filter((m, idx, arr) => arr.findIndex((x) => x.name === m.name) === idx) - .sort((a, b) => a.name.localeCompare(b.name)), - local: [], - ollama: [], - 'dexto-nova': [], - }; + }); + + if (providerId === 'amazon-bedrock') { + modelsByProvider[providerKey] = models + .map((m) => ({ ...m, name: m.name.replace(/^(eu\.|us\.|global\.)/i, '') })) + .filter((m, idx, arr) => arr.findIndex((x) => x.name === m.name) === idx) + .sort((a, b) => a.name.localeCompare(b.name)); + } else { + modelsByProvider[providerKey] = models; + } + } + + for (const overlayId of overlayProviderIds) { + modelsByProvider[overlayId] = []; + } return modelsByProvider; } diff --git a/packages/core/src/llm/resolver.ts b/packages/core/src/llm/resolver.ts index 90f4cc3e5..4e9040411 100644 --- a/packages/core/src/llm/resolver.ts +++ b/packages/core/src/llm/resolver.ts @@ -58,11 +58,21 @@ export async function resolveLLMConfig( ): Promise<{ candidate: LLMConfig; warnings: Issue<LLMUpdateContext>[] }> { const warnings: Issue<LLMUpdateContext>[] = []; - // Provider inference (if not provided, infer from native model IDs or fall back to previous provider) + // Provider inference + // - If user explicitly sets provider: use it. + // - If user only changes model: keep previous provider when it supports the model. + // - Otherwise, attempt to infer provider from the model ID (best-effort). const provider = updates.provider ?? (updates.model && !updates.model.includes('/') ? (() => { + if ( + acceptsAnyModel(previous.provider) || + supportsCustomModels(previous.provider) || + isValidProviderModel(previous.provider, updates.model) + ) { + return previous.provider; + } try { return getProviderFromModel(updates.model); } catch { @@ -154,7 +164,7 @@ export async function resolveLLMConfig( // Vertex AI validation - requires GOOGLE_VERTEX_PROJECT for ADC authentication // This upfront check provides immediate feedback rather than failing at first API call - if (provider === 'vertex') { + if (provider === 'google-vertex' || provider === 'google-vertex-anthropic') { const projectId = process.env.GOOGLE_VERTEX_PROJECT; if (!projectId || !projectId.trim()) { warnings.push({ @@ -174,7 +184,7 @@ export async function resolveLLMConfig( // Auth can be either: // 1. AWS_BEARER_TOKEN_BEDROCK (API key - simplest) // 2. AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY (IAM credentials) - if (provider === 'bedrock') { + if (provider === 'amazon-bedrock') { const region = process.env.AWS_REGION || process.env.AWS_DEFAULT_REGION; if (!region || !region.trim()) { warnings.push({ diff --git a/packages/core/src/llm/services/factory.ts b/packages/core/src/llm/services/factory.ts index a2728fc0c..819aff201 100644 --- a/packages/core/src/llm/services/factory.ts +++ b/packages/core/src/llm/services/factory.ts @@ -144,16 +144,6 @@ export function createVercelModel( ...(runtimeFetch ? { fetch: runtimeFetch } : {}), })(model); } - case 'glm': { - // Zhipu AI (GLM) - OpenAI-compatible endpoint - const glmBaseURL = baseURL || 'https://open.bigmodel.cn/api/paas/v4'; - return createOpenAI({ - apiKey: apiKey ?? '', - baseURL: glmBaseURL, - ...(extraHeaders ? { headers: extraHeaders } : {}), - ...(runtimeFetch ? { fetch: runtimeFetch } : {}), - }).chat(model); - } case 'zhipuai': { const zhipuBaseURL = baseURL || 'https://open.bigmodel.cn/api/paas/v4'; return createOpenAI({ @@ -272,39 +262,34 @@ export function createVercelModel( ...(runtimeFetch ? { fetch: runtimeFetch } : {}), }).chat(model); } - case 'vertex': { - // Google Vertex AI - supports both Gemini and Claude models + case 'google-vertex': { + // Google Vertex AI (Gemini) // Auth via Application Default Credentials (ADC) - // - // TODO: Integrate with agent config (llmConfig.vertex?.projectId) as primary, - // falling back to env vars. This would allow per-agent Vertex configuration. const projectId = process.env.GOOGLE_VERTEX_PROJECT; if (!projectId) { throw LLMError.missingConfig( - 'vertex', + 'google-vertex', 'GOOGLE_VERTEX_PROJECT environment variable' ); } - const location = process.env.GOOGLE_VERTEX_LOCATION; - - // Route based on model type: Claude models use /anthropic subpath - if (model.includes('claude')) { - // Claude models on Vertex use the /anthropic subpath export - // Default to us-east5 for Claude (limited region availability) - return createVertexAnthropic({ - project: projectId, - location: location || 'us-east5', - })(model); + const location = process.env.GOOGLE_VERTEX_LOCATION || 'us-central1'; + return createVertex({ project: projectId, location })(model); + } + case 'google-vertex-anthropic': { + // Anthropic models on Google Vertex AI + // Auth via Application Default Credentials (ADC) + const projectId = process.env.GOOGLE_VERTEX_PROJECT; + if (!projectId) { + throw LLMError.missingConfig( + 'google-vertex-anthropic', + 'GOOGLE_VERTEX_PROJECT environment variable' + ); } - - // Gemini models use the main export - // Default to us-central1 for Gemini (widely available) - return createVertex({ - project: projectId, - location: location || 'us-central1', - })(model); + // Default to us-east5 for Claude (limited region availability) + const location = process.env.GOOGLE_VERTEX_LOCATION || 'us-east5'; + return createVertexAnthropic({ project: projectId, location })(model); } - case 'bedrock': { + case 'amazon-bedrock': { // Amazon Bedrock - AWS-hosted gateway for Claude, Nova, Llama, Mistral // Auth via AWS credentials (env vars or credential provider) // @@ -322,7 +307,7 @@ export function createVercelModel( const region = process.env.AWS_REGION || process.env.AWS_DEFAULT_REGION; if (!region) { throw LLMError.missingConfig( - 'bedrock', + 'amazon-bedrock', 'AWS_REGION or AWS_DEFAULT_REGION environment variable' ); } diff --git a/packages/core/src/llm/services/test-utils.integration.ts b/packages/core/src/llm/services/test-utils.integration.ts index 253da353c..e8855d1ee 100644 --- a/packages/core/src/llm/services/test-utils.integration.ts +++ b/packages/core/src/llm/services/test-utils.integration.ts @@ -1,9 +1,9 @@ // NOTE: Shared helpers for LLM service integration tests (not itself a test file). import { DextoAgent } from '../../agent/DextoAgent.js'; import { + getApiKeyEnvVarsForProvider, resolveApiKeyForProvider, getPrimaryApiKeyEnvVar, - PROVIDER_API_KEY_MAP, } from '../../utils/api-key-resolver.js'; import type { LLMProvider } from '../types.js'; import type { AgentRuntimeSettings } from '../../agent/runtime-config.js'; @@ -21,6 +21,7 @@ import { createInMemoryCache, createInMemoryDatabase, } from '../../test-utils/in-memory-storage.js'; +import { getDefaultModelForProvider } from '../registry/index.js'; /** * Shared utilities for LLM service integration tests @@ -180,7 +181,7 @@ export const TestConfigs = { } // Default models for common providers - const defaultModels: Record<LLMProvider, string> = { + const defaultModels: Partial<Record<LLMProvider, string>> = { openai: 'gpt-4o-mini', anthropic: 'claude-haiku-4-5-20251001', google: 'gemini-2.0-flash', @@ -191,7 +192,6 @@ export const TestConfigs = { 'minimax-cn': 'MiniMax-M2.1', 'minimax-coding-plan': 'MiniMax-M2.1', 'minimax-cn-coding-plan': 'MiniMax-M2.1', - glm: 'glm-4.7', zhipuai: 'glm-4.7', 'zhipuai-coding-plan': 'glm-4.7', zai: 'glm-4.7', @@ -203,20 +203,29 @@ export const TestConfigs = { openrouter: 'anthropic/claude-3.5-haiku', // OpenRouter model format: provider/model litellm: 'gpt-4', // LiteLLM model names follow the provider's convention glama: 'openai/gpt-4o', // Glama model format: provider/model - vertex: 'gemini-2.5-pro', // Vertex AI uses ADC auth, not API keys - bedrock: 'anthropic.claude-3-5-haiku-20241022-v1:0', // Bedrock uses AWS credentials, not API keys + 'google-vertex': 'gemini-2.5-pro', // Vertex AI uses ADC auth, not API keys + 'google-vertex-anthropic': 'claude-sonnet-4@20250514', + 'amazon-bedrock': 'anthropic.claude-3-5-haiku-20241022-v1:0', // Bedrock uses AWS credentials, not API keys local: 'llama-3.2-3b-q4', // Native node-llama-cpp GGUF models ollama: 'llama3.2', // Ollama server models 'dexto-nova': 'anthropic/claude-4.5-sonnet', // Dexto gateway (OpenRouter model format) }; + const resolvedModel = + model || defaultModels[provider] || getDefaultModelForProvider(provider); + if (!resolvedModel) { + throw new Error( + `No default model found for provider '${provider}'. Pass an explicit model.` + ); + } + return { systemPrompt: SystemPromptConfigSchema.parse( 'You are a helpful assistant for testing purposes.' ), llm: LLMConfigSchema.parse({ provider, - model: model || defaultModels[provider], + model: resolvedModel, apiKey, maxOutputTokens: 1000, // Enough for reasoning models (reasoning + answer) temperature: 0, @@ -244,11 +253,10 @@ export const TestConfigs = { /** * Helper to check if a provider requires an API key - * Providers with empty arrays in PROVIDER_API_KEY_MAP don't require API keys (e.g., local, ollama, vertex) + * Providers with no key-like env vars don't require API keys (e.g., local, ollama, google-vertex) */ export function providerRequiresApiKey(provider: LLMProvider): boolean { - const envVars = PROVIDER_API_KEY_MAP[provider]; - return envVars && envVars.length > 0; + return getApiKeyEnvVarsForProvider(provider).length > 0; } /** diff --git a/packages/core/src/llm/types.ts b/packages/core/src/llm/types.ts index 58aa83b1b..ec803d5c2 100644 --- a/packages/core/src/llm/types.ts +++ b/packages/core/src/llm/types.ts @@ -1,33 +1,7 @@ -// Derive types from registry constants without creating runtime imports. -export const LLM_PROVIDERS = [ - 'openai', - 'openai-compatible', - 'anthropic', - 'google', - 'groq', - 'xai', - 'cohere', - 'minimax', - 'minimax-cn', - 'minimax-coding-plan', - 'minimax-cn-coding-plan', - 'glm', - 'zhipuai', - 'zhipuai-coding-plan', - 'zai', - 'zai-coding-plan', - 'moonshotai', - 'moonshotai-cn', - 'kimi-for-coding', - 'openrouter', - 'litellm', - 'glama', - 'vertex', - 'bedrock', - 'local', // Native node-llama-cpp execution (GGUF models) - 'ollama', // Ollama server integration - 'dexto-nova', // Dexto gateway - routes through api.dexto.ai/v1 with billing -] as const; +import { LLM_PROVIDERS as GENERATED_LLM_PROVIDERS } from './providers.generated.js'; + +// Derived from a committed models.dev provider snapshot (plus a small Dexto overlay). +export const LLM_PROVIDERS = GENERATED_LLM_PROVIDERS; export type LLMProvider = (typeof LLM_PROVIDERS)[number]; export const SUPPORTED_FILE_TYPES = ['pdf', 'image', 'audio'] as const; diff --git a/packages/core/src/utils/api-key-resolver.ts b/packages/core/src/utils/api-key-resolver.ts index 10857eb1b..a51f11716 100644 --- a/packages/core/src/utils/api-key-resolver.ts +++ b/packages/core/src/utils/api-key-resolver.ts @@ -1,53 +1,59 @@ import type { LLMProvider } from '../llm/types.js'; +import { PROVIDERS_BY_ID } from '../llm/providers.generated.js'; /** * Utility for resolving API keys from environment variables. - * This consolidates the API key resolution logic used across CLI and core components. + * + * This is intentionally derived from the committed models.dev provider snapshot so we can + * support many providers without maintaining a giant hardcoded map. */ -// Map the provider to its corresponding API key name (in order of preference) -export const PROVIDER_API_KEY_MAP: Record<LLMProvider, string[]> = { - openai: ['OPENAI_API_KEY', 'OPENAI_KEY'], - 'openai-compatible': ['OPENAI_API_KEY', 'OPENAI_KEY'], // Uses same keys as openai - anthropic: ['ANTHROPIC_API_KEY', 'ANTHROPIC_KEY', 'CLAUDE_API_KEY'], - google: ['GOOGLE_GENERATIVE_AI_API_KEY', 'GOOGLE_API_KEY', 'GEMINI_API_KEY'], - groq: ['GROQ_API_KEY'], - cohere: ['COHERE_API_KEY'], - xai: ['XAI_API_KEY', 'X_AI_API_KEY'], - minimax: ['MINIMAX_API_KEY'], - 'minimax-cn': ['MINIMAX_API_KEY'], - 'minimax-coding-plan': ['MINIMAX_API_KEY'], - 'minimax-cn-coding-plan': ['MINIMAX_API_KEY'], - glm: ['ZHIPU_API_KEY', 'ZHIPUAI_API_KEY'], - zhipuai: ['ZHIPU_API_KEY', 'ZHIPUAI_API_KEY'], - 'zhipuai-coding-plan': ['ZHIPU_API_KEY', 'ZHIPUAI_API_KEY'], - zai: ['ZHIPU_API_KEY'], - 'zai-coding-plan': ['ZHIPU_API_KEY'], - moonshotai: ['MOONSHOT_API_KEY'], - 'moonshotai-cn': ['MOONSHOT_API_KEY'], - 'kimi-for-coding': ['KIMI_API_KEY'], - openrouter: ['OPENROUTER_API_KEY'], - litellm: ['LITELLM_API_KEY', 'LITELLM_KEY'], - glama: ['GLAMA_API_KEY'], - // Vertex uses ADC (Application Default Credentials), not API keys - // GOOGLE_APPLICATION_CREDENTIALS points to service account JSON (optional) - // Primary config is GOOGLE_VERTEX_PROJECT (required) + GOOGLE_VERTEX_LOCATION (optional) - vertex: [], - // Bedrock supports two auth methods: - // 1. AWS_BEARER_TOKEN_BEDROCK - Bedrock API key (simplest) - // 2. AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY + AWS_REGION (IAM credentials) - // AWS_SESSION_TOKEN (optional, for temporary credentials) - bedrock: ['AWS_BEARER_TOKEN_BEDROCK'], - // Local providers don't require API keys - local: [], // Native node-llama-cpp execution - ollama: [], // Ollama server (no authentication required) - // Dexto gateway - requires key from `dexto login` - 'dexto-nova': ['DEXTO_API_KEY'], - // perplexity: ['PERPLEXITY_API_KEY'], - // together: ['TOGETHER_API_KEY'], - // fireworks: ['FIREWORKS_API_KEY'], - // deepseek: ['DEEPSEEK_API_KEY'], -}; +const EXTRA_API_KEY_ENV_VARS: Record<string, string[]> = { + openai: ['OPENAI_KEY'], + anthropic: ['ANTHROPIC_KEY', 'CLAUDE_API_KEY'], + google: ['GOOGLE_API_KEY', 'GEMINI_API_KEY'], + xai: ['X_AI_API_KEY'], + zhipuai: ['ZHIPUAI_API_KEY'], +} as const; + +function isLikelyApiKeyEnvVar(name: string): boolean { + return /(API_KEY|API_TOKEN|TOKEN|SECRET)\b/i.test(name); +} + +function uniqueInOrder(values: string[]): string[] { + const seen = new Set<string>(); + const result: string[] = []; + for (const value of values) { + if (seen.has(value)) continue; + seen.add(value); + result.push(value); + } + return result; +} + +export function getApiKeyEnvVarsForProvider(provider: LLMProvider): string[] { + // Providers that don't use a single API key string + if ( + provider === 'google-vertex' || + provider === 'google-vertex-anthropic' || + provider === 'local' || + provider === 'ollama' + ) { + return []; + } + + // Bedrock supports an optional bearer token for the Converse API. + // When absent, auth is handled via AWS credential chain (env/roles/SSO). + if (provider === 'amazon-bedrock') { + return ['AWS_BEARER_TOKEN_BEDROCK']; + } + + const snapshot = PROVIDERS_BY_ID[provider]; + const fromSnapshot = snapshot?.env ?? []; + const filtered = fromSnapshot.filter(isLikelyApiKeyEnvVar); + const extras = EXTRA_API_KEY_ENV_VARS[provider] ?? []; + return uniqueInOrder([...filtered, ...extras]); +} /** * Resolves API key for a given provider from environment variables. @@ -56,10 +62,7 @@ export const PROVIDER_API_KEY_MAP: Record<LLMProvider, string[]> = { * @returns Resolved API key or undefined if not found */ export function resolveApiKeyForProvider(provider: LLMProvider): string | undefined { - const envVars = PROVIDER_API_KEY_MAP[provider]; - if (!envVars) { - return undefined; - } + const envVars = getApiKeyEnvVarsForProvider(provider); // Try each environment variable in order of preference for (const envVar of envVars) { @@ -79,6 +82,6 @@ export function resolveApiKeyForProvider(provider: LLMProvider): string | undefi * @returns Primary environment variable name */ export function getPrimaryApiKeyEnvVar(provider: LLMProvider): string { - const envVars = PROVIDER_API_KEY_MAP[provider]; - return envVars?.[0] || `${provider.toUpperCase()}_API_KEY`; + const envVars = getApiKeyEnvVarsForProvider(provider); + return envVars[0] || `${provider.toUpperCase()}_API_KEY`; } diff --git a/packages/webui/components/ModelPicker/CompactModelCard.tsx b/packages/webui/components/ModelPicker/CompactModelCard.tsx index 44eaa95ce..fbed33246 100644 --- a/packages/webui/components/ModelPicker/CompactModelCard.tsx +++ b/packages/webui/components/ModelPicker/CompactModelCard.tsx @@ -26,12 +26,13 @@ const PROVIDER_DISPLAY_NAMES: Record<string, string> = { xai: 'Grok', cohere: 'Cohere', minimax: 'MiniMax', - glm: 'GLM', + zhipuai: 'GLM', openrouter: 'OpenRouter', litellm: 'LiteLLM', glama: 'Glama', - vertex: 'Vertex AI', - bedrock: 'Bedrock', + 'google-vertex': 'Vertex AI', + 'google-vertex-anthropic': 'Vertex AI (Claude)', + 'amazon-bedrock': 'Bedrock', 'openai-compatible': 'Custom', 'dexto-nova': 'Dexto Nova', }; @@ -43,8 +44,7 @@ const MULTI_VENDOR_PROVIDERS = new Set([ 'openai-compatible', 'litellm', 'glama', - 'bedrock', - 'vertex', + 'amazon-bedrock', ]); export function CompactModelCard({ diff --git a/packages/webui/components/ModelPicker/CustomModelForms.tsx b/packages/webui/components/ModelPicker/CustomModelForms.tsx index 0d4edd5cb..1b3cb7331 100644 --- a/packages/webui/components/ModelPicker/CustomModelForms.tsx +++ b/packages/webui/components/ModelPicker/CustomModelForms.tsx @@ -27,7 +27,7 @@ export type CustomModelProvider = | 'openrouter' | 'litellm' | 'glama' - | 'bedrock' + | 'amazon-bedrock' | 'ollama' | 'local' | 'dexto-nova'; @@ -75,7 +75,7 @@ const PROVIDER_OPTIONS: { value: CustomModelProvider; label: string; description description: 'OpenAI-compatible gateway for multiple providers', }, { - value: 'bedrock', + value: 'amazon-bedrock', label: 'AWS Bedrock', description: 'Custom Bedrock model IDs (uses AWS credentials)', }, @@ -1110,7 +1110,7 @@ export function CustomModelForm({ return; } break; - case 'bedrock': + case 'amazon-bedrock': if (!formData.name.trim()) { setLocalError('Model ID is required'); return; @@ -1171,7 +1171,7 @@ export function CustomModelForm({ case 'openrouter': case 'glama': return formData.name.trim() && formData.name.includes('/'); - case 'bedrock': + case 'amazon-bedrock': return formData.name.trim().length > 0; case 'ollama': return formData.name.trim().length > 0; @@ -1205,7 +1205,7 @@ export function CustomModelForm({ }; switch (formData.provider) { - case 'bedrock': + case 'amazon-bedrock': return <BedrockFields {...props} />; case 'openrouter': return <OpenRouterFields {...props} />; diff --git a/packages/webui/components/ModelPicker/ModelCard.tsx b/packages/webui/components/ModelPicker/ModelCard.tsx index 803c15bca..ad09f3555 100644 --- a/packages/webui/components/ModelPicker/ModelCard.tsx +++ b/packages/webui/components/ModelPicker/ModelCard.tsx @@ -32,11 +32,14 @@ const PROVIDER_DISPLAY_NAMES: Record<string, string> = { xai: 'Grok', cohere: 'Cohere', minimax: 'MiniMax', - glm: 'GLM', + zhipuai: 'GLM', openrouter: 'OpenRouter', 'openai-compatible': 'Custom', litellm: 'LiteLLM', glama: 'Glama', + 'google-vertex': 'Vertex AI', + 'google-vertex-anthropic': 'Vertex AI (Claude)', + 'amazon-bedrock': 'Bedrock', local: 'Local', ollama: 'Ollama', 'dexto-nova': 'Dexto Nova', @@ -56,8 +59,9 @@ function parseModelName( provider === 'openai-compatible' || provider === 'litellm' || provider === 'glama' || - provider === 'bedrock' || - provider === 'vertex' + provider === 'amazon-bedrock' || + provider === 'google-vertex' || + provider === 'google-vertex-anthropic' ) { return { providerName, modelName: displayName }; } @@ -99,7 +103,14 @@ export function ModelCard({ const displayName = model.displayName || model.name; // Local/ollama/installed models don't need API keys // Custom models are user-configured, so don't show lock (they handle their own auth) - const noApiKeyNeeded = isInstalled || isCustom || provider === 'local' || provider === 'ollama'; + const noApiKeyNeeded = + isInstalled || + isCustom || + provider === 'local' || + provider === 'ollama' || + provider === 'google-vertex' || + provider === 'google-vertex-anthropic' || + provider === 'amazon-bedrock'; const hasApiKey = noApiKeyNeeded || (providerInfo?.hasApiKey ?? false); const { providerName, modelName, suffix } = parseModelName(displayName, provider); diff --git a/packages/webui/components/ModelPicker/ModelPickerModal.tsx b/packages/webui/components/ModelPicker/ModelPickerModal.tsx index 95c312f44..10c8c3b44 100644 --- a/packages/webui/components/ModelPicker/ModelPickerModal.tsx +++ b/packages/webui/components/ModelPicker/ModelPickerModal.tsx @@ -426,13 +426,13 @@ export default function ModelPickerModal() { ); const editCustomModel = useCallback((model: CustomModel) => { - // Map provider to form-supported provider (vertex uses openai-compatible form) + // Map provider to form-supported provider const formSupportedProviders: CustomModelProvider[] = [ 'openai-compatible', 'openrouter', 'litellm', 'glama', - 'bedrock', + 'amazon-bedrock', 'ollama', 'local', ]; diff --git a/packages/webui/components/ModelPicker/constants.tsx b/packages/webui/components/ModelPicker/constants.tsx index bf12aad0e..a6af07832 100644 --- a/packages/webui/components/ModelPicker/constants.tsx +++ b/packages/webui/components/ModelPicker/constants.tsx @@ -4,7 +4,7 @@ import type { LLMProvider } from '@dexto/core'; // Provider logo file mapping - single source of truth // Empty string means "use Bot icon fallback" in components -export const PROVIDER_LOGOS: Record<LLMProvider, string> = { +export const PROVIDER_LOGOS: Partial<Record<LLMProvider, string>> = { openai: '/logos/openai.svg', anthropic: '/logos/claude-color.svg', google: '/logos/gemini-color.svg', @@ -16,7 +16,6 @@ export const PROVIDER_LOGOS: Record<LLMProvider, string> = { 'minimax-cn': '', 'minimax-coding-plan': '', 'minimax-cn-coding-plan': '', - glm: '', zhipuai: '', 'zhipuai-coding-plan': '', zai: '', @@ -27,8 +26,9 @@ export const PROVIDER_LOGOS: Record<LLMProvider, string> = { openrouter: '/logos/openrouter.svg', litellm: '/logos/litellm.svg', glama: '/logos/glama.svg', - vertex: '/logos/gemini-color.svg', // Vertex AI uses Gemini logo (primary model family) - bedrock: '/logos/aws-color.svg', + 'google-vertex': '/logos/gemini-color.svg', + 'google-vertex-anthropic': '/logos/claude-color.svg', + 'amazon-bedrock': '/logos/aws-color.svg', local: '', // Uses Bot icon fallback - local GGUF models via node-llama-cpp ollama: '/logos/ollama.svg', // Ollama server 'dexto-nova': '/logos/dexto/dexto_logo_icon.svg', // Dexto gateway - use Dexto logo @@ -43,12 +43,13 @@ export const PROVIDER_PRICING_URLS: Partial<Record<LLMProvider, string>> = { xai: 'https://docs.x.ai/docs/models', cohere: 'https://cohere.com/pricing', minimax: 'https://platform.minimax.io/docs/pricing/overview', - glm: 'https://open.bigmodel.cn/pricing', + zhipuai: 'https://open.bigmodel.cn/pricing', openrouter: 'https://openrouter.ai/models', litellm: 'https://docs.litellm.ai/', glama: 'https://glama.ai/', - vertex: 'https://cloud.google.com/vertex-ai/generative-ai/pricing', - bedrock: 'https://aws.amazon.com/bedrock/pricing/', + 'google-vertex': 'https://cloud.google.com/vertex-ai/generative-ai/pricing', + 'google-vertex-anthropic': 'https://cloud.google.com/vertex-ai/generative-ai/pricing', + 'amazon-bedrock': 'https://aws.amazon.com/bedrock/pricing/', // TODO: make this a valid URL 'dexto-nova': 'https://dexto.ai/pricing', // 'openai-compatible' intentionally omitted (varies by vendor) @@ -86,7 +87,8 @@ export const COLORED_LOGOS: readonly LLMProvider[] = [ 'google', 'cohere', 'anthropic', - 'vertex', + 'google-vertex', + 'google-vertex-anthropic', 'dexto-nova', ] as const; diff --git a/packages/webui/components/settings/sections/ApiKeysSection.tsx b/packages/webui/components/settings/sections/ApiKeysSection.tsx index d2161f9ed..a71672764 100644 --- a/packages/webui/components/settings/sections/ApiKeysSection.tsx +++ b/packages/webui/components/settings/sections/ApiKeysSection.tsx @@ -77,8 +77,9 @@ const EXCLUDED_PROVIDERS = [ 'local', // Local GGUF, no key needed 'openai-compatible', // Needs baseURL + model name (use ModelPicker) 'litellm', // Needs baseURL (use ModelPicker) - 'bedrock', // Uses AWS credentials, not API key - 'vertex', // Uses Google Cloud ADC, not API key + 'amazon-bedrock', // Uses AWS credentials, not API key + 'google-vertex', // Uses Google Cloud ADC, not API key + 'google-vertex-anthropic', // Uses Google Cloud ADC, not API key ]; type ProviderRowProps = { diff --git a/scripts/sync-llm-registry.ts b/scripts/sync-llm-models.ts similarity index 52% rename from scripts/sync-llm-registry.ts rename to scripts/sync-llm-models.ts index 097df65ae..3c31b2328 100644 --- a/scripts/sync-llm-registry.ts +++ b/scripts/sync-llm-models.ts @@ -1,16 +1,16 @@ #!/usr/bin/env tsx /** - * Syncs Dexto's built-in LLM model registry from models.dev. + * Syncs Dexto's built-in LLM model + provider snapshots from models.dev. * * Why: * - `packages/core/src/llm/registry/index.ts` used to hardcode many models (tokens/pricing/modalities), * which is painful to maintain. * - models.dev provides a maintained, cross-provider model catalog. - * - models.dev provides gateway catalogs (e.g. OpenRouter) including pricing and modalities. + * - models.dev provides provider metadata (env var hints, docs, base URLs, intended SDK transports). * * Usage: - * pnpm run sync-llm-registry # regenerate the committed snapshot - * pnpm run sync-llm-registry:check # verify snapshot is up-to-date (CI) + * pnpm run sync-llm-models # regenerate the committed snapshots + * pnpm run sync-llm-models:check # verify snapshots are up-to-date (CI) * * Optional env overrides: * DEXTO_MODELS_DEV_API_JSON=/path/to/api.json @@ -26,7 +26,14 @@ const __dirname = path.dirname(__filename); const CHECK_MODE = process.argv.includes('--check'); -const OUTPUT_PATH = path.join(__dirname, '../packages/core/src/llm/registry/models.generated.ts'); +const MODELS_OUTPUT_PATH = path.join( + __dirname, + '../packages/core/src/llm/registry/models.generated.ts' +); +const PROVIDERS_OUTPUT_PATH = path.join( + __dirname, + '../packages/core/src/llm/providers.generated.ts' +); const MODELS_DEV_URL = 'https://models.dev/api.json'; @@ -34,6 +41,10 @@ type ModelsDevApi = Record<string, ModelsDevProvider>; type ModelsDevProvider = { id: string; name: string; + env: string[]; + npm: string; + api?: string | undefined; + doc?: string | undefined; models: Record<string, ModelsDevModel>; }; type ModelsDevModel = { @@ -91,6 +102,17 @@ function requireNumber(value: unknown, label: string): number { return value; } +function parseStringArray(value: unknown): string[] { + if (!Array.isArray(value)) return []; + const result: string[] = []; + for (const item of value) { + if (typeof item !== 'string') continue; + const trimmed = item.trim(); + if (trimmed) result.push(trimmed); + } + return result; +} + function parseModelsDevApi(json: unknown): ModelsDevApi { const root = requireRecord(json, 'models.dev api.json root'); const api: ModelsDevApi = {}; @@ -126,6 +148,16 @@ function parseModelsDevApi(json: unknown): ModelsDevApi { provider.name ?? providerId, `models.dev provider '${providerId}'.name` ), + env: parseStringArray(provider.env), + npm: requireString(provider.npm, `models.dev provider '${providerId}'.npm`), + api: + typeof provider.api === 'string' && provider.api.trim() + ? provider.api.trim() + : undefined, + doc: + typeof provider.doc === 'string' && provider.doc.trim() + ? provider.doc.trim() + : undefined, models: {}, }; @@ -194,35 +226,6 @@ function parseModelsDevApi(json: unknown): ModelsDevApi { return api; } -type DextoProvider = - | 'openai' - | 'openai-compatible' - | 'anthropic' - | 'google' - | 'groq' - | 'xai' - | 'cohere' - | 'minimax' - | 'minimax-cn' - | 'minimax-coding-plan' - | 'minimax-cn-coding-plan' - | 'glm' - | 'zhipuai' - | 'zhipuai-coding-plan' - | 'zai' - | 'zai-coding-plan' - | 'moonshotai' - | 'moonshotai-cn' - | 'kimi-for-coding' - | 'openrouter' - | 'litellm' - | 'glama' - | 'vertex' - | 'bedrock' - | 'local' - | 'ollama' - | 'dexto-nova'; - type DextoSupportedFileType = 'pdf' | 'image' | 'audio'; type GeneratedModelPricing = { @@ -244,7 +247,7 @@ type GeneratedModelInfo = { }; function getSupportedFileTypesFromModel( - provider: DextoProvider, + provider: string, model: ModelsDevModel ): DextoSupportedFileType[] { const inputModalities = model.modalities?.input ?? []; @@ -281,7 +284,7 @@ function getPricing(model: ModelsDevModel): GeneratedModelPricing | undefined { function modelToGeneratedModel( model: ModelsDevModel, options: { - provider: DextoProvider; + provider: string; defaultModelId?: string; } ): GeneratedModelInfo { @@ -296,7 +299,7 @@ function modelToGeneratedModel( } function buildModelsFromModelsDevProvider(params: { - provider: DextoProvider; + provider: string; modelsDevApi: ModelsDevApi; modelsDevProviderId: string; defaultModelId?: string; @@ -332,7 +335,7 @@ async function loadModelsDevApiJsonText(): Promise<string> { } const res = await fetch(MODELS_DEV_URL, { - headers: { 'User-Agent': 'dexto-sync-llm-registry' }, + headers: { 'User-Agent': 'dexto-sync-llm-models' }, signal: AbortSignal.timeout(30_000), }); if (!res.ok) { @@ -345,7 +348,16 @@ async function syncLlmRegistry() { const modelsDevText = await loadModelsDevApiJsonText(); const modelsDevJson = parseModelsDevApi(JSON.parse(modelsDevText)); - const defaults: Partial<Record<DextoProvider, string>> = { + const overlayProviderIds = [ + 'dexto-nova', + 'openai-compatible', + 'litellm', + 'glama', + 'local', + 'ollama', + ] as const; + + const defaults: Partial<Record<string, string>> = { openai: 'gpt-5-mini', anthropic: 'claude-haiku-4-5-20251001', google: 'gemini-3-flash-preview', @@ -353,218 +365,127 @@ async function syncLlmRegistry() { xai: 'grok-4', cohere: 'command-a-03-2025', minimax: 'MiniMax-M2.1', - 'minimax-cn': 'MiniMax-M2.1', - 'minimax-coding-plan': 'MiniMax-M2.1', - 'minimax-cn-coding-plan': 'MiniMax-M2.1', - glm: 'glm-4.7', zhipuai: 'glm-4.7', - 'zhipuai-coding-plan': 'glm-4.7', - zai: 'glm-4.7', - 'zai-coding-plan': 'glm-4.7', moonshotai: 'kimi-k2.5', - 'moonshotai-cn': 'kimi-k2.5', - 'kimi-for-coding': 'k2p5', - vertex: 'gemini-3-flash-preview', - bedrock: 'anthropic.claude-sonnet-4-5-20250929-v1:0', // gateway/dynamic providers intentionally omit defaults here }; - const include = { - openai: (id: string) => id.startsWith('gpt-') || id.startsWith('o'), - anthropic: (id: string) => id.startsWith('claude-'), - google: (id: string) => id.startsWith('gemini-'), - groq: (_id: string) => true, - xai: (id: string) => id.startsWith('grok-'), - cohere: (id: string) => id.startsWith('command-'), - minimax: (_id: string) => true, - 'minimax-cn': (_id: string) => true, - 'minimax-coding-plan': (_id: string) => true, - 'minimax-cn-coding-plan': (_id: string) => true, - glm: (id: string) => id.startsWith('glm-'), - zhipuai: (id: string) => id.startsWith('glm-'), - 'zhipuai-coding-plan': (id: string) => id.startsWith('glm-'), - zai: (id: string) => id.startsWith('glm-'), - 'zai-coding-plan': (id: string) => id.startsWith('glm-'), - moonshotai: (_id: string) => true, - 'moonshotai-cn': (_id: string) => true, - 'kimi-for-coding': (_id: string) => true, - vertex: (_id: string) => true, - bedrock: (_id: string) => true, - openrouter: (_id: string) => true, - } as const; + function includeModel(providerId: string, modelId: string): boolean { + if (providerId === 'openai') return modelId.startsWith('gpt-') || modelId.startsWith('o'); + if (providerId === 'anthropic') return modelId.startsWith('claude-'); + if (providerId === 'google') return modelId.startsWith('gemini-'); + if (providerId === 'xai') return modelId.startsWith('grok-'); + if (providerId === 'cohere') return modelId.startsWith('command-'); + return true; + } - const modelsByProvider: Record<DextoProvider, GeneratedModelInfo[]> = { - openai: buildModelsFromModelsDevProvider({ - provider: 'openai', - modelsDevApi: modelsDevJson, - modelsDevProviderId: 'openai', - defaultModelId: defaults.openai, - includeModelId: include.openai, - }), - 'openai-compatible': [], - anthropic: buildModelsFromModelsDevProvider({ - provider: 'anthropic', - modelsDevApi: modelsDevJson, - modelsDevProviderId: 'anthropic', - defaultModelId: defaults.anthropic, - includeModelId: include.anthropic, - }), - google: buildModelsFromModelsDevProvider({ - provider: 'google', - modelsDevApi: modelsDevJson, - modelsDevProviderId: 'google', - defaultModelId: defaults.google, - includeModelId: include.google, - }), - groq: buildModelsFromModelsDevProvider({ - provider: 'groq', - modelsDevApi: modelsDevJson, - modelsDevProviderId: 'groq', - defaultModelId: defaults.groq, - includeModelId: include.groq, - }), - xai: buildModelsFromModelsDevProvider({ - provider: 'xai', - modelsDevApi: modelsDevJson, - modelsDevProviderId: 'xai', - defaultModelId: defaults.xai, - includeModelId: include.xai, - }), - cohere: buildModelsFromModelsDevProvider({ - provider: 'cohere', - modelsDevApi: modelsDevJson, - modelsDevProviderId: 'cohere', - defaultModelId: defaults.cohere, - includeModelId: include.cohere, - }), - minimax: buildModelsFromModelsDevProvider({ - provider: 'minimax', - modelsDevApi: modelsDevJson, - modelsDevProviderId: 'minimax', - defaultModelId: defaults.minimax, - includeModelId: include.minimax, - }), - 'minimax-cn': buildModelsFromModelsDevProvider({ - provider: 'minimax-cn', - modelsDevApi: modelsDevJson, - modelsDevProviderId: 'minimax-cn', - defaultModelId: defaults['minimax-cn'], - includeModelId: include['minimax-cn'], - }), - 'minimax-coding-plan': buildModelsFromModelsDevProvider({ - provider: 'minimax-coding-plan', - modelsDevApi: modelsDevJson, - modelsDevProviderId: 'minimax-coding-plan', - defaultModelId: defaults['minimax-coding-plan'], - includeModelId: include['minimax-coding-plan'], - }), - 'minimax-cn-coding-plan': buildModelsFromModelsDevProvider({ - provider: 'minimax-cn-coding-plan', - modelsDevApi: modelsDevJson, - modelsDevProviderId: 'minimax-cn-coding-plan', - defaultModelId: defaults['minimax-cn-coding-plan'], - includeModelId: include['minimax-cn-coding-plan'], - }), - glm: buildModelsFromModelsDevProvider({ - provider: 'glm', - modelsDevApi: modelsDevJson, - modelsDevProviderId: 'zhipuai', - defaultModelId: defaults.glm, - includeModelId: include.glm, - }), - zhipuai: buildModelsFromModelsDevProvider({ - provider: 'zhipuai', - modelsDevApi: modelsDevJson, - modelsDevProviderId: 'zhipuai', - defaultModelId: defaults.zhipuai, - includeModelId: include.zhipuai, - }), - 'zhipuai-coding-plan': buildModelsFromModelsDevProvider({ - provider: 'zhipuai-coding-plan', - modelsDevApi: modelsDevJson, - modelsDevProviderId: 'zhipuai-coding-plan', - defaultModelId: defaults['zhipuai-coding-plan'], - includeModelId: include['zhipuai-coding-plan'], - }), - zai: buildModelsFromModelsDevProvider({ - provider: 'zai', - modelsDevApi: modelsDevJson, - modelsDevProviderId: 'zai', - defaultModelId: defaults.zai, - includeModelId: include.zai, - }), - 'zai-coding-plan': buildModelsFromModelsDevProvider({ - provider: 'zai-coding-plan', - modelsDevApi: modelsDevJson, - modelsDevProviderId: 'zai-coding-plan', - defaultModelId: defaults['zai-coding-plan'], - includeModelId: include['zai-coding-plan'], - }), - moonshotai: buildModelsFromModelsDevProvider({ - provider: 'moonshotai', - modelsDevApi: modelsDevJson, - modelsDevProviderId: 'moonshotai', - defaultModelId: defaults.moonshotai, - includeModelId: include.moonshotai, - }), - 'moonshotai-cn': buildModelsFromModelsDevProvider({ - provider: 'moonshotai-cn', - modelsDevApi: modelsDevJson, - modelsDevProviderId: 'moonshotai-cn', - defaultModelId: defaults['moonshotai-cn'], - includeModelId: include['moonshotai-cn'], - }), - 'kimi-for-coding': buildModelsFromModelsDevProvider({ - provider: 'kimi-for-coding', - modelsDevApi: modelsDevJson, - modelsDevProviderId: 'kimi-for-coding', - defaultModelId: defaults['kimi-for-coding'], - includeModelId: include['kimi-for-coding'], - }), - openrouter: buildModelsFromModelsDevProvider({ - provider: 'openrouter', - modelsDevApi: modelsDevJson, - modelsDevProviderId: 'openrouter', - defaultModelId: undefined, - includeModelId: include.openrouter, - }), - litellm: [], - glama: [], - vertex: [ - ...buildModelsFromModelsDevProvider({ - provider: 'vertex', - modelsDevApi: modelsDevJson, - modelsDevProviderId: 'google-vertex', - defaultModelId: defaults.vertex, - includeModelId: include.vertex, - }), - ...buildModelsFromModelsDevProvider({ - provider: 'vertex', - modelsDevApi: modelsDevJson, - modelsDevProviderId: 'google-vertex-anthropic', - defaultModelId: undefined, - includeModelId: include.vertex, - }), - ].sort((a, b) => a.name.localeCompare(b.name)), - bedrock: buildModelsFromModelsDevProvider({ - provider: 'bedrock', + const providerIds = Object.keys(modelsDevJson).sort(); + + const modelsByProvider: Record<string, GeneratedModelInfo[]> = {}; + for (const providerId of providerIds) { + const defaultModelId = defaults[providerId]; + const models = buildModelsFromModelsDevProvider({ + provider: providerId, modelsDevApi: modelsDevJson, - modelsDevProviderId: 'amazon-bedrock', - defaultModelId: defaults.bedrock, - includeModelId: include.bedrock, - }) - // Normalize AWS region-prefixed IDs to the canonical unprefixed ID. - .map((m) => ({ ...m, name: m.name.replace(/^(eu\\.|us\\.|global\\.)/i, '') })) - // De-dupe after stripping prefixes. - .filter((m, idx, arr) => arr.findIndex((x) => x.name === m.name) === idx) - .sort((a, b) => a.name.localeCompare(b.name)), - local: [], - ollama: [], - 'dexto-nova': [], - }; + modelsDevProviderId: providerId, + defaultModelId, + includeModelId: (modelId) => includeModel(providerId, modelId), + }); + + if (providerId === 'amazon-bedrock') { + modelsByProvider[providerId] = models + // Normalize AWS region-prefixed IDs to the canonical unprefixed ID. + .map((m) => ({ ...m, name: m.name.replace(/^(eu\\.|us\\.|global\\.)/i, '') })) + // De-dupe after stripping prefixes. + .filter((m, idx, arr) => arr.findIndex((x) => x.name === m.name) === idx) + .sort((a, b) => a.name.localeCompare(b.name)); + } else { + modelsByProvider[providerId] = models; + } + } - const header = `// This file is auto-generated by scripts/sync-llm-registry.ts\n// Do not edit manually - run 'pnpm run sync-llm-registry' to update\n`; - const body = ` + for (const overlayId of overlayProviderIds) { + modelsByProvider[overlayId] = []; + } + + const providersById: Record< + string, + { + id: string; + name: string; + env: string[]; + npm: string; + api?: string; + doc?: string; + } + > = {}; + + for (const providerId of providerIds) { + const p = modelsDevJson[providerId]!; + providersById[providerId] = { + id: p.id, + name: p.name, + env: p.env, + npm: p.npm, + ...(p.api ? { api: p.api } : {}), + ...(p.doc ? { doc: p.doc } : {}), + }; + } + + const overlayProviders = { + 'dexto-nova': { + id: 'dexto-nova', + name: 'Dexto Nova', + env: ['DEXTO_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://api.dexto.ai/v1', + doc: 'https://dexto.ai', + }, + 'openai-compatible': { + id: 'openai-compatible', + name: 'OpenAI Compatible (Custom)', + env: ['OPENAI_API_KEY', 'OPENAI_KEY'], + npm: '@ai-sdk/openai-compatible', + }, + litellm: { + id: 'litellm', + name: 'LiteLLM', + env: ['LITELLM_API_KEY', 'LITELLM_KEY'], + npm: '@ai-sdk/openai-compatible', + doc: 'https://docs.litellm.ai', + }, + glama: { + id: 'glama', + name: 'Glama', + env: ['GLAMA_API_KEY'], + npm: '@ai-sdk/openai-compatible', + api: 'https://glama.ai/api/gateway/openai/v1', + doc: 'https://glama.ai', + }, + local: { + id: 'local', + name: 'Local (GGUF)', + env: [], + npm: '@ai-sdk/openai-compatible', + }, + ollama: { + id: 'ollama', + name: 'Ollama', + env: [], + npm: '@ai-sdk/openai-compatible', + api: 'http://localhost:11434/v1', + doc: 'https://ollama.com', + }, + } as const; + + for (const [providerId, info] of Object.entries(overlayProviders)) { + providersById[providerId] = { ...info }; + } + + const llmProviders = Object.keys(providersById).sort(); + + const modelsHeader = `// This file is auto-generated by scripts/sync-llm-models.ts\n// Do not edit manually - run 'pnpm run sync-llm-models' to update\n`; + const modelsBody = ` import type { LLMProvider } from '../types.js'; import type { ModelInfo } from './index.js'; @@ -574,35 +495,80 @@ export const MODELS_BY_PROVIDER = ${JSON.stringify(modelsByProvider, null, 4)} s >; `; - const prettierConfig = (await prettier.resolveConfig(OUTPUT_PATH)) ?? undefined; - const formatted = await prettier.format(header + body, { + const providersHeader = `// This file is auto-generated by scripts/sync-llm-models.ts\n// Do not edit manually - run 'pnpm run sync-llm-models' to update\n`; + const providersBody = ` +export type ProviderSnapshotEntry = { + id: string; + name: string; + env: readonly string[]; + npm: string; + api?: string; + doc?: string; +}; + +export const PROVIDERS_BY_ID = ${JSON.stringify(providersById, null, 4)} as const satisfies Record< + string, + ProviderSnapshotEntry +>; + +export const LLM_PROVIDERS = ${JSON.stringify(llmProviders, null, 4)} as const; +`; + + const prettierConfig = (await prettier.resolveConfig(MODELS_OUTPUT_PATH)) ?? undefined; + const formattedModels = await prettier.format(modelsHeader + modelsBody, { + ...prettierConfig, + parser: 'typescript', + filepath: MODELS_OUTPUT_PATH, + }); + + const formattedProviders = await prettier.format(providersHeader + providersBody, { ...prettierConfig, parser: 'typescript', - filepath: OUTPUT_PATH, + filepath: PROVIDERS_OUTPUT_PATH, }); if (CHECK_MODE) { - if (!fs.existsSync(OUTPUT_PATH)) { + if (!fs.existsSync(MODELS_OUTPUT_PATH)) { + console.error( + `❌ Missing generated file: ${path.relative(process.cwd(), MODELS_OUTPUT_PATH)}` + ); + console.error(` Run: pnpm run sync-llm-models\n`); + process.exit(1); + } + if (!fs.existsSync(PROVIDERS_OUTPUT_PATH)) { console.error( - `❌ Missing generated file: ${path.relative(process.cwd(), OUTPUT_PATH)}` + `❌ Missing generated file: ${path.relative(process.cwd(), PROVIDERS_OUTPUT_PATH)}` ); - console.error(` Run: pnpm run sync-llm-registry\n`); + console.error(` Run: pnpm run sync-llm-models\n`); process.exit(1); } - const existing = fs.readFileSync(OUTPUT_PATH, 'utf-8'); - if (existing !== formatted) { + + const existingModels = fs.readFileSync(MODELS_OUTPUT_PATH, 'utf-8'); + if (existingModels !== formattedModels) { console.error('❌ LLM registry snapshot is out of date!'); - console.error(` File: ${path.relative(process.cwd(), OUTPUT_PATH)}`); - console.error(' Run: pnpm run sync-llm-registry\n'); + console.error(` File: ${path.relative(process.cwd(), MODELS_OUTPUT_PATH)}`); + console.error(' Run: pnpm run sync-llm-models\n'); + process.exit(1); + } + + const existingProviders = fs.readFileSync(PROVIDERS_OUTPUT_PATH, 'utf-8'); + if (existingProviders !== formattedProviders) { + console.error('❌ LLM provider snapshot is out of date!'); + console.error(` File: ${path.relative(process.cwd(), PROVIDERS_OUTPUT_PATH)}`); + console.error(' Run: pnpm run sync-llm-models\n'); process.exit(1); } console.log('✅ LLM registry snapshot is up-to-date'); return; } - fs.mkdirSync(path.dirname(OUTPUT_PATH), { recursive: true }); - fs.writeFileSync(OUTPUT_PATH, formatted, 'utf-8'); - console.log(`✓ Wrote ${path.relative(process.cwd(), OUTPUT_PATH)}`); + fs.mkdirSync(path.dirname(MODELS_OUTPUT_PATH), { recursive: true }); + fs.writeFileSync(MODELS_OUTPUT_PATH, formattedModels, 'utf-8'); + console.log(`✓ Wrote ${path.relative(process.cwd(), MODELS_OUTPUT_PATH)}`); + + fs.mkdirSync(path.dirname(PROVIDERS_OUTPUT_PATH), { recursive: true }); + fs.writeFileSync(PROVIDERS_OUTPUT_PATH, formattedProviders, 'utf-8'); + console.log(`✓ Wrote ${path.relative(process.cwd(), PROVIDERS_OUTPUT_PATH)}`); } syncLlmRegistry().catch((err) => { From 14812fd2f4b4d97604398612646032cbbed76bdf Mon Sep 17 00:00:00 2001 From: Rahul Karajgikar <rahul@trytruffle.ai> Date: Mon, 23 Feb 2026 23:30:33 +0530 Subject: [PATCH 24/25] docs: sync openapi + update llm sync script name --- AGENTS.md | 6 +- docs/static/openapi/openapi.json | 11331 ++++++++++++++++++++++++++++- 2 files changed, 10995 insertions(+), 342 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index f59e75e3f..4661c4e19 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -119,9 +119,9 @@ Dexto infers its execution environment to enable context-aware defaults and path Dexto’s supported models live in core and are primarily sourced from `models.dev`. - **Registry source of truth:** `packages/core/src/llm/registry/index.ts` (consumes the generated snapshot + any manual overlays). -- **Generated snapshot:** `packages/core/src/llm/registry/models.generated.ts` (generated from `models.dev` via `scripts/sync-llm-registry.ts`). - - Update: `pnpm run sync-llm-registry` - - Verify clean repo (CI-style): `pnpm run sync-llm-registry:check` +- **Generated snapshot:** `packages/core/src/llm/registry/models.generated.ts` (generated from `models.dev` via `scripts/sync-llm-models.ts`). + - Update: `pnpm run sync-llm-models` + - Verify clean repo (CI-style): `pnpm run sync-llm-models:check` - **Gateway transform validation:** `packages/core/src/llm/registry/index.test.ts` includes a full-sweep check that our native→OpenRouter ID transform still matches the committed OpenRouter catalog snapshot (runs in `pnpm test`; catches naming drift like Anthropic dotted versions or Gemini `-001`). - **Manual overlays / missing models:** `packages/core/src/llm/registry/models.manual.ts` (e.g. models missing capability metadata upstream). - **Curation for UI/onboarding:** `packages/core/src/llm/curation-config.ts` (explicit curated model IDs; used by `/llm/catalog?scope=curated` and default pickers). diff --git a/docs/static/openapi/openapi.json b/docs/static/openapi/openapi.json index 22fbe93c3..685524937 100644 --- a/docs/static/openapi/openapi.json +++ b/docs/static/openapi/openapi.json @@ -2813,33 +2813,108 @@ "provider": { "type": "string", "enum": [ - "openai", - "openai-compatible", + "302ai", + "abacus", + "aihubmix", + "alibaba", + "alibaba-cn", + "amazon-bedrock", "anthropic", + "azure", + "azure-cognitive-services", + "bailing", + "baseten", + "berget", + "cerebras", + "chutes", + "cloudferro-sherlock", + "cloudflare-ai-gateway", + "cloudflare-workers-ai", + "cohere", + "cortecs", + "deepinfra", + "deepseek", + "dexto-nova", + "evroc", + "fastrouter", + "fireworks-ai", + "firmware", + "friendli", + "github-copilot", + "github-models", + "gitlab", + "glama", "google", + "google-vertex", + "google-vertex-anthropic", "groq", - "xai", - "cohere", + "helicone", + "huggingface", + "iflowcn", + "inception", + "inference", + "io-net", + "jiekou", + "kilo", + "kimi-for-coding", + "kuae-cloud-coding-plan", + "litellm", + "llama", + "lmstudio", + "local", + "lucidquery", + "meganova", "minimax", "minimax-cn", - "minimax-coding-plan", "minimax-cn-coding-plan", - "glm", - "zhipuai", - "zhipuai-coding-plan", - "zai", - "zai-coding-plan", + "minimax-coding-plan", + "mistral", + "moark", + "modelscope", "moonshotai", "moonshotai-cn", - "kimi-for-coding", - "openrouter", - "litellm", - "glama", - "vertex", - "bedrock", - "local", + "morph", + "nano-gpt", + "nebius", + "nova", + "novita-ai", + "nvidia", "ollama", - "dexto-nova" + "ollama-cloud", + "openai", + "openai-compatible", + "opencode", + "openrouter", + "ovhcloud", + "perplexity", + "poe", + "privatemode-ai", + "qihang-ai", + "qiniu-ai", + "requesty", + "sap-ai-core", + "scaleway", + "siliconflow", + "siliconflow-cn", + "stackit", + "stepfun", + "submodel", + "synthetic", + "togetherai", + "upstage", + "v0", + "venice", + "vercel", + "vivgrid", + "vultr", + "wandb", + "xai", + "xiaomi", + "zai", + "zai-coding-plan", + "zenmux", + "zhipuai", + "zhipuai-coding-plan" ], "description": "LLM provider" } @@ -3154,33 +3229,108 @@ "provider": { "type": "string", "enum": [ - "openai", - "openai-compatible", + "302ai", + "abacus", + "aihubmix", + "alibaba", + "alibaba-cn", + "amazon-bedrock", "anthropic", + "azure", + "azure-cognitive-services", + "bailing", + "baseten", + "berget", + "cerebras", + "chutes", + "cloudferro-sherlock", + "cloudflare-ai-gateway", + "cloudflare-workers-ai", + "cohere", + "cortecs", + "deepinfra", + "deepseek", + "dexto-nova", + "evroc", + "fastrouter", + "fireworks-ai", + "firmware", + "friendli", + "github-copilot", + "github-models", + "gitlab", + "glama", "google", + "google-vertex", + "google-vertex-anthropic", "groq", - "xai", - "cohere", + "helicone", + "huggingface", + "iflowcn", + "inception", + "inference", + "io-net", + "jiekou", + "kilo", + "kimi-for-coding", + "kuae-cloud-coding-plan", + "litellm", + "llama", + "lmstudio", + "local", + "lucidquery", + "meganova", "minimax", "minimax-cn", - "minimax-coding-plan", "minimax-cn-coding-plan", - "glm", - "zhipuai", - "zhipuai-coding-plan", - "zai", - "zai-coding-plan", + "minimax-coding-plan", + "mistral", + "moark", + "modelscope", "moonshotai", "moonshotai-cn", - "kimi-for-coding", - "openrouter", - "litellm", - "glama", - "vertex", - "bedrock", - "local", + "morph", + "nano-gpt", + "nebius", + "nova", + "novita-ai", + "nvidia", "ollama", - "dexto-nova" + "ollama-cloud", + "openai", + "openai-compatible", + "opencode", + "openrouter", + "ovhcloud", + "perplexity", + "poe", + "privatemode-ai", + "qihang-ai", + "qiniu-ai", + "requesty", + "sap-ai-core", + "scaleway", + "siliconflow", + "siliconflow-cn", + "stackit", + "stepfun", + "submodel", + "synthetic", + "togetherai", + "upstage", + "v0", + "venice", + "vercel", + "vivgrid", + "vultr", + "wandb", + "xai", + "xiaomi", + "zai", + "zai-coding-plan", + "zenmux", + "zhipuai", + "zhipuai-coding-plan" ], "description": "LLM provider (e.g., 'openai', 'anthropic', 'google', 'groq')" }, @@ -3470,7 +3620,7 @@ "providers": { "type": "object", "properties": { - "openai": { + "302ai": { "type": "object", "properties": { "name": { @@ -3599,7 +3749,7 @@ "additionalProperties": false, "description": "Provider catalog entry with models and capabilities" }, - "openai-compatible": { + "abacus": { "type": "object", "properties": { "name": { @@ -3728,7 +3878,7 @@ "additionalProperties": false, "description": "Provider catalog entry with models and capabilities" }, - "anthropic": { + "aihubmix": { "type": "object", "properties": { "name": { @@ -3857,7 +4007,7 @@ "additionalProperties": false, "description": "Provider catalog entry with models and capabilities" }, - "google": { + "alibaba": { "type": "object", "properties": { "name": { @@ -3986,7 +4136,7 @@ "additionalProperties": false, "description": "Provider catalog entry with models and capabilities" }, - "groq": { + "alibaba-cn": { "type": "object", "properties": { "name": { @@ -4115,7 +4265,7 @@ "additionalProperties": false, "description": "Provider catalog entry with models and capabilities" }, - "xai": { + "amazon-bedrock": { "type": "object", "properties": { "name": { @@ -4244,7 +4394,7 @@ "additionalProperties": false, "description": "Provider catalog entry with models and capabilities" }, - "cohere": { + "anthropic": { "type": "object", "properties": { "name": { @@ -4373,7 +4523,7 @@ "additionalProperties": false, "description": "Provider catalog entry with models and capabilities" }, - "minimax": { + "azure": { "type": "object", "properties": { "name": { @@ -4502,7 +4652,7 @@ "additionalProperties": false, "description": "Provider catalog entry with models and capabilities" }, - "minimax-cn": { + "azure-cognitive-services": { "type": "object", "properties": { "name": { @@ -4631,7 +4781,7 @@ "additionalProperties": false, "description": "Provider catalog entry with models and capabilities" }, - "minimax-coding-plan": { + "bailing": { "type": "object", "properties": { "name": { @@ -4760,7 +4910,7 @@ "additionalProperties": false, "description": "Provider catalog entry with models and capabilities" }, - "minimax-cn-coding-plan": { + "baseten": { "type": "object", "properties": { "name": { @@ -4889,7 +5039,7 @@ "additionalProperties": false, "description": "Provider catalog entry with models and capabilities" }, - "glm": { + "berget": { "type": "object", "properties": { "name": { @@ -5018,7 +5168,7 @@ "additionalProperties": false, "description": "Provider catalog entry with models and capabilities" }, - "zhipuai": { + "cerebras": { "type": "object", "properties": { "name": { @@ -5147,7 +5297,7 @@ "additionalProperties": false, "description": "Provider catalog entry with models and capabilities" }, - "zhipuai-coding-plan": { + "chutes": { "type": "object", "properties": { "name": { @@ -5276,7 +5426,7 @@ "additionalProperties": false, "description": "Provider catalog entry with models and capabilities" }, - "zai": { + "cloudferro-sherlock": { "type": "object", "properties": { "name": { @@ -5405,7 +5555,7 @@ "additionalProperties": false, "description": "Provider catalog entry with models and capabilities" }, - "zai-coding-plan": { + "cloudflare-ai-gateway": { "type": "object", "properties": { "name": { @@ -5534,7 +5684,7 @@ "additionalProperties": false, "description": "Provider catalog entry with models and capabilities" }, - "moonshotai": { + "cloudflare-workers-ai": { "type": "object", "properties": { "name": { @@ -5663,7 +5813,7 @@ "additionalProperties": false, "description": "Provider catalog entry with models and capabilities" }, - "moonshotai-cn": { + "cohere": { "type": "object", "properties": { "name": { @@ -5792,7 +5942,7 @@ "additionalProperties": false, "description": "Provider catalog entry with models and capabilities" }, - "kimi-for-coding": { + "cortecs": { "type": "object", "properties": { "name": { @@ -5921,7 +6071,7 @@ "additionalProperties": false, "description": "Provider catalog entry with models and capabilities" }, - "openrouter": { + "deepinfra": { "type": "object", "properties": { "name": { @@ -6050,7 +6200,7 @@ "additionalProperties": false, "description": "Provider catalog entry with models and capabilities" }, - "litellm": { + "deepseek": { "type": "object", "properties": { "name": { @@ -6179,7 +6329,7 @@ "additionalProperties": false, "description": "Provider catalog entry with models and capabilities" }, - "glama": { + "dexto-nova": { "type": "object", "properties": { "name": { @@ -6308,7 +6458,7 @@ "additionalProperties": false, "description": "Provider catalog entry with models and capabilities" }, - "vertex": { + "evroc": { "type": "object", "properties": { "name": { @@ -6437,7 +6587,7 @@ "additionalProperties": false, "description": "Provider catalog entry with models and capabilities" }, - "bedrock": { + "fastrouter": { "type": "object", "properties": { "name": { @@ -6566,7 +6716,7 @@ "additionalProperties": false, "description": "Provider catalog entry with models and capabilities" }, - "local": { + "fireworks-ai": { "type": "object", "properties": { "name": { @@ -6695,7 +6845,7 @@ "additionalProperties": false, "description": "Provider catalog entry with models and capabilities" }, - "ollama": { + "firmware": { "type": "object", "properties": { "name": { @@ -6824,7 +6974,7 @@ "additionalProperties": false, "description": "Provider catalog entry with models and capabilities" }, - "dexto-nova": { + "friendli": { "type": "object", "properties": { "name": { @@ -6952,82 +7102,9757 @@ ], "additionalProperties": false, "description": "Provider catalog entry with models and capabilities" - } - }, - "description": "Providers grouped by ID with their models and capabilities" - } - }, - "required": [ - "providers" - ], - "additionalProperties": false, - "description": "Grouped catalog response (mode=grouped)" - }, - { - "type": "object", - "properties": { - "models": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Model name identifier" - }, - "maxInputTokens": { - "type": "integer", - "minimum": 0, - "exclusiveMinimum": true, - "description": "Maximum input tokens" - }, - "default": { - "type": "boolean", - "description": "Whether this is a default model" - }, - "supportedFileTypes": { - "type": "array", - "items": { + }, + "github-copilot": { + "type": "object", + "properties": { + "name": { "type": "string", - "enum": [ - "audio", - "pdf", - "image" - ] + "description": "Provider display name" }, - "description": "File types this model supports" - }, - "displayName": { - "type": "string", - "description": "Human-readable display name" - }, - "pricing": { - "type": "object", - "properties": { - "inputPerM": { - "type": "number", - "description": "Input cost per million tokens (USD)" - }, - "outputPerM": { - "type": "number", - "description": "Output cost per million tokens (USD)" - }, - "cacheReadPerM": { - "type": "number", - "description": "Cache read cost per million tokens" - }, - "cacheWritePerM": { - "type": "number", - "description": "Cache write cost per million tokens" - }, - "currency": { - "type": "string", - "enum": [ - "USD" + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" ], - "description": "Currency" + "additionalProperties": false, + "description": "Model information from LLM registry" }, - "unit": { + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "github-models": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "gitlab": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "glama": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "google": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "google-vertex": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "google-vertex-anthropic": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "groq": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "helicone": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "huggingface": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "iflowcn": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "inception": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "inference": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "io-net": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "jiekou": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "kilo": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "kimi-for-coding": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "kuae-cloud-coding-plan": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "litellm": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "llama": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "lmstudio": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "local": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "lucidquery": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "meganova": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "minimax": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "minimax-cn": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "minimax-cn-coding-plan": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "minimax-coding-plan": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "mistral": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "moark": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "modelscope": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "moonshotai": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "moonshotai-cn": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "morph": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "nano-gpt": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "nebius": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "nova": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "novita-ai": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "nvidia": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "ollama": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "ollama-cloud": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "openai": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "openai-compatible": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "opencode": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "openrouter": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "ovhcloud": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "perplexity": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "poe": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "privatemode-ai": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "qihang-ai": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "qiniu-ai": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "requesty": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "sap-ai-core": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "scaleway": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "siliconflow": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "siliconflow-cn": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "stackit": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "stepfun": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "submodel": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "synthetic": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "togetherai": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "upstage": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "v0": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "venice": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "vercel": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "vivgrid": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "vultr": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "wandb": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "xai": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "xiaomi": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "zai": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "zai-coding-plan": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "zenmux": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "zhipuai": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + }, + "zhipuai-coding-plan": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider display name" + }, + "hasApiKey": { + "type": "boolean", + "description": "Whether API key is configured" + }, + "primaryEnvVar": { + "type": "string", + "description": "Primary environment variable for API key" + }, + "supportsBaseURL": { + "type": "boolean", + "description": "Whether custom base URLs are supported" + }, + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { + "type": "string", + "enum": [ + "per_million_tokens" + ], + "description": "Unit" + } + }, + "required": [ + "inputPerM", + "outputPerM" + ], + "description": "Pricing information in USD per million tokens" + } + }, + "required": [ + "name", + "maxInputTokens", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Model information from LLM registry" + }, + "description": "Models available from this provider" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "Provider-level file type support" + } + }, + "required": [ + "name", + "hasApiKey", + "primaryEnvVar", + "supportsBaseURL", + "models", + "supportedFileTypes" + ], + "additionalProperties": false, + "description": "Provider catalog entry with models and capabilities" + } + }, + "description": "Providers grouped by ID with their models and capabilities" + } + }, + "required": [ + "providers" + ], + "additionalProperties": false, + "description": "Grouped catalog response (mode=grouped)" + }, + { + "type": "object", + "properties": { + "models": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Model name identifier" + }, + "maxInputTokens": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Maximum input tokens" + }, + "default": { + "type": "boolean", + "description": "Whether this is a default model" + }, + "supportedFileTypes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "audio", + "pdf", + "image" + ] + }, + "description": "File types this model supports" + }, + "displayName": { + "type": "string", + "description": "Human-readable display name" + }, + "pricing": { + "type": "object", + "properties": { + "inputPerM": { + "type": "number", + "description": "Input cost per million tokens (USD)" + }, + "outputPerM": { + "type": "number", + "description": "Output cost per million tokens (USD)" + }, + "cacheReadPerM": { + "type": "number", + "description": "Cache read cost per million tokens" + }, + "cacheWritePerM": { + "type": "number", + "description": "Cache write cost per million tokens" + }, + "currency": { + "type": "string", + "enum": [ + "USD" + ], + "description": "Currency" + }, + "unit": { "type": "string", "enum": [ "per_million_tokens" @@ -7091,33 +16916,108 @@ "provider": { "type": "string", "enum": [ - "openai", - "openai-compatible", + "302ai", + "abacus", + "aihubmix", + "alibaba", + "alibaba-cn", + "amazon-bedrock", "anthropic", + "azure", + "azure-cognitive-services", + "bailing", + "baseten", + "berget", + "cerebras", + "chutes", + "cloudferro-sherlock", + "cloudflare-ai-gateway", + "cloudflare-workers-ai", + "cohere", + "cortecs", + "deepinfra", + "deepseek", + "dexto-nova", + "evroc", + "fastrouter", + "fireworks-ai", + "firmware", + "friendli", + "github-copilot", + "github-models", + "gitlab", + "glama", "google", + "google-vertex", + "google-vertex-anthropic", "groq", - "xai", - "cohere", + "helicone", + "huggingface", + "iflowcn", + "inception", + "inference", + "io-net", + "jiekou", + "kilo", + "kimi-for-coding", + "kuae-cloud-coding-plan", + "litellm", + "llama", + "lmstudio", + "local", + "lucidquery", + "meganova", "minimax", "minimax-cn", - "minimax-coding-plan", "minimax-cn-coding-plan", - "glm", - "zhipuai", - "zhipuai-coding-plan", - "zai", - "zai-coding-plan", + "minimax-coding-plan", + "mistral", + "moark", + "modelscope", "moonshotai", "moonshotai-cn", - "kimi-for-coding", - "openrouter", - "litellm", - "glama", - "vertex", - "bedrock", - "local", + "morph", + "nano-gpt", + "nebius", + "nova", + "novita-ai", + "nvidia", "ollama", - "dexto-nova" + "ollama-cloud", + "openai", + "openai-compatible", + "opencode", + "openrouter", + "ovhcloud", + "perplexity", + "poe", + "privatemode-ai", + "qihang-ai", + "qiniu-ai", + "requesty", + "sap-ai-core", + "scaleway", + "siliconflow", + "siliconflow-cn", + "stackit", + "stepfun", + "submodel", + "synthetic", + "togetherai", + "upstage", + "v0", + "venice", + "vercel", + "vivgrid", + "vultr", + "wandb", + "xai", + "xiaomi", + "zai", + "zai-coding-plan", + "zenmux", + "zhipuai", + "zhipuai-coding-plan" ], "description": "LLM provider (e.g., 'openai', 'anthropic', 'google', 'groq')" }, @@ -7208,33 +17108,108 @@ "provider": { "type": "string", "enum": [ - "openai", - "openai-compatible", + "302ai", + "abacus", + "aihubmix", + "alibaba", + "alibaba-cn", + "amazon-bedrock", "anthropic", + "azure", + "azure-cognitive-services", + "bailing", + "baseten", + "berget", + "cerebras", + "chutes", + "cloudferro-sherlock", + "cloudflare-ai-gateway", + "cloudflare-workers-ai", + "cohere", + "cortecs", + "deepinfra", + "deepseek", + "dexto-nova", + "evroc", + "fastrouter", + "fireworks-ai", + "firmware", + "friendli", + "github-copilot", + "github-models", + "gitlab", + "glama", "google", + "google-vertex", + "google-vertex-anthropic", "groq", - "xai", - "cohere", + "helicone", + "huggingface", + "iflowcn", + "inception", + "inference", + "io-net", + "jiekou", + "kilo", + "kimi-for-coding", + "kuae-cloud-coding-plan", + "litellm", + "llama", + "lmstudio", + "local", + "lucidquery", + "meganova", "minimax", "minimax-cn", - "minimax-coding-plan", "minimax-cn-coding-plan", - "glm", - "zhipuai", - "zhipuai-coding-plan", - "zai", - "zai-coding-plan", + "minimax-coding-plan", + "mistral", + "moark", + "modelscope", "moonshotai", "moonshotai-cn", - "kimi-for-coding", - "openrouter", - "litellm", - "glama", - "vertex", - "bedrock", - "local", + "morph", + "nano-gpt", + "nebius", + "nova", + "novita-ai", + "nvidia", "ollama", - "dexto-nova" + "ollama-cloud", + "openai", + "openai-compatible", + "opencode", + "openrouter", + "ovhcloud", + "perplexity", + "poe", + "privatemode-ai", + "qihang-ai", + "qiniu-ai", + "requesty", + "sap-ai-core", + "scaleway", + "siliconflow", + "siliconflow-cn", + "stackit", + "stepfun", + "submodel", + "synthetic", + "togetherai", + "upstage", + "v0", + "venice", + "vercel", + "vivgrid", + "vultr", + "wandb", + "xai", + "xiaomi", + "zai", + "zai-coding-plan", + "zenmux", + "zhipuai", + "zhipuai-coding-plan" ], "description": "LLM provider (e.g., 'openai', 'anthropic', 'google', 'groq')" }, @@ -7349,10 +17324,11 @@ "openrouter", "litellm", "glama", - "bedrock", + "amazon-bedrock", "ollama", "local", - "vertex", + "google-vertex", + "google-vertex-anthropic", "dexto-nova" ], "default": "openai-compatible" @@ -7431,10 +17407,11 @@ "openrouter", "litellm", "glama", - "bedrock", + "amazon-bedrock", "ollama", "local", - "vertex", + "google-vertex", + "google-vertex-anthropic", "dexto-nova" ], "default": "openai-compatible" @@ -7510,10 +17487,11 @@ "openrouter", "litellm", "glama", - "bedrock", + "amazon-bedrock", "ollama", "local", - "vertex", + "google-vertex", + "google-vertex-anthropic", "dexto-nova" ], "default": "openai-compatible" @@ -7659,33 +17637,108 @@ "schema": { "type": "string", "enum": [ - "openai", - "openai-compatible", + "302ai", + "abacus", + "aihubmix", + "alibaba", + "alibaba-cn", + "amazon-bedrock", "anthropic", + "azure", + "azure-cognitive-services", + "bailing", + "baseten", + "berget", + "cerebras", + "chutes", + "cloudferro-sherlock", + "cloudflare-ai-gateway", + "cloudflare-workers-ai", + "cohere", + "cortecs", + "deepinfra", + "deepseek", + "dexto-nova", + "evroc", + "fastrouter", + "fireworks-ai", + "firmware", + "friendli", + "github-copilot", + "github-models", + "gitlab", + "glama", "google", + "google-vertex", + "google-vertex-anthropic", "groq", - "xai", - "cohere", + "helicone", + "huggingface", + "iflowcn", + "inception", + "inference", + "io-net", + "jiekou", + "kilo", + "kimi-for-coding", + "kuae-cloud-coding-plan", + "litellm", + "llama", + "lmstudio", + "local", + "lucidquery", + "meganova", "minimax", "minimax-cn", - "minimax-coding-plan", "minimax-cn-coding-plan", - "glm", - "zhipuai", - "zhipuai-coding-plan", - "zai", - "zai-coding-plan", + "minimax-coding-plan", + "mistral", + "moark", + "modelscope", "moonshotai", "moonshotai-cn", - "kimi-for-coding", - "openrouter", - "litellm", - "glama", - "vertex", - "bedrock", - "local", + "morph", + "nano-gpt", + "nebius", + "nova", + "novita-ai", + "nvidia", "ollama", - "dexto-nova" + "ollama-cloud", + "openai", + "openai-compatible", + "opencode", + "openrouter", + "ovhcloud", + "perplexity", + "poe", + "privatemode-ai", + "qihang-ai", + "qiniu-ai", + "requesty", + "sap-ai-core", + "scaleway", + "siliconflow", + "siliconflow-cn", + "stackit", + "stepfun", + "submodel", + "synthetic", + "togetherai", + "upstage", + "v0", + "venice", + "vercel", + "vivgrid", + "vultr", + "wandb", + "xai", + "xiaomi", + "zai", + "zai-coding-plan", + "zenmux", + "zhipuai", + "zhipuai-coding-plan" ], "description": "LLM provider name" }, @@ -7717,33 +17770,108 @@ "provider": { "type": "string", "enum": [ - "openai", - "openai-compatible", + "302ai", + "abacus", + "aihubmix", + "alibaba", + "alibaba-cn", + "amazon-bedrock", "anthropic", + "azure", + "azure-cognitive-services", + "bailing", + "baseten", + "berget", + "cerebras", + "chutes", + "cloudferro-sherlock", + "cloudflare-ai-gateway", + "cloudflare-workers-ai", + "cohere", + "cortecs", + "deepinfra", + "deepseek", + "dexto-nova", + "evroc", + "fastrouter", + "fireworks-ai", + "firmware", + "friendli", + "github-copilot", + "github-models", + "gitlab", + "glama", "google", + "google-vertex", + "google-vertex-anthropic", "groq", - "xai", - "cohere", + "helicone", + "huggingface", + "iflowcn", + "inception", + "inference", + "io-net", + "jiekou", + "kilo", + "kimi-for-coding", + "kuae-cloud-coding-plan", + "litellm", + "llama", + "lmstudio", + "local", + "lucidquery", + "meganova", "minimax", "minimax-cn", - "minimax-coding-plan", "minimax-cn-coding-plan", - "glm", - "zhipuai", - "zhipuai-coding-plan", - "zai", - "zai-coding-plan", + "minimax-coding-plan", + "mistral", + "moark", + "modelscope", "moonshotai", "moonshotai-cn", - "kimi-for-coding", - "openrouter", - "litellm", - "glama", - "vertex", - "bedrock", - "local", + "morph", + "nano-gpt", + "nebius", + "nova", + "novita-ai", + "nvidia", "ollama", - "dexto-nova" + "ollama-cloud", + "openai", + "openai-compatible", + "opencode", + "openrouter", + "ovhcloud", + "perplexity", + "poe", + "privatemode-ai", + "qihang-ai", + "qiniu-ai", + "requesty", + "sap-ai-core", + "scaleway", + "siliconflow", + "siliconflow-cn", + "stackit", + "stepfun", + "submodel", + "synthetic", + "togetherai", + "upstage", + "v0", + "venice", + "vercel", + "vivgrid", + "vultr", + "wandb", + "xai", + "xiaomi", + "zai", + "zai-coding-plan", + "zenmux", + "zhipuai", + "zhipuai-coding-plan" ], "description": "Provider name" }, @@ -9020,33 +19148,108 @@ "provider": { "type": "string", "enum": [ - "openai", - "openai-compatible", + "302ai", + "abacus", + "aihubmix", + "alibaba", + "alibaba-cn", + "amazon-bedrock", "anthropic", + "azure", + "azure-cognitive-services", + "bailing", + "baseten", + "berget", + "cerebras", + "chutes", + "cloudferro-sherlock", + "cloudflare-ai-gateway", + "cloudflare-workers-ai", + "cohere", + "cortecs", + "deepinfra", + "deepseek", + "dexto-nova", + "evroc", + "fastrouter", + "fireworks-ai", + "firmware", + "friendli", + "github-copilot", + "github-models", + "gitlab", + "glama", "google", + "google-vertex", + "google-vertex-anthropic", "groq", - "xai", - "cohere", + "helicone", + "huggingface", + "iflowcn", + "inception", + "inference", + "io-net", + "jiekou", + "kilo", + "kimi-for-coding", + "kuae-cloud-coding-plan", + "litellm", + "llama", + "lmstudio", + "local", + "lucidquery", + "meganova", "minimax", "minimax-cn", - "minimax-coding-plan", "minimax-cn-coding-plan", - "glm", - "zhipuai", - "zhipuai-coding-plan", - "zai", - "zai-coding-plan", + "minimax-coding-plan", + "mistral", + "moark", + "modelscope", "moonshotai", "moonshotai-cn", - "kimi-for-coding", - "openrouter", - "litellm", - "glama", - "vertex", - "bedrock", - "local", + "morph", + "nano-gpt", + "nebius", + "nova", + "novita-ai", + "nvidia", "ollama", - "dexto-nova" + "ollama-cloud", + "openai", + "openai-compatible", + "opencode", + "openrouter", + "ovhcloud", + "perplexity", + "poe", + "privatemode-ai", + "qihang-ai", + "qiniu-ai", + "requesty", + "sap-ai-core", + "scaleway", + "siliconflow", + "siliconflow-cn", + "stackit", + "stepfun", + "submodel", + "synthetic", + "togetherai", + "upstage", + "v0", + "venice", + "vercel", + "vivgrid", + "vultr", + "wandb", + "xai", + "xiaomi", + "zai", + "zai-coding-plan", + "zenmux", + "zhipuai", + "zhipuai-coding-plan" ], "description": "Provider identifier for assistant messages" }, @@ -9833,33 +20036,108 @@ "provider": { "type": "string", "enum": [ - "openai", - "openai-compatible", + "302ai", + "abacus", + "aihubmix", + "alibaba", + "alibaba-cn", + "amazon-bedrock", "anthropic", + "azure", + "azure-cognitive-services", + "bailing", + "baseten", + "berget", + "cerebras", + "chutes", + "cloudferro-sherlock", + "cloudflare-ai-gateway", + "cloudflare-workers-ai", + "cohere", + "cortecs", + "deepinfra", + "deepseek", + "dexto-nova", + "evroc", + "fastrouter", + "fireworks-ai", + "firmware", + "friendli", + "github-copilot", + "github-models", + "gitlab", + "glama", "google", + "google-vertex", + "google-vertex-anthropic", "groq", - "xai", - "cohere", + "helicone", + "huggingface", + "iflowcn", + "inception", + "inference", + "io-net", + "jiekou", + "kilo", + "kimi-for-coding", + "kuae-cloud-coding-plan", + "litellm", + "llama", + "lmstudio", + "local", + "lucidquery", + "meganova", "minimax", "minimax-cn", - "minimax-coding-plan", "minimax-cn-coding-plan", - "glm", - "zhipuai", - "zhipuai-coding-plan", - "zai", - "zai-coding-plan", + "minimax-coding-plan", + "mistral", + "moark", + "modelscope", "moonshotai", "moonshotai-cn", - "kimi-for-coding", - "openrouter", - "litellm", - "glama", - "vertex", - "bedrock", - "local", + "morph", + "nano-gpt", + "nebius", + "nova", + "novita-ai", + "nvidia", "ollama", - "dexto-nova" + "ollama-cloud", + "openai", + "openai-compatible", + "opencode", + "openrouter", + "ovhcloud", + "perplexity", + "poe", + "privatemode-ai", + "qihang-ai", + "qiniu-ai", + "requesty", + "sap-ai-core", + "scaleway", + "siliconflow", + "siliconflow-cn", + "stackit", + "stepfun", + "submodel", + "synthetic", + "togetherai", + "upstage", + "v0", + "venice", + "vercel", + "vivgrid", + "vultr", + "wandb", + "xai", + "xiaomi", + "zai", + "zai-coding-plan", + "zenmux", + "zhipuai", + "zhipuai-coding-plan" ], "description": "Provider identifier for assistant messages" }, @@ -10261,33 +20539,108 @@ "provider": { "type": "string", "enum": [ - "openai", - "openai-compatible", + "302ai", + "abacus", + "aihubmix", + "alibaba", + "alibaba-cn", + "amazon-bedrock", "anthropic", + "azure", + "azure-cognitive-services", + "bailing", + "baseten", + "berget", + "cerebras", + "chutes", + "cloudferro-sherlock", + "cloudflare-ai-gateway", + "cloudflare-workers-ai", + "cohere", + "cortecs", + "deepinfra", + "deepseek", + "dexto-nova", + "evroc", + "fastrouter", + "fireworks-ai", + "firmware", + "friendli", + "github-copilot", + "github-models", + "gitlab", + "glama", "google", + "google-vertex", + "google-vertex-anthropic", "groq", - "xai", - "cohere", + "helicone", + "huggingface", + "iflowcn", + "inception", + "inference", + "io-net", + "jiekou", + "kilo", + "kimi-for-coding", + "kuae-cloud-coding-plan", + "litellm", + "llama", + "lmstudio", + "local", + "lucidquery", + "meganova", "minimax", "minimax-cn", - "minimax-coding-plan", "minimax-cn-coding-plan", - "glm", - "zhipuai", - "zhipuai-coding-plan", - "zai", - "zai-coding-plan", + "minimax-coding-plan", + "mistral", + "moark", + "modelscope", "moonshotai", "moonshotai-cn", - "kimi-for-coding", - "openrouter", - "litellm", - "glama", - "vertex", - "bedrock", - "local", + "morph", + "nano-gpt", + "nebius", + "nova", + "novita-ai", + "nvidia", "ollama", - "dexto-nova" + "ollama-cloud", + "openai", + "openai-compatible", + "opencode", + "openrouter", + "ovhcloud", + "perplexity", + "poe", + "privatemode-ai", + "qihang-ai", + "qiniu-ai", + "requesty", + "sap-ai-core", + "scaleway", + "siliconflow", + "siliconflow-cn", + "stackit", + "stepfun", + "submodel", + "synthetic", + "togetherai", + "upstage", + "v0", + "venice", + "vercel", + "vivgrid", + "vultr", + "wandb", + "xai", + "xiaomi", + "zai", + "zai-coding-plan", + "zenmux", + "zhipuai", + "zhipuai-coding-plan" ], "description": "Provider identifier for assistant messages" }, @@ -15466,33 +25819,108 @@ "schema": { "type": "string", "enum": [ - "openai", - "openai-compatible", + "302ai", + "abacus", + "aihubmix", + "alibaba", + "alibaba-cn", + "amazon-bedrock", "anthropic", + "azure", + "azure-cognitive-services", + "bailing", + "baseten", + "berget", + "cerebras", + "chutes", + "cloudferro-sherlock", + "cloudflare-ai-gateway", + "cloudflare-workers-ai", + "cohere", + "cortecs", + "deepinfra", + "deepseek", + "dexto-nova", + "evroc", + "fastrouter", + "fireworks-ai", + "firmware", + "friendli", + "github-copilot", + "github-models", + "gitlab", + "glama", "google", + "google-vertex", + "google-vertex-anthropic", "groq", - "xai", - "cohere", + "helicone", + "huggingface", + "iflowcn", + "inception", + "inference", + "io-net", + "jiekou", + "kilo", + "kimi-for-coding", + "kuae-cloud-coding-plan", + "litellm", + "llama", + "lmstudio", + "local", + "lucidquery", + "meganova", "minimax", "minimax-cn", - "minimax-coding-plan", "minimax-cn-coding-plan", - "glm", - "zhipuai", - "zhipuai-coding-plan", - "zai", - "zai-coding-plan", + "minimax-coding-plan", + "mistral", + "moark", + "modelscope", "moonshotai", "moonshotai-cn", - "kimi-for-coding", - "openrouter", - "litellm", - "glama", - "vertex", - "bedrock", - "local", + "morph", + "nano-gpt", + "nebius", + "nova", + "novita-ai", + "nvidia", "ollama", - "dexto-nova" + "ollama-cloud", + "openai", + "openai-compatible", + "opencode", + "openrouter", + "ovhcloud", + "perplexity", + "poe", + "privatemode-ai", + "qihang-ai", + "qiniu-ai", + "requesty", + "sap-ai-core", + "scaleway", + "siliconflow", + "siliconflow-cn", + "stackit", + "stepfun", + "submodel", + "synthetic", + "togetherai", + "upstage", + "v0", + "venice", + "vercel", + "vivgrid", + "vultr", + "wandb", + "xai", + "xiaomi", + "zai", + "zai-coding-plan", + "zenmux", + "zhipuai", + "zhipuai-coding-plan" ], "description": "LLM provider identifier" }, @@ -15513,33 +25941,108 @@ "provider": { "type": "string", "enum": [ - "openai", - "openai-compatible", + "302ai", + "abacus", + "aihubmix", + "alibaba", + "alibaba-cn", + "amazon-bedrock", "anthropic", + "azure", + "azure-cognitive-services", + "bailing", + "baseten", + "berget", + "cerebras", + "chutes", + "cloudferro-sherlock", + "cloudflare-ai-gateway", + "cloudflare-workers-ai", + "cohere", + "cortecs", + "deepinfra", + "deepseek", + "dexto-nova", + "evroc", + "fastrouter", + "fireworks-ai", + "firmware", + "friendli", + "github-copilot", + "github-models", + "gitlab", + "glama", "google", + "google-vertex", + "google-vertex-anthropic", "groq", - "xai", - "cohere", + "helicone", + "huggingface", + "iflowcn", + "inception", + "inference", + "io-net", + "jiekou", + "kilo", + "kimi-for-coding", + "kuae-cloud-coding-plan", + "litellm", + "llama", + "lmstudio", + "local", + "lucidquery", + "meganova", "minimax", "minimax-cn", - "minimax-coding-plan", "minimax-cn-coding-plan", - "glm", - "zhipuai", - "zhipuai-coding-plan", - "zai", - "zai-coding-plan", + "minimax-coding-plan", + "mistral", + "moark", + "modelscope", "moonshotai", "moonshotai-cn", - "kimi-for-coding", - "openrouter", - "litellm", - "glama", - "vertex", - "bedrock", - "local", + "morph", + "nano-gpt", + "nebius", + "nova", + "novita-ai", + "nvidia", "ollama", - "dexto-nova" + "ollama-cloud", + "openai", + "openai-compatible", + "opencode", + "openrouter", + "ovhcloud", + "perplexity", + "poe", + "privatemode-ai", + "qihang-ai", + "qiniu-ai", + "requesty", + "sap-ai-core", + "scaleway", + "siliconflow", + "siliconflow-cn", + "stackit", + "stepfun", + "submodel", + "synthetic", + "togetherai", + "upstage", + "v0", + "venice", + "vercel", + "vivgrid", + "vultr", + "wandb", + "xai", + "xiaomi", + "zai", + "zai-coding-plan", + "zenmux", + "zhipuai", + "zhipuai-coding-plan" ], "description": "Provider identifier" }, @@ -15586,33 +26089,108 @@ "provider": { "type": "string", "enum": [ - "openai", - "openai-compatible", + "302ai", + "abacus", + "aihubmix", + "alibaba", + "alibaba-cn", + "amazon-bedrock", "anthropic", + "azure", + "azure-cognitive-services", + "bailing", + "baseten", + "berget", + "cerebras", + "chutes", + "cloudferro-sherlock", + "cloudflare-ai-gateway", + "cloudflare-workers-ai", + "cohere", + "cortecs", + "deepinfra", + "deepseek", + "dexto-nova", + "evroc", + "fastrouter", + "fireworks-ai", + "firmware", + "friendli", + "github-copilot", + "github-models", + "gitlab", + "glama", "google", + "google-vertex", + "google-vertex-anthropic", "groq", - "xai", - "cohere", + "helicone", + "huggingface", + "iflowcn", + "inception", + "inference", + "io-net", + "jiekou", + "kilo", + "kimi-for-coding", + "kuae-cloud-coding-plan", + "litellm", + "llama", + "lmstudio", + "local", + "lucidquery", + "meganova", "minimax", "minimax-cn", - "minimax-coding-plan", "minimax-cn-coding-plan", - "glm", - "zhipuai", - "zhipuai-coding-plan", - "zai", - "zai-coding-plan", + "minimax-coding-plan", + "mistral", + "moark", + "modelscope", "moonshotai", "moonshotai-cn", - "kimi-for-coding", - "openrouter", - "litellm", - "glama", - "vertex", - "bedrock", - "local", + "morph", + "nano-gpt", + "nebius", + "nova", + "novita-ai", + "nvidia", "ollama", - "dexto-nova" + "ollama-cloud", + "openai", + "openai-compatible", + "opencode", + "openrouter", + "ovhcloud", + "perplexity", + "poe", + "privatemode-ai", + "qihang-ai", + "qiniu-ai", + "requesty", + "sap-ai-core", + "scaleway", + "siliconflow", + "siliconflow-cn", + "stackit", + "stepfun", + "submodel", + "synthetic", + "togetherai", + "upstage", + "v0", + "venice", + "vercel", + "vivgrid", + "vultr", + "wandb", + "xai", + "xiaomi", + "zai", + "zai-coding-plan", + "zenmux", + "zhipuai", + "zhipuai-coding-plan" ], "description": "LLM provider identifier (e.g., openai, anthropic)" }, @@ -15650,33 +26228,108 @@ "provider": { "type": "string", "enum": [ - "openai", - "openai-compatible", + "302ai", + "abacus", + "aihubmix", + "alibaba", + "alibaba-cn", + "amazon-bedrock", "anthropic", + "azure", + "azure-cognitive-services", + "bailing", + "baseten", + "berget", + "cerebras", + "chutes", + "cloudferro-sherlock", + "cloudflare-ai-gateway", + "cloudflare-workers-ai", + "cohere", + "cortecs", + "deepinfra", + "deepseek", + "dexto-nova", + "evroc", + "fastrouter", + "fireworks-ai", + "firmware", + "friendli", + "github-copilot", + "github-models", + "gitlab", + "glama", "google", + "google-vertex", + "google-vertex-anthropic", "groq", - "xai", - "cohere", + "helicone", + "huggingface", + "iflowcn", + "inception", + "inference", + "io-net", + "jiekou", + "kilo", + "kimi-for-coding", + "kuae-cloud-coding-plan", + "litellm", + "llama", + "lmstudio", + "local", + "lucidquery", + "meganova", "minimax", "minimax-cn", - "minimax-coding-plan", "minimax-cn-coding-plan", - "glm", - "zhipuai", - "zhipuai-coding-plan", - "zai", - "zai-coding-plan", + "minimax-coding-plan", + "mistral", + "moark", + "modelscope", "moonshotai", "moonshotai-cn", - "kimi-for-coding", - "openrouter", - "litellm", - "glama", - "vertex", - "bedrock", - "local", + "morph", + "nano-gpt", + "nebius", + "nova", + "novita-ai", + "nvidia", "ollama", - "dexto-nova" + "ollama-cloud", + "openai", + "openai-compatible", + "opencode", + "openrouter", + "ovhcloud", + "perplexity", + "poe", + "privatemode-ai", + "qihang-ai", + "qiniu-ai", + "requesty", + "sap-ai-core", + "scaleway", + "siliconflow", + "siliconflow-cn", + "stackit", + "stepfun", + "submodel", + "synthetic", + "togetherai", + "upstage", + "v0", + "venice", + "vercel", + "vivgrid", + "vultr", + "wandb", + "xai", + "xiaomi", + "zai", + "zai-coding-plan", + "zenmux", + "zhipuai", + "zhipuai-coding-plan" ], "description": "Provider for which the key was saved" }, From 7939a45d4a7a59f1310c1b3b6006eb2d6f0059e6 Mon Sep 17 00:00:00 2001 From: Rahul Karajgikar <rahul@trytruffle.ai> Date: Mon, 23 Feb 2026 23:38:33 +0530 Subject: [PATCH 25/25] docs: resync openapi after merge --- docs/static/openapi/openapi.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/static/openapi/openapi.json b/docs/static/openapi/openapi.json index 8e92ee51d..be61960cb 100644 --- a/docs/static/openapi/openapi.json +++ b/docs/static/openapi/openapi.json @@ -2,7 +2,7 @@ "openapi": "3.0.0", "info": { "title": "Dexto API", - "version": "1.6.0", + "version": "1.6.1", "description": "OpenAPI spec for the Dexto REST API server" }, "servers": [