From 0474213f6ca8dc2a2fec761965c8aab0873862d8 Mon Sep 17 00:00:00 2001
From: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
Date: Thu, 15 Oct 2026 00:15:39 -0700
Subject: [PATCH 01/29] fix(vscode): keep Auto Compact and its strategy
together in Feature settings (#15109)
The Cloud toggle was appended to the agent toggle list, which renders
before the Auto Compact Strategy dropdown, so it split Auto Compact from
its strategy. Render the Cloud row after Web Search instead.
---
.../sections/FeatureSettingsSection.tsx | 18 ++++++++----------
1 file changed, 8 insertions(+), 10 deletions(-)
diff --git a/apps/vscode/webview-ui/src/components/settings/sections/FeatureSettingsSection.tsx b/apps/vscode/webview-ui/src/components/settings/sections/FeatureSettingsSection.tsx
index a7bc2b9ce4..7892121fed 100644
--- a/apps/vscode/webview-ui/src/components/settings/sections/FeatureSettingsSection.tsx
+++ b/apps/vscode/webview-ui/src/components/settings/sections/FeatureSettingsSection.tsx
@@ -39,14 +39,6 @@ const agentFeatures: FeatureToggle[] = [
stateKey: "useAutoCondense",
settingKey: "useAutoCondense",
},
- {
- id: "cloud-sessions",
- label: "Cloud",
- description:
- "Run Cline on your GitHub repositories in secure cloud sandboxes. Adds a Cloud option to the new task composer. Requires a Cline account with GitHub connected.",
- stateKey: "cloudSessionsEnabled",
- settingKey: "cloudSessionsEnabled",
- },
]
const editorFeatures: FeatureToggle[] = [
@@ -175,13 +167,11 @@ const FeatureSettingsSection = ({ renderSectionHeader }: FeatureSettingsSectionP
subagentsEnabled,
worktreesEnabled: worktreesEnabled?.user,
backgroundEditEnabled,
- cloudSessionsEnabled,
}
// Visibility lookup for features with feature flags
const featureVisibility: Record = {
worktreesEnabled: worktreesEnabled?.featureFlag,
- cloudSessionsEnabled: !!cloudSessionsAvailable,
}
return (
@@ -228,6 +218,14 @@ const FeatureSettingsSection = ({ renderSectionHeader }: FeatureSettingsSectionP
label="Web Search"
onChange={(checked) => updateSetting("webSearchEnabled", checked)}
/>
+ updateSetting("cloudSessionsEnabled", checked)}
+ />
From 2ffa920b0e6a5b2f7a8c22d253f51c765cba4011 Mon Sep 17 00:00:00 2001
From: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
Date: Thu, 15 Oct 2026 02:15:02 -0700
Subject: [PATCH 02/29] fix: add /v1 to host-only OpenAI Compatible base URLs
once, on VS Code and JetBrains (#15108)
* fix(vscode): migrate host-only OpenAI Compatible base URLs to /v1 once
Earlier extension builds sent requests for a host-only OpenAI Compatible base
URL to /v1. #15057 now uses the URL as entered, so persist the /v1 for
existing users once instead of retrying requests at runtime.
* Revert "fix(vscode): migrate host-only OpenAI Compatible base URLs to /v1 once"
This reverts commit 424bad47e8359f7a9e6af0a2f668d1b9a78b7727.
* fix(vscode): add /v1 to host-only OpenAI Compatible base URLs in the storage migration
Earlier SDK extension builds sent requests for a host-only OpenAI Compatible
base URL to /v1. #15057 now uses the URL as entered, so add a v4 step to
the VS Code storage migration that saves the /v1 for existing users once.
* fix(vscode): don't log the OpenAI Compatible base URL in the /v1 migration
Base URLs can carry credentials (user:pass@host) or tokens in the query string.
* fix: run the OpenAI Compatible /v1 migration on JetBrains too
Move the host-only base URL rewrite out of the VS Code-only storage
migration into a host-neutral step that both extension.ts and the
standalone cline-core.ts run before initialize(). It keeps its own marker
in the shared globalState.json, set even when there is nothing to rewrite,
so it runs once across hosts and later host-only URLs stay as entered.
---
.../openai-base-url-migration.test.ts | 73 +++++++++++++++++++
.../core/storage/openai-base-url-migration.ts | 29 ++++++++
apps/vscode/src/extension.ts | 2 +
apps/vscode/src/standalone/cline-core.ts | 2 +
4 files changed, 106 insertions(+)
create mode 100644 apps/vscode/src/core/storage/__tests__/openai-base-url-migration.test.ts
create mode 100644 apps/vscode/src/core/storage/openai-base-url-migration.ts
diff --git a/apps/vscode/src/core/storage/__tests__/openai-base-url-migration.test.ts b/apps/vscode/src/core/storage/__tests__/openai-base-url-migration.test.ts
new file mode 100644
index 0000000000..72cfbd33a2
--- /dev/null
+++ b/apps/vscode/src/core/storage/__tests__/openai-base-url-migration.test.ts
@@ -0,0 +1,73 @@
+import { afterEach, beforeEach, describe, expect, it } from "bun:test"
+import fs from "node:fs"
+import os from "node:os"
+import path from "node:path"
+import { createStorageContext, type StorageContext } from "@/shared/storage/storage-context"
+import { migrateOpenAiCompatibleBaseUrlToV1 } from "../openai-base-url-migration"
+
+describe("migrateOpenAiCompatibleBaseUrlToV1", () => {
+ let tempDir: string
+ let storage: StorageContext
+
+ beforeEach(() => {
+ tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "openai-base-url-migration-"))
+ storage = createStorageContext({ clineDir: tempDir, workspacePath: tempDir })
+ })
+
+ afterEach(() => {
+ fs.rmSync(tempDir, { recursive: true, force: true })
+ })
+
+ for (const [baseUrl, expected] of [
+ ["https://example.com", "https://example.com/v1"],
+ ["http://localhost:8000/", "http://localhost:8000/v1"],
+ ]) {
+ it(`adds /v1 to the host-only base URL ${baseUrl}`, () => {
+ storage.globalState.update("openAiBaseUrl", baseUrl)
+
+ migrateOpenAiCompatibleBaseUrlToV1(storage)
+
+ expect(storage.globalState.get("openAiBaseUrl")).toBe(expected)
+ })
+ }
+
+ for (const baseUrl of ["https://example.com/v1", "https://example.com/api/foo", "not a url"]) {
+ it(`leaves the base URL ${baseUrl} unchanged`, () => {
+ storage.globalState.update("openAiBaseUrl", baseUrl)
+
+ migrateOpenAiCompatibleBaseUrlToV1(storage)
+
+ expect(storage.globalState.get("openAiBaseUrl")).toBe(baseUrl)
+ })
+ }
+
+ it("runs only once, so a host-only URL saved afterwards stays as entered", () => {
+ storage.globalState.update("openAiBaseUrl", "https://example.com")
+ migrateOpenAiCompatibleBaseUrlToV1(storage)
+ storage.globalState.update("openAiBaseUrl", "https://example.com")
+
+ migrateOpenAiCompatibleBaseUrlToV1(storage)
+
+ expect(storage.globalState.get("openAiBaseUrl")).toBe("https://example.com")
+ })
+
+ it("marks itself done when there is no base URL, so a later host-only URL stays as entered", () => {
+ migrateOpenAiCompatibleBaseUrlToV1(storage)
+ storage.globalState.update("openAiBaseUrl", "https://example.com")
+
+ migrateOpenAiCompatibleBaseUrlToV1(storage)
+
+ expect(storage.globalState.get("openAiBaseUrl")).toBe("https://example.com")
+ })
+
+ it("shares its marker across hosts through globalState.json", () => {
+ storage.globalState.update("openAiBaseUrl", "https://example.com")
+ migrateOpenAiCompatibleBaseUrlToV1(storage)
+ storage.globalState.update("openAiBaseUrl", "https://example.com")
+
+ const otherHost = createStorageContext({ clineDir: tempDir, workspacePath: tempDir })
+ migrateOpenAiCompatibleBaseUrlToV1(otherHost)
+
+ expect(otherHost.globalState.get("openAiBaseUrl")).toBe("https://example.com")
+ })
+})
diff --git a/apps/vscode/src/core/storage/openai-base-url-migration.ts b/apps/vscode/src/core/storage/openai-base-url-migration.ts
new file mode 100644
index 0000000000..73402b6081
--- /dev/null
+++ b/apps/vscode/src/core/storage/openai-base-url-migration.ts
@@ -0,0 +1,29 @@
+import { Logger } from "@/shared/services/Logger"
+import type { StorageContext } from "@/shared/storage/storage-context"
+
+const MIGRATED_KEY = "__openAiBaseUrlV1Migrated"
+
+/**
+ * Earlier SDK builds sent requests for an OpenAI Compatible base URL with no
+ * path (`http://localhost:8000`) to `/v1`; the URL is now used as entered.
+ * Save the `/v1` so existing setups keep reaching the same endpoint.
+ *
+ * Runs once across all hosts: the marker lives in the shared globalState.json
+ * and is set even when there is nothing to rewrite, so a host-only URL saved
+ * afterwards (in any host) stays as entered.
+ */
+export function migrateOpenAiCompatibleBaseUrlToV1(storage: StorageContext): void {
+ if (storage.globalState.get(MIGRATED_KEY)) {
+ return
+ }
+ const baseUrl = storage.globalState.get("openAiBaseUrl")?.trim()
+ if (baseUrl && URL.canParse(baseUrl)) {
+ const url = new URL(baseUrl)
+ if (url.pathname === "/") {
+ url.pathname = "/v1"
+ storage.globalState.update("openAiBaseUrl", url.toString().replace(/\/$/, ""))
+ Logger.info("[Migration] Added /v1 to the host-only OpenAI Compatible base URL")
+ }
+ }
+ storage.globalState.update(MIGRATED_KEY, true)
+}
diff --git a/apps/vscode/src/extension.ts b/apps/vscode/src/extension.ts
index f93bec1a83..2bbc09bf8e 100644
--- a/apps/vscode/src/extension.ts
+++ b/apps/vscode/src/extension.ts
@@ -29,6 +29,7 @@ import { improveWithCline } from "./core/controller/commands/improveWithCline"
import { sendAddToInputEvent } from "./core/controller/ui/subscribeToAddToInput"
import { sendShowWebviewEvent } from "./core/controller/ui/subscribeToShowWebview"
import { HookDiscoveryCache } from "./core/hooks/HookDiscoveryCache"
+import { migrateOpenAiCompatibleBaseUrlToV1 } from "./core/storage/openai-base-url-migration"
import {
cleanupMcpMarketplaceCatalogFromGlobalState,
cleanupOldApiKey,
@@ -84,6 +85,7 @@ export async function activate(context: vscode.ExtensionContext) {
const workspacePath = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath
const storageContext = createStorageContext({ workspacePath })
await exportVSCodeStorageToSharedFiles(context, storageContext)
+ migrateOpenAiCompatibleBaseUrlToV1(storageContext)
// 4. Register services and perform common initialization
// IMPORTANT: Must be done after host provider is setup and migrations are complete
diff --git a/apps/vscode/src/standalone/cline-core.ts b/apps/vscode/src/standalone/cline-core.ts
index d95c006cbf..56372a6d0b 100644
--- a/apps/vscode/src/standalone/cline-core.ts
+++ b/apps/vscode/src/standalone/cline-core.ts
@@ -14,6 +14,7 @@ import { retryOperation } from "@utils/retry"
import * as path from "path"
import { initialize, tearDown } from "@/common"
import { SqliteLockManager } from "@/core/locks/SqliteLockManager"
+import { migrateOpenAiCompatibleBaseUrlToV1 } from "@/core/storage/openai-base-url-migration"
import { WebviewProvider } from "@/core/webview"
import { AuthHandler } from "@/hosts/external/AuthHandler"
import { HostProvider } from "@/hosts/host-provider"
@@ -87,6 +88,7 @@ async function main() {
// Create shared file-backed storage
const storageContext = createStorageContext()
+ migrateOpenAiCompatibleBaseUrlToV1(storageContext)
const webviewProvider = await initialize(storageContext)
// Enable the localhost HTTP server that handles auth redirects.
From 48594e5a7c896b0b65be4a435fed9cbafd0d4319 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1s=20Barreiro?=
<52393857+BarreiroT@users.noreply.github.com>
Date: Thu, 15 Oct 2026 09:13:09 -0300
Subject: [PATCH 03/29] Log request ids (#15044)
* Log request ids on failure logs
* refactor
* Capture only the base error message
* address review comments
---
sdk/packages/llms/src/providers/ai-sdk.ts | 26 ++--
.../llms/src/providers/gateway.test.ts | 118 +++++++++++++++---
.../src/providers/response-request-id.test.ts | 76 +++++++++++
.../llms/src/providers/response-request-id.ts | 58 +++++++++
4 files changed, 255 insertions(+), 23 deletions(-)
create mode 100644 sdk/packages/llms/src/providers/response-request-id.test.ts
create mode 100644 sdk/packages/llms/src/providers/response-request-id.ts
diff --git a/sdk/packages/llms/src/providers/ai-sdk.ts b/sdk/packages/llms/src/providers/ai-sdk.ts
index b4dfa9e9bc..890a7e207a 100644
--- a/sdk/packages/llms/src/providers/ai-sdk.ts
+++ b/sdk/packages/llms/src/providers/ai-sdk.ts
@@ -60,6 +60,11 @@ import {
recordProviderRequestCapture,
wrapFetchForProviderRequestCapture,
} from "./provider-request-capture";
+import {
+ appendRequestId,
+ extractResponseRequestId,
+ findRequestIdHeader,
+} from "./response-request-id";
import {
applyPromptCacheToLastTextPart,
shouldApplyPromptCache,
@@ -1467,13 +1472,19 @@ interface CapturedStreamError {
* does not report the same failure a second time.
*/
reported?: boolean;
+ requestId?: string;
+ baseMessage: string;
}
function captureStreamError(error: unknown): CapturedStreamError {
+ const requestId = extractResponseRequestId(error);
+ const baseMessage = extractErrorMessage(error);
return {
- message: extractErrorMessage(error),
+ message: appendRequestId(baseMessage, requestId),
+ baseMessage,
errorClass: classifyProviderError(error),
retryable: isRetryableBeyondSdkRetries(error),
+ ...(requestId ? { requestId } : {}),
};
}
@@ -1517,9 +1528,7 @@ async function* emitAiSdkEvents(
continue;
}
if (part.type === "finish-step") {
- requestId = Object.entries(part.response?.headers ?? {}).find(
- ([name]) => name.toLowerCase() === "x-request-id",
- )?.[1];
+ requestId = findRequestIdHeader(part.response?.headers);
continue;
}
if (part.type === "text-delta") {
@@ -1994,10 +2003,11 @@ async function* emitAiSdkEvents(
};
}
+ const finishRequestId = requestId ?? streamError?.requestId;
yield {
type: "finish",
reason: streamError ? "error" : mapFinishReason(finishReason),
- ...(requestId ? { requestId } : {}),
+ ...(finishRequestId ? { requestId: finishRequestId } : {}),
error: streamError?.message,
errorClass: streamError?.errorClass,
errorRetryable: streamError?.retryable,
@@ -2381,13 +2391,14 @@ function createAiSdkProvider(
component: "llms",
operation: "provider.stream",
error: streamError,
- errorMessage: msg,
+ errorMessage: captured.baseMessage,
severity: "error",
handled: true,
context: {
providerId: request.providerId,
modelId: request.modelId,
providerKind: kind,
+ requestId: captured.requestId,
},
});
},
@@ -2430,13 +2441,14 @@ function createAiSdkProvider(
component: "llms",
operation: "provider.create_or_stream",
error,
- errorMessage: msg,
+ errorMessage: captured.baseMessage,
severity: "error",
handled: true,
context: {
providerId: request.providerId,
modelId: request.modelId,
providerKind: kind,
+ requestId: captured.requestId,
},
});
yield {
diff --git a/sdk/packages/llms/src/providers/gateway.test.ts b/sdk/packages/llms/src/providers/gateway.test.ts
index fbff5b9a39..b501fa67a0 100644
--- a/sdk/packages/llms/src/providers/gateway.test.ts
+++ b/sdk/packages/llms/src/providers/gateway.test.ts
@@ -19,6 +19,7 @@ import {
type ITelemetryService,
resetSdkErrorRateLimiterForTests,
} from "@cline/shared";
+import { APICallError } from "ai";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { normalizeModelsDevProviderModels } from "../catalog/catalog-live";
import { createOpenAICompatibleProvider } from "./ai-sdk";
@@ -96,22 +97,28 @@ function createFetchMock() {
};
}
-vi.mock("ai", () => ({
- jsonSchema: (schema: unknown, options: unknown) => ({
- jsonSchema: schema,
- ...(options && typeof options === "object" ? options : {}),
- }),
- generateImage: (input: unknown) => generateImageSpy(input),
- streamText: (input: unknown) => streamTextSpy(input),
- // `wrapLanguageModel` is used by the openai-compatible and mistral
- // vendors to attach `splitToolImagesMiddleware`. The middleware itself
- // is exercised by its own unit tests; here we just need an identity
- // pass-through so the vendor factories' downstream `model:` callbacks
- // keep returning the spy-produced mock objects unchanged. (The mock
- // objects don't satisfy the real `LanguageModelV4` interface, so we
- // can't call the real `wrapLanguageModel` either way.)
- wrapLanguageModel: ({ model }: { model: unknown }) => model,
-}));
+vi.mock("ai", async (importOriginal) => {
+ const { APICallError, RetryError } =
+ await importOriginal();
+ return {
+ APICallError,
+ RetryError,
+ jsonSchema: (schema: unknown, options: unknown) => ({
+ jsonSchema: schema,
+ ...(options && typeof options === "object" ? options : {}),
+ }),
+ generateImage: (input: unknown) => generateImageSpy(input),
+ streamText: (input: unknown) => streamTextSpy(input),
+ // `wrapLanguageModel` is used by the openai-compatible and mistral
+ // vendors to attach `splitToolImagesMiddleware`. The middleware itself
+ // is exercised by its own unit tests; here we just need an identity
+ // pass-through so the vendor factories' downstream `model:` callbacks
+ // keep returning the spy-produced mock objects unchanged. (The mock
+ // objects don't satisfy the real `LanguageModelV4` interface, so we
+ // can't call the real `wrapLanguageModel` either way.)
+ wrapLanguageModel: ({ model }: { model: unknown }) => model,
+ };
+});
vi.mock("@ai-sdk/openai", () => ({
createOpenAI: () => ({
@@ -1401,6 +1408,44 @@ describe("sdk-gateway", () => {
});
});
+ it("includes the response x-request-id in stream error messages", async () => {
+ streamTextSpy.mockReturnValue({
+ fullStream: makeStreamParts([
+ {
+ type: "error",
+ error: new APICallError({
+ message: "Unauthorized",
+ url: "https://api.cline.bot/api/v1/chat/completions",
+ requestBodyValues: {},
+ statusCode: 401,
+ responseHeaders: { "X-Request-ID": "req_abc123" },
+ responseBody: JSON.stringify({
+ error: { message: "Unauthorized: re-authenticate" },
+ }),
+ }),
+ },
+ ]),
+ });
+ const gateway = createGateway({
+ providerConfigs: [{ providerId: "openai-native", apiKey: "test" }],
+ });
+
+ const events = await collect(
+ await gateway.stream({
+ providerId: "openai-native",
+ modelId: "gpt-5-mini",
+ messages: baseMessages,
+ }),
+ );
+
+ expect(events.at(-1)).toMatchObject({
+ type: "finish",
+ reason: "error",
+ requestId: "req_abc123",
+ error: "Unauthorized: re-authenticate (Request ID: req_abc123)",
+ });
+ });
+
it("preserves valid mixed text when a generated image is rejected", async () => {
const oversized = "A".repeat(DEFAULT_MAX_IMAGE_ENCODED_BYTES + 4);
streamTextSpy.mockReturnValue({
@@ -2802,6 +2847,47 @@ describe("sdk-gateway", () => {
expect(sdkErrors).toHaveLength(5);
});
+ it("rate-limits stream failures that differ only by request ID", async () => {
+ const { telemetry, capture } = createTelemetryMock();
+ const gateway = createGateway({
+ telemetry,
+ providerConfigs: [{ providerId: "openai-native", apiKey: "test" }],
+ });
+
+ for (let i = 0; i < 20; i++) {
+ const rawError = new APICallError({
+ message: "Unauthorized",
+ url: "https://api.cline.bot/api/v1/chat/completions",
+ requestBodyValues: {},
+ statusCode: 401,
+ responseHeaders: { "x-request-id": `req_${"abcdefghijklmnopqrst"[i]}` },
+ });
+ streamTextSpy.mockImplementation(
+ (input: { onError?: (event: { error: unknown }) => void }) => {
+ input.onError?.({ error: rawError });
+ return {
+ fullStream: makeStreamParts([{ type: "error", error: rawError }]),
+ };
+ },
+ );
+ await collect(
+ await gateway.stream({
+ providerId: "openai-native",
+ modelId: "gpt-5-mini",
+ messages: baseMessages,
+ }),
+ );
+ }
+
+ const sdkErrors = capture.mock.calls.filter(
+ ([call]) => (call as { event: string }).event === "sdk.error",
+ );
+ expect(sdkErrors).toHaveLength(5);
+ expect(sdkErrors[0]?.[0]).toMatchObject({
+ properties: { error_message: "Unauthorized", requestId: "req_a" },
+ });
+ });
+
it("records the extracted cause when provider creation fails through a generic wrapper", async () => {
streamTextSpy.mockImplementation(() => {
throw new Error("No output generated. Check the stream for errors.", {
diff --git a/sdk/packages/llms/src/providers/response-request-id.test.ts b/sdk/packages/llms/src/providers/response-request-id.test.ts
new file mode 100644
index 0000000000..69931e281d
--- /dev/null
+++ b/sdk/packages/llms/src/providers/response-request-id.test.ts
@@ -0,0 +1,76 @@
+import { APICallError, RetryError } from "ai";
+import { describe, expect, it } from "vitest";
+import {
+ extractResponseRequestId,
+ findRequestIdHeader,
+} from "./response-request-id";
+
+function apiCallError(responseHeaders?: Record) {
+ return new APICallError({
+ message: "Bad Gateway",
+ url: "https://api.cline.bot/api/v1/chat/completions",
+ requestBodyValues: {},
+ statusCode: 502,
+ responseHeaders,
+ });
+}
+
+describe("findRequestIdHeader", () => {
+ it("matches the header case-insensitively and trims it", () => {
+ expect(findRequestIdHeader({ "X-Request-ID": " req_1 " })).toBe("req_1");
+ });
+
+ it("returns undefined for missing or blank headers", () => {
+ expect(findRequestIdHeader(undefined)).toBeUndefined();
+ expect(findRequestIdHeader({ "x-request-id": " " })).toBeUndefined();
+ });
+});
+
+describe("extractResponseRequestId", () => {
+ it("reads a top-level APICallError", () => {
+ expect(
+ extractResponseRequestId(apiCallError({ "x-request-id": "req_top" })),
+ ).toBe("req_top");
+ });
+
+ it("walks the cause chain to a wrapped APICallError", () => {
+ const wrapped = new Error("outer", {
+ cause: new Error("middle", {
+ cause: apiCallError({ "x-request-id": "req_nested" }),
+ }),
+ });
+ expect(extractResponseRequestId(wrapped)).toBe("req_nested");
+ });
+
+ it("stops at the depth guard on cyclic causes", () => {
+ const a = new Error("a") as Error & { cause?: unknown };
+ const b = new Error("b", { cause: a });
+ a.cause = b;
+ expect(extractResponseRequestId(a)).toBeUndefined();
+ });
+
+ it("falls back to earlier RetryError attempts newest-first", () => {
+ const error = new RetryError({
+ message: "Failed after 3 attempts",
+ reason: "maxRetriesExceeded",
+ errors: [
+ apiCallError({ "x-request-id": "req_first" }),
+ apiCallError({ "x-request-id": "req_second" }),
+ apiCallError(),
+ ],
+ });
+ expect(extractResponseRequestId(error)).toBe("req_second");
+ });
+
+ it("prefers RetryError.lastError when it has a request id", () => {
+ const error = new RetryError({
+ message: "Failed after 2 attempts",
+ reason: "maxRetriesExceeded",
+ errors: [
+ apiCallError({ "x-request-id": "req_first" }),
+ apiCallError({ "x-request-id": "req_last" }),
+ ],
+ });
+ expect(extractResponseRequestId(error)).toBe("req_last");
+ });
+});
diff --git a/sdk/packages/llms/src/providers/response-request-id.ts b/sdk/packages/llms/src/providers/response-request-id.ts
new file mode 100644
index 0000000000..2fbba27818
--- /dev/null
+++ b/sdk/packages/llms/src/providers/response-request-id.ts
@@ -0,0 +1,58 @@
+import { APICallError, RetryError } from "ai";
+
+const REQUEST_ID_HEADER = "x-request-id";
+const MAX_CAUSE_DEPTH = 5;
+
+export function findRequestIdHeader(
+ headers: Record | undefined,
+): string | undefined {
+ const value = Object.entries(headers ?? {}).find(
+ ([name]) => name.toLowerCase() === REQUEST_ID_HEADER,
+ )?.[1];
+ return value?.trim() || undefined;
+}
+
+export function extractResponseRequestId(
+ error: unknown,
+ depth = 0,
+): string | undefined {
+ if (depth > MAX_CAUSE_DEPTH || !error || typeof error !== "object") {
+ return undefined;
+ }
+ if (RetryError.isInstance(error)) {
+ const fromLast = extractResponseRequestId(error.lastError, depth + 1);
+ if (fromLast) {
+ return fromLast;
+ }
+ for (let i = error.errors.length - 1; i >= 0; i--) {
+ const attempt = error.errors[i];
+ if (attempt === error.lastError) {
+ continue;
+ }
+ const fromAttempt = extractResponseRequestId(attempt, depth + 1);
+ if (fromAttempt) {
+ return fromAttempt;
+ }
+ }
+ }
+ if (APICallError.isInstance(error)) {
+ const fromHeaders = findRequestIdHeader(error.responseHeaders);
+ if (fromHeaders) {
+ return fromHeaders;
+ }
+ }
+ return extractResponseRequestId(
+ (error as { cause?: unknown }).cause,
+ depth + 1,
+ );
+}
+
+export function appendRequestId(
+ message: string,
+ requestId: string | undefined,
+): string {
+ if (!requestId || message.includes(requestId)) {
+ return message;
+ }
+ return `${message} (Request ID: ${requestId})`;
+}
From 3834735da26b70503aa5c0aa377949612a2816ad Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Miko=C5=82aj=20Kondratek?=
<19799111+mkondratek@users.noreply.github.com>
Date: Thu, 15 Oct 2026 15:45:19 +0200
Subject: [PATCH 04/29] fix(webview): keep the Run task card above the
Auto-approve bar in JetBrains (#15120)
---
.../chat/chat-view/components/layout/WelcomeSection.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/apps/vscode/webview-ui/src/components/chat/chat-view/components/layout/WelcomeSection.tsx b/apps/vscode/webview-ui/src/components/chat/chat-view/components/layout/WelcomeSection.tsx
index f506717aea..1e62a3fd91 100644
--- a/apps/vscode/webview-ui/src/components/chat/chat-view/components/layout/WelcomeSection.tsx
+++ b/apps/vscode/webview-ui/src/components/chat/chat-view/components/layout/WelcomeSection.tsx
@@ -318,7 +318,7 @@ export const WelcomeSection: React.FC = ({
}, [bannerConfig, banners, clineUser, handleBannerAction, handleBannerDismiss, clinePassPromoBanner])
return (
-
+
Date: Thu, 15 Oct 2026 13:23:49 -0700
Subject: [PATCH 05/29] feat(desktop): remove the Cloud sessions settings
toggle (#15110)
* feat(desktop): enable cloud sessions for everyone
Remove the Cloud sessions preview toggle from Settings and the
code-cloud-agents rollout flag that revealed it. Cloud sessions are now
on by default; CLINE_CODE_CLOUD_AGENTS=0 still turns them off for
development and tests.
* fix(desktop): keep the code-cloud-agents rollout flag as the cloud gate
Only the Settings opt-in should go away. Cloud sessions are enabled
wherever the code-cloud-agents PostHog flag is on (or the
CLINE_CODE_CLOUD_AGENTS env override forces them).
---
.../desktop-app/sidecar/ARCHITECTURE.md | 5 +-
.../sidecar/commands-settings.test.ts | 51 +------
apps/examples/desktop-app/sidecar/commands.ts | 26 ----
.../sidecar/desktop-settings.test.ts | 62 --------
.../desktop-app/sidecar/desktop-settings.ts | 49 ------
.../desktop-app/sidecar/diagnostics.ts | 2 -
.../desktop-app/sidecar/feature-flags.test.ts | 27 +---
.../desktop-app/sidecar/feature-flags.ts | 16 +-
.../examples/desktop-app/webview/app/page.tsx | 12 --
.../views/settings/settings-view.test.tsx | 49 ------
.../views/settings/settings-view.tsx | 140 ++----------------
sdk/packages/shared/src/feature-flags.ts | 2 +-
12 files changed, 29 insertions(+), 412 deletions(-)
delete mode 100644 apps/examples/desktop-app/sidecar/desktop-settings.test.ts
delete mode 100644 apps/examples/desktop-app/sidecar/desktop-settings.ts
diff --git a/apps/examples/desktop-app/sidecar/ARCHITECTURE.md b/apps/examples/desktop-app/sidecar/ARCHITECTURE.md
index 1716153ce6..cc58a1c476 100644
--- a/apps/examples/desktop-app/sidecar/ARCHITECTURE.md
+++ b/apps/examples/desktop-app/sidecar/ARCHITECTURE.md
@@ -21,7 +21,6 @@ sidecar/
├── chat-session.ts # Shared-Hub chat session adapter (local + cloud routing)
├── cloud-sessions.ts # Cloud session REST client + Hub-proxy manager
├── cline-auth.ts # Refresh-aware Cline auth token resolution
-├── desktop-settings.ts # Desktop-owned settings (cloud sessions opt-in)
├── feature-flags.ts # Cloud sessions gate (env override + settings toggle)
├── session-data/ # Shared discovery, messages, artifacts, search helpers
├── paths.ts # Path resolution
@@ -212,9 +211,7 @@ Supported commands:
| `read_session_hooks` | Session data readers |
| `delete_chat_session` | `SqliteSessionStore.delete` + file cleanup; cloud sessions also delete the sandbox |
| `update_chat_session_title` | `resolveSessionBackend().updateSession`; cloud sessions PATCH the cloud API |
-| `get_feature_flags` | `isCloudAgentsEnabled()` (env override + settings toggle) |
-| `get_desktop_settings` | `readDesktopSettings()` |
-| `set_cloud_sessions_enabled` | `setCloudSessionsEnabled()` + `feature_flags_changed` broadcast |
+| `get_feature_flags` | PostHog flag snapshot + `isCloudAgentsEnabled()` (env override + `code-cloud-agents` rollout flag) |
| `list_cloud_repositories` | `CloudSessionManager.listRepositories()` (GitHub integration) |
| `list_cloud_models` | `CloudSessionManager.listModels()` (account-scoped Usage-Billing, ClinePass, and ClineFree catalogs; model IDs use the Cline cloud transport) |
| `list_cloud_branches` | `CloudSessionManager.listBranches()` (paginated) |
diff --git a/apps/examples/desktop-app/sidecar/commands-settings.test.ts b/apps/examples/desktop-app/sidecar/commands-settings.test.ts
index 309d800c20..d03998b50e 100644
--- a/apps/examples/desktop-app/sidecar/commands-settings.test.ts
+++ b/apps/examples/desktop-app/sidecar/commands-settings.test.ts
@@ -9,7 +9,6 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { getCloudSessionManager } from "./cloud-sessions";
import { handleCommand } from "./commands";
import { createSidecarContext } from "./context";
-import { setCloudSessionsEnabled } from "./desktop-settings";
import {
getDesktopFeatureFlagsService,
resetDesktopFeatureFlagsForTesting,
@@ -79,7 +78,7 @@ describe("desktop settings commands", () => {
"list_chat_sessions",
"list_discovered_sessions",
"search_sessions",
- ])("hides cloud rows from %s unless rollout and user toggle are enabled", async (command) => {
+ ])("hides cloud rows from %s unless the rollout flag is enabled", async (command) => {
const { ctx } = createContext();
for (const target of ["local", "cloud"] as const) {
ctx.liveSessions.set(target, {
@@ -113,16 +112,13 @@ describe("desktop settings commands", () => {
.map((row) => row.sessionId)
.sort();
- expect(await rows()).toEqual(["local"]);
- expect(discovery).not.toHaveBeenCalled();
- setCloudSessionsEnabled(true);
expect(await rows()).toEqual(["cloud", "local"]);
discovery.mockImplementationOnce(async () => {
- setCloudSessionsEnabled(false);
+ process.env.CLINE_CODE_CLOUD_AGENTS = "0";
return cloudRows;
});
expect(await rows()).toEqual(["local"]);
- setCloudSessionsEnabled(true);
+ delete process.env.CLINE_CODE_CLOUD_AGENTS;
discovery.mockClear();
flags.hydrateCache({
userId: null,
@@ -172,45 +168,4 @@ describe("desktop settings commands", () => {
expect.objectContaining({ id: "cline-cloud/cloud-only" }),
);
});
-
- it("rejects a non-boolean cloud sessions toggle value", async () => {
- const { ctx, events } = createContext();
-
- await expect(
- handleCommand(ctx, "set_cloud_sessions_enabled", {
- cloud_sessions_enabled: "yes",
- }),
- ).rejects.toThrow("cloud_sessions_enabled must be a boolean");
- expect(events).toEqual([]);
- });
-
- it.each([
- true,
- false,
- ])("persists toggle %s and refreshes cloud history immediately", async (enabled) => {
- const { ctx, events } = createContext();
-
- await expect(
- handleCommand(ctx, "set_cloud_sessions_enabled", {
- cloud_sessions_enabled: enabled,
- }),
- ).resolves.toEqual({ cloudSessionsEnabled: enabled });
- expect(events).toEqual([
- { name: "cloud_sessions_changed", payload: { environmentId: "local" } },
- {
- name: "feature_flags_changed",
- payload: {
- cloudAgents: false,
- cloudAgentsAvailable: false,
- environmentId: "local",
- },
- },
- ]);
- await expect(
- handleCommand(ctx, "get_feature_flags", {}),
- ).resolves.toMatchObject({ cloudAgents: false });
- await expect(
- handleCommand(ctx, "get_desktop_settings", {}),
- ).resolves.toEqual({ cloudSessionsEnabled: enabled });
- });
});
diff --git a/apps/examples/desktop-app/sidecar/commands.ts b/apps/examples/desktop-app/sidecar/commands.ts
index d0d8df21fc..45662858b4 100644
--- a/apps/examples/desktop-app/sidecar/commands.ts
+++ b/apps/examples/desktop-app/sidecar/commands.ts
@@ -126,14 +126,9 @@ import {
resolveSidecarAskQuestion,
sendEventToClient,
} from "./context";
-import {
- readDesktopSettings,
- setCloudSessionsEnabled,
-} from "./desktop-settings";
import { writeDiagnosticsReport } from "./diagnostics";
import {
identifyDesktopFeatureFlagsAccount,
- isCloudAgentsAvailable,
isCloudAgentsEnabled,
refreshDesktopFeatureFlags,
} from "./feature-flags";
@@ -2207,8 +2202,6 @@ export async function handleCommand(
};
}
if (command === "get_feature_flags") {
- // Resolve flags in the sidecar: available shows the opt-in;
- // enabled requires both the rollout flag and the user's opt-in.
const snapshot = await refreshDesktopFeatureFlags({
logger: ctx.logger,
telemetry: ctx.telemetry,
@@ -2219,10 +2212,6 @@ export async function handleCommand(
logger: ctx.logger,
telemetry: ctx.telemetry,
}),
- cloudAgentsAvailable: isCloudAgentsAvailable({
- logger: ctx.logger,
- telemetry: ctx.telemetry,
- }),
};
}
if (command === "list_cloud_models") {
@@ -3221,9 +3210,6 @@ export async function handleCommand(
setAutoUpdateEnabledGlobally(args.auto_update_enabled);
return readGlobalSettings();
}
- if (command === "get_desktop_settings") {
- return readDesktopSettings();
- }
if (command === "export_diagnostics") {
const sessionIds = Array.isArray(args?.sessionIds)
? args.sessionIds.filter(
@@ -3234,18 +3220,6 @@ export async function handleCommand(
openFileInEditor(dirname(result.path));
return result;
}
- if (command === "set_cloud_sessions_enabled") {
- if (typeof args?.cloud_sessions_enabled !== "boolean") {
- throw new Error("cloud_sessions_enabled must be a boolean");
- }
- const settings = setCloudSessionsEnabled(args.cloud_sessions_enabled);
- broadcastEvent(ctx, "cloud_sessions_changed", {});
- broadcastEvent(ctx, "feature_flags_changed", {
- cloudAgents: isCloudAgentsEnabled(),
- cloudAgentsAvailable: isCloudAgentsAvailable(),
- });
- return settings;
- }
// ── Connector channels ─────────────────────────────────────────────
if (command === "list_connector_channels") {
diff --git a/apps/examples/desktop-app/sidecar/desktop-settings.test.ts b/apps/examples/desktop-app/sidecar/desktop-settings.test.ts
deleted file mode 100644
index e8d68da192..0000000000
--- a/apps/examples/desktop-app/sidecar/desktop-settings.test.ts
+++ /dev/null
@@ -1,62 +0,0 @@
-import {
- mkdirSync,
- mkdtempSync,
- readFileSync,
- rmSync,
- writeFileSync,
-} from "node:fs";
-import { tmpdir } from "node:os";
-import { dirname, join } from "node:path";
-import { afterEach, beforeEach, describe, expect, it } from "vitest";
-import {
- readDesktopSettings,
- resolveDesktopSettingsPath,
- setCloudSessionsEnabled,
-} from "./desktop-settings";
-
-let dataDir: string;
-
-beforeEach(() => {
- dataDir = mkdtempSync(join(tmpdir(), "cline-desktop-settings-"));
- process.env.CLINE_DATA_DIR = dataDir;
-});
-
-afterEach(() => {
- delete process.env.CLINE_DATA_DIR;
- rmSync(dataDir, { recursive: true, force: true });
-});
-
-describe("desktop settings", () => {
- it("defaults cloud sessions to off when no settings file exists", () => {
- expect(readDesktopSettings()).toEqual({ cloudSessionsEnabled: false });
- });
-
- it("persists the cloud sessions opt-in and reads it back", () => {
- expect(setCloudSessionsEnabled(true)).toEqual({
- cloudSessionsEnabled: true,
- });
- expect(readDesktopSettings()).toEqual({ cloudSessionsEnabled: true });
- expect(resolveDesktopSettingsPath().endsWith("code-settings.json")).toBe(
- true,
- );
- expect(
- JSON.parse(readFileSync(resolveDesktopSettingsPath(), "utf8")),
- ).toMatchObject({ cloudSessionsEnabled: true });
- expect(setCloudSessionsEnabled(false)).toEqual({
- cloudSessionsEnabled: false,
- });
- expect(readDesktopSettings()).toEqual({ cloudSessionsEnabled: false });
- });
-
- it("treats malformed files and non-boolean values as off", () => {
- mkdirSync(dirname(resolveDesktopSettingsPath()), { recursive: true });
- writeFileSync(resolveDesktopSettingsPath(), "{not json", "utf8");
- expect(readDesktopSettings()).toEqual({ cloudSessionsEnabled: false });
- writeFileSync(
- resolveDesktopSettingsPath(),
- JSON.stringify({ cloudSessionsEnabled: "yes" }),
- "utf8",
- );
- expect(readDesktopSettings()).toEqual({ cloudSessionsEnabled: false });
- });
-});
diff --git a/apps/examples/desktop-app/sidecar/desktop-settings.ts b/apps/examples/desktop-app/sidecar/desktop-settings.ts
deleted file mode 100644
index dc26e2fe7c..0000000000
--- a/apps/examples/desktop-app/sidecar/desktop-settings.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-import { mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
-import { dirname, join } from "node:path";
-import { resolveClineDataDir } from "@cline/shared/storage";
-
-/** Desktop-only preferences kept separate from strict shared global settings. */
-export type DesktopSettings = {
- /** Opt-in gate for cloud sessions while the feature is in preview. */
- cloudSessionsEnabled: boolean;
-};
-
-const DEFAULT_SETTINGS: DesktopSettings = {
- cloudSessionsEnabled: false,
-};
-
-export function resolveDesktopSettingsPath(): string {
- return join(resolveClineDataDir(), "settings", "code-settings.json");
-}
-
-export function readDesktopSettings(): DesktopSettings {
- let raw: string;
- try {
- raw = readFileSync(resolveDesktopSettingsPath(), "utf8");
- } catch {
- return { ...DEFAULT_SETTINGS };
- }
- try {
- const parsed = JSON.parse(raw) as Record;
- return {
- cloudSessionsEnabled: parsed.cloudSessionsEnabled === true,
- };
- } catch {
- return { ...DEFAULT_SETTINGS };
- }
-}
-
-export function writeDesktopSettings(settings: DesktopSettings): void {
- const filePath = resolveDesktopSettingsPath();
- mkdirSync(dirname(filePath), { recursive: true });
- // Avoid leaving torn settings if the process exits mid-write.
- const tempPath = `${filePath}.${process.pid}.tmp`;
- writeFileSync(tempPath, `${JSON.stringify(settings, null, 2)}\n`, "utf8");
- renameSync(tempPath, filePath);
-}
-
-export function setCloudSessionsEnabled(enabled: boolean): DesktopSettings {
- const next = { ...readDesktopSettings(), cloudSessionsEnabled: enabled };
- writeDesktopSettings(next);
- return next;
-}
diff --git a/apps/examples/desktop-app/sidecar/diagnostics.ts b/apps/examples/desktop-app/sidecar/diagnostics.ts
index 0595aa9484..3226878b30 100644
--- a/apps/examples/desktop-app/sidecar/diagnostics.ts
+++ b/apps/examples/desktop-app/sidecar/diagnostics.ts
@@ -11,7 +11,6 @@ import { arch, homedir, platform, release } from "node:os";
import { join } from "node:path";
import { readGlobalSettings, resolveClineDataDir } from "@cline/core";
import packageJson from "../package.json";
-import { readDesktopSettings } from "./desktop-settings";
import { readSessionManifest } from "./paths";
/** How much of each log file (from the end) is included in the report. */
@@ -88,7 +87,6 @@ export function buildDiagnosticsReport(
},
dataDir,
globalSettings: readGlobalSettings(),
- desktopSettings: readDesktopSettings(),
};
let text = `${JSON.stringify(report, null, 2)}\n`;
diff --git a/apps/examples/desktop-app/sidecar/feature-flags.test.ts b/apps/examples/desktop-app/sidecar/feature-flags.test.ts
index 82b5cc2a56..119325a172 100644
--- a/apps/examples/desktop-app/sidecar/feature-flags.test.ts
+++ b/apps/examples/desktop-app/sidecar/feature-flags.test.ts
@@ -337,45 +337,32 @@ describe("cloud agents gate", () => {
delete process.env.CLINE_CODE_CLOUD_AGENTS;
});
- it("is unavailable and disabled while the rollout flag is off", async () => {
- const { isCloudAgentsAvailable, isCloudAgentsEnabled } = await import(
- "./feature-flags"
- );
- expect(isCloudAgentsAvailable()).toBe(false);
+ it("is disabled while the rollout flag is off", async () => {
+ const { isCloudAgentsEnabled } = await import("./feature-flags");
expect(isCloudAgentsEnabled()).toBe(false);
});
it("does not enable a boolean rollout from a truthy variant payload", async () => {
- const { isCloudAgentsAvailable } = await import("./feature-flags");
+ const { isCloudAgentsEnabled } = await import("./feature-flags");
mocks.getFlagPayload.mockReturnValue("control");
- expect(isCloudAgentsAvailable()).toBe(false);
+ expect(isCloudAgentsEnabled()).toBe(false);
expect(mocks.getBooleanFlagEnabled).toHaveBeenCalledWith(
"code-cloud-agents",
);
});
- it("needs both the rollout flag and the user's opt-in to enable", async () => {
- const { isCloudAgentsEnabled, isCloudAgentsAvailable } = await import(
- "./feature-flags"
- );
- const { setCloudSessionsEnabled } = await import("./desktop-settings");
+ it("is enabled by the rollout flag alone", async () => {
+ const { isCloudAgentsEnabled } = await import("./feature-flags");
mocks.getBooleanFlagEnabled.mockImplementation(
(flag: unknown) => flag === "code-cloud-agents",
);
- expect(isCloudAgentsAvailable()).toBe(true);
- setCloudSessionsEnabled(false);
- expect(isCloudAgentsEnabled()).toBe(false);
- setCloudSessionsEnabled(true);
expect(isCloudAgentsEnabled()).toBe(true);
});
it("lets the env override force the gate in both directions", async () => {
- const { isCloudAgentsEnabled, isCloudAgentsAvailable } = await import(
- "./feature-flags"
- );
+ const { isCloudAgentsEnabled } = await import("./feature-flags");
mocks.getFlagPayload.mockReturnValue(undefined);
process.env.CLINE_CODE_CLOUD_AGENTS = "1";
- expect(isCloudAgentsAvailable()).toBe(true);
expect(isCloudAgentsEnabled()).toBe(true);
process.env.CLINE_CODE_CLOUD_AGENTS = "0";
expect(isCloudAgentsEnabled()).toBe(false);
diff --git a/apps/examples/desktop-app/sidecar/feature-flags.ts b/apps/examples/desktop-app/sidecar/feature-flags.ts
index 298724eddd..47eaeba7af 100644
--- a/apps/examples/desktop-app/sidecar/feature-flags.ts
+++ b/apps/examples/desktop-app/sidecar/feature-flags.ts
@@ -22,7 +22,6 @@ import {
} from "@cline/core/services/feature-flags/posthog";
import { FeatureFlag as SharedFeatureFlag } from "@cline/shared";
import { resolveClineDataDir } from "@cline/shared/storage";
-import { readDesktopSettings } from "./desktop-settings";
const FEATURE_FLAG_CODE_CLOUD_AGENTS = SharedFeatureFlag.CODE_CLOUD_AGENTS;
@@ -282,8 +281,8 @@ export function readCloudAgentsEnvOverride(): boolean | undefined {
return undefined;
}
-/** Whether the rollout makes cloud sessions available to this install. */
-export function isCloudAgentsAvailable(options?: {
+/** Whether the rollout enables cloud sessions for this install. */
+export function isCloudAgentsEnabled(options?: {
logger?: BasicLogger;
telemetry?: ITelemetryService;
}): boolean {
@@ -293,14 +292,3 @@ export function isCloudAgentsAvailable(options?: {
FEATURE_FLAG_CODE_CLOUD_AGENTS,
);
}
-
-/** Whether cloud sessions are both available and enabled by the user. */
-export function isCloudAgentsEnabled(options?: {
- logger?: BasicLogger;
- telemetry?: ITelemetryService;
-}): boolean {
- const override = readCloudAgentsEnvOverride();
- if (override !== undefined) return override;
- if (!isCloudAgentsAvailable(options)) return false;
- return readDesktopSettings().cloudSessionsEnabled;
-}
diff --git a/apps/examples/desktop-app/webview/app/page.tsx b/apps/examples/desktop-app/webview/app/page.tsx
index ac957758ca..9406775719 100644
--- a/apps/examples/desktop-app/webview/app/page.tsx
+++ b/apps/examples/desktop-app/webview/app/page.tsx
@@ -1276,20 +1276,8 @@ function ChatThreadPane({
});
};
fetchFlags();
- // Reflect Settings changes without restarting or switching accounts.
- const unsubscribe = desktopClient.subscribe(
- "feature_flags_changed",
- (payload) => {
- if (!cancelled) {
- setCloudAgentsFlagEnabled(
- Boolean((payload as { cloudAgents?: boolean })?.cloudAgents),
- );
- }
- },
- );
return () => {
cancelled = true;
- unsubscribe();
if (retryTimer !== undefined) window.clearTimeout(retryTimer);
};
}, [accountUserId]);
diff --git a/apps/examples/desktop-app/webview/components/views/settings/settings-view.test.tsx b/apps/examples/desktop-app/webview/components/views/settings/settings-view.test.tsx
index d694502f55..788d51f366 100644
--- a/apps/examples/desktop-app/webview/components/views/settings/settings-view.test.tsx
+++ b/apps/examples/desktop-app/webview/components/views/settings/settings-view.test.tsx
@@ -112,52 +112,3 @@ describe("SettingsView font size", () => {
expect(increaseButton?.disabled).toBe(true);
});
});
-
-describe("SettingsView cloud sessions rollout", () => {
- it.each([
- {
- caseName: "the rollout explicitly enables it",
- featureFlags: { cloudAgents: false, cloudAgentsAvailable: true },
- visible: true,
- },
- {
- caseName: "feature flags are unavailable",
- featureFlags: new Error("feature flags unavailable"),
- visible: false,
- },
- ])("shows the preview setting only when $caseName", async ({
- featureFlags,
- visible,
- }) => {
- invoke.mockImplementation(async (command: string) => {
- if (command === "get_feature_flags") {
- if (featureFlags instanceof Error) throw featureFlags;
- return featureFlags;
- }
- if (command === "get_desktop_settings") {
- return { cloudSessionsEnabled: false };
- }
- return {
- telemetryOptOut: false,
- autoUpdateEnabled: true,
- };
- });
-
- await act(async () => {
- root.render(
- ,
- );
- });
- await vi.waitFor(() =>
- expect(
- container.querySelector(
- '[role="switch"][aria-label="Cloud sessions"]',
- ) !== null,
- ).toBe(visible),
- );
- });
-});
diff --git a/apps/examples/desktop-app/webview/components/views/settings/settings-view.tsx b/apps/examples/desktop-app/webview/components/views/settings/settings-view.tsx
index c9c6f05cff..333f3d9027 100644
--- a/apps/examples/desktop-app/webview/components/views/settings/settings-view.tsx
+++ b/apps/examples/desktop-app/webview/components/views/settings/settings-view.tsx
@@ -699,32 +699,6 @@ function GeneralSettingsContent({
const [autoUpdateLoading, setAutoUpdateLoading] = useState(true);
const [autoUpdateSaving, setAutoUpdateSaving] = useState(false);
const [autoUpdateError, setAutoUpdateError] = useState(null);
- const [cloudSessionsEnabled, setCloudSessionsEnabled] = useState(false);
- const [cloudSessionsLoading, setCloudSessionsLoading] = useState(true);
- const [cloudSessionsSaving, setCloudSessionsSaving] = useState(false);
- const [cloudSessionsError, setCloudSessionsError] = useState(
- null,
- );
- // The environment override can differ from the stored opt-in.
- const [cloudSessionsEffective, setCloudSessionsEffective] = useState<
- boolean | null
- >(null);
- // Keep the preview hidden until the rollout service explicitly enables it.
- const [cloudSessionsAvailable, setCloudSessionsAvailable] = useState(false);
-
- const refreshCloudSessionsEffective = useCallback(async () => {
- try {
- const flags = await desktopClient.invoke<{
- cloudAgents?: boolean;
- cloudAgentsAvailable?: boolean;
- }>("get_feature_flags");
- setCloudSessionsEffective(Boolean(flags.cloudAgents));
- setCloudSessionsAvailable(flags.cloudAgentsAvailable === true);
- } catch {
- setCloudSessionsEffective(null);
- setCloudSessionsAvailable(false);
- }
- }, []);
useEffect(() => setAppIconLocation(appIconSurface(navigator.userAgent)), []);
useEffect(() => subscribeToAppFontSize(setFontSize), []);
@@ -734,45 +708,21 @@ function GeneralSettingsContent({
setTelemetryError(null);
setAutoUpdateLoading(true);
setAutoUpdateError(null);
- setCloudSessionsLoading(true);
- setCloudSessionsError(null);
- await Promise.all([
- (async () => {
- try {
- const settings = await desktopClient.invoke(
- "get_global_settings",
- );
- setTelemetryOptOut(settings.telemetryOptOut);
- setAutoUpdateEnabled(settings.autoUpdateEnabled);
- } catch (error) {
- const message =
- error instanceof Error ? error.message : String(error);
- setTelemetryError(message);
- setAutoUpdateError(message);
- } finally {
- setTelemetryLoading(false);
- setAutoUpdateLoading(false);
- }
- })(),
- (async () => {
- try {
- const desktopSettings = await desktopClient.invoke<{
- cloudSessionsEnabled: boolean;
- }>("get_desktop_settings");
- setCloudSessionsEnabled(
- Boolean(desktopSettings.cloudSessionsEnabled),
- );
- } catch (error) {
- setCloudSessionsError(
- error instanceof Error ? error.message : String(error),
- );
- } finally {
- setCloudSessionsLoading(false);
- }
- })(),
- refreshCloudSessionsEffective(),
- ]);
- }, [refreshCloudSessionsEffective]);
+ try {
+ const settings = await desktopClient.invoke(
+ "get_global_settings",
+ );
+ setTelemetryOptOut(settings.telemetryOptOut);
+ setAutoUpdateEnabled(settings.autoUpdateEnabled);
+ } catch (error) {
+ const message = error instanceof Error ? error.message : String(error);
+ setTelemetryError(message);
+ setAutoUpdateError(message);
+ } finally {
+ setTelemetryLoading(false);
+ setAutoUpdateLoading(false);
+ }
+ }, []);
useEffect(() => {
const timeoutId = window.setTimeout(() => {
@@ -821,26 +771,6 @@ function GeneralSettingsContent({
}
};
- const updateCloudSessionsEnabled = async (nextValue: boolean) => {
- const previousValue = cloudSessionsEnabled;
- setCloudSessionsEnabled(nextValue);
- setCloudSessionsSaving(true);
- setCloudSessionsError(null);
- try {
- const settings = await desktopClient.invoke<{
- cloudSessionsEnabled: boolean;
- }>("set_cloud_sessions_enabled", { cloud_sessions_enabled: nextValue });
- setCloudSessionsEnabled(Boolean(settings.cloudSessionsEnabled));
- await refreshCloudSessionsEffective();
- } catch (error) {
- const message = error instanceof Error ? error.message : String(error);
- setCloudSessionsEnabled(previousValue);
- setCloudSessionsError(message);
- } finally {
- setCloudSessionsSaving(false);
- }
- };
-
const updateTheme = (darkModeEnabled: boolean) => {
const nextTheme = darkModeEnabled ? "dark" : "light";
setTheme(setStoredHubTheme(nextTheme));
@@ -1051,46 +981,6 @@ function GeneralSettingsContent({
onCheckedChange={(checked) => void updateAutoUpdateEnabled(checked)}
/>
- {cloudSessionsAvailable ? (
-
-
-
- Cloud sessions
-
- Preview
-
-
-
- Run Cline on your GitHub repositories in secure cloud sandboxes.
- Adds a Cloud option to the new-session composer. Requires a
- Cline account with GitHub connected.
-
- {cloudSessionsError ? (
-
- Failed to update cloud sessions setting: {cloudSessionsError}
-
- ) : null}
- {cloudSessionsEffective !== null &&
- !cloudSessionsLoading &&
- cloudSessionsEffective !== cloudSessionsEnabled ? (
-
- Cloud sessions are currently{" "}
- {cloudSessionsEffective ? "enabled" : "disabled"} by the
- CLINE_CODE_CLOUD_AGENTS environment override, which takes
- precedence over this setting.
-
- ) : null}
-
-
- void updateCloudSessionsEnabled(checked)
- }
- />
-
- ) : null}
Telemetry
diff --git a/sdk/packages/shared/src/feature-flags.ts b/sdk/packages/shared/src/feature-flags.ts
index afc01524f9..4efa7adca7 100644
--- a/sdk/packages/shared/src/feature-flags.ts
+++ b/sdk/packages/shared/src/feature-flags.ts
@@ -1,7 +1,7 @@
export const FeatureFlag = {
/** Enables ClinePass provider/model list exposure in supported clients. */
CLINE_PASS: "ext-cline-pass",
- /** Makes the Cloud sessions opt-in visible in the Cline Code desktop app. */
+ /** Enables Cloud sessions in the Cline Code desktop app. */
CODE_CLOUD_AGENTS: "code-cloud-agents",
/** Shows the GitHub integration step in the desktop app */
CODE_ONBOARDING_GITHUB: "code-onboarding-github",
From c8f808b51e2ae80ac7fb7b41c6a780a0bdbdec89 Mon Sep 17 00:00:00 2001
From: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
Date: Thu, 15 Oct 2026 13:25:30 -0700
Subject: [PATCH 06/29] test(core): expect the OpenCode Go /inference/go/v1
endpoint in routing tests (#15051)
The catalog refresh in #15047 moved OpenCode Go from /zen/go/v1 to
/inference/go/v1 and updated the llms tests, but the core routing test
still asserted the old URL, failing sdk-test on main (and therefore
sdk-publish).
From ee7f4f5c669bac81cbf5745087930adf29765c9e Mon Sep 17 00:00:00 2001
From: Bee <68532117+abeatrix@users.noreply.github.com>
Date: Thu, 15 Oct 2026 14:42:30 -0700
Subject: [PATCH 07/29] fix(llms): retry stream errors and report terminal
failures to Langfuse (#15100)
* fix: report stream failures as errors in logs and Langfuse
* fix: correlate model failures and distinguish timeout aborts
* fix: enable three stream retries with terminal error reporting
* fix(llms): close failed attempt spans and retain trace call IDs
* docs(llms): clarify request and stream retry ownership
* fix(llms): classify attempt errors before exporting finished spans
* fix(llms): preserve successful model span completion timing
* fix(llms): use camelCase for error context fields
---
sdk/ARCHITECTURE.md | 15 ++
sdk/packages/agents/src/agent-runtime.test.ts | 38 +++
sdk/packages/agents/src/agent-runtime.ts | 11 +
.../telemetry/OpenTelemetryAdapter.test.ts | 25 ++
.../telemetry/OpenTelemetryAdapter.ts | 27 +-
sdk/packages/llms/src/providers/ai-sdk.ts | 224 ++++++++++------
.../src/providers/error-classification.ts | 5 +-
.../llms/src/providers/gateway.test.ts | 154 +++++++++++
.../src/services/langfuse-stream-telemetry.ts | 122 +++++++++
.../langfuse-telemetry.integration.test.ts | 252 +++++++++++++++++-
.../src/services/langfuse-telemetry.test.ts | 37 ++-
.../llms/src/services/langfuse-telemetry.ts | 26 +-
.../src/services/stream-error-telemetry.ts | 89 +++++++
.../shared/src/services/telemetry.test.ts | 22 ++
sdk/packages/shared/src/services/telemetry.ts | 18 ++
15 files changed, 958 insertions(+), 107 deletions(-)
create mode 100644 sdk/packages/llms/src/services/langfuse-stream-telemetry.ts
create mode 100644 sdk/packages/llms/src/services/stream-error-telemetry.ts
diff --git a/sdk/ARCHITECTURE.md b/sdk/ARCHITECTURE.md
index 785da2000f..0300ad4683 100644
--- a/sdk/ARCHITECTURE.md
+++ b/sdk/ARCHITECTURE.md
@@ -557,6 +557,21 @@ uses an isolated provider owned and disposed by `llms`. It does not replace or
shut down an ambient host provider. When both routes are configured, the relay
takes precedence so a request is not exported through both routes.
+Each issued agent model request gets a `modelRequestId`, shared by request-start
+and stream lifecycle events, provider error logs, and AI SDK runtime context.
+Transport retries within one AI SDK call share that ID; a new agent request gets
+a new ID, even within the same run and iteration. Provider errors also include
+run, agent, session, and conversation IDs when available. The AI SDK `callId`
+is recorded separately as `aiSdkCallId` on errors.
+
+Terminal stream failures notify both application error reporting and tracing
+integrations. Native timeout aborts are failures; explicit caller cancellation
+does not emit a provider `sdk.error`. AI SDK stream recovery permits three retries
+per model step. Recovered attempts do not produce terminal `sdk.error` reports or
+mark the operation as failed. Exhausted stream recovery disables the agent's
+whole-turn retry so the two retry budgets do not multiply. Previously streamed
+text and reasoning follow AI SDK's append semantics and may repeat on recovery.
+
### 7. Storage Adapters
Stateful persistence should be isolated behind adapter/service layers.
diff --git a/sdk/packages/agents/src/agent-runtime.test.ts b/sdk/packages/agents/src/agent-runtime.test.ts
index 349f0ce33c..fed7860b6d 100644
--- a/sdk/packages/agents/src/agent-runtime.test.ts
+++ b/sdk/packages/agents/src/agent-runtime.test.ts
@@ -3283,6 +3283,44 @@ describe("AgentRuntime", () => {
);
});
+ it("correlates model request starts with issued requests and assigns new IDs per request", async () => {
+ const { capture, telemetry } = createTelemetryMock();
+ const model = new ScriptedModel(
+ [0, 1].map(() => () => [
+ { type: "text-delta", text: "hello" } as AgentModelEvent,
+ { type: "finish", reason: "stop" } as AgentModelEvent,
+ ]),
+ );
+ const runtime = new AgentRuntime({
+ model,
+ telemetry,
+ sessionId: "session-test",
+ });
+ await runtime.run("first");
+ await runtime.continue("second");
+ const starts = capture.mock.calls
+ .map(([call]) => call)
+ .filter((call) => call.event === TASK_PROVIDER_REQUEST_STARTED_EVENT);
+ expect(starts).toHaveLength(2);
+ const ids = model.requests.map(
+ (request) =>
+ (request.options?.metadata as Record
).modelRequestId,
+ );
+ expect(ids.every((id) => typeof id === "string")).toBe(true);
+ expect(new Set(ids).size).toBe(2);
+ expect(starts.map((event) => event.properties.modelRequestId)).toEqual(ids);
+ for (const event of capture.mock.calls
+ .map(([call]) => call)
+ .filter((call) =>
+ [
+ TASK_PROVIDER_STREAM_STARTED_EVENT,
+ TASK_FIRST_CHUNK_RECEIVED_EVENT,
+ ].includes(call.event),
+ )) {
+ expect(ids).toContain(event.properties.modelRequestId);
+ }
+ });
+
it("captures task lifecycle telemetry around a successful model stream", async () => {
const { capture, telemetry } = createTelemetryMock();
const model = new ScriptedModel([
diff --git a/sdk/packages/agents/src/agent-runtime.ts b/sdk/packages/agents/src/agent-runtime.ts
index 57e96692b5..d29f0fce82 100644
--- a/sdk/packages/agents/src/agent-runtime.ts
+++ b/sdk/packages/agents/src/agent-runtime.ts
@@ -601,6 +601,7 @@ export class AgentRuntime {
private modelSteerController?: AbortController;
private readonly telemetryProviderId?: string;
private readonly telemetryModelId?: string;
+ private modelRequestId?: string;
constructor(config: AgentRuntimeConfig) {
this.telemetryProviderId =
@@ -792,6 +793,7 @@ export class AgentRuntime {
this.abortController = new AbortController();
this.state.runId = createUID("run");
+ this.modelRequestId = undefined;
this.state.status = "running";
this.state.iteration = 0;
this.state.pendingToolCalls = [];
@@ -1765,6 +1767,13 @@ export class AgentRuntime {
let request = prepared.request;
this.throwIfAborted();
+ this.modelRequestId = createUID("model_request", 21);
+ request = {
+ ...request,
+ options: mergeModelOptions(request.options, {
+ metadata: { modelRequestId: this.modelRequestId },
+ }),
+ };
this.captureTaskLifecycle(TASK_PROVIDER_REQUEST_STARTED_EVENT, {
durationMs: getTaskLifecycleDurationMs(),
phase: "provider_request_started",
@@ -2155,6 +2164,7 @@ export class AgentRuntime {
const sessionId = trimNonEmpty(this.config.sessionId);
captureTaskLifecycleEvent(this.config.telemetry, {
event,
+ modelRequestId: this.modelRequestId,
sessionId,
ulid: sessionId,
agentId: this.state.agentId,
@@ -2728,6 +2738,7 @@ export class AgentRuntime {
...(metadata as TelemetryProperties),
providerId: this.getTelemetryProviderId(),
modelId: this.getTelemetryModelId(),
+ modelRequestId: this.modelRequestId,
...(this.state.lastFinishReason
? { finishReason: this.state.lastFinishReason }
: {}),
diff --git a/sdk/packages/core/src/services/telemetry/OpenTelemetryAdapter.test.ts b/sdk/packages/core/src/services/telemetry/OpenTelemetryAdapter.test.ts
index 98bba87e4e..66498bd14f 100644
--- a/sdk/packages/core/src/services/telemetry/OpenTelemetryAdapter.test.ts
+++ b/sdk/packages/core/src/services/telemetry/OpenTelemetryAdapter.test.ts
@@ -1,9 +1,32 @@
+import { SeverityNumber } from "@opentelemetry/api-logs";
import type { LoggerProvider } from "@opentelemetry/sdk-logs";
import type { MeterProvider } from "@opentelemetry/sdk-metrics";
import { describe, expect, it, vi } from "vitest";
import { OpenTelemetryAdapter } from "./OpenTelemetryAdapter";
describe("OpenTelemetryAdapter", () => {
+ it.each([
+ ["error", "ERROR", SeverityNumber.ERROR],
+ ["warn", "WARN", SeverityNumber.WARN],
+ ["debug", "DEBUG", SeverityNumber.DEBUG],
+ ])("exports %s severity in the OTLP record", (severity, severityText, severityNumber) => {
+ const emit = vi.fn();
+ const adapter = new OpenTelemetryAdapter({
+ metadata: makeMetadata(),
+ loggerProvider: {
+ getLogger: () => ({ emit }),
+ } as unknown as LoggerProvider,
+ });
+ adapter.emit("sdk.error", { severity, error_message: "ConnectionClosed" });
+ expect(emit).toHaveBeenCalledWith(
+ expect.objectContaining({
+ body: "sdk.error",
+ severityText,
+ severityNumber,
+ attributes: expect.objectContaining({ severity }),
+ }),
+ );
+ });
it("emits events in the telemetry service log format", () => {
const emit = vi.fn();
const adapter = new OpenTelemetryAdapter({
@@ -28,6 +51,7 @@ describe("OpenTelemetryAdapter", () => {
expect(emit).toHaveBeenCalledWith({
severityText: "INFO",
+ severityNumber: SeverityNumber.INFO,
body: "task.created",
attributes: expect.objectContaining({
ulid: "01HXYZ",
@@ -57,6 +81,7 @@ describe("OpenTelemetryAdapter", () => {
expect(emit).toHaveBeenCalledWith({
severityText: "INFO",
+ severityNumber: SeverityNumber.INFO,
body: "user.opt_out",
attributes: expect.objectContaining({
_required: true,
diff --git a/sdk/packages/core/src/services/telemetry/OpenTelemetryAdapter.ts b/sdk/packages/core/src/services/telemetry/OpenTelemetryAdapter.ts
index ac0c4f089a..b12bacd6f6 100644
--- a/sdk/packages/core/src/services/telemetry/OpenTelemetryAdapter.ts
+++ b/sdk/packages/core/src/services/telemetry/OpenTelemetryAdapter.ts
@@ -1,5 +1,8 @@
import type { Meter } from "@opentelemetry/api";
-import type { Logger as OpenTelemetryLogger } from "@opentelemetry/api-logs";
+import {
+ type Logger as OpenTelemetryLogger,
+ SeverityNumber,
+} from "@opentelemetry/api-logs";
import type { LoggerProvider } from "@opentelemetry/sdk-logs";
import type { MeterProvider } from "@opentelemetry/sdk-metrics";
import type {
@@ -216,8 +219,10 @@ export class OpenTelemetryAdapter implements ITelemetryAdapter {
const attributes = this.flattenProperties(
this.buildAttributes(properties, required),
);
+ const severity = logSeverity(attributes.severity);
this.logger.emit({
- severityText: "INFO",
+ severityText: severity.text,
+ severityNumber: severity.number,
body: event,
attributes,
});
@@ -337,6 +342,24 @@ export class OpenTelemetryAdapter implements ITelemetryAdapter {
}
}
+function logSeverity(value: unknown): { text: string; number: SeverityNumber } {
+ switch (typeof value === "string" ? value.toLowerCase() : value) {
+ case "trace":
+ return { text: "TRACE", number: SeverityNumber.TRACE };
+ case "debug":
+ return { text: "DEBUG", number: SeverityNumber.DEBUG };
+ case "warn":
+ case "warning":
+ return { text: "WARN", number: SeverityNumber.WARN };
+ case "error":
+ return { text: "ERROR", number: SeverityNumber.ERROR };
+ case "fatal":
+ return { text: "FATAL", number: SeverityNumber.FATAL };
+ default:
+ return { text: "INFO", number: SeverityNumber.INFO };
+ }
+}
+
function isTelemetryPrimitive(
value: unknown,
): value is Exclude {
diff --git a/sdk/packages/llms/src/providers/ai-sdk.ts b/sdk/packages/llms/src/providers/ai-sdk.ts
index 890a7e207a..ec03af4322 100644
--- a/sdk/packages/llms/src/providers/ai-sdk.ts
+++ b/sdk/packages/llms/src/providers/ai-sdk.ts
@@ -44,6 +44,10 @@ import {
} from "ai";
import { nanoid } from "nanoid";
import type { AiSdkTelemetryDecision } from "../services/langfuse-telemetry";
+import {
+ createStreamErrorTelemetry,
+ isTimeoutReason,
+} from "../services/stream-error-telemetry";
import {
classifyProviderError,
isRetryableBeyondSdkRetries,
@@ -723,6 +727,12 @@ function buildAiSdkRuntimeContext(
? { conversationId: metadata.conversationId }
: {}),
...(typeof metadata.runId === "string" ? { runId: metadata.runId } : {}),
+ ...(typeof metadata.agentId === "string"
+ ? { agentId: metadata.agentId }
+ : {}),
+ ...(typeof metadata.modelRequestId === "string"
+ ? { modelRequestId: metadata.modelRequestId }
+ : {}),
...(typeof metadata.iteration === "number"
? { iteration: metadata.iteration }
: {}),
@@ -1075,21 +1085,16 @@ function getNestedUsageValue(
}
/**
- * AI SDK request-level retries for each model call (the SDK default is 2). The
- * SDK retries the *initial* request on transient failures — 429/5xx/network —
- * with exponential backoff that honors `retry-after` headers. It never sees an
- * error the provider emits *mid-stream* (OpenRouter's "Provider returned error"
- * arrives as a stream part after a 200), so the agent loop keeps its own
- * turn-level retry for those.
+ * AI SDK request-start retries (`maxRetries`) handle transient failures before
+ * streaming begins, with backoff that honors `retry-after` headers. Provider
+ * error parts received after streaming starts use `streamRetries` instead.
*
- * Each failure class has exactly one retrying layer, so the counts never
- * multiply: request-start failures belong to this setting (a `RetryError` is
- * terminal for the turn-level retry, see `isRetryableBeyondSdkRetries`);
- * pre-output socket deaths and empty responses belong to
- * `withEmptyResponseRetry`, which never sees request-start rejections; and
- * mid-stream provider errors belong to the turn-level retry alone.
+ * Exhausted request-start retries (`RetryError`) and terminal stream error parts
+ * do not trigger the agent's whole-turn retry, so the retry budgets do not
+ * multiply. See `captureStreamError` and `isRetryableBeyondSdkRetries`.
*/
const MODEL_REQUEST_MAX_RETRIES = 5;
+const MODEL_STREAM_MAX_RETRIES = 3;
type UsagePath = readonly [string] | readonly [string, string];
@@ -1454,6 +1459,14 @@ function extractGoogleThoughtMetadata(
* `extractErrorMessage`.
*/
interface CapturedStreamError {
+ error: unknown;
+ phase:
+ | "stream_callback"
+ | "stream_part"
+ | "stream_read"
+ | "result"
+ | "request_start"
+ | "timeout";
message: string;
errorClass: ProviderErrorClass;
/**
@@ -1461,9 +1474,9 @@ interface CapturedStreamError {
* while the structured error is still in hand and forwarded as
* `errorRetryable` on the `finish` event (the flattened message the agent
* loop receives cannot carry it). Transient by the AI SDK's own typed
- * `isRetryable` flag, except that a `RetryError` is terminal: the SDK
- * already spent its request-start retries, and the turn-level retry must
- * not multiply them.
+ * `isRetryable` flag, except that request-start RetryErrors and terminal
+ * stream error parts have already spent the SDK's retry budget. The
+ * turn-level retry must not multiply those attempts.
*/
retryable: boolean;
/**
@@ -1476,15 +1489,25 @@ interface CapturedStreamError {
baseMessage: string;
}
-function captureStreamError(error: unknown): CapturedStreamError {
+function captureStreamError(
+ error: unknown,
+ phase: CapturedStreamError["phase"] = "stream_callback",
+): CapturedStreamError {
const requestId = extractResponseRequestId(error);
const baseMessage = extractErrorMessage(error);
return {
+ error,
+ phase,
message: appendRequestId(baseMessage, requestId),
baseMessage,
- errorClass: classifyProviderError(error),
- retryable: isRetryableBeyondSdkRetries(error),
...(requestId ? { requestId } : {}),
+ errorClass: classifyProviderError(error),
+ // Error parts reaching the consumer have exhausted AI SDK stream recovery.
+ // Do not multiply its retry budget in the agent's whole-turn retry loop.
+ retryable:
+ phase !== "stream_callback" &&
+ phase !== "stream_part" &&
+ isRetryableBeyondSdkRetries(error),
};
}
@@ -1495,6 +1518,7 @@ async function* emitAiSdkEvents(
pricingValue?: unknown,
capturedError?: { current: CapturedStreamError | undefined },
modelToolAdapters?: BuiltModelTools,
+ reportError?: (error: CapturedStreamError) => Promise,
): AsyncIterable {
const emittedToolCallIds = new Set();
let finishReason: unknown;
@@ -1858,12 +1882,18 @@ async function* emitAiSdkEvents(
if (part.type === "error") {
streamError =
- capturedError?.current ?? captureStreamError(part.error);
+ capturedError?.current ??
+ captureStreamError(part.error, "stream_part");
break;
}
if (part.type === "abort") {
streamAborted = true;
+ if (isTimeoutReason(part.reason)) {
+ streamError =
+ capturedError?.current ??
+ captureStreamError(part.reason, "timeout");
+ }
break;
}
}
@@ -1875,7 +1905,8 @@ async function* emitAiSdkEvents(
} catch (error) {
// Prefer the real provider error from onError over the generic
// NoOutputGeneratedError the AI SDK throws when 0 steps are recorded.
- streamError = capturedError?.current ?? captureStreamError(error);
+ streamError =
+ capturedError?.current ?? captureStreamError(error, "stream_read");
}
if (!streamError) {
@@ -1986,7 +2017,8 @@ async function* emitAiSdkEvents(
usageToEmit = await stream.usage;
} catch (error) {
if (!streamError) {
- streamError = capturedError?.current ?? captureStreamError(error);
+ streamError =
+ capturedError?.current ?? captureStreamError(error, "result");
}
usageToEmit = finishUsage;
metadataToUse = finishProviderMetadata;
@@ -2003,6 +2035,8 @@ async function* emitAiSdkEvents(
};
}
+ if (streamError) await reportError?.(streamError);
+
const finishRequestId = requestId ?? streamError?.requestId;
yield {
type: "finish",
@@ -2144,6 +2178,70 @@ function createAiSdkProvider(
const capturedError: { current: CapturedStreamError | undefined } = {
current: undefined,
};
+ let recordTraceError: ((error: unknown) => Promise) | undefined;
+ let getAiSdkCallId: (() => string | undefined) | undefined;
+ let reportedError: CapturedStreamError | undefined;
+ const reportError = async (
+ captured: CapturedStreamError,
+ operation = "provider.stream",
+ ) => {
+ if (reportedError === captured) return;
+ // Explicit user/steering cancellation is not a provider failure.
+ if (
+ request.signal?.aborted &&
+ !isTimeoutReason(request.signal.reason) &&
+ !isTimeoutReason(captured.error)
+ )
+ return;
+ reportedError = captured;
+ const runtimeContext = buildAiSdkRuntimeContext(request, context);
+ const correlation = Object.fromEntries(
+ [
+ "runId",
+ "agentId",
+ "sessionId",
+ "conversationId",
+ "modelRequestId",
+ "iteration",
+ ].flatMap((key) =>
+ runtimeContext[key] === undefined
+ ? []
+ : [[key, runtimeContext[key]]],
+ ),
+ );
+ if (log?.error) {
+ log.error("[ai-sdk] provider error", {
+ ...correlation,
+ providerId: request.providerId,
+ error: captured.error,
+ severity: "error",
+ });
+ } else {
+ log?.log(`[ai-sdk] provider error: ${captured.message}`, {
+ providerId: request.providerId,
+ severity: "error",
+ });
+ }
+ captured.reported = captureSdkError(context.telemetry, {
+ component: "llms",
+ operation,
+ error: captured.error,
+ errorMessage: captured.baseMessage,
+ severity: "error",
+ handled: true,
+ context: {
+ ...correlation,
+ aiSdkCallId: getAiSdkCallId?.(),
+ errorPhase: captured.phase,
+ errorTurnRetryable: captured.retryable,
+ providerId: request.providerId,
+ modelId: request.modelId,
+ providerKind: kind,
+ requestId: captured.requestId,
+ },
+ });
+ await recordTraceError?.(captured.error);
+ };
try {
const provider = await createProviderModule(
kind,
@@ -2271,10 +2369,12 @@ function createAiSdkProvider(
yield { type: "finish", reason: "stop" };
return;
}
- const aiSdkTelemetry = await resolveGatewayAiSdkTelemetry(
- config.providerId,
- request,
+ const streamTelemetry = createStreamErrorTelemetry(
+ await resolveGatewayAiSdkTelemetry(config.providerId, request),
);
+ const aiSdkTelemetry = streamTelemetry.telemetry;
+ recordTraceError = streamTelemetry.recordError;
+ getAiSdkCallId = streamTelemetry.getCallId;
const externalToolExecutionDisabled =
providerDisablesExternalToolExecution(context);
const toolCallingDisabled =
@@ -2358,6 +2458,8 @@ function createAiSdkProvider(
tags: true,
conversationId: true,
runId: true,
+ agentId: true,
+ modelRequestId: true,
iteration: true,
providerId: true,
modelId: true,
@@ -2370,37 +2472,21 @@ function createAiSdkProvider(
? { stopWhen: stepCountIs(8) }
: {}),
...requestConfig,
+ streamRetries: MODEL_STREAM_MAX_RETRIES,
...(portableReasoning ? { reasoning: portableReasoning } : {}),
+ onLanguageModelCallStart: () => {
+ capturedError.current = undefined;
+ },
onError: ({ error: streamError }) => {
const captured = captureStreamError(streamError);
- const msg = captured.message;
capturedError.current = captured;
- if (log?.error) {
- log.error("[ai-sdk] stream error", {
- providerId: request.providerId,
- error: streamError,
- severity: "error",
- });
- } else if (log) {
- log.log(`[ai-sdk] stream error: ${msg}`, {
- providerId: request.providerId,
- severity: "error",
- });
- }
- captured.reported = captureSdkError(context.telemetry, {
- component: "llms",
- operation: "provider.stream",
- error: streamError,
- errorMessage: captured.baseMessage,
- severity: "error",
- handled: true,
- context: {
- providerId: request.providerId,
- modelId: request.modelId,
- providerKind: kind,
- requestId: captured.requestId,
- },
- });
+ streamTelemetry.captureError(streamError);
+ },
+ onAbort: async ({ reason }) => {
+ if (!isTimeoutReason(reason)) return;
+ const captured = captureStreamError(reason, "timeout");
+ capturedError.current = captured;
+ await reportError(captured);
},
}) as unknown as AiSdkStreamResult,
);
@@ -2418,46 +2504,22 @@ function createAiSdkProvider(
context.model.metadata?.pricing,
capturedError,
modelToolAdapters,
+ reportError,
);
} catch (error) {
suppressDanglingStreamPromises(stream);
// Prefer the real provider error captured in onError over the generic
// NoOutputGeneratedError that the AI SDK throws when 0 steps are recorded.
- const captured = capturedError.current ?? captureStreamError(error);
- const msg = captured.message;
- if (log?.error) {
- log.error("[ai-sdk] provider error", {
- providerId: request.providerId,
- error,
- severity: "error",
- });
- } else if (log) {
- log.log(`[ai-sdk] provider error: ${msg}`, {
- providerId: request.providerId,
- severity: "error",
- });
- }
- const reported = captureSdkError(context.telemetry, {
- component: "llms",
- operation: "provider.create_or_stream",
- error,
- errorMessage: captured.baseMessage,
- severity: "error",
- handled: true,
- context: {
- providerId: request.providerId,
- modelId: request.modelId,
- providerKind: kind,
- requestId: captured.requestId,
- },
- });
+ const captured =
+ capturedError.current ?? captureStreamError(error, "request_start");
+ await reportError(captured, "provider.create_or_stream");
yield {
type: "finish",
reason: "error",
- error: msg,
+ error: captured.message,
errorClass: captured.errorClass,
errorRetryable: captured.retryable,
- errorReported: reported || captured.reported,
+ errorReported: captured.reported,
};
}
},
diff --git a/sdk/packages/llms/src/providers/error-classification.ts b/sdk/packages/llms/src/providers/error-classification.ts
index 025e0564db..32c932536d 100644
--- a/sdk/packages/llms/src/providers/error-classification.ts
+++ b/sdk/packages/llms/src/providers/error-classification.ts
@@ -443,8 +443,9 @@ export function isRetryableProviderError(error: unknown): boolean {
* exhausted, surfaces a `RetryError`. Re-running such a turn would multiply
* the SDK's attempts by the agent's, so a `RetryError` is terminal here even
* when its final attempt looks transient. Everything else (most importantly a
- * provider error emitted mid-stream, which the SDK never retries) is judged by
- * {@link isRetryableProviderError}.
+ * raw stream-reader failures) is judged by {@link isRetryableProviderError}.
+ * Callers must separately disable whole-turn retries for error parts that
+ * already exhausted AI SDK stream recovery.
*/
export function isRetryableBeyondSdkRetries(error: unknown): boolean {
// Guarded like the other typed checks: `RetryError.isInstance` throws when
diff --git a/sdk/packages/llms/src/providers/gateway.test.ts b/sdk/packages/llms/src/providers/gateway.test.ts
index b501fa67a0..8ccded1727 100644
--- a/sdk/packages/llms/src/providers/gateway.test.ts
+++ b/sdk/packages/llms/src/providers/gateway.test.ts
@@ -723,6 +723,8 @@ describe("sdk-gateway", () => {
tags: true,
conversationId: true,
runId: true,
+ agentId: true,
+ modelRequestId: true,
iteration: true,
providerId: true,
modelId: true,
@@ -1647,6 +1649,7 @@ describe("sdk-gateway", () => {
error: `Image media exceeds the ${DEFAULT_MAX_IMAGE_ENCODED_BYTES} byte encoded limit`,
errorClass: "unknown",
errorRetryable: false,
+ errorReported: false,
},
]);
});
@@ -2481,6 +2484,7 @@ describe("sdk-gateway", () => {
error: "OpenAI image generation tool returned no supported image output",
errorClass: "unknown",
errorRetryable: false,
+ errorReported: false,
});
});
@@ -2700,6 +2704,153 @@ describe("sdk-gateway", () => {
error: "Invalid API key",
errorClass: "unknown",
errorRetryable: false,
+ errorReported: false,
+ });
+ });
+
+ it("reports a thrown socket reader error at the provider boundary", async () => {
+ const error = Object.assign(
+ new Error("The socket connection was closed unexpectedly"),
+ {
+ code: "ConnectionClosed",
+ },
+ );
+ streamTextSpy.mockReturnValue({
+ fullStream: (async function* () {
+ yield { type: "reasoning-delta", text: "partial reasoning" };
+ throw error;
+ })(),
+ });
+ const { telemetry, capture } = createTelemetryMock();
+ const logger = { error: vi.fn(), log: vi.fn() };
+ const gateway = createGateway({
+ telemetry,
+ logger,
+ providerConfigs: [{ providerId: "openai-native", apiKey: "test" }],
+ });
+ const events = await collect(
+ await gateway.stream({
+ providerId: "openai-native",
+ modelId: "gpt-5-mini",
+ messages: baseMessages,
+ metadata: {
+ runId: "run-test",
+ agentId: "agent-test",
+ sessionId: "session-test",
+ conversationId: "conversation-test",
+ modelRequestId: "request-test",
+ iteration: 3,
+ },
+ }),
+ );
+ expect(logger.error).toHaveBeenCalledWith(
+ expect.any(String),
+ expect.objectContaining({ error, severity: "error" }),
+ );
+ expect(capture).toHaveBeenCalledWith({
+ event: "sdk.error",
+ properties: expect.objectContaining({
+ component: "llms",
+ operation: "provider.stream",
+ severity: "error",
+ runId: "run-test",
+ agentId: "agent-test",
+ sessionId: "session-test",
+ conversationId: "conversation-test",
+ modelRequestId: "request-test",
+ iteration: 3,
+ errorPhase: "stream_read",
+ error_code: "ConnectionClosed",
+ error_message: error.message,
+ }),
+ });
+ expect(events.at(-1)).toMatchObject({
+ type: "finish",
+ reason: "error",
+ error: error.message,
+ errorReported: true,
+ });
+ expect(
+ capture.mock.calls.filter(([call]) => call.event === "sdk.error"),
+ ).toHaveLength(1);
+ });
+
+ it.each([
+ "AbortError",
+ "TimeoutError",
+ ])("classifies %s cancellation independently of provider failure", async (name) => {
+ const controller = new AbortController();
+ const reason = new DOMException("request aborted", name);
+ controller.abort(reason);
+ streamTextSpy.mockImplementation(
+ (input: { onAbort?: (event: { reason: unknown }) => Promise }) => {
+ return {
+ fullStream: (async function* () {
+ await input.onAbort?.({ reason });
+ yield { type: "abort", reason };
+ })(),
+ };
+ },
+ );
+ const { telemetry, capture } = createTelemetryMock();
+ const logger = { error: vi.fn(), log: vi.fn() };
+ const gateway = createGateway({
+ telemetry,
+ logger,
+ providerConfigs: [{ providerId: "openai-native", apiKey: "test" }],
+ });
+ await collect(
+ await gateway.stream({
+ providerId: "openai-native",
+ modelId: "gpt-5-mini",
+ messages: baseMessages,
+ signal: controller.signal,
+ }),
+ );
+ const errors = capture.mock.calls.filter(
+ ([call]) => call.event === "sdk.error",
+ );
+ if (name === "TimeoutError") {
+ expect(errors).toHaveLength(1);
+ expect(errors[0]?.[0].properties).toMatchObject({
+ error_type: "TimeoutError",
+ errorPhase: "timeout",
+ severity: "error",
+ });
+ } else {
+ expect(errors).toHaveLength(0);
+ expect(logger.error).not.toHaveBeenCalled();
+ }
+ });
+
+ it("uses three SDK stream retries without allowing another whole-turn retry", async () => {
+ const error = {
+ message: "upstream timeout",
+ code: "504",
+ isRetryable: true,
+ };
+ streamTextSpy.mockImplementation(
+ (input: { onError?: (event: { error: unknown }) => void }) => {
+ input.onError?.({ error });
+ return { fullStream: makeStreamParts([{ type: "error", error }]) };
+ },
+ );
+ const gateway = createGateway({
+ providerConfigs: [{ providerId: "openai-native", apiKey: "test" }],
+ });
+ const events = await collect(
+ await gateway.stream({
+ providerId: "openai-native",
+ modelId: "gpt-5-mini",
+ messages: baseMessages,
+ }),
+ );
+ expect(streamTextSpy.mock.calls.at(-1)?.[0]).toMatchObject({
+ streamRetries: 3,
+ });
+ expect(events.at(-1)).toMatchObject({
+ reason: "error",
+ errorRetryable: false,
});
});
@@ -2957,6 +3108,7 @@ describe("sdk-gateway", () => {
error: "Invalid API key",
errorClass: "unknown",
errorRetryable: false,
+ errorReported: false,
},
]);
});
@@ -2998,6 +3150,7 @@ describe("sdk-gateway", () => {
error: "prompt is too long: 213462 tokens > 200000 maximum",
errorClass: "context_window_exceeded",
errorRetryable: false,
+ errorReported: false,
});
});
@@ -3035,6 +3188,7 @@ describe("sdk-gateway", () => {
error: "Instructions are required",
errorClass: "unknown",
errorRetryable: false,
+ errorReported: false,
});
});
diff --git a/sdk/packages/llms/src/services/langfuse-stream-telemetry.ts b/sdk/packages/llms/src/services/langfuse-stream-telemetry.ts
new file mode 100644
index 0000000000..24648531ef
--- /dev/null
+++ b/sdk/packages/llms/src/services/langfuse-stream-telemetry.ts
@@ -0,0 +1,122 @@
+import { LangfuseVercelAiSdkIntegration } from "@langfuse/vercel-ai-sdk";
+import { type Span, SpanStatusCode, type Tracer } from "@opentelemetry/api";
+import type {
+ LanguageModelCallEndEvent,
+ LanguageModelCallStartEvent,
+ ToolSet,
+} from "ai";
+import type { StreamAttemptTelemetry } from "./stream-error-telemetry";
+
+/** Owns the lifetime of model attempts that end without an AI SDK finish event. */
+export class LangfuseStreamTelemetry
+ extends LangfuseVercelAiSdkIntegration
+ implements StreamAttemptTelemetry
+{
+ private readonly attempts = new Map();
+ private readonly completedAttempts = new Map<
+ string,
+ LanguageModelCallEndEvent
+ >();
+ private startingCallId?: string;
+
+ constructor(tracer: Tracer) {
+ super({
+ tracer: {
+ startSpan: (name, options, context) => {
+ const span = tracer.startSpan(name, options, context);
+ if (this.startingCallId) this.attempts.set(this.startingCallId, span);
+ return span;
+ },
+ startActiveSpan: tracer.startActiveSpan.bind(tracer),
+ },
+ });
+ }
+
+ override onLanguageModelCallStart(event: LanguageModelCallStartEvent): void {
+ // A retry can cancel the failed stream before its finish event is read.
+ this.endAttempt(event.callId);
+ this.startingCallId = event.callId;
+ try {
+ super.onLanguageModelCallStart(event);
+ } finally {
+ this.startingCallId = undefined;
+ }
+ }
+
+ override onLanguageModelCallEnd(
+ event: LanguageModelCallEndEvent,
+ ): void {
+ // A failed finish can be read ahead of the application's error callback.
+ // Defer that completion so the original error can still mark the span.
+ // Successful calls keep their original lifetime and latency measurement.
+ this.completedAttempts.set(event.callId, event);
+ if (event.finishReason !== "error") this.endAttempt(event.callId);
+ }
+
+ private endAttempt(callId: string): void {
+ const completed = this.completedAttempts.get(callId);
+ if (completed) super.onLanguageModelCallEnd(completed);
+ else this.attempts.get(callId)?.end();
+ this.completedAttempts.delete(callId);
+ this.attempts.delete(callId);
+ }
+
+ override onStepEnd(
+ event: Parameters[0],
+ ): void {
+ this.endAttempt(event.callId);
+ super.onStepEnd(event);
+ }
+
+ onLanguageModelCallError({
+ callId,
+ error,
+ }: {
+ callId: string;
+ error: unknown;
+ }): void {
+ const span = this.attempts.get(callId);
+ if (!span) return;
+ const message =
+ error instanceof Error
+ ? error.message
+ : typeof error === "object" &&
+ error !== null &&
+ "message" in error &&
+ typeof error.message === "string"
+ ? error.message
+ : "Provider stream failed";
+ span.recordException(error instanceof Error ? error : { message });
+ span.setStatus({ code: SpanStatusCode.ERROR, message });
+ }
+
+ override onError(error: unknown): void {
+ if (
+ typeof error === "object" &&
+ error !== null &&
+ "callId" in error &&
+ typeof error.callId === "string"
+ ) {
+ this.onLanguageModelCallError({
+ callId: error.callId,
+ error: "error" in error ? error.error : error,
+ });
+ this.endAttempt(error.callId);
+ }
+ super.onError(error);
+ }
+
+ override onEnd(
+ event: Parameters[0],
+ ): void {
+ this.endAttempt(event.callId);
+ super.onEnd(event);
+ }
+
+ override onAbort(
+ event: Parameters[0],
+ ): void {
+ this.endAttempt(event.callId);
+ super.onAbort(event);
+ }
+}
diff --git a/sdk/packages/llms/src/services/langfuse-telemetry.integration.test.ts b/sdk/packages/llms/src/services/langfuse-telemetry.integration.test.ts
index 8d113dbca9..e7d94a533d 100644
--- a/sdk/packages/llms/src/services/langfuse-telemetry.integration.test.ts
+++ b/sdk/packages/llms/src/services/langfuse-telemetry.integration.test.ts
@@ -2,7 +2,7 @@ import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import path from "node:path";
import { markOtlpTraceRelayProvider } from "@cline/shared";
-import { context, trace } from "@opentelemetry/api";
+import { context, SpanStatusCode, trace } from "@opentelemetry/api";
import {
InMemorySpanExporter,
NodeTracerProvider,
@@ -16,6 +16,7 @@ import {
resetLangfuseTelemetryForTests,
resolveAiSdkTelemetry,
} from "./langfuse-telemetry";
+import { createStreamErrorTelemetry } from "./stream-error-telemetry";
const { settingsPath, directExporters } = vi.hoisted(() => ({
settingsPath: { current: "" },
@@ -76,6 +77,255 @@ afterEach(async () => {
vi.unstubAllEnvs();
});
+it.each([
+ ["relay", "error part"],
+ ["relay", "reader rejection"],
+ ["direct", "error part"],
+ ["direct", "reader rejection"],
+ ["relay", "timeout abort"],
+ ["relay", "caller abort"],
+ ["direct", "timeout abort"],
+ ["direct", "caller abort"],
+])("exports %s %s with the correct Langfuse observation status", async (route, failure) => {
+ if (route === "direct") {
+ trace.disable();
+ context.disable();
+ vi.stubEnv("LANGFUSE_BASE_URL", "https://langfuse.example");
+ vi.stubEnv("LANGFUSE_PUBLIC_KEY", "public-key");
+ vi.stubEnv("LANGFUSE_SECRET_KEY", "secret-key");
+ }
+ const error = failure.endsWith("abort")
+ ? new DOMException(
+ "test abort",
+ failure === "timeout abort" ? "TimeoutError" : "AbortError",
+ )
+ : Object.assign(
+ new Error("The socket connection was closed unexpectedly"),
+ {
+ code: "ConnectionClosed",
+ },
+ );
+ const { telemetry, recordError } = createStreamErrorTelemetry(
+ await resolveAiSdkTelemetry("cline", "socket-test"),
+ );
+ let index = 0;
+ const abortController = new AbortController();
+ const result = streamText({
+ model: new MockLanguageModelV4({
+ provider: "cline",
+ modelId: "socket-test",
+ doStream: async () => ({
+ stream: new ReadableStream({
+ pull(controller) {
+ switch (index++) {
+ case 0:
+ controller.enqueue({ type: "stream-start", warnings: [] });
+ break;
+ case 1:
+ controller.enqueue({ type: "text-start", id: "text" });
+ break;
+ case 2:
+ controller.enqueue({
+ type: "text-delta",
+ id: "text",
+ delta: "partial output",
+ });
+ break;
+ default:
+ if (failure.endsWith("abort")) {
+ abortController.abort(error);
+ controller.enqueue({
+ type: "text-delta",
+ id: "text",
+ delta: "discarded",
+ });
+ } else if (failure === "reader rejection")
+ controller.error(error);
+ else {
+ controller.enqueue({ type: "error", error });
+ controller.close();
+ }
+ }
+ },
+ }),
+ }),
+ }),
+ prompt: "test",
+ abortSignal: abortController.signal,
+ telemetry,
+ onError: ({ error }) => recordError(error),
+ });
+ // A failed stream also rejects its result promises.
+ for (const promise of [
+ result.usage,
+ result.totalUsage,
+ result.finishReason,
+ result.steps,
+ result.text,
+ result.response,
+ ]) {
+ promise.catch(() => {});
+ }
+ try {
+ for await (const part of result.fullStream) {
+ if (part.type === "error") await recordError(part.error);
+ }
+ } catch (error) {
+ await recordError(error);
+ }
+ await provider.forceFlush();
+ const errorExporter = route === "direct" ? directExporters[0] : exporter;
+ expect(errorExporter).toBeDefined();
+ const spans = errorExporter?.getFinishedSpans() ?? [];
+ expect(spans.length).toBeGreaterThan(0);
+ expect(
+ spans.every(
+ (span) =>
+ span.status.code ===
+ (failure === "caller abort"
+ ? SpanStatusCode.UNSET
+ : SpanStatusCode.ERROR),
+ ),
+ ).toBe(true);
+ expect(
+ spans.some((span) =>
+ span.events.some(
+ (event) =>
+ event.name === "exception" &&
+ event.attributes?.["exception.message"] === error.message,
+ ),
+ ),
+ ).toBe(failure !== "caller abort");
+ const count = spans.length;
+ await recordError(error);
+ await provider.forceFlush();
+ expect(errorExporter?.getFinishedSpans()).toHaveLength(count);
+});
+
+it.each([
+ ["relay", 2, true],
+ ["relay", 4, true],
+ ["relay", 2, false],
+ ["relay", 4, false],
+ ["direct", 2, true],
+ ["direct", 4, true],
+ ["direct", 2, false],
+ ["direct", 4, false],
+] as const)("exports %s attempts after %s failures (finish event: %s)", async (route, failures, hasFinish) => {
+ if (route === "direct") {
+ trace.disable();
+ context.disable();
+ vi.stubEnv("LANGFUSE_BASE_URL", "https://langfuse.example");
+ vi.stubEnv("LANGFUSE_PUBLIC_KEY", "public-key");
+ vi.stubEnv("LANGFUSE_SECRET_KEY", "secret-key");
+ }
+ let calls = 0;
+ const streamTelemetry = createStreamErrorTelemetry(
+ await resolveAiSdkTelemetry("cline", "retry-test"),
+ );
+ const result = streamText({
+ model: new MockLanguageModelV4({
+ provider: "cline",
+ modelId: "retry-test",
+ doStream: async () => {
+ // Every earlier attempt must already be exported before issuing a retry.
+ const completed = (route === "direct" ? directExporters[0] : exporter)
+ .getFinishedSpans()
+ .filter((span) => span.name === "chat retry-test");
+ expect(completed).toHaveLength(calls);
+ const fail = calls++ < failures;
+ return {
+ stream: new ReadableStream({
+ start(controller) {
+ controller.enqueue({ type: "stream-start", warnings: [] });
+ if (fail)
+ controller.enqueue({
+ type: "error",
+ error: {
+ message: "upstream timeout",
+ type: "timeout_error",
+ code: "504",
+ },
+ });
+ else {
+ controller.enqueue({ type: "text-start", id: "text" });
+ controller.enqueue({
+ type: "text-delta",
+ id: "text",
+ delta: "recovered",
+ });
+ controller.enqueue({ type: "text-end", id: "text" });
+ }
+ if (!fail || hasFinish)
+ controller.enqueue({
+ type: "finish",
+ finishReason: {
+ unified: fail ? "error" : "stop",
+ raw: undefined,
+ },
+ usage: {
+ inputTokens: {
+ total: 1,
+ noCache: 1,
+ cacheRead: 0,
+ cacheWrite: 0,
+ },
+ outputTokens: { total: 1, text: 1, reasoning: 0 },
+ },
+ });
+ controller.close();
+ },
+ }),
+ };
+ },
+ }),
+ prompt: "test",
+ streamRetries: 3,
+ maxRetries: 0,
+ telemetry: streamTelemetry.telemetry,
+ onError: async ({ error }) => {
+ // The SDK may read the finish event ahead of a slower error consumer.
+ await new Promise((resolve) => setImmediate(resolve));
+ streamTelemetry.captureError(error);
+ },
+ });
+ for (const promise of [
+ result.usage,
+ result.totalUsage,
+ result.finishReason,
+ result.steps,
+ result.text,
+ result.response,
+ ])
+ promise.catch(() => {});
+ // Let the producer complete before the event consumer reports errors.
+ await result.text.catch(() => {});
+ expect(streamTelemetry.getCallId()).toEqual(expect.any(String));
+ const errors: unknown[] = [];
+ for await (const part of result.fullStream) {
+ if (part.type === "error") {
+ errors.push(part.error);
+ await streamTelemetry.recordError(part.error);
+ }
+ }
+ await provider.forceFlush();
+ expect(calls).toBe(failures === 2 ? 3 : 4);
+ expect(errors).toHaveLength(failures === 2 ? 0 : 1);
+ const spans = (
+ route === "direct" ? directExporters[0] : exporter
+ ).getFinishedSpans();
+ const attempts = spans.filter((span) => span.name === "chat retry-test");
+ expect(attempts).toHaveLength(calls);
+ expect(
+ attempts.filter((span) => span.status.code === SpanStatusCode.ERROR),
+ ).toHaveLength(Math.min(failures, 4));
+ const roots = spans.filter((span) => !span.parentSpanContext);
+ expect(roots).toHaveLength(1);
+ expect(roots[0]?.status.code).toBe(
+ failures === 2 ? SpanStatusCode.UNSET : SpanStatusCode.ERROR,
+ );
+});
+
async function runStream(
telemetry = { isEnabled: true } as Awaited<
ReturnType
diff --git a/sdk/packages/llms/src/services/langfuse-telemetry.test.ts b/sdk/packages/llms/src/services/langfuse-telemetry.test.ts
index bf3692b7e0..71764169b2 100644
--- a/sdk/packages/llms/src/services/langfuse-telemetry.test.ts
+++ b/sdk/packages/llms/src/services/langfuse-telemetry.test.ts
@@ -20,7 +20,11 @@ const {
spanProcessorConfigSpy: vi.fn(),
integrationOptionsSpy: vi.fn(),
telemetryStartSpy: vi.fn(),
- globalGetTracerSpy: vi.fn(() => ({ name: "managed-global-tracer" })),
+ globalGetTracerSpy: vi.fn(() => ({
+ name: "managed-global-tracer",
+ startSpan: vi.fn(),
+ startActiveSpan: vi.fn(),
+ })),
getDelegateSpy: vi.fn(),
getTracerProviderSpy: vi.fn(),
forceFlushSpy: vi.fn(),
@@ -69,7 +73,11 @@ vi.mock("@langfuse/vercel-ai-sdk", () => ({
class MockNodeTracerProvider {
forceFlush = vi.fn(async () => undefined);
shutdown = vi.fn(async () => undefined);
- getTracer = vi.fn(() => ({ name: "direct-langfuse-tracer" }));
+ getTracer = vi.fn(() => ({
+ name: "direct-langfuse-tracer",
+ startSpan: vi.fn(),
+ startActiveSpan: vi.fn(),
+ }));
constructor(_options: unknown) {
tracerProviderInstances.push(this);
@@ -180,7 +188,10 @@ describe("langfuse telemetry", () => {
const decision = await resolveAiSdkTelemetry("cline");
expect(decision.isEnabled).toBe(true);
expect(integrationOptionsSpy).toHaveBeenCalledWith({
- tracer: { name: "direct-langfuse-tracer" },
+ tracer: {
+ startSpan: expect.any(Function),
+ startActiveSpan: expect.any(Function),
+ },
});
await disposeLangfuseTelemetry();
expect(forceFlushSpy).not.toHaveBeenCalled();
@@ -225,7 +236,10 @@ describe("langfuse telemetry", () => {
expect(relay.integrations).not.toBe(direct.integrations);
expect(relay.recordInputs).toBe(false);
expect(integrationOptionsSpy).toHaveBeenLastCalledWith({
- tracer: { name: "managed-global-tracer" },
+ tracer: {
+ startSpan: expect.any(Function),
+ startActiveSpan: expect.any(Function),
+ },
});
});
@@ -269,7 +283,10 @@ describe("langfuse telemetry", () => {
recordOutputs: false,
});
expect(integrationOptionsSpy).toHaveBeenLastCalledWith({
- tracer: { name: "managed-global-tracer" },
+ tracer: {
+ startSpan: expect.any(Function),
+ startActiveSpan: expect.any(Function),
+ },
});
} else {
expect(decision).toEqual({ isEnabled: false });
@@ -562,7 +579,10 @@ describe("langfuse telemetry", () => {
});
expect(spanProcessorConfigSpy).toHaveBeenCalledWith(genericConfig);
expect(integrationOptionsSpy).toHaveBeenCalledWith({
- tracer: { name: "direct-langfuse-tracer" },
+ tracer: {
+ startSpan: expect.any(Function),
+ startActiveSpan: expect.any(Function),
+ },
});
});
@@ -590,7 +610,10 @@ describe("langfuse telemetry", () => {
expect(decision.isEnabled).toBe(true);
expect(integrationOptionsSpy).toHaveBeenCalledWith({
- tracer: { name: "direct-langfuse-tracer" },
+ tracer: {
+ startSpan: expect.any(Function),
+ startActiveSpan: expect.any(Function),
+ },
});
expect(globalGetTracerSpy).not.toHaveBeenCalled();
});
diff --git a/sdk/packages/llms/src/services/langfuse-telemetry.ts b/sdk/packages/llms/src/services/langfuse-telemetry.ts
index e459025655..e15afa7858 100644
--- a/sdk/packages/llms/src/services/langfuse-telemetry.ts
+++ b/sdk/packages/llms/src/services/langfuse-telemetry.ts
@@ -1,5 +1,5 @@
import type { Tracer } from "@opentelemetry/api";
-import type { Telemetry } from "ai";
+import type { StreamAttemptTelemetry } from "./stream-error-telemetry";
type DirectLangfuseTelemetryConfig = {
baseUrl: string;
@@ -10,7 +10,7 @@ type DirectLangfuseTelemetryConfig = {
};
type DirectLangfuseTelemetryRuntime = {
- integration: Telemetry;
+ integration: StreamAttemptTelemetry;
tracerProvider: {
forceFlush(): Promise;
shutdown(): Promise;
@@ -173,7 +173,7 @@ function isClineProviderId(providerId: string): boolean {
export type AiSdkTelemetryDecision = {
isEnabled: boolean;
- integrations?: Telemetry;
+ integrations?: StreamAttemptTelemetry | StreamAttemptTelemetry[];
recordInputs?: boolean;
recordOutputs?: boolean;
};
@@ -250,14 +250,12 @@ export async function resolveAiSdkTelemetry(
return TELEMETRY_DISABLED;
}
}
- const { LangfuseVercelAiSdkIntegration } = await import(
- "@langfuse/vercel-ai-sdk"
+ const { LangfuseStreamTelemetry } = await import(
+ "./langfuse-stream-telemetry"
);
// Resolve the host tracer per call so remote-config replacement cannot
// leave a cached integration attached to a shut-down provider.
- const integration = new LangfuseVercelAiSdkIntegration({
- tracer: relayTracer,
- });
+ const integration = new LangfuseStreamTelemetry(relayTracer);
const recordContent = isEnvTruthy(process.env.CLINE_TRACE_RECORD_CONTENT);
return {
isEnabled: true,
@@ -344,7 +342,7 @@ function fnv1a32(value: string): number {
async function ensureDirectLangfuseIntegration(
providerId: string,
config: DirectLangfuseTelemetryConfig,
-): Promise {
+): Promise {
const configKey = JSON.stringify(config);
let runtimePromise = directLangfuseRuntimes.get(configKey);
if (!runtimePromise) {
@@ -403,11 +401,11 @@ async function initializeDirectLangfuseTelemetry(
await ensureLangfuseContextManager();
const [
{ LangfuseSpanProcessor },
- { LangfuseVercelAiSdkIntegration },
+ { LangfuseStreamTelemetry },
{ NodeTracerProvider },
] = await Promise.all([
import("@langfuse/otel"),
- import("@langfuse/vercel-ai-sdk"),
+ import("./langfuse-stream-telemetry"),
import("@opentelemetry/sdk-trace-node"),
]);
@@ -415,9 +413,9 @@ async function initializeDirectLangfuseTelemetry(
const tracerProvider = new NodeTracerProvider({
spanProcessors: [spanProcessor],
});
- const integration = new LangfuseVercelAiSdkIntegration({
- tracer: tracerProvider.getTracer("cline-langfuse-direct"),
- });
+ const integration = new LangfuseStreamTelemetry(
+ tracerProvider.getTracer("cline-langfuse-direct"),
+ );
debugLangfuse(
`created isolated direct exporter baseUrl=${config.baseUrl} environment=${config.environment ?? ""}`,
);
diff --git a/sdk/packages/llms/src/services/stream-error-telemetry.ts b/sdk/packages/llms/src/services/stream-error-telemetry.ts
new file mode 100644
index 0000000000..9dfa8145fa
--- /dev/null
+++ b/sdk/packages/llms/src/services/stream-error-telemetry.ts
@@ -0,0 +1,89 @@
+import type { Telemetry } from "ai";
+import type { AiSdkTelemetryDecision } from "./langfuse-telemetry";
+
+export interface StreamAttemptTelemetry extends Telemetry {
+ onLanguageModelCallError?: (event: {
+ callId: string;
+ error: unknown;
+ }) => void;
+}
+
+/** Connect application-level stream failures to the operation's tracing lifecycle. */
+export function createStreamErrorTelemetry(decision: AiSdkTelemetryDecision): {
+ telemetry: AiSdkTelemetryDecision;
+ recordError: (error: unknown) => Promise;
+ captureError: (error: unknown) => void;
+ getCallId: () => string | undefined;
+} {
+ const integrations = decision.integrations
+ ? Array.isArray(decision.integrations)
+ ? decision.integrations
+ : [decision.integrations]
+ : [];
+ let callId: string | undefined;
+ let active = false;
+ let failed = false;
+ let pendingError: unknown;
+ const lifecycle: Telemetry = {
+ onStart(event) {
+ callId = event.callId;
+ active = true;
+ },
+ onError() {
+ failed = true;
+ },
+ onLanguageModelCallStart() {
+ // A new provider attempt can recover a previously reported error part.
+ pendingError = undefined;
+ },
+ async onEnd(event) {
+ if (
+ "finishReason" in event &&
+ event.finishReason === "error" &&
+ pendingError !== undefined
+ ) {
+ await recordError(pendingError);
+ }
+ active = false;
+ },
+ async onAbort(event) {
+ if (isTimeoutReason(event.reason)) await recordError(event.reason);
+ active = false;
+ },
+ };
+ async function recordError(error: unknown) {
+ if (!callId || !active || failed) return;
+ failed = true;
+ await Promise.all(
+ integrations.map((integration) =>
+ integration.onError?.({ callId, error }),
+ ),
+ );
+ }
+ return {
+ telemetry:
+ decision.isEnabled && integrations.length > 0
+ ? { ...decision, integrations: [lifecycle, ...integrations] }
+ : decision,
+ // Error stream parts do not always notify tracing integrations.
+ recordError,
+ captureError: (error) => {
+ pendingError = error;
+ if (!callId || !active) return;
+ for (const integration of integrations) {
+ integration.onLanguageModelCallError?.({ callId, error });
+ }
+ },
+ getCallId: () => callId,
+ };
+}
+
+/** Native AbortSignal timeouts are distinct from user cancellation. */
+export function isTimeoutReason(reason: unknown): boolean {
+ return (
+ typeof reason === "object" &&
+ reason !== null &&
+ "name" in reason &&
+ reason.name === "TimeoutError"
+ );
+}
diff --git a/sdk/packages/shared/src/services/telemetry.test.ts b/sdk/packages/shared/src/services/telemetry.test.ts
index f5787ad870..d348e251e1 100644
--- a/sdk/packages/shared/src/services/telemetry.test.ts
+++ b/sdk/packages/shared/src/services/telemetry.test.ts
@@ -13,6 +13,28 @@ beforeEach(() => {
});
describe("SDK error telemetry", () => {
+ it("preserves typed retryability and nested transport codes without matching messages", () => {
+ const socket = Object.assign(new Error("socket closed"), {
+ code: "ECONNRESET",
+ });
+ const error = Object.assign(
+ new Error("API failed", {
+ cause: new Error("wrapper", { cause: socket }),
+ }),
+ { isRetryable: true },
+ );
+ expect(normalizeSdkError(error)).toMatchObject({
+ error_cause_code: "ECONNRESET",
+ error_retryable: true,
+ });
+ expect(normalizeSdkError(socket)).not.toHaveProperty("error_retryable");
+ });
+
+ it("bounds traversal of cyclic error causes", () => {
+ const error = new Error("cyclic");
+ error.cause = error;
+ expect(normalizeSdkError(error)).toMatchObject({ error_message: "cyclic" });
+ });
it("normalizes unknown errors with sanitized, bounded messages", () => {
const normalized = normalizeSdkError(
new Error(
diff --git a/sdk/packages/shared/src/services/telemetry.ts b/sdk/packages/shared/src/services/telemetry.ts
index 0aab43380f..b4e33eb6da 100644
--- a/sdk/packages/shared/src/services/telemetry.ts
+++ b/sdk/packages/shared/src/services/telemetry.ts
@@ -71,6 +71,8 @@ export const TASK_MAX_TOKENS_RECOVERY_EVENT = "task.max_tokens_recovery";
export interface CaptureTaskLifecycleEventInput {
event: string;
+ /** One issued model request; AI SDK transport retries share this identity. */
+ modelRequestId?: string;
sessionId?: string;
ulid?: string;
agentId?: string;
@@ -284,6 +286,7 @@ export function captureTaskLifecycleEvent(
event: input.event,
properties: stripUndefinedTelemetryProperties({
sessionId: input.sessionId,
+ modelRequestId: input.modelRequestId,
ulid: input.ulid ?? input.sessionId,
agentId: input.agentId,
conversationId: input.conversationId,
@@ -385,6 +388,17 @@ export function normalizeSdkError(
fallbackErrorString(error) ??
"Unknown error";
const code = stringOrNumberValue(record?.code);
+ const causes: Record[] = [];
+ const visited = new Set([error]);
+ let cause = record?.cause;
+ while (isRecord(cause) && !visited.has(cause) && causes.length < 8) {
+ visited.add(cause);
+ causes.push(cause);
+ cause = cause.cause;
+ }
+ const causeCode = causes
+ .map((cause) => stringOrNumberValue(cause.code))
+ .find((code) => code !== undefined);
const status =
numberValue(record?.status) ??
numberValue(record?.statusCode) ??
@@ -401,6 +415,10 @@ export function normalizeSdkError(
messageLimit,
),
...(code !== undefined ? { error_code: code } : {}),
+ ...(causeCode !== undefined ? { error_cause_code: causeCode } : {}),
+ ...(typeof record?.isRetryable === "boolean"
+ ? { error_retryable: record.isRetryable }
+ : {}),
...(status !== undefined ? { error_status: status } : {}),
};
}
From 23791b9323aadd91d7dbaea8a8fa262cd2f7ad0b Mon Sep 17 00:00:00 2001
From: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
Date: Thu, 15 Oct 2026 17:25:25 -0700
Subject: [PATCH 08/29] fix(desktop): pass --use-system-ca when launching the
backend on the bundled CLI (#15125)
The desktop backend now runs as `BUN_BE_BUN=1 cline-cli run `.
In that mode Bun ignores the flags baked into the CLI with
--compile-exec-argv, so the backend lost the --use-system-ca that #14462
added and went back to trusting only Bun's bundled roots on macOS and
Windows. Requests the backend makes itself (model lists from a LiteLLM or
other intranet endpoint, sign-in refresh, marketplace, cloud sessions)
failed with "unable to get local issuer certificate" behind a corporate
CA. Pass the flag on the run command, and mirror it in the startup test.
---
.../scripts/build-desktop-runtime.ts | 5 ++--
.../scripts/desktop-startup.test.ts | 25 +++++++++++--------
.../desktop-app/src-tauri/src/main.rs | 8 +++++-
3 files changed, 24 insertions(+), 14 deletions(-)
diff --git a/apps/examples/desktop-app/scripts/build-desktop-runtime.ts b/apps/examples/desktop-app/scripts/build-desktop-runtime.ts
index 80e707037d..9eab55fe78 100644
--- a/apps/examples/desktop-app/scripts/build-desktop-runtime.ts
+++ b/apps/examples/desktop-app/scripts/build-desktop-runtime.ts
@@ -82,8 +82,9 @@ const compileDesktopCli = async (
// Bun only trusts its bundled Mozilla roots on macOS/Windows, so TLS to
// intranet endpoints signed by a corporate CA (LiteLLM proxies, MITM
// firewalls) fails with "unable to get local issuer certificate". Bake
- // --use-system-ca in so the Hub and the backend running on this runtime
- // also trust the OS Keychain/cert store, as the npm wrapper does.
+ // --use-system-ca in so the Hub also trusts the OS Keychain/cert store,
+ // as the npm wrapper does. `BUN_BE_BUN=1 cline-cli run` ignores baked-in
+ // flags, so main.rs passes it again when launching the backend.
execArgv: ["--use-system-ca"],
});
return outfile;
diff --git a/apps/examples/desktop-app/scripts/desktop-startup.test.ts b/apps/examples/desktop-app/scripts/desktop-startup.test.ts
index 2f036a8b2d..f80c5980a1 100644
--- a/apps/examples/desktop-app/scripts/desktop-startup.test.ts
+++ b/apps/examples/desktop-app/scripts/desktop-startup.test.ts
@@ -200,18 +200,21 @@ async function runStartupScenario(
// The backend bundle on the CLI's runtime, started outside the
// workspace like the packaged app does.
- child = Bun.spawn([cli, "run", "--no-env-file", bundle], {
- cwd: dirname(bundle),
- env: {
- ...env,
- BUN_BE_BUN: "1",
- CLINE_DESKTOP_CLI_PATH: cli,
- CLINE_DESKTOP_WORKSPACE_ROOT: root,
+ child = Bun.spawn(
+ [cli, "run", "--use-system-ca", "--no-env-file", bundle],
+ {
+ cwd: dirname(bundle),
+ env: {
+ ...env,
+ BUN_BE_BUN: "1",
+ CLINE_DESKTOP_CLI_PATH: cli,
+ CLINE_DESKTOP_WORKSPACE_ROOT: root,
+ },
+ stdin: "ignore",
+ stdout,
+ stderr,
},
- stdin: "ignore",
- stdout,
- stderr,
- });
+ );
let endpoint: string | undefined;
const deadline = Date.now() + 30_000;
while (Date.now() < deadline) {
diff --git a/apps/examples/desktop-app/src-tauri/src/main.rs b/apps/examples/desktop-app/src-tauri/src/main.rs
index aecb764b09..b8f0e72136 100644
--- a/apps/examples/desktop-app/src-tauri/src/main.rs
+++ b/apps/examples/desktop-app/src-tauri/src/main.rs
@@ -545,7 +545,13 @@ fn spawn_desktop_backend_process(context: &AppContext) -> Result
resolve_desktop_backend_bundle_path(context),
) {
let mut command = Command::new(cli_path);
- command.arg("run").arg("--no-env-file").arg(&bundle_path);
+ // Under BUN_BE_BUN the CLI's baked-in --use-system-ca does not apply,
+ // so pass it again or the backend only trusts Bun's bundled roots.
+ command
+ .arg("run")
+ .arg("--use-system-ca")
+ .arg("--no-env-file")
+ .arg(&bundle_path);
// Run from the bundle's own directory so the runtime cannot pick up
// a workspace .env or bunfig.toml; the backend moves to the
// workspace root itself (CLINE_DESKTOP_WORKSPACE_ROOT).
From 5d5d2e90bf155f690f086dadd15ca6dd492c8d77 Mon Sep 17 00:00:00 2001
From: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
Date: Thu, 15 Oct 2026 20:22:08 -0700
Subject: [PATCH 09/29] test(sdk): route OpenCode Go messages tests through
minimax-m3
The model catalog no longer lists minimax-m2.7 for OpenCode Go, so the
anthropic-protocol routing cases fall back to chat/completions. Use
minimax-m3, which the catalog still serves over messages.
---
.../core/src/services/llms/handler-factory.routing.test.ts | 2 +-
sdk/packages/llms/src/providers/opencode-go.test.ts | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/sdk/packages/core/src/services/llms/handler-factory.routing.test.ts b/sdk/packages/core/src/services/llms/handler-factory.routing.test.ts
index fd491e0856..ebb9358ce0 100644
--- a/sdk/packages/core/src/services/llms/handler-factory.routing.test.ts
+++ b/sdk/packages/core/src/services/llms/handler-factory.routing.test.ts
@@ -6,7 +6,7 @@ import { toProviderConfig } from "./provider-settings";
describe("core agent per-model protocol routing", () => {
it.each([
["muse-spark-1.3-contributor", "responses", "input"],
- ["minimax-m2.7", "messages", "messages"],
+ ["minimax-m3", "messages", "messages"],
["qwen3.7-plus", "messages", "messages"],
["glm-5.3", "chat/completions", "messages"],
])("routes catalog model %s to %s without a provider-wide override", async (modelId, endpoint, inputField) => {
diff --git a/sdk/packages/llms/src/providers/opencode-go.test.ts b/sdk/packages/llms/src/providers/opencode-go.test.ts
index bb51d85880..dd91a03815 100644
--- a/sdk/packages/llms/src/providers/opencode-go.test.ts
+++ b/sdk/packages/llms/src/providers/opencode-go.test.ts
@@ -199,7 +199,7 @@ describe("OpenCode Go HTTP integration", () => {
["kimi-k2.6", "chat/completions", chatResponse],
["muse-spark-1.3-contributor", "responses", responsesResponse],
["muse-spark-1.2-contributor", "responses", responsesResponse],
- ["minimax-m2.7", "messages", messagesResponse],
+ ["minimax-m3", "messages", messagesResponse],
["qwen3.7-plus", "messages", messagesResponse],
])("routes %s with conversation headers, tools, and stream decoding", async (modelId, endpoint, response) => {
const fetchMock = vi.fn(
From 2bbaa7a8d33de8006a3ee0c242761517284a95c1 Mon Sep 17 00:00:00 2001
From: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
Date: Thu, 15 Oct 2026 20:22:09 -0700
Subject: [PATCH 10/29] chore(sdk): release v0.0.94
---
bun.lock | 10 +-
sdk/CHANGELOG.md | 12 +
sdk/packages/agents/package.json | 2 +-
sdk/packages/core/package.json | 2 +-
sdk/packages/llms/package.json | 2 +-
.../llms/src/catalog/catalog.generated.ts | 9351 +++++++++++------
.../catalog/cline-recommended.generated.ts | 44 +-
.../src/providers/provider-ids.generated.ts | 3 +
.../llms/src/providers/providers.generated.ts | 107 +-
sdk/packages/sdk/package.json | 2 +-
sdk/packages/shared/package.json | 2 +-
11 files changed, 6397 insertions(+), 3140 deletions(-)
diff --git a/bun.lock b/bun.lock
index 42bbad8d45..f65a6ebca9 100644
--- a/bun.lock
+++ b/bun.lock
@@ -645,7 +645,7 @@
},
"sdk/packages/agents": {
"name": "@cline/agents",
- "version": "0.0.93",
+ "version": "0.0.94",
"dependencies": {
"@cline/llms": "workspace:*",
"@cline/shared": "workspace:*",
@@ -654,7 +654,7 @@
},
"sdk/packages/core": {
"name": "@cline/core",
- "version": "0.0.93",
+ "version": "0.0.94",
"dependencies": {
"@cline/agents": "workspace:*",
"@cline/llms": "workspace:*",
@@ -696,7 +696,7 @@
},
"sdk/packages/llms": {
"name": "@cline/llms",
- "version": "0.0.93",
+ "version": "0.0.94",
"dependencies": {
"@ai-sdk/amazon-bedrock": "^5.0.98",
"@ai-sdk/anthropic": "^4.0.67",
@@ -745,14 +745,14 @@
},
"sdk/packages/sdk": {
"name": "@cline/sdk",
- "version": "0.0.93",
+ "version": "0.0.94",
"dependencies": {
"@cline/core": "workspace:*",
},
},
"sdk/packages/shared": {
"name": "@cline/shared",
- "version": "0.0.93",
+ "version": "0.0.94",
"dependencies": {
"aws4fetch": "^1.0.20",
"jsonrepair": "^3.13.2",
diff --git a/sdk/CHANGELOG.md b/sdk/CHANGELOG.md
index 04a70230b5..f3598c8739 100644
--- a/sdk/CHANGELOG.md
+++ b/sdk/CHANGELOG.md
@@ -1,5 +1,17 @@
# Cline SDK Changelog
+## 0.0.94
+
+- Plugins now run only in worker threads (the default, `CLINE_PLUGIN_MODE=worker`) or in the subprocess sandbox (`sandbox`). The `in_process` mode is removed, along with its silent fallback. A host that ships no `plugin-sandbox-bootstrap.js` fails every plugin load with `PluginBootstrapMissingError`, which names `CLINE_PLUGIN_BOOTSTRAP_PATH`, instead of quietly running plugins inside the hub. The hub daemon's uncaught error handlers are fatal again. The SSH remote hub ships no bootstrap yet, so it reports plugin tools as missing
+- Provider errors that arrive after a model stream has started are retried up to 3 times, and the final failure is reported as an error in logs and Langfuse traces. Exhausted retries no longer also trigger the agent's whole-turn retry, so retry budgets don't multiply
+- Model request failure logs include the provider's request id
+- `setHubDaemonLauncher` lets an embedding host start the hub daemon through a bundled Cline CLI, and `ensureDetachedHubServer` gains a `beforeSpawn` hook that runs only when a new daemon actually starts. The standalone SSH remote helper entrypoint is removed: SSH remotes run the hub through the uploaded Cline CLI
+- `NodeHubClient` accepts `resolveConnectionHeaders`, so a remote proxy's WebSocket upgrade can be authenticated with HTTP headers refreshed on every reconnect. It is threaded through `HubRuntimeHost` and `RemoteRuntimeHost`
+- `AskQuestionExecutor` may return text and image blocks, so attachments sent with an answer reach the model
+- New `buildTelemetrySelfcheckReport` export in `@cline/shared`
+- The `cline` provider's bundled default (the first Cline recommended model) is now Gemini 4 Argon instead of Claude Sonnet 5.5, because the recommended list now leads with it
+- Refreshed the model catalog (6,862 → 6,952 models). Adds the Boundless and Standard Compute providers, and SambaNova now comes from the catalog with MiniMax M3 as its default. The Cline recommended list adds Gemini 4 Argon and drops Grok 4.7, and the Cline free list replaces Step 5 Preview with Nemotron 3.5 Super VL. OpenCode Go no longer lists MiniMax M2.7. Default models change for Cortecs, CrossModel, Eden AI, Google Gemini, GitHub Copilot, Google Vertex AI, LLM Gateway, Ofox, OpenCode Go, and Prime Inference (Gemini 4 Argon), Fireworks AI, Nebius Token Factory, and Requesty (Muse Spark Open), CoreWeave, DigitalOcean, NanoGPT, and Nvidia (Nemotron 3.5 Super VL), Aixy and Neon (Claude Haiku 5.5), Agnes AI, Ambient, IteraCompute, Poe, Scaleway, and SenseNova
+
## 0.0.93
- Plugins load in-process through one registry per process instead of a node/bun subprocess, so the compiled CLI and its hub no longer need a runtime on PATH, and plugins can use the Bun global under the Bun-built hub. `CLINE_PLUGIN_MODE=sandbox` keeps the subprocess sandbox. The registry wraps import, setup, hooks, tools and commands with timeouts and error capture, and tracks each plugin's state (loading/ready/degraded/failed/disabled) with its last error. A failing plugin no longer silently drops its tools: `session.create` accepts a `plugins` policy and returns `pluginIssues`, later failures reach affected sessions as status notices, the hub answers `plugins.list`/`plugins.status`/`plugins.reload` and broadcasts `plugin.status_changed`, and the daemon marks a plugin failed instead of shutting down when an uncaught error comes from it. Each session gets its own copy of every plugin module, so plugins that keep per-session state at module level keep working
diff --git a/sdk/packages/agents/package.json b/sdk/packages/agents/package.json
index 84ab3e5ade..aa966f2dfe 100644
--- a/sdk/packages/agents/package.json
+++ b/sdk/packages/agents/package.json
@@ -1,6 +1,6 @@
{
"name": "@cline/agents",
- "version": "0.0.93",
+ "version": "0.0.94",
"repository": {
"type": "git",
"url": "https://github.com/cline/cline",
diff --git a/sdk/packages/core/package.json b/sdk/packages/core/package.json
index 84f0d076d2..f5f2007a3e 100644
--- a/sdk/packages/core/package.json
+++ b/sdk/packages/core/package.json
@@ -1,7 +1,7 @@
{
"name": "@cline/core",
"description": "Cline Core SDK for Node Runtime",
- "version": "0.0.93",
+ "version": "0.0.94",
"repository": {
"type": "git",
"url": "https://github.com/cline/cline",
diff --git a/sdk/packages/llms/package.json b/sdk/packages/llms/package.json
index d1f3377f31..993e14adce 100644
--- a/sdk/packages/llms/package.json
+++ b/sdk/packages/llms/package.json
@@ -1,6 +1,6 @@
{
"name": "@cline/llms",
- "version": "0.0.93",
+ "version": "0.0.94",
"description": "Config-driven SDK for selecting, extending, and instantiating LLM providers and models",
"repository": {
"type": "git",
diff --git a/sdk/packages/llms/src/catalog/catalog.generated.ts b/sdk/packages/llms/src/catalog/catalog.generated.ts
index b3c01414e8..0359d5092e 100644
--- a/sdk/packages/llms/src/catalog/catalog.generated.ts
+++ b/sdk/packages/llms/src/catalog/catalog.generated.ts
@@ -14,7 +14,7 @@ export const GENERATED_PROVIDER_MODELS: {
version: number
providers: Record>
} = {
- version: 1791877806756,
+ version: 1792120582911,
providers: {
"302ai": {
"claude-haiku-5-5": {
@@ -6508,6 +6508,32 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"agnes": {
+ "agnes-3.0-flash": {
+ "id": "agnes-3.0-flash",
+ "name": "Agnes 3.0 Flash",
+ "contextWindow": 512000,
+ "maxInputTokens": 512000,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "toggle"
+ }
+ ],
+ "pricing": {
+ "input": 0,
+ "output": 0,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-09"
+ },
"agnes-2.5-pro-alpha": {
"id": "agnes-2.5-pro-alpha",
"name": "Agnes 2.5 Pro Alpha",
@@ -6560,32 +6586,6 @@ export const GENERATED_PROVIDER_MODELS: {
"cacheWrite": 0
},
"releaseDate": "2026-07"
- },
- "agnes-2.0-flash": {
- "id": "agnes-2.0-flash",
- "name": "Agnes 2.0 Flash",
- "contextWindow": 512000,
- "maxInputTokens": 512000,
- "maxTokens": 65536,
- "capabilities": [
- "images",
- "tools",
- "reasoning",
- "structured_output",
- "temperature"
- ],
- "reasoningOptions": [
- {
- "type": "toggle"
- }
- ],
- "pricing": {
- "input": 0,
- "output": 0,
- "cacheRead": 0,
- "cacheWrite": 0
- },
- "releaseDate": "2026-05-25"
}
},
"ai-router": {
@@ -7243,6 +7243,52 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"aihubmix": {
+ "gemini-4-argon": {
+ "id": "gemini-4-argon",
+ "name": "Gemini 4 Argon",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 10,
+ "cacheRead": 0.1,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-13",
+ "family": "gemini",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio",
+ "pdf"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
"claude-haiku-5-5": {
"id": "claude-haiku-5-5",
"name": "Claude Haiku 5.5",
@@ -14148,27 +14194,6 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-04-22",
"family": "mimo"
},
- "alibaba/qwen3.6-max-preview": {
- "id": "alibaba/qwen3.6-max-preview",
- "name": "Qwen3.6 Max Preview",
- "contextWindow": 262144,
- "maxInputTokens": 262144,
- "maxTokens": 65536,
- "capabilities": [
- "tools",
- "reasoning",
- "temperature"
- ],
- "reasoningOptions": [],
- "pricing": {
- "input": 0.65,
- "output": 3.9,
- "cacheRead": 0,
- "cacheWrite": 0
- },
- "releaseDate": "2026-04-20",
- "family": "qwen"
- },
"anthropic/claude-opus-4.7": {
"id": "anthropic/claude-opus-4.7",
"name": "Claude 4.7 Opus",
@@ -15304,26 +15329,6 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2025-10-29",
"family": "gpt-oss"
},
- "alibaba/qwen3-vl-flash": {
- "id": "alibaba/qwen3-vl-flash",
- "name": "Qwen3 VL Flash",
- "contextWindow": 262144,
- "maxInputTokens": 262144,
- "maxTokens": 32768,
- "capabilities": [
- "images",
- "tools",
- "temperature",
- "prompt-cache"
- ],
- "pricing": {
- "input": 0.065,
- "output": 0.52,
- "cacheRead": 0.065,
- "cacheWrite": 0
- },
- "releaseDate": "2025-10-15"
- },
"anthropic/claude-haiku-4.5": {
"id": "anthropic/claude-haiku-4.5",
"name": "Claude 4.5 Haiku",
@@ -15421,46 +15426,6 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2025-09-29",
"family": "claude-sonnet"
},
- "alibaba/qwen3-max": {
- "id": "alibaba/qwen3-max",
- "name": "Qwen3 Max Instruct",
- "contextWindow": 262144,
- "maxInputTokens": 262144,
- "maxTokens": 65536,
- "capabilities": [
- "tools",
- "temperature",
- "prompt-cache"
- ],
- "pricing": {
- "input": 1.56,
- "output": 7.8,
- "cacheRead": 0.312,
- "cacheWrite": 0
- },
- "releaseDate": "2025-09-23",
- "family": "qwen"
- },
- "alibaba/qwen3-max-preview": {
- "id": "alibaba/qwen3-max-preview",
- "name": "Qwen3 Max Preview",
- "contextWindow": 252000,
- "maxInputTokens": 252000,
- "maxTokens": 32768,
- "capabilities": [
- "tools",
- "temperature",
- "prompt-cache"
- ],
- "pricing": {
- "input": 1.56,
- "output": 7.8,
- "cacheRead": 0.312,
- "cacheWrite": 0
- },
- "releaseDate": "2025-09-05",
- "family": "qwen"
- },
"moonshotai/kimi-k2-0905": {
"id": "moonshotai/kimi-k2-0905",
"name": "Kimi K2 0905",
@@ -15491,8 +15456,8 @@ export const GENERATED_PROVIDER_MODELS: {
"temperature"
],
"pricing": {
- "input": 0.195,
- "output": 1.56,
+ "input": 0.20631,
+ "output": 1.65048,
"cacheRead": 0,
"cacheWrite": 0
},
@@ -15950,12 +15915,13 @@ export const GENERATED_PROVIDER_MODELS: {
"maxTokens": 65536,
"capabilities": [
"tools",
- "temperature"
+ "temperature",
+ "prompt-cache"
],
"pricing": {
- "input": 1.95,
- "output": 9.75,
- "cacheRead": 0,
+ "input": 1.3754,
+ "output": 6.705075,
+ "cacheRead": 1.3754,
"cacheWrite": 0
},
"releaseDate": "2025-04",
@@ -16632,6 +16598,47 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"aixy": {
+ "anthropic/claude-haiku-5-5": {
+ "id": "anthropic/claude-haiku-5-5",
+ "name": "Claude Haiku 5.5",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "toggle"
+ },
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.1,
+ "output": 0.5,
+ "cacheRead": 0.01,
+ "cacheWrite": 0.125
+ },
+ "releaseDate": "2026-10-07",
+ "family": "claude-haiku",
+ "metadata": {
+ "apiProtocol": "anthropic"
+ }
+ },
"openai/gpt-6.1-sol": {
"id": "openai/gpt-6.1-sol",
"name": "GPT-6.1 Sol",
@@ -16670,6 +16677,82 @@ export const GENERATED_PROVIDER_MODELS: {
"apiProtocol": "openai-responses"
}
},
+ "anthropic/claude-sonnet-5-5": {
+ "id": "anthropic/claude-sonnet-5-5",
+ "name": "Claude Sonnet 5.5",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 10,
+ "cacheRead": 0.1,
+ "cacheWrite": 2.5
+ },
+ "releaseDate": "2026-09-28",
+ "family": "claude-sonnet",
+ "metadata": {
+ "apiProtocol": "anthropic"
+ }
+ },
+ "anthropic/claude-opus-5-5": {
+ "id": "anthropic/claude-opus-5-5",
+ "name": "Claude Opus 5.5",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 4,
+ "output": 20,
+ "cacheRead": 0.2,
+ "cacheWrite": 5
+ },
+ "releaseDate": "2026-09-22",
+ "family": "claude-opus",
+ "metadata": {
+ "apiProtocol": "anthropic"
+ }
+ },
"openai/gpt-6-luna": {
"id": "openai/gpt-6-luna",
"name": "GPT-6 Luna",
@@ -16786,6 +16869,44 @@ export const GENERATED_PROVIDER_MODELS: {
"apiProtocol": "openai-responses"
}
},
+ "anthropic/claude-fable-5-1": {
+ "id": "anthropic/claude-fable-5-1",
+ "name": "Claude Fable 5.1",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 10,
+ "output": 50,
+ "cacheRead": 0.25,
+ "cacheWrite": 12.5
+ },
+ "releaseDate": "2026-09-01",
+ "family": "claude-fable",
+ "metadata": {
+ "apiProtocol": "anthropic"
+ }
+ },
"openai/gpt-5.6-luna": {
"id": "openai/gpt-5.6-luna",
"name": "GPT-5.6 Luna",
@@ -22263,6 +22384,43 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"ambient": {
+ "ambient/small": {
+ "id": "ambient/small",
+ "name": "Ambient Small",
+ "contextWindow": 101072,
+ "maxInputTokens": 101072,
+ "maxTokens": 101072,
+ "capabilities": [
+ "tools",
+ "temperature"
+ ],
+ "pricing": {
+ "input": 0.001,
+ "output": 0.001,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-13"
+ },
+ "unsloth/qwen3.8-27b-gguf": {
+ "id": "unsloth/qwen3.8-27b-gguf",
+ "name": "qwen3.8-27b-4q",
+ "contextWindow": 101072,
+ "maxInputTokens": 101072,
+ "maxTokens": 101072,
+ "capabilities": [
+ "tools",
+ "temperature"
+ ],
+ "pricing": {
+ "input": 0.001,
+ "output": 0.001,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-13",
+ "family": "unsloth"
+ },
"qwen/qwen3-30b-a3b-instruct-2507": {
"id": "qwen/qwen3-30b-a3b-instruct-2507",
"name": "Qwen3 30B A3B Instruct 2507",
@@ -22472,6 +22630,33 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-06-12",
"family": "kimi-k2"
},
+ "minimax/minimax-m3": {
+ "id": "minimax/minimax-m3",
+ "name": "MiniMax-M3",
+ "contextWindow": 262144,
+ "maxInputTokens": 262144,
+ "maxTokens": 262144,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "toggle"
+ }
+ ],
+ "pricing": {
+ "input": 0.23,
+ "output": 0.96,
+ "cacheRead": 0.05,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-06-01",
+ "family": "minimax"
+ },
"stepfun/step-3.7-flash": {
"id": "stepfun/step-3.7-flash",
"name": "Step 3.7 Flash",
@@ -32300,6 +32485,650 @@ export const GENERATED_PROVIDER_MODELS: {
"family": "gemma"
}
},
+ "boundless": {
+ "claude-opus-5.5": {
+ "id": "claude-opus-5.5",
+ "name": "Claude Opus 5.5",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 4,
+ "output": 20,
+ "cacheRead": 0.2,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-09-22",
+ "family": "claude-opus"
+ },
+ "gpt-6-luna": {
+ "id": "gpt-6-luna",
+ "name": "GPT-6 Luna",
+ "contextWindow": 1050000,
+ "maxInputTokens": 922000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.1,
+ "output": 0.5,
+ "cacheRead": 0.01,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-09-22",
+ "family": "gpt-luna"
+ },
+ "gpt-6-sol": {
+ "id": "gpt-6-sol",
+ "name": "GPT-6 Sol",
+ "contextWindow": 1050000,
+ "maxInputTokens": 922000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 10,
+ "cacheRead": 0.2,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-09-22",
+ "family": "gpt-sol"
+ },
+ "mimo-v2.6-flash": {
+ "id": "mimo-v2.6-flash",
+ "name": "MiMo-V2.6-Flash",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 131072,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "toggle"
+ }
+ ],
+ "pricing": {
+ "input": 0.14,
+ "output": 0.28,
+ "cacheRead": 0.0028,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-09-22",
+ "family": "mimo",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "audio",
+ "video"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
+ "mimo-v2.6-pro": {
+ "id": "mimo-v2.6-pro",
+ "name": "MiMo-V2.6-Pro",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 131072,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "toggle"
+ }
+ ],
+ "pricing": {
+ "input": 0.435,
+ "output": 0.87,
+ "cacheRead": 0.0036,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-09-22",
+ "family": "mimo",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "audio",
+ "video"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
+ "deepseek-v4.1-flash": {
+ "id": "deepseek-v4.1-flash",
+ "name": "DeepSeek V4.1 Flash",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 384000,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.2,
+ "output": 1,
+ "cacheRead": 0.01,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-09-10",
+ "family": "deepseek-flash"
+ },
+ "claude-fable-5.1": {
+ "id": "claude-fable-5.1",
+ "name": "Claude Fable 5.1",
+ "contextWindow": 262144,
+ "maxInputTokens": 262144,
+ "maxTokens": 128000,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 10,
+ "output": 50,
+ "cacheRead": 0.25,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-09-01",
+ "family": "claude-fable"
+ },
+ "glm-5.3-flash": {
+ "id": "glm-5.3-flash",
+ "name": "GLM-5.3-Flash",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 131072,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.12,
+ "output": 0.4,
+ "cacheRead": 0.024,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-08-26",
+ "family": "glm-flash"
+ },
+ "qwen3.8-flash": {
+ "id": "qwen3.8-flash",
+ "name": "Qwen3.8 Flash",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 131072,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.15,
+ "output": 0.47,
+ "cacheRead": 0.016,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-08-26",
+ "family": "qwen"
+ },
+ "glm-5.3": {
+ "id": "glm-5.3",
+ "name": "GLM-5.3",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 131072,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1.12,
+ "output": 3.52,
+ "cacheRead": 0.14,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-08-14",
+ "family": "glm"
+ },
+ "deepseek-v4-pro-0813": {
+ "id": "deepseek-v4-pro-0813",
+ "name": "DeepSeek V4 Pro 0813",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 384000,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1.04,
+ "output": 2.08,
+ "cacheRead": 0.0352,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-08-12",
+ "family": "deepseek-thinking"
+ },
+ "dsv4": {
+ "id": "dsv4",
+ "name": "DeepSeek V4 Flash 0731",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 384000,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.04,
+ "output": 0.21,
+ "cacheRead": 0.02,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-07-31",
+ "family": "deepseek-flash"
+ },
+ "claude-opus-5": {
+ "id": "claude-opus-5",
+ "name": "Claude Opus 5",
+ "contextWindow": 262144,
+ "maxInputTokens": 262144,
+ "maxTokens": 128000,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 5,
+ "output": 25,
+ "cacheRead": 0.5,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-07-24",
+ "family": "claude-opus"
+ },
+ "kimi-k3": {
+ "id": "kimi-k3",
+ "name": "Kimi K3",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 131072,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2.3,
+ "output": 11.4,
+ "cacheRead": 0.23,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-07-16",
+ "family": "kimi-k3"
+ },
+ "gpt-5.6-luna": {
+ "id": "gpt-5.6-luna",
+ "name": "GPT-5.6 Luna",
+ "contextWindow": 262144,
+ "maxInputTokens": 262144,
+ "maxTokens": 128000,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.2,
+ "output": 1.2,
+ "cacheRead": 0.02,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-07-09",
+ "family": "gpt-luna"
+ },
+ "gpt-5.6-sol": {
+ "id": "gpt-5.6-sol",
+ "name": "GPT-5.6 Sol",
+ "contextWindow": 262144,
+ "maxInputTokens": 262144,
+ "maxTokens": 128000,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 10,
+ "cacheRead": 0.2,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-07-09",
+ "family": "gpt-sol"
+ },
+ "glm-5.2": {
+ "id": "glm-5.2",
+ "name": "GLM-5.2",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 131072,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.34,
+ "output": 2.3,
+ "cacheRead": 0.17,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-06-13",
+ "family": "glm"
+ },
+ "minimax-m3": {
+ "id": "minimax-m3",
+ "name": "MiniMax-M3",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 512000,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "toggle"
+ }
+ ],
+ "pricing": {
+ "input": 0.28,
+ "output": 1.1,
+ "cacheRead": 0.056,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-06-01",
+ "family": "minimax"
+ },
+ "qwen3.6": {
+ "id": "qwen3.6",
+ "name": "Qwen3.6 35B-A3B",
+ "contextWindow": 262144,
+ "maxInputTokens": 262144,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "toggle"
+ }
+ ],
+ "pricing": {
+ "input": 0.04,
+ "output": 0.35,
+ "cacheRead": 0.02,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-04-17",
+ "family": "qwen"
+ },
+ "nemotron3-super": {
+ "id": "nemotron3-super",
+ "name": "Nemotron 3 Super 120B A12B",
+ "contextWindow": 262144,
+ "maxInputTokens": 262144,
+ "maxTokens": 262144,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.12,
+ "output": 0.52,
+ "cacheRead": 0.06,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-03-11",
+ "family": "nemotron"
+ }
+ },
"cerebras": {
"qwen-3.8-27b": {
"id": "qwen-3.8-27b",
@@ -32994,12 +33823,12 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"cline": {
- "cline-free/step-5-preview": {
- "id": "cline-free/step-5-preview",
- "name": "Step 5 Preview (free)",
- "contextWindow": 1000000,
- "maxInputTokens": 1000000,
- "maxTokens": 64000,
+ "cline-free/nemotron-3.5-super-vl": {
+ "id": "cline-free/nemotron-3.5-super-vl",
+ "name": "Nemotron 3.5 Super VL (free)",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 235929,
"capabilities": [
"images",
"video",
@@ -33011,12 +33840,7 @@ export const GENERATED_PROVIDER_MODELS: {
],
"reasoningOptions": [
{
- "type": "effort",
- "values": [
- "low",
- "medium",
- "high"
- ]
+ "type": "toggle"
}
],
"pricing": {
@@ -33025,8 +33849,9 @@ export const GENERATED_PROVIDER_MODELS: {
"cacheRead": 0,
"cacheWrite": 0
},
- "releaseDate": "2026-09-16",
- "description": "StepFun's flagship model for agentic work, built on a sparse Mixture-of-Experts"
+ "releaseDate": "2026-10-15",
+ "family": "nemotron",
+ "description": "NVIDIA’s latest model with 120B and fast output"
},
"cline-free/mimo-v2.6-flash": {
"id": "cline-free/mimo-v2.6-flash",
@@ -33152,7 +33977,7 @@ export const GENERATED_PROVIDER_MODELS: {
"id": "cline-pass/deepseek-v4.1-flash",
"contextWindow": 1048576,
"maxInputTokens": 1048576,
- "maxTokens": 943718,
+ "maxTokens": 393216,
"capabilities": [
"images",
"tools",
@@ -33162,12 +33987,10 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"low",
"high",
"max"
@@ -33299,41 +34122,6 @@ export const GENERATED_PROVIDER_MODELS: {
"family": "glm",
"description": "Z-AI's new top open-weights model"
},
- "cline-pass/deepseek-v4-pro": {
- "name": "DeepSeek V4 Pro",
- "id": "cline-pass/deepseek-v4-pro",
- "contextWindow": 1048576,
- "maxInputTokens": 1048576,
- "maxTokens": 384000,
- "capabilities": [
- "tools",
- "reasoning",
- "structured_output",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [
- {
- "type": "toggle"
- },
- {
- "type": "effort",
- "values": [
- "high",
- "xhigh"
- ]
- }
- ],
- "pricing": {
- "input": 0,
- "output": 0,
- "cacheRead": 0,
- "cacheWrite": 0
- },
- "releaseDate": "2026-04-24",
- "family": "deepseek-thinking",
- "description": "Frontier reasoning and coding with 1M context window"
- },
"cline-pass/qwen3.8-max": {
"name": "cline-pass/qwen3.8-max",
"contextWindow": 128000,
@@ -33353,6 +34141,39 @@ export const GENERATED_PROVIDER_MODELS: {
"id": "cline-pass/qwen3.8-max",
"description": "Qwen's New SOTA coding model"
},
+ "cline-pass/deepseek-v4-pro": {
+ "name": "DeepSeek V4 Pro",
+ "id": "cline-pass/deepseek-v4-pro",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 384000,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0,
+ "output": 0,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-04-24",
+ "family": "deepseek-thinking",
+ "description": "Frontier reasoning and coding with 1M context window"
+ },
"cline-pass/muse-spark-1.3-contributor": {
"name": "Muse Spark 1.3 Contributor",
"id": "cline-pass/muse-spark-1.3-contributor",
@@ -33408,12 +34229,10 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"low",
"high",
"max"
@@ -33435,7 +34254,7 @@ export const GENERATED_PROVIDER_MODELS: {
"id": "cline-pass/glm-5.3-flash",
"contextWindow": 1048576,
"maxInputTokens": 1048576,
- "maxTokens": 943718,
+ "maxTokens": 943717,
"capabilities": [
"images",
"video",
@@ -33465,6 +34284,35 @@ export const GENERATED_PROVIDER_MODELS: {
"family": "glm-flash",
"description": "Latest natively multimodal model in the GLM-5 series"
},
+ "cline-pass/qwen3.7-plus": {
+ "name": "Qwen3.7 Plus",
+ "id": "cline-pass/qwen3.7-plus",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 131072,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "toggle"
+ }
+ ],
+ "pricing": {
+ "input": 0,
+ "output": 0,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-06-02",
+ "family": "qwen",
+ "description": "Fast multimodal agent model with vision and video input"
+ },
"cline-pass/minimax-m3": {
"name": "MiniMax-M3",
"id": "cline-pass/minimax-m3",
@@ -33523,35 +34371,6 @@ export const GENERATED_PROVIDER_MODELS: {
"family": "qwen",
"description": "Flagship agent model with 1M context window"
},
- "cline-pass/qwen3.7-plus": {
- "name": "Qwen3.7 Plus",
- "id": "cline-pass/qwen3.7-plus",
- "contextWindow": 1000000,
- "maxInputTokens": 1000000,
- "maxTokens": 131072,
- "capabilities": [
- "images",
- "tools",
- "reasoning",
- "structured_output",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [
- {
- "type": "toggle"
- }
- ],
- "pricing": {
- "input": 0,
- "output": 0,
- "cacheRead": 0,
- "cacheWrite": 0
- },
- "releaseDate": "2026-06-02",
- "family": "qwen",
- "description": "Fast multimodal agent model with vision and video input"
- },
"cline-pass/mimo-v2.5-pro": {
"name": "MiMo-V2.5-Pro",
"id": "cline-pass/mimo-v2.5-pro",
@@ -33621,12 +34440,12 @@ export const GENERATED_PROVIDER_MODELS: {
},
"description": "Fast and efficient MiMo for everyday coding"
},
- "cline-free/step-5-preview": {
- "id": "cline-free/step-5-preview",
- "name": "Step 5 Preview (free)",
- "contextWindow": 1000000,
- "maxInputTokens": 1000000,
- "maxTokens": 64000,
+ "cline-free/nemotron-3.5-super-vl": {
+ "id": "cline-free/nemotron-3.5-super-vl",
+ "name": "Nemotron 3.5 Super VL (free)",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 235929,
"capabilities": [
"images",
"video",
@@ -33638,12 +34457,7 @@ export const GENERATED_PROVIDER_MODELS: {
],
"reasoningOptions": [
{
- "type": "effort",
- "values": [
- "low",
- "medium",
- "high"
- ]
+ "type": "toggle"
}
],
"pricing": {
@@ -33652,8 +34466,9 @@ export const GENERATED_PROVIDER_MODELS: {
"cacheRead": 0,
"cacheWrite": 0
},
- "releaseDate": "2026-09-16",
- "description": "StepFun's flagship model for agentic work, built on a sparse Mixture-of-Experts"
+ "releaseDate": "2026-10-15",
+ "family": "nemotron",
+ "description": "NVIDIA’s latest model with 120B and fast output"
},
"cline-free/mimo-v2.6-flash": {
"id": "cline-free/mimo-v2.6-flash",
@@ -34541,6 +35356,50 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"cortecs": {
+ "gemini-4-argon": {
+ "id": "gemini-4-argon",
+ "name": "Gemini 4 Argon",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 65535,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2.25,
+ "output": 11.249,
+ "cacheRead": 0.113,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-13",
+ "family": "gemini",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "audio",
+ "pdf"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
"claude-haiku-5.5": {
"id": "claude-haiku-5.5",
"name": "Claude Haiku 5.5",
@@ -36218,7 +37077,7 @@ export const GENERATED_PROVIDER_MODELS: {
},
"ministral-14b-2512": {
"id": "ministral-14b-2512",
- "name": "ministral-14b-2512",
+ "name": "Ministral 3 14B 2512",
"contextWindow": 256000,
"maxInputTokens": 256000,
"maxTokens": 256000,
@@ -36234,11 +37093,12 @@ export const GENERATED_PROVIDER_MODELS: {
"cacheRead": 0.022,
"cacheWrite": 0
},
- "releaseDate": "2025-12-03"
+ "releaseDate": "2025-12-02",
+ "family": "ministral"
},
"ministral-3b-2512": {
"id": "ministral-3b-2512",
- "name": "ministral-3b-2512",
+ "name": "Ministral 3 3B 2512",
"contextWindow": 256000,
"maxInputTokens": 256000,
"maxTokens": 256000,
@@ -36254,11 +37114,12 @@ export const GENERATED_PROVIDER_MODELS: {
"cacheRead": 0.012,
"cacheWrite": 0
},
- "releaseDate": "2025-12-03"
+ "releaseDate": "2025-12-02",
+ "family": "ministral"
},
"ministral-8b-2512": {
"id": "ministral-8b-2512",
- "name": "ministral-8b-2512",
+ "name": "Ministral 3 8B 2512",
"contextWindow": 256000,
"maxInputTokens": 256000,
"maxTokens": 256000,
@@ -36274,7 +37135,8 @@ export const GENERATED_PROVIDER_MODELS: {
"cacheRead": 0.017,
"cacheWrite": 0
},
- "releaseDate": "2025-12-03"
+ "releaseDate": "2025-12-02",
+ "family": "ministral"
},
"mistral-large-2512": {
"id": "mistral-large-2512",
@@ -36593,6 +37455,25 @@ export const GENERATED_PROVIDER_MODELS: {
},
"releaseDate": "2025-09-02"
},
+ "hermes-4-405b": {
+ "id": "hermes-4-405b",
+ "name": "Hermes 4 405B",
+ "contextWindow": 128000,
+ "maxInputTokens": 128000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "tools",
+ "structured_output"
+ ],
+ "pricing": {
+ "input": 0.996,
+ "output": 2.989,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2025-08-26",
+ "family": "hermes"
+ },
"gpt-5": {
"id": "gpt-5",
"name": "GPT-5",
@@ -37043,49 +37924,6 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2025-04-14",
"family": "gpt-nano"
},
- "nova-lite-v1": {
- "id": "nova-lite-v1",
- "name": "nova-lite-v1",
- "contextWindow": 300000,
- "maxInputTokens": 300000,
- "maxTokens": 10000,
- "capabilities": [
- "images",
- "files",
- "tools",
- "reasoning",
- "structured_output"
- ],
- "reasoningOptions": [],
- "pricing": {
- "input": 0.069,
- "output": 0.275,
- "cacheRead": 0,
- "cacheWrite": 0
- },
- "releaseDate": "2025-04-14"
- },
- "nova-micro-v1": {
- "id": "nova-micro-v1",
- "name": "nova-micro-v1",
- "contextWindow": 128000,
- "maxInputTokens": 128000,
- "maxTokens": 10000,
- "capabilities": [
- "images",
- "tools",
- "reasoning",
- "structured_output"
- ],
- "reasoningOptions": [],
- "pricing": {
- "input": 0.04,
- "output": 0.159,
- "cacheRead": 0,
- "cacheWrite": 0
- },
- "releaseDate": "2025-04-14"
- },
"pixtral-large-2502": {
"id": "pixtral-large-2502",
"name": "Pixtral Large (25.02)",
@@ -37191,6 +38029,51 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2024-12-06",
"family": "llama"
},
+ "nova-lite-v1": {
+ "id": "nova-lite-v1",
+ "name": "Nova Lite 1.0",
+ "contextWindow": 300000,
+ "maxInputTokens": 300000,
+ "maxTokens": 10000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output"
+ ],
+ "reasoningOptions": [],
+ "pricing": {
+ "input": 0.069,
+ "output": 0.275,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2024-12-05",
+ "family": "nova-lite"
+ },
+ "nova-micro-v1": {
+ "id": "nova-micro-v1",
+ "name": "Nova Micro 1.0",
+ "contextWindow": 128000,
+ "maxInputTokens": 128000,
+ "maxTokens": 10000,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output"
+ ],
+ "reasoningOptions": [],
+ "pricing": {
+ "input": 0.04,
+ "output": 0.159,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2024-12-05",
+ "family": "nova-micro"
+ },
"nova-pro-v1": {
"id": "nova-pro-v1",
"name": "Nova Pro 1.0",
@@ -37212,7 +38095,7 @@ export const GENERATED_PROVIDER_MODELS: {
"cacheRead": 0,
"cacheWrite": 0
},
- "releaseDate": "2024-12-03",
+ "releaseDate": "2024-12-05",
"family": "nova-pro"
},
"pixtral-12b-2409": {
@@ -37236,24 +38119,6 @@ export const GENERATED_PROVIDER_MODELS: {
},
"releaseDate": "2024-11-09"
},
- "hermes-4-405b": {
- "id": "hermes-4-405b",
- "name": "hermes-4-405b",
- "contextWindow": 128000,
- "maxInputTokens": 128000,
- "maxTokens": 128000,
- "capabilities": [
- "tools",
- "structured_output"
- ],
- "pricing": {
- "input": 0.996,
- "output": 2.989,
- "cacheRead": 0,
- "cacheWrite": 0
- },
- "releaseDate": "2024-08-13"
- },
"mistral-nemo-instruct-2407": {
"id": "mistral-nemo-instruct-2407",
"name": "mistral-nemo-instruct-2407",
@@ -38093,6 +38958,52 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"crossmodel": {
+ "gemini/gemini-4-argon": {
+ "id": "gemini/gemini-4-argon",
+ "name": "Gemini 4 Argon",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "minimal",
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 10,
+ "cacheRead": 0.1,
+ "cacheWrite": 2
+ },
+ "releaseDate": "2026-10-13",
+ "family": "gemini",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "audio",
+ "video"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
"anthropic/claude-haiku-5-5": {
"id": "anthropic/claude-haiku-5-5",
"name": "Claude Haiku 5.5",
@@ -42239,6 +43150,27 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"digitalocean": {
+ "nemotron-3.5-super-vl": {
+ "id": "nemotron-3.5-super-vl",
+ "name": "NVIDIA Nemotron 3.5 Super VL",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 1048576,
+ "capabilities": [
+ "images",
+ "tools",
+ "temperature",
+ "prompt-cache"
+ ],
+ "pricing": {
+ "input": 0.3,
+ "output": 0.65,
+ "cacheRead": 0.06,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-15",
+ "family": "nemotron"
+ },
"anthropic-claude-5.5-haiku": {
"id": "anthropic-claude-5.5-haiku",
"name": "Anthropic Claude 5.5 Haiku",
@@ -45177,6 +46109,282 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"edenai": {
+ "google/gemini-4-argon": {
+ "id": "google/gemini-4-argon",
+ "name": "Gemini 4 Argon",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 4,
+ "output": 20,
+ "cacheRead": 0.2,
+ "cacheWrite": 0.375
+ },
+ "releaseDate": "2026-10-13",
+ "family": "gemini",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio",
+ "pdf"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
+ "google/gemini-pro-latest": {
+ "id": "google/gemini-pro-latest",
+ "name": "Gemini Pro Latest (Gemini 4 Argon)",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 4,
+ "output": 20,
+ "cacheRead": 0.2,
+ "cacheWrite": 0.375
+ },
+ "releaseDate": "2026-10-13",
+ "family": "gemini",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio",
+ "pdf"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
+ "vertex/gemini-4-argon": {
+ "id": "vertex/gemini-4-argon",
+ "name": "Gemini 4 Argon (Vertex AI)",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 4,
+ "output": 20,
+ "cacheRead": 0.2,
+ "cacheWrite": 0.375
+ },
+ "releaseDate": "2026-10-13",
+ "family": "gemini",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio",
+ "pdf"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
+ "vertex/gemini-4-argon@eu": {
+ "id": "vertex/gemini-4-argon@eu",
+ "name": "Gemini 4 Argon (Vertex AI, EU)",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 4,
+ "output": 20,
+ "cacheRead": 0.2,
+ "cacheWrite": 0.375
+ },
+ "releaseDate": "2026-10-13",
+ "family": "gemini",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio",
+ "pdf"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
+ "vertex/gemini-4-argon@us": {
+ "id": "vertex/gemini-4-argon@us",
+ "name": "Gemini 4 Argon (Vertex AI, US)",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 4,
+ "output": 20,
+ "cacheRead": 0.2,
+ "cacheWrite": 0.375
+ },
+ "releaseDate": "2026-10-13",
+ "family": "gemini",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio",
+ "pdf"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
+ "vertex/gemini-pro-latest": {
+ "id": "vertex/gemini-pro-latest",
+ "name": "Gemini Pro Latest (Gemini 4 Argon, Vertex AI)",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 4,
+ "output": 20,
+ "cacheRead": 0.2,
+ "cacheWrite": 0.375
+ },
+ "releaseDate": "2026-10-13",
+ "family": "gemini",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio",
+ "pdf"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
"anthropic/claude-haiku-5-5": {
"id": "anthropic/claude-haiku-5-5",
"name": "Claude Haiku 5.5",
@@ -45213,6 +46421,42 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-10-07",
"family": "claude-haiku"
},
+ "anthropic/claude-haiku-latest": {
+ "id": "anthropic/claude-haiku-latest",
+ "name": "Claude Haiku Latest (Claude Haiku 5.5)",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.1,
+ "output": 0.5,
+ "cacheRead": 0.01,
+ "cacheWrite": 0.125
+ },
+ "releaseDate": "2026-10-07",
+ "family": "claude-haiku"
+ },
"openai/gpt-6.1-sol": {
"id": "openai/gpt-6.1-sol",
"name": "GPT-6.1 Sol",
@@ -45574,6 +46818,38 @@ export const GENERATED_PROVIDER_MODELS: {
]
}
},
+ "deepinfra/stepfun-ai/Step-5-Preview": {
+ "id": "deepinfra/stepfun-ai/Step-5-Preview",
+ "name": "Step 5 Preview (Deep Infra)",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 1000000,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1,
+ "output": 2.7,
+ "cacheRead": 0.05,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-09-16"
+ },
"deepinfra/deepseek-ai/DeepSeek-V4.1-Flash": {
"id": "deepinfra/deepseek-ai/DeepSeek-V4.1-Flash",
"name": "DeepSeek V4.1 Flash (Deep Infra)",
@@ -45634,9 +46910,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.09,
- "output": 0.18,
- "cacheRead": 0.0135,
+ "input": 0.1,
+ "output": 0.66,
+ "cacheRead": 0.015,
"cacheWrite": 0
},
"releaseDate": "2026-09-10",
@@ -45700,9 +46976,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.245982,
- "output": 1.229911,
- "cacheRead": 0.012299,
+ "input": 0.246576,
+ "output": 1.23288,
+ "cacheRead": 0.012329,
"cacheWrite": 0
},
"releaseDate": "2026-09-10",
@@ -45782,6 +47058,7 @@ export const GENERATED_PROVIDER_MODELS: {
"maxInputTokens": 256000,
"maxTokens": 384000,
"capabilities": [
+ "images",
"tools",
"reasoning",
"temperature",
@@ -45799,9 +47076,43 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.67086,
- "output": 2.012581,
- "cacheRead": 0.134172,
+ "input": 0.67248,
+ "output": 2.01744,
+ "cacheRead": 0.134496,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-09-10",
+ "family": "deepseek-flash"
+ },
+ "tencent/deepseek-v4.1-flash": {
+ "id": "tencent/deepseek-v4.1-flash",
+ "name": "DeepSeek V4.1 Flash (Tencent)",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 384000,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "high",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.15,
+ "output": 0.6,
+ "cacheRead": 0.003,
"cacheWrite": 0
},
"releaseDate": "2026-09-10",
@@ -46432,6 +47743,40 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-08-26",
"family": "glm-flash"
},
+ "deepseek-v4-flash-vision-exp": {
+ "id": "deepseek-v4-flash-vision-exp",
+ "name": "DeepSeek V4 Flash Vision Exp",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 384000,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "high",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.15,
+ "output": 0.6,
+ "cacheRead": 0.003,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-08-21",
+ "family": "deepseek-flash"
+ },
"deepseek/deepseek-v4-flash-vision-exp": {
"id": "deepseek/deepseek-v4-flash-vision-exp",
"name": "DeepSeek V4 Flash Vision Exp",
@@ -46917,6 +48262,39 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-08-12",
"family": "qwen"
},
+ "tencent/deepseek-v4-pro-0813": {
+ "id": "tencent/deepseek-v4-pro-0813",
+ "name": "DeepSeek V4 Pro 0813 (Tencent)",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 384000,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "high",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.66,
+ "output": 1.98,
+ "cacheRead": 0.022,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-08-12",
+ "family": "deepseek-thinking"
+ },
"tensorx/deepseek/deepseek-v4-pro-0813": {
"id": "tensorx/deepseek/deepseek-v4-pro-0813",
"name": "DeepSeek V4 Pro 0813 (TensorX)",
@@ -47076,9 +48454,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.35,
- "output": 1.5,
- "cacheRead": 0.0525,
+ "input": 0.3,
+ "output": 1.2,
+ "cacheRead": 0.045,
"cacheWrite": 0
},
"releaseDate": "2026-08-10",
@@ -47276,9 +48654,42 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.0192,
- "output": 0.27,
- "cacheRead": 0.0029,
+ "input": 0.119,
+ "output": 0.238,
+ "cacheRead": 0.0178,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-07-31",
+ "family": "deepseek-flash"
+ },
+ "flexai/DeepSeek-V4-Flash-0731@eu": {
+ "id": "flexai/DeepSeek-V4-Flash-0731@eu",
+ "name": "DeepSeek V4 Flash 0731 (FlexAI, EU)",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 384000,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "high",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.119,
+ "output": 0.238,
+ "cacheRead": 0.0178,
"cacheWrite": 0
},
"releaseDate": "2026-07-31",
@@ -47309,9 +48720,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.156534,
- "output": 0.391335,
- "cacheRead": 0.044724,
+ "input": 0.156912,
+ "output": 0.39228,
+ "cacheRead": 0.044832,
"cacheWrite": 0
},
"releaseDate": "2026-07-31",
@@ -47407,9 +48818,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.44724,
- "output": 0.89448,
- "cacheRead": 0.089448,
+ "input": 0.44832,
+ "output": 0.89664,
+ "cacheRead": 0.089664,
"cacheWrite": 0
},
"releaseDate": "2026-07-31",
@@ -48249,6 +49660,78 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-07-09",
"family": "gpt-terra"
},
+ "openai/gpt-mini-latest": {
+ "id": "openai/gpt-mini-latest",
+ "name": "GPT Mini Latest (GPT-5.6 Luna)",
+ "contextWindow": 1050000,
+ "maxInputTokens": 922000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.2,
+ "output": 1.2,
+ "cacheRead": 0.02,
+ "cacheWrite": 0.25
+ },
+ "releaseDate": "2026-07-09",
+ "family": "gpt-luna"
+ },
+ "openai/gpt-pro-latest": {
+ "id": "openai/gpt-pro-latest",
+ "name": "GPT Pro Latest (GPT-5.6 Sol)",
+ "contextWindow": 1050000,
+ "maxInputTokens": 922000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 4,
+ "output": 20,
+ "cacheRead": 0.4,
+ "cacheWrite": 5
+ },
+ "releaseDate": "2026-07-09",
+ "family": "gpt-sol"
+ },
"xai/grok-4.5": {
"id": "xai/grok-4.5",
"name": "Grok 4.5",
@@ -49244,38 +50727,6 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-04-23",
"family": "gpt-pro"
},
- "openai/gpt-pro-latest": {
- "id": "openai/gpt-pro-latest",
- "name": "GPT Pro Latest (GPT-5.5 Pro)",
- "contextWindow": 1050000,
- "maxInputTokens": 922000,
- "maxTokens": 128000,
- "capabilities": [
- "images",
- "files",
- "tools",
- "reasoning",
- "structured_output"
- ],
- "reasoningOptions": [
- {
- "type": "effort",
- "values": [
- "medium",
- "high",
- "xhigh"
- ]
- }
- ],
- "pricing": {
- "input": 30,
- "output": 180,
- "cacheRead": 0,
- "cacheWrite": 0
- },
- "releaseDate": "2026-04-23",
- "family": "gpt-pro"
- },
"moonshot/kimi-k2.6": {
"id": "moonshot/kimi-k2.6",
"name": "Kimi K2.6",
@@ -49538,42 +50989,6 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-03-17",
"family": "gpt-nano"
},
- "openai/gpt-mini-latest": {
- "id": "openai/gpt-mini-latest",
- "name": "GPT Mini Latest (GPT-5.4 mini)",
- "contextWindow": 400000,
- "maxInputTokens": 272000,
- "maxTokens": 128000,
- "capabilities": [
- "images",
- "files",
- "tools",
- "reasoning",
- "structured_output",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [
- {
- "type": "effort",
- "values": [
- "none",
- "low",
- "medium",
- "high",
- "xhigh"
- ]
- }
- ],
- "pricing": {
- "input": 0.75,
- "output": 4.5,
- "cacheRead": 0.075,
- "cacheWrite": 0
- },
- "releaseDate": "2026-03-17",
- "family": "gpt-mini"
- },
"mistral/mistral-small-2603": {
"id": "mistral/mistral-small-2603",
"name": "Mistral Small 4",
@@ -49949,53 +51364,6 @@ export const GENERATED_PROVIDER_MODELS: {
]
}
},
- "google/gemini-pro-latest": {
- "id": "google/gemini-pro-latest",
- "name": "Gemini Pro Latest (Gemini 3.1 Pro Preview)",
- "contextWindow": 1048576,
- "maxInputTokens": 1048576,
- "maxTokens": 65536,
- "capabilities": [
- "images",
- "video",
- "files",
- "tools",
- "reasoning",
- "structured_output",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [
- {
- "type": "effort",
- "values": [
- "low",
- "medium",
- "high"
- ]
- }
- ],
- "pricing": {
- "input": 2,
- "output": 12,
- "cacheRead": 0.2,
- "cacheWrite": 0.375
- },
- "releaseDate": "2026-02-19",
- "family": "gemini-pro",
- "modalities": {
- "input": [
- "text",
- "image",
- "video",
- "audio",
- "pdf"
- ],
- "output": [
- "text"
- ]
- }
- },
"vertex/gemini-3.1-pro-preview": {
"id": "vertex/gemini-3.1-pro-preview",
"name": "Gemini 3.1 Pro Preview (Vertex AI)",
@@ -50043,53 +51411,6 @@ export const GENERATED_PROVIDER_MODELS: {
]
}
},
- "vertex/gemini-pro-latest": {
- "id": "vertex/gemini-pro-latest",
- "name": "Gemini Pro Latest (Gemini 3.1 Pro Preview, Vertex AI)",
- "contextWindow": 1048576,
- "maxInputTokens": 1048576,
- "maxTokens": 65536,
- "capabilities": [
- "images",
- "video",
- "files",
- "tools",
- "reasoning",
- "structured_output",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [
- {
- "type": "effort",
- "values": [
- "low",
- "medium",
- "high"
- ]
- }
- ],
- "pricing": {
- "input": 2,
- "output": 12,
- "cacheRead": 0.2,
- "cacheWrite": 0.375
- },
- "releaseDate": "2026-02-19",
- "family": "gemini-pro",
- "modalities": {
- "input": [
- "text",
- "image",
- "video",
- "audio",
- "pdf"
- ],
- "output": [
- "text"
- ]
- }
- },
"anthropic/claude-sonnet-4-6": {
"id": "anthropic/claude-sonnet-4-6",
"name": "Claude Sonnet 4.6",
@@ -50330,6 +51651,26 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-02-03",
"family": "qwen"
},
+ "ionos/Qwen/Qwen3-Coder-Next": {
+ "id": "ionos/Qwen/Qwen3-Coder-Next",
+ "name": "Qwen3 Coder Next (IONOS)",
+ "contextWindow": 128000,
+ "maxInputTokens": 128000,
+ "maxTokens": 65536,
+ "capabilities": [
+ "tools",
+ "structured_output",
+ "temperature"
+ ],
+ "pricing": {
+ "input": 0.16812,
+ "output": 0.89664,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-02-03",
+ "family": "qwen"
+ },
"deepinfra/stepfun-ai/Step-3.5-Flash": {
"id": "deepinfra/stepfun-ai/Step-3.5-Flash",
"name": "Step 3.5 Flash (Deep Infra)",
@@ -50849,6 +52190,27 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2025-12-08",
"family": "glm"
},
+ "infomaniak/mistralai/Ministral-3-14B-Instruct-2512": {
+ "id": "infomaniak/mistralai/Ministral-3-14B-Instruct-2512",
+ "name": "Ministral 3 14B (Infomaniak)",
+ "contextWindow": 100000,
+ "maxInputTokens": 100000,
+ "maxTokens": 262144,
+ "capabilities": [
+ "images",
+ "tools",
+ "structured_output",
+ "temperature"
+ ],
+ "pricing": {
+ "input": 0.33624,
+ "output": 0.44832,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2025-12-02",
+ "family": "ministral"
+ },
"mistral/devstral-medium-latest": {
"id": "mistral/devstral-medium-latest",
"name": "Devstral 2 (latest)",
@@ -51098,7 +52460,6 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "none",
"low",
"medium",
"high"
@@ -51963,9 +53324,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.03,
- "output": 0.17,
- "cacheRead": 0.0045,
+ "input": 0.05,
+ "output": 0.25,
+ "cacheRead": 0.0075,
"cacheWrite": 0
},
"releaseDate": "2025-08-05",
@@ -52026,8 +53387,8 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.22362,
- "output": 0.78267,
+ "input": 0.22416,
+ "output": 0.78456,
"cacheRead": 0,
"cacheWrite": 0
},
@@ -52098,6 +53459,37 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2025-08-05",
"family": "gpt-oss"
},
+ "ionos/openai/gpt-oss-120b": {
+ "id": "ionos/openai/gpt-oss-120b",
+ "name": "GPT OSS 120B (IONOS)",
+ "contextWindow": 128000,
+ "maxInputTokens": 128000,
+ "maxTokens": 32768,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.16812,
+ "output": 0.72852,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2025-08-05",
+ "family": "gpt-oss"
+ },
"nebius/openai/gpt-oss-120b": {
"id": "nebius/openai/gpt-oss-120b",
"name": "GPT OSS 120B (Nebius)",
@@ -52130,6 +53522,68 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2025-08-05",
"family": "gpt-oss"
},
+ "ovhcloud/gpt-oss-120b": {
+ "id": "ovhcloud/gpt-oss-120b",
+ "name": "GPT OSS 120B (OVHcloud)",
+ "contextWindow": 131072,
+ "maxInputTokens": 131072,
+ "maxTokens": 32768,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.09,
+ "output": 0.47,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2025-08-05",
+ "family": "gpt-oss"
+ },
+ "ovhcloud/gpt-oss-20b": {
+ "id": "ovhcloud/gpt-oss-20b",
+ "name": "GPT OSS 20B (OVHcloud)",
+ "contextWindow": 131072,
+ "maxInputTokens": 131072,
+ "maxTokens": 32768,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.05,
+ "output": 0.18,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2025-08-05",
+ "family": "gpt-oss"
+ },
"scaleway/gpt-oss-120b": {
"id": "scaleway/gpt-oss-120b",
"name": "GPT OSS 120B (Scaleway)",
@@ -52152,8 +53606,8 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.167715,
- "output": 0.67086,
+ "input": 0.16812,
+ "output": 0.67248,
"cacheRead": 0,
"cacheWrite": 0
},
@@ -52265,8 +53719,8 @@ export const GENERATED_PROVIDER_MODELS: {
"temperature"
],
"pricing": {
- "input": 1.00629,
- "output": 3.018871,
+ "input": 1.00872,
+ "output": 3.026159,
"cacheRead": 0,
"cacheWrite": 0
},
@@ -52305,8 +53759,8 @@ export const GENERATED_PROVIDER_MODELS: {
"temperature"
],
"pricing": {
- "input": 0.838575,
- "output": 2.515726,
+ "input": 0.8406,
+ "output": 2.5218,
"cacheRead": 0,
"cacheWrite": 0
},
@@ -52706,8 +54160,8 @@ export const GENERATED_PROVIDER_MODELS: {
"temperature"
],
"pricing": {
- "input": 0.22362,
- "output": 0.89448,
+ "input": 0.22416,
+ "output": 0.89664,
"cacheRead": 0,
"cacheWrite": 0
},
@@ -53172,8 +54626,28 @@ export const GENERATED_PROVIDER_MODELS: {
"temperature"
],
"pricing": {
- "input": 1.229911,
- "output": 1.229911,
+ "input": 1.23288,
+ "output": 1.23288,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2024-12-06",
+ "family": "llama"
+ },
+ "ionos/meta-llama/Llama-3.3-70B-Instruct": {
+ "id": "ionos/meta-llama/Llama-3.3-70B-Instruct",
+ "name": "Llama-3.3-70B-Instruct (IONOS)",
+ "contextWindow": 128000,
+ "maxInputTokens": 128000,
+ "maxTokens": 4096,
+ "capabilities": [
+ "tools",
+ "structured_output",
+ "temperature"
+ ],
+ "pricing": {
+ "input": 0.72852,
+ "output": 0.72852,
"cacheRead": 0,
"cacheWrite": 0
},
@@ -53191,8 +54665,8 @@ export const GENERATED_PROVIDER_MODELS: {
"temperature"
],
"pricing": {
- "input": 1.00629,
- "output": 1.00629,
+ "input": 1.00872,
+ "output": 1.00872,
"cacheRead": 0,
"cacheWrite": 0
},
@@ -57459,6 +58933,40 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"fireworks": {
+ "accounts/fireworks/models/muse-spark-open": {
+ "id": "accounts/fireworks/models/muse-spark-open",
+ "name": "Muse Spark Open",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 131072,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1.25,
+ "output": 4.25,
+ "cacheRead": 0.15,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-15",
+ "family": "muse"
+ },
"accounts/fireworks/models/ember-1": {
"id": "accounts/fireworks/models/ember-1",
"name": "Ember-1",
@@ -59548,6 +61056,53 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"gemini": {
+ "gemini-4-argon": {
+ "id": "gemini-4-argon",
+ "name": "Gemini 4 Argon",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 32768,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 10,
+ "cacheRead": 0.1,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-13",
+ "family": "gemini",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio",
+ "pdf"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
"gemini-3.8-flash": {
"id": "gemini-3.8-flash",
"name": "Gemini 3.8 Flash",
@@ -60589,6 +62144,52 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"github-copilot": {
+ "gemini-4-argon": {
+ "id": "gemini-4-argon",
+ "name": "Gemini 4 Argon",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 10,
+ "cacheRead": 0.1,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-13",
+ "family": "gemini",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio",
+ "pdf"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
"claude-haiku-5.5": {
"id": "claude-haiku-5.5",
"name": "Claude Haiku 5.5",
@@ -68051,6 +69652,25 @@ export const GENERATED_PROVIDER_MODELS: {
},
"releaseDate": "2026-04-13",
"family": "gpt-oss"
+ },
+ "prism": {
+ "id": "prism",
+ "name": "Prism",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 16000,
+ "capabilities": [
+ "images",
+ "tools",
+ "prompt-cache"
+ ],
+ "pricing": {
+ "input": 3.2664,
+ "output": 16.332,
+ "cacheRead": 0.32664,
+ "cacheWrite": 0
+ },
+ "releaseDate": "1970-01-01"
}
},
"iflowcn": {
@@ -72188,6 +73808,70 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"iteracompute": {
+ "deepseek/deepseek-v4-flash-0731": {
+ "id": "deepseek/deepseek-v4-flash-0731",
+ "name": "DeepSeek V4 Flash 0731 (legacy alias)",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 393216,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "high",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.29,
+ "output": 1.16,
+ "cacheRead": 0.0058,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-09-10",
+ "family": "deepseek-flash"
+ },
+ "deepseek/deepseek-v4.1-flash": {
+ "id": "deepseek/deepseek-v4.1-flash",
+ "name": "DeepSeek V4.1 Flash",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 393216,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "high",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.29,
+ "output": 1.16,
+ "cacheRead": 0.0058,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-09-10",
+ "family": "deepseek-flash"
+ },
"z-ai/glm-5.3-flash": {
"id": "z-ai/glm-5.3-flash",
"name": "GLM-5.3-Flash",
@@ -72212,61 +73896,34 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.14,
- "output": 0.49,
- "cacheRead": 0.03,
+ "input": 0.099,
+ "output": 0.35,
+ "cacheRead": 0.025,
"cacheWrite": 0
},
"releaseDate": "2026-08-26",
"family": "glm-flash"
},
- "ornith-ai/ornith-1.5-35b-a3b": {
- "id": "ornith-ai/ornith-1.5-35b-a3b",
- "name": "Ornith 1.5 35B A3B",
- "contextWindow": 327680,
- "maxInputTokens": 262144,
- "maxTokens": 65536,
+ "qwen/qwen3.8-27b": {
+ "id": "qwen/qwen3.8-27b",
+ "name": "Qwen3.8 27B",
+ "contextWindow": 131072,
+ "maxInputTokens": 131072,
+ "maxTokens": 8192,
"capabilities": [
"images",
"tools",
"reasoning",
"structured_output",
- "temperature",
- "prompt-cache"
+ "temperature"
],
"reasoningOptions": [
{
"type": "toggle"
- }
- ],
- "pricing": {
- "input": 0.3,
- "output": 3,
- "cacheRead": 0.03,
- "cacheWrite": 0
- },
- "releaseDate": "2026-08-18",
- "family": "ornith"
- },
- "qwen/qwen3.8-27b": {
- "id": "qwen/qwen3.8-27b",
- "name": "Qwen3.8 27B",
- "contextWindow": 327680,
- "maxInputTokens": 262144,
- "maxTokens": 65536,
- "capabilities": [
- "images",
- "tools",
- "reasoning",
- "structured_output",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [
+ },
{
"type": "effort",
"values": [
- "none",
"low",
"medium",
"xhigh"
@@ -72274,9 +73931,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.3,
- "output": 2.5,
- "cacheRead": 0.03,
+ "input": 0,
+ "output": 0,
+ "cacheRead": 0,
"cacheWrite": 0
},
"releaseDate": "2026-08-14",
@@ -72294,11 +73951,20 @@ export const GENERATED_PROVIDER_MODELS: {
"temperature",
"prompt-cache"
],
- "reasoningOptions": [],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "high",
+ "max"
+ ]
+ }
+ ],
"pricing": {
- "input": 1.2,
- "output": 3.5,
- "cacheRead": 0.26,
+ "input": 0.99,
+ "output": 3.45,
+ "cacheRead": 0.245,
"cacheWrite": 0
},
"releaseDate": "2026-08-14",
@@ -72317,11 +73983,20 @@ export const GENERATED_PROVIDER_MODELS: {
"temperature",
"prompt-cache"
],
- "reasoningOptions": [],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "high",
+ "max"
+ ]
+ }
+ ],
"pricing": {
- "input": 1.1,
- "output": 3.3,
- "cacheRead": 0.11,
+ "input": 0.89,
+ "output": 2.69,
+ "cacheRead": 0.03,
"cacheWrite": 0
},
"releaseDate": "2026-08-12",
@@ -72330,8 +74005,8 @@ export const GENERATED_PROVIDER_MODELS: {
"qwen/qwen3.8-2.4t-a95b": {
"id": "qwen/qwen3.8-2.4t-a95b",
"name": "Qwen3.8 2.4T A95B",
- "contextWindow": 970000,
- "maxInputTokens": 970000,
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
"maxTokens": 131072,
"capabilities": [
"images",
@@ -72344,40 +74019,25 @@ export const GENERATED_PROVIDER_MODELS: {
"reasoningOptions": [
{
"type": "toggle"
+ },
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "xhigh"
+ ]
}
],
"pricing": {
"input": 1.95,
- "output": 5.95,
- "cacheRead": 0.2,
+ "output": 5.7,
+ "cacheRead": 0.245,
"cacheWrite": 0
},
"releaseDate": "2026-08-12",
"family": "qwen"
},
- "deepseek/deepseek-v4-flash-0731": {
- "id": "deepseek/deepseek-v4-flash-0731",
- "name": "DeepSeek V4 Flash 0731",
- "contextWindow": 970000,
- "maxInputTokens": 970000,
- "maxTokens": 393216,
- "capabilities": [
- "tools",
- "reasoning",
- "structured_output",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [],
- "pricing": {
- "input": 0.34,
- "output": 1.05,
- "cacheRead": 0.035,
- "cacheWrite": 0
- },
- "releaseDate": "2026-07-31",
- "family": "deepseek-flash"
- },
"moonshotai/kimi-k3": {
"id": "moonshotai/kimi-k3",
"name": "Kimi K3",
@@ -72388,18 +74048,52 @@ export const GENERATED_PROVIDER_MODELS: {
"images",
"tools",
"reasoning",
+ "structured_output",
+ "temperature",
"prompt-cache"
],
- "reasoningOptions": [],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "high",
+ "max"
+ ]
+ }
+ ],
"pricing": {
- "input": 3,
- "output": 14.9,
- "cacheRead": 0.29,
+ "input": 2.39,
+ "output": 11.99,
+ "cacheRead": 0.24,
"cacheWrite": 0
},
"releaseDate": "2026-07-16",
"family": "kimi-k3"
},
+ "moonshotai/kimi-k2.7-code": {
+ "id": "moonshotai/kimi-k2.7-code",
+ "name": "Kimi K2.7 Code",
+ "contextWindow": 262144,
+ "maxInputTokens": 262144,
+ "maxTokens": 235929,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [],
+ "pricing": {
+ "input": 0.69,
+ "output": 3.29,
+ "cacheRead": 0.15,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-06-12",
+ "family": "kimi-k2"
+ },
"minimax/minimax-m3": {
"id": "minimax/minimax-m3",
"name": "MiniMax-M3",
@@ -72415,9 +74109,9 @@ export const GENERATED_PROVIDER_MODELS: {
],
"reasoningOptions": [],
"pricing": {
- "input": 0.29,
- "output": 1.2,
- "cacheRead": 0.08,
+ "input": 0.299,
+ "output": 1.19,
+ "cacheRead": 0.045,
"cacheWrite": 0
},
"releaseDate": "2026-06-01",
@@ -76109,6 +77803,236 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"kilo": {
+ "meta/muse-spark-open": {
+ "id": "meta/muse-spark-open",
+ "name": "Muse Spark Open",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 943718,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1.25,
+ "output": 4.25,
+ "cacheRead": 0.15,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-15",
+ "family": "muse",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "pdf",
+ "audio"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
+ "nvidia/nemotron-3.5-super-vl": {
+ "id": "nvidia/nemotron-3.5-super-vl",
+ "name": "NVIDIA: Nemotron 3.5 Super VL",
+ "contextWindow": 262144,
+ "maxInputTokens": 262144,
+ "maxTokens": 235929,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.1,
+ "output": 0.4,
+ "cacheRead": 0.08,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-15",
+ "family": "nemotron"
+ },
+ "nvidia/nemotron-3.5-super-vl:free": {
+ "id": "nvidia/nemotron-3.5-super-vl:free",
+ "name": "NVIDIA: Nemotron 3.5 Super VL (free)",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 131072,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0,
+ "output": 0,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-15",
+ "family": "nemotron"
+ },
+ "~unbiased/pareto-latest": {
+ "id": "~unbiased/pareto-latest",
+ "name": "Pareto Latest",
+ "contextWindow": 262144,
+ "maxInputTokens": 262144,
+ "maxTokens": 131072,
+ "capabilities": [
+ "images",
+ "tools",
+ "temperature",
+ "prompt-cache"
+ ],
+ "pricing": {
+ "input": 2.5,
+ "output": 7.5,
+ "cacheRead": 0.25,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-13"
+ },
+ "google/gemini-4-argon": {
+ "id": "google/gemini-4-argon",
+ "name": "Gemini 4 Argon",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 10,
+ "cacheRead": 0.1,
+ "cacheWrite": 0.1875
+ },
+ "releaseDate": "2026-10-13",
+ "family": "gemini",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio",
+ "pdf"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
+ "liquid/lfm-2.5-24b-a2b": {
+ "id": "liquid/lfm-2.5-24b-a2b",
+ "name": "LiquidAI: LFM2.5-24B-A2B",
+ "contextWindow": 128000,
+ "maxInputTokens": 128000,
+ "maxTokens": 8192,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.05,
+ "output": 0.7,
+ "cacheRead": 0.025,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-13",
+ "family": "liquid"
+ },
+ "unbiased/pareto-26.9": {
+ "id": "unbiased/pareto-26.9",
+ "name": "Pareto 26.9",
+ "contextWindow": 262144,
+ "maxInputTokens": 262144,
+ "maxTokens": 131072,
+ "capabilities": [
+ "images",
+ "tools",
+ "temperature",
+ "prompt-cache"
+ ],
+ "pricing": {
+ "input": 2.5,
+ "output": 7.5,
+ "cacheRead": 0.25,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-13"
+ },
"meta/muse-wonder": {
"id": "meta/muse-wonder",
"name": "Meta: Muse Wonder",
@@ -76236,7 +78160,9 @@ export const GENERATED_PROVIDER_MODELS: {
"capabilities": [
"tools",
"reasoning",
- "temperature"
+ "structured_output",
+ "temperature",
+ "prompt-cache"
],
"reasoningOptions": [
{
@@ -76248,34 +78174,14 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0,
- "output": 0,
- "cacheRead": 0,
+ "input": 0.3,
+ "output": 0.9,
+ "cacheRead": 0.06,
"cacheWrite": 0
},
"releaseDate": "2026-10-02",
"family": "ling"
},
- "unbiased/pareto-26.10-preview": {
- "id": "unbiased/pareto-26.10-preview",
- "name": "Pareto 26.10 Preview",
- "contextWindow": 1048576,
- "maxInputTokens": 1048576,
- "maxTokens": 131072,
- "capabilities": [
- "images",
- "tools",
- "temperature",
- "prompt-cache"
- ],
- "pricing": {
- "input": 0.8,
- "output": 3.2,
- "cacheRead": 0.03,
- "cacheWrite": 0
- },
- "releaseDate": "2026-10-01"
- },
"openai/gpt-6.1-sol": {
"id": "openai/gpt-6.1-sol",
"name": "GPT-6.1 Sol",
@@ -77109,26 +79015,6 @@ export const GENERATED_PROVIDER_MODELS: {
]
}
},
- "unbiased/pareto": {
- "id": "unbiased/pareto",
- "name": "Pareto",
- "contextWindow": 262144,
- "maxInputTokens": 262144,
- "maxTokens": 131072,
- "capabilities": [
- "images",
- "tools",
- "temperature",
- "prompt-cache"
- ],
- "pricing": {
- "input": 2.5,
- "output": 7.5,
- "cacheRead": 0.25,
- "cacheWrite": 0
- },
- "releaseDate": "2026-09-17"
- },
"stepfun/step-5-preview": {
"id": "stepfun/step-5-preview",
"name": "Step 5 Preview",
@@ -77157,7 +79043,7 @@ export const GENERATED_PROVIDER_MODELS: {
"pricing": {
"input": 1,
"output": 2.7,
- "cacheRead": 0.05,
+ "cacheRead": 0.1,
"cacheWrite": 0
},
"releaseDate": "2026-09-16"
@@ -77188,8 +79074,8 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.0441,
- "output": 0.891,
+ "input": 0.0144,
+ "output": 0.684,
"cacheRead": 0.0054,
"cacheWrite": 0
},
@@ -77201,7 +79087,7 @@ export const GENERATED_PROVIDER_MODELS: {
"name": "DeepSeek: DeepSeek Pro Latest",
"contextWindow": 1048576,
"maxInputTokens": 1048576,
- "maxTokens": 943718,
+ "maxTokens": 393216,
"capabilities": [
"tools",
"reasoning",
@@ -77221,9 +79107,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.25,
- "output": 5,
- "cacheRead": 0.2,
+ "input": 0.225,
+ "output": 8,
+ "cacheRead": 0.23,
"cacheWrite": 0
},
"releaseDate": "2026-09-14",
@@ -77442,7 +79328,7 @@ export const GENERATED_PROVIDER_MODELS: {
"name": "DeepSeek V4.1 Flash",
"contextWindow": 1048576,
"maxInputTokens": 1048576,
- "maxTokens": 943718,
+ "maxTokens": 393216,
"capabilities": [
"images",
"tools",
@@ -77474,8 +79360,8 @@ export const GENERATED_PROVIDER_MODELS: {
"inclusionai/ling-3.0-flash-vl": {
"id": "inclusionai/ling-3.0-flash-vl",
"name": "inclusionAI: Ling 3.0 Flash VL",
- "contextWindow": 262144,
- "maxInputTokens": 262144,
+ "contextWindow": 131072,
+ "maxInputTokens": 131072,
"maxTokens": 32768,
"capabilities": [
"images",
@@ -77496,9 +79382,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.075,
- "output": 0.22,
- "cacheRead": 0.015,
+ "input": 0.06,
+ "output": 0.18,
+ "cacheRead": 0.012,
"cacheWrite": 0
},
"releaseDate": "2026-09-10",
@@ -77570,36 +79456,6 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-09-08",
"family": "agi"
},
- "inclusionai/ling-3.0-flash-sante": {
- "id": "inclusionai/ling-3.0-flash-sante",
- "name": "inclusionAI: Ling 3.0 Flash Sante",
- "contextWindow": 262144,
- "maxInputTokens": 262144,
- "maxTokens": 32768,
- "capabilities": [
- "tools",
- "reasoning",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [
- {
- "type": "effort",
- "values": [
- "none",
- "high"
- ]
- }
- ],
- "pricing": {
- "input": 0.075,
- "output": 0.22,
- "cacheRead": 0.015,
- "cacheWrite": 0
- },
- "releaseDate": "2026-09-04",
- "family": "ling"
- },
"openai/gpt-6-astra": {
"id": "openai/gpt-6-astra",
"name": "GPT-6 Astra",
@@ -77920,9 +79776,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.7506,
- "output": 2.2509,
- "cacheRead": 0.0378,
+ "input": 0.801,
+ "output": 2.48,
+ "cacheRead": 0.038,
"cacheWrite": 0
},
"releaseDate": "2026-08-28",
@@ -77933,7 +79789,7 @@ export const GENERATED_PROVIDER_MODELS: {
"name": "Z.ai: GLM Flash Latest",
"contextWindow": 1048576,
"maxInputTokens": 1048576,
- "maxTokens": 943718,
+ "maxTokens": 131072,
"capabilities": [
"images",
"video",
@@ -77954,44 +79810,14 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.0261,
- "output": 0.9,
- "cacheRead": 0.0108,
+ "input": 0.0139,
+ "output": 0.8132,
+ "cacheRead": 0.0125,
"cacheWrite": 0
},
"releaseDate": "2026-08-27",
"family": "glm-flash"
},
- "inclusionai/ling-3.0-flash-fin": {
- "id": "inclusionai/ling-3.0-flash-fin",
- "name": "inclusionAI: Ling 3.0 Flash Fin",
- "contextWindow": 262144,
- "maxInputTokens": 262144,
- "maxTokens": 32768,
- "capabilities": [
- "tools",
- "reasoning",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [
- {
- "type": "effort",
- "values": [
- "none",
- "high"
- ]
- }
- ],
- "pricing": {
- "input": 0.075,
- "output": 0.22,
- "cacheRead": 0.015,
- "cacheWrite": 0
- },
- "releaseDate": "2026-08-27",
- "family": "ling"
- },
"qwen/qwen3.8-flash": {
"id": "qwen/qwen3.8-flash",
"name": "Qwen3.8 Flash",
@@ -78028,9 +79854,9 @@ export const GENERATED_PROVIDER_MODELS: {
"z-ai/glm-5.3-flash": {
"id": "z-ai/glm-5.3-flash",
"name": "GLM-5.3-Flash",
- "contextWindow": 1048576,
- "maxInputTokens": 1048576,
- "maxTokens": 943718,
+ "contextWindow": 1048575,
+ "maxInputTokens": 1048575,
+ "maxTokens": 943717,
"capabilities": [
"images",
"video",
@@ -78135,7 +79961,7 @@ export const GENERATED_PROVIDER_MODELS: {
"name": "Z.ai: GLM Latest",
"contextWindow": 1048576,
"maxInputTokens": 1048576,
- "maxTokens": 943718,
+ "maxTokens": 131072,
"capabilities": [
"tools",
"reasoning",
@@ -78154,9 +79980,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.055,
- "output": 5,
- "cacheRead": 0.06,
+ "input": 0.0608,
+ "output": 4.4,
+ "cacheRead": 0.0565,
"cacheWrite": 0
},
"releaseDate": "2026-08-19",
@@ -78374,8 +80200,8 @@ export const GENERATED_PROVIDER_MODELS: {
"qwen/qwen3.8-2.4t-a95b": {
"id": "qwen/qwen3.8-2.4t-a95b",
"name": "Qwen3.8 2.4T A95B",
- "contextWindow": 1048576,
- "maxInputTokens": 1048576,
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
"maxTokens": 131072,
"capabilities": [
"tools",
@@ -78692,9 +80518,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.0144,
- "output": 0.576,
- "cacheRead": 0.0108,
+ "input": 0.0058,
+ "output": 0.64,
+ "cacheRead": 0.0058,
"cacheWrite": 0
},
"releaseDate": "2026-08-01",
@@ -79092,6 +80918,7 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
+ "none",
"low",
"high",
"max"
@@ -79549,9 +81376,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.0825,
- "output": 0.33,
- "cacheRead": 0.020625,
+ "input": 0.132,
+ "output": 0.528,
+ "cacheRead": 0.033,
"cacheWrite": 0
},
"releaseDate": "2026-07-06",
@@ -79870,9 +81697,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.5,
- "output": 2.2,
- "cacheRead": 0.1,
+ "input": 0.4,
+ "output": 1.76,
+ "cacheRead": 0.08,
"cacheWrite": 0
},
"releaseDate": "2026-06-04",
@@ -80412,9 +82239,9 @@ export const GENERATED_PROVIDER_MODELS: {
],
"pricing": {
"input": 2,
- "output": 12,
- "cacheRead": 0.2,
- "cacheWrite": 0.375
+ "output": 10,
+ "cacheRead": 0.1,
+ "cacheWrite": 0.1875
},
"releaseDate": "2026-04-27",
"family": "gemini-pro",
@@ -80458,9 +82285,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.73,
- "output": 13.5,
- "cacheRead": 0.55,
+ "input": 0.33,
+ "output": 14,
+ "cacheRead": 0.3,
"cacheWrite": 0
},
"releaseDate": "2026-04-27",
@@ -80570,9 +82397,9 @@ export const GENERATED_PROVIDER_MODELS: {
"deepseek/deepseek-v4-flash": {
"id": "deepseek/deepseek-v4-flash",
"name": "DeepSeek V4 Flash",
- "contextWindow": 1048576,
- "maxInputTokens": 1048576,
- "maxTokens": 943718,
+ "contextWindow": 1048575,
+ "maxInputTokens": 1048575,
+ "maxTokens": 943717,
"capabilities": [
"tools",
"reasoning",
@@ -80591,9 +82418,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.0425,
- "output": 1.28,
- "cacheRead": 0.0425,
+ "input": 0.091,
+ "output": 0.182,
+ "cacheRead": 0.0182,
"cacheWrite": 0
},
"releaseDate": "2026-04-24",
@@ -80703,7 +82530,7 @@ export const GENERATED_PROVIDER_MODELS: {
"name": "Qwen3.6 27B",
"contextWindow": 262144,
"maxInputTokens": 262144,
- "maxTokens": 81920,
+ "maxTokens": 65536,
"capabilities": [
"images",
"video",
@@ -80908,7 +82735,7 @@ export const GENERATED_PROVIDER_MODELS: {
"name": "Qwen3.6 35B-A3B",
"contextWindow": 262144,
"maxInputTokens": 262144,
- "maxTokens": 65536,
+ "maxTokens": 235929,
"capabilities": [
"images",
"video",
@@ -80928,9 +82755,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.1,
- "output": 0.95,
- "cacheRead": 0.1,
+ "input": 0.15,
+ "output": 1,
+ "cacheRead": 0.05,
"cacheWrite": 0
},
"releaseDate": "2026-04-17",
@@ -81165,9 +82992,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.09,
+ "input": 0.1,
"output": 0.34,
- "cacheRead": 0.05,
+ "cacheRead": 0.1,
"cacheWrite": 0
},
"releaseDate": "2026-04-02",
@@ -81821,9 +83648,9 @@ export const GENERATED_PROVIDER_MODELS: {
"qwen/qwen3.5-35b-a3b": {
"id": "qwen/qwen3.5-35b-a3b",
"name": "Qwen3.5 35B-A3B",
- "contextWindow": 262144,
- "maxInputTokens": 262144,
- "maxTokens": 32768,
+ "contextWindow": 256000,
+ "maxInputTokens": 256000,
+ "maxTokens": 16384,
"capabilities": [
"images",
"video",
@@ -82183,9 +84010,9 @@ export const GENERATED_PROVIDER_MODELS: {
"minimax/minimax-m2.5": {
"id": "minimax/minimax-m2.5",
"name": "MiniMax-M2.5",
- "contextWindow": 200000,
- "maxInputTokens": 200000,
- "maxTokens": 128000,
+ "contextWindow": 198000,
+ "maxInputTokens": 198000,
+ "maxTokens": 32768,
"capabilities": [
"tools",
"reasoning",
@@ -82213,9 +84040,9 @@ export const GENERATED_PROVIDER_MODELS: {
"z-ai/glm-5": {
"id": "z-ai/glm-5",
"name": "GLM-5",
- "contextWindow": 198000,
- "maxInputTokens": 198000,
- "maxTokens": 128000,
+ "contextWindow": 202752,
+ "maxInputTokens": 202752,
+ "maxTokens": 131072,
"capabilities": [
"tools",
"reasoning",
@@ -82233,9 +84060,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.6,
- "output": 1.92,
- "cacheRead": 0.12,
+ "input": 1,
+ "output": 3.2,
+ "cacheRead": 0.2,
"cacheWrite": 0
},
"releaseDate": "2026-02-12",
@@ -82999,17 +84826,17 @@ export const GENERATED_PROVIDER_MODELS: {
"deepseek/deepseek-chat": {
"id": "deepseek/deepseek-chat",
"name": "DeepSeek Chat",
- "contextWindow": 163840,
- "maxInputTokens": 163840,
- "maxTokens": 16384,
+ "contextWindow": 128000,
+ "maxInputTokens": 128000,
+ "maxTokens": 16000,
"capabilities": [
"tools",
"structured_output",
"temperature"
],
"pricing": {
- "input": 0.32,
- "output": 0.89,
+ "input": 0.2574,
+ "output": 1.0287,
"cacheRead": 0,
"cacheWrite": 0
},
@@ -83199,7 +85026,6 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "none",
"low",
"medium",
"high"
@@ -83299,9 +85125,9 @@ export const GENERATED_PROVIDER_MODELS: {
"minimax/minimax-m2": {
"id": "minimax/minimax-m2",
"name": "MiniMax-M2",
- "contextWindow": 196608,
- "maxInputTokens": 196608,
- "maxTokens": 176947,
+ "contextWindow": 204800,
+ "maxInputTokens": 204800,
+ "maxTokens": 131072,
"capabilities": [
"tools",
"reasoning",
@@ -83632,17 +85458,16 @@ export const GENERATED_PROVIDER_MODELS: {
"name": "Qwen3-Next 80B-A3B Instruct",
"contextWindow": 262144,
"maxInputTokens": 262144,
- "maxTokens": 235929,
+ "maxTokens": 16384,
"capabilities": [
"tools",
"structured_output",
- "temperature",
- "prompt-cache"
+ "temperature"
],
"pricing": {
- "input": 0.1,
+ "input": 0.09,
"output": 1.1,
- "cacheRead": 0.07,
+ "cacheRead": 0,
"cacheWrite": 0
},
"releaseDate": "2025-09",
@@ -83885,37 +85710,6 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2025-08-26",
"family": "qwen3.6"
},
- "stepfun/step-5-preview-free": {
- "id": "stepfun/step-5-preview-free",
- "name": "StepFun: Step 5 Preview (free)",
- "contextWindow": 1000000,
- "maxInputTokens": 1000000,
- "maxTokens": 64000,
- "capabilities": [
- "images",
- "tools",
- "reasoning",
- "temperature"
- ],
- "reasoningOptions": [
- {
- "type": "effort",
- "values": [
- "low",
- "medium",
- "high"
- ]
- }
- ],
- "pricing": {
- "input": 0,
- "output": 0,
- "cacheRead": 0,
- "cacheWrite": 0
- },
- "releaseDate": "2025-08-26",
- "family": "step"
- },
"deepseek/deepseek-chat-v3.1": {
"id": "deepseek/deepseek-chat-v3.1",
"name": "DeepSeek V3.1",
@@ -84161,7 +85955,7 @@ export const GENERATED_PROVIDER_MODELS: {
"pricing": {
"input": 0.03,
"output": 0.15,
- "cacheRead": 0.03,
+ "cacheRead": 0.015,
"cacheWrite": 0
},
"releaseDate": "2025-08-05",
@@ -84646,7 +86440,6 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "none",
"high"
]
}
@@ -84733,38 +86526,6 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2025-05-28",
"family": "deepseek-thinking"
},
- "anthropic/claude-sonnet-4": {
- "id": "anthropic/claude-sonnet-4",
- "name": "Anthropic: Claude Sonnet 4",
- "contextWindow": 200000,
- "maxInputTokens": 200000,
- "maxTokens": 64000,
- "capabilities": [
- "images",
- "files",
- "tools",
- "reasoning",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [
- {
- "type": "effort",
- "values": [
- "none",
- "high"
- ]
- }
- ],
- "pricing": {
- "input": 3,
- "output": 15,
- "cacheRead": 0.3,
- "cacheWrite": 3.75
- },
- "releaseDate": "2025-05-22",
- "family": "claude-sonnet"
- },
"mistralai/mistral-medium-3": {
"id": "mistralai/mistral-medium-3",
"name": "Mistral Medium 3",
@@ -84866,7 +86627,6 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "none",
"high"
]
}
@@ -84898,7 +86658,6 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "none",
"high"
]
}
@@ -85047,8 +86806,8 @@ export const GENERATED_PROVIDER_MODELS: {
"temperature"
],
"pricing": {
- "input": 0.1,
- "output": 0.3,
+ "input": 0.08,
+ "output": 0.24,
"cacheRead": 0,
"cacheWrite": 0
},
@@ -85160,8 +86919,8 @@ export const GENERATED_PROVIDER_MODELS: {
"temperature"
],
"pricing": {
- "input": 0.05,
- "output": 0.15,
+ "input": 0.04,
+ "output": 0.12,
"cacheRead": 0,
"cacheWrite": 0
},
@@ -85286,7 +87045,6 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "none",
"high"
]
}
@@ -85397,7 +87155,6 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "none",
"high"
]
}
@@ -86754,6 +88511,46 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-10-06",
"family": "mistral-large"
},
+ "gemini-4-argon": {
+ "id": "gemini-4-argon",
+ "name": "Gemini 4 Argon",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 1048576,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 4,
+ "output": 20,
+ "cacheRead": 0.2,
+ "cacheWrite": 0.375
+ },
+ "releaseDate": "2026-09-30",
+ "family": "gemini",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "audio"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
"gpt-6.1-sol": {
"id": "gpt-6.1-sol",
"name": "GPT-6.1 Sol",
@@ -86988,9 +88785,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.14,
- "output": 0.28,
- "cacheRead": 0.0028,
+ "input": 0.12,
+ "output": 0.25,
+ "cacheRead": 0.0025,
"cacheWrite": 0
},
"releaseDate": "2026-09-22",
@@ -87088,39 +88885,6 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-09-21",
"family": "grok"
},
- "atria-dawn-preview": {
- "id": "atria-dawn-preview",
- "name": "Atria Dawn Preview",
- "contextWindow": 262144,
- "maxInputTokens": 262144,
- "maxTokens": 262144,
- "capabilities": [
- "tools",
- "reasoning",
- "temperature"
- ],
- "reasoningOptions": [
- {
- "type": "effort",
- "values": [
- "none",
- "minimal",
- "low",
- "medium",
- "high",
- "xhigh",
- "max"
- ]
- }
- ],
- "pricing": {
- "input": 0,
- "output": 0,
- "cacheRead": 0,
- "cacheWrite": 0
- },
- "releaseDate": "2026-09-12"
- },
"fugu-max": {
"id": "fugu-max",
"name": "Fugu Max",
@@ -87654,9 +89418,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.924,
- "output": 2.904,
- "cacheRead": 0.1716,
+ "input": 0.5,
+ "output": 2,
+ "cacheRead": 0.15,
"cacheWrite": 0
},
"releaseDate": "2026-08-14",
@@ -88527,7 +90291,7 @@ export const GENERATED_PROVIDER_MODELS: {
],
"reasoningOptions": [],
"pricing": {
- "input": 2.1256,
+ "input": 2.156,
"output": 6.776,
"cacheRead": 0.429,
"cacheWrite": 0
@@ -88734,9 +90498,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.3,
- "output": 1.2,
- "cacheRead": 0.06,
+ "input": 0.28,
+ "output": 1.1,
+ "cacheRead": 0.05,
"cacheWrite": 0
},
"releaseDate": "2026-06-01",
@@ -89116,9 +90880,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.065,
- "output": 0.116,
- "cacheRead": 0.012,
+ "input": 0.076,
+ "output": 0.153,
+ "cacheRead": 0.014,
"cacheWrite": 0
},
"releaseDate": "2026-04-24",
@@ -92296,149 +94060,6 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2025-06-20",
"family": "mistral-small"
},
- "gemini-2.5-flash": {
- "id": "gemini-2.5-flash",
- "name": "Gemini 2.5 Flash",
- "contextWindow": 1048576,
- "maxInputTokens": 1048576,
- "maxTokens": 65536,
- "capabilities": [
- "images",
- "video",
- "files",
- "tools",
- "reasoning",
- "structured_output",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [
- {
- "type": "budget_tokens",
- "min": 1,
- "max": 24576
- },
- {
- "type": "effort",
- "values": [
- "low",
- "medium",
- "high"
- ]
- }
- ],
- "pricing": {
- "input": 0.3,
- "output": 2.5,
- "cacheRead": 0.03,
- "cacheWrite": 0
- },
- "releaseDate": "2025-06-17",
- "family": "gemini-flash",
- "modalities": {
- "input": [
- "text",
- "image",
- "audio",
- "video",
- "pdf"
- ],
- "output": [
- "text"
- ]
- }
- },
- "gemini-2.5-flash-lite": {
- "id": "gemini-2.5-flash-lite",
- "name": "Gemini 2.5 Flash-Lite",
- "contextWindow": 1048576,
- "maxInputTokens": 1048576,
- "maxTokens": 65536,
- "capabilities": [
- "images",
- "video",
- "files",
- "tools",
- "reasoning",
- "structured_output",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [],
- "pricing": {
- "input": 0.1,
- "output": 0.4,
- "cacheRead": 0.01,
- "cacheWrite": 0
- },
- "releaseDate": "2025-06-17",
- "family": "gemini-flash-lite",
- "modalities": {
- "input": [
- "text",
- "image",
- "audio",
- "video",
- "pdf"
- ],
- "output": [
- "text"
- ]
- }
- },
- "gemini-2.5-pro": {
- "id": "gemini-2.5-pro",
- "name": "Gemini 2.5 Pro",
- "contextWindow": 1048576,
- "maxInputTokens": 1048576,
- "maxTokens": 65536,
- "capabilities": [
- "images",
- "video",
- "files",
- "tools",
- "reasoning",
- "structured_output",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [
- {
- "type": "effort",
- "values": [
- "minimal",
- "low",
- "medium",
- "high"
- ]
- },
- {
- "type": "budget_tokens",
- "min": 128,
- "max": 32768
- }
- ],
- "pricing": {
- "input": 1.25,
- "output": 10,
- "cacheRead": 0.125,
- "cacheWrite": 0
- },
- "releaseDate": "2025-06-17",
- "family": "gemini-pro",
- "modalities": {
- "input": [
- "text",
- "image",
- "audio",
- "video",
- "pdf"
- ],
- "output": [
- "text"
- ]
- }
- },
"qwen3-235b-a22b-fp8": {
"id": "qwen3-235b-a22b-fp8",
"name": "Qwen3 235B A22B FP8",
@@ -93010,6 +94631,50 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"llmgateway-providers": {
+ "google-ai-studio/gemini-4-argon": {
+ "id": "google-ai-studio/gemini-4-argon",
+ "name": "Gemini 4 Argon (Google AI Studio)",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 1048576,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 4,
+ "output": 20,
+ "cacheRead": 0.2,
+ "cacheWrite": 0.375
+ },
+ "releaseDate": "2026-10-13",
+ "family": "gemini",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio",
+ "pdf"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
"meta/muse-wonder-1.0": {
"id": "meta/muse-wonder-1.0",
"name": "Muse Wonder 1.0 (Meta)",
@@ -93171,6 +94836,46 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-10-06",
"family": "mistral-large"
},
+ "google-vertex/gemini-4-argon": {
+ "id": "google-vertex/gemini-4-argon",
+ "name": "Gemini 4 Argon (Google Vertex AI)",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 1048576,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 4,
+ "output": 20,
+ "cacheRead": 0.2,
+ "cacheWrite": 0.375
+ },
+ "releaseDate": "2026-09-30",
+ "family": "gemini",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "audio"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
"azure/gpt-6.1-sol": {
"id": "azure/gpt-6.1-sol",
"name": "GPT-6.1 Sol (Azure)",
@@ -93551,6 +95256,42 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-09-22",
"family": "gpt-sol"
},
+ "consensusprotocol/mimo-v2.6-flash": {
+ "id": "consensusprotocol/mimo-v2.6-flash",
+ "name": "MiMo V2.6 Flash (Consensus Protocol)",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 131072,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "minimal",
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.12,
+ "output": 0.25,
+ "cacheRead": 0.0025,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-09-22",
+ "family": "mimo"
+ },
"deepinfra/mimo-v2.6-flash": {
"id": "deepinfra/mimo-v2.6-flash",
"name": "MiMo V2.6 Flash (DeepInfra)",
@@ -93878,39 +95619,6 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-09-21",
"family": "grok"
},
- "atria/atria-dawn-preview": {
- "id": "atria/atria-dawn-preview",
- "name": "Atria Dawn Preview (Atria)",
- "contextWindow": 262144,
- "maxInputTokens": 262144,
- "maxTokens": 65536,
- "capabilities": [
- "tools",
- "reasoning",
- "temperature"
- ],
- "reasoningOptions": [
- {
- "type": "effort",
- "values": [
- "none",
- "minimal",
- "low",
- "medium",
- "high",
- "xhigh",
- "max"
- ]
- }
- ],
- "pricing": {
- "input": 0,
- "output": 0,
- "cacheRead": 0,
- "cacheWrite": 0
- },
- "releaseDate": "2026-09-12"
- },
"sakana/fugu-max": {
"id": "sakana/fugu-max",
"name": "Fugu Max (Sakana AI)",
@@ -94981,7 +96689,7 @@ export const GENERATED_PROVIDER_MODELS: {
"pricing": {
"input": 0.1,
"output": 0.25,
- "cacheRead": 0.02,
+ "cacheRead": 0.01,
"cacheWrite": 0
},
"releaseDate": "2026-08-26",
@@ -95057,42 +96765,6 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-08-26",
"family": "glm-flash"
},
- "gonka24/glm-5.3-flash": {
- "id": "gonka24/glm-5.3-flash",
- "name": "GLM-5.3 Flash (Gonka24)",
- "contextWindow": 200000,
- "maxInputTokens": 200000,
- "maxTokens": 16384,
- "capabilities": [
- "tools",
- "reasoning",
- "structured_output",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [
- {
- "type": "effort",
- "values": [
- "none",
- "minimal",
- "low",
- "medium",
- "high",
- "xhigh",
- "max"
- ]
- }
- ],
- "pricing": {
- "input": 0.15,
- "output": 0.3,
- "cacheRead": 0.035,
- "cacheWrite": 0
- },
- "releaseDate": "2026-08-26",
- "family": "glm-flash"
- },
"inference.net/glm-5.3-flash": {
"id": "inference.net/glm-5.3-flash",
"name": "GLM-5.3 Flash (Inference.net)",
@@ -95197,45 +96869,6 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-08-26",
"family": "qwen"
},
- "reka-ai/glm-5.3-flash": {
- "id": "reka-ai/glm-5.3-flash",
- "name": "GLM-5.3 Flash (reka-ai)",
- "contextWindow": 262144,
- "maxInputTokens": 262144,
- "maxTokens": 262144,
- "capabilities": [
- "images",
- "video",
- "files",
- "tools",
- "reasoning",
- "structured_output",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [
- {
- "type": "effort",
- "values": [
- "none",
- "minimal",
- "low",
- "medium",
- "high",
- "xhigh",
- "max"
- ]
- }
- ],
- "pricing": {
- "input": 0.15,
- "output": 0.5,
- "cacheRead": 0.02,
- "cacheWrite": 0
- },
- "releaseDate": "2026-08-26",
- "family": "glm-flash"
- },
"runware/glm-5.3-flash": {
"id": "runware/glm-5.3-flash",
"name": "GLM-5.3 Flash (Runware)",
@@ -95440,6 +97073,40 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-08-14",
"family": "glm"
},
+ "entrim/glm-5.3": {
+ "id": "entrim/glm-5.3",
+ "name": "GLM-5.3 (entrim)",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 131072,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.5,
+ "output": 2,
+ "cacheRead": 0.15,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-08-14",
+ "family": "glm"
+ },
"fireworks/glm-5.3": {
"id": "fireworks/glm-5.3",
"name": "GLM-5.3 (Fireworks AI)",
@@ -95623,44 +97290,6 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-08-14",
"family": "glm"
},
- "reka-ai/qwen3.8-27b": {
- "id": "reka-ai/qwen3.8-27b",
- "name": "Qwen3.8 27B (reka-ai)",
- "contextWindow": 262144,
- "maxInputTokens": 262144,
- "maxTokens": 262144,
- "capabilities": [
- "images",
- "video",
- "tools",
- "reasoning",
- "structured_output",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [
- {
- "type": "effort",
- "values": [
- "none",
- "minimal",
- "low",
- "medium",
- "high",
- "xhigh",
- "max"
- ]
- }
- ],
- "pricing": {
- "input": 0.41,
- "output": 3,
- "cacheRead": 0.085,
- "cacheWrite": 0
- },
- "releaseDate": "2026-08-14",
- "family": "qwen"
- },
"runware/glm-5.3": {
"id": "runware/glm-5.3",
"name": "GLM-5.3 (Runware)",
@@ -98013,7 +99642,7 @@ export const GENERATED_PROVIDER_MODELS: {
],
"reasoningOptions": [],
"pricing": {
- "input": 2.1256,
+ "input": 2.156,
"output": 6.776,
"cacheRead": 0.429,
"cacheWrite": 0
@@ -98438,6 +100067,42 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-06-02",
"family": "qwen"
},
+ "consensusprotocol/minimax-m3": {
+ "id": "consensusprotocol/minimax-m3",
+ "name": "MiniMax M3 (Consensus Protocol)",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 512000,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "minimal",
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.28,
+ "output": 1.1,
+ "cacheRead": 0.05,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-06-01",
+ "family": "minimax"
+ },
"deepinfra/nemotron-3-ultra-550b": {
"id": "deepinfra/nemotron-3-ultra-550b",
"name": "Nemotron 3 Ultra 550B (DeepInfra)",
@@ -99472,8 +101137,8 @@ export const GENERATED_PROVIDER_MODELS: {
"consensusprotocol/deepseek-v4-flash": {
"id": "consensusprotocol/deepseek-v4-flash",
"name": "DeepSeek V4 Flash (Consensus Protocol)",
- "contextWindow": 524288,
- "maxInputTokens": 524288,
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
"maxTokens": 384000,
"capabilities": [
"tools",
@@ -99633,73 +101298,6 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-04-24",
"family": "deepseek-flash"
},
- "fireworks/deepseek-v4-pro": {
- "id": "fireworks/deepseek-v4-pro",
- "name": "DeepSeek V4 Pro (Fireworks AI)",
- "contextWindow": 1048576,
- "maxInputTokens": 1048576,
- "maxTokens": 393216,
- "capabilities": [
- "tools",
- "reasoning",
- "structured_output",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [
- {
- "type": "effort",
- "values": [
- "none",
- "low",
- "medium",
- "high",
- "xhigh",
- "max"
- ]
- }
- ],
- "pricing": {
- "input": 1.32,
- "output": 3.96,
- "cacheRead": 0.044,
- "cacheWrite": 0
- },
- "releaseDate": "2026-04-24",
- "family": "deepseek-thinking"
- },
- "gonka24/deepseek-v4-flash": {
- "id": "gonka24/deepseek-v4-flash",
- "name": "DeepSeek V4 Flash (Gonka24)",
- "contextWindow": 390000,
- "maxInputTokens": 390000,
- "maxTokens": 16384,
- "capabilities": [
- "tools",
- "reasoning",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [
- {
- "type": "effort",
- "values": [
- "none",
- "low",
- "medium",
- "high"
- ]
- }
- ],
- "pricing": {
- "input": 0.065,
- "output": 0.116,
- "cacheRead": 0.012,
- "cacheWrite": 0
- },
- "releaseDate": "2026-04-24",
- "family": "deepseek-flash"
- },
"novita/deepseek-v4-flash": {
"id": "novita/deepseek-v4-flash",
"name": "DeepSeek V4 Flash (NovitaAI)",
@@ -99771,42 +101369,6 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-04-24",
"family": "deepseek-flash"
},
- "reka-ai/deepseek-v4-flash": {
- "id": "reka-ai/deepseek-v4-flash",
- "name": "DeepSeek V4 Flash (reka-ai)",
- "contextWindow": 262144,
- "maxInputTokens": 262144,
- "maxTokens": 131072,
- "capabilities": [
- "tools",
- "reasoning",
- "structured_output",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [
- {
- "type": "effort",
- "values": [
- "none",
- "minimal",
- "low",
- "medium",
- "high",
- "xhigh",
- "max"
- ]
- }
- ],
- "pricing": {
- "input": 0.11,
- "output": 0.66,
- "cacheRead": 0.01,
- "cacheWrite": 0
- },
- "releaseDate": "2026-04-24",
- "family": "deepseek-flash"
- },
"reka-ai/deepseek-v4-pro": {
"id": "reka-ai/deepseek-v4-pro",
"name": "DeepSeek V4 Pro (reka-ai)",
@@ -100254,83 +101816,6 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-04-22",
"family": "mimo"
},
- "xiaomi/mimo-v2.5": {
- "id": "xiaomi/mimo-v2.5",
- "name": "MiMo V2.5 (Xiaomi)",
- "contextWindow": 1000000,
- "maxInputTokens": 1000000,
- "maxTokens": 131072,
- "capabilities": [
- "images",
- "video",
- "tools",
- "reasoning",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [
- {
- "type": "effort",
- "values": [
- "none",
- "low",
- "medium",
- "high"
- ]
- }
- ],
- "pricing": {
- "input": 0.14,
- "output": 0.28,
- "cacheRead": 0.0028,
- "cacheWrite": 0
- },
- "releaseDate": "2026-04-22",
- "family": "mimo",
- "modalities": {
- "input": [
- "text",
- "image",
- "audio",
- "video"
- ],
- "output": [
- "text"
- ]
- }
- },
- "xiaomi/mimo-v2.5-pro": {
- "id": "xiaomi/mimo-v2.5-pro",
- "name": "MiMo V2.5 Pro (Xiaomi)",
- "contextWindow": 1000000,
- "maxInputTokens": 1000000,
- "maxTokens": 131072,
- "capabilities": [
- "tools",
- "reasoning",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [
- {
- "type": "effort",
- "values": [
- "none",
- "low",
- "medium",
- "high"
- ]
- }
- ],
- "pricing": {
- "input": 0.435,
- "output": 0.87,
- "cacheRead": 0.0036,
- "cacheWrite": 0
- },
- "releaseDate": "2026-04-22",
- "family": "mimo"
- },
"baidu/kimi-k2.6": {
"id": "baidu/kimi-k2.6",
"name": "Kimi K2.6 (Baidu)",
@@ -101218,25 +102703,6 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-04-02",
"family": "gemma"
},
- "scx-ai/gemma-4-31b-it": {
- "id": "scx-ai/gemma-4-31b-it",
- "name": "Gemma 4 31B IT (SCX.ai (Turbo))",
- "contextWindow": 131072,
- "maxInputTokens": 131072,
- "maxTokens": 8192,
- "capabilities": [
- "tools",
- "temperature"
- ],
- "pricing": {
- "input": 0.3,
- "output": 0.91,
- "cacheRead": 0,
- "cacheWrite": 0
- },
- "releaseDate": "2026-04-02",
- "family": "gemma"
- },
"tencent/glm-5v-turbo": {
"id": "tencent/glm-5v-turbo",
"name": "GLM-5V Turbo (Tencent Cloud)",
@@ -105907,288 +107373,6 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2025-06-25",
"family": "seed"
},
- "google-ai-studio/gemini-2.5-flash": {
- "id": "google-ai-studio/gemini-2.5-flash",
- "name": "Gemini 2.5 Flash (Google AI Studio)",
- "contextWindow": 1048576,
- "maxInputTokens": 1048576,
- "maxTokens": 65535,
- "capabilities": [
- "images",
- "video",
- "files",
- "tools",
- "reasoning",
- "structured_output",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [
- {
- "type": "budget_tokens",
- "min": 1,
- "max": 24576
- },
- {
- "type": "effort",
- "values": [
- "low",
- "medium",
- "high"
- ]
- }
- ],
- "pricing": {
- "input": 0.3,
- "output": 2.5,
- "cacheRead": 0.03,
- "cacheWrite": 0
- },
- "releaseDate": "2025-06-17",
- "family": "gemini-flash",
- "modalities": {
- "input": [
- "text",
- "image",
- "audio",
- "video",
- "pdf"
- ],
- "output": [
- "text"
- ]
- }
- },
- "google-ai-studio/gemini-2.5-flash-lite": {
- "id": "google-ai-studio/gemini-2.5-flash-lite",
- "name": "Gemini 2.5 Flash Lite (Google AI Studio)",
- "contextWindow": 1048576,
- "maxInputTokens": 1048576,
- "maxTokens": 65535,
- "capabilities": [
- "images",
- "video",
- "files",
- "tools",
- "structured_output",
- "temperature",
- "prompt-cache"
- ],
- "pricing": {
- "input": 0.1,
- "output": 0.4,
- "cacheRead": 0.01,
- "cacheWrite": 0
- },
- "releaseDate": "2025-06-17",
- "family": "gemini-flash-lite",
- "modalities": {
- "input": [
- "text",
- "image",
- "audio",
- "video",
- "pdf"
- ],
- "output": [
- "text"
- ]
- }
- },
- "google-ai-studio/gemini-2.5-pro": {
- "id": "google-ai-studio/gemini-2.5-pro",
- "name": "Gemini 2.5 Pro (Google AI Studio)",
- "contextWindow": 1048576,
- "maxInputTokens": 1048576,
- "maxTokens": 65536,
- "capabilities": [
- "images",
- "video",
- "files",
- "tools",
- "reasoning",
- "structured_output",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [
- {
- "type": "effort",
- "values": [
- "minimal",
- "low",
- "medium",
- "high"
- ]
- },
- {
- "type": "budget_tokens",
- "min": 128,
- "max": 32768
- }
- ],
- "pricing": {
- "input": 1.25,
- "output": 10,
- "cacheRead": 0.125,
- "cacheWrite": 0
- },
- "releaseDate": "2025-06-17",
- "family": "gemini-pro",
- "modalities": {
- "input": [
- "text",
- "image",
- "audio",
- "video",
- "pdf"
- ],
- "output": [
- "text"
- ]
- }
- },
- "google-vertex/gemini-2.5-flash": {
- "id": "google-vertex/gemini-2.5-flash",
- "name": "Gemini 2.5 Flash (Google Vertex AI)",
- "contextWindow": 1048576,
- "maxInputTokens": 1048576,
- "maxTokens": 65535,
- "capabilities": [
- "images",
- "video",
- "files",
- "tools",
- "reasoning",
- "structured_output",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [
- {
- "type": "budget_tokens",
- "min": 1,
- "max": 24576
- },
- {
- "type": "effort",
- "values": [
- "low",
- "medium",
- "high"
- ]
- }
- ],
- "pricing": {
- "input": 0.3,
- "output": 2.5,
- "cacheRead": 0.03,
- "cacheWrite": 0
- },
- "releaseDate": "2025-06-17",
- "family": "gemini-flash",
- "modalities": {
- "input": [
- "text",
- "image",
- "audio",
- "video",
- "pdf"
- ],
- "output": [
- "text"
- ]
- }
- },
- "google-vertex/gemini-2.5-flash-lite": {
- "id": "google-vertex/gemini-2.5-flash-lite",
- "name": "Gemini 2.5 Flash Lite (Google Vertex AI)",
- "contextWindow": 1048576,
- "maxInputTokens": 1048576,
- "maxTokens": 65535,
- "capabilities": [
- "images",
- "video",
- "files",
- "tools",
- "structured_output",
- "temperature",
- "prompt-cache"
- ],
- "pricing": {
- "input": 0.1,
- "output": 0.4,
- "cacheRead": 0.01,
- "cacheWrite": 0
- },
- "releaseDate": "2025-06-17",
- "family": "gemini-flash-lite",
- "modalities": {
- "input": [
- "text",
- "image",
- "audio",
- "video",
- "pdf"
- ],
- "output": [
- "text"
- ]
- }
- },
- "google-vertex/gemini-2.5-pro": {
- "id": "google-vertex/gemini-2.5-pro",
- "name": "Gemini 2.5 Pro (Google Vertex AI)",
- "contextWindow": 1048576,
- "maxInputTokens": 1048576,
- "maxTokens": 65536,
- "capabilities": [
- "images",
- "video",
- "files",
- "tools",
- "reasoning",
- "structured_output",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [
- {
- "type": "effort",
- "values": [
- "minimal",
- "low",
- "medium",
- "high"
- ]
- },
- {
- "type": "budget_tokens",
- "min": 128,
- "max": 32768
- }
- ],
- "pricing": {
- "input": 1.25,
- "output": 10,
- "cacheRead": 0.125,
- "cacheWrite": 0
- },
- "releaseDate": "2025-06-17",
- "family": "gemini-pro",
- "modalities": {
- "input": [
- "text",
- "image",
- "audio",
- "video",
- "pdf"
- ],
- "output": [
- "text"
- ]
- }
- },
"openai/o4-mini": {
"id": "openai/o4-mini",
"name": "o4 Mini (OpenAI)",
@@ -106267,28 +107451,6 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2025-04-14",
"family": "gpt-mini"
},
- "azure/gpt-4.1-nano": {
- "id": "azure/gpt-4.1-nano",
- "name": "GPT-4.1 Nano (Azure)",
- "contextWindow": 1000000,
- "maxInputTokens": 1000000,
- "maxTokens": 32768,
- "capabilities": [
- "images",
- "tools",
- "structured_output",
- "temperature",
- "prompt-cache"
- ],
- "pricing": {
- "input": 0.1,
- "output": 0.4,
- "cacheRead": 0.025,
- "cacheWrite": 0
- },
- "releaseDate": "2025-04-14",
- "family": "gpt-nano"
- },
"openai/gpt-4.1": {
"id": "openai/gpt-4.1",
"name": "GPT-4.1 (OpenAI)",
@@ -106376,25 +107538,6 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2025-04-14",
"family": "glm"
},
- "scx-ai/llama-4-maverick-17b-instruct": {
- "id": "scx-ai/llama-4-maverick-17b-instruct",
- "name": "Llama 4 Maverick 17B Instruct (SCX.ai (Turbo))",
- "contextWindow": 131072,
- "maxInputTokens": 131072,
- "maxTokens": 8192,
- "capabilities": [
- "tools",
- "temperature"
- ],
- "pricing": {
- "input": 0.53,
- "output": 1.62,
- "cacheRead": 0,
- "cacheWrite": 0
- },
- "releaseDate": "2025-04-05",
- "family": "llama"
- },
"novita/qwen3-coder-30b-a3b-instruct": {
"id": "novita/qwen3-coder-30b-a3b-instruct",
"name": "Qwen3 Coder 30B A3B Instruct (NovitaAI)",
@@ -107702,6 +108845,249 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-10-06",
"family": "mistral-large"
},
+ "auto/openai/gpt-6.1-sol": {
+ "id": "auto/openai/gpt-6.1-sol",
+ "name": "GPT-6.1 Sol",
+ "contextWindow": 1050000,
+ "maxInputTokens": 922000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 10,
+ "cacheRead": 0.1,
+ "cacheWrite": 2.5
+ },
+ "releaseDate": "2026-09-29",
+ "family": "gpt-sol"
+ },
+ "auto/openai/gpt-6-luna": {
+ "id": "auto/openai/gpt-6-luna",
+ "name": "GPT-6 Luna",
+ "contextWindow": 1050000,
+ "maxInputTokens": 922000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.1,
+ "output": 0.5,
+ "cacheRead": 0.01,
+ "cacheWrite": 0.125
+ },
+ "releaseDate": "2026-09-22",
+ "family": "gpt-luna"
+ },
+ "auto/openai/gpt-6-sol": {
+ "id": "auto/openai/gpt-6-sol",
+ "name": "GPT-6 Sol",
+ "contextWindow": 1050000,
+ "maxInputTokens": 922000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 10,
+ "cacheRead": 0.2,
+ "cacheWrite": 2.5
+ },
+ "releaseDate": "2026-09-22",
+ "family": "gpt-sol"
+ },
+ "auto/openai/gpt-6-astra": {
+ "id": "auto/openai/gpt-6-astra",
+ "name": "GPT-6 Astra",
+ "contextWindow": 1050000,
+ "maxInputTokens": 922000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 10,
+ "output": 50,
+ "cacheRead": 1,
+ "cacheWrite": 12.5
+ },
+ "releaseDate": "2026-09-04",
+ "family": "gpt-astra"
+ },
+ "auto/openai/gpt-5.6-luna": {
+ "id": "auto/openai/gpt-5.6-luna",
+ "name": "GPT-5.6 Luna",
+ "contextWindow": 1050000,
+ "maxInputTokens": 922000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.2,
+ "output": 1.2,
+ "cacheRead": 0.02,
+ "cacheWrite": 0.25
+ },
+ "releaseDate": "2026-07-09",
+ "family": "gpt-luna"
+ },
+ "auto/openai/gpt-5.6-sol": {
+ "id": "auto/openai/gpt-5.6-sol",
+ "name": "GPT-5.6 Sol",
+ "contextWindow": 1050000,
+ "maxInputTokens": 922000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 4,
+ "output": 20,
+ "cacheRead": 0.4,
+ "cacheWrite": 5
+ },
+ "releaseDate": "2026-07-09",
+ "family": "gpt-sol"
+ },
+ "auto/openai/gpt-5.6-terra": {
+ "id": "auto/openai/gpt-5.6-terra",
+ "name": "GPT-5.6 Terra",
+ "contextWindow": 1050000,
+ "maxInputTokens": 922000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 12,
+ "cacheRead": 0.2,
+ "cacheWrite": 2.5
+ },
+ "releaseDate": "2026-07-09",
+ "family": "gpt-terra"
+ },
"auto/mistralai/mistral-medium-3.5": {
"id": "auto/mistralai/mistral-medium-3.5",
"name": "Mistral Medium 3.5",
@@ -107734,6 +109120,76 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-04-29",
"family": "mistral-medium"
},
+ "auto/openai/gpt-5.5": {
+ "id": "auto/openai/gpt-5.5",
+ "name": "GPT-5.5",
+ "contextWindow": 1050000,
+ "maxInputTokens": 922000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 5,
+ "output": 30,
+ "cacheRead": 0.5,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-04-23",
+ "family": "gpt"
+ },
+ "auto/openai/gpt-5.4-mini": {
+ "id": "auto/openai/gpt-5.4-mini",
+ "name": "GPT-5.4 mini",
+ "contextWindow": 400000,
+ "maxInputTokens": 272000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.75,
+ "output": 4.5,
+ "cacheRead": 0.075,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-03-17",
+ "family": "gpt-mini"
+ },
"auto/mistralai/mistral-small-2603": {
"id": "auto/mistralai/mistral-small-2603",
"name": "Mistral Small 4",
@@ -107765,6 +109221,77 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-03-16",
"family": "mistral-small"
},
+ "auto/openai/gpt-5.4": {
+ "id": "auto/openai/gpt-5.4",
+ "name": "GPT-5.4",
+ "contextWindow": 1050000,
+ "maxInputTokens": 922000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2.5,
+ "output": 15,
+ "cacheRead": 0.25,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-03-05",
+ "family": "gpt"
+ },
+ "auto/openai/gpt-5.2": {
+ "id": "auto/openai/gpt-5.2",
+ "name": "GPT-5.2",
+ "contextWindow": 400000,
+ "maxInputTokens": 272000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1.75,
+ "output": 14,
+ "cacheRead": 0.175,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2025-12-11",
+ "family": "gpt"
+ },
"auto/mistralai/ministral-14b-2512": {
"id": "auto/mistralai/ministral-14b-2512",
"name": "Ministral 3 14B",
@@ -107896,6 +109423,105 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2025-10-29",
"family": "gpt-oss"
},
+ "auto/openai/gpt-5": {
+ "id": "auto/openai/gpt-5",
+ "name": "GPT-5",
+ "contextWindow": 400000,
+ "maxInputTokens": 272000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "minimal",
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1.25,
+ "output": 10,
+ "cacheRead": 0.125,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2025-08-07",
+ "family": "gpt"
+ },
+ "auto/openai/gpt-5-mini": {
+ "id": "auto/openai/gpt-5-mini",
+ "name": "GPT-5 Mini",
+ "contextWindow": 400000,
+ "maxInputTokens": 272000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "minimal",
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.25,
+ "output": 2,
+ "cacheRead": 0.025,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2025-08-07",
+ "family": "gpt-mini"
+ },
+ "auto/openai/gpt-5-nano": {
+ "id": "auto/openai/gpt-5-nano",
+ "name": "GPT-5 Nano",
+ "contextWindow": 400000,
+ "maxInputTokens": 272000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "minimal",
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.05,
+ "output": 0.4,
+ "cacheRead": 0.005,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2025-08-07",
+ "family": "gpt-nano"
+ },
"auto/openai/gpt-oss-120b": {
"id": "auto/openai/gpt-oss-120b",
"name": "GPT OSS 120B",
@@ -107978,6 +109604,131 @@ export const GENERATED_PROVIDER_MODELS: {
},
"releaseDate": "2025-07-30",
"family": "codestral"
+ },
+ "auto/openai/o3": {
+ "id": "auto/openai/o3",
+ "name": "o3",
+ "contextWindow": 200000,
+ "maxInputTokens": 200000,
+ "maxTokens": 100000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 8,
+ "cacheRead": 0.5,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2025-04-16",
+ "family": "o"
+ },
+ "auto/openai/gpt-4.1": {
+ "id": "auto/openai/gpt-4.1",
+ "name": "GPT-4.1",
+ "contextWindow": 1047576,
+ "maxInputTokens": 1047576,
+ "maxTokens": 32768,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 8,
+ "cacheRead": 0.5,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2025-04-14",
+ "family": "gpt"
+ },
+ "auto/openai/gpt-4.1-mini": {
+ "id": "auto/openai/gpt-4.1-mini",
+ "name": "GPT-4.1 mini",
+ "contextWindow": 1047576,
+ "maxInputTokens": 1047576,
+ "maxTokens": 32768,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "pricing": {
+ "input": 0.4,
+ "output": 1.6,
+ "cacheRead": 0.1,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2025-04-14",
+ "family": "gpt-mini"
+ },
+ "auto/openai/gpt-4o-mini": {
+ "id": "auto/openai/gpt-4o-mini",
+ "name": "GPT-4o mini",
+ "contextWindow": 128000,
+ "maxInputTokens": 128000,
+ "maxTokens": 16384,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "pricing": {
+ "input": 0.15,
+ "output": 0.6,
+ "cacheRead": 0.075,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2024-07-18",
+ "family": "gpt-mini"
+ },
+ "auto/openai/gpt-4o": {
+ "id": "auto/openai/gpt-4o",
+ "name": "GPT-4o",
+ "contextWindow": 128000,
+ "maxInputTokens": 128000,
+ "maxTokens": 16384,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "pricing": {
+ "input": 2.5,
+ "output": 10,
+ "cacheRead": 1.25,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2024-05-13",
+ "family": "gpt"
}
},
"lucidquery": {
@@ -108834,7 +110585,8 @@ export const GENERATED_PROVIDER_MODELS: {
"tools",
"reasoning",
"structured_output",
- "temperature"
+ "temperature",
+ "prompt-cache"
],
"reasoningOptions": [
{
@@ -108850,9 +110602,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0,
- "output": 0,
- "cacheRead": 0,
+ "input": 4,
+ "output": 20,
+ "cacheRead": 0.2,
"cacheWrite": 0
},
"releaseDate": "2026-10-12",
@@ -112139,6 +113891,127 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"nano-gpt": {
+ "nvidia/nemotron-3.5-super-vl": {
+ "id": "nvidia/nemotron-3.5-super-vl",
+ "name": "Nvidia Nemotron 3.5 Super VL",
+ "contextWindow": 262144,
+ "maxInputTokens": 262144,
+ "maxTokens": 16384,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.15,
+ "output": 0.5,
+ "cacheRead": 0.02,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-15",
+ "family": "nemotron"
+ },
+ "reka/reka-edge-2603": {
+ "id": "reka/reka-edge-2603",
+ "name": "Reka Edge 2603",
+ "contextWindow": 16384,
+ "maxInputTokens": 16384,
+ "maxTokens": 16384,
+ "capabilities": [
+ "images",
+ "tools",
+ "structured_output"
+ ],
+ "pricing": {
+ "input": 0.105,
+ "output": 0.105,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-15",
+ "family": "reka"
+ },
+ "liquid/lfm-2.5-24b-a2b": {
+ "id": "liquid/lfm-2.5-24b-a2b",
+ "name": "LFM2.5 24B A2B",
+ "contextWindow": 128000,
+ "maxInputTokens": 128000,
+ "maxTokens": 8192,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [],
+ "pricing": {
+ "input": 0.05,
+ "output": 0.7,
+ "cacheRead": 0.025,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-14",
+ "family": "liquid"
+ },
+ "google/gemini-4-argon": {
+ "id": "google/gemini-4-argon",
+ "name": "Gemini 4 Argon",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 10,
+ "cacheRead": 0.1,
+ "cacheWrite": 0.1875
+ },
+ "releaseDate": "2026-10-13",
+ "family": "gemini",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio",
+ "pdf"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
"gemma-4-26b-a4b-it-chimeraxheretic": {
"id": "gemma-4-26b-a4b-it-chimeraxheretic",
"name": "Gemma 4 26B A4B Chimera X Heretic",
@@ -112494,6 +114367,7 @@ export const GENERATED_PROVIDER_MODELS: {
"capabilities": [
"tools",
"reasoning",
+ "structured_output",
"prompt-cache"
],
"reasoningOptions": [
@@ -113470,6 +115344,25 @@ export const GENERATED_PROVIDER_MODELS: {
},
"releaseDate": "2026-09-18"
},
+ "unbiased/pareto-26.9": {
+ "id": "unbiased/pareto-26.9",
+ "name": "Pareto 26.9",
+ "contextWindow": 262144,
+ "maxInputTokens": 262144,
+ "maxTokens": 131072,
+ "capabilities": [
+ "images",
+ "tools",
+ "prompt-cache"
+ ],
+ "pricing": {
+ "input": 2.5,
+ "output": 7.5,
+ "cacheRead": 0.25,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-09-18"
+ },
"google/gemma4-31b-splituntied": {
"id": "google/gemma4-31b-splituntied",
"name": "Gemma 4 31B Split-Untied",
@@ -113532,26 +115425,6 @@ export const GENERATED_PROVIDER_MODELS: {
]
}
},
- "unbiased/pareto": {
- "id": "unbiased/pareto",
- "name": "Pareto",
- "contextWindow": 262144,
- "maxInputTokens": 262144,
- "maxTokens": 131072,
- "capabilities": [
- "images",
- "tools",
- "temperature",
- "prompt-cache"
- ],
- "pricing": {
- "input": 2.5,
- "output": 7.5,
- "cacheRead": 0.25,
- "cacheWrite": 0
- },
- "releaseDate": "2026-09-17"
- },
"stepfun/step-5-preview": {
"id": "stepfun/step-5-preview",
"name": "Step 5 Preview",
@@ -114916,9 +116789,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.48,
- "output": 1.98,
- "cacheRead": 0.1,
+ "input": 1.1,
+ "output": 2.5,
+ "cacheRead": 0.04,
"cacheWrite": 0
},
"releaseDate": "2026-08-12",
@@ -114949,9 +116822,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.48,
- "output": 1.98,
- "cacheRead": 0.1,
+ "input": 1.1,
+ "output": 2.5,
+ "cacheRead": 0.04,
"cacheWrite": 0
},
"releaseDate": "2026-08-12",
@@ -116070,8 +117943,8 @@ export const GENERATED_PROVIDER_MODELS: {
"reasoningOptions": [],
"pricing": {
"input": 0.25,
- "output": 1.5,
- "cacheRead": 0.2,
+ "output": 1.75,
+ "cacheRead": 0.225,
"cacheWrite": 0
},
"releaseDate": "2026-07-29",
@@ -116093,8 +117966,8 @@ export const GENERATED_PROVIDER_MODELS: {
"reasoningOptions": [],
"pricing": {
"input": 0.25,
- "output": 1.5,
- "cacheRead": 0.2,
+ "output": 1.75,
+ "cacheRead": 0.225,
"cacheWrite": 0
},
"releaseDate": "2026-07-29",
@@ -117412,7 +119285,6 @@ export const GENERATED_PROVIDER_MODELS: {
"maxTokens": 32768,
"capabilities": [
"images",
- "video",
"tools",
"structured_output",
"temperature",
@@ -117425,18 +119297,7 @@ export const GENERATED_PROVIDER_MODELS: {
"cacheWrite": 0
},
"releaseDate": "2026-06-09",
- "family": "gemma",
- "modalities": {
- "input": [
- "text",
- "image",
- "video",
- "audio"
- ],
- "output": [
- "text"
- ]
- }
+ "family": "gemma"
},
"nvidia/nemotron-3-ultra-550b-a55b": {
"id": "nvidia/nemotron-3-ultra-550b-a55b",
@@ -118222,9 +120083,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.48,
- "output": 1.98,
- "cacheRead": 0.1,
+ "input": 1.1,
+ "output": 2.5,
+ "cacheRead": 0.04,
"cacheWrite": 0
},
"releaseDate": "2026-05-03",
@@ -119114,9 +120975,9 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"pricing": {
- "input": 0.441,
- "output": 2.45,
- "cacheRead": 0.0878,
+ "input": 0.5,
+ "output": 2.6,
+ "cacheRead": 0.125,
"cacheWrite": 0
},
"releaseDate": "2026-04-21",
@@ -119137,9 +120998,9 @@ export const GENERATED_PROVIDER_MODELS: {
],
"reasoningOptions": [],
"pricing": {
- "input": 0.441,
- "output": 2.45,
- "cacheRead": 0.0878,
+ "input": 0.5,
+ "output": 2.6,
+ "cacheRead": 0.125,
"cacheWrite": 0
},
"releaseDate": "2026-04-21",
@@ -121521,9 +123382,9 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"pricing": {
- "input": 0.28,
- "output": 0.42,
- "cacheRead": 0.14,
+ "input": 0.2088,
+ "output": 0.3096,
+ "cacheRead": 0.0216,
"cacheWrite": 0
},
"releaseDate": "2025-12-01",
@@ -121545,9 +123406,9 @@ export const GENERATED_PROVIDER_MODELS: {
],
"reasoningOptions": [],
"pricing": {
- "input": 0.28,
- "output": 0.42,
- "cacheRead": 0.14,
+ "input": 0.2088,
+ "output": 0.3096,
+ "cacheRead": 0.0216,
"cacheWrite": 0
},
"releaseDate": "2025-12-01",
@@ -123967,9 +125828,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.15,
+ "input": 0.08,
"output": 0.5,
- "cacheRead": 0.035,
+ "cacheRead": 0.012,
"cacheWrite": 0
},
"releaseDate": "2026-08-26",
@@ -125228,6 +127089,74 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"nebius": {
+ "meta-models/muse-spark-open": {
+ "id": "meta-models/muse-spark-open",
+ "name": "Muse Spark Open",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 1048576,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1.25,
+ "output": 4.25,
+ "cacheRead": 1.25,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-15",
+ "family": "muse"
+ },
+ "nvidia/Nemotron-3.5-Super-VL": {
+ "id": "nvidia/Nemotron-3.5-Super-VL",
+ "name": "Nemotron 3.5 Super VL 120B A12B",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 1048576,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.3,
+ "output": 0.9,
+ "cacheRead": 0.3,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-15",
+ "family": "nemotron"
+ },
"deepseek-ai/DeepSeek-V4.1-Flash": {
"id": "deepseek-ai/DeepSeek-V4.1-Flash",
"name": "DeepSeek V4.1 Flash",
@@ -125788,6 +127717,109 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"neon": {
+ "claude-haiku-5-5": {
+ "id": "claude-haiku-5-5",
+ "name": "Claude Haiku 5.5",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "toggle"
+ },
+ {
+ "type": "budget_tokens",
+ "min": 1024,
+ "max": 63999
+ }
+ ],
+ "pricing": {
+ "input": 0.1,
+ "output": 0.5,
+ "cacheRead": 0.01,
+ "cacheWrite": 0.125
+ },
+ "releaseDate": "2026-10-07",
+ "family": "claude-haiku"
+ },
+ "gpt-6-1-sol": {
+ "id": "gpt-6-1-sol",
+ "name": "GPT-6.1 Sol",
+ "contextWindow": 1050000,
+ "maxInputTokens": 922000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 10,
+ "cacheRead": 0.1,
+ "cacheWrite": 2.5
+ },
+ "releaseDate": "2026-09-29",
+ "family": "gpt-sol",
+ "metadata": {
+ "apiProtocol": "openai-responses"
+ }
+ },
+ "claude-sonnet-5-5": {
+ "id": "claude-sonnet-5-5",
+ "name": "Claude Sonnet 5.5",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 10,
+ "cacheRead": 0.2,
+ "cacheWrite": 2.5
+ },
+ "releaseDate": "2026-09-28",
+ "family": "claude-sonnet"
+ },
"claude-opus-5-5": {
"id": "claude-opus-5-5",
"name": "Claude Opus 5.5",
@@ -125822,6 +127854,199 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-09-22",
"family": "claude-opus"
},
+ "gpt-6-luna": {
+ "id": "gpt-6-luna",
+ "name": "GPT-6 Luna",
+ "contextWindow": 1050000,
+ "maxInputTokens": 922000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.1,
+ "output": 0.5,
+ "cacheRead": 0.01,
+ "cacheWrite": 0.125
+ },
+ "releaseDate": "2026-09-22",
+ "family": "gpt-luna",
+ "metadata": {
+ "apiProtocol": "openai-responses"
+ }
+ },
+ "gpt-6-sol": {
+ "id": "gpt-6-sol",
+ "name": "GPT-6 Sol",
+ "contextWindow": 1050000,
+ "maxInputTokens": 922000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 10,
+ "cacheRead": 0.2,
+ "cacheWrite": 2.5
+ },
+ "releaseDate": "2026-09-22",
+ "family": "gpt-sol",
+ "metadata": {
+ "apiProtocol": "openai-responses"
+ }
+ },
+ "grok-4-7": {
+ "id": "grok-4-7",
+ "name": "Grok 4.7",
+ "contextWindow": 500000,
+ "maxInputTokens": 500000,
+ "maxTokens": 500000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2.5,
+ "output": 7.5,
+ "cacheRead": 0.5,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-09-21",
+ "family": "grok",
+ "metadata": {
+ "apiProtocol": "openai-responses"
+ }
+ },
+ "deepseek-v4-1-flash": {
+ "id": "deepseek-v4-1-flash",
+ "name": "DeepSeek V4.1 Flash",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 384000,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "high",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.3,
+ "output": 1.2,
+ "cacheRead": 0.03,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-09-10",
+ "family": "deepseek-flash"
+ },
+ "gemini-3-8-flash": {
+ "id": "gemini-3-8-flash",
+ "name": "Gemini 3.8 Flash",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1.5,
+ "output": 7.5,
+ "cacheRead": 0.15,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-09-02",
+ "family": "gemini-flash",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio",
+ "pdf"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
"claude-fable-5-1": {
"id": "claude-fable-5-1",
"name": "Claude Fable 5.1",
@@ -125891,6 +128116,84 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-08-26",
"family": "glm-flash"
},
+ "glm-5-3": {
+ "id": "glm-5-3",
+ "name": "GLM-5.3",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 131072,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "high",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1.4,
+ "output": 4.4,
+ "cacheRead": 0.26,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-08-14",
+ "family": "glm"
+ },
+ "gemini-3-7-flash": {
+ "id": "gemini-3-7-flash",
+ "name": "Gemini 3.7 Flash",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1.5,
+ "output": 7.5,
+ "cacheRead": 0.15,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-08-13",
+ "family": "gemini-flash",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio",
+ "pdf"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
"grok-4-6": {
"id": "grok-4-6",
"name": "Grok 4.6",
@@ -127853,7 +130156,8 @@ export const GENERATED_PROVIDER_MODELS: {
"maxTokens": 262144,
"capabilities": [
"tools",
- "reasoning"
+ "reasoning",
+ "prompt-cache"
],
"reasoningOptions": [
{
@@ -127861,9 +130165,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0,
- "output": 0,
- "cacheRead": 0,
+ "input": 0.3,
+ "output": 0.9,
+ "cacheRead": 0.06,
"cacheWrite": 0
},
"releaseDate": "2026-09-29",
@@ -127949,6 +130253,38 @@ export const GENERATED_PROVIDER_MODELS: {
]
}
},
+ "stepfun/step-5-preview": {
+ "id": "stepfun/step-5-preview",
+ "name": "Step 5 Preview",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 64000,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1,
+ "output": 2.7,
+ "cacheRead": 0.1,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-09-16"
+ },
"deepseek/deepseek-v4.1-flash": {
"id": "deepseek/deepseek-v4.1-flash",
"name": "DeepSeek V4.1 Flash",
@@ -129850,6 +132186,33 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"nvidia": {
+ "nvidia/nemotron-3.5-super-vl-120b-a12b": {
+ "id": "nvidia/nemotron-3.5-super-vl-120b-a12b",
+ "name": "Nemotron 3.5 Super VL 120B A12B",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 8192,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "temperature"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "toggle"
+ }
+ ],
+ "pricing": {
+ "input": 0,
+ "output": 0,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-15",
+ "family": "nemotron"
+ },
"deepseek-ai/deepseek-v4.1-flash": {
"id": "deepseek-ai/deepseek-v4.1-flash",
"name": "DeepSeek V4.1 Flash",
@@ -130226,31 +132589,6 @@ export const GENERATED_PROVIDER_MODELS: {
]
}
},
- "nvidia/nemotron-3-super-120b-a12b": {
- "id": "nvidia/nemotron-3-super-120b-a12b",
- "name": "Nemotron 3 Super",
- "contextWindow": 262144,
- "maxInputTokens": 262144,
- "maxTokens": 262144,
- "capabilities": [
- "tools",
- "reasoning",
- "temperature"
- ],
- "reasoningOptions": [
- {
- "type": "toggle"
- }
- ],
- "pricing": {
- "input": 0.2,
- "output": 0.8,
- "cacheRead": 0,
- "cacheWrite": 0
- },
- "releaseDate": "2026-03-11",
- "family": "nemotron"
- },
"nvidia/cosmos-reason2-8b": {
"id": "nvidia/cosmos-reason2-8b",
"name": "Cosmos Reason2 8B",
@@ -130627,6 +132965,55 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"ofox": {
+ "google/gemini-4-argon": {
+ "id": "google/gemini-4-argon",
+ "name": "Gemini 4 Argon",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 10,
+ "cacheRead": 0.1,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-13",
+ "family": "gemini",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio",
+ "pdf"
+ ],
+ "output": [
+ "text"
+ ]
+ },
+ "metadata": {
+ "apiProtocol": "gemini"
+ }
+ },
"anthropic/claude-haiku-5.5": {
"id": "anthropic/claude-haiku-5.5",
"name": "Claude Haiku 5.5",
@@ -135513,6 +137900,40 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"ollama": {
+ "muse-spark-open": {
+ "id": "muse-spark-open",
+ "name": "Muse Spark Open",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 131072,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1.25,
+ "output": 4.25,
+ "cacheRead": 0.15,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-15",
+ "family": "muse"
+ },
"mistral-large-4": {
"id": "mistral-large-4",
"name": "Mistral Large 4",
@@ -137413,11 +139834,94 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"opencode": {
+ "nemotron-3.5-super-vl-free": {
+ "id": "nemotron-3.5-super-vl-free",
+ "name": "Nemotron 3.5 Super VL Free",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 131072,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "temperature"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "minimal",
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0,
+ "output": 0,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-15",
+ "family": "nemotron-free"
+ },
+ "gemini-4-argon": {
+ "id": "gemini-4-argon",
+ "name": "Gemini 4 Argon",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 10,
+ "cacheRead": 0.1,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-13",
+ "family": "gemini",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio",
+ "pdf"
+ ],
+ "output": [
+ "text"
+ ]
+ },
+ "metadata": {
+ "apiProtocol": "gemini"
+ }
+ },
"cat-jam-free": {
"id": "cat-jam-free",
"name": "Cat Jam Free",
- "contextWindow": 262144,
- "maxInputTokens": 262144,
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
"maxTokens": 131072,
"capabilities": [
"tools",
@@ -137486,33 +139990,6 @@ export const GENERATED_PROVIDER_MODELS: {
"apiProtocol": "anthropic"
}
},
- "exo-free": {
- "id": "exo-free",
- "name": "Exo Free",
- "contextWindow": 1048576,
- "maxInputTokens": 1048576,
- "maxTokens": 131072,
- "capabilities": [
- "images",
- "tools",
- "reasoning"
- ],
- "reasoningOptions": [
- {
- "type": "effort",
- "values": [
- "high"
- ]
- }
- ],
- "pricing": {
- "input": 0,
- "output": 0,
- "cacheRead": 0,
- "cacheWrite": 0
- },
- "releaseDate": "2026-10-06"
- },
"mistral-large-4": {
"id": "mistral-large-4",
"name": "Mistral Large 4",
@@ -137583,31 +140060,6 @@ export const GENERATED_PROVIDER_MODELS: {
"apiProtocol": "openai-responses"
}
},
- "ling-3.1-flash-free": {
- "id": "ling-3.1-flash-free",
- "name": "Ling 3.1 Flash Free",
- "contextWindow": 262144,
- "maxInputTokens": 262144,
- "maxTokens": 32768,
- "capabilities": [
- "tools",
- "reasoning",
- "temperature"
- ],
- "reasoningOptions": [
- {
- "type": "toggle"
- }
- ],
- "pricing": {
- "input": 0,
- "output": 0,
- "cacheRead": 0,
- "cacheWrite": 0
- },
- "releaseDate": "2026-09-29",
- "family": "ling"
- },
"claude-sonnet-5-5": {
"id": "claude-sonnet-5-5",
"name": "Claude Sonnet 5.5",
@@ -137890,37 +140342,6 @@ export const GENERATED_PROVIDER_MODELS: {
"apiProtocol": "openai-responses"
}
},
- "step-5-preview-free": {
- "id": "step-5-preview-free",
- "name": "Step 5 Preview Free",
- "contextWindow": 1000000,
- "maxInputTokens": 1000000,
- "maxTokens": 65536,
- "capabilities": [
- "images",
- "video",
- "tools",
- "reasoning",
- "structured_output"
- ],
- "reasoningOptions": [
- {
- "type": "effort",
- "values": [
- "low",
- "medium",
- "high"
- ]
- }
- ],
- "pricing": {
- "input": 0,
- "output": 0,
- "cacheRead": 0,
- "cacheWrite": 0
- },
- "releaseDate": "2026-09-16"
- },
"deepseek-v4.1-flash": {
"id": "deepseek-v4.1-flash",
"name": "DeepSeek V4.1 Flash",
@@ -137954,6 +140375,38 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-09-10",
"family": "deepseek-flash"
},
+ "deepseek-v4.1-flash-free": {
+ "id": "deepseek-v4.1-flash-free",
+ "name": "DeepSeek V4.1 Flash Free",
+ "contextWindow": 200000,
+ "maxInputTokens": 200000,
+ "maxTokens": 32000,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "high",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0,
+ "output": 0,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-09-10",
+ "family": "deepseek-flash"
+ },
"gpt-6-astra": {
"id": "gpt-6-astra",
"name": "GPT-6 Astra",
@@ -138182,31 +140635,6 @@ export const GENERATED_PROVIDER_MODELS: {
"apiProtocol": "anthropic"
}
},
- "ling-3.0-flash-fin-free": {
- "id": "ling-3.0-flash-fin-free",
- "name": "Ling 3.0 Flash Fin Free",
- "contextWindow": 262144,
- "maxInputTokens": 262144,
- "maxTokens": 32768,
- "capabilities": [
- "tools",
- "reasoning",
- "temperature"
- ],
- "reasoningOptions": [
- {
- "type": "toggle"
- }
- ],
- "pricing": {
- "input": 0,
- "output": 0,
- "cacheRead": 0,
- "cacheWrite": 0
- },
- "releaseDate": "2026-08-27",
- "family": "ling"
- },
"glm-5.3-flash": {
"id": "glm-5.3-flash",
"name": "GLM-5.3-Flash",
@@ -140444,6 +142872,87 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"opencode-go": {
+ "gemini-4-argon-contributor": {
+ "id": "gemini-4-argon-contributor",
+ "name": "Gemini 4 Argon Contributor",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 4,
+ "output": 20,
+ "cacheRead": 0.2,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-13",
+ "family": "gemini",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio",
+ "pdf"
+ ],
+ "output": [
+ "text"
+ ]
+ },
+ "metadata": {
+ "apiProtocol": "gemini"
+ }
+ },
+ "cat-jam-free": {
+ "id": "cat-jam-free",
+ "name": "Cat Jam Free",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 131072,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0,
+ "output": 0,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-12"
+ },
"claude-haiku-5-5": {
"id": "claude-haiku-5-5",
"name": "Claude Haiku 5.5",
@@ -140691,9 +143200,9 @@ export const GENERATED_PROVIDER_MODELS: {
"apiProtocol": "openai-responses"
}
},
- "step-5-preview-free": {
- "id": "step-5-preview-free",
- "name": "Step 5 Preview Free",
+ "step-5-preview": {
+ "id": "step-5-preview",
+ "name": "Step 5 Preview",
"contextWindow": 1000000,
"maxInputTokens": 1000000,
"maxTokens": 65536,
@@ -140702,7 +143211,8 @@ export const GENERATED_PROVIDER_MODELS: {
"video",
"tools",
"reasoning",
- "structured_output"
+ "structured_output",
+ "prompt-cache"
],
"reasoningOptions": [
{
@@ -140715,9 +143225,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0,
- "output": 0,
- "cacheRead": 0,
+ "input": 1,
+ "output": 2.7,
+ "cacheRead": 0.1,
"cacheWrite": 0
},
"releaseDate": "2026-09-16"
@@ -140915,42 +143425,6 @@ export const GENERATED_PROVIDER_MODELS: {
"apiProtocol": "anthropic"
}
},
- "deepseek-v4-flash-vision-exp": {
- "id": "deepseek-v4-flash-vision-exp",
- "name": "DeepSeek V4 Flash Vision Exp",
- "contextWindow": 1000000,
- "maxInputTokens": 1000000,
- "maxTokens": 384000,
- "capabilities": [
- "images",
- "tools",
- "reasoning",
- "structured_output",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [
- {
- "type": "toggle"
- },
- {
- "type": "effort",
- "values": [
- "low",
- "high",
- "max"
- ]
- }
- ],
- "pricing": {
- "input": 0.15,
- "output": 0.6,
- "cacheRead": 0.003,
- "cacheWrite": 0
- },
- "releaseDate": "2026-08-21",
- "family": "deepseek-flash"
- },
"glm-5.3": {
"id": "glm-5.3",
"name": "GLM-5.3",
@@ -140983,43 +143457,6 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-08-14",
"family": "glm"
},
- "grok-4.6": {
- "id": "grok-4.6",
- "name": "Grok 4.6",
- "contextWindow": 500000,
- "maxInputTokens": 500000,
- "maxTokens": 500000,
- "capabilities": [
- "images",
- "tools",
- "reasoning",
- "structured_output",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [
- {
- "type": "effort",
- "values": [
- "low",
- "medium",
- "high",
- "xhigh"
- ]
- }
- ],
- "pricing": {
- "input": 2,
- "output": 6,
- "cacheRead": 0.5,
- "cacheWrite": 0
- },
- "releaseDate": "2026-08-12",
- "family": "grok",
- "metadata": {
- "apiProtocol": "openai-responses"
- }
- },
"muse-spark-1.2-contributor": {
"id": "muse-spark-1.2-contributor",
"name": "Muse Spark 1.2 Contributor",
@@ -141116,38 +143553,6 @@ export const GENERATED_PROVIDER_MODELS: {
"apiProtocol": "anthropic"
}
},
- "deepseek-v4-flash": {
- "id": "deepseek-v4-flash",
- "name": "DeepSeek V4 Flash",
- "contextWindow": 1000000,
- "maxInputTokens": 1000000,
- "maxTokens": 384000,
- "capabilities": [
- "tools",
- "reasoning",
- "structured_output",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [
- {
- "type": "effort",
- "values": [
- "low",
- "high",
- "max"
- ]
- }
- ],
- "pricing": {
- "input": 0.15,
- "output": 0.6,
- "cacheRead": 0.003,
- "cacheWrite": 0
- },
- "releaseDate": "2026-07-31",
- "family": "deepseek-flash"
- },
"kimi-k3": {
"id": "kimi-k3",
"name": "Kimi K3",
@@ -141483,31 +143888,6 @@ export const GENERATED_PROVIDER_MODELS: {
},
"releaseDate": "2026-04-22",
"family": "mimo-v2.5-pro"
- },
- "minimax-m2.7": {
- "id": "minimax-m2.7",
- "name": "MiniMax-M2.7",
- "contextWindow": 204800,
- "maxInputTokens": 204800,
- "maxTokens": 131072,
- "capabilities": [
- "tools",
- "reasoning",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [],
- "pricing": {
- "input": 0.3,
- "output": 1.2,
- "cacheRead": 0.06,
- "cacheWrite": 0.375
- },
- "releaseDate": "2026-03-18",
- "family": "minimax-m2.7",
- "metadata": {
- "apiProtocol": "anthropic"
- }
}
},
"openreason": {
@@ -141606,6 +143986,221 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"openrouter": {
+ "meta/muse-spark-open": {
+ "id": "meta/muse-spark-open",
+ "name": "Muse Spark Open",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 943718,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1.25,
+ "output": 4.25,
+ "cacheRead": 0.15,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-15",
+ "family": "muse",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "pdf",
+ "audio"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
+ "nvidia/nemotron-3.5-super-vl": {
+ "id": "nvidia/nemotron-3.5-super-vl",
+ "name": "Nemotron 3.5 Super VL",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 235929,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "toggle"
+ }
+ ],
+ "pricing": {
+ "input": 0.15,
+ "output": 0.5,
+ "cacheRead": 0.02,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-15",
+ "family": "nemotron"
+ },
+ "nvidia/nemotron-3.5-super-vl:free": {
+ "id": "nvidia/nemotron-3.5-super-vl:free",
+ "name": "Nemotron 3.5 Super VL (free)",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 131072,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "toggle"
+ }
+ ],
+ "pricing": {
+ "input": 0,
+ "output": 0,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-15",
+ "family": "nemotron"
+ },
+ "~unbiased/pareto-latest": {
+ "id": "~unbiased/pareto-latest",
+ "name": "Pareto Latest",
+ "contextWindow": 262144,
+ "maxInputTokens": 262144,
+ "maxTokens": 131072,
+ "capabilities": [
+ "images",
+ "tools",
+ "temperature",
+ "prompt-cache"
+ ],
+ "pricing": {
+ "input": 2.5,
+ "output": 7.5,
+ "cacheRead": 0.25,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-13"
+ },
+ "google/gemini-4-argon": {
+ "id": "google/gemini-4-argon",
+ "name": "Gemini 4 Argon",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 10,
+ "cacheRead": 0.1,
+ "cacheWrite": 0.1875
+ },
+ "releaseDate": "2026-10-13",
+ "family": "gemini",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio",
+ "pdf"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
+ "liquid/lfm-2.5-24b-a2b": {
+ "id": "liquid/lfm-2.5-24b-a2b",
+ "name": "LFM2.5-24B-A2B",
+ "contextWindow": 128000,
+ "maxInputTokens": 128000,
+ "maxTokens": 8192,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [],
+ "pricing": {
+ "input": 0.05,
+ "output": 0.7,
+ "cacheRead": 0.025,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-13",
+ "family": "liquid"
+ },
+ "unbiased/pareto-26.9": {
+ "id": "unbiased/pareto-26.9",
+ "name": "Pareto 26.9",
+ "contextWindow": 262144,
+ "maxInputTokens": 262144,
+ "maxTokens": 131072,
+ "capabilities": [
+ "images",
+ "tools",
+ "temperature",
+ "prompt-cache"
+ ],
+ "pricing": {
+ "input": 2.5,
+ "output": 7.5,
+ "cacheRead": 0.25,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-13"
+ },
"meta/muse-wonder": {
"id": "meta/muse-wonder",
"name": "Muse Wonder",
@@ -141671,12 +144266,10 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"low",
"medium",
"high",
@@ -141708,12 +144301,10 @@ export const GENERATED_PROVIDER_MODELS: {
"temperature"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"minimal",
"high"
]
@@ -141779,7 +144370,9 @@ export const GENERATED_PROVIDER_MODELS: {
"capabilities": [
"tools",
"reasoning",
- "temperature"
+ "structured_output",
+ "temperature",
+ "prompt-cache"
],
"reasoningOptions": [
{
@@ -141787,59 +144380,14 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0,
- "output": 0,
- "cacheRead": 0,
+ "input": 0.075,
+ "output": 0.225,
+ "cacheRead": 0.015,
"cacheWrite": 0
},
"releaseDate": "2026-10-02",
"family": "ling"
},
- "apodex/apodex-1.1-mini:free": {
- "id": "apodex/apodex-1.1-mini:free",
- "name": "Apodex 1.1 Mini (free)",
- "contextWindow": 262144,
- "maxInputTokens": 262144,
- "maxTokens": 235929,
- "capabilities": [
- "tools",
- "reasoning",
- "structured_output",
- "temperature"
- ],
- "reasoningOptions": [
- {
- "type": "toggle"
- }
- ],
- "pricing": {
- "input": 0,
- "output": 0,
- "cacheRead": 0,
- "cacheWrite": 0
- },
- "releaseDate": "2026-10-01"
- },
- "unbiased/pareto-26.10-preview": {
- "id": "unbiased/pareto-26.10-preview",
- "name": "Pareto 26.10 Preview",
- "contextWindow": 1048576,
- "maxInputTokens": 1048576,
- "maxTokens": 131072,
- "capabilities": [
- "images",
- "tools",
- "temperature",
- "prompt-cache"
- ],
- "pricing": {
- "input": 0.8,
- "output": 3.2,
- "cacheRead": 0.03,
- "cacheWrite": 0
- },
- "releaseDate": "2026-10-01"
- },
"openai/gpt-6.1-sol": {
"id": "openai/gpt-6.1-sol",
"name": "GPT-6.1 Sol",
@@ -142005,12 +144553,10 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"low",
"high",
"max"
@@ -142565,12 +145111,10 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"medium",
"xhigh"
]
@@ -142660,30 +145204,10 @@ export const GENERATED_PROVIDER_MODELS: {
]
}
},
- "unbiased/pareto": {
- "id": "unbiased/pareto",
- "name": "Pareto",
- "contextWindow": 262144,
- "maxInputTokens": 262144,
- "maxTokens": 131072,
- "capabilities": [
- "images",
- "tools",
- "temperature",
- "prompt-cache"
- ],
- "pricing": {
- "input": 2.5,
- "output": 7.5,
- "cacheRead": 0.25,
- "cacheWrite": 0
- },
- "releaseDate": "2026-09-17"
- },
"stepfun/step-5-preview": {
"id": "stepfun/step-5-preview",
"name": "Step 5 Preview",
- "contextWindow": 1000000,
+ "contextWindow": 1048576,
"maxInputTokens": 1000000,
"maxTokens": 64000,
"capabilities": [
@@ -142708,7 +145232,7 @@ export const GENERATED_PROVIDER_MODELS: {
"pricing": {
"input": 1,
"output": 2.7,
- "cacheRead": 0.05,
+ "cacheRead": 0.1,
"cacheWrite": 0
},
"releaseDate": "2026-09-16"
@@ -142728,12 +145252,10 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"low",
"high",
"max"
@@ -142741,9 +145263,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.0441,
- "output": 0.891,
- "cacheRead": 0.0054,
+ "input": 0.0115,
+ "output": 0.6,
+ "cacheRead": 0.006,
"cacheWrite": 0
},
"releaseDate": "2026-09-14",
@@ -142754,7 +145276,7 @@ export const GENERATED_PROVIDER_MODELS: {
"name": "DeepSeek Pro Latest",
"contextWindow": 1048576,
"maxInputTokens": 1048576,
- "maxTokens": 943718,
+ "maxTokens": 393216,
"capabilities": [
"tools",
"reasoning",
@@ -142763,12 +145285,10 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"low",
"high",
"max"
@@ -142776,9 +145296,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.25,
- "output": 5,
- "cacheRead": 0.2,
+ "input": 0.225,
+ "output": 8,
+ "cacheRead": 0.23,
"cacheWrite": 0
},
"releaseDate": "2026-09-14",
@@ -142997,7 +145517,7 @@ export const GENERATED_PROVIDER_MODELS: {
"name": "DeepSeek V4.1 Flash",
"contextWindow": 1048576,
"maxInputTokens": 1048576,
- "maxTokens": 943718,
+ "maxTokens": 393216,
"capabilities": [
"images",
"tools",
@@ -143007,12 +145527,10 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"low",
"high",
"max"
@@ -143020,9 +145538,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.0441,
- "output": 0.891,
- "cacheRead": 0.0054,
+ "input": 0.3,
+ "output": 1.2,
+ "cacheRead": 0.006,
"cacheWrite": 0
},
"releaseDate": "2026-09-10",
@@ -143031,8 +145549,8 @@ export const GENERATED_PROVIDER_MODELS: {
"inclusionai/ling-3.0-flash-vl": {
"id": "inclusionai/ling-3.0-flash-vl",
"name": "Ling 3.0 Flash VL",
- "contextWindow": 262144,
- "maxInputTokens": 262144,
+ "contextWindow": 131072,
+ "maxInputTokens": 131072,
"maxTokens": 32768,
"capabilities": [
"images",
@@ -143049,9 +145567,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.021,
- "output": 0.0616,
- "cacheRead": 0.0042,
+ "input": 0.06,
+ "output": 0.18,
+ "cacheRead": 0.012,
"cacheWrite": 0
},
"releaseDate": "2026-09-10",
@@ -143123,32 +145641,6 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-09-08",
"family": "agi"
},
- "inclusionai/ling-3.0-flash-sante": {
- "id": "inclusionai/ling-3.0-flash-sante",
- "name": "Ling 3.0 Flash Sante",
- "contextWindow": 262144,
- "maxInputTokens": 262144,
- "maxTokens": 32768,
- "capabilities": [
- "tools",
- "reasoning",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [
- {
- "type": "toggle"
- }
- ],
- "pricing": {
- "input": 0.042,
- "output": 0.1232,
- "cacheRead": 0.0084,
- "cacheWrite": 0
- },
- "releaseDate": "2026-09-04",
- "family": "ling"
- },
"openai/gpt-6-astra": {
"id": "openai/gpt-6-astra",
"name": "GPT-6 Astra",
@@ -143246,9 +145738,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.75,
- "output": 3.75,
- "cacheRead": 0.075,
+ "input": 0.825,
+ "output": 4.125,
+ "cacheRead": 0.0825,
"cacheWrite": 0.041667
},
"releaseDate": "2026-09-02",
@@ -143503,40 +145995,14 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.0261,
- "output": 0.9,
- "cacheRead": 0.0108,
+ "input": 0.01251,
+ "output": 1.125,
+ "cacheRead": 0.009,
"cacheWrite": 0
},
"releaseDate": "2026-08-27",
"family": "glm-flash"
},
- "inclusionai/ling-3.0-flash-fin": {
- "id": "inclusionai/ling-3.0-flash-fin",
- "name": "Ling 3.0 Flash Fin",
- "contextWindow": 262144,
- "maxInputTokens": 262144,
- "maxTokens": 32768,
- "capabilities": [
- "tools",
- "reasoning",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [
- {
- "type": "toggle"
- }
- ],
- "pricing": {
- "input": 0.042,
- "output": 0.1232,
- "cacheRead": 0.0084,
- "cacheWrite": 0
- },
- "releaseDate": "2026-08-27",
- "family": "ling"
- },
"qwen/qwen3.8-flash": {
"id": "qwen/qwen3.8-flash",
"name": "Qwen3.8 Flash",
@@ -143574,7 +146040,7 @@ export const GENERATED_PROVIDER_MODELS: {
"name": "GLM-5.3-Flash",
"contextWindow": 1048576,
"maxInputTokens": 1048576,
- "maxTokens": 943718,
+ "maxTokens": 943717,
"capabilities": [
"images",
"video",
@@ -143595,9 +146061,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.0261,
- "output": 0.9,
- "cacheRead": 0.0108,
+ "input": 0.15,
+ "output": 0.5,
+ "cacheRead": 0.03,
"cacheWrite": 0
},
"releaseDate": "2026-08-26",
@@ -143618,12 +146084,10 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"low",
"high",
"max"
@@ -143681,7 +146145,7 @@ export const GENERATED_PROVIDER_MODELS: {
"name": "GLM Latest",
"contextWindow": 1048576,
"maxInputTokens": 1048576,
- "maxTokens": 943718,
+ "maxTokens": 131072,
"capabilities": [
"tools",
"reasoning",
@@ -143700,9 +146164,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.055,
- "output": 5,
- "cacheRead": 0.06,
+ "input": 0.0608,
+ "output": 4.4,
+ "cacheRead": 0.0565,
"cacheWrite": 0
},
"releaseDate": "2026-08-19",
@@ -143750,12 +146214,10 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"low",
"medium",
"xhigh"
@@ -143763,9 +146225,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.04,
- "output": 2.3,
- "cacheRead": 0.0198,
+ "input": 0.24,
+ "output": 2.2,
+ "cacheRead": 0.05,
"cacheWrite": 0
},
"releaseDate": "2026-08-14",
@@ -143797,7 +146259,7 @@ export const GENERATED_PROVIDER_MODELS: {
"pricing": {
"input": 0.079,
"output": 4.8,
- "cacheRead": 0.059,
+ "cacheRead": 0.078,
"cacheWrite": 0
},
"releaseDate": "2026-08-14",
@@ -143892,12 +146354,10 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"low",
"high",
"max"
@@ -144207,12 +146667,10 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"low",
"high",
"max"
@@ -144220,9 +146678,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.0144,
+ "input": 0.00522,
"output": 0.576,
- "cacheRead": 0.0108,
+ "cacheRead": 0.00522,
"cacheWrite": 0
},
"releaseDate": "2026-08-01",
@@ -144242,12 +146700,10 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"low",
"high",
"max"
@@ -144255,9 +146711,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.016,
+ "input": 0.0058,
"output": 0.64,
- "cacheRead": 0.016,
+ "cacheRead": 0.0058,
"cacheWrite": 0
},
"releaseDate": "2026-07-31",
@@ -144367,12 +146823,10 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"low",
"medium",
"high",
@@ -144608,12 +147062,10 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"low",
"high",
"max"
@@ -144621,9 +147073,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.73,
- "output": 13.5,
- "cacheRead": 0.55,
+ "input": 0.405,
+ "output": 15.45,
+ "cacheRead": 0.28,
"cacheWrite": 0
},
"releaseDate": "2026-07-16",
@@ -144849,10 +147301,10 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 2,
- "output": 10,
- "cacheRead": 0.2,
- "cacheWrite": 2.5
+ "input": 4,
+ "output": 20,
+ "cacheRead": 0.4,
+ "cacheWrite": 5
},
"releaseDate": "2026-07-09",
"family": "gpt-sol"
@@ -144885,10 +147337,10 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 2,
- "output": 10,
- "cacheRead": 0.2,
- "cacheWrite": 2.5
+ "input": 4,
+ "output": 20,
+ "cacheRead": 0.4,
+ "cacheWrite": 5
},
"releaseDate": "2026-07-09",
"family": "gpt-sol"
@@ -145174,12 +147626,10 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"low",
"medium",
"high",
@@ -145209,12 +147659,10 @@ export const GENERATED_PROVIDER_MODELS: {
"temperature"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"minimal",
"high"
]
@@ -145310,21 +147758,19 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"high",
"xhigh"
]
}
],
"pricing": {
- "input": 0.06,
- "output": 7,
- "cacheRead": 0.059,
+ "input": 0.62,
+ "output": 2.42,
+ "cacheRead": 0.14,
"cacheWrite": 0
},
"releaseDate": "2026-06-13",
@@ -145438,12 +147884,10 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"medium",
"high"
]
@@ -145473,12 +147917,10 @@ export const GENERATED_PROVIDER_MODELS: {
"temperature"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"medium",
"high"
]
@@ -145601,12 +148043,10 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"low",
"medium",
"high",
@@ -145671,12 +148111,10 @@ export const GENERATED_PROVIDER_MODELS: {
"temperature"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"minimal",
"high"
]
@@ -145793,12 +148231,10 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"minimal",
"low",
"medium",
@@ -145937,12 +148373,10 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"low",
"medium",
"high",
@@ -146070,9 +148504,9 @@ export const GENERATED_PROVIDER_MODELS: {
],
"pricing": {
"input": 2,
- "output": 12,
- "cacheRead": 0.2,
- "cacheWrite": 0.375
+ "output": 10,
+ "cacheRead": 0.1,
+ "cacheWrite": 0.1875
},
"releaseDate": "2026-04-27",
"family": "gemini-pro",
@@ -146105,12 +148539,10 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"low",
"high",
"max"
@@ -146118,9 +148550,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.73,
- "output": 13.5,
- "cacheRead": 0.55,
+ "input": 0.32,
+ "output": 24,
+ "cacheRead": 0.31,
"cacheWrite": 0
},
"releaseDate": "2026-04-27",
@@ -146224,7 +148656,7 @@ export const GENERATED_PROVIDER_MODELS: {
"name": "DeepSeek V4 Flash",
"contextWindow": 1048576,
"maxInputTokens": 1048576,
- "maxTokens": 943718,
+ "maxTokens": 943717,
"capabilities": [
"tools",
"reasoning",
@@ -146233,21 +148665,19 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"high",
"xhigh"
]
}
],
"pricing": {
- "input": 0.0425,
- "output": 1.28,
- "cacheRead": 0.0425,
+ "input": 0.091,
+ "output": 0.182,
+ "cacheRead": 0.0182,
"cacheWrite": 0
},
"releaseDate": "2026-04-24",
@@ -146267,12 +148697,10 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"high",
"xhigh"
]
@@ -146359,14 +148787,15 @@ export const GENERATED_PROVIDER_MODELS: {
"name": "Qwen3.6 27B",
"contextWindow": 262144,
"maxInputTokens": 262144,
- "maxTokens": 81920,
+ "maxTokens": 65536,
"capabilities": [
"images",
"video",
"tools",
"reasoning",
"structured_output",
- "temperature"
+ "temperature",
+ "prompt-cache"
],
"reasoningOptions": [
{
@@ -146374,9 +148803,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.32,
- "output": 3.2,
- "cacheRead": 0,
+ "input": 0.25,
+ "output": 2,
+ "cacheRead": 0.025,
"cacheWrite": 0
},
"releaseDate": "2026-04-22",
@@ -146593,7 +149022,7 @@ export const GENERATED_PROVIDER_MODELS: {
"name": "Qwen3.6 35B-A3B",
"contextWindow": 262144,
"maxInputTokens": 262144,
- "maxTokens": 65536,
+ "maxTokens": 235929,
"capabilities": [
"images",
"video",
@@ -146609,9 +149038,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.1,
- "output": 0.95,
- "cacheRead": 0.1,
+ "input": 0.15,
+ "output": 1,
+ "cacheRead": 0.05,
"cacheWrite": 0
},
"releaseDate": "2026-04-17",
@@ -146667,12 +149096,10 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"low",
"medium",
"high",
@@ -146800,9 +149227,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.09,
- "output": 0.3,
- "cacheRead": 0.05,
+ "input": 0.0765,
+ "output": 0.255,
+ "cacheRead": 0.0425,
"cacheWrite": 0
},
"releaseDate": "2026-04-02",
@@ -146847,8 +149274,7 @@ export const GENERATED_PROVIDER_MODELS: {
"tools",
"reasoning",
"structured_output",
- "temperature",
- "prompt-cache"
+ "temperature"
],
"reasoningOptions": [
{
@@ -146856,9 +149282,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.09,
- "output": 0.34,
- "cacheRead": 0.05,
+ "input": 0.2,
+ "output": 0.4,
+ "cacheRead": 0,
"cacheWrite": 0
},
"releaseDate": "2026-04-02",
@@ -147184,12 +149610,10 @@ export const GENERATED_PROVIDER_MODELS: {
"temperature"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"low",
"medium"
]
@@ -147220,12 +149644,10 @@ export const GENERATED_PROVIDER_MODELS: {
"temperature"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"low",
"medium"
]
@@ -147360,12 +149782,10 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"minimal",
"low",
"medium",
@@ -147407,12 +149827,10 @@ export const GENERATED_PROVIDER_MODELS: {
"temperature"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"minimal",
"high"
]
@@ -147547,7 +149965,7 @@ export const GENERATED_PROVIDER_MODELS: {
"name": "Qwen3.5 35B-A3B",
"contextWindow": 262144,
"maxInputTokens": 262144,
- "maxTokens": 32768,
+ "maxTokens": 16384,
"capabilities": [
"images",
"video",
@@ -147563,9 +149981,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.08,
- "output": 0.75,
- "cacheRead": 0.04,
+ "input": 0.15,
+ "output": 1,
+ "cacheRead": 0.05,
"cacheWrite": 0
},
"releaseDate": "2026-02-23",
@@ -147709,12 +150127,10 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"low",
"medium",
"high",
@@ -147780,9 +150196,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.55,
- "output": 3.5,
- "cacheRead": 0.225,
+ "input": 0.5,
+ "output": 3.6,
+ "cacheRead": 0.3,
"cacheWrite": 0
},
"releaseDate": "2026-02-15",
@@ -147803,12 +150219,10 @@ export const GENERATED_PROVIDER_MODELS: {
"temperature"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"low",
"medium",
"high"
@@ -147839,12 +150253,10 @@ export const GENERATED_PROVIDER_MODELS: {
"temperature"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"minimal",
"low",
"medium",
@@ -147876,12 +150288,10 @@ export const GENERATED_PROVIDER_MODELS: {
"temperature"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"minimal",
"low",
"medium",
@@ -147903,7 +150313,7 @@ export const GENERATED_PROVIDER_MODELS: {
"name": "MiniMax-M2.5",
"contextWindow": 204800,
"maxInputTokens": 204800,
- "maxTokens": 128000,
+ "maxTokens": 32768,
"capabilities": [
"tools",
"reasoning",
@@ -147914,8 +150324,8 @@ export const GENERATED_PROVIDER_MODELS: {
"reasoningOptions": [],
"pricing": {
"input": 0.27,
- "output": 1.08,
- "cacheRead": 0.027,
+ "output": 0.95,
+ "cacheRead": 0.03,
"cacheWrite": 0
},
"releaseDate": "2026-02-12",
@@ -147926,7 +150336,7 @@ export const GENERATED_PROVIDER_MODELS: {
"name": "GLM-5",
"contextWindow": 204800,
"maxInputTokens": 204800,
- "maxTokens": 128000,
+ "maxTokens": 131072,
"capabilities": [
"tools",
"reasoning",
@@ -147940,9 +150350,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.6,
- "output": 1.92,
- "cacheRead": 0.12,
+ "input": 1,
+ "output": 3.2,
+ "cacheRead": 0.2,
"cacheWrite": 0
},
"releaseDate": "2026-02-12",
@@ -147964,12 +150374,10 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"low",
"medium",
"high",
@@ -148355,12 +150763,10 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
+ "none",
"minimal",
"low",
"medium",
@@ -148727,15 +151133,15 @@ export const GENERATED_PROVIDER_MODELS: {
"name": "DeepSeek Chat",
"contextWindow": 163840,
"maxInputTokens": 163840,
- "maxTokens": 16384,
+ "maxTokens": 16000,
"capabilities": [
"tools",
"structured_output",
"temperature"
],
"pricing": {
- "input": 0.32,
- "output": 0.89,
+ "input": 0.2574,
+ "output": 1.0287,
"cacheRead": 0,
"cacheWrite": 0
},
@@ -148944,9 +151350,6 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"reasoningOptions": [
- {
- "type": "toggle"
- },
{
"type": "effort",
"values": [
@@ -149046,7 +151449,7 @@ export const GENERATED_PROVIDER_MODELS: {
"name": "MiniMax-M2",
"contextWindow": 204800,
"maxInputTokens": 204800,
- "maxTokens": 176947,
+ "maxTokens": 131072,
"capabilities": [
"tools",
"reasoning",
@@ -149055,8 +151458,8 @@ export const GENERATED_PROVIDER_MODELS: {
],
"reasoningOptions": [],
"pricing": {
- "input": 0.3,
- "output": 1.2,
+ "input": 0.255,
+ "output": 1.02,
"cacheRead": 0,
"cacheWrite": 0
},
@@ -149413,17 +151816,16 @@ export const GENERATED_PROVIDER_MODELS: {
"name": "Qwen3-Next 80B-A3B Instruct",
"contextWindow": 262144,
"maxInputTokens": 262144,
- "maxTokens": 235929,
+ "maxTokens": 16384,
"capabilities": [
"tools",
"structured_output",
- "temperature",
- "prompt-cache"
+ "temperature"
],
"pricing": {
- "input": 0.1,
+ "input": 0.09,
"output": 1.1,
- "cacheRead": 0.07,
+ "cacheRead": 0,
"cacheWrite": 0
},
"releaseDate": "2025-09",
@@ -150246,34 +152648,6 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2025-05-28",
"family": "deepseek-thinking"
},
- "anthropic/claude-sonnet-4": {
- "id": "anthropic/claude-sonnet-4",
- "name": "Claude Sonnet 4",
- "contextWindow": 200000,
- "maxInputTokens": 200000,
- "maxTokens": 64000,
- "capabilities": [
- "images",
- "files",
- "tools",
- "reasoning",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [
- {
- "type": "toggle"
- }
- ],
- "pricing": {
- "input": 3,
- "output": 15,
- "cacheRead": 0.3,
- "cacheWrite": 3.75
- },
- "releaseDate": "2025-05-22",
- "family": "claude-sonnet"
- },
"mistralai/mistral-medium-3": {
"id": "mistralai/mistral-medium-3",
"name": "Mistral Medium 3",
@@ -156858,25 +159232,6 @@ export const GENERATED_PROVIDER_MODELS: {
},
"releaseDate": "2025-04-01"
},
- "mistral-7b-instruct-v0.3": {
- "id": "mistral-7b-instruct-v0.3",
- "name": "Mistral-7B-Instruct-v0.3",
- "contextWindow": 65536,
- "maxInputTokens": 65536,
- "maxTokens": 65536,
- "capabilities": [
- "tools",
- "structured_output",
- "temperature"
- ],
- "pricing": {
- "input": 0.11,
- "output": 0.11,
- "cacheRead": 0,
- "cacheWrite": 0
- },
- "releaseDate": "2025-04-01"
- },
"mistral-nemo-instruct-2407": {
"id": "mistral-nemo-instruct-2407",
"name": "Mistral-Nemo-Instruct-2407",
@@ -161310,6 +163665,188 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"poe": {
+ "google/gemini-3.8-flash": {
+ "id": "google/gemini-3.8-flash",
+ "name": "Gemini-3.8-Flash",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.7576,
+ "output": 3.7879,
+ "cacheRead": 0.0758,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-09-02",
+ "family": "gemini-flash",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
+ "google/gemini-3.7-flash": {
+ "id": "google/gemini-3.7-flash",
+ "name": "Gemini-3.7-Flash",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.7576,
+ "output": 3.7879,
+ "cacheRead": 0.0758,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-08-13",
+ "family": "gemini-flash",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
+ "google/gemini-3.5-flash-lite": {
+ "id": "google/gemini-3.5-flash-lite",
+ "name": "Gemini-3.5-Flash-Lite",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "minimal",
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.303,
+ "output": 2.5253,
+ "cacheRead": 0.0303,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-07-21",
+ "family": "gemini-flash-lite",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
+ "google/gemini-3.6-flash": {
+ "id": "google/gemini-3.6-flash",
+ "name": "Gemini-3.6-Flash",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "minimal",
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.7576,
+ "output": 3.7879,
+ "cacheRead": 0.0758,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-07-21",
+ "family": "gemini-flash",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
"anthropic/claude-opus-4.8": {
"id": "anthropic/claude-opus-4.8",
"name": "Claude-Opus-4.8",
@@ -161352,9 +163889,11 @@ export const GENERATED_PROVIDER_MODELS: {
"maxTokens": 65536,
"capabilities": [
"images",
+ "video",
"tools",
"reasoning",
"structured_output",
+ "temperature",
"prompt-cache"
],
"reasoningOptions": [
@@ -161374,11 +163913,45 @@ export const GENERATED_PROVIDER_MODELS: {
"cacheWrite": 0
},
"releaseDate": "2026-05-19",
- "family": "gemini-flash",
+ "family": "gemini-flash"
+ },
+ "google/gemini-3.1-flash-lite": {
+ "id": "google/gemini-3.1-flash-lite",
+ "name": "Gemini-3.1-Flash-Lite",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "minimal",
+ "low",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.2525,
+ "output": 1.5152,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-05-07",
+ "family": "gemini-flash-lite",
"modalities": {
"input": [
"text",
"image",
+ "video",
"audio"
],
"output": [
@@ -161635,6 +164208,8 @@ export const GENERATED_PROVIDER_MODELS: {
"video",
"tools",
"reasoning",
+ "structured_output",
+ "temperature",
"prompt-cache"
],
"reasoningOptions": [
@@ -161647,53 +164222,13 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 2,
- "output": 12,
- "cacheRead": 0.2,
+ "input": 2.0202,
+ "output": 12.1212,
+ "cacheRead": 0.202,
"cacheWrite": 0
},
"releaseDate": "2026-02-19",
- "modalities": {
- "input": [
- "text",
- "image",
- "video",
- "audio"
- ],
- "output": [
- "text"
- ]
- }
- },
- "google/gemini-3.1-flash-lite": {
- "id": "google/gemini-3.1-flash-lite",
- "name": "Gemini-3.1-Flash-Lite",
- "contextWindow": 1048576,
- "maxInputTokens": 1048576,
- "maxTokens": 65536,
- "capabilities": [
- "images",
- "video",
- "tools",
- "reasoning"
- ],
- "reasoningOptions": [
- {
- "type": "effort",
- "values": [
- "minimal",
- "low",
- "high"
- ]
- }
- ],
- "pricing": {
- "input": 0.25,
- "output": 1.5,
- "cacheRead": 0,
- "cacheWrite": 0
- },
- "releaseDate": "2026-02-18",
+ "family": "gemini-pro",
"modalities": {
"input": [
"text",
@@ -161973,6 +164508,51 @@ export const GENERATED_PROVIDER_MODELS: {
},
"releaseDate": "2025-12-22"
},
+ "google/gemini-3-flash": {
+ "id": "google/gemini-3-flash",
+ "name": "Gemini-3-Flash",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "minimal",
+ "low",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.404,
+ "output": 2.4242,
+ "cacheRead": 0.0404,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2025-12-17",
+ "family": "gemini-flash",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
"openai/gpt-5.2-instant": {
"id": "openai/gpt-5.2-instant",
"name": "GPT-5.2-Instant",
@@ -162397,48 +164977,6 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2025-10-15",
"family": "claude-haiku"
},
- "google/gemini-3-flash": {
- "id": "google/gemini-3-flash",
- "name": "Gemini-3-Flash",
- "contextWindow": 1048576,
- "maxInputTokens": 1048576,
- "maxTokens": 65536,
- "capabilities": [
- "images",
- "video",
- "tools",
- "reasoning",
- "prompt-cache"
- ],
- "reasoningOptions": [
- {
- "type": "effort",
- "values": [
- "minimal",
- "low",
- "high"
- ]
- }
- ],
- "pricing": {
- "input": 0.4,
- "output": 2.4,
- "cacheRead": 0.04,
- "cacheWrite": 0
- },
- "releaseDate": "2025-10-07",
- "modalities": {
- "input": [
- "text",
- "image",
- "video",
- "audio"
- ],
- "output": [
- "text"
- ]
- }
- },
"openai/gpt-5-pro": {
"id": "openai/gpt-5-pro",
"name": "GPT-5-Pro",
@@ -163726,6 +166264,50 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"prime": {
+ "google/gemini-4-argon": {
+ "id": "google/gemini-4-argon",
+ "name": "Gemini 4 Argon",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 10,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-13",
+ "family": "gemini",
+ "modalities": {
+ "input": [
+ "audio",
+ "image",
+ "text",
+ "video"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
"openai/gpt-6.1-sol": {
"id": "openai/gpt-6.1-sol",
"name": "GPT-6.1 Sol",
@@ -163742,11 +166324,11 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "max",
- "xhigh",
- "high",
+ "low",
"medium",
- "low"
+ "high",
+ "xhigh",
+ "max"
]
}
],
@@ -163759,6 +166341,39 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-09-29",
"family": "gpt-sol"
},
+ "anthropic/claude-sonnet-5.5": {
+ "id": "anthropic/claude-sonnet-5.5",
+ "name": "Claude Sonnet 5.5",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 10,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-09-28",
+ "family": "claude-sonnet"
+ },
"anthropic/claude-opus-5.5": {
"id": "anthropic/claude-opus-5.5",
"name": "Claude Opus 5.5",
@@ -163768,17 +166383,18 @@ export const GENERATED_PROVIDER_MODELS: {
"capabilities": [
"images",
"tools",
- "reasoning"
+ "reasoning",
+ "structured_output"
],
"reasoningOptions": [
{
"type": "effort",
"values": [
- "max",
- "xhigh",
- "high",
+ "low",
"medium",
- "low"
+ "high",
+ "xhigh",
+ "max"
]
}
],
@@ -163807,12 +166423,12 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "max",
- "xhigh",
- "high",
- "medium",
+ "none",
"low",
- "none"
+ "medium",
+ "high",
+ "xhigh",
+ "max"
]
}
],
@@ -163841,12 +166457,12 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "max",
- "xhigh",
- "high",
- "medium",
+ "none",
"low",
- "none"
+ "medium",
+ "high",
+ "xhigh",
+ "max"
]
}
],
@@ -163876,10 +166492,10 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "xhigh",
- "high",
+ "low",
"medium",
- "low"
+ "high",
+ "xhigh"
]
}
],
@@ -163899,6 +166515,7 @@ export const GENERATED_PROVIDER_MODELS: {
"maxInputTokens": 1048576,
"maxTokens": 131072,
"capabilities": [
+ "images",
"tools",
"reasoning",
"structured_output",
@@ -163941,11 +166558,11 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "max",
- "xhigh",
- "high",
+ "low",
"medium",
- "low"
+ "high",
+ "xhigh",
+ "max"
]
}
],
@@ -163976,9 +166593,9 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "high",
+ "low",
"medium",
- "low"
+ "high"
]
}
],
@@ -164011,17 +166628,18 @@ export const GENERATED_PROVIDER_MODELS: {
"capabilities": [
"images",
"tools",
- "reasoning"
+ "reasoning",
+ "structured_output"
],
"reasoningOptions": [
{
"type": "effort",
"values": [
- "max",
- "xhigh",
- "high",
+ "low",
"medium",
- "low"
+ "high",
+ "xhigh",
+ "max"
]
}
],
@@ -164036,7 +166654,7 @@ export const GENERATED_PROVIDER_MODELS: {
},
"z-ai/glm-5.3-flash": {
"id": "z-ai/glm-5.3-flash",
- "name": "GLM-5.3-Flash",
+ "name": "GLM 5.3 Flash",
"contextWindow": 1048576,
"maxInputTokens": 1048576,
"maxTokens": 943718,
@@ -164052,9 +166670,9 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "max",
+ "low",
"high",
- "low"
+ "max"
]
}
],
@@ -164069,7 +166687,7 @@ export const GENERATED_PROVIDER_MODELS: {
},
"z-ai/glm-5.3": {
"id": "z-ai/glm-5.3",
- "name": "GLM-5.3",
+ "name": "GLM 5.3",
"contextWindow": 1048576,
"maxInputTokens": 1048576,
"maxTokens": 131072,
@@ -164116,9 +166734,9 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "high",
+ "low",
"medium",
- "low"
+ "high"
]
}
],
@@ -164159,10 +166777,10 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "xhigh",
- "high",
+ "low",
"medium",
- "low"
+ "high",
+ "xhigh"
]
}
],
@@ -164191,9 +166809,10 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "max",
+ "none",
+ "low",
"high",
- "low"
+ "max"
]
}
],
@@ -164215,17 +166834,19 @@ export const GENERATED_PROVIDER_MODELS: {
"capabilities": [
"images",
"tools",
- "reasoning"
+ "reasoning",
+ "structured_output"
],
"reasoningOptions": [
{
"type": "effort",
"values": [
- "max",
- "xhigh",
- "high",
+ "none",
+ "low",
"medium",
- "low"
+ "high",
+ "xhigh",
+ "max"
]
}
],
@@ -164256,10 +166877,10 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "high",
- "medium",
+ "minimal",
"low",
- "minimal"
+ "medium",
+ "high"
]
}
],
@@ -164301,9 +166922,10 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "max",
+ "none",
+ "low",
"high",
- "low"
+ "max"
]
}
],
@@ -164332,12 +166954,12 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "max",
- "xhigh",
- "high",
- "medium",
+ "none",
"low",
- "none"
+ "medium",
+ "high",
+ "xhigh",
+ "max"
]
}
],
@@ -164350,6 +166972,40 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-07-09",
"family": "gpt-luna"
},
+ "openai/gpt-5.6-luna-pro": {
+ "id": "openai/gpt-5.6-luna-pro",
+ "name": "GPT-5.6 Luna Pro",
+ "contextWindow": 1050000,
+ "maxInputTokens": 1050000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1,
+ "output": 6,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-07-09",
+ "family": "gpt-luna"
+ },
"openai/gpt-5.6-sol": {
"id": "openai/gpt-5.6-sol",
"name": "GPT-5.6 Sol",
@@ -164366,12 +167022,46 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "max",
- "xhigh",
- "high",
- "medium",
+ "none",
"low",
- "none"
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 5,
+ "output": 30,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-07-09",
+ "family": "gpt-sol"
+ },
+ "openai/gpt-5.6-sol-pro": {
+ "id": "openai/gpt-5.6-sol-pro",
+ "name": "GPT-5.6 Sol Pro",
+ "contextWindow": 1050000,
+ "maxInputTokens": 1050000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
]
}
],
@@ -164400,12 +167090,46 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "max",
- "xhigh",
- "high",
- "medium",
+ "none",
"low",
- "none"
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2.5,
+ "output": 15,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-07-09",
+ "family": "gpt-terra"
+ },
+ "openai/gpt-5.6-terra-pro": {
+ "id": "openai/gpt-5.6-terra-pro",
+ "name": "GPT-5.6 Terra Pro",
+ "contextWindow": 1050000,
+ "maxInputTokens": 1050000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
]
}
],
@@ -164427,17 +167151,19 @@ export const GENERATED_PROVIDER_MODELS: {
"capabilities": [
"images",
"tools",
- "reasoning"
+ "reasoning",
+ "structured_output"
],
"reasoningOptions": [
{
"type": "effort",
"values": [
- "max",
- "xhigh",
- "high",
+ "none",
+ "low",
"medium",
- "low"
+ "high",
+ "xhigh",
+ "max"
]
}
],
@@ -164452,7 +167178,7 @@ export const GENERATED_PROVIDER_MODELS: {
},
"z-ai/glm-5.2": {
"id": "z-ai/glm-5.2",
- "name": "GLM-5.2",
+ "name": "GLM 5.2",
"contextWindow": 1048576,
"maxInputTokens": 1048576,
"maxTokens": 943718,
@@ -164466,8 +167192,9 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "xhigh",
- "high"
+ "none",
+ "high",
+ "xhigh"
]
}
],
@@ -164489,17 +167216,18 @@ export const GENERATED_PROVIDER_MODELS: {
"capabilities": [
"images",
"tools",
- "reasoning"
+ "reasoning",
+ "structured_output"
],
"reasoningOptions": [
{
"type": "effort",
"values": [
- "max",
- "xhigh",
- "high",
+ "low",
"medium",
- "low"
+ "high",
+ "xhigh",
+ "max"
]
}
],
@@ -164521,17 +167249,19 @@ export const GENERATED_PROVIDER_MODELS: {
"capabilities": [
"images",
"tools",
- "reasoning"
+ "reasoning",
+ "structured_output"
],
"reasoningOptions": [
{
"type": "effort",
"values": [
- "max",
- "xhigh",
- "high",
+ "none",
+ "low",
"medium",
- "low"
+ "high",
+ "xhigh",
+ "max"
]
}
],
@@ -164562,10 +167292,10 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "high",
- "medium",
+ "minimal",
"low",
- "minimal"
+ "medium",
+ "high"
]
}
],
@@ -164591,10 +167321,10 @@ export const GENERATED_PROVIDER_MODELS: {
},
"deepseek/deepseek-v4-flash": {
"id": "deepseek/deepseek-v4-flash",
- "name": "DeepSeek V4 Flash",
+ "name": "DeepSeek V4 Flash 0423",
"contextWindow": 1048576,
"maxInputTokens": 1048576,
- "maxTokens": 943718,
+ "maxTokens": 943717,
"capabilities": [
"tools",
"reasoning",
@@ -164605,8 +167335,9 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "xhigh",
- "high"
+ "none",
+ "high",
+ "xhigh"
]
}
],
@@ -164621,7 +167352,7 @@ export const GENERATED_PROVIDER_MODELS: {
},
"deepseek/deepseek-v4-pro": {
"id": "deepseek/deepseek-v4-pro",
- "name": "DeepSeek V4 Pro",
+ "name": "DeepSeek V4 Pro 0423",
"contextWindow": 1048576,
"maxInputTokens": 1048576,
"maxTokens": 384000,
@@ -164635,8 +167366,9 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "xhigh",
- "high"
+ "none",
+ "high",
+ "xhigh"
]
}
],
@@ -164665,11 +167397,11 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "xhigh",
- "high",
- "medium",
+ "none",
"low",
- "none"
+ "medium",
+ "high",
+ "xhigh"
]
}
],
@@ -164691,17 +167423,19 @@ export const GENERATED_PROVIDER_MODELS: {
"capabilities": [
"images",
"tools",
- "reasoning"
+ "reasoning",
+ "structured_output"
],
"reasoningOptions": [
{
"type": "effort",
"values": [
- "max",
- "xhigh",
- "high",
+ "none",
+ "low",
"medium",
- "low"
+ "high",
+ "xhigh",
+ "max"
]
}
],
@@ -164716,7 +167450,7 @@ export const GENERATED_PROVIDER_MODELS: {
},
"openai/gpt-5.4-mini": {
"id": "openai/gpt-5.4-mini",
- "name": "GPT-5.4 mini",
+ "name": "GPT-5.4 Mini",
"contextWindow": 400000,
"maxInputTokens": 400000,
"maxTokens": 128000,
@@ -164730,11 +167464,11 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "xhigh",
- "high",
- "medium",
+ "none",
"low",
- "none"
+ "medium",
+ "high",
+ "xhigh"
]
}
],
@@ -164749,7 +167483,7 @@ export const GENERATED_PROVIDER_MODELS: {
},
"openai/gpt-5.4-nano": {
"id": "openai/gpt-5.4-nano",
- "name": "GPT-5.4 nano",
+ "name": "GPT-5.4 Nano",
"contextWindow": 400000,
"maxInputTokens": 400000,
"maxTokens": 128000,
@@ -164763,11 +167497,11 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "xhigh",
- "high",
- "medium",
+ "none",
"low",
- "none"
+ "medium",
+ "high",
+ "xhigh"
]
}
],
@@ -164790,14 +167524,15 @@ export const GENERATED_PROVIDER_MODELS: {
"images",
"tools",
"reasoning",
+ "structured_output",
"temperature"
],
"reasoningOptions": [
{
"type": "effort",
"values": [
- "high",
- "none"
+ "none",
+ "high"
]
}
],
@@ -164826,11 +167561,11 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "xhigh",
- "high",
- "medium",
+ "none",
"low",
- "none"
+ "medium",
+ "high",
+ "xhigh"
]
}
],
@@ -164852,15 +167587,16 @@ export const GENERATED_PROVIDER_MODELS: {
"capabilities": [
"images",
"tools",
- "reasoning"
+ "reasoning",
+ "structured_output"
],
"reasoningOptions": [
{
"type": "effort",
"values": [
- "xhigh",
+ "medium",
"high",
- "medium"
+ "xhigh"
]
}
],
@@ -164891,9 +167627,9 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "high",
+ "low",
"medium",
- "low"
+ "high"
]
}
],
@@ -164927,16 +167663,18 @@ export const GENERATED_PROVIDER_MODELS: {
"images",
"tools",
"reasoning",
+ "structured_output",
"temperature"
],
"reasoningOptions": [
{
"type": "effort",
"values": [
- "max",
- "high",
+ "none",
+ "low",
"medium",
- "low"
+ "high",
+ "max"
]
}
],
@@ -164959,16 +167697,18 @@ export const GENERATED_PROVIDER_MODELS: {
"images",
"tools",
"reasoning",
+ "structured_output",
"temperature"
],
"reasoningOptions": [
{
"type": "effort",
"values": [
- "max",
- "high",
+ "none",
+ "low",
"medium",
- "low"
+ "high",
+ "max"
]
}
],
@@ -164983,7 +167723,7 @@ export const GENERATED_PROVIDER_MODELS: {
},
"openai/gpt-5.3-codex": {
"id": "openai/gpt-5.3-codex",
- "name": "GPT-5.3 Codex",
+ "name": "GPT-5.3-Codex",
"contextWindow": 400000,
"maxInputTokens": 400000,
"maxTokens": 128000,
@@ -164997,11 +167737,11 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "xhigh",
- "high",
- "medium",
+ "none",
"low",
- "none"
+ "medium",
+ "high",
+ "xhigh"
]
}
],
@@ -165052,10 +167792,11 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "high",
- "medium",
+ "none",
+ "minimal",
"low",
- "minimal"
+ "medium",
+ "high"
]
}
],
@@ -165095,11 +167836,11 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "xhigh",
- "high",
- "medium",
+ "none",
"low",
- "none"
+ "medium",
+ "high",
+ "xhigh"
]
}
],
@@ -165112,45 +167853,16 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2025-12-11",
"family": "gpt"
},
- "openai/gpt-5.2-pro": {
- "id": "openai/gpt-5.2-pro",
- "name": "GPT-5.2 Pro",
- "contextWindow": 400000,
- "maxInputTokens": 400000,
- "maxTokens": 128000,
- "capabilities": [
- "images",
- "tools",
- "reasoning"
- ],
- "reasoningOptions": [
- {
- "type": "effort",
- "values": [
- "xhigh",
- "high",
- "medium"
- ]
- }
- ],
- "pricing": {
- "input": 21,
- "output": 168,
- "cacheRead": 0,
- "cacheWrite": 0
- },
- "releaseDate": "2025-12-11",
- "family": "gpt-pro"
- },
"mistralai/mistral-large-2512": {
"id": "mistralai/mistral-large-2512",
- "name": "Mistral Large 3",
+ "name": "Mistral Large 3 2512",
"contextWindow": 262144,
"maxInputTokens": 262144,
"maxTokens": 209715,
"capabilities": [
"images",
"tools",
+ "structured_output",
"temperature"
],
"pricing": {
@@ -165178,10 +167890,10 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "high",
- "medium",
+ "none",
"low",
- "none"
+ "medium",
+ "high"
]
}
],
@@ -165203,6 +167915,7 @@ export const GENERATED_PROVIDER_MODELS: {
"capabilities": [
"images",
"tools",
+ "structured_output",
"temperature"
],
"pricing": {
@@ -165237,12 +167950,13 @@ export const GENERATED_PROVIDER_MODELS: {
},
"moonshotai/kimi-k2-0905": {
"id": "moonshotai/kimi-k2-0905",
- "name": "Kimi K2 Instruct 0905",
+ "name": "Kimi K2 0905",
"contextWindow": 262144,
"maxInputTokens": 262144,
"maxTokens": 98304,
"capabilities": [
"tools",
+ "structured_output",
"temperature"
],
"pricing": {
@@ -165270,10 +167984,10 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "high",
- "medium",
+ "minimal",
"low",
- "minimal"
+ "medium",
+ "high"
]
}
],
@@ -165302,10 +168016,10 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "high",
- "medium",
+ "minimal",
"low",
- "minimal"
+ "medium",
+ "high"
]
}
],
@@ -165334,10 +168048,10 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "high",
- "medium",
+ "minimal",
"low",
- "minimal"
+ "medium",
+ "high"
]
}
],
@@ -165352,10 +168066,10 @@ export const GENERATED_PROVIDER_MODELS: {
},
"openai/gpt-oss-120b": {
"id": "openai/gpt-oss-120b",
- "name": "GPT OSS 120B",
+ "name": "gpt-oss-120b",
"contextWindow": 131072,
"maxInputTokens": 131072,
- "maxTokens": 117964,
+ "maxTokens": 65536,
"capabilities": [
"tools",
"reasoning",
@@ -165366,9 +168080,9 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "high",
+ "low",
"medium",
- "low"
+ "high"
]
}
],
@@ -165383,7 +168097,7 @@ export const GENERATED_PROVIDER_MODELS: {
},
"openai/gpt-oss-20b": {
"id": "openai/gpt-oss-20b",
- "name": "GPT OSS 20B",
+ "name": "gpt-oss-20b",
"contextWindow": 131072,
"maxInputTokens": 131072,
"maxTokens": 32768,
@@ -165397,9 +168111,9 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "high",
+ "low",
"medium",
- "low"
+ "high"
]
}
],
@@ -165435,7 +168149,7 @@ export const GENERATED_PROVIDER_MODELS: {
},
"openai/gpt-4.1-mini": {
"id": "openai/gpt-4.1-mini",
- "name": "GPT-4.1 mini",
+ "name": "GPT-4.1 Mini",
"contextWindow": 1047576,
"maxInputTokens": 1047576,
"maxTokens": 32768,
@@ -165456,7 +168170,7 @@ export const GENERATED_PROVIDER_MODELS: {
},
"openai/gpt-4.1-nano": {
"id": "openai/gpt-4.1-nano",
- "name": "GPT-4.1 nano",
+ "name": "GPT-4.1 Nano",
"contextWindow": 1047576,
"maxInputTokens": 1047576,
"maxTokens": 32768,
@@ -165477,13 +168191,14 @@ export const GENERATED_PROVIDER_MODELS: {
},
"google/gemma-3-27b-it": {
"id": "google/gemma-3-27b-it",
- "name": "Gemma 3 27B IT",
+ "name": "Gemma 3 27B",
"contextWindow": 131072,
"maxInputTokens": 131072,
"maxTokens": 117964,
"capabilities": [
"images",
"tools",
+ "structured_output",
"temperature"
],
"pricing": {
@@ -165497,12 +168212,13 @@ export const GENERATED_PROVIDER_MODELS: {
},
"meta-llama/llama-3.3-70b-instruct": {
"id": "meta-llama/llama-3.3-70b-instruct",
- "name": "Llama-3.3-70B-Instruct",
+ "name": "Llama 3.3 70B Instruct",
"contextWindow": 131072,
"maxInputTokens": 131072,
- "maxTokens": 16384,
+ "maxTokens": 32768,
"capabilities": [
"tools",
+ "structured_output",
"temperature"
],
"pricing": {
@@ -165516,7 +168232,7 @@ export const GENERATED_PROVIDER_MODELS: {
},
"openai/gpt-4o-mini": {
"id": "openai/gpt-4o-mini",
- "name": "GPT-4o mini",
+ "name": "GPT-4o-mini",
"contextWindow": 128000,
"maxInputTokens": 128000,
"maxTokens": 16384,
@@ -165543,6 +168259,7 @@ export const GENERATED_PROVIDER_MODELS: {
"maxTokens": 16384,
"capabilities": [
"tools",
+ "structured_output",
"temperature"
],
"pricing": {
@@ -165574,6 +168291,26 @@ export const GENERATED_PROVIDER_MODELS: {
},
"releaseDate": "2024-05-13",
"family": "gpt"
+ },
+ "mistralai/mixtral-8x22b-instruct": {
+ "id": "mistralai/mixtral-8x22b-instruct",
+ "name": "Mixtral 8x22B Instruct",
+ "contextWindow": 65536,
+ "maxInputTokens": 65536,
+ "maxTokens": 52428,
+ "capabilities": [
+ "tools",
+ "structured_output",
+ "temperature"
+ ],
+ "pricing": {
+ "input": 2.2,
+ "output": 6.6,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2024-04-17",
+ "family": "mistral"
}
},
"privatemode-ai": {
@@ -168238,6 +170975,197 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"requesty": {
+ "muse-spark-open": {
+ "id": "muse-spark-open",
+ "name": "Muse Spark Open",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 131072,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1.25,
+ "output": 4.25,
+ "cacheRead": 0.15,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-15",
+ "family": "muse",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
+ "gemini-4-argon": {
+ "id": "gemini-4-argon",
+ "name": "Gemini 4 Argon",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 10,
+ "cacheRead": 0.1,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-13",
+ "family": "gemini",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio",
+ "pdf"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
+ "gemini-4-argon@eu": {
+ "id": "gemini-4-argon@eu",
+ "name": "Gemini 4 Argon (EU)",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2.2,
+ "output": 11,
+ "cacheRead": 0.11,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-13",
+ "family": "gemini",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio",
+ "pdf"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
+ "muse-wonder-1.0": {
+ "id": "muse-wonder-1.0",
+ "name": "Muse Wonder",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 943718,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 4,
+ "output": 20,
+ "cacheRead": 0.2,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-12",
+ "family": "muse",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "pdf",
+ "audio"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
"claude-haiku-5-5": {
"id": "claude-haiku-5-5",
"name": "Claude Haiku 5.5",
@@ -169061,6 +171989,55 @@ export const GENERATED_PROVIDER_MODELS: {
]
}
},
+ "muse-spark-1.3": {
+ "id": "muse-spark-1.3",
+ "name": "Muse Spark 1.3",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 943718,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1.25,
+ "output": 4.25,
+ "cacheRead": 0.15,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-09-02",
+ "family": "muse",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "pdf",
+ "audio"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
"claude-fable-5.1": {
"id": "claude-fable-5.1",
"name": "Claude Fable 5.1",
@@ -171581,15 +174558,17 @@ export const GENERATED_PROVIDER_MODELS: {
},
"mistral-medium-3-5": {
"id": "mistral-medium-3-5",
- "name": "mistral-medium-3-5",
+ "name": "Mistral Medium 3.5",
"contextWindow": 262144,
"maxInputTokens": 262144,
"maxTokens": 262144,
"capabilities": [
"images",
+ "files",
"tools",
"reasoning",
"structured_output",
+ "temperature",
"prompt-cache"
],
"reasoningOptions": [
@@ -171615,15 +174594,17 @@ export const GENERATED_PROVIDER_MODELS: {
},
"mistral-medium-3-5@eu": {
"id": "mistral-medium-3-5@eu",
- "name": "mistral-medium-3-5@eu",
+ "name": "Mistral Medium 3.5 (EU)",
"contextWindow": 262144,
"maxInputTokens": 262144,
"maxTokens": 262144,
"capabilities": [
"images",
+ "files",
"tools",
"reasoning",
"structured_output",
+ "temperature",
"prompt-cache"
],
"reasoningOptions": [
@@ -174733,6 +177714,163 @@ export const GENERATED_PROVIDER_MODELS: {
"family": "fugu"
}
},
+ "sambanova": {
+ "MiniMax-M3": {
+ "id": "MiniMax-M3",
+ "name": "MiniMax-M3",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 1048576,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "toggle"
+ }
+ ],
+ "pricing": {
+ "input": 0.6,
+ "output": 2.4,
+ "cacheRead": 0.06,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-06-01",
+ "family": "minimax"
+ },
+ "gemma-4-31B-it": {
+ "id": "gemma-4-31B-it",
+ "name": "Gemma 4 31B IT",
+ "contextWindow": 131072,
+ "maxInputTokens": 131072,
+ "maxTokens": 131072,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "toggle"
+ }
+ ],
+ "pricing": {
+ "input": 0.38,
+ "output": 1.15,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-04-02",
+ "family": "gemma"
+ },
+ "DeepSeek-V3.2": {
+ "id": "DeepSeek-V3.2",
+ "name": "DeepSeek V3.2",
+ "contextWindow": 32768,
+ "maxInputTokens": 32768,
+ "maxTokens": 7168,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "toggle"
+ }
+ ],
+ "pricing": {
+ "input": 3,
+ "output": 4.5,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2025-12-01",
+ "family": "deepseek"
+ },
+ "DeepSeek-V3.1": {
+ "id": "DeepSeek-V3.1",
+ "name": "DeepSeek-V3.1",
+ "contextWindow": 131072,
+ "maxInputTokens": 131072,
+ "maxTokens": 7168,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "temperature"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "toggle"
+ }
+ ],
+ "pricing": {
+ "input": 3,
+ "output": 4.5,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2025-08-21",
+ "family": "deepseek"
+ },
+ "gpt-oss-120b": {
+ "id": "gpt-oss-120b",
+ "name": "GPT OSS 120B",
+ "contextWindow": 131072,
+ "maxInputTokens": 131072,
+ "maxTokens": 131072,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.22,
+ "output": 0.59,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2025-08-05",
+ "family": "gpt-oss"
+ },
+ "Meta-Llama-3.3-70B-Instruct": {
+ "id": "Meta-Llama-3.3-70B-Instruct",
+ "name": "Llama-3.3-70B-Instruct",
+ "contextWindow": 131072,
+ "maxInputTokens": 131072,
+ "maxTokens": 3072,
+ "capabilities": [
+ "tools",
+ "temperature"
+ ],
+ "pricing": {
+ "input": 0.6,
+ "output": 1.2,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2024-12-06",
+ "family": "llama"
+ }
+ },
"sapaicore": {
"gpt-6.1-sol": {
"id": "gpt-6.1-sol",
@@ -176161,6 +179299,37 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"scaleway": {
+ "glm-5.3": {
+ "id": "glm-5.3",
+ "name": "GLM-5.3",
+ "contextWindow": 256000,
+ "maxInputTokens": 256000,
+ "maxTokens": 16384,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "high",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2.01,
+ "output": 6.15,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-08-14",
+ "family": "glm"
+ },
"qwen3.8-27b": {
"id": "qwen3.8-27b",
"name": "Qwen3.8 27B",
@@ -177167,6 +180336,39 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"sensenova": {
+ "deepseek-v4.1-flash": {
+ "id": "deepseek-v4.1-flash",
+ "name": "DeepSeek V4.1 Flash",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "high",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0,
+ "output": 0,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-09-10",
+ "family": "deepseek-flash"
+ },
"deepseek-v4-pro": {
"id": "deepseek-v4-pro",
"name": "DeepSeek V4 Pro",
@@ -180612,6 +183814,35 @@ export const GENERATED_PROVIDER_MODELS: {
"family": "qwen"
}
},
+ "standardcompute": {
+ "standardcompute": {
+ "id": "standardcompute",
+ "name": "Standard Compute",
+ "contextWindow": 1000000,
+ "maxInputTokens": 850000,
+ "maxTokens": 50000,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "toggle"
+ }
+ ],
+ "pricing": {
+ "input": 0,
+ "output": 0,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-03-01",
+ "family": "auto"
+ }
+ },
"stepfun": {
"step-5-preview": {
"id": "step-5-preview",
@@ -188968,6 +192199,218 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"vercel-ai-gateway": {
+ "meta/muse-spark-open": {
+ "id": "meta/muse-spark-open",
+ "name": "Muse Spark Open",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 1048576,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1.25,
+ "output": 4.25,
+ "cacheRead": 0.15,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-15",
+ "family": "muse"
+ },
+ "nvidia/nemotron-3.5-super-vl": {
+ "id": "nvidia/nemotron-3.5-super-vl",
+ "name": "NVIDIA Nemotron 3.5 Super VL",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 1048576,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.2,
+ "output": 0.5,
+ "cacheRead": 0.04,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-15",
+ "family": "nemotron"
+ },
+ "stealth/cat-jam": {
+ "id": "stealth/cat-jam",
+ "name": "Cat Jam",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 131072,
+ "capabilities": [
+ "tools",
+ "reasoning"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0,
+ "output": 0,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-15"
+ },
+ "google/gemini-4-argon": {
+ "id": "google/gemini-4-argon",
+ "name": "Gemini 4 Argon",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 1000000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 10,
+ "cacheRead": 0.1,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-13",
+ "family": "gemini"
+ },
+ "liquid/lfm2.5-24b-a2b": {
+ "id": "liquid/lfm2.5-24b-a2b",
+ "name": "LFM2.5-24B-A2B",
+ "contextWindow": 128000,
+ "maxInputTokens": 128000,
+ "maxTokens": 8200,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "minimal",
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.05,
+ "output": 0.7,
+ "cacheRead": 0.025,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-13",
+ "family": "liquid"
+ },
+ "microsoft/mai-image-2.6": {
+ "id": "microsoft/mai-image-2.6",
+ "name": "MAI-Image-2.6",
+ "contextWindow": 0,
+ "maxInputTokens": 0,
+ "maxTokens": 0,
+ "capabilities": [],
+ "pricing": {
+ "input": 5,
+ "output": 38,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-13",
+ "family": "mai",
+ "operation": "image-generation",
+ "modalities": {
+ "input": [
+ "text"
+ ],
+ "output": [
+ "image"
+ ]
+ }
+ },
+ "microsoft/mai-image-2.6-flash": {
+ "id": "microsoft/mai-image-2.6-flash",
+ "name": "MAI-Image-2.6-Flash",
+ "contextWindow": 0,
+ "maxInputTokens": 0,
+ "maxTokens": 0,
+ "capabilities": [],
+ "pricing": {
+ "input": 1.75,
+ "output": 19,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-13",
+ "family": "mai",
+ "operation": "image-generation",
+ "modalities": {
+ "input": [
+ "text"
+ ],
+ "output": [
+ "image"
+ ]
+ }
+ },
"meta/muse-wonder-1.0": {
"id": "meta/muse-wonder-1.0",
"name": "Muse Wonder",
@@ -188991,7 +192434,8 @@ export const GENERATED_PROVIDER_MODELS: {
"low",
"medium",
"high",
- "xhigh"
+ "xhigh",
+ "max"
]
}
],
@@ -189258,7 +192702,8 @@ export const GENERATED_PROVIDER_MODELS: {
"maxTokens": 32768,
"capabilities": [
"tools",
- "reasoning"
+ "reasoning",
+ "prompt-cache"
],
"reasoningOptions": [
{
@@ -189272,39 +192717,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0,
- "output": 0,
- "cacheRead": 0,
- "cacheWrite": 0
- },
- "releaseDate": "2026-09-29",
- "family": "ling"
- },
- "inclusionai/ling-3.1-flash-free": {
- "id": "inclusionai/ling-3.1-flash-free",
- "name": "Ling 3.1 Flash (Free)",
- "contextWindow": 262144,
- "maxInputTokens": 262144,
- "maxTokens": 32768,
- "capabilities": [
- "tools",
- "reasoning"
- ],
- "reasoningOptions": [
- {
- "type": "effort",
- "values": [
- "none",
- "low",
- "medium",
- "high"
- ]
- }
- ],
- "pricing": {
- "input": 0,
- "output": 0,
- "cacheRead": 0,
+ "input": 0.3,
+ "output": 0.9,
+ "cacheRead": 0.06,
"cacheWrite": 0
},
"releaseDate": "2026-09-29",
@@ -190473,7 +193888,8 @@ export const GENERATED_PROVIDER_MODELS: {
"low",
"medium",
"high",
- "xhigh"
+ "xhigh",
+ "max"
]
}
],
@@ -190507,7 +193923,8 @@ export const GENERATED_PROVIDER_MODELS: {
"low",
"medium",
"high",
- "xhigh"
+ "xhigh",
+ "max"
]
}
],
@@ -191119,6 +194536,38 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-08-11",
"family": "nemotron"
},
+ "nvidia/nemotron-3.5-lightning-free": {
+ "id": "nvidia/nemotron-3.5-lightning-free",
+ "name": "Nemotron 3.5 Lightning Free",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 65000,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0,
+ "output": 0,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-08-11",
+ "family": "nemotron"
+ },
"meta/muse-glimmer-30b": {
"id": "meta/muse-glimmer-30b",
"name": "Muse Glimmer 30B",
@@ -192294,13 +195743,7 @@ export const GENERATED_PROVIDER_MODELS: {
],
"reasoningOptions": [
{
- "type": "effort",
- "values": [
- "none",
- "low",
- "medium",
- "high"
- ]
+ "type": "toggle"
}
],
"pricing": {
@@ -192329,13 +195772,7 @@ export const GENERATED_PROVIDER_MODELS: {
],
"reasoningOptions": [
{
- "type": "effort",
- "values": [
- "none",
- "low",
- "medium",
- "high"
- ]
+ "type": "toggle"
}
],
"pricing": {
@@ -193190,9 +196627,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.435,
- "output": 0.87,
- "cacheRead": 0.0036,
+ "input": 0.3045,
+ "output": 0.609,
+ "cacheRead": 0.0028,
"cacheWrite": 0
},
"releaseDate": "2026-04-22",
@@ -196640,38 +200077,6 @@ export const GENERATED_PROVIDER_MODELS: {
]
}
},
- "anthropic/claude-sonnet-4": {
- "id": "anthropic/claude-sonnet-4",
- "name": "Claude Sonnet 4",
- "contextWindow": 1000000,
- "maxInputTokens": 1000000,
- "maxTokens": 64000,
- "capabilities": [
- "images",
- "files",
- "tools",
- "reasoning",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [
- {
- "type": "toggle"
- },
- {
- "type": "budget_tokens",
- "min": 1024
- }
- ],
- "pricing": {
- "input": 3,
- "output": 15,
- "cacheRead": 0.3,
- "cacheWrite": 3.75
- },
- "releaseDate": "2025-05-22",
- "family": "claude-sonnet"
- },
"alibaba/qwen-3-14b": {
"id": "alibaba/qwen-3-14b",
"name": "Qwen3-14B",
@@ -197694,6 +201099,52 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"vertex": {
+ "gemini-4-argon": {
+ "id": "gemini-4-argon",
+ "name": "Gemini 4 Argon",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 10,
+ "cacheRead": 0.1,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-13",
+ "family": "gemini",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio",
+ "pdf"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
"claude-haiku-5-5@default": {
"id": "claude-haiku-5-5@default",
"name": "Claude Haiku 5.5",
@@ -202064,6 +205515,34 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"wandb": {
+ "nvidia/NVIDIA-Nemotron-3.5-Super-VL-120B-A12B": {
+ "id": "nvidia/NVIDIA-Nemotron-3.5-Super-VL-120B-A12B",
+ "name": "Nemotron 3.5 Super VL",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 1048576,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "toggle"
+ }
+ ],
+ "pricing": {
+ "input": 0.15,
+ "output": 0.75,
+ "cacheRead": 0.02,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-15",
+ "family": "nemotron"
+ },
"deepseek-ai/DeepSeek-V4.1-Flash": {
"id": "deepseek-ai/DeepSeek-V4.1-Flash",
"name": "DeepSeek V4.1 Flash",
@@ -202084,9 +205563,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.2,
+ "input": 0.15,
"output": 0.65,
- "cacheRead": 0.03,
+ "cacheRead": 0.002,
"cacheWrite": 0
},
"releaseDate": "2026-09-10",
@@ -202110,7 +205589,7 @@ export const GENERATED_PROVIDER_MODELS: {
"pricing": {
"input": 0.15,
"output": 0.5,
- "cacheRead": 0.05,
+ "cacheRead": 0.02,
"cacheWrite": 0
},
"releaseDate": "2026-08-26",
@@ -202271,7 +205750,7 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.76,
+ "input": 0.62,
"output": 2.42,
"cacheRead": 0.14,
"cacheWrite": 0
@@ -202961,97 +206440,6 @@ export const GENERATED_PROVIDER_MODELS: {
"text"
]
}
- },
- "mimo-v2.5-pro-ultraspeed": {
- "id": "mimo-v2.5-pro-ultraspeed",
- "name": "MiMo-V2.5-Pro-UltraSpeed",
- "contextWindow": 1048576,
- "maxInputTokens": 1048576,
- "maxTokens": 131072,
- "capabilities": [
- "tools",
- "reasoning",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [
- {
- "type": "toggle"
- }
- ],
- "pricing": {
- "input": 1.305,
- "output": 2.61,
- "cacheRead": 0.0108,
- "cacheWrite": 0
- },
- "releaseDate": "2026-06-08",
- "family": "mimo"
- },
- "mimo-v2.5": {
- "id": "mimo-v2.5",
- "name": "MiMo-V2.5",
- "contextWindow": 1048576,
- "maxInputTokens": 1048576,
- "maxTokens": 131072,
- "capabilities": [
- "images",
- "video",
- "tools",
- "reasoning",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [
- {
- "type": "toggle"
- }
- ],
- "pricing": {
- "input": 0.14,
- "output": 0.28,
- "cacheRead": 0.0028,
- "cacheWrite": 0
- },
- "releaseDate": "2026-04-22",
- "family": "mimo",
- "modalities": {
- "input": [
- "text",
- "image",
- "audio",
- "video"
- ],
- "output": [
- "text"
- ]
- }
- },
- "mimo-v2.5-pro": {
- "id": "mimo-v2.5-pro",
- "name": "MiMo-V2.5-Pro",
- "contextWindow": 1048576,
- "maxInputTokens": 1048576,
- "maxTokens": 131072,
- "capabilities": [
- "tools",
- "reasoning",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [
- {
- "type": "toggle"
- }
- ],
- "pricing": {
- "input": 0.435,
- "output": 0.87,
- "cacheRead": 0.0036,
- "cacheWrite": 0
- },
- "releaseDate": "2026-04-22",
- "family": "mimo"
}
},
"xiaomi-token-plan-ams": {
@@ -203130,69 +206518,6 @@ export const GENERATED_PROVIDER_MODELS: {
"text"
]
}
- },
- "mimo-v2.5": {
- "id": "mimo-v2.5",
- "name": "MiMo-V2.5",
- "contextWindow": 1048576,
- "maxInputTokens": 1048576,
- "maxTokens": 131072,
- "capabilities": [
- "images",
- "video",
- "tools",
- "reasoning",
- "temperature"
- ],
- "reasoningOptions": [
- {
- "type": "toggle"
- }
- ],
- "pricing": {
- "input": 0,
- "output": 0,
- "cacheRead": 0,
- "cacheWrite": 0
- },
- "releaseDate": "2026-04-22",
- "family": "mimo",
- "modalities": {
- "input": [
- "text",
- "image",
- "audio",
- "video"
- ],
- "output": [
- "text"
- ]
- }
- },
- "mimo-v2.5-pro": {
- "id": "mimo-v2.5-pro",
- "name": "MiMo-V2.5-Pro",
- "contextWindow": 1048576,
- "maxInputTokens": 1048576,
- "maxTokens": 131072,
- "capabilities": [
- "tools",
- "reasoning",
- "temperature"
- ],
- "reasoningOptions": [
- {
- "type": "toggle"
- }
- ],
- "pricing": {
- "input": 0,
- "output": 0,
- "cacheRead": 0,
- "cacheWrite": 0
- },
- "releaseDate": "2026-04-22",
- "family": "mimo"
}
},
"xiaomi-token-plan-cn": {
@@ -203271,69 +206596,6 @@ export const GENERATED_PROVIDER_MODELS: {
"text"
]
}
- },
- "mimo-v2.5": {
- "id": "mimo-v2.5",
- "name": "MiMo-V2.5",
- "contextWindow": 1048576,
- "maxInputTokens": 1048576,
- "maxTokens": 131072,
- "capabilities": [
- "images",
- "video",
- "tools",
- "reasoning",
- "temperature"
- ],
- "reasoningOptions": [
- {
- "type": "toggle"
- }
- ],
- "pricing": {
- "input": 0,
- "output": 0,
- "cacheRead": 0,
- "cacheWrite": 0
- },
- "releaseDate": "2026-04-22",
- "family": "mimo",
- "modalities": {
- "input": [
- "text",
- "image",
- "audio",
- "video"
- ],
- "output": [
- "text"
- ]
- }
- },
- "mimo-v2.5-pro": {
- "id": "mimo-v2.5-pro",
- "name": "MiMo-V2.5-Pro",
- "contextWindow": 1048576,
- "maxInputTokens": 1048576,
- "maxTokens": 131072,
- "capabilities": [
- "tools",
- "reasoning",
- "temperature"
- ],
- "reasoningOptions": [
- {
- "type": "toggle"
- }
- ],
- "pricing": {
- "input": 0,
- "output": 0,
- "cacheRead": 0,
- "cacheWrite": 0
- },
- "releaseDate": "2026-04-22",
- "family": "mimo"
}
},
"xiaomi-token-plan-sgp": {
@@ -203412,69 +206674,6 @@ export const GENERATED_PROVIDER_MODELS: {
"text"
]
}
- },
- "mimo-v2.5": {
- "id": "mimo-v2.5",
- "name": "MiMo-V2.5",
- "contextWindow": 1048576,
- "maxInputTokens": 1048576,
- "maxTokens": 131072,
- "capabilities": [
- "images",
- "video",
- "tools",
- "reasoning",
- "temperature"
- ],
- "reasoningOptions": [
- {
- "type": "toggle"
- }
- ],
- "pricing": {
- "input": 0,
- "output": 0,
- "cacheRead": 0,
- "cacheWrite": 0
- },
- "releaseDate": "2026-04-22",
- "family": "mimo",
- "modalities": {
- "input": [
- "text",
- "image",
- "audio",
- "video"
- ],
- "output": [
- "text"
- ]
- }
- },
- "mimo-v2.5-pro": {
- "id": "mimo-v2.5-pro",
- "name": "MiMo-V2.5-Pro",
- "contextWindow": 1048576,
- "maxInputTokens": 1048576,
- "maxTokens": 131072,
- "capabilities": [
- "tools",
- "reasoning",
- "temperature"
- ],
- "reasoningOptions": [
- {
- "type": "toggle"
- }
- ],
- "pricing": {
- "input": 0,
- "output": 0,
- "cacheRead": 0,
- "cacheWrite": 0
- },
- "releaseDate": "2026-04-22",
- "family": "mimo"
}
},
"xpersona": {
diff --git a/sdk/packages/llms/src/catalog/cline-recommended.generated.ts b/sdk/packages/llms/src/catalog/cline-recommended.generated.ts
index 291cc58869..046c797b9a 100644
--- a/sdk/packages/llms/src/catalog/cline-recommended.generated.ts
+++ b/sdk/packages/llms/src/catalog/cline-recommended.generated.ts
@@ -4,6 +4,13 @@ import type { ClineRecommendedModelsPayload } from "./catalog-cline-recommended"
export const GENERATED_CLINE_RECOMMENDED_MODELS: ClineRecommendedModelsPayload =
{
recommended: [
+ {
+ id: "google/gemini-4-argon",
+ name: "Gemini 4 Argon",
+ description:
+ "Frontier model for real-world coding, enterprise knowledge work, and cyber defense",
+ tags: ["NEW"],
+ },
{
id: "anthropic/claude-sonnet-5.5",
name: "claude-sonnet-5.5",
@@ -16,12 +23,6 @@ export const GENERATED_CLINE_RECOMMENDED_MODELS: ClineRecommendedModelsPayload =
description: "",
tags: ["NEW"],
},
- {
- id: "x-ai/grok-4.7",
- name: "grok-4.7",
- description: "",
- tags: ["NEW"],
- },
{
id: "openai/gpt-6-astra",
name: "gpt-6-astra",
@@ -44,10 +45,9 @@ export const GENERATED_CLINE_RECOMMENDED_MODELS: ClineRecommendedModelsPayload =
],
free: [
{
- id: "cline-free/step-5-preview",
- name: "Step 5 Preview",
- description:
- "StepFun's flagship model for agentic work, built on a sparse Mixture-of-Experts",
+ id: "cline-free/nemotron-3.5-super-vl",
+ name: "cline-free/nemotron-3.5-super-vl",
+ description: "NVIDIA’s latest model with 120B and fast output",
tags: [],
},
{
@@ -96,18 +96,18 @@ export const GENERATED_CLINE_RECOMMENDED_MODELS: ClineRecommendedModelsPayload =
description: "Z-AI's new top open-weights model",
tags: [],
},
- {
- id: "cline-pass/deepseek-v4-pro",
- name: "cline-pass/deepseek-v4-pro",
- description: "Frontier reasoning and coding with 1M context window",
- tags: [],
- },
{
id: "cline-pass/qwen3.8-max",
name: "cline-pass/qwen3.8-max",
description: "Qwen's New SOTA coding model",
tags: [],
},
+ {
+ id: "cline-pass/deepseek-v4-pro",
+ name: "cline-pass/deepseek-v4-pro",
+ description: "Frontier reasoning and coding with 1M context window",
+ tags: [],
+ },
{
id: "cline-pass/muse-spark-1.3-contributor",
name: "cline-pass/muse-spark-1.3-contributor",
@@ -127,6 +127,12 @@ export const GENERATED_CLINE_RECOMMENDED_MODELS: ClineRecommendedModelsPayload =
description: "Latest natively multimodal model in the GLM-5 series",
tags: [],
},
+ {
+ id: "cline-pass/qwen3.7-plus",
+ name: "cline-pass/qwen3.7-plus",
+ description: "Fast multimodal agent model with vision and video input",
+ tags: [],
+ },
{
id: "cline-pass/minimax-m3",
name: "cline-pass/minimax-m3",
@@ -139,12 +145,6 @@ export const GENERATED_CLINE_RECOMMENDED_MODELS: ClineRecommendedModelsPayload =
description: "Flagship agent model with 1M context window",
tags: [],
},
- {
- id: "cline-pass/qwen3.7-plus",
- name: "cline-pass/qwen3.7-plus",
- description: "Fast multimodal agent model with vision and video input",
- tags: [],
- },
{
id: "cline-pass/mimo-v2.5-pro",
name: "cline-pass/mimo-v2.5-pro",
diff --git a/sdk/packages/llms/src/providers/provider-ids.generated.ts b/sdk/packages/llms/src/providers/provider-ids.generated.ts
index 92a02a4490..132089012d 100644
--- a/sdk/packages/llms/src/providers/provider-ids.generated.ts
+++ b/sdk/packages/llms/src/providers/provider-ids.generated.ts
@@ -44,6 +44,7 @@ export const GENERATED_PROVIDER_IDS = [
"berget",
"blueclaw",
"bothub",
+ "boundless",
"cerebras",
"chutes",
"clarifai",
@@ -167,6 +168,7 @@ export const GENERATED_PROVIDER_IDS = [
"routing-run",
"runinfra",
"sakana",
+ "sambanova",
"sapaicore",
"sarvam",
"scaleway",
@@ -177,6 +179,7 @@ export const GENERATED_PROVIDER_IDS = [
"siliconflow-cn",
"snowflake-cortex",
"stackit",
+ "standardcompute",
"stepfun",
"stepfun-ai",
"stepfun-ai-step-plan",
diff --git a/sdk/packages/llms/src/providers/providers.generated.ts b/sdk/packages/llms/src/providers/providers.generated.ts
index e3306abd70..7da04b9841 100644
--- a/sdk/packages/llms/src/providers/providers.generated.ts
+++ b/sdk/packages/llms/src/providers/providers.generated.ts
@@ -94,7 +94,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "agnes",
- defaultModelId: "agnes-2.5-pro-alpha",
+ defaultModelId: "agnes-3.0-flash",
apiKeyEnv: ["AGNES_API_KEY"],
docsUrl: "https://agnes-ai.com/doc",
defaults: {
@@ -150,7 +150,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "aihubmix",
- defaultModelId: "claude-haiku-5-5",
+ defaultModelId: "gemini-4-argon",
apiKeyEnv: ["AIHUBMIX_API_KEY"],
docsUrl: "https://docs.aihubmix.com",
},
@@ -189,7 +189,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "aixy",
- defaultModelId: "openai/gpt-6.1-sol",
+ defaultModelId: "anthropic/claude-haiku-5-5",
apiKeyEnv: ["AIXY_API_KEY"],
docsUrl: "https://docs.aixy-gateway.com/integrations/overview",
defaults: {
@@ -305,7 +305,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "prompt-cache", "reasoning"],
modelsProviderId: "ambient",
- defaultModelId: "qwen/qwen3-30b-a3b-instruct-2507",
+ defaultModelId: "ambient/small",
apiKeyEnv: ["AMBIENT_API_KEY"],
docsUrl: "https://ambient.xyz",
defaults: {
@@ -494,6 +494,20 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
baseUrl: "https://openai.bothub.ru/v1",
},
},
+ {
+ id: "boundless",
+ name: "Boundless",
+ description: "Boundless model provider from models.dev",
+ family: "openai-compatible",
+ capabilities: ["tools", "reasoning", "prompt-cache"],
+ modelsProviderId: "boundless",
+ defaultModelId: "claude-opus-5.5",
+ apiKeyEnv: ["BOUNDLESS_API_KEY"],
+ docsUrl: "https://inference.boundless.network/models",
+ defaults: {
+ baseUrl: "https://api.inference.boundless.network/v1",
+ },
+ },
{
id: "cerebras",
name: "Cerebras",
@@ -611,7 +625,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "cortecs",
- defaultModelId: "claude-haiku-5.5",
+ defaultModelId: "gemini-4-argon",
apiKeyEnv: ["CORTECS_API_KEY"],
docsUrl: "https://api.cortecs.ai/v1/models",
defaults: {
@@ -639,7 +653,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "crossmodel",
- defaultModelId: "anthropic/claude-haiku-5-5",
+ defaultModelId: "gemini/gemini-4-argon",
apiKeyEnv: ["CROSSMODEL_API_KEY"],
docsUrl: "https://www.crossmodel.ai/docs",
defaults: {
@@ -708,9 +722,9 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
name: "DigitalOcean",
description: "DigitalOcean model provider from models.dev",
family: "openai-compatible",
- capabilities: ["tools", "reasoning", "prompt-cache"],
+ capabilities: ["tools", "prompt-cache", "reasoning"],
modelsProviderId: "digitalocean",
- defaultModelId: "anthropic-claude-5.5-haiku",
+ defaultModelId: "nemotron-3.5-super-vl",
apiKeyEnv: ["DIGITALOCEAN_ACCESS_TOKEN"],
docsUrl:
"https://docs.digitalocean.com/products/gradient-ai-platform/details/models/",
@@ -781,7 +795,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "edenai",
- defaultModelId: "anthropic/claude-haiku-5-5",
+ defaultModelId: "google/gemini-4-argon",
apiKeyEnv: ["EDENAI_API_KEY"],
docsUrl: "https://docs.edenai.co",
defaults: {
@@ -851,7 +865,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "fireworks",
- defaultModelId: "accounts/fireworks/models/ember-1",
+ defaultModelId: "accounts/fireworks/models/muse-spark-open",
apiKeyEnv: ["FIREWORKS_API_KEY"],
docsUrl: "https://fireworks.ai/docs/",
defaults: {
@@ -908,7 +922,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "google",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "gemini",
- defaultModelId: "gemini-3.8-flash",
+ defaultModelId: "gemini-4-argon",
apiKeyEnv: [
"GOOGLE_API_KEY",
"GOOGLE_GENERATIVE_AI_API_KEY",
@@ -923,7 +937,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "github-copilot",
- defaultModelId: "claude-haiku-5.5",
+ defaultModelId: "gemini-4-argon",
apiKeyEnv: ["GITHUB_TOKEN"],
docsUrl: "https://docs.github.com/en/copilot",
defaults: {
@@ -1189,7 +1203,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "iteracompute",
- defaultModelId: "z-ai/glm-5.3-flash",
+ defaultModelId: "deepseek/deepseek-v4-flash-0731",
apiKeyEnv: ["ITERACOMPUTE_API_KEY"],
docsUrl: "https://iteracompute.com/docs.html",
defaults: {
@@ -1246,7 +1260,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "kilo",
- defaultModelId: "meta/muse-wonder",
+ defaultModelId: "meta/muse-spark-open",
apiKeyEnv: ["KILO_API_KEY"],
docsUrl: "https://kilo.ai",
defaults: {
@@ -1373,7 +1387,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "llmgateway-providers",
- defaultModelId: "meta/muse-wonder-1.0",
+ defaultModelId: "google-ai-studio/gemini-4-argon",
apiKeyEnv: ["LLMGATEWAY_API_KEY"],
docsUrl: "https://llmgateway.io/docs",
defaults: {
@@ -1735,7 +1749,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "nano-gpt",
- defaultModelId: "gemma-4-26b-a4b-it-chimeraxheretic",
+ defaultModelId: "nvidia/nemotron-3.5-super-vl",
apiKeyEnv: ["NANO_GPT_API_KEY"],
docsUrl: "https://docs.nano-gpt.com",
defaults: {
@@ -1763,7 +1777,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "nebius",
- defaultModelId: "deepseek-ai/DeepSeek-V4.1-Flash",
+ defaultModelId: "meta-models/muse-spark-open",
apiKeyEnv: ["NEBIUS_API_KEY"],
docsUrl: "https://docs.tokenfactory.nebius.com/",
defaults: {
@@ -1777,7 +1791,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "neon",
- defaultModelId: "claude-opus-5-5",
+ defaultModelId: "claude-haiku-5-5",
apiKeyEnv: ["NEON_AI_GATEWAY_BASE_URL", "NEON_AI_GATEWAY_TOKEN"],
docsUrl: "https://neon.com/docs",
defaults: {
@@ -1847,7 +1861,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "nvidia",
- defaultModelId: "deepseek-ai/deepseek-v4.1-flash",
+ defaultModelId: "nvidia/nemotron-3.5-super-vl-120b-a12b",
apiKeyEnv: ["NVIDIA_API_KEY"],
docsUrl: "https://docs.api.nvidia.com/nim/",
defaults: {
@@ -1877,7 +1891,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "ofox",
- defaultModelId: "anthropic/claude-haiku-5.5",
+ defaultModelId: "google/gemini-4-argon",
apiKeyEnv: ["OFOX_API_KEY"],
docsUrl: "https://ofox.ai/docs",
defaults: {
@@ -1891,7 +1905,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "ollama",
- defaultModelId: "mistral-large-4",
+ defaultModelId: "muse-spark-open",
apiKeyEnv: ["OLLAMA_API_KEY"],
docsUrl: "https://docs.ollama.com/cloud",
defaults: {
@@ -1916,7 +1930,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "opencode",
- defaultModelId: "cat-jam-free",
+ defaultModelId: "nemotron-3.5-super-vl-free",
apiKeyEnv: ["OPENCODE_API_KEY"],
docsUrl: "https://opencode.ai/v2/docs/console/models/",
defaults: {
@@ -1930,7 +1944,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "opencode-go",
- defaultModelId: "claude-haiku-5-5",
+ defaultModelId: "gemini-4-argon-contributor",
apiKeyEnv: ["OPENCODE_API_KEY"],
docsUrl: "https://opencode.ai/v2/docs/console/go/",
defaults: {
@@ -1958,7 +1972,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "openrouter",
- defaultModelId: "meta/muse-wonder",
+ defaultModelId: "meta/muse-spark-open",
apiKeyEnv: ["OPENROUTER_API_KEY"],
docsUrl: "https://openrouter.ai/models",
defaults: {
@@ -2070,7 +2084,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "poe",
- defaultModelId: "anthropic/claude-opus-4.8",
+ defaultModelId: "google/gemini-3.8-flash",
apiKeyEnv: ["POE_API_KEY"],
docsUrl:
"https://creator.poe.com/docs/external-applications/openai-compatible-api",
@@ -2099,7 +2113,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "prime",
- defaultModelId: "openai/gpt-6.1-sol",
+ defaultModelId: "google/gemini-4-argon",
apiKeyEnv: ["PRIME_API_KEY"],
docsUrl: "https://docs.primeintellect.ai/inference/overview",
defaults: {
@@ -2169,7 +2183,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "requesty",
- defaultModelId: "claude-haiku-5-5",
+ defaultModelId: "muse-spark-open",
apiKeyEnv: ["REQUESTY_API_KEY"],
docsUrl: "https://requesty.ai/solution/llm-routing/models",
defaults: {
@@ -2218,6 +2232,21 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
baseUrl: "https://api.sakana.ai/v1",
},
},
+ {
+ id: "sambanova",
+ name: "SambaNova",
+ description: "SambaNova model provider from models.dev",
+ family: "openai-compatible",
+ capabilities: ["tools", "reasoning", "prompt-cache"],
+ modelsProviderId: "sambanova",
+ defaultModelId: "MiniMax-M3",
+ apiKeyEnv: ["SAMBANOVA_API_KEY"],
+ docsUrl:
+ "https://docs.sambanova.ai/cloud/docs/get-started/supported-models",
+ defaults: {
+ baseUrl: "https://api.sambanova.ai/v1",
+ },
+ },
{
id: "sapaicore",
name: "SAP AI Core",
@@ -2250,7 +2279,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "scaleway",
- defaultModelId: "qwen3.8-27b",
+ defaultModelId: "glm-5.3",
apiKeyEnv: ["SCALEWAY_API_KEY"],
docsUrl: "https://www.scaleway.com/en/docs/generative-apis/",
defaults: {
@@ -2293,7 +2322,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning"],
modelsProviderId: "sensenova",
- defaultModelId: "deepseek-v4-pro",
+ defaultModelId: "deepseek-v4.1-flash",
apiKeyEnv: ["SENSENOVA_API_KEY"],
docsUrl: "https://platform.sensenova.cn/docs",
defaults: {
@@ -2360,6 +2389,20 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
"https://api.openai-compat.model-serving.eu01.onstackit.cloud/v1",
},
},
+ {
+ id: "standardcompute",
+ name: "Standard Compute",
+ description: "Standard Compute model provider from models.dev",
+ family: "openai-compatible",
+ capabilities: ["tools", "reasoning"],
+ modelsProviderId: "standardcompute",
+ defaultModelId: "standardcompute",
+ apiKeyEnv: ["STANDARDCOMPUTE_API_KEY"],
+ docsUrl: "https://docs.standardcompute.com/models",
+ defaults: {
+ baseUrl: "https://api.stdcmpt.com/v1",
+ },
+ },
{
id: "stepfun",
name: "StepFun (China)",
@@ -2704,7 +2747,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "vercel-ai-gateway",
- defaultModelId: "meta/muse-wonder-1.0",
+ defaultModelId: "meta/muse-spark-open",
apiKeyEnv: ["AI_GATEWAY_API_KEY"],
docsUrl:
"https://github.com/vercel/ai/tree/5eb85cc45a259553501f535b8ac79a77d0e79223/packages/gateway",
@@ -2716,7 +2759,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "vertex",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "vertex",
- defaultModelId: "claude-haiku-5-5@default",
+ defaultModelId: "gemini-4-argon",
apiKeyEnv: [
"GOOGLE_VERTEX_PROJECT",
"GOOGLE_VERTEX_LOCATION",
@@ -2829,7 +2872,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "wandb",
- defaultModelId: "deepseek-ai/DeepSeek-V4.1-Flash",
+ defaultModelId: "nvidia/NVIDIA-Nemotron-3.5-Super-VL-120B-A12B",
apiKeyEnv: ["WANDB_API_KEY"],
docsUrl: "https://docs.wandb.ai/inference",
defaults: {
diff --git a/sdk/packages/sdk/package.json b/sdk/packages/sdk/package.json
index 2685d9d86b..ff853c6dbc 100644
--- a/sdk/packages/sdk/package.json
+++ b/sdk/packages/sdk/package.json
@@ -1,7 +1,7 @@
{
"name": "@cline/sdk",
"description": "Cline SDK - user-facing alias for @cline/core",
- "version": "0.0.93",
+ "version": "0.0.94",
"repository": {
"type": "git",
"url": "https://github.com/cline/cline",
diff --git a/sdk/packages/shared/package.json b/sdk/packages/shared/package.json
index 41226d4f42..053d9b3803 100644
--- a/sdk/packages/shared/package.json
+++ b/sdk/packages/shared/package.json
@@ -1,6 +1,6 @@
{
"name": "@cline/shared",
- "version": "0.0.93",
+ "version": "0.0.94",
"description": "Shared utilities, types, and schemas for Cline packages",
"repository": {
"type": "git",
From cd01a92faac40af398e43cbafecfb31c63dba2ad Mon Sep 17 00:00:00 2001
From: TheRealSpencer <32678829+TheRealSpencer@users.noreply.github.com>
Date: Thu, 15 Oct 2026 23:02:38 -0500
Subject: [PATCH 11/29] security: dependency floor lifts for open Dependabot
advisories (#15132)
---
apps/vscode/package.json | 2 +-
.../runtime-files/package-lock.json | 8 +++---
.../standalone/runtime-files/package.json | 2 +-
bun.lock | 6 ++---
docs/package-lock.json | 27 +++++++++----------
docs/package.json | 5 +++-
package.json | 2 +-
7 files changed, 27 insertions(+), 25 deletions(-)
diff --git a/apps/vscode/package.json b/apps/vscode/package.json
index 44b8202625..3133b8a8a3 100644
--- a/apps/vscode/package.json
+++ b/apps/vscode/package.json
@@ -496,7 +496,7 @@
"@vscode/codicons": "^0.0.36",
"archiver": "^7.0.1",
"aws4fetch": "^1.0.20",
- "axios": "1.18.0",
+ "axios": "1.20.0",
"better-sqlite3": "^12.4.1",
"cheerio": "^1.0.0",
"chokidar": "^4.0.1",
diff --git a/apps/vscode/standalone/runtime-files/package-lock.json b/apps/vscode/standalone/runtime-files/package-lock.json
index 6c44527a06..462fd66149 100644
--- a/apps/vscode/standalone/runtime-files/package-lock.json
+++ b/apps/vscode/standalone/runtime-files/package-lock.json
@@ -8,7 +8,7 @@
"name": "cline-core",
"version": "0.0.1",
"dependencies": {
- "@grpc/grpc-js": "^1.13.3",
+ "@grpc/grpc-js": "~1.13.6",
"@grpc/reflection": "^1.0.4",
"better-sqlite3": "^12.4.1",
"grpc-health-check": "^2.0.2",
@@ -17,9 +17,9 @@
}
},
"node_modules/@grpc/grpc-js": {
- "version": "1.13.3",
- "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.13.3.tgz",
- "integrity": "sha512-FTXHdOoPbZrBjlVLHuKbDZnsTxXv2BlHF57xw6LuThXacXvtkahEPED0CKMk6obZDf65Hv4k3z62eyPNpvinIg==",
+ "version": "1.13.7",
+ "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.13.7.tgz",
+ "integrity": "sha512-Q6KuzM6QCvNbVWOxf9gHCedUUByhVWsfg6QTN/Jk0KJooG5WfJC3HkHDiVGjCmQFo6mhovEX+8B4phpIOaCr/A==",
"license": "Apache-2.0",
"dependencies": {
"@grpc/proto-loader": "^0.7.13",
diff --git a/apps/vscode/standalone/runtime-files/package.json b/apps/vscode/standalone/runtime-files/package.json
index e27103d065..e7661c3649 100644
--- a/apps/vscode/standalone/runtime-files/package.json
+++ b/apps/vscode/standalone/runtime-files/package.json
@@ -3,7 +3,7 @@
"version": "0.0.1",
"main": "cline-core.js",
"dependencies": {
- "@grpc/grpc-js": "^1.13.3",
+ "@grpc/grpc-js": "~1.13.6",
"@grpc/reflection": "^1.0.4",
"better-sqlite3": "^12.4.1",
"grpc-health-check": "^2.0.2",
diff --git a/bun.lock b/bun.lock
index f65a6ebca9..460ce193eb 100644
--- a/bun.lock
+++ b/bun.lock
@@ -400,7 +400,7 @@
"@vscode/codicons": "^0.0.36",
"archiver": "^7.0.1",
"aws4fetch": "^1.0.20",
- "axios": "1.18.0",
+ "axios": "1.20.0",
"better-sqlite3": "^12.4.1",
"cheerio": "^1.0.0",
"chokidar": "^4.0.1",
@@ -836,7 +836,7 @@
"@sap-cloud-sdk/openapi": "4.9.1",
"@sap-cloud-sdk/resilience": "4.9.1",
"@sap-cloud-sdk/util": "4.9.1",
- "axios": "1.18.0",
+ "axios": "1.20.0",
"diff": "8.0.4",
"fast-uri": ">=3.1.4",
"js-yaml": ">=4.3.2 <5",
@@ -2872,7 +2872,7 @@
"axe-core": ["axe-core@4.13.0", "", {}, "sha512-UzGt8zg7Ny8djbYMhxl2zuEevVa7r2gJjYY5Lwr1xM7+XU2nd6CkIWFTVcCIbAP63vSz71NaVyyuSk9lHKcy0A=="],
- "axios": ["axios@1.18.0", "", { "dependencies": { "follow-redirects": "^1.16.0", "form-data": "^4.0.5", "https-proxy-agent": "^5.0.1", "proxy-from-env": "^2.1.0" } }, "sha512-E32NzpYKp++W7XRe52rHiXV2ehxmh3wbdgO7MHeFM+vqxLBYHzt0ElkiImtOBxtOmyp0yoC8C6uESVV84Y2/hw=="],
+ "axios": ["axios@1.20.0", "", { "dependencies": { "follow-redirects": "^1.16.0", "form-data": "^4.0.6", "https-proxy-agent": "^5.0.1", "proxy-from-env": "^2.1.0" } }, "sha512-r8aOh8j9cGKpgQAqpzrUHnSIc6a59Y3Xf/cv8sy1DrHCkZHzQGEuoq1tARk6qSyDdtQGSDgpb9kFlruzPvrgwg=="],
"azure-devops-node-api": ["azure-devops-node-api@12.5.0", "", { "dependencies": { "tunnel": "0.0.6", "typed-rest-client": "^1.8.4" } }, "sha512-R5eFskGvOm3U/GzeAuxRkUsAl0hrAwGgWn6zAd2KrZmrEhWZVqLew4OOupbQlXUuojUzpGtq62SmdhJ06N88og=="],
diff --git a/docs/package-lock.json b/docs/package-lock.json
index b5c932ce68..fb378f2969 100644
--- a/docs/package-lock.json
+++ b/docs/package-lock.json
@@ -3185,13 +3185,13 @@
}
},
"node_modules/axios": {
- "version": "1.18.0",
- "resolved": "https://registry.npmjs.org/axios/-/axios-1.18.0.tgz",
- "integrity": "sha512-E32NzpYKp++W7XRe52rHiXV2ehxmh3wbdgO7MHeFM+vqxLBYHzt0ElkiImtOBxtOmyp0yoC8C6uESVV84Y2/hw==",
+ "version": "1.20.0",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.20.0.tgz",
+ "integrity": "sha512-r8aOh8j9cGKpgQAqpzrUHnSIc6a59Y3Xf/cv8sy1DrHCkZHzQGEuoq1tARk6qSyDdtQGSDgpb9kFlruzPvrgwg==",
"license": "MIT",
"dependencies": {
"follow-redirects": "^1.16.0",
- "form-data": "^4.0.5",
+ "form-data": "^4.0.6",
"https-proxy-agent": "^5.0.1",
"proxy-from-env": "^2.1.0"
}
@@ -3400,9 +3400,9 @@
"license": "MIT"
},
"node_modules/brace-expansion": {
- "version": "1.1.18",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz",
- "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==",
+ "version": "1.1.21",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz",
+ "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0",
@@ -4476,16 +4476,15 @@
}
},
"node_modules/engine.io": {
- "version": "6.6.9",
- "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.9.tgz",
- "integrity": "sha512-clKkw4C7nJ22mGgoVcCg6V/W/TxdNyIOTr89k2ONZu81qqkddPFDF0LXcbAwhzPD8DjkiRCjzuiO6Y+fkpD4vg==",
+ "version": "6.6.11",
+ "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.11.tgz",
+ "integrity": "sha512-z34mGpLoY/82ZbkX1LqGMIaf3wjVMPL6gVC681QDqnmzJ26synI8qAE32P+a7UazmpJZ8UGrFIeAavgRfXzYrg==",
"license": "MIT",
"dependencies": {
"@types/cors": "^2.8.12",
"@types/node": ">=10.0.0",
"@types/ws": "^8.5.12",
"accepts": "~1.3.4",
- "base64id": "2.0.0",
"cookie": "~0.7.2",
"cors": "~2.8.5",
"debug": "~4.4.1",
@@ -6432,9 +6431,9 @@
}
},
"node_modules/ip-address": {
- "version": "10.4.0",
- "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.4.0.tgz",
- "integrity": "sha512-oSK96Grm3aP6OrS263xVxbNDGVL7rzBtYdpGqlDG8iQdoenDoTs/nkki+DflYbAEE8Xl6o5YxhxlrKvI3nqKXQ==",
+ "version": "10.7.4",
+ "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.7.4.tgz",
+ "integrity": "sha512-DWBMKyeM25D70nrIiTkgQth59/G+naKOTep6huF9j+GmeK3DMD60Zvxg5d5qQnz+38AHgou6ean2LECX+lrKDg==",
"license": "MIT",
"engines": {
"node": ">= 12"
diff --git a/docs/package.json b/docs/package.json
index ad1f926d0a..0e3fd63482 100644
--- a/docs/package.json
+++ b/docs/package.json
@@ -20,7 +20,10 @@
"js-yaml": ">=4.3.2 <5",
"tar": ">=7.5.21",
"body-parser@<1.20.6": "1.20.6",
- "axios@<1.18.0": "1.18.0",
+ "axios": ">=1.20.0 <2",
+ "engine.io": ">=6.6.10 <7",
+ "brace-expansion@<2": "1.1.21",
+ "ip-address": ">=10.7.1 <11",
"qs": ">=6.15.2",
"express@<=4.20.0": "4.20.0",
"serve-static@<=1.16.0": "1.16.0",
diff --git a/package.json b/package.json
index ef6799c8aa..a0f5c16fde 100644
--- a/package.json
+++ b/package.json
@@ -66,7 +66,7 @@
"typescript": "^5.9.3"
},
"overrides": {
- "axios": "1.18.0",
+ "axios": "1.20.0",
"fast-uri": ">=3.1.4",
"undici": ">=7.29.0 <8",
"@opentui/core": "0.4.3",
From 1faa00fa25380de5e98f0ad1b48f597f790f3cb5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Miko=C5=82aj=20Kondratek?=
<19799111+mkondratek@users.noreply.github.com>
Date: Fri, 16 Oct 2026 07:13:55 +0200
Subject: [PATCH 12/29] fix(webview): use editor-neutral wording in Cloud
sessions copy (#15123)
The webview is shared with the JetBrains plugin, where "after you close
VS Code" is wrong. Say "your editor" instead in the onboarding/GitHub
cards, the Run task hint and the cloud auto-approve tooltip.
---
.../src/components/chat/auto-approve-menu/AutoApproveBar.tsx | 2 +-
apps/vscode/webview-ui/src/components/cloud/CloudGitHubCard.tsx | 2 +-
.../webview-ui/src/components/cloud/CloudOnboardingCard.tsx | 2 +-
apps/vscode/webview-ui/src/components/cloud/TaskTargetPanel.tsx | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/apps/vscode/webview-ui/src/components/chat/auto-approve-menu/AutoApproveBar.tsx b/apps/vscode/webview-ui/src/components/chat/auto-approve-menu/AutoApproveBar.tsx
index 779f42977f..cf1df577d9 100644
--- a/apps/vscode/webview-ui/src/components/chat/auto-approve-menu/AutoApproveBar.tsx
+++ b/apps/vscode/webview-ui/src/components/chat/auto-approve-menu/AutoApproveBar.tsx
@@ -12,7 +12,7 @@ interface AutoApproveBarProps {
}
export const CLOUD_AUTO_APPROVE_TOOLTIP =
- "Cloud sessions always auto-approve actions so they can continue running when VS Code is closed. Your local auto-approve settings are unchanged."
+ "Cloud sessions always auto-approve actions so they can continue running when your editor is closed. Your local auto-approve settings are unchanged."
const AutoApproveBar = ({ style, cloudAutoApprove = false }: AutoApproveBarProps) => {
const { autoApprovalSettings } = useExtensionState()
diff --git a/apps/vscode/webview-ui/src/components/cloud/CloudGitHubCard.tsx b/apps/vscode/webview-ui/src/components/cloud/CloudGitHubCard.tsx
index 7325a96da0..1aed431c70 100644
--- a/apps/vscode/webview-ui/src/components/cloud/CloudGitHubCard.tsx
+++ b/apps/vscode/webview-ui/src/components/cloud/CloudGitHubCard.tsx
@@ -63,7 +63,7 @@ export function CloudGitHubCard() {
) : (
- Connect GitHub to run tasks in isolated cloud sandboxes that keep working after you close VS Code.
+ Connect GitHub to run tasks in isolated cloud sandboxes that keep working after you close your editor.
)}
diff --git a/apps/vscode/webview-ui/src/components/cloud/CloudOnboardingCard.tsx b/apps/vscode/webview-ui/src/components/cloud/CloudOnboardingCard.tsx
index 3dfd004657..5dca92360e 100644
--- a/apps/vscode/webview-ui/src/components/cloud/CloudOnboardingCard.tsx
+++ b/apps/vscode/webview-ui/src/components/cloud/CloudOnboardingCard.tsx
@@ -59,7 +59,7 @@ export function CloudOnboardingCard({
Cloud sessions run in an isolated sandbox on Cline's infrastructure. Cline clones your repository, works on a
- branch, and keeps going after you close VS Code.
+ branch, and keeps going after you close your editor.
diff --git a/apps/vscode/webview-ui/src/components/cloud/TaskTargetPanel.tsx b/apps/vscode/webview-ui/src/components/cloud/TaskTargetPanel.tsx
index 9d0b48b856..53cddf207d 100644
--- a/apps/vscode/webview-ui/src/components/cloud/TaskTargetPanel.tsx
+++ b/apps/vscode/webview-ui/src/components/cloud/TaskTargetPanel.tsx
@@ -201,7 +201,7 @@ export function TaskTargetPanel() {
>
) : (
- "Uses a Cline model and Cline credits in an isolated sandbox. Tools are auto-approved so the task can keep going after you close VS Code."
+ "Uses a Cline model and Cline credits in an isolated sandbox. Tools are auto-approved so the task can keep going after you close your editor."
)}
From d9deb814e8a7fe5d97cd6217dcb431cc06952e4a Mon Sep 17 00:00:00 2001
From: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
Date: Thu, 15 Oct 2026 22:25:34 -0700
Subject: [PATCH 13/29] chore(cli): release v3.0.72
---
apps/cli/CHANGELOG.md | 10 ++++++++++
apps/cli/package.json | 2 +-
bun.lock | 2 +-
3 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/apps/cli/CHANGELOG.md b/apps/cli/CHANGELOG.md
index d1ba8a4b4f..34dc05ac1d 100644
--- a/apps/cli/CHANGELOG.md
+++ b/apps/cli/CHANGELOG.md
@@ -1,5 +1,15 @@
# Cline CLI Changelog
+## 3.0.72
+
+- Plugins now run in a worker instead of directly inside the hub. If this build can't run plugins, Cline says so in `cline config tools`, `cline hub plugins`, and the session-start warnings instead of quietly running them inside the hub. `CLINE_PLUGIN_MODE=in_process` is no longer supported; use `worker` (the default) or `sandbox`
+- When a provider error interrupts a response mid-stream, Cline retries it up to 3 times before failing the turn
+- Failed model requests now log the provider's request id, which makes support tickets easier to trace
+- `cline hub ensure` and `cline hub start` gain `--json` (prints the hub URL and auth token), `--allow-port-fallback`, `--no-connectors`, and `--login-shell-path`. `cline hub` accepts `--discovery-path` to use a dedicated discovery record
+- `cline hub` commands no longer count as a CLI activation in usage stats
+- With no model chosen, the Cline provider now uses Gemini 4 Argon, the new first model in Cline's recommended list
+- Refreshed the model catalog. Adds the Boundless and Standard Compute providers, and SambaNova now comes from the catalog with MiniMax M3 as its default. The Cline recommended list adds Gemini 4 Argon and drops Grok 4.7, and the Cline free list replaces Step 5 Preview with Nemotron 3.5 Super VL. OpenCode Go no longer lists MiniMax M2.7. Default models change for Cortecs, CrossModel, Eden AI, Google Gemini, GitHub Copilot, Google Vertex AI, LLM Gateway, Ofox, OpenCode Go, and Prime Inference (Gemini 4 Argon), Fireworks AI, Nebius Token Factory, and Requesty (Muse Spark Open), CoreWeave, DigitalOcean, NanoGPT, and Nvidia (Nemotron 3.5 Super VL), Aixy and Neon (Claude Haiku 5.5), Agnes AI, Ambient, IteraCompute, Poe, Scaleway, and SenseNova
+
## 3.0.71
- Plugins now load inside the hub instead of a separate node or bun process, so the CLI no longer needs a JavaScript runtime on your PATH to run plugins. A plugin that fails to load no longer silently loses its tools: Cline prints a warning naming the plugin and the error, `cline config tools --json` lists it as a `plugin_failure` entry, and the new `cline hub plugins` shows each plugin's status and last error (`--reload ` re-imports one without restarting the hub). Set `CLINE_PLUGIN_MODE=sandbox` to keep the old subprocess behavior
diff --git a/apps/cli/package.json b/apps/cli/package.json
index 19858fe73a..490c623c4f 100644
--- a/apps/cli/package.json
+++ b/apps/cli/package.json
@@ -1,7 +1,7 @@
{
"name": "@cline/cli",
"displayName": "cline",
- "version": "3.0.71",
+ "version": "3.0.72",
"description": "Autonomous coding agent CLI - capable of creating/editing files, running commands, using the browser, and more",
"type": "module",
"publishConfig": {
diff --git a/bun.lock b/bun.lock
index 460ce193eb..fa684903b7 100644
--- a/bun.lock
+++ b/bun.lock
@@ -19,7 +19,7 @@
},
"apps/cli": {
"name": "@cline/cli",
- "version": "3.0.71",
+ "version": "3.0.72",
"bin": {
"cline": "src/index.ts",
},
From 9098d603ccb10f7f04889dcec9223e6bbcbe9600 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Miko=C5=82aj=20Kondratek?=
<19799111+mkondratek@users.noreply.github.com>
Date: Fri, 16 Oct 2026 08:06:59 +0200
Subject: [PATCH 14/29] feat(webview): name the host editor in Cloud sessions
copy (#15133)
* feat(webview): name the host editor in Cloud sessions copy
The Cloud sessions copy said "your editor". Name the editor the user is
actually in instead: "VS Code", "Cursor", "PyCharm" and so on.
The extension already gets the product name from the host bridge
(getHostVersion's platform); fetch it once and pass it to the webview as
hostName. The webview shortens it the way users say it (drops the
JetBrains edition, "Visual Studio Code" -> "VS Code") and falls back to
"your editor" when the host is unknown.
* fix: read the host name from HostRegistryInfo instead of a bridge call
HostRegistryInfo already holds getHostVersion's platform from startup, so
building webview state no longer waits on the host bridge. The tooltip
test now asserts the visible text instead of reusing the function it tests.
* fix(webview): fall back to "your IDE" when the host is unknown
---
.../state/getStateToPostToWebview.ts | 5 ++++-
apps/vscode/src/shared/ExtensionMessage.ts | 2 ++
.../auto-approve-menu/AutoApproveBar.test.tsx | 8 +++----
.../chat/auto-approve-menu/AutoApproveBar.tsx | 9 ++++----
.../src/components/cloud/CloudGitHubCard.tsx | 6 ++++-
.../components/cloud/CloudOnboardingCard.tsx | 5 ++++-
.../components/cloud/TaskTargetPanel.test.tsx | 12 +++++++++-
.../src/components/cloud/TaskTargetPanel.tsx | 7 ++++--
.../src/utils/__tests__/editorName.spec.ts | 22 +++++++++++++++++++
.../vscode/webview-ui/src/utils/editorName.ts | 16 ++++++++++++++
10 files changed, 78 insertions(+), 14 deletions(-)
create mode 100644 apps/vscode/webview-ui/src/utils/__tests__/editorName.spec.ts
create mode 100644 apps/vscode/webview-ui/src/utils/editorName.ts
diff --git a/apps/vscode/src/core/controller/state/getStateToPostToWebview.ts b/apps/vscode/src/core/controller/state/getStateToPostToWebview.ts
index b9a7cfb587..cd5f2099fb 100644
--- a/apps/vscode/src/core/controller/state/getStateToPostToWebview.ts
+++ b/apps/vscode/src/core/controller/state/getStateToPostToWebview.ts
@@ -8,7 +8,7 @@ import { isModelToolEnabledGlobally, readCompactionStrategyGlobally } from "@cli
import { getHooksEnabledSafe } from "@core/hooks/hooks-utils"
import type { ExtensionState, Platform } from "@shared/ExtensionMessage"
import { ClineEnv } from "@/config"
-import { ExtensionRegistryInfo } from "@/registry"
+import { ExtensionRegistryInfo, HostRegistryInfo } from "@/registry"
import { BannerService } from "@/services/banner/BannerService"
import { featureFlagsService } from "@/services/feature-flags"
import { getDistinctId } from "@/services/logging/distinctId"
@@ -98,6 +98,8 @@ export async function getStateToPostToWebview(controller: {
const version = ExtensionRegistryInfo.version
const clineConfig = ClineEnv.config()
const environment = clineConfig.environment
+ const hostPlatform = HostRegistryInfo.get()?.platform
+ const hostName = hostPlatform && hostPlatform !== "unknown" ? hostPlatform : undefined
const banners = BannerService.get().getActiveBanners() ?? []
const welcomeBanners = BannerService.get().getWelcomeBanners() ?? []
@@ -133,6 +135,7 @@ export async function getStateToPostToWebview(controller: {
enableCheckpointsSetting: enableCheckpointsSetting ?? true,
platform,
environment,
+ hostName,
distinctId,
globalClineRulesToggles: globalClineRulesToggles || {},
localClineRulesToggles: localClineRulesToggles || {},
diff --git a/apps/vscode/src/shared/ExtensionMessage.ts b/apps/vscode/src/shared/ExtensionMessage.ts
index 7221447950..0569fcc7fe 100644
--- a/apps/vscode/src/shared/ExtensionMessage.ts
+++ b/apps/vscode/src/shared/ExtensionMessage.ts
@@ -86,6 +86,8 @@ export interface ExtensionState {
enableCheckpointsSetting?: boolean
platform: Platform
environment?: Environment
+ /** The editor Cline runs in, as the host reports it ("Visual Studio Code", "Cursor", "PyCharm Professional"). */
+ hostName?: string
shouldShowAnnouncement: boolean
taskHistory: HistoryItem[]
telemetrySetting: TelemetrySetting
diff --git a/apps/vscode/webview-ui/src/components/chat/auto-approve-menu/AutoApproveBar.test.tsx b/apps/vscode/webview-ui/src/components/chat/auto-approve-menu/AutoApproveBar.test.tsx
index 362de85bfd..98ba38b72f 100644
--- a/apps/vscode/webview-ui/src/components/chat/auto-approve-menu/AutoApproveBar.test.tsx
+++ b/apps/vscode/webview-ui/src/components/chat/auto-approve-menu/AutoApproveBar.test.tsx
@@ -2,7 +2,7 @@ import { fireEvent, render, screen } from "@testing-library/react"
import userEvent from "@testing-library/user-event"
import type React from "react"
import { beforeEach, describe, expect, it, vi } from "vitest"
-import AutoApproveBar, { CLOUD_AUTO_APPROVE_TOOLTIP } from "./AutoApproveBar"
+import AutoApproveBar from "./AutoApproveBar"
vi.mock("@vscode/webview-ui-toolkit/react", () => ({
VSCodeCheckbox: ({ checked, children, disabled }: { checked: boolean; children: React.ReactNode; disabled: boolean }) => (
@@ -33,7 +33,7 @@ const mocks = vi.hoisted(() => ({
}))
vi.mock("@/context/ExtensionStateContext", () => ({
- useExtensionState: () => ({ autoApprovalSettings: mocks.autoApprovalSettings }),
+ useExtensionState: () => ({ autoApprovalSettings: mocks.autoApprovalSettings, hostName: "PyCharm Professional" }),
}))
vi.mock("./AutoApproveSettingsAPI", () => ({
@@ -61,7 +61,7 @@ describe("AutoApproveBar", () => {
expect(trigger).toHaveTextContent("Auto-approve:Read, Edit, Commands, Web Fetch, MCP")
await user.hover(trigger)
- expect(await screen.findByText(CLOUD_AUTO_APPROVE_TOOLTIP)).toBeInTheDocument()
+ expect(await screen.findByText(/when PyCharm is closed\./)).toBeInTheDocument()
fireEvent.click(trigger)
expect(
@@ -81,7 +81,7 @@ describe("AutoApproveBar", () => {
fireEvent.click(screen.getByLabelText("Close auto-approve settings"))
rerender()
expect(screen.getByLabelText("Open auto-approve settings")).toHaveTextContent("Auto-approve:Read")
- expect(screen.queryByText(CLOUD_AUTO_APPROVE_TOOLTIP)).not.toBeInTheDocument()
+ expect(screen.queryByText(/when PyCharm is closed\./)).not.toBeInTheDocument()
expect(mocks.autoApprovalSettings).toEqual(localSettings)
})
})
diff --git a/apps/vscode/webview-ui/src/components/chat/auto-approve-menu/AutoApproveBar.tsx b/apps/vscode/webview-ui/src/components/chat/auto-approve-menu/AutoApproveBar.tsx
index cf1df577d9..4674b3db46 100644
--- a/apps/vscode/webview-ui/src/components/chat/auto-approve-menu/AutoApproveBar.tsx
+++ b/apps/vscode/webview-ui/src/components/chat/auto-approve-menu/AutoApproveBar.tsx
@@ -2,6 +2,7 @@ import { ChevronDownIcon, ChevronRightIcon } from "lucide-react"
import { useRef, useState } from "react"
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
import { useExtensionState } from "@/context/ExtensionStateContext"
+import { editorName } from "@/utils/editorName"
import { getAsVar, VSC_TITLEBAR_INACTIVE_FOREGROUND } from "@/utils/vscStyles"
import AutoApproveModal from "./AutoApproveModal"
import { ACTION_METADATA } from "./constants"
@@ -11,11 +12,11 @@ interface AutoApproveBarProps {
cloudAutoApprove?: boolean
}
-export const CLOUD_AUTO_APPROVE_TOOLTIP =
- "Cloud sessions always auto-approve actions so they can continue running when your editor is closed. Your local auto-approve settings are unchanged."
+const cloudAutoApproveTooltip = (editor: string) =>
+ `Cloud sessions always auto-approve actions so they can continue running when ${editor} is closed. Your local auto-approve settings are unchanged.`
const AutoApproveBar = ({ style, cloudAutoApprove = false }: AutoApproveBarProps) => {
- const { autoApprovalSettings } = useExtensionState()
+ const { autoApprovalSettings, hostName } = useExtensionState()
const [isModalVisible, setIsModalVisible] = useState(false)
const buttonRef = useRef(null)
@@ -121,7 +122,7 @@ const AutoApproveBar = ({ style, cloudAutoApprove = false }: AutoApproveBarProps
{isModalVisible ? : }
- {cloudAutoApprove && {CLOUD_AUTO_APPROVE_TOOLTIP}}
+ {cloudAutoApprove && {cloudAutoApproveTooltip(editorName(hostName))}}
) : (
- Connect GitHub to run tasks in isolated cloud sandboxes that keep working after you close your editor.
+ Connect GitHub to run tasks in isolated cloud sandboxes that keep working after you close{" "}
+ {editorName(hostName)}.
)}
diff --git a/apps/vscode/webview-ui/src/components/cloud/CloudOnboardingCard.tsx b/apps/vscode/webview-ui/src/components/cloud/CloudOnboardingCard.tsx
index 5dca92360e..cac000331d 100644
--- a/apps/vscode/webview-ui/src/components/cloud/CloudOnboardingCard.tsx
+++ b/apps/vscode/webview-ui/src/components/cloud/CloudOnboardingCard.tsx
@@ -19,6 +19,7 @@ export function CloudOnboardingCard({
checking = false,
waiting = false,
errorMessage,
+ editor,
}: {
variant: CloudOnboardingVariant
onConnect: () => void
@@ -28,6 +29,8 @@ export function CloudOnboardingCard({
/** True after the user opened the connect flow and we are polling for completion. */
waiting?: boolean
errorMessage?: string
+ /** How the copy names the editor, e.g. "PyCharm" or "your IDE". */
+ editor: string
}) {
if (variant === "error") {
return (
@@ -59,7 +62,7 @@ export function CloudOnboardingCard({
Cloud sessions run in an isolated sandbox on Cline's infrastructure. Cline clones your repository, works on a
- branch, and keeps going after you close your editor.
+ branch, and keeps going after you close {editor}.
diff --git a/apps/vscode/webview-ui/src/components/cloud/TaskTargetPanel.test.tsx b/apps/vscode/webview-ui/src/components/cloud/TaskTargetPanel.test.tsx
index 4193243fbf..3ac972f5a7 100644
--- a/apps/vscode/webview-ui/src/components/cloud/TaskTargetPanel.test.tsx
+++ b/apps/vscode/webview-ui/src/components/cloud/TaskTargetPanel.test.tsx
@@ -12,6 +12,7 @@ const mocks = vi.hoisted(() => ({
workspaceRepoUrl?: string
},
clineUser: undefined as { uid: string } | undefined,
+ hostName: undefined as string | undefined,
connection: undefined as
| {
signedIn: boolean
@@ -26,7 +27,7 @@ const mocks = vi.hoisted(() => ({
}))
vi.mock("@/context/ExtensionStateContext", () => ({
- useExtensionState: () => ({ cloudTaskTarget: mocks.cloudTaskTarget }),
+ useExtensionState: () => ({ cloudTaskTarget: mocks.cloudTaskTarget, hostName: mocks.hostName }),
}))
vi.mock("@/context/ClineAuthContext", () => ({
@@ -63,6 +64,7 @@ describe("TaskTargetPanel", () => {
)
mocks.cloudTaskTarget = { target: "cloud" }
mocks.clineUser = undefined
+ mocks.hostName = undefined
mocks.connection = undefined
mocks.getRepositoryBranches.mockResolvedValue({ branches: [] })
mocks.chooseCloudTaskTarget.mockResolvedValue({})
@@ -75,6 +77,14 @@ describe("TaskTargetPanel", () => {
expect(screen.getByRole("button", { name: /Sign in to Cline/i })).toBeInTheDocument()
})
+ it("names the host editor in the onboarding copy", async () => {
+ mocks.hostName = "PyCharm Professional"
+
+ render()
+
+ expect(await screen.findByText(/keeps going after you close PyCharm\./)).toBeInTheDocument()
+ })
+
it("shows repository onboarding when GitHub has no accessible repositories", async () => {
mocks.clineUser = { uid: "user-1" }
mocks.connection = { signedIn: true, connected: true, connectUrl: "", repositories: [] }
diff --git a/apps/vscode/webview-ui/src/components/cloud/TaskTargetPanel.tsx b/apps/vscode/webview-ui/src/components/cloud/TaskTargetPanel.tsx
index 53cddf207d..74beec37fb 100644
--- a/apps/vscode/webview-ui/src/components/cloud/TaskTargetPanel.tsx
+++ b/apps/vscode/webview-ui/src/components/cloud/TaskTargetPanel.tsx
@@ -8,6 +8,7 @@ import { useExtensionState } from "@/context/ExtensionStateContext"
import { useGitHubConnection } from "@/hooks/useGitHubConnection"
import { cn } from "@/lib/utils"
import { CloudServiceClient } from "@/services/grpc-client"
+import { editorName } from "@/utils/editorName"
import { CloudOnboardingCard, type CloudOnboardingVariant } from "./CloudOnboardingCard"
import { SearchableSelect } from "./SearchableSelect"
@@ -28,7 +29,8 @@ const GITHUB_ICON = (
* itself, so nothing it does in the background can override a click.
*/
export function TaskTargetPanel() {
- const { cloudTaskTarget } = useExtensionState()
+ const { cloudTaskTarget, hostName } = useExtensionState()
+ const editor = editorName(hostName)
const { clineUser } = useClineAuth()
const { handleSignIn } = useClineSignIn()
const signedIn = !!clineUser?.uid
@@ -155,6 +157,7 @@ export function TaskTargetPanel() {
{onboardingVariant ? (
void refresh()}
@@ -201,7 +204,7 @@ export function TaskTargetPanel() {
>
) : (
- "Uses a Cline model and Cline credits in an isolated sandbox. Tools are auto-approved so the task can keep going after you close your editor."
+ `Uses a Cline model and Cline credits in an isolated sandbox. Tools are auto-approved so the task can keep going after you close ${editor}.`
)}
diff --git a/apps/vscode/webview-ui/src/utils/__tests__/editorName.spec.ts b/apps/vscode/webview-ui/src/utils/__tests__/editorName.spec.ts
new file mode 100644
index 0000000000..f2ef1464a4
--- /dev/null
+++ b/apps/vscode/webview-ui/src/utils/__tests__/editorName.spec.ts
@@ -0,0 +1,22 @@
+import { describe, expect, it } from "vitest"
+import { editorName } from "../editorName"
+
+describe("editorName", () => {
+ it.each([
+ ["Visual Studio Code", "VS Code"],
+ ["Visual Studio Code - Insiders", "VS Code Insiders"],
+ ["Cursor", "Cursor"],
+ ["Windsurf", "Windsurf"],
+ ["IntelliJ IDEA Ultimate", "IntelliJ IDEA"],
+ ["PyCharm Professional", "PyCharm"],
+ ["PyCharm Community", "PyCharm"],
+ ["WebStorm", "WebStorm"],
+ ["Android Studio", "Android Studio"],
+ ])("names %s as %s", (hostName, expected) => {
+ expect(editorName(hostName)).toBe(expected)
+ })
+
+ it.each([undefined, "", " "])("falls back to a generic name for %j", (hostName) => {
+ expect(editorName(hostName)).toBe("your IDE")
+ })
+})
diff --git a/apps/vscode/webview-ui/src/utils/editorName.ts b/apps/vscode/webview-ui/src/utils/editorName.ts
new file mode 100644
index 0000000000..c0a018af11
--- /dev/null
+++ b/apps/vscode/webview-ui/src/utils/editorName.ts
@@ -0,0 +1,16 @@
+/**
+ * The editor's name as users say it, for copy like "after you close PyCharm".
+ * Hosts report full product names: VS Code's app name ("Visual Studio Code - Insiders")
+ * and JetBrains products with their edition ("PyCharm Professional"). Forks like Cursor
+ * report their own name. Falls back to "your IDE" when the host is unknown.
+ */
+export function editorName(hostName: string | undefined): string {
+ const name = hostName?.trim()
+ if (!name) {
+ return "your IDE"
+ }
+ return name
+ .replace(/^Visual Studio Code(?: - )?/, "VS Code ")
+ .replace(/ (?:Ultimate|Community|Professional|Educational)(?: Edition)?$/, "")
+ .trim()
+}
From 98a53322f904d9c922bd33444b3ab50f890754e3 Mon Sep 17 00:00:00 2001
From: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
Date: Thu, 15 Oct 2026 22:31:31 -0700
Subject: [PATCH 15/29] chore(desktop): release v0.0.47
---
apps/examples/desktop-app/CHANGELOG.md | 8 ++++++++
apps/examples/desktop-app/package.json | 2 +-
apps/examples/desktop-app/src-tauri/tauri.conf.json | 2 +-
bun.lock | 2 +-
4 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/apps/examples/desktop-app/CHANGELOG.md b/apps/examples/desktop-app/CHANGELOG.md
index f7a96bf6f2..2cf8b83051 100644
--- a/apps/examples/desktop-app/CHANGELOG.md
+++ b/apps/examples/desktop-app/CHANGELOG.md
@@ -1,5 +1,13 @@
# Cline Desktop Changelog
+## 0.0.47
+
+- Marketplace plugins such as goal load again. In 0.0.46 they failed with `Cannot find module '@cline/sdk'` because the packaged app didn't include the SDK packages plugins import
+- The Cloud sessions toggle is gone from Settings. Cloud sessions are on wherever they are available
+- When a provider error interrupts a response mid-stream, Cline retries it up to 3 times before failing the turn
+- The Cline provider's default model is now Gemini 4 Argon, the new first model in Cline's recommended list
+- Refreshed the model catalog. Adds the Boundless and Standard Compute providers, and SambaNova now comes from the catalog with MiniMax M3 as its default. The Cline recommended list adds Gemini 4 Argon and drops Grok 4.7, and the Cline free list replaces Step 5 Preview with Nemotron 3.5 Super VL. OpenCode Go no longer lists MiniMax M2.7. Default models change for Cortecs, CrossModel, Eden AI, Google Gemini, GitHub Copilot, Google Vertex AI, LLM Gateway, Ofox, OpenCode Go, and Prime Inference (Gemini 4 Argon), Fireworks AI, Nebius Token Factory, and Requesty (Muse Spark Open), CoreWeave, DigitalOcean, NanoGPT, and Nvidia (Nemotron 3.5 Super VL), Aixy and Neon (Claude Haiku 5.5), Agnes AI, Ambient, IteraCompute, Poe, Scaleway, and SenseNova
+
## 0.0.46
- A new outline along the left edge of the conversation lists each prompt you sent. Hover a mark to preview the prompt, and click it to jump there
diff --git a/apps/examples/desktop-app/package.json b/apps/examples/desktop-app/package.json
index 6b38488880..6e19a09e38 100644
--- a/apps/examples/desktop-app/package.json
+++ b/apps/examples/desktop-app/package.json
@@ -1,6 +1,6 @@
{
"name": "@cline/code",
- "version": "0.0.46",
+ "version": "0.0.47",
"private": true,
"scripts": {
"build:ui": "bun -F @cline/ui build",
diff --git a/apps/examples/desktop-app/src-tauri/tauri.conf.json b/apps/examples/desktop-app/src-tauri/tauri.conf.json
index 09b6f151b8..c6bda06075 100644
--- a/apps/examples/desktop-app/src-tauri/tauri.conf.json
+++ b/apps/examples/desktop-app/src-tauri/tauri.conf.json
@@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "Cline",
- "version": "0.0.46",
+ "version": "0.0.47",
"identifier": "bot.cline.app",
"build": {
"beforeDevCommand": "bun run build:runtime && bun run dev:web",
diff --git a/bun.lock b/bun.lock
index fa684903b7..941f9f6248 100644
--- a/bun.lock
+++ b/bun.lock
@@ -165,7 +165,7 @@
},
"apps/examples/desktop-app": {
"name": "@cline/code",
- "version": "0.0.46",
+ "version": "0.0.47",
"dependencies": {
"@ai-sdk/gateway": "^4.0.98",
"@ai-sdk/openai": "^4.0.79",
From 01b8a9724da905423e636396d7fb4acdf47796bb Mon Sep 17 00:00:00 2001
From: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
Date: Thu, 15 Oct 2026 23:21:22 -0700
Subject: [PATCH 16/29] chore(vscode): release v4.1.25
---
CHANGELOG.md | 20 ++++++++++++++++++++
apps/vscode/package.json | 2 +-
bun.lock | 2 +-
3 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 56fdcec5c7..7d5b14b515 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,25 @@
# Changelog
+## [4.1.25]
+
+### Added
+
+- Cline Cloud sessions, rolling out gradually: run a task in a hosted sandbox on a GitHub repo and branch you pick. Turn it on in Settings. Cloud tasks show in Recent and History with their status, notify you when they finish, and keep running after you close your editor.
+
+### Changed
+
+- With no model chosen, the Cline provider now uses Gemini 4 Argon, the new first model in Cline's recommended list. OpenRouter stays on Claude Sonnet 5.5.
+- Refreshed the model catalog. Adds the Boundless and Standard Compute providers, and SambaNova now comes from the catalog with MiniMax M3 as its default. The Cline recommended list adds Gemini 4 Argon and drops Grok 4.7, and the Cline free list replaces Step 5 Preview with Nemotron 3.5 Super VL. OpenCode Go no longer lists MiniMax M2.7. Default models change for Cortecs, CrossModel, Eden AI, Google Gemini, GitHub Copilot, Google Vertex AI, LLM Gateway, Ofox, OpenCode Go, and Prime Inference (Gemini 4 Argon), Fireworks AI, Nebius Token Factory, and Requesty (Muse Spark Open), CoreWeave, DigitalOcean, NanoGPT, and Nvidia (Nemotron 3.5 Super VL), Aixy and Neon (Claude Haiku 5.5), Agnes AI, Ambient, IteraCompute, Poe, Scaleway, and SenseNova. If you use one of those providers without pinning a model, expect a different default.
+
+### Fixed
+
+- Long requests to local models (LM Studio, Ollama) no longer fail after 5 minutes of silence with `terminated: BodyTimeoutError` while the server is still processing a large prompt.
+- OpenAI Compatible base URLs are used exactly as entered. A host-only URL like `https://abc.com` used to get `/v1` added silently. Host-only URLs saved by earlier versions get `/v1` added once, so existing setups keep working.
+- Images and files attached to an answer to one of Cline's questions now reach the model instead of being dropped.
+- When a provider error interrupts a response mid-stream, Cline retries it up to 3 times before failing the turn.
+- In JetBrains, the Run task card stays above the Auto-approve bar.
+- Auto Compact and its strategy setting sit together again in Feature settings.
+
## [4.1.24]
### Changed
diff --git a/apps/vscode/package.json b/apps/vscode/package.json
index 3133b8a8a3..794e36be56 100644
--- a/apps/vscode/package.json
+++ b/apps/vscode/package.json
@@ -2,7 +2,7 @@
"name": "claude-dev",
"displayName": "Cline",
"description": "Autonomous coding agent right in your IDE, capable of creating/editing files, running commands, using the browser, and more with your permission every step of the way.",
- "version": "4.1.24",
+ "version": "4.1.25",
"icon": "assets/icons/icon.png",
"engines": {
"vscode": "^1.101.0"
diff --git a/bun.lock b/bun.lock
index 941f9f6248..d6245264ca 100644
--- a/bun.lock
+++ b/bun.lock
@@ -363,7 +363,7 @@
},
"apps/vscode": {
"name": "claude-dev",
- "version": "4.1.24",
+ "version": "4.1.25",
"dependencies": {
"@anthropic-ai/sdk": "^0.37.0",
"@bufbuild/protobuf": "^2.2.5",
From f67e933376d5885b2dbbe511a67aca2038d57f9a Mon Sep 17 00:00:00 2001
From: Bee <68532117+abeatrix@users.noreply.github.com>
Date: Fri, 16 Oct 2026 11:11:53 -0700
Subject: [PATCH 17/29] fix(desktop): bake the OTLP trace exporter into desktop
builds and record who launched the hub (#15135)
---
.github/workflows/desktop-publish.yml | 30 +++++++
.../scripts/desktop-startup.test.ts | 1 +
.../scripts/telemetry-define-args.test.ts | 15 ++++
.../scripts/telemetry-define-args.ts | 8 +-
.../desktop-app/sidecar/cli-runtime.test.ts | 8 +-
.../desktop-app/sidecar/cli-runtime.ts | 13 ++-
sdk/ARCHITECTURE.md | 6 ++
.../core/src/hub/daemon/index.test.ts | 15 ++++
sdk/packages/core/src/hub/daemon/index.ts | 21 ++++-
.../core/src/hub/daemon/telemetry.test.ts | 68 +++++++++++++++-
sdk/packages/core/src/hub/daemon/telemetry.ts | 45 ++++++++++-
.../src/remote/remote-environments.test.ts | 2 +-
.../core/src/remote/remote-environments.ts | 14 ++++
.../telemetry/OpenTelemetryProvider.ts | 8 ++
sdk/packages/shared/src/index.ts | 7 ++
.../shared/src/runtime/hub-daemon-env.test.ts | 74 +++++++++++++++++
.../shared/src/runtime/hub-daemon-env.ts | 80 +++++++++++++++++++
.../src/services/telemetry-selfcheck.test.ts | 9 +++
.../src/services/telemetry-selfcheck.ts | 8 ++
19 files changed, 425 insertions(+), 7 deletions(-)
diff --git a/.github/workflows/desktop-publish.yml b/.github/workflows/desktop-publish.yml
index c0bfb990cb..717b462c0f 100644
--- a/.github/workflows/desktop-publish.yml
+++ b/.github/workflows/desktop-publish.yml
@@ -312,6 +312,8 @@ jobs:
OTEL_TELEMETRY_ENABLED: ${{ secrets.OTEL_TELEMETRY_ENABLED }}
OTEL_LOGS_EXPORTER: otlp
OTEL_METRICS_EXPORTER: otlp
+ OTEL_TRACES_EXPORTER: otlp
+ CLINE_TRACE_RECORD_CONTENT: "true"
OTEL_EXPORTER_OTLP_PROTOCOL: ${{ secrets.OTEL_EXPORTER_OTLP_PROTOCOL }}
OTEL_EXPORTER_OTLP_ENDPOINT: ${{ secrets.OTEL_EXPORTER_OTLP_ENDPOINT }}
OTEL_EXPORTER_OTLP_HEADERS: ${{ secrets.OTEL_EXPORTER_OTLP_HEADERS }}
@@ -346,6 +348,8 @@ jobs:
OTEL_TELEMETRY_ENABLED: ${{ secrets.OTEL_TELEMETRY_ENABLED }}
OTEL_LOGS_EXPORTER: otlp
OTEL_METRICS_EXPORTER: otlp
+ OTEL_TRACES_EXPORTER: otlp
+ CLINE_TRACE_RECORD_CONTENT: "true"
OTEL_EXPORTER_OTLP_PROTOCOL: ${{ secrets.OTEL_EXPORTER_OTLP_PROTOCOL }}
OTEL_EXPORTER_OTLP_ENDPOINT: ${{ secrets.OTEL_EXPORTER_OTLP_ENDPOINT }}
OTEL_EXPORTER_OTLP_HEADERS: ${{ secrets.OTEL_EXPORTER_OTLP_HEADERS }}
@@ -482,6 +486,12 @@ jobs:
echo "OTEL_EXPORTER_OTLP_ENDPOINT secret."
exit 1
fi
+ if ! printf '%s' "$SELFCHECK" | grep -q '"traces_exporter":"otlp"'; then
+ echo "Packaged $COMPONENT has no OTLP traces exporter inlined, so"
+ echo "cline-provider spans would never reach the collector (and"
+ echo "Langfuse). Check OTEL_TRACES_EXPORTER on the build step."
+ exit 1
+ fi
done
# Boot the Cline CLI and desktop backend that will actually ship — built
@@ -681,6 +691,8 @@ jobs:
OTEL_TELEMETRY_ENABLED: ${{ secrets.OTEL_TELEMETRY_ENABLED }}
OTEL_LOGS_EXPORTER: otlp
OTEL_METRICS_EXPORTER: otlp
+ OTEL_TRACES_EXPORTER: otlp
+ CLINE_TRACE_RECORD_CONTENT: "true"
OTEL_EXPORTER_OTLP_PROTOCOL: ${{ secrets.OTEL_EXPORTER_OTLP_PROTOCOL }}
OTEL_EXPORTER_OTLP_ENDPOINT: ${{ secrets.OTEL_EXPORTER_OTLP_ENDPOINT }}
OTEL_EXPORTER_OTLP_HEADERS: ${{ secrets.OTEL_EXPORTER_OTLP_HEADERS }}
@@ -743,6 +755,8 @@ jobs:
OTEL_TELEMETRY_ENABLED: ${{ secrets.OTEL_TELEMETRY_ENABLED }}
OTEL_LOGS_EXPORTER: otlp
OTEL_METRICS_EXPORTER: otlp
+ OTEL_TRACES_EXPORTER: otlp
+ CLINE_TRACE_RECORD_CONTENT: "true"
OTEL_EXPORTER_OTLP_PROTOCOL: ${{ secrets.OTEL_EXPORTER_OTLP_PROTOCOL }}
OTEL_EXPORTER_OTLP_ENDPOINT: ${{ secrets.OTEL_EXPORTER_OTLP_ENDPOINT }}
OTEL_EXPORTER_OTLP_HEADERS: ${{ secrets.OTEL_EXPORTER_OTLP_HEADERS }}
@@ -828,6 +842,12 @@ jobs:
echo "Check the OTEL_EXPORTER_OTLP_ENDPOINT secret."
exit 1
fi
+ if ! printf '%s' "$SELFCHECK" | grep -q '"traces_exporter":"otlp"'; then
+ echo "Packaged $COMPONENT has no OTLP traces exporter inlined, so"
+ echo "cline-provider spans would never reach the collector (and"
+ echo "Langfuse). Check OTEL_TRACES_EXPORTER on the build step."
+ exit 1
+ fi
done
# Same release-time gate as the macOS job; see the comment there.
@@ -1008,6 +1028,8 @@ jobs:
OTEL_TELEMETRY_ENABLED: ${{ secrets.OTEL_TELEMETRY_ENABLED }}
OTEL_LOGS_EXPORTER: otlp
OTEL_METRICS_EXPORTER: otlp
+ OTEL_TRACES_EXPORTER: otlp
+ CLINE_TRACE_RECORD_CONTENT: "true"
OTEL_EXPORTER_OTLP_PROTOCOL: ${{ secrets.OTEL_EXPORTER_OTLP_PROTOCOL }}
OTEL_EXPORTER_OTLP_ENDPOINT: ${{ secrets.OTEL_EXPORTER_OTLP_ENDPOINT }}
OTEL_EXPORTER_OTLP_HEADERS: ${{ secrets.OTEL_EXPORTER_OTLP_HEADERS }}
@@ -1027,6 +1049,8 @@ jobs:
OTEL_TELEMETRY_ENABLED: ${{ secrets.OTEL_TELEMETRY_ENABLED }}
OTEL_LOGS_EXPORTER: otlp
OTEL_METRICS_EXPORTER: otlp
+ OTEL_TRACES_EXPORTER: otlp
+ CLINE_TRACE_RECORD_CONTENT: "true"
OTEL_EXPORTER_OTLP_PROTOCOL: ${{ secrets.OTEL_EXPORTER_OTLP_PROTOCOL }}
OTEL_EXPORTER_OTLP_ENDPOINT: ${{ secrets.OTEL_EXPORTER_OTLP_ENDPOINT }}
OTEL_EXPORTER_OTLP_HEADERS: ${{ secrets.OTEL_EXPORTER_OTLP_HEADERS }}
@@ -1099,6 +1123,12 @@ jobs:
echo "Check the OTEL_EXPORTER_OTLP_ENDPOINT secret."
exit 1
fi
+ if ! printf '%s' "$SELFCHECK" | grep -q '"traces_exporter":"otlp"'; then
+ echo "Packaged $COMPONENT has no OTLP traces exporter inlined, so"
+ echo "cline-provider spans would never reach the collector (and"
+ echo "Langfuse). Check OTEL_TRACES_EXPORTER on the build step."
+ exit 1
+ fi
done
# Same release-time gate as the macOS job; see the comment there.
diff --git a/apps/examples/desktop-app/scripts/desktop-startup.test.ts b/apps/examples/desktop-app/scripts/desktop-startup.test.ts
index f80c5980a1..24f471a969 100644
--- a/apps/examples/desktop-app/scripts/desktop-startup.test.ts
+++ b/apps/examples/desktop-app/scripts/desktop-startup.test.ts
@@ -107,6 +107,7 @@ test("the shipped CLI and backend report telemetry without starting a hub", asyn
otlp_endpoint_host: expect.any(String),
logs_exporter: expect.any(String),
metrics_exporter: expect.any(String),
+ traces_exporter: expect.any(String),
});
}
}, 120_000);
diff --git a/apps/examples/desktop-app/scripts/telemetry-define-args.test.ts b/apps/examples/desktop-app/scripts/telemetry-define-args.test.ts
index 92701cfa05..c6b1bce71e 100644
--- a/apps/examples/desktop-app/scripts/telemetry-define-args.test.ts
+++ b/apps/examples/desktop-app/scripts/telemetry-define-args.test.ts
@@ -46,6 +46,21 @@ describe("telemetryDefineArgs", () => {
const defines = defineMap(telemetryDefineArgs({}));
expect(defines["process.env.OTEL_TELEMETRY_ENABLED"]).toBe('""');
expect(defines["process.env.OTEL_EXPORTER_OTLP_ENDPOINT"]).toBe('""');
+ expect(defines["process.env.OTEL_TRACES_EXPORTER"]).toBe('""');
+ });
+
+ it("inlines the trace policy vars the Langfuse relay reads at runtime", () => {
+ const defines = defineMap(
+ telemetryDefineArgs({
+ CLINE_TRACE_SAMPLE_PERCENT: "25",
+ CLINE_TRACE_RECORD_CONTENT: "true",
+ }),
+ );
+ expect(defines["process.env.CLINE_TRACE_SAMPLE_PERCENT"]).toBe('"25"');
+ expect(defines["process.env.CLINE_TRACE_RECORD_CONTENT"]).toBe('"true"');
+ const unset = defineMap(telemetryDefineArgs({}));
+ expect(unset["process.env.CLINE_TRACE_SAMPLE_PERCENT"]).toBe('""');
+ expect(unset["process.env.CLINE_TRACE_RECORD_CONTENT"]).toBe('""');
});
it("includes API key defines only when the vars are set", () => {
diff --git a/apps/examples/desktop-app/scripts/telemetry-define-args.ts b/apps/examples/desktop-app/scripts/telemetry-define-args.ts
index 6bc705f652..cb8816349f 100644
--- a/apps/examples/desktop-app/scripts/telemetry-define-args.ts
+++ b/apps/examples/desktop-app/scripts/telemetry-define-args.ts
@@ -20,14 +20,20 @@ const OPTIONAL_FEATURE_ENV_VARS = ["CLINE_CODE_CLOUD_AGENTS"] as const;
/**
* Every env var `getTelemetryBuildTimeConfig` reads
- * (sdk/packages/shared/src/services/telemetry-config.ts). Always inlined,
+ * (sdk/packages/shared/src/services/telemetry-config.ts), plus the trace
+ * policy vars the Langfuse relay reads literally
+ * (sdk/packages/llms/src/services/langfuse-telemetry.ts). Always inlined,
* defaulting to "", so a packaged binary never falls back to runtime env.
+ * Mirrors BUILD_TIME_INLINED_ENV_VARS in apps/cli/script/compile-binary.ts,
+ * which bakes the same set into the bundled Cline CLI (the Hub daemon).
*/
const OTEL_ENV_VARS = [
"OTEL_TELEMETRY_ENABLED",
"OTEL_METRICS_EXPORTER",
"OTEL_LOGS_EXPORTER",
"OTEL_TRACES_EXPORTER",
+ "CLINE_TRACE_SAMPLE_PERCENT",
+ "CLINE_TRACE_RECORD_CONTENT",
"OTEL_EXPORTER_OTLP_PROTOCOL",
"OTEL_EXPORTER_OTLP_ENDPOINT",
"OTEL_EXPORTER_OTLP_HEADERS",
diff --git a/apps/examples/desktop-app/sidecar/cli-runtime.test.ts b/apps/examples/desktop-app/sidecar/cli-runtime.test.ts
index 175ae78714..1aa17ef293 100644
--- a/apps/examples/desktop-app/sidecar/cli-runtime.test.ts
+++ b/apps/examples/desktop-app/sidecar/cli-runtime.test.ts
@@ -19,7 +19,13 @@ describe("ensureHubWithDesktopCli", () => {
["hub", "ensure", "--json", "--cwd", "/work"],
{
cwd: "/work",
- env: { PATH: "/usr/bin", CLINE_NO_AUTO_UPDATE: "1" },
+ env: {
+ PATH: "/usr/bin",
+ CLINE_NO_AUTO_UPDATE: "1",
+ CLINE_HUB_LAUNCHER_CLIENT: "cline-desktop",
+ CLINE_HUB_LAUNCHER_VERSION: expect.stringMatching(/^\d+\.\d+\.\d+/),
+ CLINE_HUB_LAUNCHER_TRANSPORT: "local",
+ },
timeoutMs: 60_000,
},
);
diff --git a/apps/examples/desktop-app/sidecar/cli-runtime.ts b/apps/examples/desktop-app/sidecar/cli-runtime.ts
index 3f46da4ef9..4548859d63 100644
--- a/apps/examples/desktop-app/sidecar/cli-runtime.ts
+++ b/apps/examples/desktop-app/sidecar/cli-runtime.ts
@@ -1,5 +1,7 @@
import { execFile } from "node:child_process";
import { setHubDaemonLauncher } from "@cline/core";
+import { withHubLauncherIdentity } from "@cline/shared";
+import { DESKTOP_CLIENT_CONTEXT } from "./client-context";
/** Absolute path of the Cline CLI binary the desktop shell bundles and launched us with. */
export const DESKTOP_CLI_PATH_ENV = "CLINE_DESKTOP_CLI_PATH";
@@ -94,7 +96,16 @@ export async function ensureHubWithDesktopCli(
["hub", "ensure", "--json", "--cwd", workspaceRoot],
{
cwd: workspaceRoot,
- env: { ...(options.env ?? process.env), CLINE_NO_AUTO_UPDATE: "1" },
+ // The CLI spawns the daemon, so stamp the desktop as its launcher
+ // here or the hub's telemetry would say the CLI started it.
+ env: withHubLauncherIdentity(
+ { ...(options.env ?? process.env), CLINE_NO_AUTO_UPDATE: "1" },
+ {
+ client: DESKTOP_CLIENT_CONTEXT.name,
+ version: DESKTOP_CLIENT_CONTEXT.version,
+ transport: "local",
+ },
+ ),
timeoutMs: HUB_ENSURE_TIMEOUT_MS,
},
);
diff --git a/sdk/ARCHITECTURE.md b/sdk/ARCHITECTURE.md
index 0300ad4683..1338d726fe 100644
--- a/sdk/ARCHITECTURE.md
+++ b/sdk/ARCHITECTURE.md
@@ -180,6 +180,7 @@ field.
2. `@cline/core` selects `HubRuntimeHost` or `RemoteRuntimeHost` through `packages/core/src/runtime/host.ts`.
3. When no compatible local hub is already discovered, `@cline/core` can spawn a detached hub daemon and reconnect through discovery. The spawner waits up to 15s for the daemon to publish a usable discovery record (cold starts of the compiled binary on Windows regularly need more than the previous 8s). If the daemon still fails to come up, the runtime host's `No compatible hub runtime is available` error carries the underlying reason, and the daemon reports its own startup failure to telemetry (`hub.daemon.startup`) before exiting.
4. Hosts attach and detach from shared sessions without stopping the authority runtime, so another client can keep streaming or resume the same session later.
+ One daemon serves every Cline client on the machine, and a hub-hosted session's telemetry carries only its own client (`clientName`/`clientVersion`), so the daemon also records *whose build started it*. The spawner stamps `CLINE_HUB_LAUNCHER_CLIENT`, `CLINE_HUB_LAUNCHER_VERSION`, and `CLINE_HUB_LAUNCHER_TRANSPORT` on the daemon environment (`withHubLauncherIdentity` in `@cline/shared`), defaulting to the spawning process's `ClineClientIdentity` and `local`. An embedding host that starts the hub through the CLI (the desktop app running `cline-cli hub ensure`) stamps itself first, and a stamp already present is kept as a whole, so the CLI that performs the spawn never records its own name or fills in its version next to the host's name. SSH remote hubs are stamped by the client over the `env` prefix of the remote `hub ensure` command with `transport=ssh`. The daemon claims the stamp out of its environment at startup (`claimHubLauncherIdentity`, same hazard as the daemon sentinel: hosted sessions spawn processes that inherit the environment, and a hub one of them starts must record itself) and publishes it with its build id and executable name as OTel resource attributes: `cline.hub.launcher.client`, `cline.hub.launcher.version`, `cline.hub.launcher.transport`, `cline.hub.build_id`, `cline.hub.runtime`. Collectors and Langfuse surface these as `resourceAttributes.*`, so a desktop session hosted by a CLI-started hub is attributable to that CLI build.
5. The hub-hosted runtime executes the agent loop using `@cline/agents` and `@cline/llms`.
6. `@cline/core` hub services broker sessions, events, approvals, schedules, and client-owned runtime capabilities such as session-local tool executors.
7. Hub event forwarding preserves structured streaming lifecycle boundaries: text/reasoning deltas, final text/reasoning completion, tool start/update/finish, and agent done events are translated across the hub transport so host UIs can reliably close loading/streaming state. `run.started` is emitted only after the target session is resolved and carries the originating command's `requestId` and `clientId`, allowing multi-client hosts to correlate delivery acknowledgments.
@@ -549,6 +550,11 @@ IDs must be span attributes, not only observation metadata, for Langfuse trackin
In the collector relay path, spans use the existing host OTLP exporter. The
collector owns Langfuse credentials and downstream filtering and sampling.
+The relay exists only when the host registered a traces exporter, which release
+builds inline at build time (`OTEL_TRACES_EXPORTER`, `CLINE_TRACE_*`) into the
+CLI, the extension, and the desktop backend and its bundled CLI; a packaged
+app has no runtime environment to read them from. The `--telemetry-selfcheck`
+report includes `traces_exporter` so publish workflows can gate on it.
`llms` checks provider eligibility, client sampling, opt-out, and content policy
per request. The host owns flushing and shutting down its provider.
diff --git a/sdk/packages/core/src/hub/daemon/index.test.ts b/sdk/packages/core/src/hub/daemon/index.test.ts
index f576251a35..4bd5793371 100644
--- a/sdk/packages/core/src/hub/daemon/index.test.ts
+++ b/sdk/packages/core/src/hub/daemon/index.test.ts
@@ -126,6 +126,21 @@ vi.mock("@cline/shared", () => ({
},
resolveClineBuildEnv: () => "production",
withResolvedClineBuildEnv: (env: NodeJS.ProcessEnv) => env,
+ getClineClientIdentity: () => ({ name: "cline-cli", version: "0.0.0" }),
+ withHubLauncherIdentity: (
+ env: NodeJS.ProcessEnv,
+ identity?: { client: string; version?: string; transport?: string },
+ ) =>
+ env.CLINE_HUB_LAUNCHER_CLIENT || !identity
+ ? env
+ : {
+ ...env,
+ CLINE_HUB_LAUNCHER_CLIENT: identity.client,
+ ...(identity.version
+ ? { CLINE_HUB_LAUNCHER_VERSION: identity.version }
+ : {}),
+ CLINE_HUB_LAUNCHER_TRANSPORT: identity.transport ?? "local",
+ },
}));
vi.mock("../client", () => ({
diff --git a/sdk/packages/core/src/hub/daemon/index.ts b/sdk/packages/core/src/hub/daemon/index.ts
index fa99f57c63..33c084116f 100644
--- a/sdk/packages/core/src/hub/daemon/index.ts
+++ b/sdk/packages/core/src/hub/daemon/index.ts
@@ -10,9 +10,11 @@ import { basename, dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import {
CLINE_RUN_AS_HUB_DAEMON_ENV,
+ getClineClientIdentity,
isBunEmbeddedModulePath,
isHubDaemonProcess,
resolveClineBuildEnv,
+ withHubLauncherIdentity,
withResolvedClineBuildEnv,
} from "@cline/shared";
import {
@@ -465,13 +467,30 @@ function resolveLaunchCommand(
],
cwd: workspaceRoot,
env: {
- ...withResolvedClineBuildEnv(process.env),
+ // Record which client's build is starting this shared daemon. An
+ // embedding host that already stamped the launcher (the desktop app
+ // running `cline-cli hub ensure`) keeps its own identity; otherwise
+ // this process's client identity (cline-cli, cline-acp, ...) is used.
+ ...withHubLauncherIdentity(
+ withResolvedClineBuildEnv(process.env),
+ resolveSelfLauncherIdentity(),
+ ),
CLINE_NO_INTERACTIVE: "1",
[CLINE_RUN_AS_HUB_DAEMON_ENV]: "1",
},
};
}
+function resolveSelfLauncherIdentity():
+ | { client: string; version?: string; transport: "local" }
+ | undefined {
+ const identity = getClineClientIdentity();
+ const client = identity?.name?.trim();
+ return client
+ ? { client, version: identity?.version, transport: "local" }
+ : undefined;
+}
+
function isTextFileBusyError(error: unknown): boolean {
if (!error || typeof error !== "object") {
return false;
diff --git a/sdk/packages/core/src/hub/daemon/telemetry.test.ts b/sdk/packages/core/src/hub/daemon/telemetry.test.ts
index 76a694a78e..567ccb01ba 100644
--- a/sdk/packages/core/src/hub/daemon/telemetry.test.ts
+++ b/sdk/packages/core/src/hub/daemon/telemetry.test.ts
@@ -51,7 +51,10 @@ vi.mock("../../services/storage/provider-settings-manager", () => ({
},
}));
-import { createHubDaemonTelemetry } from "./telemetry";
+import {
+ createHubDaemonTelemetry,
+ hubDaemonResourceAttributes,
+} from "./telemetry";
describe("createHubDaemonTelemetry", () => {
beforeEach(() => {
@@ -104,6 +107,41 @@ describe("createHubDaemonTelemetry", () => {
);
});
+ it("publishes who launched the daemon as resource attributes", () => {
+ mockGetProviderSettings.mockReturnValue(undefined);
+ vi.stubEnv("CLINE_HUB_LAUNCHER_CLIENT", "cline-desktop");
+ vi.stubEnv("CLINE_HUB_LAUNCHER_VERSION", "0.0.46");
+ vi.stubEnv("CLINE_HUB_LAUNCHER_TRANSPORT", "local");
+ try {
+ const daemonTelemetry = createHubDaemonTelemetry();
+ expect(daemonTelemetry.launcher).toEqual({
+ client: "cline-desktop",
+ version: "0.0.46",
+ transport: "local",
+ });
+ // A desktop session hosted by a CLI-started hub (or the reverse)
+ // is only attributable through the daemon's resource, since the
+ // span's clientName describes the session's client, not the host.
+ // Claimed, not read: hosted sessions must not inherit the stamp.
+ expect(process.env.CLINE_HUB_LAUNCHER_CLIENT).toBeUndefined();
+ expect(process.env.CLINE_HUB_LAUNCHER_VERSION).toBeUndefined();
+ expect(process.env.CLINE_HUB_LAUNCHER_TRANSPORT).toBeUndefined();
+ expect(mockCreateConfiguredTelemetryHandle).toHaveBeenCalledWith(
+ expect.objectContaining({
+ resourceAttributes: expect.objectContaining({
+ "cline.hub.launcher.client": "cline-desktop",
+ "cline.hub.launcher.version": "0.0.46",
+ "cline.hub.launcher.transport": "local",
+ "cline.hub.build_id": expect.any(String),
+ "cline.hub.runtime": expect.any(String),
+ }),
+ }),
+ );
+ } finally {
+ vi.unstubAllEnvs();
+ }
+ });
+
it("stays anonymous when no cached account exists, then identifies once the user logs in", () => {
mockGetProviderSettings.mockReturnValue(undefined);
createHubDaemonTelemetry();
@@ -230,3 +268,31 @@ describe("createHubDaemonTelemetry", () => {
await expect(disposed).resolves.toBeUndefined();
});
});
+
+describe("hubDaemonResourceAttributes", () => {
+ it("falls back to unknown launcher fields and strips the executable path", () => {
+ expect(
+ hubDaemonResourceAttributes(undefined, {
+ buildId: "build-1",
+ execPath: "C:\\Program Files\\Cline\\cline-cli.exe",
+ }),
+ ).toEqual({
+ "cline.hub.build_id": "build-1",
+ "cline.hub.runtime": "cline-cli",
+ "cline.hub.launcher.client": "unknown",
+ "cline.hub.launcher.version": "unknown",
+ "cline.hub.launcher.transport": "local",
+ });
+ expect(
+ hubDaemonResourceAttributes(
+ { client: "cline-cli", version: "3.0.72", transport: "ssh" },
+ { buildId: "build-2", execPath: "/home/dev/.cline/remote/cline" },
+ ),
+ ).toMatchObject({
+ "cline.hub.runtime": "cline",
+ "cline.hub.launcher.client": "cline-cli",
+ "cline.hub.launcher.version": "3.0.72",
+ "cline.hub.launcher.transport": "ssh",
+ });
+ });
+});
diff --git a/sdk/packages/core/src/hub/daemon/telemetry.ts b/sdk/packages/core/src/hub/daemon/telemetry.ts
index cb36710334..eef9779069 100644
--- a/sdk/packages/core/src/hub/daemon/telemetry.ts
+++ b/sdk/packages/core/src/hub/daemon/telemetry.ts
@@ -1,7 +1,10 @@
import { release } from "node:os";
import {
+ claimHubLauncherIdentity,
createClineTelemetryServiceConfig,
+ type HubLauncherIdentity,
type ITelemetryService,
+ readHubLauncherIdentity,
} from "@cline/shared";
import type { AuthSettings } from "../../services/llms/provider-settings";
import { ProviderSettingsManager } from "../../services/storage/provider-settings-manager";
@@ -12,16 +15,48 @@ import {
import { resolveCoreDistinctId } from "../../services/telemetry/distinct-id";
import { createConfiguredTelemetryHandle } from "../../services/telemetry/OpenTelemetryProvider";
import { CORE_BUILD_VERSION } from "../../version";
+import { resolveHubBuildId } from "../discovery";
const IDENTITY_REFRESH_INTERVAL_MS = 5 * 60 * 1000;
const DISPOSE_FLUSH_TIMEOUT_MS = 5_000;
export interface HubDaemonTelemetry {
readonly telemetry: ITelemetryService;
+ /** Who started this daemon, as published on its telemetry resource. */
+ readonly launcher?: HubLauncherIdentity;
/** Flushes pending batches and disposes the underlying provider. */
dispose(): Promise;
}
+/**
+ * Resource attributes that say whose build is hosting the sessions. One hub
+ * serves every Cline client on the machine, and a session only carries its
+ * own client's name/version (`clientName: cline-desktop`), so without these
+ * a desktop trace cannot be told apart from "desktop session on a hub the
+ * CLI started" - which decides whether a build-specific telemetry gap is the
+ * desktop's or the CLI's. Values are low-cardinality identifiers, never paths.
+ */
+export function hubDaemonResourceAttributes(
+ launcher: HubLauncherIdentity | undefined = readHubLauncherIdentity(),
+ options: { buildId?: string; execPath?: string } = {},
+): Record {
+ const buildId = options.buildId ?? resolveHubBuildId();
+ const execPath = options.execPath ?? process.execPath ?? "";
+ return {
+ "cline.hub.build_id": buildId,
+ // Executable name only: cline-cli (bundled by the desktop), cline
+ // (npm), code-sidecar (older desktop), bun/node (source runs). Split on
+ // both separators so a Windows path read on any platform strips too.
+ "cline.hub.runtime": (execPath.split(/[\\/]/).pop() ?? "").replace(
+ /\.exe$/i,
+ "",
+ ),
+ "cline.hub.launcher.client": launcher?.client ?? "unknown",
+ "cline.hub.launcher.version": launcher?.version ?? "unknown",
+ "cline.hub.launcher.transport": launcher?.transport ?? "local",
+ };
+}
+
/**
* Telemetry for the detached hub daemon process.
*
@@ -35,6 +70,10 @@ export interface HubDaemonTelemetry {
* periodically rather than only once at startup.
*/
export function createHubDaemonTelemetry(): HubDaemonTelemetry {
+ // Claim rather than read: sessions this daemon hosts spawn processes that
+ // inherit its environment, and a hub one of them starts must record its
+ // own launcher, not this one's.
+ const launcher = claimHubLauncherIdentity();
const config = createClineTelemetryServiceConfig({
// Spans carry only the OTel resource, not per-event metadata, so the
// daemon needs its own service identity: it ships in the same binary
@@ -54,7 +93,10 @@ export function createHubDaemonTelemetry(): HubDaemonTelemetry {
os_version: release(),
},
});
- const handle = createConfiguredTelemetryHandle(config);
+ const handle = createConfiguredTelemetryHandle({
+ ...config,
+ resourceAttributes: hubDaemonResourceAttributes(launcher),
+ });
// Constructed once and reused: the constructor runs legacy settings
// migration and provider registration side effects, while
@@ -112,6 +154,7 @@ export function createHubDaemonTelemetry(): HubDaemonTelemetry {
return {
telemetry: handle.telemetry,
+ launcher,
dispose: async (): Promise => {
clearInterval(identityTimer);
// dispose only runs on the daemon's way out; a hung exporter must
diff --git a/sdk/packages/core/src/remote/remote-environments.test.ts b/sdk/packages/core/src/remote/remote-environments.test.ts
index 2f07a5b6ef..d19ca7bf01 100644
--- a/sdk/packages/core/src/remote/remote-environments.test.ts
+++ b/sdk/packages/core/src/remote/remote-environments.test.ts
@@ -519,7 +519,7 @@ describe("RemoteEnvironmentService", () => {
/\/home\/dev\/\.cline\/data\/remote\/[a-f0-9-]+\.json/,
);
expect(ensure?.args.at(-1)).toContain(
- "exec 'env' 'CLINE_NO_AUTO_UPDATE=1' '/home/dev/.cline/remote/cline-linux-arm64-abcdef0123456789' 'hub' 'ensure' '--json' '--allow-port-fallback' '--no-connectors' '--login-shell-path' '--cwd' '/home/dev' '--host' '127.0.0.1' '--port' '0' '--pathname' '/hub' '--discovery-path' ",
+ "exec 'env' 'CLINE_NO_AUTO_UPDATE=1' 'CLINE_HUB_LAUNCHER_CLIENT=cline' 'CLINE_HUB_LAUNCHER_TRANSPORT=ssh' '/home/dev/.cline/remote/cline-linux-arm64-abcdef0123456789' 'hub' 'ensure' '--json' '--allow-port-fallback' '--no-connectors' '--login-shell-path' '--cwd' '/home/dev' '--host' '127.0.0.1' '--port' '0' '--pathname' '/hub' '--discovery-path' ",
);
expect(spawnTunnel).toHaveBeenCalledWith(
"ssh",
diff --git a/sdk/packages/core/src/remote/remote-environments.ts b/sdk/packages/core/src/remote/remote-environments.ts
index 07120623f9..0ff2d064a4 100644
--- a/sdk/packages/core/src/remote/remote-environments.ts
+++ b/sdk/packages/core/src/remote/remote-environments.ts
@@ -15,6 +15,12 @@ import {
import { createConnection, createServer } from "node:net";
import { homedir } from "node:os";
import { basename, dirname, join } from "node:path";
+import {
+ CLINE_HUB_LAUNCHER_CLIENT_ENV,
+ CLINE_HUB_LAUNCHER_TRANSPORT_ENV,
+ CLINE_HUB_LAUNCHER_VERSION_ENV,
+ getClineClientIdentity,
+} from "@cline/shared";
import { resolveClineDataDir } from "@cline/shared/storage";
import { requestHubShutdown } from "../hub/client";
@@ -999,10 +1005,18 @@ function remoteHubEnsureCommand(
cwd: string,
discoveryPath: string,
): RemoteCommandInput {
+ const launcher = getClineClientIdentity();
return {
command: "env",
args: [
"CLINE_NO_AUTO_UPDATE=1",
+ // The remote daemon's telemetry records who started it; the staged
+ // CLI would otherwise report itself.
+ `${CLINE_HUB_LAUNCHER_CLIENT_ENV}=${launcher?.name?.trim() || "cline"}`,
+ ...(launcher?.version?.trim()
+ ? [`${CLINE_HUB_LAUNCHER_VERSION_ENV}=${launcher.version.trim()}`]
+ : []),
+ `${CLINE_HUB_LAUNCHER_TRANSPORT_ENV}=ssh`,
cli,
"hub",
"ensure",
diff --git a/sdk/packages/core/src/services/telemetry/OpenTelemetryProvider.ts b/sdk/packages/core/src/services/telemetry/OpenTelemetryProvider.ts
index 780ed1b6d9..9295260320 100644
--- a/sdk/packages/core/src/services/telemetry/OpenTelemetryProvider.ts
+++ b/sdk/packages/core/src/services/telemetry/OpenTelemetryProvider.ts
@@ -127,6 +127,13 @@ export interface OpenTelemetryProviderOptions
> {
serviceName?: string;
serviceVersion?: string;
+ /**
+ * Extra OTel resource attributes stamped on every span, log, and metric
+ * this provider exports (collectors and Langfuse surface them as
+ * `resourceAttributes.*`). For process-level facts such as which client
+ * started a shared hub daemon; per-event metadata belongs on the event.
+ */
+ resourceAttributes?: Record;
enabled?: boolean;
logsExporter?: string | OpenTelemetryExporterKind[];
metricsExporter?: string | OpenTelemetryExporterKind[];
@@ -164,6 +171,7 @@ export class OpenTelemetryProvider {
constructor(options: OpenTelemetryProviderOptions = {}) {
this.options = options;
const resource = resourceFromAttributes({
+ ...options.resourceAttributes,
[ATTR_SERVICE_NAME]: options.serviceName ?? "cline",
...(options.serviceVersion
? { [ATTR_SERVICE_VERSION]: options.serviceVersion }
diff --git a/sdk/packages/shared/src/index.ts b/sdk/packages/shared/src/index.ts
index 3d7cb1aa5f..5ccccd5841 100644
--- a/sdk/packages/shared/src/index.ts
+++ b/sdk/packages/shared/src/index.ts
@@ -517,20 +517,27 @@ export {
export type {
ConnectorCliLaunchSpec,
ConnectorInstanceRef,
+ HubLauncherIdentity,
} from "./runtime/hub-daemon-env";
export {
CLINE_CONNECTOR_CLI_LAUNCH_ENV,
CLINE_CONNECTOR_STARTING_INSTANCE_ENV,
CLINE_CONNECTOR_SUPERVISED_ENV,
+ CLINE_HUB_LAUNCHER_CLIENT_ENV,
+ CLINE_HUB_LAUNCHER_TRANSPORT_ENV,
+ CLINE_HUB_LAUNCHER_VERSION_ENV,
CLINE_RUN_AS_HUB_DAEMON_ENV,
claimHubDaemonProcess,
+ claimHubLauncherIdentity,
claimSupervisedConnectorProcess,
isHubDaemonProcess,
isSupervisedConnectorProcess,
readConnectorCliLaunchSpec,
+ readHubLauncherIdentity,
readStartingConnectorInstance,
setConnectorCliLaunchSpec,
setStartingConnectorInstance,
+ withHubLauncherIdentity,
} from "./runtime/hub-daemon-env";
export {
ensureLoopbackProxyBypass,
diff --git a/sdk/packages/shared/src/runtime/hub-daemon-env.test.ts b/sdk/packages/shared/src/runtime/hub-daemon-env.test.ts
index 2cf71ee663..10d5f08c1d 100644
--- a/sdk/packages/shared/src/runtime/hub-daemon-env.test.ts
+++ b/sdk/packages/shared/src/runtime/hub-daemon-env.test.ts
@@ -5,13 +5,16 @@ import {
CLINE_CONNECTOR_SUPERVISED_ENV,
CLINE_RUN_AS_HUB_DAEMON_ENV,
claimHubDaemonProcess,
+ claimHubLauncherIdentity,
claimSupervisedConnectorProcess,
isHubDaemonProcess,
isSupervisedConnectorProcess,
readConnectorCliLaunchSpec,
+ readHubLauncherIdentity,
readStartingConnectorInstance,
setConnectorCliLaunchSpec,
setStartingConnectorInstance,
+ withHubLauncherIdentity,
} from "./hub-daemon-env";
describe("hub daemon environment helpers", () => {
@@ -188,3 +191,74 @@ describe("supervised connector marker", () => {
).toBe(true);
});
});
+
+describe("hub launcher identity", () => {
+ it("stamps the launcher onto a daemon environment without overriding an embedding host", () => {
+ const stamped = withHubLauncherIdentity(
+ { PATH: "/usr/bin" },
+ { client: "cline-cli", version: "3.0.72" },
+ );
+ expect(stamped).toEqual({
+ PATH: "/usr/bin",
+ CLINE_HUB_LAUNCHER_CLIENT: "cline-cli",
+ CLINE_HUB_LAUNCHER_VERSION: "3.0.72",
+ CLINE_HUB_LAUNCHER_TRANSPORT: "local",
+ });
+ // The desktop app runs `cline-cli hub ensure`; the CLI process that
+ // actually spawns the daemon must not replace the desktop's stamp.
+ const preserved = withHubLauncherIdentity(stamped, {
+ client: "cline-desktop",
+ version: "0.0.46",
+ });
+ expect(preserved).toEqual(stamped);
+ // A host that stamped only its client must not have another build's
+ // version filled in next to its name.
+ const clientOnly = withHubLauncherIdentity(
+ { CLINE_HUB_LAUNCHER_CLIENT: "cline-desktop" },
+ { client: "cline-cli", version: "3.0.72" },
+ );
+ expect(clientOnly).toEqual({ CLINE_HUB_LAUNCHER_CLIENT: "cline-desktop" });
+ expect(withHubLauncherIdentity({ A: "1" }, undefined)).toEqual({ A: "1" });
+ expect(withHubLauncherIdentity({ A: "1" }, { client: " " })).toEqual({
+ A: "1",
+ });
+ });
+
+ it("claims the launcher stamp so hosted sessions do not pass it on", () => {
+ const env: Record = {
+ CLINE_HUB_LAUNCHER_CLIENT: "cline-desktop",
+ CLINE_HUB_LAUNCHER_VERSION: "0.0.46",
+ CLINE_HUB_LAUNCHER_TRANSPORT: "ssh",
+ PATH: "/usr/bin",
+ };
+ expect(claimHubLauncherIdentity(env)).toEqual({
+ client: "cline-desktop",
+ version: "0.0.46",
+ transport: "ssh",
+ });
+ expect(env).toEqual({ PATH: "/usr/bin" });
+ // A hub started by a command inside that session records itself.
+ expect(
+ withHubLauncherIdentity(env, { client: "cline-cli", version: "3.0.72" })
+ .CLINE_HUB_LAUNCHER_CLIENT,
+ ).toBe("cline-cli");
+ expect(claimHubLauncherIdentity({})).toBeUndefined();
+ });
+
+ it("reads the launcher back, ignoring unknown transports", () => {
+ expect(readHubLauncherIdentity({})).toBeUndefined();
+ expect(
+ readHubLauncherIdentity({
+ CLINE_HUB_LAUNCHER_CLIENT: " cline-desktop ",
+ CLINE_HUB_LAUNCHER_VERSION: "0.0.46",
+ CLINE_HUB_LAUNCHER_TRANSPORT: "ssh",
+ }),
+ ).toEqual({ client: "cline-desktop", version: "0.0.46", transport: "ssh" });
+ expect(
+ readHubLauncherIdentity({
+ CLINE_HUB_LAUNCHER_CLIENT: "cline-cli",
+ CLINE_HUB_LAUNCHER_TRANSPORT: "carrier-pigeon",
+ }),
+ ).toEqual({ client: "cline-cli" });
+ });
+});
diff --git a/sdk/packages/shared/src/runtime/hub-daemon-env.ts b/sdk/packages/shared/src/runtime/hub-daemon-env.ts
index 202219a235..13dfe312b7 100644
--- a/sdk/packages/shared/src/runtime/hub-daemon-env.ts
+++ b/sdk/packages/shared/src/runtime/hub-daemon-env.ts
@@ -3,6 +3,86 @@ export const CLINE_CONNECTOR_CLI_LAUNCH_ENV = "CLINE_CONNECTOR_CLI_LAUNCH";
export const CLINE_CONNECTOR_STARTING_INSTANCE_ENV =
"CLINE_CONNECTOR_STARTING_INSTANCE";
export const CLINE_CONNECTOR_SUPERVISED_ENV = "CLINE_CONNECTOR_SUPERVISED";
+export const CLINE_HUB_LAUNCHER_CLIENT_ENV = "CLINE_HUB_LAUNCHER_CLIENT";
+export const CLINE_HUB_LAUNCHER_VERSION_ENV = "CLINE_HUB_LAUNCHER_VERSION";
+export const CLINE_HUB_LAUNCHER_TRANSPORT_ENV = "CLINE_HUB_LAUNCHER_TRANSPORT";
+
+/**
+ * Which Cline client started a Hub daemon. The daemon is one shared process
+ * per machine and any client attaches to it, so a session's own client
+ * identity (desktop, CLI, extension) says nothing about whose build is
+ * hosting it. The spawner stamps this into the daemon's environment and the
+ * daemon publishes it as OTel resource attributes, so a trace from a desktop
+ * session can be read as "served by the hub the CLI started" (or vice versa).
+ */
+export interface HubLauncherIdentity {
+ /** Client name of the spawner, e.g. `cline-desktop`, `cline-cli`. */
+ client: string;
+ version?: string;
+ /** `local` for a daemon on the client's own machine, `ssh` for a remote one. */
+ transport?: "local" | "ssh";
+}
+
+/**
+ * Stamp the launcher identity onto a daemon environment. A launcher already
+ * in `env` is kept as a whole: an embedding host (the desktop app running
+ * `cline-cli hub ensure`) stamps itself before handing the spawn to the CLI,
+ * and filling in fields it left unset from the CLI's identity would pair the
+ * host's name with another build's version.
+ */
+export function withHubLauncherIdentity<
+ T extends Record,
+>(env: T, identity: HubLauncherIdentity | undefined): T {
+ if (env[CLINE_HUB_LAUNCHER_CLIENT_ENV]?.trim()) {
+ return env;
+ }
+ const client = identity?.client?.trim();
+ if (!client) {
+ return env;
+ }
+ const version = identity?.version?.trim();
+ return {
+ ...env,
+ [CLINE_HUB_LAUNCHER_CLIENT_ENV]: client,
+ ...(version ? { [CLINE_HUB_LAUNCHER_VERSION_ENV]: version } : {}),
+ [CLINE_HUB_LAUNCHER_TRANSPORT_ENV]: identity?.transport ?? "local",
+ };
+}
+
+/**
+ * Take the launcher stamp out of a daemon's environment, returning it.
+ *
+ * Same hazard as {@link claimHubDaemonProcess}: everything a hub-hosted
+ * session spawns inherits the daemon's environment. A shell command that
+ * starts its own hub (`cline hub ensure --discovery-path ...`) would
+ * otherwise keep the outer hub's stamp, and a local CLI hub started inside
+ * an SSH-hosted session would report the desktop launcher and `ssh`.
+ */
+export function claimHubLauncherIdentity(
+ env: Record = process.env,
+): HubLauncherIdentity | undefined {
+ const identity = readHubLauncherIdentity(env);
+ delete env[CLINE_HUB_LAUNCHER_CLIENT_ENV];
+ delete env[CLINE_HUB_LAUNCHER_VERSION_ENV];
+ delete env[CLINE_HUB_LAUNCHER_TRANSPORT_ENV];
+ return identity;
+}
+
+export function readHubLauncherIdentity(
+ env: Record = process.env,
+): HubLauncherIdentity | undefined {
+ const client = env[CLINE_HUB_LAUNCHER_CLIENT_ENV]?.trim();
+ if (!client) {
+ return undefined;
+ }
+ const version = env[CLINE_HUB_LAUNCHER_VERSION_ENV]?.trim();
+ const transport = env[CLINE_HUB_LAUNCHER_TRANSPORT_ENV]?.trim();
+ return {
+ client,
+ ...(version ? { version } : {}),
+ ...(transport === "ssh" || transport === "local" ? { transport } : {}),
+ };
+}
export interface ConnectorCliLaunchSpec {
launcher: string;
diff --git a/sdk/packages/shared/src/services/telemetry-selfcheck.test.ts b/sdk/packages/shared/src/services/telemetry-selfcheck.test.ts
index b0bdda6a90..4a532bd355 100644
--- a/sdk/packages/shared/src/services/telemetry-selfcheck.test.ts
+++ b/sdk/packages/shared/src/services/telemetry-selfcheck.test.ts
@@ -9,6 +9,7 @@ describe("buildTelemetrySelfcheckReport", () => {
otlpEndpoint: "https://otel.example.com:4318",
logsExporter: "otlp",
metricsExporter: "otlp",
+ tracesExporter: "otlp",
}),
).toEqual({
telemetry_selfcheck: true,
@@ -16,6 +17,7 @@ describe("buildTelemetrySelfcheckReport", () => {
otlp_endpoint_host: "otel.example.com:4318",
logs_exporter: "otlp",
metrics_exporter: "otlp",
+ traces_exporter: "otlp",
});
expect(
buildTelemetrySelfcheckReport({
@@ -57,6 +59,13 @@ describe("buildTelemetrySelfcheckReport", () => {
}
});
+ it("reports an empty traces exporter when none was inlined", () => {
+ expect(
+ buildTelemetrySelfcheckReport({ enabled: true, logsExporter: "otlp" })
+ .traces_exporter,
+ ).toBe("");
+ });
+
it("only treats an explicit true as enabled", () => {
expect(buildTelemetrySelfcheckReport({}).enabled).toBe(false);
expect(buildTelemetrySelfcheckReport({ enabled: true }).enabled).toBe(true);
diff --git a/sdk/packages/shared/src/services/telemetry-selfcheck.ts b/sdk/packages/shared/src/services/telemetry-selfcheck.ts
index 23429e8ebd..a6b90fb369 100644
--- a/sdk/packages/shared/src/services/telemetry-selfcheck.ts
+++ b/sdk/packages/shared/src/services/telemetry-selfcheck.ts
@@ -10,6 +10,7 @@ export type TelemetrySelfcheckConfig = {
otlpEndpoint?: string;
logsExporter?: string;
metricsExporter?: string;
+ tracesExporter?: string;
};
export type TelemetrySelfcheckReport = {
@@ -24,6 +25,12 @@ export type TelemetrySelfcheckReport = {
otlp_endpoint_host: string;
logs_exporter: string;
metrics_exporter: string;
+ /**
+ * `""` when no traces exporter was inlined. Without one the host never
+ * registers a tracer provider, so cline-provider spans (the Langfuse
+ * relay) are silently never emitted; release gates require `"otlp"`.
+ */
+ traces_exporter: string;
};
// The SDK's OTLP exporters are the http/json ones
@@ -54,5 +61,6 @@ export function buildTelemetrySelfcheckReport(
otlp_endpoint_host: otlpEndpointHost(config.otlpEndpoint),
logs_exporter: config.logsExporter ?? "",
metrics_exporter: config.metricsExporter ?? "",
+ traces_exporter: config.tracesExporter ?? "",
};
}
From 44b388b998bd50aa0d1c6267553d753f93461859 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Miko=C5=82aj=20Kondratek?=
<19799111+mkondratek@users.noreply.github.com>
Date: Fri, 16 Oct 2026 20:13:15 +0200
Subject: [PATCH 18/29] chore(vscode): fix integration test runner on macOS
(#15088)
* chore(vscode): fix integration test runner on macOS
Bump @vscode/test-electron to 3.1.0, which resolves the macOS executable
from Info.plist. VS Code 1.110+ renamed Contents/MacOS/Electron to Code
and dropped the compatibility symlink, so 2.5.2 failed every run with
`spawn .../Contents/MacOS/Electron ENOENT`.
Also pass a short --user-data-dir on macOS. VS Code puts its IPC socket
in the user data dir, and the default .vscode-test/user-data overflows
the 103-char unix socket limit from deep checkouts such as worktrees
(`listen EINVAL ... 1.14-main.sock`). Linux and Windows keep the default.
* test(vscode): drop the macOS E2E executable fallback
@vscode/test-electron 3.1.0 resolves the macOS executable from the app
bundle's Info.plist for both Stable and Insiders, so downloadAndUnzipVSCode
now returns Contents/MacOS/Code directly and the Code / Code - Insiders
fallback never runs.
---
apps/vscode/.vscode-test.mjs | 18 +++++++++--
apps/vscode/package.json | 2 +-
apps/vscode/src/test/e2e/utils/helpers.ts | 37 ++---------------------
bun.lock | 4 +--
4 files changed, 21 insertions(+), 40 deletions(-)
diff --git a/apps/vscode/.vscode-test.mjs b/apps/vscode/.vscode-test.mjs
index e509190129..b7d2618b8f 100644
--- a/apps/vscode/.vscode-test.mjs
+++ b/apps/vscode/.vscode-test.mjs
@@ -1,7 +1,21 @@
import { defineConfig } from "@vscode/test-cli"
+import { createHash } from "crypto"
+import os from "os"
import path from "path"
const vscodeTestVersion = process.env.VSCODE_TEST_VERSION ?? "stable"
+const extensionDevelopmentPath = path.resolve("./")
+
+// VS Code puts its IPC socket (e.g. `1.14-main.sock`) in the user data dir, and
+// macOS caps unix socket paths at 103 chars. The default `.vscode-test/user-data`
+// overflows that from deep checkouts such as worktrees (`listen EINVAL`), so on
+// macOS use a short dir in the temp folder, keyed by checkout so concurrent runs
+// from different worktrees don't hand off to each other's instance.
+const launchArgs = ["--disable-extensions"]
+if (process.platform === "darwin") {
+ const checkoutHash = createHash("sha256").update(extensionDevelopmentPath).digest("hex").slice(0, 8)
+ launchArgs.push(`--user-data-dir=${path.join(os.tmpdir(), `cline-vscode-test-${checkoutHash}`)}`)
+}
export default defineConfig({
files: [
@@ -25,6 +39,6 @@ export default defineConfig({
},
workspaceFolder: "test-workspace",
version: vscodeTestVersion,
- extensionDevelopmentPath: path.resolve("./"),
- launchArgs: ["--disable-extensions"],
+ extensionDevelopmentPath,
+ launchArgs,
})
diff --git a/apps/vscode/package.json b/apps/vscode/package.json
index 794e36be56..6a4ca4a708 100644
--- a/apps/vscode/package.json
+++ b/apps/vscode/package.json
@@ -433,7 +433,7 @@
"@types/vscode": "1.101.0",
"@types/ws": "^8.18.1",
"@vscode/test-cli": "^0.0.12",
- "@vscode/test-electron": "^2.5.2",
+ "@vscode/test-electron": "^3.1.0",
"@vscode/vsce": "^3.6.0",
"c8": "^10.1.3",
"chai": "^4.3.10",
diff --git a/apps/vscode/src/test/e2e/utils/helpers.ts b/apps/vscode/src/test/e2e/utils/helpers.ts
index f2e40a672a..89e55908bf 100644
--- a/apps/vscode/src/test/e2e/utils/helpers.ts
+++ b/apps/vscode/src/test/e2e/utils/helpers.ts
@@ -1,5 +1,5 @@
import { type ChildProcess, spawnSync } from "node:child_process"
-import { existsSync, mkdirSync, mkdtempSync, type PathLike, type RmOptions, readdirSync, rmSync, writeFileSync } from "node:fs"
+import { mkdirSync, mkdtempSync, type PathLike, type RmOptions, readdirSync, rmSync, writeFileSync } from "node:fs"
import * as os from "node:os"
import * as path from "node:path"
import { type ElectronApplication, expect, type Frame, type Page, test } from "@playwright/test"
@@ -61,37 +61,6 @@ export class E2ETestHelper {
return `${baseName}${projectSuffix}`
}
- /**
- * Resolves the real VS Code executable for `_electron.launch()`.
- *
- * `@vscode/test-electron` hardcodes the macOS entry point as
- * `Visual Studio Code.app/Contents/MacOS/Electron`, but recent VS Code builds
- * ship that binary as `Code` instead, so launching fails with ENOENT.
- * See https://github.com/microsoft/vscode-test/issues/355.
- *
- * When the reported path is missing, fall back to the bundle's real executable
- * name(s) so E2E works on both the old and new layouts.
- */
- public static resolveVSCodeExecutablePath(executablePath: string): string {
- if (existsSync(executablePath)) {
- return executablePath
- }
-
- if (process.platform !== "darwin") {
- return executablePath
- }
-
- const macOSDir = path.dirname(executablePath)
- for (const candidate of ["Code", "Code - Insiders"]) {
- const candidatePath = path.join(macOSDir, candidate)
- if (existsSync(candidatePath)) {
- return candidatePath
- }
- }
-
- return executablePath
- }
-
public static async waitUntil(predicate: () => boolean | Promise, maxDelay = 10000): Promise {
let delay = 10
const start = Date.now()
@@ -412,9 +381,7 @@ export const e2e = test
})
.extend<{ openVSCode: (workspacePath: string) => Promise }>({
openVSCode: async ({ userDataDir, channel }, use, testInfo) => {
- const executablePath = E2ETestHelper.resolveVSCodeExecutablePath(
- await downloadAndUnzipVSCode(channel, undefined, new SilentReporter()),
- )
+ const executablePath = await downloadAndUnzipVSCode(channel, undefined, new SilentReporter())
await use(async (workspacePath: string) => {
// Create isolated Cline data directory for this test
diff --git a/bun.lock b/bun.lock
index d6245264ca..4bc68fa333 100644
--- a/bun.lock
+++ b/bun.lock
@@ -474,7 +474,7 @@
"@types/vscode": "1.101.0",
"@types/ws": "^8.18.1",
"@vscode/test-cli": "^0.0.12",
- "@vscode/test-electron": "^2.5.2",
+ "@vscode/test-electron": "^3.1.0",
"@vscode/vsce": "^3.6.0",
"c8": "^10.1.3",
"chai": "^4.3.10",
@@ -2748,7 +2748,7 @@
"@vscode/test-cli": ["@vscode/test-cli@0.0.12", "", { "dependencies": { "@types/mocha": "^10.0.10", "c8": "^10.1.3", "chokidar": "^3.6.0", "enhanced-resolve": "^5.18.3", "glob": "^10.3.10", "minimatch": "^9.0.3", "mocha": "^11.7.4", "supports-color": "^10.2.2", "yargs": "^17.7.2" }, "bin": { "vscode-test": "out/bin.mjs" } }, "sha512-iYN0fDg29+a2Xelle/Y56Xvv7Nc8Thzq4VwpzAF/SIE6918rDicqfsQxV6w1ttr2+SOm+10laGuY9FG2ptEKsQ=="],
- "@vscode/test-electron": ["@vscode/test-electron@2.5.2", "", { "dependencies": { "http-proxy-agent": "^7.0.2", "https-proxy-agent": "^7.0.5", "jszip": "^3.10.1", "ora": "^8.1.0", "semver": "^7.6.2" } }, "sha512-8ukpxv4wYe0iWMRQU18jhzJOHkeGKbnw7xWRX3Zw1WJA4cEKbHcmmLPdPrPtL6rhDcrlCZN+xKRpv09n4gRHYg=="],
+ "@vscode/test-electron": ["@vscode/test-electron@3.1.0", "", { "dependencies": { "http-proxy-agent": "^7.0.2", "https-proxy-agent": "^7.0.5", "jszip": "^3.10.1", "ora": "^8.1.0", "semver": "^7.6.2" } }, "sha512-CRqv5u+YYoseuNVJ6Tyo4k0sF0mx4qnKMihRB0PjsUF8Dc0WKtCXo6CNL6nWWm5esfFQsQA/pejMj4ZbpJVLTw=="],
"@vscode/vsce": ["@vscode/vsce@3.9.2", "", { "dependencies": { "@azure/identity": "^4.1.0", "@secretlint/node": "^10.1.2", "@secretlint/secretlint-formatter-sarif": "^10.1.2", "@secretlint/secretlint-rule-no-dotenv": "^10.1.2", "@secretlint/secretlint-rule-preset-recommend": "^10.1.2", "@vscode/vsce-sign": "^2.0.0", "azure-devops-node-api": "^12.5.0", "chalk": "^4.1.2", "cheerio": "^1.0.0-rc.9", "cockatiel": "^3.1.2", "commander": "^12.1.0", "form-data": "^4.0.0", "glob": "^13.0.6", "hosted-git-info": "^4.0.2", "jsonc-parser": "^3.2.0", "leven": "^3.1.0", "markdown-it": "^14.1.0", "mime": "^1.3.4", "minimatch": "^10.2.2", "parse-semver": "^1.1.1", "read": "^1.0.7", "secretlint": "^10.1.2", "semver": "^7.5.2", "tmp": "^0.2.3", "typed-rest-client": "^1.8.4", "url-join": "^4.0.1", "xml2js": "^0.5.0", "yauzl": "^3.2.1", "yazl": "^2.2.2" }, "optionalDependencies": { "keytar": "^7.7.0" }, "bin": { "vsce": "vsce" } }, "sha512-XSxMosEEDO6vLxELAHVkwmhC0qe0ijZni2jB9Rcs8kQsW4lhTDQ/wMzmwFs/buotAWSnpmUp/dRWD2ufG3UYKA=="],
From b549ceb4bb4247284c975f6d6ca0979decec097c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Miko=C5=82aj=20Kondratek?=
<19799111+mkondratek@users.noreply.github.com>
Date: Fri, 16 Oct 2026 20:14:20 +0200
Subject: [PATCH 19/29] fix(llms): send max_completion_tokens for gpt-6 ids on
OpenAI-compatible endpoints (#15137)
The reasoning-era model-id matcher only covered o1/o3/o4 and gpt-5, so
gpt-6 requests (gpt-6-sol, gpt-6.1-sol, gpt-6-1-sol) kept max_tokens and
OpenAI/Azure rejected them. Widen the gpt pattern to gpt-5 through gpt-9,
keeping the version digit single so Azure's gpt-35-turbo stays out.
---
.../llms/src/providers/model-facts.ts | 21 +++++++++-------
.../vendors/openai-compatible.test.ts | 25 ++++++++++++++++++-
2 files changed, 36 insertions(+), 10 deletions(-)
diff --git a/sdk/packages/llms/src/providers/model-facts.ts b/sdk/packages/llms/src/providers/model-facts.ts
index 2692c06270..d0c2717757 100644
--- a/sdk/packages/llms/src/providers/model-facts.ts
+++ b/sdk/packages/llms/src/providers/model-facts.ts
@@ -247,7 +247,8 @@ export function isQwenModel(options: {
}
// OpenAI reasoning-era chat models: the o-series (o1/o3/o4, including -mini,
-// -pro, and dated variants) and the gpt-5 family (including gpt-5-chat).
+// -pro, and dated variants) and gpt-5 and every later single-digit family
+// (gpt-5-chat, gpt-5.6-sol, gpt-6-sol, gpt-6.1-sol, ...).
// These models diverge from classic chat-completions parameter rules — most
// importantly they reject `max_tokens` and require `max_completion_tokens`.
// Detection is an id-pattern fallback (mirroring the legacy extension's
@@ -257,11 +258,13 @@ export function isQwenModel(options: {
// match, while namespaced ids like "openai/o3-mini" do.
//
// Maintenance:
-// - If OpenAI ships a new family with the same parameter rules (e.g. gpt-6),
-// add a pattern here and cases to the positive/negative lists in
-// `vendors/openai-compatible.test.ts`. The failure mode until then is the
-// loud, self-describing OpenAI 400 ("'max_tokens' is not supported with
-// this model. Use 'max_completion_tokens' instead."), not silent breakage.
+// - New gpt families up to gpt-9 match without changes. The version digit
+// stays single on purpose: two digits would match Azure's `gpt-35-turbo`.
+// For a new family outside this pattern, add one here and cases to the
+// positive/negative lists in `vendors/openai-compatible.test.ts`. The
+// failure mode until then is the loud, self-describing OpenAI 400
+// ("'max_tokens' is not supported with this model. Use
+// 'max_completion_tokens' instead."), not silent breakage.
// - Keep the boundary anchoring on BOTH sides of each pattern; loosening it
// risks renaming the parameter for unrelated third-party models.
// - Only `withMaxCompletionTokensForReasoningModels` in
@@ -269,8 +272,8 @@ export function isQwenModel(options: {
// `@ai-sdk/openai-compatible` maps `max_completion_tokens` itself (as
// `@ai-sdk/openai` already does), delete that transform and this helper.
const OPENAI_O_SERIES_MODEL_ID_PATTERN = /(^|[^a-z0-9])o[134](?=$|[^a-z0-9])/;
-const OPENAI_GPT5_FAMILY_MODEL_ID_PATTERN =
- /(^|[^a-z0-9])gpt-?5(?=$|[^a-z0-9])/;
+const OPENAI_GPT5_AND_LATER_MODEL_ID_PATTERN =
+ /(^|[^a-z0-9])gpt-?[5-9](?=$|[^a-z0-9])/;
export function isOpenAIReasoningEraModelId(
modelId: string | undefined,
@@ -282,7 +285,7 @@ export function isOpenAIReasoningEraModelId(
return (
OPENAI_O_SERIES_MODEL_ID_PATTERN.test(normalized) ||
- OPENAI_GPT5_FAMILY_MODEL_ID_PATTERN.test(normalized)
+ OPENAI_GPT5_AND_LATER_MODEL_ID_PATTERN.test(normalized)
);
}
diff --git a/sdk/packages/llms/src/providers/vendors/openai-compatible.test.ts b/sdk/packages/llms/src/providers/vendors/openai-compatible.test.ts
index f517c8f415..b8a71c66f6 100644
--- a/sdk/packages/llms/src/providers/vendors/openai-compatible.test.ts
+++ b/sdk/packages/llms/src/providers/vendors/openai-compatible.test.ts
@@ -11,7 +11,7 @@ import {
} from "./openai-compatible";
describe("isOpenAIReasoningEraModelId", () => {
- it("matches o-series and gpt-5-family model ids", () => {
+ it("matches o-series and gpt-5-and-later model ids", () => {
for (const modelId of [
"o1",
"o1-mini",
@@ -32,6 +32,14 @@ describe("isOpenAIReasoningEraModelId", () => {
"openai/gpt-5.2",
"GPT-5-Mini",
"azure-gpt-5-mini",
+ "gpt-5.6-sol",
+ "gpt-6",
+ "gpt-6-sol",
+ "gpt-6.1-sol",
+ "gpt-6-1-sol",
+ "openai/gpt-6-luna",
+ "azure/gpt-6-astra",
+ "gpt-7",
]) {
expect(isOpenAIReasoningEraModelId(modelId), modelId).toBe(true);
}
@@ -57,6 +65,10 @@ describe("isOpenAIReasoningEraModelId", () => {
"chatgpt-5",
"somegpt-5-custom",
"xgpt5",
+ "gpt-35-turbo-16k",
+ "gpt-55",
+ "gpt-6o",
+ "somegpt-6-custom",
]) {
expect(isOpenAIReasoningEraModelId(modelId), modelId).toBe(false);
}
@@ -132,6 +144,17 @@ describe("createOpenAICompatibleProviderModule wire format", () => {
expect(requestBody()).not.toHaveProperty("max_tokens");
});
+ it("sends max_completion_tokens instead of max_tokens for gpt-6 streaming requests", async () => {
+ const { requestBody } = await stream({ modelId: "gpt-6.1-sol" });
+
+ expect(requestBody()).toMatchObject({
+ model: "gpt-6.1-sol",
+ max_completion_tokens: 8_192,
+ stream: true,
+ });
+ expect(requestBody()).not.toHaveProperty("max_tokens");
+ });
+
it("sends max_completion_tokens instead of max_tokens for o-series streaming requests", async () => {
const { requestBody } = await stream({ modelId: "o3-mini" });
From 729d6c224ed73d636f7ee11b2aed5eb220f6ff90 Mon Sep 17 00:00:00 2001
From: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
Date: Fri, 16 Oct 2026 19:36:11 -0700
Subject: [PATCH 20/29] fix(llms): pin OpenCode Go base URL to the shared
inference root (#15154)
models.dev now lists https://opencode.ai/inference/go/openai/v1, which
only serves OpenAI routes: /messages returns 404 there, so every
Anthropic-protocol OpenCode Go model would fail after a catalog regen.
Routing appends per-model protocol endpoints to the base URL, so keep
the shared /inference/go/v1 root that serves chat, responses and
messages.
---
sdk/packages/llms/src/providers/builtins.ts | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/sdk/packages/llms/src/providers/builtins.ts b/sdk/packages/llms/src/providers/builtins.ts
index cfdbf54659..5da4681bca 100644
--- a/sdk/packages/llms/src/providers/builtins.ts
+++ b/sdk/packages/llms/src/providers/builtins.ts
@@ -778,7 +778,13 @@ const OPENAI_COMPATIBLE_SPEC_OVERRIDES: BuiltinSpecOverride[] = [
{
id: "opencode-go",
docsUrl: "https://opencode.ai/docs/go/",
- defaults: { headers: { "User-Agent": "Cline/SDK" } },
+ defaults: {
+ // models.dev lists the OpenAI-only path (/inference/go/openai/v1),
+ // which 404s on /messages. Routing appends per-model protocol
+ // endpoints, so pin the shared root that serves all of them.
+ baseUrl: "https://opencode.ai/inference/go/v1",
+ headers: { "User-Agent": "Cline/SDK" },
+ },
metadata: {
routing: { modelApiProtocol: true },
stickySession: {
From 36b80d8ce42be472f91bb818b79001b89392306d Mon Sep 17 00:00:00 2001
From: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
Date: Fri, 16 Oct 2026 19:37:13 -0700
Subject: [PATCH 21/29] chore(sdk): release v0.0.95
---
bun.lock | 10 +-
sdk/CHANGELOG.md | 7 +
sdk/packages/agents/package.json | 2 +-
sdk/packages/core/package.json | 2 +-
sdk/packages/llms/package.json | 2 +-
.../llms/src/catalog/catalog.generated.ts | 4356 ++++++++++++++---
.../catalog/cline-recommended.generated.ts | 24 +-
.../src/providers/provider-ids.generated.ts | 2 +
.../llms/src/providers/providers.generated.ts | 52 +-
sdk/packages/sdk/package.json | 2 +-
sdk/packages/shared/package.json | 2 +-
11 files changed, 3879 insertions(+), 582 deletions(-)
diff --git a/bun.lock b/bun.lock
index 4bc68fa333..5d267d7c87 100644
--- a/bun.lock
+++ b/bun.lock
@@ -645,7 +645,7 @@
},
"sdk/packages/agents": {
"name": "@cline/agents",
- "version": "0.0.94",
+ "version": "0.0.95",
"dependencies": {
"@cline/llms": "workspace:*",
"@cline/shared": "workspace:*",
@@ -654,7 +654,7 @@
},
"sdk/packages/core": {
"name": "@cline/core",
- "version": "0.0.94",
+ "version": "0.0.95",
"dependencies": {
"@cline/agents": "workspace:*",
"@cline/llms": "workspace:*",
@@ -696,7 +696,7 @@
},
"sdk/packages/llms": {
"name": "@cline/llms",
- "version": "0.0.94",
+ "version": "0.0.95",
"dependencies": {
"@ai-sdk/amazon-bedrock": "^5.0.98",
"@ai-sdk/anthropic": "^4.0.67",
@@ -745,14 +745,14 @@
},
"sdk/packages/sdk": {
"name": "@cline/sdk",
- "version": "0.0.94",
+ "version": "0.0.95",
"dependencies": {
"@cline/core": "workspace:*",
},
},
"sdk/packages/shared": {
"name": "@cline/shared",
- "version": "0.0.94",
+ "version": "0.0.95",
"dependencies": {
"aws4fetch": "^1.0.20",
"jsonrepair": "^3.13.2",
diff --git a/sdk/CHANGELOG.md b/sdk/CHANGELOG.md
index f3598c8739..346d27c276 100644
--- a/sdk/CHANGELOG.md
+++ b/sdk/CHANGELOG.md
@@ -1,5 +1,12 @@
# Cline SDK Changelog
+## 0.0.95
+
+- OpenAI-compatible requests for GPT-6 models (`gpt-6-sol`, `gpt-6.1-sol`, `gpt-6-1-sol`, and later gpt-5 through gpt-9 ids) send `max_completion_tokens` instead of `max_tokens`, so OpenAI and Azure no longer reject them. Azure's `gpt-35-turbo` keeps `max_tokens`
+- The hub daemon records which client started it (`CLINE_HUB_LAUNCHER_CLIENT`, `CLINE_HUB_LAUNCHER_VERSION`, `CLINE_HUB_LAUNCHER_TRANSPORT`) and publishes that as OTel resource attributes. SSH remote hubs report the local client with transport `ssh`. `@cline/shared` adds `withHubLauncherIdentity`, `claimHubLauncherIdentity` and `readHubLauncherIdentity`
+- The telemetry self-check report includes `traces_exporter`
+- Refreshed the model catalog (6,952 → 7,041 models). Adds the CommandCode and Reflection providers. The Cline recommended list leads with Claude Sonnet 5.5 again, so the `cline` provider's bundled default goes back to Claude Sonnet 5.5 from Gemini 4 Argon. Default models change for 302.AI (Gemini 4 Argon), Eden AI and Prime Inference (Muse Spark Open), CoreWeave (Reflection Beam 1.0), NanoGPT, Pioneer (Nemotron 3.5 Super VL), and Scaleway (DeepSeek V4.1 Flash). OpenCode Go keeps its `https://opencode.ai/inference/go/v1` base URL, now pinned, because models.dev moved its provider-level URL to an OpenAI-only path
+
## 0.0.94
- Plugins now run only in worker threads (the default, `CLINE_PLUGIN_MODE=worker`) or in the subprocess sandbox (`sandbox`). The `in_process` mode is removed, along with its silent fallback. A host that ships no `plugin-sandbox-bootstrap.js` fails every plugin load with `PluginBootstrapMissingError`, which names `CLINE_PLUGIN_BOOTSTRAP_PATH`, instead of quietly running plugins inside the hub. The hub daemon's uncaught error handlers are fatal again. The SSH remote hub ships no bootstrap yet, so it reports plugin tools as missing
diff --git a/sdk/packages/agents/package.json b/sdk/packages/agents/package.json
index aa966f2dfe..ef983eb622 100644
--- a/sdk/packages/agents/package.json
+++ b/sdk/packages/agents/package.json
@@ -1,6 +1,6 @@
{
"name": "@cline/agents",
- "version": "0.0.94",
+ "version": "0.0.95",
"repository": {
"type": "git",
"url": "https://github.com/cline/cline",
diff --git a/sdk/packages/core/package.json b/sdk/packages/core/package.json
index f5f2007a3e..fb34374a87 100644
--- a/sdk/packages/core/package.json
+++ b/sdk/packages/core/package.json
@@ -1,7 +1,7 @@
{
"name": "@cline/core",
"description": "Cline Core SDK for Node Runtime",
- "version": "0.0.94",
+ "version": "0.0.95",
"repository": {
"type": "git",
"url": "https://github.com/cline/cline",
diff --git a/sdk/packages/llms/package.json b/sdk/packages/llms/package.json
index 993e14adce..654288bc3a 100644
--- a/sdk/packages/llms/package.json
+++ b/sdk/packages/llms/package.json
@@ -1,6 +1,6 @@
{
"name": "@cline/llms",
- "version": "0.0.94",
+ "version": "0.0.95",
"description": "Config-driven SDK for selecting, extending, and instantiating LLM providers and models",
"repository": {
"type": "git",
diff --git a/sdk/packages/llms/src/catalog/catalog.generated.ts b/sdk/packages/llms/src/catalog/catalog.generated.ts
index 0359d5092e..e8337ff79f 100644
--- a/sdk/packages/llms/src/catalog/catalog.generated.ts
+++ b/sdk/packages/llms/src/catalog/catalog.generated.ts
@@ -14,9 +14,55 @@ export const GENERATED_PROVIDER_MODELS: {
version: number
providers: Record>
} = {
- version: 1792120582911,
+ version: 1792204603381,
providers: {
"302ai": {
+ "gemini-4-argon": {
+ "id": "gemini-4-argon",
+ "name": "Gemini 4 Argon",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 4,
+ "output": 10,
+ "cacheRead": 0.2,
+ "cacheWrite": 0.375
+ },
+ "releaseDate": "2026-10-13",
+ "family": "gemini",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio",
+ "pdf"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
"claude-haiku-5-5": {
"id": "claude-haiku-5-5",
"name": "Claude Haiku 5.5",
@@ -15557,9 +15603,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 1.891175,
- "output": 15.1294,
- "cacheRead": 1.71925,
+ "input": 1.625,
+ "output": 13,
+ "cacheRead": 0.1625,
"cacheWrite": 0
},
"releaseDate": "2025-08-07",
@@ -15590,9 +15636,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.378235,
- "output": 3.02588,
- "cacheRead": 0.34385,
+ "input": 0.325,
+ "output": 2.6,
+ "cacheRead": 0.0325,
"cacheWrite": 0
},
"releaseDate": "2025-08-07",
@@ -15623,9 +15669,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.075647,
- "output": 0.605176,
- "cacheRead": 0.06877,
+ "input": 0.065,
+ "output": 0.52,
+ "cacheRead": 0.0065,
"cacheWrite": 0
},
"releaseDate": "2025-08-07",
@@ -33977,7 +34023,7 @@ export const GENERATED_PROVIDER_MODELS: {
"id": "cline-pass/deepseek-v4.1-flash",
"contextWindow": 1048576,
"maxInputTokens": 1048576,
- "maxTokens": 393216,
+ "maxTokens": 943718,
"capabilities": [
"images",
"tools",
@@ -34254,7 +34300,7 @@ export const GENERATED_PROVIDER_MODELS: {
"id": "cline-pass/glm-5.3-flash",
"contextWindow": 1048576,
"maxInputTokens": 1048576,
- "maxTokens": 943717,
+ "maxTokens": 943718,
"capabilities": [
"images",
"video",
@@ -34284,35 +34330,6 @@ export const GENERATED_PROVIDER_MODELS: {
"family": "glm-flash",
"description": "Latest natively multimodal model in the GLM-5 series"
},
- "cline-pass/qwen3.7-plus": {
- "name": "Qwen3.7 Plus",
- "id": "cline-pass/qwen3.7-plus",
- "contextWindow": 1000000,
- "maxInputTokens": 1000000,
- "maxTokens": 131072,
- "capabilities": [
- "images",
- "tools",
- "reasoning",
- "structured_output",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [
- {
- "type": "toggle"
- }
- ],
- "pricing": {
- "input": 0,
- "output": 0,
- "cacheRead": 0,
- "cacheWrite": 0
- },
- "releaseDate": "2026-06-02",
- "family": "qwen",
- "description": "Fast multimodal agent model with vision and video input"
- },
"cline-pass/minimax-m3": {
"name": "MiniMax-M3",
"id": "cline-pass/minimax-m3",
@@ -34343,6 +34360,35 @@ export const GENERATED_PROVIDER_MODELS: {
"family": "minimax",
"description": "Frontier coding and agent model with 1M context window"
},
+ "cline-pass/qwen3.7-plus": {
+ "name": "Qwen3.7 Plus",
+ "id": "cline-pass/qwen3.7-plus",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 131072,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "toggle"
+ }
+ ],
+ "pricing": {
+ "input": 0,
+ "output": 0,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-06-02",
+ "family": "qwen",
+ "description": "Fast multimodal agent model with vision and video input"
+ },
"cline-pass/qwen3.7-max": {
"name": "Qwen3.7 Max",
"id": "cline-pass/qwen3.7-max",
@@ -35221,6 +35267,2571 @@ export const GENERATED_PROVIDER_MODELS: {
"family": "llama"
}
},
+ "commandcode": {
+ "google/gemini-4-argon": {
+ "id": "google/gemini-4-argon",
+ "name": "Gemini 4 Argon",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 10,
+ "cacheRead": 0.1,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-13",
+ "family": "gemini",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio",
+ "pdf"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
+ "meta/muse-wonder-1.0": {
+ "id": "meta/muse-wonder-1.0",
+ "name": "Muse Wonder",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 131072,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 4,
+ "output": 20,
+ "cacheRead": 0.2,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-12",
+ "family": "muse",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "pdf",
+ "audio"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
+ "claude-haiku-5-5": {
+ "id": "claude-haiku-5-5",
+ "name": "Claude Haiku 5.5",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "toggle"
+ },
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.1,
+ "output": 0.5,
+ "cacheRead": 0.01,
+ "cacheWrite": 0.125
+ },
+ "releaseDate": "2026-10-07",
+ "family": "claude-haiku",
+ "metadata": {
+ "apiProtocol": "anthropic"
+ }
+ },
+ "mistral/mistral-large-4": {
+ "id": "mistral/mistral-large-4",
+ "name": "Mistral Large 4",
+ "contextWindow": 524288,
+ "maxInputTokens": 524288,
+ "maxTokens": 262144,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1.36,
+ "output": 4.18,
+ "cacheRead": 0.14,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-06",
+ "family": "mistral-large"
+ },
+ "gpt-6.1-sol": {
+ "id": "gpt-6.1-sol",
+ "name": "GPT-6.1 Sol",
+ "contextWindow": 1050000,
+ "maxInputTokens": 922000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 10,
+ "cacheRead": 0.1,
+ "cacheWrite": 2.5
+ },
+ "releaseDate": "2026-09-29",
+ "family": "gpt-sol"
+ },
+ "inclusionai/ling-3.1-flash:free": {
+ "id": "inclusionai/ling-3.1-flash:free",
+ "name": "Ling 3.1 Flash",
+ "contextWindow": 262144,
+ "maxInputTokens": 262144,
+ "maxTokens": 32768,
+ "capabilities": [
+ "tools",
+ "reasoning"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0,
+ "output": 0,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-09-29",
+ "family": "ling"
+ },
+ "claude-sonnet-5-5": {
+ "id": "claude-sonnet-5-5",
+ "name": "Claude Sonnet 5.5",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 10,
+ "cacheRead": 0.1,
+ "cacheWrite": 2.5
+ },
+ "releaseDate": "2026-09-28",
+ "family": "claude-sonnet",
+ "metadata": {
+ "apiProtocol": "anthropic"
+ }
+ },
+ "claude-opus-5-5": {
+ "id": "claude-opus-5-5",
+ "name": "Claude Opus 5.5",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 4,
+ "output": 20,
+ "cacheRead": 0.2,
+ "cacheWrite": 5
+ },
+ "releaseDate": "2026-09-22",
+ "family": "claude-opus",
+ "metadata": {
+ "apiProtocol": "anthropic"
+ }
+ },
+ "gpt-6-luna": {
+ "id": "gpt-6-luna",
+ "name": "GPT-6 Luna",
+ "contextWindow": 1050000,
+ "maxInputTokens": 922000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.1,
+ "output": 0.5,
+ "cacheRead": 0.01,
+ "cacheWrite": 0.125
+ },
+ "releaseDate": "2026-09-22",
+ "family": "gpt-luna"
+ },
+ "gpt-6-sol": {
+ "id": "gpt-6-sol",
+ "name": "GPT-6 Sol",
+ "contextWindow": 1050000,
+ "maxInputTokens": 922000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 10,
+ "cacheRead": 0.2,
+ "cacheWrite": 2.5
+ },
+ "releaseDate": "2026-09-22",
+ "family": "gpt-sol"
+ },
+ "xai/grok-4.7": {
+ "id": "xai/grok-4.7",
+ "name": "Grok 4.7",
+ "contextWindow": 500000,
+ "maxInputTokens": 500000,
+ "maxTokens": 500000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 6,
+ "cacheRead": 0.5,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-09-21",
+ "family": "grok"
+ },
+ "Qwen/Qwen3.8-Omni-Flash": {
+ "id": "Qwen/Qwen3.8-Omni-Flash",
+ "name": "Qwen3.8 Omni Flash",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 131072,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.15,
+ "output": 0.47,
+ "cacheRead": 0.016,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-09-17",
+ "family": "qwen",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "audio",
+ "video"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
+ "stepfun/Step-5-Preview": {
+ "id": "stepfun/Step-5-Preview",
+ "name": "Step 5 Preview",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 1000000,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1,
+ "output": 2.7,
+ "cacheRead": 0.05,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-09-16"
+ },
+ "deepseek/deepseek-v4.1-flash": {
+ "id": "deepseek/deepseek-v4.1-flash",
+ "name": "DeepSeek V4.1 Flash",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 384000,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "toggle"
+ },
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "high",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.15,
+ "output": 0.6,
+ "cacheRead": 0.003,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-09-10",
+ "family": "deepseek-flash"
+ },
+ "deepseek/deepseek-v4.1-flash-fast": {
+ "id": "deepseek/deepseek-v4.1-flash-fast",
+ "name": "DeepSeek V4.1 Flash Fast",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 384000,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "toggle"
+ },
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "high",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.16,
+ "output": 0.58,
+ "cacheRead": 0.016,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-09-10",
+ "family": "deepseek-flash"
+ },
+ "gpt-6-astra": {
+ "id": "gpt-6-astra",
+ "name": "GPT-6 Astra",
+ "contextWindow": 1050000,
+ "maxInputTokens": 922000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 10,
+ "output": 50,
+ "cacheRead": 1,
+ "cacheWrite": 12.5
+ },
+ "releaseDate": "2026-09-04",
+ "family": "gpt-astra"
+ },
+ "google/gemini-3.8-flash": {
+ "id": "google/gemini-3.8-flash",
+ "name": "Gemini 3.8 Flash",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1.5,
+ "output": 7.5,
+ "cacheRead": 0.15,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-09-02",
+ "family": "gemini-flash",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio",
+ "pdf"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
+ "meta/muse-spark-1.3": {
+ "id": "meta/muse-spark-1.3",
+ "name": "Muse Spark 1.3",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 131072,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1.25,
+ "output": 4.25,
+ "cacheRead": 0.15,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-09-02",
+ "family": "muse",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "pdf",
+ "audio"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
+ "meta/muse-spark-1.3-contributor": {
+ "id": "meta/muse-spark-1.3-contributor",
+ "name": "Muse Spark 1.3 (Contributor)",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 131072,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.1,
+ "output": 0.2,
+ "cacheRead": 0.002,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-09-02",
+ "family": "muse",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "pdf",
+ "audio"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
+ "Qwen/Qwen3.8-Max-0902": {
+ "id": "Qwen/Qwen3.8-Max-0902",
+ "name": "Qwen3.8 Max 0902",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 131072,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 6,
+ "cacheRead": 0.25,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-09-02",
+ "family": "qwen"
+ },
+ "claude-fable-5-1": {
+ "id": "claude-fable-5-1",
+ "name": "Claude Fable 5.1",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 10,
+ "output": 50,
+ "cacheRead": 0.25,
+ "cacheWrite": 12.5
+ },
+ "releaseDate": "2026-09-01",
+ "family": "claude-fable",
+ "metadata": {
+ "apiProtocol": "anthropic"
+ }
+ },
+ "tencent/hy4-preview": {
+ "id": "tencent/hy4-preview",
+ "name": "Hy4 preview",
+ "contextWindow": 1024000,
+ "maxInputTokens": 1024000,
+ "maxTokens": 64000,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.834,
+ "output": 2.501,
+ "cacheRead": 0.042,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-08-28",
+ "family": "Hy"
+ },
+ "Qwen/Qwen3.8-Flash": {
+ "id": "Qwen/Qwen3.8-Flash",
+ "name": "Qwen3.8 Flash",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 131072,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.16,
+ "output": 0.47,
+ "cacheRead": 0.016,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-08-26",
+ "family": "qwen"
+ },
+ "z-ai/glm-5.3-flash": {
+ "id": "z-ai/glm-5.3-flash",
+ "name": "GLM-5.3-Flash",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 131072,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "high",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.15,
+ "output": 0.5,
+ "cacheRead": 0.03,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-08-26",
+ "family": "glm-flash"
+ },
+ "z-ai/glm-5.3-flashx": {
+ "id": "z-ai/glm-5.3-flashx",
+ "name": "GLM-5.3-FlashX",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 131072,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "high",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.37,
+ "output": 1.25,
+ "cacheRead": 0.075,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-08-26",
+ "family": "glm-flash"
+ },
+ "deepseek/deepseek-v4-flash-vision-exp": {
+ "id": "deepseek/deepseek-v4-flash-vision-exp",
+ "name": "DeepSeek V4 Flash Vision Exp",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 384000,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "toggle"
+ },
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "high",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.15,
+ "output": 0.6,
+ "cacheRead": 0.003,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-08-21",
+ "family": "deepseek-flash"
+ },
+ "Qwen/Qwen3.8-27B": {
+ "id": "Qwen/Qwen3.8-27B",
+ "name": "Qwen3.8 27B",
+ "contextWindow": 262144,
+ "maxInputTokens": 262144,
+ "maxTokens": 32768,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.4,
+ "output": 3,
+ "cacheRead": 0.04,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-08-14",
+ "family": "qwen"
+ },
+ "zai-org/GLM-5.3": {
+ "id": "zai-org/GLM-5.3",
+ "name": "GLM-5.3",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 131072,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "high",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1.4,
+ "output": 4.4,
+ "cacheRead": 0.26,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-08-14",
+ "family": "glm"
+ },
+ "google/gemini-3.7-flash": {
+ "id": "google/gemini-3.7-flash",
+ "name": "Gemini 3.7 Flash",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1.5,
+ "output": 7.5,
+ "cacheRead": 0.15,
+ "cacheWrite": 0.08334
+ },
+ "releaseDate": "2026-08-13",
+ "family": "gemini-flash",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio",
+ "pdf"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
+ "xai/grok-4.6": {
+ "id": "xai/grok-4.6",
+ "name": "Grok 4.6",
+ "contextWindow": 500000,
+ "maxInputTokens": 500000,
+ "maxTokens": 500000,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 6,
+ "cacheRead": 0.5,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-08-12",
+ "family": "grok"
+ },
+ "meta/muse-spark-1.2": {
+ "id": "meta/muse-spark-1.2",
+ "name": "Muse Spark 1.2",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 131072,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1.25,
+ "output": 4.25,
+ "cacheRead": 0.15,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-08-05",
+ "family": "muse",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "pdf",
+ "audio"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
+ "meta/muse-spark-1.2-contributor": {
+ "id": "meta/muse-spark-1.2-contributor",
+ "name": "Muse Spark 1.2 (Contributor)",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 131072,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.1,
+ "output": 0.2,
+ "cacheRead": 0.002,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-08-05",
+ "family": "muse",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "pdf",
+ "audio"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
+ "Qwen/Qwen3.8-Max": {
+ "id": "Qwen/Qwen3.8-Max",
+ "name": "Qwen3.8 Max",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 131072,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 6,
+ "cacheRead": 0.25,
+ "cacheWrite": 2.5
+ },
+ "releaseDate": "2026-08-03",
+ "family": "qwen"
+ },
+ "thinkingmachines/inkling-small": {
+ "id": "thinkingmachines/inkling-small",
+ "name": "Inkling Small",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 1000000,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.5,
+ "output": 1.2,
+ "cacheRead": 0.1,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-07-30",
+ "family": "ling",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "audio"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
+ "claude-opus-5": {
+ "id": "claude-opus-5",
+ "name": "Claude Opus 5",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 5,
+ "output": 25,
+ "cacheRead": 0.5,
+ "cacheWrite": 6.25
+ },
+ "releaseDate": "2026-07-24",
+ "family": "claude-opus",
+ "metadata": {
+ "apiProtocol": "anthropic"
+ }
+ },
+ "google/gemini-3.5-flash-lite": {
+ "id": "google/gemini-3.5-flash-lite",
+ "name": "Gemini 3.5 Flash Lite",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.3,
+ "output": 2.5,
+ "cacheRead": 0.03,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-07-21",
+ "family": "gemini-flash-lite",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio",
+ "pdf"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
+ "google/gemini-3.6-flash": {
+ "id": "google/gemini-3.6-flash",
+ "name": "Gemini 3.6 Flash",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1.5,
+ "output": 7.5,
+ "cacheRead": 0.15,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-07-21",
+ "family": "gemini-flash",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio",
+ "pdf"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
+ "moonshotai/Kimi-K3": {
+ "id": "moonshotai/Kimi-K3",
+ "name": "Kimi K3",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 131072,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "high",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 3,
+ "output": 15,
+ "cacheRead": 0.3,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-07-16",
+ "family": "kimi-k3"
+ },
+ "thinkingmachines/inkling": {
+ "id": "thinkingmachines/inkling",
+ "name": "Inkling",
+ "contextWindow": 256000,
+ "maxInputTokens": 256000,
+ "maxTokens": 256000,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1,
+ "output": 4.05,
+ "cacheRead": 0.17,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-07-15",
+ "family": "ling",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "audio"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
+ "gpt-5.6-luna": {
+ "id": "gpt-5.6-luna",
+ "name": "GPT-5.6 Luna",
+ "contextWindow": 1050000,
+ "maxInputTokens": 922000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.2,
+ "output": 1.2,
+ "cacheRead": 0.02,
+ "cacheWrite": 0.25
+ },
+ "releaseDate": "2026-07-09",
+ "family": "gpt-luna"
+ },
+ "gpt-5.6-sol": {
+ "id": "gpt-5.6-sol",
+ "name": "GPT-5.6 Sol",
+ "contextWindow": 1050000,
+ "maxInputTokens": 922000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 5,
+ "output": 30,
+ "cacheRead": 0.5,
+ "cacheWrite": 6.25
+ },
+ "releaseDate": "2026-07-09",
+ "family": "gpt-sol"
+ },
+ "gpt-5.6-terra": {
+ "id": "gpt-5.6-terra",
+ "name": "GPT-5.6 Terra",
+ "contextWindow": 1050000,
+ "maxInputTokens": 922000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 12,
+ "cacheRead": 0.2,
+ "cacheWrite": 2.5
+ },
+ "releaseDate": "2026-07-09",
+ "family": "gpt-terra"
+ },
+ "xai/grok-4.5": {
+ "id": "xai/grok-4.5",
+ "name": "Grok 4.5",
+ "contextWindow": 500000,
+ "maxInputTokens": 500000,
+ "maxTokens": 500000,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 6,
+ "cacheRead": 0.5,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-07-08",
+ "family": "grok"
+ },
+ "tencent/hy3-paid": {
+ "id": "tencent/hy3-paid",
+ "name": "Hy3",
+ "contextWindow": 256000,
+ "maxInputTokens": 192000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.14,
+ "output": 0.58,
+ "cacheRead": 0.035,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-07-06",
+ "family": "Hy"
+ },
+ "claude-sonnet-5": {
+ "id": "claude-sonnet-5",
+ "name": "Claude Sonnet 5",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "toggle"
+ },
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 10,
+ "cacheRead": 0.2,
+ "cacheWrite": 2.5
+ },
+ "releaseDate": "2026-06-30",
+ "family": "claude-sonnet",
+ "metadata": {
+ "apiProtocol": "anthropic"
+ }
+ },
+ "sakana/fugu-ultra": {
+ "id": "sakana/fugu-ultra",
+ "name": "Fugu Ultra",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 5,
+ "output": 30,
+ "cacheRead": 0.5,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-06-15",
+ "family": "fugu"
+ },
+ "zai-org/GLM-5.2": {
+ "id": "zai-org/GLM-5.2",
+ "name": "GLM-5.2",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 131072,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "high",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1.4,
+ "output": 4.4,
+ "cacheRead": 0.26,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-06-13",
+ "family": "glm"
+ },
+ "zai-org/GLM-5.2-Fast": {
+ "id": "zai-org/GLM-5.2-Fast",
+ "name": "GLM-5.2-Fast",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 131072,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "high",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 3,
+ "output": 10.25,
+ "cacheRead": 0.5,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-06-13",
+ "family": "glm"
+ },
+ "moonshotai/Kimi-K2.7-Code": {
+ "id": "moonshotai/Kimi-K2.7-Code",
+ "name": "Kimi K2.7 Code",
+ "contextWindow": 256000,
+ "maxInputTokens": 256000,
+ "maxTokens": 256000,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [],
+ "pricing": {
+ "input": 0.95,
+ "output": 4,
+ "cacheRead": 0.19,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-06-12",
+ "family": "kimi-k2"
+ },
+ "moonshotai/Kimi-K2.7-Code-Highspeed": {
+ "id": "moonshotai/Kimi-K2.7-Code-Highspeed",
+ "name": "Kimi K2.7 Code Highspeed",
+ "contextWindow": 262000,
+ "maxInputTokens": 262000,
+ "maxTokens": 262000,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [],
+ "pricing": {
+ "input": 1.9,
+ "output": 8,
+ "cacheRead": 0.38,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-06-12",
+ "family": "kimi-k2"
+ },
+ "claude-fable-5": {
+ "id": "claude-fable-5",
+ "name": "Claude Fable 5",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 10,
+ "output": 50,
+ "cacheRead": 1,
+ "cacheWrite": 12.5
+ },
+ "releaseDate": "2026-06-09",
+ "family": "claude-fable",
+ "metadata": {
+ "apiProtocol": "anthropic"
+ }
+ },
+ "nvidia/nemotron-3-ultra-550b-a55b": {
+ "id": "nvidia/nemotron-3-ultra-550b-a55b",
+ "name": "Nemotron 3 Ultra 550B A55B",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "toggle"
+ }
+ ],
+ "pricing": {
+ "input": 0.6,
+ "output": 2.4,
+ "cacheRead": 0.12,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-06-04",
+ "family": "nemotron"
+ },
+ "MiniMaxAI/MiniMax-M3": {
+ "id": "MiniMaxAI/MiniMax-M3",
+ "name": "MiniMax-M3",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 512000,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "toggle"
+ }
+ ],
+ "pricing": {
+ "input": 0.3,
+ "output": 1.2,
+ "cacheRead": 0.06,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-06-01",
+ "family": "minimax"
+ },
+ "stepfun/Step-3.7-Flash": {
+ "id": "stepfun/Step-3.7-Flash",
+ "name": "Step 3.7 Flash",
+ "contextWindow": 256000,
+ "maxInputTokens": 256000,
+ "maxTokens": 256000,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.2,
+ "output": 1.15,
+ "cacheRead": 0.04,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-05-29"
+ },
+ "claude-opus-4-8": {
+ "id": "claude-opus-4-8",
+ "name": "Claude Opus 4.8",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 5,
+ "output": 25,
+ "cacheRead": 0.5,
+ "cacheWrite": 6.25
+ },
+ "releaseDate": "2026-05-28",
+ "family": "claude-opus",
+ "metadata": {
+ "apiProtocol": "anthropic"
+ }
+ },
+ "google/gemini-3.5-flash": {
+ "id": "google/gemini-3.5-flash",
+ "name": "Gemini 3.5 Flash",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1.5,
+ "output": 9,
+ "cacheRead": 0.15,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-05-19",
+ "family": "gemini-flash",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio",
+ "pdf"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
+ "google/gemini-3.1-flash-lite": {
+ "id": "google/gemini-3.1-flash-lite",
+ "name": "Gemini 3.1 Flash Lite",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.25,
+ "output": 1.5,
+ "cacheRead": 0.03,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-05-07",
+ "family": "gemini-flash-lite",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio",
+ "pdf"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
+ "deepseek/deepseek-v4-flash": {
+ "id": "deepseek/deepseek-v4-flash",
+ "name": "DeepSeek V4 Flash",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 384000,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "toggle"
+ },
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "high",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.15,
+ "output": 0.6,
+ "cacheRead": 0.003,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-04-24",
+ "family": "deepseek-flash"
+ },
+ "deepseek/deepseek-v4-flash-fast": {
+ "id": "deepseek/deepseek-v4-flash-fast",
+ "name": "DeepSeek V4 Flash Fast",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 384000,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "high",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.28,
+ "output": 0.56,
+ "cacheRead": 0.07,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-04-24",
+ "family": "deepseek-flash"
+ },
+ "deepseek/deepseek-v4-pro": {
+ "id": "deepseek/deepseek-v4-pro",
+ "name": "DeepSeek V4 Pro",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 384000,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "toggle"
+ },
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "high",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.66,
+ "output": 1.98,
+ "cacheRead": 0.022,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-04-24",
+ "family": "deepseek-thinking"
+ },
+ "gpt-5.5": {
+ "id": "gpt-5.5",
+ "name": "GPT-5.5",
+ "contextWindow": 400000,
+ "maxInputTokens": 400000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 5,
+ "output": 30,
+ "cacheRead": 0.5,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-04-23",
+ "family": "gpt"
+ },
+ "claude-opus-4-7": {
+ "id": "claude-opus-4-7",
+ "name": "Claude Opus 4.7",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 5,
+ "output": 25,
+ "cacheRead": 0.5,
+ "cacheWrite": 6.25
+ },
+ "releaseDate": "2026-04-16",
+ "family": "claude-opus",
+ "metadata": {
+ "apiProtocol": "anthropic"
+ }
+ },
+ "meta/muse-spark-1.1": {
+ "id": "meta/muse-spark-1.1",
+ "name": "Muse Spark 1.1",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 131072,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1.25,
+ "output": 4.25,
+ "cacheRead": 0.15,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-04-08",
+ "family": "muse"
+ },
+ "MiniMaxAI/MiniMax-M2.7": {
+ "id": "MiniMaxAI/MiniMax-M2.7",
+ "name": "MiniMax-M2.7",
+ "contextWindow": 200000,
+ "maxInputTokens": 200000,
+ "maxTokens": 131072,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [],
+ "pricing": {
+ "input": 0.3,
+ "output": 1.2,
+ "cacheRead": 0.06,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-03-18",
+ "family": "minimax"
+ },
+ "gpt-5.4-mini": {
+ "id": "gpt-5.4-mini",
+ "name": "GPT-5.4 mini",
+ "contextWindow": 400000,
+ "maxInputTokens": 272000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.75,
+ "output": 4.5,
+ "cacheRead": 0.075,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-03-17",
+ "family": "gpt-mini"
+ },
+ "gpt-5.4": {
+ "id": "gpt-5.4",
+ "name": "GPT-5.4",
+ "contextWindow": 400000,
+ "maxInputTokens": 400000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2.5,
+ "output": 15,
+ "cacheRead": 0.25,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-03-05",
+ "family": "gpt"
+ },
+ "claude-sonnet-4-6": {
+ "id": "claude-sonnet-4-6",
+ "name": "Claude Sonnet 4.6",
+ "contextWindow": 1000000,
+ "maxInputTokens": 1000000,
+ "maxTokens": 64000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "max"
+ ]
+ },
+ {
+ "type": "budget_tokens"
+ }
+ ],
+ "pricing": {
+ "input": 3,
+ "output": 15,
+ "cacheRead": 0.3,
+ "cacheWrite": 3.75
+ },
+ "releaseDate": "2026-02-17",
+ "family": "claude-sonnet",
+ "metadata": {
+ "apiProtocol": "anthropic"
+ }
+ },
+ "MiniMaxAI/MiniMax-M2.5": {
+ "id": "MiniMaxAI/MiniMax-M2.5",
+ "name": "MiniMax-M2.5",
+ "contextWindow": 200000,
+ "maxInputTokens": 200000,
+ "maxTokens": 131072,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [],
+ "pricing": {
+ "input": 0.3,
+ "output": 1.2,
+ "cacheRead": 0.03,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-02-12",
+ "family": "minimax"
+ },
+ "gpt-5.3-codex": {
+ "id": "gpt-5.3-codex",
+ "name": "GPT-5.3 Codex",
+ "contextWindow": 400000,
+ "maxInputTokens": 272000,
+ "maxTokens": 128000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 2,
+ "output": 8,
+ "cacheRead": 0.5,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-02-05",
+ "family": "gpt-codex"
+ },
+ "stepfun/Step-3.5-Flash": {
+ "id": "stepfun/Step-3.5-Flash",
+ "name": "Step 3.5 Flash",
+ "contextWindow": 256000,
+ "maxInputTokens": 256000,
+ "maxTokens": 256000,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.09,
+ "output": 0.3,
+ "cacheRead": 0.02,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-01-29"
+ },
+ "claude-haiku-4-5-20251001": {
+ "id": "claude-haiku-4-5-20251001",
+ "name": "Claude Haiku 4.5",
+ "contextWindow": 200000,
+ "maxInputTokens": 200000,
+ "maxTokens": 64000,
+ "capabilities": [
+ "images",
+ "files",
+ "tools",
+ "reasoning",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "budget_tokens"
+ }
+ ],
+ "pricing": {
+ "input": 1,
+ "output": 5,
+ "cacheRead": 0.1,
+ "cacheWrite": 1.25
+ },
+ "releaseDate": "2025-10-15",
+ "family": "claude-haiku",
+ "metadata": {
+ "apiProtocol": "anthropic"
+ }
+ }
+ },
"coralbricks": {
"deepseek-v4.1-flash-fast": {
"id": "deepseek-v4.1-flash-fast",
@@ -38138,27 +40749,6 @@ export const GENERATED_PROVIDER_MODELS: {
},
"releaseDate": "2024-08-07"
},
- "llama-3.1-8b-instruct": {
- "id": "llama-3.1-8b-instruct",
- "name": "Llama-3.1-8B-Instruct",
- "contextWindow": 128000,
- "maxInputTokens": 128000,
- "maxTokens": 128000,
- "capabilities": [
- "tools",
- "reasoning",
- "structured_output"
- ],
- "reasoningOptions": [],
- "pricing": {
- "input": 0.167,
- "output": 0.167,
- "cacheRead": 0,
- "cacheWrite": 0
- },
- "releaseDate": "2024-07-23",
- "family": "llama"
- },
"gpt-4o-mini": {
"id": "gpt-4o-mini",
"name": "GPT-4o mini",
@@ -42211,6 +44801,52 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-06-12",
"family": "kimi-k2"
},
+ "databricks-gemini-3-5-flash": {
+ "id": "databricks-gemini-3-5-flash",
+ "name": "Gemini 3.5 Flash",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "minimal",
+ "low",
+ "medium",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1.5,
+ "output": 9,
+ "cacheRead": 0.15,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-05-19",
+ "family": "gemini-flash",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
"databricks-gpt-5-5": {
"id": "databricks-gpt-5-5",
"name": "GPT-5.5",
@@ -43481,8 +46117,6 @@ export const GENERATED_PROVIDER_MODELS: {
"maxInputTokens": 1048576,
"maxTokens": 131072,
"capabilities": [
- "images",
- "video",
"tools",
"reasoning",
"structured_output",
@@ -46109,6 +48743,102 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"edenai": {
+ "fireworks_ai/accounts/fireworks/models/muse-spark-open": {
+ "id": "fireworks_ai/accounts/fireworks/models/muse-spark-open",
+ "name": "Muse Spark Open (Fireworks AI)",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 131072,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1.25,
+ "output": 4.25,
+ "cacheRead": 0.15,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-15",
+ "family": "muse",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "pdf",
+ "audio"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
+ "nebius/meta-models/muse-spark-open": {
+ "id": "nebius/meta-models/muse-spark-open",
+ "name": "Muse Spark Open (Nebius)",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 131072,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1.25,
+ "output": 4.25,
+ "cacheRead": 1.25,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-15",
+ "family": "muse",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "pdf",
+ "audio"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
"google/gemini-4-argon": {
"id": "google/gemini-4-argon",
"name": "Gemini 4 Argon",
@@ -46976,9 +49706,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.246576,
- "output": 1.23288,
- "cacheRead": 0.012329,
+ "input": 0.247566,
+ "output": 1.23783,
+ "cacheRead": 0.012378,
"cacheWrite": 0
},
"releaseDate": "2026-09-10",
@@ -47076,9 +49806,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.67248,
- "output": 2.01744,
- "cacheRead": 0.134496,
+ "input": 0.67518,
+ "output": 2.02554,
+ "cacheRead": 0.135036,
"cacheWrite": 0
},
"releaseDate": "2026-09-10",
@@ -48720,9 +51450,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.156912,
- "output": 0.39228,
- "cacheRead": 0.044832,
+ "input": 0.157542,
+ "output": 0.393855,
+ "cacheRead": 0.045012,
"cacheWrite": 0
},
"releaseDate": "2026-07-31",
@@ -48818,9 +51548,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.44832,
- "output": 0.89664,
- "cacheRead": 0.089664,
+ "input": 0.45012,
+ "output": 0.90024,
+ "cacheRead": 0.090024,
"cacheWrite": 0
},
"releaseDate": "2026-07-31",
@@ -51663,8 +54393,8 @@ export const GENERATED_PROVIDER_MODELS: {
"temperature"
],
"pricing": {
- "input": 0.16812,
- "output": 0.89664,
+ "input": 0.168795,
+ "output": 0.90024,
"cacheRead": 0,
"cacheWrite": 0
},
@@ -52203,8 +54933,8 @@ export const GENERATED_PROVIDER_MODELS: {
"temperature"
],
"pricing": {
- "input": 0.33624,
- "output": 0.44832,
+ "input": 0.33759,
+ "output": 0.45012,
"cacheRead": 0,
"cacheWrite": 0
},
@@ -53387,8 +56117,8 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.22416,
- "output": 0.78456,
+ "input": 0.22506,
+ "output": 0.78771,
"cacheRead": 0,
"cacheWrite": 0
},
@@ -53482,8 +56212,8 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.16812,
- "output": 0.72852,
+ "input": 0.168795,
+ "output": 0.731445,
"cacheRead": 0,
"cacheWrite": 0
},
@@ -53606,8 +56336,8 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.16812,
- "output": 0.67248,
+ "input": 0.168795,
+ "output": 0.67518,
"cacheRead": 0,
"cacheWrite": 0
},
@@ -53719,8 +56449,8 @@ export const GENERATED_PROVIDER_MODELS: {
"temperature"
],
"pricing": {
- "input": 1.00872,
- "output": 3.026159,
+ "input": 1.01277,
+ "output": 3.03831,
"cacheRead": 0,
"cacheWrite": 0
},
@@ -53759,8 +56489,8 @@ export const GENERATED_PROVIDER_MODELS: {
"temperature"
],
"pricing": {
- "input": 0.8406,
- "output": 2.5218,
+ "input": 0.843975,
+ "output": 2.531925,
"cacheRead": 0,
"cacheWrite": 0
},
@@ -54160,8 +56890,8 @@ export const GENERATED_PROVIDER_MODELS: {
"temperature"
],
"pricing": {
- "input": 0.22416,
- "output": 0.89664,
+ "input": 0.22506,
+ "output": 0.90024,
"cacheRead": 0,
"cacheWrite": 0
},
@@ -54626,8 +57356,8 @@ export const GENERATED_PROVIDER_MODELS: {
"temperature"
],
"pricing": {
- "input": 1.23288,
- "output": 1.23288,
+ "input": 1.23783,
+ "output": 1.23783,
"cacheRead": 0,
"cacheWrite": 0
},
@@ -54646,8 +57376,8 @@ export const GENERATED_PROVIDER_MODELS: {
"temperature"
],
"pricing": {
- "input": 0.72852,
- "output": 0.72852,
+ "input": 0.731445,
+ "output": 0.731445,
"cacheRead": 0,
"cacheWrite": 0
},
@@ -54665,8 +57395,8 @@ export const GENERATED_PROVIDER_MODELS: {
"temperature"
],
"pricing": {
- "input": 1.00872,
- "output": 1.00872,
+ "input": 1.01277,
+ "output": 1.01277,
"cacheRead": 0,
"cacheWrite": 0
},
@@ -57378,8 +60108,8 @@ export const GENERATED_PROVIDER_MODELS: {
"deepseek-v4.1-flash": {
"id": "deepseek-v4.1-flash",
"name": "DeepSeek V4.1 Flash",
- "contextWindow": 327680,
- "maxInputTokens": 262144,
+ "contextWindow": 1048576,
+ "maxInputTokens": 983040,
"maxTokens": 65536,
"capabilities": [
"images",
@@ -57414,8 +60144,8 @@ export const GENERATED_PROVIDER_MODELS: {
"glm-5.3-flash": {
"id": "glm-5.3-flash",
"name": "GLM-5.3-Flash",
- "contextWindow": 262144,
- "maxInputTokens": 229376,
+ "contextWindow": 327680,
+ "maxInputTokens": 294912,
"maxTokens": 32768,
"capabilities": [
"images",
@@ -77803,6 +80533,69 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"kilo": {
+ "reflection/beam-1.0-501b-a23b": {
+ "id": "reflection/beam-1.0-501b-a23b",
+ "name": "Reflection: Beam 1.0 501B A23B",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 943718,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.25,
+ "output": 1,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-16",
+ "family": "beam"
+ },
+ "xingchen-agi/xing4.0-29b-a4b:free": {
+ "id": "xingchen-agi/xing4.0-29b-a4b:free",
+ "name": "XingChen: Xing4.0 29B A4B (free)",
+ "contextWindow": 262144,
+ "maxInputTokens": 262144,
+ "maxTokens": 235929,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0,
+ "output": 0,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-16",
+ "family": "agi"
+ },
"meta/muse-spark-open": {
"id": "meta/muse-spark-open",
"name": "Muse Spark Open",
@@ -79074,9 +81867,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.0144,
- "output": 0.684,
- "cacheRead": 0.0054,
+ "input": 0.032,
+ "output": 0.144,
+ "cacheRead": 0.0016,
"cacheWrite": 0
},
"releaseDate": "2026-09-14",
@@ -79107,9 +81900,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.225,
- "output": 8,
- "cacheRead": 0.23,
+ "input": 0.24948,
+ "output": 0.74844,
+ "cacheRead": 0.007938,
"cacheWrite": 0
},
"releaseDate": "2026-09-14",
@@ -79328,7 +82121,7 @@ export const GENERATED_PROVIDER_MODELS: {
"name": "DeepSeek V4.1 Flash",
"contextWindow": 1048576,
"maxInputTokens": 1048576,
- "maxTokens": 393216,
+ "maxTokens": 943718,
"capabilities": [
"images",
"tools",
@@ -79776,9 +82569,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.801,
- "output": 2.48,
- "cacheRead": 0.038,
+ "input": 0.834,
+ "output": 2.501,
+ "cacheRead": 0.042,
"cacheWrite": 0
},
"releaseDate": "2026-08-28",
@@ -79789,7 +82582,7 @@ export const GENERATED_PROVIDER_MODELS: {
"name": "Z.ai: GLM Flash Latest",
"contextWindow": 1048576,
"maxInputTokens": 1048576,
- "maxTokens": 131072,
+ "maxTokens": 943718,
"capabilities": [
"images",
"video",
@@ -79810,9 +82603,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.0139,
- "output": 0.8132,
- "cacheRead": 0.0125,
+ "input": 0.04,
+ "output": 0.2,
+ "cacheRead": 0.006,
"cacheWrite": 0
},
"releaseDate": "2026-08-27",
@@ -79854,9 +82647,9 @@ export const GENERATED_PROVIDER_MODELS: {
"z-ai/glm-5.3-flash": {
"id": "z-ai/glm-5.3-flash",
"name": "GLM-5.3-Flash",
- "contextWindow": 1048575,
- "maxInputTokens": 1048575,
- "maxTokens": 943717,
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 943718,
"capabilities": [
"images",
"video",
@@ -79961,7 +82754,7 @@ export const GENERATED_PROVIDER_MODELS: {
"name": "Z.ai: GLM Latest",
"contextWindow": 1048576,
"maxInputTokens": 1048576,
- "maxTokens": 131072,
+ "maxTokens": 943718,
"capabilities": [
"tools",
"reasoning",
@@ -79980,9 +82773,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.0608,
- "output": 4.4,
- "cacheRead": 0.0565,
+ "input": 0.079,
+ "output": 4.8,
+ "cacheRead": 0.078,
"cacheWrite": 0
},
"releaseDate": "2026-08-19",
@@ -80518,9 +83311,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.0058,
- "output": 0.64,
- "cacheRead": 0.0058,
+ "input": 0.00392,
+ "output": 0.143616,
+ "cacheRead": 0.001523,
"cacheWrite": 0
},
"releaseDate": "2026-08-01",
@@ -82285,9 +85078,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.33,
- "output": 14,
- "cacheRead": 0.3,
+ "input": 0.294,
+ "output": 24,
+ "cacheRead": 0.284,
"cacheWrite": 0
},
"releaseDate": "2026-04-27",
@@ -84826,17 +87619,17 @@ export const GENERATED_PROVIDER_MODELS: {
"deepseek/deepseek-chat": {
"id": "deepseek/deepseek-chat",
"name": "DeepSeek Chat",
- "contextWindow": 128000,
- "maxInputTokens": 128000,
- "maxTokens": 16000,
+ "contextWindow": 163840,
+ "maxInputTokens": 163840,
+ "maxTokens": 16384,
"capabilities": [
"tools",
"structured_output",
"temperature"
],
"pricing": {
- "input": 0.2574,
- "output": 1.0287,
+ "input": 0.32,
+ "output": 0.89,
"cacheRead": 0,
"cacheWrite": 0
},
@@ -85502,6 +88295,38 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2025-09",
"family": "qwen"
},
+ "reflection/beam-free": {
+ "id": "reflection/beam-free",
+ "name": "Reflection: Beam 1.0 (free)",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 131072,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "temperature"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0,
+ "output": 0,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2025-08-26",
+ "family": "beam"
+ },
"stealth/claude-opus-4.6": {
"id": "stealth/claude-opus-4.6",
"name": "Stealth: Claude Opus 4.6 (20% off)",
@@ -86796,9 +89621,9 @@ export const GENERATED_PROVIDER_MODELS: {
"meta-llama/llama-4-scout": {
"id": "meta-llama/llama-4-scout",
"name": "Meta: Llama 4 Scout",
- "contextWindow": 131072,
- "maxInputTokens": 131072,
- "maxTokens": 117964,
+ "contextWindow": 327680,
+ "maxInputTokens": 327680,
+ "maxTokens": 16384,
"capabilities": [
"images",
"tools",
@@ -87063,7 +89888,7 @@ export const GENERATED_PROVIDER_MODELS: {
"name": "Llama-3.3-70B-Instruct",
"contextWindow": 131072,
"maxInputTokens": 131072,
- "maxTokens": 32768,
+ "maxTokens": 16384,
"capabilities": [
"tools",
"structured_output",
@@ -97416,53 +100241,6 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-08-14",
"family": "glm"
},
- "google-ai-studio/gemini-3.7-flash": {
- "id": "google-ai-studio/gemini-3.7-flash",
- "name": "Gemini 3.7 Flash (Google AI Studio)",
- "contextWindow": 1048576,
- "maxInputTokens": 1048576,
- "maxTokens": 65536,
- "capabilities": [
- "images",
- "video",
- "files",
- "tools",
- "reasoning",
- "structured_output",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [
- {
- "type": "effort",
- "values": [
- "low",
- "medium",
- "high"
- ]
- }
- ],
- "pricing": {
- "input": 0.75,
- "output": 3.75,
- "cacheRead": 0.075,
- "cacheWrite": 0.08333
- },
- "releaseDate": "2026-08-13",
- "family": "gemini-flash",
- "modalities": {
- "input": [
- "text",
- "image",
- "video",
- "audio",
- "pdf"
- ],
- "output": [
- "text"
- ]
- }
- },
"google-vertex/gemini-3.7-flash": {
"id": "google-vertex/gemini-3.7-flash",
"name": "Gemini 3.7 Flash (Google Vertex AI)",
@@ -100437,54 +103215,6 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-05-20",
"family": "grok-build"
},
- "google-ai-studio/gemini-3.5-flash": {
- "id": "google-ai-studio/gemini-3.5-flash",
- "name": "Gemini 3.5 Flash (Google AI Studio)",
- "contextWindow": 1048576,
- "maxInputTokens": 1048576,
- "maxTokens": 65536,
- "capabilities": [
- "images",
- "video",
- "files",
- "tools",
- "reasoning",
- "structured_output",
- "temperature",
- "prompt-cache"
- ],
- "reasoningOptions": [
- {
- "type": "effort",
- "values": [
- "minimal",
- "low",
- "medium",
- "high"
- ]
- }
- ],
- "pricing": {
- "input": 1.5,
- "output": 9,
- "cacheRead": 0.15,
- "cacheWrite": 0.08333
- },
- "releaseDate": "2026-05-19",
- "family": "gemini-flash",
- "modalities": {
- "input": [
- "text",
- "image",
- "video",
- "audio",
- "pdf"
- ],
- "output": [
- "text"
- ]
- }
- },
"google-vertex/gemini-3.5-flash": {
"id": "google-vertex/gemini-3.5-flash",
"name": "Gemini 3.5 Flash (Google Vertex AI)",
@@ -113891,6 +116621,103 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"nano-gpt": {
+ "heabsy/qwen3.8-27b-uncensored-fast": {
+ "id": "heabsy/qwen3.8-27b-uncensored-fast",
+ "name": "Qwen 3.8 27B Uncensored Fast by Heabsy",
+ "contextWindow": 524288,
+ "maxInputTokens": 524288,
+ "maxTokens": 235929,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "high"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1,
+ "output": 3,
+ "cacheRead": 0.22,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-16",
+ "family": "qwen"
+ },
+ "reflection/beam-1.0": {
+ "id": "reflection/beam-1.0",
+ "name": "Beam 1.0 501B A23B",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 131072,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.45,
+ "output": 1.25,
+ "cacheRead": 0.04,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-16",
+ "family": "beam"
+ },
+ "meta/muse-spark-open": {
+ "id": "meta/muse-spark-open",
+ "name": "Muse Spark Open",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 131072,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1.25,
+ "output": 4.25,
+ "cacheRead": 0.15,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-15",
+ "family": "muse"
+ },
"nvidia/nemotron-3.5-super-vl": {
"id": "nvidia/nemotron-3.5-super-vl",
"name": "Nvidia Nemotron 3.5 Super VL",
@@ -114909,6 +117736,38 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-09-22",
"family": "claude-opus"
},
+ "fireworks/ember-1": {
+ "id": "fireworks/ember-1",
+ "name": "Ember 1",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 131072,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "high",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 3,
+ "output": 15,
+ "cacheRead": 0.3,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-09-22"
+ },
"openai/gpt-6-luna": {
"id": "openai/gpt-6-luna",
"name": "GPT 6 Luna",
@@ -116466,9 +119325,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.44,
- "output": 1.32,
- "cacheRead": 0.014,
+ "input": 0.22,
+ "output": 0.66,
+ "cacheRead": 0.007,
"cacheWrite": 0
},
"releaseDate": "2026-08-21",
@@ -124054,9 +126913,9 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"pricing": {
- "input": 0.09,
+ "input": 0.1,
"output": 1.1,
- "cacheRead": 0.075,
+ "cacheRead": 0.07,
"cacheWrite": 0
},
"releaseDate": "2025-09",
@@ -133195,10 +136054,10 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.08,
- "output": 0.4,
- "cacheRead": 0.008,
- "cacheWrite": 0.1
+ "input": 0.1,
+ "output": 0.5,
+ "cacheRead": 0.01,
+ "cacheWrite": 0.125
},
"releaseDate": "2026-09-22",
"family": "gpt-luna",
@@ -133234,10 +136093,10 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 1.6,
- "output": 8,
- "cacheRead": 0.16,
- "cacheWrite": 2
+ "input": 2,
+ "output": 10,
+ "cacheRead": 0.2,
+ "cacheWrite": 2.5
},
"releaseDate": "2026-09-22",
"family": "gpt-sol",
@@ -133343,9 +136202,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.21,
- "output": 0.84,
- "cacheRead": 0.0042,
+ "input": 0.3,
+ "output": 1.2,
+ "cacheRead": 0.006,
"cacheWrite": 0
},
"releaseDate": "2026-09-10",
@@ -133378,10 +136237,10 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 8,
- "output": 40,
- "cacheRead": 0.8,
- "cacheWrite": 10
+ "input": 10,
+ "output": 50,
+ "cacheRead": 1,
+ "cacheWrite": 12.5
},
"releaseDate": "2026-09-04",
"family": "gpt-astra",
@@ -133863,9 +136722,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.924,
- "output": 2.772,
- "cacheRead": 0.0308,
+ "input": 1.32,
+ "output": 3.96,
+ "cacheRead": 0.044,
"cacheWrite": 0
},
"releaseDate": "2026-08-12",
@@ -134016,9 +136875,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.308,
- "output": 0.924,
- "cacheRead": 0.0098,
+ "input": 0.44,
+ "output": 1.32,
+ "cacheRead": 0.014,
"cacheWrite": 0
},
"releaseDate": "2026-07-31",
@@ -135122,9 +137981,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 4,
- "output": 24,
- "cacheRead": 0.4,
+ "input": 5,
+ "output": 30,
+ "cacheRead": 0.5,
"cacheWrite": 0
},
"releaseDate": "2026-04-23",
@@ -135565,9 +138424,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.6,
- "output": 3.6,
- "cacheRead": 0.06,
+ "input": 0.75,
+ "output": 4.5,
+ "cacheRead": 0.075,
"cacheWrite": 0
},
"releaseDate": "2026-03-17",
@@ -135603,9 +138462,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.16,
- "output": 1,
- "cacheRead": 0.016,
+ "input": 0.2,
+ "output": 1.25,
+ "cacheRead": 0.02,
"cacheWrite": 0
},
"releaseDate": "2026-03-17",
@@ -135694,9 +138553,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 2,
- "output": 12,
- "cacheRead": 0.2,
+ "input": 2.5,
+ "output": 15,
+ "cacheRead": 0.25,
"cacheWrite": 0
},
"releaseDate": "2026-03-05",
@@ -135727,8 +138586,8 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 24,
- "output": 144,
+ "input": 30,
+ "output": 180,
"cacheRead": 0,
"cacheWrite": 0
},
@@ -136474,9 +139333,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 1.4,
- "output": 11.2,
- "cacheRead": 0.144,
+ "input": 1.75,
+ "output": 14,
+ "cacheRead": 0.18,
"cacheWrite": 0
},
"releaseDate": "2026-02-05",
@@ -136773,9 +139632,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 1.4,
- "output": 11.2,
- "cacheRead": 0.144,
+ "input": 1.75,
+ "output": 14,
+ "cacheRead": 0.18,
"cacheWrite": 0
},
"releaseDate": "2025-12-11",
@@ -136810,9 +139669,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 1.4,
- "output": 11.2,
- "cacheRead": 0.144,
+ "input": 1.75,
+ "output": 14,
+ "cacheRead": 0.18,
"cacheWrite": 0
},
"releaseDate": "2025-12-11",
@@ -136936,9 +139795,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 1,
- "output": 8,
- "cacheRead": 0.104,
+ "input": 1.25,
+ "output": 10,
+ "cacheRead": 0.13,
"cacheWrite": 0
},
"releaseDate": "2025-11-13",
@@ -136972,9 +139831,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 1,
- "output": 8,
- "cacheRead": 0.104,
+ "input": 1.25,
+ "output": 10,
+ "cacheRead": 0.13,
"cacheWrite": 0
},
"releaseDate": "2025-11-13",
@@ -137008,9 +139867,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.2,
- "output": 1.6,
- "cacheRead": 0.024,
+ "input": 0.25,
+ "output": 2,
+ "cacheRead": 0.03,
"cacheWrite": 0
},
"releaseDate": "2025-11-13",
@@ -137285,9 +140144,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 1,
- "output": 8,
- "cacheRead": 0.104,
+ "input": 1.25,
+ "output": 10,
+ "cacheRead": 0.13,
"cacheWrite": 0
},
"releaseDate": "2025-08-07",
@@ -137321,9 +140180,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.2,
- "output": 1.6,
- "cacheRead": 0.024,
+ "input": 0.25,
+ "output": 2,
+ "cacheRead": 0.03,
"cacheWrite": 0
},
"releaseDate": "2025-08-07",
@@ -137345,9 +140204,9 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"pricing": {
- "input": 0.04,
- "output": 0.32,
- "cacheRead": 0.008,
+ "input": 0.05,
+ "output": 0.4,
+ "cacheRead": 0.01,
"cacheWrite": 0
},
"releaseDate": "2025-08-07",
@@ -137647,9 +140506,9 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"pricing": {
- "input": 1.6,
- "output": 6.4,
- "cacheRead": 0.4,
+ "input": 2,
+ "output": 8,
+ "cacheRead": 0.5,
"cacheWrite": 0
},
"releaseDate": "2025-04-14",
@@ -137673,9 +140532,9 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"pricing": {
- "input": 0.32,
- "output": 1.28,
- "cacheRead": 0.08,
+ "input": 0.4,
+ "output": 1.6,
+ "cacheRead": 0.1,
"cacheWrite": 0
},
"releaseDate": "2025-04-14",
@@ -137739,9 +140598,9 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"pricing": {
- "input": 0.12,
- "output": 0.48,
- "cacheRead": 0.06,
+ "input": 0.15,
+ "output": 0.6,
+ "cacheRead": 0.075,
"cacheWrite": 0
},
"releaseDate": "2024-07-18",
@@ -137765,9 +140624,9 @@ export const GENERATED_PROVIDER_MODELS: {
"prompt-cache"
],
"pricing": {
- "input": 2,
- "output": 8,
- "cacheRead": 1,
+ "input": 2.5,
+ "output": 10,
+ "cacheRead": 1.25,
"cacheWrite": 0
},
"releaseDate": "2024-05-13",
@@ -139917,38 +142776,6 @@ export const GENERATED_PROVIDER_MODELS: {
"apiProtocol": "gemini"
}
},
- "cat-jam-free": {
- "id": "cat-jam-free",
- "name": "Cat Jam Free",
- "contextWindow": 1048576,
- "maxInputTokens": 1048576,
- "maxTokens": 131072,
- "capabilities": [
- "tools",
- "reasoning",
- "structured_output",
- "temperature"
- ],
- "reasoningOptions": [
- {
- "type": "effort",
- "values": [
- "low",
- "medium",
- "high",
- "xhigh",
- "max"
- ]
- }
- ],
- "pricing": {
- "input": 0,
- "output": 0,
- "cacheRead": 0,
- "cacheWrite": 0
- },
- "releaseDate": "2026-10-12"
- },
"claude-haiku-5-5": {
"id": "claude-haiku-5-5",
"name": "Claude Haiku 5.5",
@@ -140022,6 +142849,39 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-10-06",
"family": "mistral-large"
},
+ "beam-free": {
+ "id": "beam-free",
+ "name": "Beam Free",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 131072,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0,
+ "output": 0,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-05",
+ "family": "beam"
+ },
"gpt-6.1-sol": {
"id": "gpt-6.1-sol",
"name": "GPT-6.1 Sol",
@@ -140547,57 +143407,6 @@ export const GENERATED_PROVIDER_MODELS: {
"apiProtocol": "openai-responses"
}
},
- "muse-spark-1.3-contributor-free": {
- "id": "muse-spark-1.3-contributor-free",
- "name": "Muse Spark 1.3 Free",
- "contextWindow": 1048576,
- "maxInputTokens": 1048576,
- "maxTokens": 131072,
- "capabilities": [
- "images",
- "video",
- "files",
- "tools",
- "reasoning",
- "structured_output",
- "temperature"
- ],
- "reasoningOptions": [
- {
- "type": "effort",
- "values": [
- "minimal",
- "low",
- "medium",
- "high",
- "xhigh"
- ]
- }
- ],
- "pricing": {
- "input": 0,
- "output": 0,
- "cacheRead": 0,
- "cacheWrite": 0
- },
- "releaseDate": "2026-09-02",
- "family": "muse-free",
- "modalities": {
- "input": [
- "text",
- "image",
- "video",
- "pdf",
- "audio"
- ],
- "output": [
- "text"
- ]
- },
- "metadata": {
- "apiProtocol": "openai-responses"
- }
- },
"claude-fable-5-1": {
"id": "claude-fable-5-1",
"name": "Claude Fable 5.1",
@@ -140670,6 +143479,40 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-08-26",
"family": "glm-flash"
},
+ "glm-5.3-flash-free": {
+ "id": "glm-5.3-flash-free",
+ "name": "GLM-5.3-Flash Free",
+ "contextWindow": 200000,
+ "maxInputTokens": 200000,
+ "maxTokens": 32000,
+ "capabilities": [
+ "images",
+ "video",
+ "files",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "high",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0,
+ "output": 0,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-08-26",
+ "family": "glm-flash"
+ },
"qwen3.8-flash": {
"id": "qwen3.8-flash",
"name": "Qwen3.8 Flash",
@@ -142921,38 +145764,6 @@ export const GENERATED_PROVIDER_MODELS: {
"apiProtocol": "gemini"
}
},
- "cat-jam-free": {
- "id": "cat-jam-free",
- "name": "Cat Jam Free",
- "contextWindow": 1048576,
- "maxInputTokens": 1048576,
- "maxTokens": 131072,
- "capabilities": [
- "tools",
- "reasoning",
- "structured_output",
- "temperature"
- ],
- "reasoningOptions": [
- {
- "type": "effort",
- "values": [
- "low",
- "medium",
- "high",
- "xhigh",
- "max"
- ]
- }
- ],
- "pricing": {
- "input": 0,
- "output": 0,
- "cacheRead": 0,
- "cacheWrite": 0
- },
- "releaseDate": "2026-10-12"
- },
"claude-haiku-5-5": {
"id": "claude-haiku-5-5",
"name": "Claude Haiku 5.5",
@@ -142994,6 +145805,39 @@ export const GENERATED_PROVIDER_MODELS: {
"apiProtocol": "anthropic"
}
},
+ "beam-free": {
+ "id": "beam-free",
+ "name": "Beam Free",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 131072,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0,
+ "output": 0,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-05",
+ "family": "beam"
+ },
"longcat-2.5-preview-free": {
"id": "longcat-2.5-preview-free",
"name": "LongCat 2.5 Preview Free",
@@ -143986,6 +146830,66 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"openrouter": {
+ "reflection/beam-1.0-501b-a23b": {
+ "id": "reflection/beam-1.0-501b-a23b",
+ "name": "Beam 1.0 501B A23B",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 943718,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1,
+ "output": 3,
+ "cacheRead": 0.1,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-16",
+ "family": "beam"
+ },
+ "xingchen-agi/xing4.0-29b-a4b:free": {
+ "id": "xingchen-agi/xing4.0-29b-a4b:free",
+ "name": "Xing4.0 29B A4B (free)",
+ "contextWindow": 262144,
+ "maxInputTokens": 262144,
+ "maxTokens": 235929,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "toggle"
+ }
+ ],
+ "pricing": {
+ "input": 0,
+ "output": 0,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-16",
+ "family": "agi"
+ },
"meta/muse-spark-open": {
"id": "meta/muse-spark-open",
"name": "Muse Spark Open",
@@ -144055,9 +146959,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.15,
- "output": 0.5,
- "cacheRead": 0.02,
+ "input": 0.1,
+ "output": 0.4,
+ "cacheRead": 0.08,
"cacheWrite": 0
},
"releaseDate": "2026-10-15",
@@ -145263,9 +148167,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.0115,
- "output": 0.6,
- "cacheRead": 0.006,
+ "input": 0.032,
+ "output": 0.144,
+ "cacheRead": 0.0016,
"cacheWrite": 0
},
"releaseDate": "2026-09-14",
@@ -145296,9 +148200,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.225,
- "output": 8,
- "cacheRead": 0.23,
+ "input": 0.24948,
+ "output": 0.74844,
+ "cacheRead": 0.007938,
"cacheWrite": 0
},
"releaseDate": "2026-09-14",
@@ -145517,7 +148421,7 @@ export const GENERATED_PROVIDER_MODELS: {
"name": "DeepSeek V4.1 Flash",
"contextWindow": 1048576,
"maxInputTokens": 1048576,
- "maxTokens": 393216,
+ "maxTokens": 943718,
"capabilities": [
"images",
"tools",
@@ -145538,9 +148442,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.3,
- "output": 1.2,
- "cacheRead": 0.006,
+ "input": 0.032,
+ "output": 0.144,
+ "cacheRead": 0.0016,
"cacheWrite": 0
},
"releaseDate": "2026-09-10",
@@ -145995,9 +148899,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.01251,
- "output": 1.125,
- "cacheRead": 0.009,
+ "input": 0.04,
+ "output": 0.2,
+ "cacheRead": 0.006,
"cacheWrite": 0
},
"releaseDate": "2026-08-27",
@@ -146040,7 +148944,7 @@ export const GENERATED_PROVIDER_MODELS: {
"name": "GLM-5.3-Flash",
"contextWindow": 1048576,
"maxInputTokens": 1048576,
- "maxTokens": 943717,
+ "maxTokens": 943718,
"capabilities": [
"images",
"video",
@@ -146061,9 +148965,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.15,
- "output": 0.5,
- "cacheRead": 0.03,
+ "input": 0.04,
+ "output": 0.2,
+ "cacheRead": 0.006,
"cacheWrite": 0
},
"releaseDate": "2026-08-26",
@@ -146145,7 +149049,7 @@ export const GENERATED_PROVIDER_MODELS: {
"name": "GLM Latest",
"contextWindow": 1048576,
"maxInputTokens": 1048576,
- "maxTokens": 131072,
+ "maxTokens": 943718,
"capabilities": [
"tools",
"reasoning",
@@ -146164,9 +149068,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.0608,
- "output": 4.4,
- "cacheRead": 0.0565,
+ "input": 0.079,
+ "output": 4.8,
+ "cacheRead": 0.078,
"cacheWrite": 0
},
"releaseDate": "2026-08-19",
@@ -146365,9 +149269,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 1.32,
- "output": 3.96,
- "cacheRead": 0.044,
+ "input": 0.66,
+ "output": 1.98,
+ "cacheRead": 0.022,
"cacheWrite": 0
},
"releaseDate": "2026-08-12",
@@ -146678,9 +149582,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.00522,
- "output": 0.576,
- "cacheRead": 0.00522,
+ "input": 0.0168,
+ "output": 0.112,
+ "cacheRead": 0.001523,
"cacheWrite": 0
},
"releaseDate": "2026-08-01",
@@ -146711,9 +149615,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.0058,
- "output": 0.64,
- "cacheRead": 0.0058,
+ "input": 0.07,
+ "output": 0.14,
+ "cacheRead": 0.014,
"cacheWrite": 0
},
"releaseDate": "2026-07-31",
@@ -147073,9 +149977,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.405,
- "output": 15.45,
- "cacheRead": 0.28,
+ "input": 0.304,
+ "output": 11.936,
+ "cacheRead": 0.21,
"cacheWrite": 0
},
"releaseDate": "2026-07-16",
@@ -148550,9 +151454,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.32,
+ "input": 0.294,
"output": 24,
- "cacheRead": 0.31,
+ "cacheRead": 0.284,
"cacheWrite": 0
},
"releaseDate": "2026-04-27",
@@ -148707,9 +151611,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.95526,
- "output": 1.91052,
- "cacheRead": 0.079605,
+ "input": 0.2088,
+ "output": 0.4176,
+ "cacheRead": 0.0174,
"cacheWrite": 0
},
"releaseDate": "2026-04-24",
@@ -149227,9 +152131,9 @@ export const GENERATED_PROVIDER_MODELS: {
}
],
"pricing": {
- "input": 0.0765,
- "output": 0.255,
- "cacheRead": 0.0425,
+ "input": 0.0675,
+ "output": 0.225,
+ "cacheRead": 0.0375,
"cacheWrite": 0
},
"releaseDate": "2026-04-02",
@@ -151133,15 +154037,15 @@ export const GENERATED_PROVIDER_MODELS: {
"name": "DeepSeek Chat",
"contextWindow": 163840,
"maxInputTokens": 163840,
- "maxTokens": 16000,
+ "maxTokens": 16384,
"capabilities": [
"tools",
"structured_output",
"temperature"
],
"pricing": {
- "input": 0.2574,
- "output": 1.0287,
+ "input": 0.32,
+ "output": 0.89,
"cacheRead": 0,
"cacheWrite": 0
},
@@ -152906,7 +155810,7 @@ export const GENERATED_PROVIDER_MODELS: {
"name": "Llama 4 Scout",
"contextWindow": 1310720,
"maxInputTokens": 1310720,
- "maxTokens": 117964,
+ "maxTokens": 16384,
"capabilities": [
"images",
"tools",
@@ -152914,8 +155818,8 @@ export const GENERATED_PROVIDER_MODELS: {
"temperature"
],
"pricing": {
- "input": 0.18,
- "output": 0.59,
+ "input": 0.1,
+ "output": 0.3,
"cacheRead": 0,
"cacheWrite": 0
},
@@ -153158,17 +156062,16 @@ export const GENERATED_PROVIDER_MODELS: {
"name": "Llama-3.3-70B-Instruct",
"contextWindow": 131072,
"maxInputTokens": 131072,
- "maxTokens": 32768,
+ "maxTokens": 16384,
"capabilities": [
"tools",
"structured_output",
- "temperature",
- "prompt-cache"
+ "temperature"
],
"pricing": {
- "input": 0.59,
- "output": 0.79,
- "cacheRead": 0.295,
+ "input": 0.1,
+ "output": 0.32,
+ "cacheRead": 0,
"cacheWrite": 0
},
"releaseDate": "2024-12-06",
@@ -160203,6 +163106,40 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"pioneer": {
+ "nvidia/NVIDIA-Nemotron-3.5-Super-VL-120B-A12B-NVFP4": {
+ "id": "nvidia/NVIDIA-Nemotron-3.5-Super-VL-120B-A12B-NVFP4",
+ "name": "Nemotron 3.5 Super VL 120B A12B",
+ "contextWindow": 262144,
+ "maxInputTokens": 262144,
+ "maxTokens": 4096,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.08,
+ "output": 0.45,
+ "cacheRead": 0.04,
+ "cacheWrite": 0.08
+ },
+ "releaseDate": "2026-10-15",
+ "family": "nemotron"
+ },
"fastino/GLiNER-2.5-Decide": {
"id": "fastino/GLiNER-2.5-Decide",
"name": "GLiNER-2.5-Decide",
@@ -166264,6 +169201,51 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"prime": {
+ "meta/muse-spark-open": {
+ "id": "meta/muse-spark-open",
+ "name": "Muse Spark Open",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 943718,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1.25,
+ "output": 4.25,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-15",
+ "family": "muse",
+ "modalities": {
+ "input": [
+ "text",
+ "image",
+ "video",
+ "audio"
+ ],
+ "output": [
+ "text"
+ ]
+ }
+ },
"google/gemini-4-argon": {
"id": "google/gemini-4-argon",
"name": "Gemini 4 Argon",
@@ -168215,7 +171197,7 @@ export const GENERATED_PROVIDER_MODELS: {
"name": "Llama 3.3 70B Instruct",
"contextWindow": 131072,
"maxInputTokens": 131072,
- "maxTokens": 32768,
+ "maxTokens": 16384,
"capabilities": [
"tools",
"structured_output",
@@ -170664,6 +173646,41 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2025-08-05"
}
},
+ "reflection": {
+ "Beam-1.0-501B-A23B": {
+ "id": "Beam-1.0-501B-A23B",
+ "name": "Beam 1.0 501B A23B",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 131072,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0,
+ "output": 0,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-05",
+ "family": "beam"
+ }
+ },
"regolo-ai": {
"qwen3.8-27b": {
"id": "qwen3.8-27b",
@@ -171786,6 +174803,40 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-09-21",
"family": "grok"
},
+ "step-5-preview": {
+ "id": "step-5-preview",
+ "name": "Step 5 Preview",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 65536,
+ "capabilities": [
+ "images",
+ "video",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1,
+ "output": 2.7,
+ "cacheRead": 0.05,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-09-16"
+ },
"deepseek-v4.1-flash": {
"id": "deepseek-v4.1-flash",
"name": "DeepSeek V4.1 Flash",
@@ -179299,6 +182350,40 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"scaleway": {
+ "deepseek-v4.1-flash": {
+ "id": "deepseek-v4.1-flash",
+ "name": "DeepSeek V4.1 Flash",
+ "contextWindow": 256000,
+ "maxInputTokens": 256000,
+ "maxTokens": 32768,
+ "capabilities": [
+ "images",
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "high",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0.672,
+ "output": 2.016,
+ "cacheRead": 0.134,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-09-10",
+ "family": "deepseek-flash"
+ },
"glm-5.3": {
"id": "glm-5.3",
"name": "GLM-5.3",
@@ -192199,6 +195284,68 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"vercel-ai-gateway": {
+ "reflection/beam": {
+ "id": "reflection/beam",
+ "name": "Beam 1.0",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 131072,
+ "capabilities": [
+ "tools",
+ "reasoning"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0,
+ "output": 0,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-16",
+ "family": "beam"
+ },
+ "reflection/beam-free": {
+ "id": "reflection/beam-free",
+ "name": "Beam 1.0 (Free)",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 131072,
+ "capabilities": [
+ "tools",
+ "reasoning"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 0,
+ "output": 0,
+ "cacheRead": 0,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-16",
+ "family": "beam"
+ },
"meta/muse-spark-open": {
"id": "meta/muse-spark-open",
"name": "Muse Spark Open",
@@ -193439,7 +196586,8 @@ export const GENERATED_PROVIDER_MODELS: {
"type": "effort",
"values": [
"high",
- "xhigh"
+ "xhigh",
+ "max"
]
}
],
@@ -193470,7 +196618,8 @@ export const GENERATED_PROVIDER_MODELS: {
"type": "effort",
"values": [
"high",
- "xhigh"
+ "xhigh",
+ "max"
]
}
],
@@ -193954,16 +197103,12 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "none",
"low",
"medium",
"high",
"xhigh",
"max"
]
- },
- {
- "type": "budget_tokens"
}
],
"pricing": {
@@ -194519,12 +197664,13 @@ export const GENERATED_PROVIDER_MODELS: {
],
"reasoningOptions": [
{
- "type": "toggle"
- },
- {
- "type": "budget_tokens",
- "min": 1,
- "max": 32768
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high"
+ ]
}
],
"pricing": {
@@ -194740,9 +197886,12 @@ export const GENERATED_PROVIDER_MODELS: {
"type": "effort",
"values": [
"none",
+ "minimal",
"low",
"medium",
- "high"
+ "high",
+ "xhigh",
+ "max"
]
}
],
@@ -195075,7 +198224,6 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "none",
"low",
"high",
"max"
@@ -195648,7 +198796,8 @@ export const GENERATED_PROVIDER_MODELS: {
"type": "effort",
"values": [
"high",
- "xhigh"
+ "xhigh",
+ "max"
]
}
],
@@ -195743,7 +198892,13 @@ export const GENERATED_PROVIDER_MODELS: {
],
"reasoningOptions": [
{
- "type": "toggle"
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high"
+ ]
}
],
"pricing": {
@@ -195772,7 +198927,13 @@ export const GENERATED_PROVIDER_MODELS: {
],
"reasoningOptions": [
{
- "type": "toggle"
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high"
+ ]
}
],
"pricing": {
@@ -195801,16 +198962,12 @@ export const GENERATED_PROVIDER_MODELS: {
{
"type": "effort",
"values": [
- "none",
"low",
"medium",
"high",
"xhigh",
"max"
]
- },
- {
- "type": "budget_tokens"
}
],
"pricing": {
@@ -195839,6 +198996,7 @@ export const GENERATED_PROVIDER_MODELS: {
"type": "effort",
"values": [
"none",
+ "low",
"medium",
"high"
]
@@ -196764,32 +199922,6 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-04-16",
"family": "claude-opus"
},
- "quiverai/arrow-1.1": {
- "id": "quiverai/arrow-1.1",
- "name": "Arrow 1.1",
- "contextWindow": 131072,
- "maxInputTokens": 131072,
- "maxTokens": 131072,
- "capabilities": [
- "temperature"
- ],
- "pricing": {
- "input": 0,
- "output": 0,
- "cacheRead": 0,
- "cacheWrite": 0
- },
- "releaseDate": "2026-04-16",
- "operation": "image-generation",
- "modalities": {
- "input": [
- "text"
- ],
- "output": [
- "image"
- ]
- }
- },
"spacexai/grok-build-0.1": {
"id": "spacexai/grok-build-0.1",
"name": "Grok Build 0.1",
@@ -196875,7 +200007,13 @@ export const GENERATED_PROVIDER_MODELS: {
],
"reasoningOptions": [
{
- "type": "toggle"
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high"
+ ]
}
],
"pricing": {
@@ -197023,7 +200161,13 @@ export const GENERATED_PROVIDER_MODELS: {
],
"reasoningOptions": [
{
- "type": "toggle"
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high"
+ ]
}
],
"pricing": {
@@ -197241,7 +200385,13 @@ export const GENERATED_PROVIDER_MODELS: {
],
"reasoningOptions": [
{
- "type": "toggle"
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high"
+ ]
}
],
"pricing": {
@@ -197936,7 +201086,13 @@ export const GENERATED_PROVIDER_MODELS: {
],
"reasoningOptions": [
{
- "type": "toggle"
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high"
+ ]
}
],
"pricing": {
@@ -198148,7 +201304,13 @@ export const GENERATED_PROVIDER_MODELS: {
],
"reasoningOptions": [
{
- "type": "toggle"
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high"
+ ]
}
],
"pricing": {
@@ -198174,7 +201336,13 @@ export const GENERATED_PROVIDER_MODELS: {
],
"reasoningOptions": [
{
- "type": "toggle"
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high"
+ ]
}
],
"pricing": {
@@ -198255,7 +201423,13 @@ export const GENERATED_PROVIDER_MODELS: {
],
"reasoningOptions": [
{
- "type": "toggle"
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high"
+ ]
}
],
"pricing": {
@@ -198332,7 +201506,13 @@ export const GENERATED_PROVIDER_MODELS: {
],
"reasoningOptions": [
{
- "type": "toggle"
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high"
+ ]
}
],
"pricing": {
@@ -199029,7 +202209,13 @@ export const GENERATED_PROVIDER_MODELS: {
],
"reasoningOptions": [
{
- "type": "toggle"
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high"
+ ]
}
],
"pricing": {
@@ -199478,7 +202664,13 @@ export const GENERATED_PROVIDER_MODELS: {
],
"reasoningOptions": [
{
- "type": "toggle"
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high"
+ ]
}
],
"pricing": {
@@ -200171,12 +203363,13 @@ export const GENERATED_PROVIDER_MODELS: {
],
"reasoningOptions": [
{
- "type": "toggle"
- },
- {
- "type": "budget_tokens",
- "min": 1,
- "max": 38912
+ "type": "effort",
+ "values": [
+ "none",
+ "low",
+ "medium",
+ "high"
+ ]
}
],
"pricing": {
@@ -205515,6 +208708,41 @@ export const GENERATED_PROVIDER_MODELS: {
}
},
"wandb": {
+ "reflection/Beam-1.0-501B-A23B": {
+ "id": "reflection/Beam-1.0-501B-A23B",
+ "name": "Beam 1.0",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 1048576,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "minimal",
+ "low",
+ "medium",
+ "high",
+ "xhigh",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1,
+ "output": 3,
+ "cacheRead": 0.1,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-10-16",
+ "family": "beam"
+ },
"nvidia/NVIDIA-Nemotron-3.5-Super-VL-120B-A12B": {
"id": "nvidia/NVIDIA-Nemotron-3.5-Super-VL-120B-A12B",
"name": "Nemotron 3.5 Super VL",
@@ -205536,7 +208764,7 @@ export const GENERATED_PROVIDER_MODELS: {
],
"pricing": {
"input": 0.15,
- "output": 0.75,
+ "output": 0.5,
"cacheRead": 0.02,
"cacheWrite": 0
},
@@ -205650,6 +208878,38 @@ export const GENERATED_PROVIDER_MODELS: {
"releaseDate": "2026-08-14",
"family": "qwen"
},
+ "zai-org/GLM-5.3": {
+ "id": "zai-org/GLM-5.3",
+ "name": "GLM 5.3",
+ "contextWindow": 1048576,
+ "maxInputTokens": 1048576,
+ "maxTokens": 1048576,
+ "capabilities": [
+ "tools",
+ "reasoning",
+ "structured_output",
+ "temperature",
+ "prompt-cache"
+ ],
+ "reasoningOptions": [
+ {
+ "type": "effort",
+ "values": [
+ "low",
+ "high",
+ "max"
+ ]
+ }
+ ],
+ "pricing": {
+ "input": 1.2,
+ "output": 4,
+ "cacheRead": 0.19,
+ "cacheWrite": 0
+ },
+ "releaseDate": "2026-08-14",
+ "family": "glm"
+ },
"deepseek-ai/DeepSeek-V4-Pro-0813": {
"id": "deepseek-ai/DeepSeek-V4-Pro-0813",
"name": "DeepSeek V4 Pro 0813",
diff --git a/sdk/packages/llms/src/catalog/cline-recommended.generated.ts b/sdk/packages/llms/src/catalog/cline-recommended.generated.ts
index 046c797b9a..24e44a9c47 100644
--- a/sdk/packages/llms/src/catalog/cline-recommended.generated.ts
+++ b/sdk/packages/llms/src/catalog/cline-recommended.generated.ts
@@ -4,6 +4,12 @@ import type { ClineRecommendedModelsPayload } from "./catalog-cline-recommended"
export const GENERATED_CLINE_RECOMMENDED_MODELS: ClineRecommendedModelsPayload =
{
recommended: [
+ {
+ id: "anthropic/claude-sonnet-5.5",
+ name: "claude-sonnet-5.5",
+ description: "",
+ tags: ["NEW"],
+ },
{
id: "google/gemini-4-argon",
name: "Gemini 4 Argon",
@@ -11,12 +17,6 @@ export const GENERATED_CLINE_RECOMMENDED_MODELS: ClineRecommendedModelsPayload =
"Frontier model for real-world coding, enterprise knowledge work, and cyber defense",
tags: ["NEW"],
},
- {
- id: "anthropic/claude-sonnet-5.5",
- name: "claude-sonnet-5.5",
- description: "",
- tags: ["NEW"],
- },
{
id: "anthropic/claude-opus-5.5",
name: "claude-opus-5.5",
@@ -127,18 +127,18 @@ export const GENERATED_CLINE_RECOMMENDED_MODELS: ClineRecommendedModelsPayload =
description: "Latest natively multimodal model in the GLM-5 series",
tags: [],
},
- {
- id: "cline-pass/qwen3.7-plus",
- name: "cline-pass/qwen3.7-plus",
- description: "Fast multimodal agent model with vision and video input",
- tags: [],
- },
{
id: "cline-pass/minimax-m3",
name: "cline-pass/minimax-m3",
description: "Frontier coding and agent model with 1M context window",
tags: [],
},
+ {
+ id: "cline-pass/qwen3.7-plus",
+ name: "cline-pass/qwen3.7-plus",
+ description: "Fast multimodal agent model with vision and video input",
+ tags: [],
+ },
{
id: "cline-pass/qwen3.7-max",
name: "cline-pass/qwen3.7-max",
diff --git a/sdk/packages/llms/src/providers/provider-ids.generated.ts b/sdk/packages/llms/src/providers/provider-ids.generated.ts
index 132089012d..eb309b03d1 100644
--- a/sdk/packages/llms/src/providers/provider-ids.generated.ts
+++ b/sdk/packages/llms/src/providers/provider-ids.generated.ts
@@ -52,6 +52,7 @@ export const GENERATED_PROVIDER_IDS = [
"cline-pass",
"cloudferro-sherlock",
"cloudflare-workers-ai",
+ "commandcode",
"coralbricks",
"cortecs",
"crof",
@@ -163,6 +164,7 @@ export const GENERATED_PROVIDER_IDS = [
"privatemode-ai",
"qihang-ai",
"qiniu-ai",
+ "reflection",
"regolo-ai",
"requesty",
"routing-run",
diff --git a/sdk/packages/llms/src/providers/providers.generated.ts b/sdk/packages/llms/src/providers/providers.generated.ts
index 7da04b9841..d7cfc80eb0 100644
--- a/sdk/packages/llms/src/providers/providers.generated.ts
+++ b/sdk/packages/llms/src/providers/providers.generated.ts
@@ -24,7 +24,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "302ai",
- defaultModelId: "claude-haiku-5-5",
+ defaultModelId: "gemini-4-argon",
apiKeyEnv: ["302AI_API_KEY"],
docsUrl: "https://doc.302.ai",
defaults: {
@@ -604,6 +604,20 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
"https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/ai/v1",
},
},
+ {
+ id: "commandcode",
+ name: "CommandCode",
+ description: "CommandCode model provider from models.dev",
+ family: "openai-compatible",
+ capabilities: ["tools", "reasoning", "prompt-cache"],
+ modelsProviderId: "commandcode",
+ defaultModelId: "google/gemini-4-argon",
+ apiKeyEnv: ["CMD_API_KEY"],
+ docsUrl: "https://commandcode.ai/docs/provider",
+ defaults: {
+ baseUrl: "https://api.commandcode.ai/provider/v1",
+ },
+ },
{
id: "coralbricks",
name: "CoralBricks",
@@ -795,7 +809,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "edenai",
- defaultModelId: "google/gemini-4-argon",
+ defaultModelId: "fireworks_ai/accounts/fireworks/models/muse-spark-open",
apiKeyEnv: ["EDENAI_API_KEY"],
docsUrl: "https://docs.edenai.co",
defaults: {
@@ -1260,7 +1274,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "kilo",
- defaultModelId: "meta/muse-spark-open",
+ defaultModelId: "reflection/beam-1.0-501b-a23b",
apiKeyEnv: ["KILO_API_KEY"],
docsUrl: "https://kilo.ai",
defaults: {
@@ -1749,7 +1763,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "nano-gpt",
- defaultModelId: "nvidia/nemotron-3.5-super-vl",
+ defaultModelId: "heabsy/qwen3.8-27b-uncensored-fast",
apiKeyEnv: ["NANO_GPT_API_KEY"],
docsUrl: "https://docs.nano-gpt.com",
defaults: {
@@ -1934,7 +1948,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
apiKeyEnv: ["OPENCODE_API_KEY"],
docsUrl: "https://opencode.ai/v2/docs/console/models/",
defaults: {
- baseUrl: "https://opencode.ai/inference/v1",
+ baseUrl: "https://opencode.ai/inference/openai/v1",
},
},
{
@@ -1948,7 +1962,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
apiKeyEnv: ["OPENCODE_API_KEY"],
docsUrl: "https://opencode.ai/v2/docs/console/go/",
defaults: {
- baseUrl: "https://opencode.ai/inference/go/v1",
+ baseUrl: "https://opencode.ai/inference/go/openai/v1",
},
},
{
@@ -1972,7 +1986,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "openrouter",
- defaultModelId: "meta/muse-spark-open",
+ defaultModelId: "reflection/beam-1.0-501b-a23b",
apiKeyEnv: ["OPENROUTER_API_KEY"],
docsUrl: "https://openrouter.ai/models",
defaults: {
@@ -2070,7 +2084,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "pioneer",
- defaultModelId: "fastino/GLiNER-2.5-Decide",
+ defaultModelId: "nvidia/NVIDIA-Nemotron-3.5-Super-VL-120B-A12B-NVFP4",
apiKeyEnv: ["PIONEER_API_KEY"],
docsUrl: "https://agent.pioneer.ai/llms.txt",
defaults: {
@@ -2113,7 +2127,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "prime",
- defaultModelId: "google/gemini-4-argon",
+ defaultModelId: "meta/muse-spark-open",
apiKeyEnv: ["PRIME_API_KEY"],
docsUrl: "https://docs.primeintellect.ai/inference/overview",
defaults: {
@@ -2162,6 +2176,20 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
baseUrl: "https://api.qnaigc.com/v1",
},
},
+ {
+ id: "reflection",
+ name: "Reflection",
+ description: "Reflection model provider from models.dev",
+ family: "openai-compatible",
+ capabilities: ["tools", "reasoning"],
+ modelsProviderId: "reflection",
+ defaultModelId: "Beam-1.0-501B-A23B",
+ apiKeyEnv: ["REFLECTION_API_KEY"],
+ docsUrl: "https://developers.reflection.ai/models",
+ defaults: {
+ baseUrl: "https://api.reflection.ai/openai/v1",
+ },
+ },
{
id: "regolo-ai",
name: "Regolo AI",
@@ -2279,7 +2307,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "scaleway",
- defaultModelId: "glm-5.3",
+ defaultModelId: "deepseek-v4.1-flash",
apiKeyEnv: ["SCALEWAY_API_KEY"],
docsUrl: "https://www.scaleway.com/en/docs/generative-apis/",
defaults: {
@@ -2747,7 +2775,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "vercel-ai-gateway",
- defaultModelId: "meta/muse-spark-open",
+ defaultModelId: "reflection/beam",
apiKeyEnv: ["AI_GATEWAY_API_KEY"],
docsUrl:
"https://github.com/vercel/ai/tree/5eb85cc45a259553501f535b8ac79a77d0e79223/packages/gateway",
@@ -2872,7 +2900,7 @@ export const GENERATED_PROVIDER_SPECS: readonly BuiltinSpec[] = [
family: "openai-compatible",
capabilities: ["tools", "reasoning", "prompt-cache"],
modelsProviderId: "wandb",
- defaultModelId: "nvidia/NVIDIA-Nemotron-3.5-Super-VL-120B-A12B",
+ defaultModelId: "reflection/Beam-1.0-501B-A23B",
apiKeyEnv: ["WANDB_API_KEY"],
docsUrl: "https://docs.wandb.ai/inference",
defaults: {
diff --git a/sdk/packages/sdk/package.json b/sdk/packages/sdk/package.json
index ff853c6dbc..41c3c2b4ce 100644
--- a/sdk/packages/sdk/package.json
+++ b/sdk/packages/sdk/package.json
@@ -1,7 +1,7 @@
{
"name": "@cline/sdk",
"description": "Cline SDK - user-facing alias for @cline/core",
- "version": "0.0.94",
+ "version": "0.0.95",
"repository": {
"type": "git",
"url": "https://github.com/cline/cline",
diff --git a/sdk/packages/shared/package.json b/sdk/packages/shared/package.json
index 053d9b3803..9ec37ff789 100644
--- a/sdk/packages/shared/package.json
+++ b/sdk/packages/shared/package.json
@@ -1,6 +1,6 @@
{
"name": "@cline/shared",
- "version": "0.0.94",
+ "version": "0.0.95",
"description": "Shared utilities, types, and schemas for Cline packages",
"repository": {
"type": "git",
From c718573538d76310f464541617ab665108a6c999 Mon Sep 17 00:00:00 2001
From: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
Date: Fri, 16 Oct 2026 19:37:19 -0700
Subject: [PATCH 22/29] chore(cli): release v3.0.73
---
apps/cli/CHANGELOG.md | 6 ++++++
apps/cli/package.json | 2 +-
bun.lock | 2 +-
3 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/apps/cli/CHANGELOG.md b/apps/cli/CHANGELOG.md
index 34dc05ac1d..982732b1a5 100644
--- a/apps/cli/CHANGELOG.md
+++ b/apps/cli/CHANGELOG.md
@@ -1,5 +1,11 @@
# Cline CLI Changelog
+## 3.0.73
+
+- GPT-6 models (such as `gpt-6-sol` and `gpt-6.1-sol`) work on OpenAI and Azure OpenAI-compatible endpoints. Before, every request was rejected because Cline sent `max_tokens` instead of `max_completion_tokens`
+- With no model chosen, the Cline provider uses Claude Sonnet 5.5 again, which is back at the top of Cline's recommended list
+- Refreshed the model catalog. Adds the CommandCode and Reflection providers. Default models change for 302.AI (Gemini 4 Argon), Eden AI and Prime Inference (Muse Spark Open), CoreWeave (Reflection Beam 1.0), NanoGPT, Pioneer (Nemotron 3.5 Super VL), and Scaleway (DeepSeek V4.1 Flash)
+
## 3.0.72
- Plugins now run in a worker instead of directly inside the hub. If this build can't run plugins, Cline says so in `cline config tools`, `cline hub plugins`, and the session-start warnings instead of quietly running them inside the hub. `CLINE_PLUGIN_MODE=in_process` is no longer supported; use `worker` (the default) or `sandbox`
diff --git a/apps/cli/package.json b/apps/cli/package.json
index 490c623c4f..8944d30ba4 100644
--- a/apps/cli/package.json
+++ b/apps/cli/package.json
@@ -1,7 +1,7 @@
{
"name": "@cline/cli",
"displayName": "cline",
- "version": "3.0.72",
+ "version": "3.0.73",
"description": "Autonomous coding agent CLI - capable of creating/editing files, running commands, using the browser, and more",
"type": "module",
"publishConfig": {
diff --git a/bun.lock b/bun.lock
index 5d267d7c87..c58294815c 100644
--- a/bun.lock
+++ b/bun.lock
@@ -19,7 +19,7 @@
},
"apps/cli": {
"name": "@cline/cli",
- "version": "3.0.72",
+ "version": "3.0.73",
"bin": {
"cline": "src/index.ts",
},
From a42df8c8d5fd9d9f9a9073589baffe32ea9bb2f0 Mon Sep 17 00:00:00 2001
From: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
Date: Fri, 16 Oct 2026 20:08:38 -0700
Subject: [PATCH 23/29] chore(desktop): release v0.0.48
---
apps/examples/desktop-app/CHANGELOG.md | 6 ++++++
apps/examples/desktop-app/package.json | 2 +-
apps/examples/desktop-app/src-tauri/tauri.conf.json | 2 +-
bun.lock | 2 +-
4 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/apps/examples/desktop-app/CHANGELOG.md b/apps/examples/desktop-app/CHANGELOG.md
index 2cf8b83051..11e8a49536 100644
--- a/apps/examples/desktop-app/CHANGELOG.md
+++ b/apps/examples/desktop-app/CHANGELOG.md
@@ -1,5 +1,11 @@
# Cline Desktop Changelog
+## 0.0.48
+
+- GPT-6 models (such as `gpt-6-sol` and `gpt-6.1-sol`) work on OpenAI and Azure OpenAI-compatible endpoints. Before, every request was rejected because Cline sent `max_tokens` instead of `max_completion_tokens`
+- The Cline provider's default model is Claude Sonnet 5.5 again, which is back at the top of Cline's recommended list
+- Refreshed the model catalog. Adds the CommandCode and Reflection providers. Default models change for 302.AI (Gemini 4 Argon), Eden AI and Prime Inference (Muse Spark Open), CoreWeave (Reflection Beam 1.0), NanoGPT, Pioneer (Nemotron 3.5 Super VL), and Scaleway (DeepSeek V4.1 Flash)
+
## 0.0.47
- Marketplace plugins such as goal load again. In 0.0.46 they failed with `Cannot find module '@cline/sdk'` because the packaged app didn't include the SDK packages plugins import
diff --git a/apps/examples/desktop-app/package.json b/apps/examples/desktop-app/package.json
index 6e19a09e38..3451e998ea 100644
--- a/apps/examples/desktop-app/package.json
+++ b/apps/examples/desktop-app/package.json
@@ -1,6 +1,6 @@
{
"name": "@cline/code",
- "version": "0.0.47",
+ "version": "0.0.48",
"private": true,
"scripts": {
"build:ui": "bun -F @cline/ui build",
diff --git a/apps/examples/desktop-app/src-tauri/tauri.conf.json b/apps/examples/desktop-app/src-tauri/tauri.conf.json
index c6bda06075..05c3f9e9ee 100644
--- a/apps/examples/desktop-app/src-tauri/tauri.conf.json
+++ b/apps/examples/desktop-app/src-tauri/tauri.conf.json
@@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "Cline",
- "version": "0.0.47",
+ "version": "0.0.48",
"identifier": "bot.cline.app",
"build": {
"beforeDevCommand": "bun run build:runtime && bun run dev:web",
diff --git a/bun.lock b/bun.lock
index c58294815c..7e9e0c6047 100644
--- a/bun.lock
+++ b/bun.lock
@@ -165,7 +165,7 @@
},
"apps/examples/desktop-app": {
"name": "@cline/code",
- "version": "0.0.47",
+ "version": "0.0.48",
"dependencies": {
"@ai-sdk/gateway": "^4.0.98",
"@ai-sdk/openai": "^4.0.79",
From 731f48462b00d4c23f7e900c7102dd79b16b5e4d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1s=20Barreiro?=
<52393857+BarreiroT@users.noreply.github.com>
Date: Sun, 18 Oct 2026 19:10:19 -0300
Subject: [PATCH 24/29] Support MCP Resources [NO-OP] (#15165)
* Support MCP Resources
* Small fixes
* Address PR comments
* remove CreateMcpToolsOptions mcpApps option
---
.../src/sdk/vscode-runtime-builder.test.ts | 41 +++++
apps/vscode/src/sdk/vscode-runtime-builder.ts | 8 +-
apps/vscode/src/services/mcp/McpHub.ts | 25 +++
.../mcp/__tests__/McpHub.readResource.test.ts | 57 ++++++
apps/vscode/src/shared/mcp.ts | 1 +
sdk/DOC.md | 27 +++
.../core/src/extensions/mcp/apps.test.ts | 82 +++++++++
sdk/packages/core/src/extensions/mcp/apps.ts | 68 +++++++
.../src/extensions/mcp/client-apps.test.ts | 170 ++++++++++++++++++
.../src/extensions/mcp/client-url.test.ts | 90 +++++++++-
.../core/src/extensions/mcp/client.ts | 71 +++++++-
sdk/packages/core/src/extensions/mcp/index.ts | 13 ++
.../core/src/extensions/mcp/manager.test.ts | 91 ++++++++++
.../core/src/extensions/mcp/manager.ts | 27 +++
.../core/src/extensions/mcp/tools.test.ts | 26 +++
sdk/packages/core/src/extensions/mcp/tools.ts | 3 +-
sdk/packages/core/src/extensions/mcp/types.ts | 27 +++
sdk/packages/core/src/index.ts | 12 ++
18 files changed, 829 insertions(+), 10 deletions(-)
create mode 100644 apps/vscode/src/services/mcp/__tests__/McpHub.readResource.test.ts
create mode 100644 sdk/packages/core/src/extensions/mcp/apps.test.ts
create mode 100644 sdk/packages/core/src/extensions/mcp/apps.ts
create mode 100644 sdk/packages/core/src/extensions/mcp/client-apps.test.ts
diff --git a/apps/vscode/src/sdk/vscode-runtime-builder.test.ts b/apps/vscode/src/sdk/vscode-runtime-builder.test.ts
index 1b29c21063..be4edc99fd 100644
--- a/apps/vscode/src/sdk/vscode-runtime-builder.test.ts
+++ b/apps/vscode/src/sdk/vscode-runtime-builder.test.ts
@@ -21,4 +21,45 @@ describe("McpHubToolProvider", () => {
expect(callTool.calledOnce).toBe(true)
expect(callTool.firstCall.args[4]).toBe(controller.signal)
})
+
+ it("keeps MCP Apps tool metadata", async () => {
+ const getServers = sinon.stub().returns([
+ {
+ name: "weather",
+ tools: [
+ {
+ name: "show_weather",
+ inputSchema: { type: "object" },
+ _meta: { ui: { resourceUri: "ui://weather/view.html" } },
+ },
+ { name: "plain", inputSchema: { type: "object" } },
+ ],
+ },
+ ])
+ const provider = new McpHubToolProvider({ getServers } as never)
+
+ expect(await provider.listTools("weather")).toEqual([
+ {
+ name: "show_weather",
+ description: undefined,
+ inputSchema: { type: "object" },
+ _meta: { ui: { resourceUri: "ui://weather/view.html" } },
+ },
+ { name: "plain", description: undefined, inputSchema: { type: "object" } },
+ ])
+ })
+
+ it("forwards resource reads with the agent abort signal", async () => {
+ const readResource = sinon.stub().resolves({ contents: [] })
+ const provider = new McpHubToolProvider({ readResource } as never)
+ const controller = new AbortController()
+
+ await provider.readResource({
+ serverName: "weather",
+ uri: "ui://weather/view.html",
+ context: { agentId: "agent", iteration: 1, signal: controller.signal },
+ })
+
+ expect(readResource.firstCall.args).toEqual(["weather", "ui://weather/view.html", controller.signal])
+ })
})
diff --git a/apps/vscode/src/sdk/vscode-runtime-builder.ts b/apps/vscode/src/sdk/vscode-runtime-builder.ts
index 80afb09c98..52eccaaf86 100644
--- a/apps/vscode/src/sdk/vscode-runtime-builder.ts
+++ b/apps/vscode/src/sdk/vscode-runtime-builder.ts
@@ -1,4 +1,4 @@
-import { createMcpTools } from "@cline/core"
+import { createMcpTools, type McpResourceReadResult } from "@cline/core"
import type { AgentTool, AgentToolContext } from "@cline/shared"
import type { VscodeTerminalManager } from "@/hosts/vscode/terminal/VscodeTerminalManager"
import type { McpHub } from "@/services/mcp/McpHub"
@@ -11,6 +11,7 @@ interface McpToolDescriptor {
name: string
description?: string
inputSchema: Record
+ _meta?: Record
}
export class McpHubToolProvider {
@@ -31,6 +32,7 @@ export class McpHubToolProvider {
type: "object",
properties: {},
},
+ ...(tool._meta ? { _meta: tool._meta } : {}),
}))
}
@@ -43,6 +45,10 @@ export class McpHubToolProvider {
const ulid = `sdk-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`
return this.mcpHub.callTool(request.serverName, request.toolName, request.arguments ?? {}, ulid, request.context?.signal)
}
+
+ async readResource(request: { serverName: string; uri: string; context?: AgentToolContext }): Promise {
+ return this.mcpHub.readResource(request.serverName, request.uri, request.context?.signal)
+ }
}
export interface VscodeExtraToolsOptions {
diff --git a/apps/vscode/src/services/mcp/McpHub.ts b/apps/vscode/src/services/mcp/McpHub.ts
index 4d90235052..22ae2b3178 100644
--- a/apps/vscode/src/services/mcp/McpHub.ts
+++ b/apps/vscode/src/services/mcp/McpHub.ts
@@ -16,6 +16,8 @@ import {
ListToolsResultSchema,
McpError,
PromptListChangedNotificationSchema,
+ type ReadResourceResult,
+ ReadResourceResultSchema,
ResourceListChangedNotificationSchema,
ToolListChangedNotificationSchema,
} from "@modelcontextprotocol/sdk/types.js"
@@ -1751,6 +1753,29 @@ export class McpHub {
}
}
+ async readResource(serverName: string, uri: string, signal?: AbortSignal): Promise {
+ const connection = this.connections.find((conn) => conn.server.name === serverName)
+ if (!connection) {
+ throw new Error(`No connection found for server: ${serverName}`)
+ }
+ if (connection.server.disabled) {
+ throw new Error(`Server "${serverName}" is disabled and cannot be used`)
+ }
+ if (!connection.client) {
+ throw new Error(`Server "${serverName}" is not connected and cannot be used.`)
+ }
+
+ const timeout = resolveMcpServerTimeoutMs(connection.server.config)
+ try {
+ return await connection.client.request({ method: "resources/read", params: { uri } }, ReadResourceResultSchema, {
+ timeout,
+ signal,
+ })
+ } catch (error) {
+ throw augmentMcpTimeoutError(error, serverName, timeout)
+ }
+ }
+
/**
* RPC variant of toggleToolAutoApprove that returns the updated servers instead of notifying the webview
* @param serverName The name of the MCP server
diff --git a/apps/vscode/src/services/mcp/__tests__/McpHub.readResource.test.ts b/apps/vscode/src/services/mcp/__tests__/McpHub.readResource.test.ts
new file mode 100644
index 0000000000..338835d081
--- /dev/null
+++ b/apps/vscode/src/services/mcp/__tests__/McpHub.readResource.test.ts
@@ -0,0 +1,57 @@
+import { describe, it } from "bun:test"
+import "should"
+import sinon from "sinon"
+import { McpHub } from "../McpHub"
+
+function createMcpHub(options: { disabled?: boolean; client?: { request: sinon.SinonStub } | null } = {}) {
+ const client =
+ options.client === null
+ ? undefined
+ : (options.client ?? {
+ request: sinon.stub().resolves({
+ contents: [
+ { uri: "ui://weather/view.html", mimeType: "text/html;profile=mcp-app", text: "" },
+ ],
+ }),
+ })
+ const hub = Object.create(McpHub.prototype) as McpHub
+ ;(hub as any).connections = [
+ {
+ server: {
+ name: "weather",
+ config: JSON.stringify({ type: "stdio", command: "test", timeout: 60 }),
+ status: "connected",
+ disabled: options.disabled ?? false,
+ },
+ client,
+ transport: {},
+ },
+ ]
+ return { hub, client }
+}
+
+describe("McpHub.readResource", () => {
+ it("sends resources/read with the server timeout and abort signal", async () => {
+ const { hub, client } = createMcpHub()
+ const controller = new AbortController()
+
+ const result = await hub.readResource("weather", "ui://weather/view.html", controller.signal)
+
+ result.contents[0].uri.should.equal("ui://weather/view.html")
+ const [request, , options] = client!.request.firstCall.args
+ request.should.deepEqual({ method: "resources/read", params: { uri: "ui://weather/view.html" } })
+ options.should.deepEqual({ timeout: 60_000, signal: controller.signal })
+ })
+
+ it("rejects unknown, disabled, and disconnected servers", async () => {
+ await createMcpHub()
+ .hub.readResource("missing", "ui://x")
+ .should.be.rejectedWith(/No connection found/)
+ await createMcpHub({ disabled: true })
+ .hub.readResource("weather", "ui://x")
+ .should.be.rejectedWith(/disabled/)
+ await createMcpHub({ client: null })
+ .hub.readResource("weather", "ui://x")
+ .should.be.rejectedWith(/not connected/)
+ })
+})
diff --git a/apps/vscode/src/shared/mcp.ts b/apps/vscode/src/shared/mcp.ts
index 4b1f0e66d1..e6dd0cbdfe 100644
--- a/apps/vscode/src/shared/mcp.ts
+++ b/apps/vscode/src/shared/mcp.ts
@@ -35,6 +35,7 @@ export type McpTool = {
description?: string
inputSchema?: object
autoApprove?: boolean
+ _meta?: Record
}
export type McpResource = {
diff --git a/sdk/DOC.md b/sdk/DOC.md
index 36c79fb253..da9c40d6d5 100644
--- a/sdk/DOC.md
+++ b/sdk/DOC.md
@@ -378,3 +378,30 @@ Pass `connectorsRequest: (path, init) => Promise` to `LocalRuntimeHost
and `createLocalHubScheduleRuntimeHandlers` to supply connector authentication.
Paths start with `/api/v1/connectors`; the host supplies the API origin and
authentication. Omit it to retain local account authentication and rollout checks.
+
+## MCP Apps (experimental)
+
+MCP Apps support is off by default.
+`createDefaultMcpServerClientFactory({ mcpApps: true })` turns it on by
+advertising the `io.modelcontextprotocol/ui` extension (`MCP_APPS_EXTENSION_ID`)
+with the `text/html;profile=mcp-app` MIME type during `initialize`, for stdio
+and URL servers alike.
+
+`createMcpTools` always leaves out tools whose `_meta.ui.visibility` does not
+include `"model"`, whether or not the client advertised the extension.
+
+Tool descriptors keep the server's `_meta`. `getMcpAppToolMeta` reads
+`_meta.ui`: `resourceUri` is kept only for `ui://` URIs, and `visibility`
+defaults to `["model", "app"]` when it is not an array. An explicit array is
+used as given after dropping unknown entries, so `[]` makes the tool visible to
+neither. `isMcpToolVisibleToModel` and `isMcpToolVisibleToApp` check those
+lists; a host must reject app-initiated tool calls when
+`isMcpToolVisibleToApp` is false.
+
+`McpManager.readResource({ serverName, uri, context })` sends `resources/read`
+and returns `{ contents, _meta? }`, validated against the MCP SDK schema;
+malformed replies throw. It is optional on `McpManager` and
+`McpServerClient`. `InMemoryMcpManager` reads without waiting for in-flight
+tool calls on an already connected server. A read that starts while the server
+is being disconnected or re-registered can fail with a disconnect error; retry
+it.
diff --git a/sdk/packages/core/src/extensions/mcp/apps.test.ts b/sdk/packages/core/src/extensions/mcp/apps.test.ts
new file mode 100644
index 0000000000..e9a75a9c1b
--- /dev/null
+++ b/sdk/packages/core/src/extensions/mcp/apps.test.ts
@@ -0,0 +1,82 @@
+import { describe, expect, it } from "vitest";
+import {
+ createMcpAppsClientCapabilities,
+ getMcpAppToolMeta,
+ isMcpAppResourceUri,
+ isMcpToolVisibleToApp,
+ isMcpToolVisibleToModel,
+} from "./apps";
+
+describe("MCP Apps tool metadata", () => {
+ it("advertises the HTML app profile under the UI extension", () => {
+ expect(createMcpAppsClientCapabilities()).toEqual({
+ extensions: {
+ "io.modelcontextprotocol/ui": {
+ mimeTypes: ["text/html;profile=mcp-app"],
+ },
+ },
+ });
+ });
+
+ it("accepts only ui:// resource URIs", () => {
+ expect(isMcpAppResourceUri("ui://weather/view.html")).toBe(true);
+ expect(isMcpAppResourceUri("https://example.test/view.html")).toBe(false);
+ expect(isMcpAppResourceUri("not a uri")).toBe(false);
+ });
+
+ it("treats tools without UI metadata as plain model tools", () => {
+ expect(getMcpAppToolMeta({})).toBeUndefined();
+ expect(isMcpToolVisibleToModel({})).toBe(true);
+ expect(isMcpToolVisibleToApp({})).toBe(true);
+ });
+
+ it("defaults visibility to model and app when only a resource is declared", () => {
+ const tool = { _meta: { ui: { resourceUri: "ui://weather/view.html" } } };
+ expect(getMcpAppToolMeta(tool)).toEqual({
+ resourceUri: "ui://weather/view.html",
+ visibility: ["model", "app"],
+ });
+ expect(isMcpToolVisibleToModel(tool)).toBe(true);
+ expect(isMcpToolVisibleToApp(tool)).toBe(true);
+ });
+
+ it("hides app-only tools from the model", () => {
+ const tool = { _meta: { ui: { visibility: ["app"] } } };
+ expect(isMcpToolVisibleToModel(tool)).toBe(false);
+ expect(isMcpToolVisibleToApp(tool)).toBe(true);
+ });
+
+ it("keeps model-only tools away from apps", () => {
+ const tool = { _meta: { ui: { visibility: ["model"] } } };
+ expect(isMcpToolVisibleToModel(tool)).toBe(true);
+ expect(isMcpToolVisibleToApp(tool)).toBe(false);
+ });
+
+ it("drops unknown visibility entries and non-ui resource URIs", () => {
+ expect(
+ getMcpAppToolMeta({
+ _meta: {
+ ui: {
+ resourceUri: "https://example.test/view.html",
+ visibility: ["app", "everyone"],
+ },
+ },
+ }),
+ ).toEqual({ resourceUri: undefined, visibility: ["app"] });
+ });
+
+ it("falls back to the default visibility when visibility is not an array", () => {
+ const tool = { _meta: { ui: { visibility: "app" } } };
+ expect(getMcpAppToolMeta(tool)?.visibility).toEqual(["model", "app"]);
+ expect(isMcpToolVisibleToModel(tool)).toBe(true);
+ });
+
+ it("treats an explicit visibility array as authoritative even when empty", () => {
+ for (const visibility of [[], ["everyone"]]) {
+ const tool = { _meta: { ui: { visibility } } };
+ expect(getMcpAppToolMeta(tool)?.visibility).toEqual([]);
+ expect(isMcpToolVisibleToModel(tool)).toBe(false);
+ expect(isMcpToolVisibleToApp(tool)).toBe(false);
+ }
+ });
+});
diff --git a/sdk/packages/core/src/extensions/mcp/apps.ts b/sdk/packages/core/src/extensions/mcp/apps.ts
new file mode 100644
index 0000000000..72935387d2
--- /dev/null
+++ b/sdk/packages/core/src/extensions/mcp/apps.ts
@@ -0,0 +1,68 @@
+import type { McpToolDescriptor } from "./types";
+
+export const MCP_APPS_EXTENSION_ID = "io.modelcontextprotocol/ui";
+export const MCP_APP_MIME_TYPE = "text/html;profile=mcp-app";
+export const MCP_APP_RESOURCE_URI_SCHEME = "ui:";
+
+export type McpAppToolVisibility = "model" | "app";
+
+export interface McpAppToolMeta {
+ resourceUri?: string;
+ visibility: readonly McpAppToolVisibility[];
+}
+
+const DEFAULT_VISIBILITY: readonly McpAppToolVisibility[] = ["model", "app"];
+
+export function createMcpAppsClientCapabilities(): {
+ extensions: Record>;
+} {
+ return {
+ extensions: {
+ [MCP_APPS_EXTENSION_ID]: { mimeTypes: [MCP_APP_MIME_TYPE] },
+ },
+ };
+}
+
+export function isMcpAppResourceUri(uri: string): boolean {
+ try {
+ return new URL(uri).protocol === MCP_APP_RESOURCE_URI_SCHEME;
+ } catch {
+ return false;
+ }
+}
+
+function isRecord(value: unknown): value is Record {
+ return typeof value === "object" && value !== null && !Array.isArray(value);
+}
+
+export function getMcpAppToolMeta(
+ tool: Pick,
+): McpAppToolMeta | undefined {
+ const ui = tool._meta?.ui;
+ if (!isRecord(ui)) {
+ return undefined;
+ }
+ const resourceUri =
+ typeof ui.resourceUri === "string" && isMcpAppResourceUri(ui.resourceUri)
+ ? ui.resourceUri
+ : undefined;
+ const visibility = Array.isArray(ui.visibility)
+ ? ui.visibility.filter(
+ (entry): entry is McpAppToolVisibility =>
+ entry === "model" || entry === "app",
+ )
+ : DEFAULT_VISIBILITY;
+ return { resourceUri, visibility };
+}
+
+export function isMcpToolVisibleToModel(
+ tool: Pick,
+): boolean {
+ return getMcpAppToolMeta(tool)?.visibility.includes("model") ?? true;
+}
+
+export function isMcpToolVisibleToApp(
+ tool: Pick,
+): boolean {
+ return getMcpAppToolMeta(tool)?.visibility.includes("app") ?? true;
+}
diff --git a/sdk/packages/core/src/extensions/mcp/client-apps.test.ts b/sdk/packages/core/src/extensions/mcp/client-apps.test.ts
new file mode 100644
index 0000000000..641e8d02d9
--- /dev/null
+++ b/sdk/packages/core/src/extensions/mcp/client-apps.test.ts
@@ -0,0 +1,170 @@
+import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
+import { tmpdir } from "node:os";
+import { join } from "node:path";
+import { afterAll, beforeAll, describe, expect, it } from "vitest";
+import { createDefaultMcpServerClientFactory } from "./client";
+import type { McpServerRegistration } from "./types";
+
+const APPS_SERVER_SCRIPT = `
+let buffer = "";
+let initializeCapabilities;
+process.stdin.on("data", (chunk) => {
+ buffer += chunk.toString("utf8");
+ let idx;
+ while ((idx = buffer.indexOf("\\n")) >= 0) {
+ const line = buffer.slice(0, idx).trim();
+ buffer = buffer.slice(idx + 1);
+ if (!line) continue;
+ const msg = JSON.parse(line);
+ if (msg.id === undefined) continue;
+ let result;
+ if (msg.method === "initialize") {
+ initializeCapabilities = msg.params.capabilities;
+ result = {
+ protocolVersion: "2024-11-05",
+ capabilities: { tools: {}, resources: {} },
+ serverInfo: { name: "apps", version: "0.0.0" },
+ };
+ } else if (msg.method === "tools/list") {
+ result = {
+ tools: [
+ {
+ name: "show_weather",
+ inputSchema: { type: "object" },
+ _meta: { ui: { resourceUri: "ui://weather/view.html" } },
+ },
+ { name: "plain", inputSchema: { type: "object" } },
+ ],
+ };
+ } else if (msg.method === "tools/call") {
+ result = {
+ content: [{ type: "text", text: JSON.stringify(initializeCapabilities) }],
+ };
+ } else if (msg.params?.uri === "ui://broken/missing-contents") {
+ result = {};
+ } else if (msg.params?.uri === "ui://broken/object-contents") {
+ result = { contents: {} };
+ } else if (msg.method === "resources/read") {
+ result = {
+ contents: [
+ {
+ uri: msg.params.uri,
+ mimeType: "text/html;profile=mcp-app",
+ text: "",
+ _meta: { ui: { prefersBorder: true } },
+ },
+ ],
+ };
+ } else {
+ result = {};
+ }
+ process.stdout.write(JSON.stringify({ jsonrpc: "2.0", id: msg.id, result }) + "\\n");
+ }
+});
+process.stdin.on("end", () => process.exit(0));
+`;
+
+let tempRoot = "";
+
+beforeAll(() => {
+ tempRoot = mkdtempSync(join(tmpdir(), "cline-mcp-apps-"));
+ writeFileSync(join(tempRoot, "apps-server.js"), APPS_SERVER_SCRIPT);
+});
+
+afterAll(() => {
+ rmSync(tempRoot, { recursive: true, force: true });
+});
+
+function appsServerRegistration(): McpServerRegistration {
+ return {
+ name: "apps-server",
+ transport: {
+ type: "stdio",
+ command:
+ process.platform === "win32"
+ ? `"${process.execPath}"`
+ : process.execPath,
+ args: [join(tempRoot, "apps-server.js")],
+ },
+ };
+}
+
+async function readInitializeCapabilities(
+ mcpApps: boolean | undefined,
+): Promise {
+ const client = await createDefaultMcpServerClientFactory({ mcpApps })(
+ appsServerRegistration(),
+ );
+ try {
+ await client.connect();
+ const result = (await client.callTool({ name: "capabilities" })) as {
+ content: Array<{ text: string }>;
+ };
+ return JSON.parse(result.content[0].text);
+ } finally {
+ await client.disconnect();
+ }
+}
+
+describe("stdio MCP client app support", () => {
+ it("advertises the MCP Apps extension only when enabled", async () => {
+ expect(await readInitializeCapabilities(undefined)).toEqual({});
+ expect(await readInitializeCapabilities(true)).toEqual({
+ extensions: {
+ "io.modelcontextprotocol/ui": {
+ mimeTypes: ["text/html;profile=mcp-app"],
+ },
+ },
+ });
+ });
+
+ it("keeps tool _meta and reads ui:// resources", async () => {
+ const client = await createDefaultMcpServerClientFactory()(
+ appsServerRegistration(),
+ );
+ try {
+ await client.connect();
+ expect(await client.listTools()).toEqual([
+ {
+ name: "show_weather",
+ inputSchema: { type: "object" },
+ _meta: { ui: { resourceUri: "ui://weather/view.html" } },
+ },
+ { name: "plain", inputSchema: { type: "object" } },
+ ]);
+ expect(
+ await client.readResource?.({ uri: "ui://weather/view.html" }),
+ ).toEqual({
+ contents: [
+ {
+ uri: "ui://weather/view.html",
+ mimeType: "text/html;profile=mcp-app",
+ text: "",
+ _meta: { ui: { prefersBorder: true } },
+ },
+ ],
+ });
+ } finally {
+ await client.disconnect();
+ }
+ });
+
+ it("rejects malformed resources/read results", async () => {
+ const client = await createDefaultMcpServerClientFactory()(
+ appsServerRegistration(),
+ );
+ try {
+ await client.connect();
+ for (const uri of [
+ "ui://broken/missing-contents",
+ "ui://broken/object-contents",
+ ]) {
+ await expect(client.readResource?.({ uri })).rejects.toThrow(
+ 'MCP server "apps-server" returned an invalid resources/read result',
+ );
+ }
+ } finally {
+ await client.disconnect();
+ }
+ });
+});
diff --git a/sdk/packages/core/src/extensions/mcp/client-url.test.ts b/sdk/packages/core/src/extensions/mcp/client-url.test.ts
index 20409f7d16..21c32a9199 100644
--- a/sdk/packages/core/src/extensions/mcp/client-url.test.ts
+++ b/sdk/packages/core/src/extensions/mcp/client-url.test.ts
@@ -16,8 +16,12 @@ function makeSseError(code: number | undefined, message: string): SseError {
}
const clientState = vi.hoisted(() => ({
+ constructorOptions: undefined as unknown,
connectOptions: undefined as unknown,
listToolsOptions: undefined as unknown,
+ listedTools: [] as unknown[],
+ readResourceRequest: undefined as unknown,
+ readResourceOptions: undefined as unknown,
callToolOptions: undefined as unknown,
callToolError: undefined as unknown,
connectError: undefined as unknown,
@@ -26,6 +30,10 @@ const clientState = vi.hoisted(() => ({
vi.mock("@modelcontextprotocol/sdk/client/index.js", () => ({
Client: class {
+ constructor(_info: unknown, options?: unknown) {
+ clientState.constructorOptions = options;
+ }
+
async connect(_transport: unknown, options: unknown): Promise {
clientState.connectOptions = options;
if (clientState.connectError) {
@@ -39,7 +47,13 @@ vi.mock("@modelcontextprotocol/sdk/client/index.js", () => ({
async listTools(_params: unknown, options: unknown) {
clientState.listToolsOptions = options;
- return { tools: [] };
+ return { tools: clientState.listedTools };
+ }
+
+ async readResource(request: unknown, options: unknown) {
+ clientState.readResourceRequest = request;
+ clientState.readResourceOptions = options;
+ return { contents: [] };
}
async callTool(
@@ -258,6 +272,80 @@ describe("SDK URL MCP client timeout", () => {
});
});
+describe("SDK URL MCP client app support", () => {
+ beforeEach(() => {
+ clientState.constructorOptions = undefined;
+ clientState.listedTools = [];
+ clientState.readResourceRequest = undefined;
+ clientState.readResourceOptions = undefined;
+ clientState.connectError = undefined;
+ });
+
+ const registration = {
+ name: "remote",
+ transport: {
+ type: "streamableHttp" as const,
+ url: "https://mcp.example.test",
+ },
+ timeoutSeconds: 12,
+ };
+
+ it("advertises the MCP Apps extension only when enabled", async () => {
+ await (await createDefaultMcpServerClientFactory()(registration)).connect();
+ expect(clientState.constructorOptions).toBeUndefined();
+
+ await (
+ await createDefaultMcpServerClientFactory({ mcpApps: true })(registration)
+ ).connect();
+ expect(clientState.constructorOptions).toEqual({
+ capabilities: {
+ extensions: {
+ "io.modelcontextprotocol/ui": {
+ mimeTypes: ["text/html;profile=mcp-app"],
+ },
+ },
+ },
+ });
+ });
+
+ it("keeps tool _meta and reads resources with the request timeout", async () => {
+ clientState.listedTools = [
+ {
+ name: "show_weather",
+ inputSchema: { type: "object" },
+ _meta: { ui: { resourceUri: "ui://weather/view.html" } },
+ },
+ ];
+ const client = await createDefaultMcpServerClientFactory()(registration);
+ const controller = new AbortController();
+
+ expect(await client.listTools()).toEqual([
+ {
+ name: "show_weather",
+ description: undefined,
+ inputSchema: { type: "object" },
+ _meta: { ui: { resourceUri: "ui://weather/view.html" } },
+ },
+ ]);
+ await client.readResource?.({
+ uri: "ui://weather/view.html",
+ context: {
+ agentId: "test-agent",
+ iteration: 1,
+ signal: controller.signal,
+ },
+ });
+
+ expect(clientState.readResourceRequest).toEqual({
+ uri: "ui://weather/view.html",
+ });
+ expect(clientState.readResourceOptions).toEqual({
+ timeout: 12_000,
+ signal: controller.signal,
+ });
+ });
+});
+
describe("SDK URL MCP client authorization persistence", () => {
const tempRoots: string[] = [];
diff --git a/sdk/packages/core/src/extensions/mcp/client.ts b/sdk/packages/core/src/extensions/mcp/client.ts
index 16849bb019..76f82111bb 100644
--- a/sdk/packages/core/src/extensions/mcp/client.ts
+++ b/sdk/packages/core/src/extensions/mcp/client.ts
@@ -8,6 +8,8 @@ import {
} from "@cline/shared";
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import type { FetchLike } from "@modelcontextprotocol/sdk/shared/transport.js";
+import { ReadResourceResultSchema } from "@modelcontextprotocol/sdk/types.js";
+import { createMcpAppsClientCapabilities } from "./apps";
import {
createMcpOAuthClientInformation,
createMcpOAuthProviderContext,
@@ -17,6 +19,7 @@ import {
} from "./oauth";
import { augmentMcpTimeoutError, resolveMcpRequestTimeoutMs } from "./timeout";
import type {
+ McpResourceReadResult,
McpServerClient,
McpServerClientFactory,
McpServerRegistration,
@@ -224,9 +227,11 @@ class StdioMcpClient implements McpServerClient {
private protocolMode: StdioProtocolMode = "newline";
private readonly requestTimeoutMs: number;
private readonly connectAttemptTimeoutMs: number;
+ private readonly mcpApps: boolean;
- constructor(registration: McpServerRegistration) {
+ constructor(registration: McpServerRegistration, mcpApps = false) {
this.registration = registration;
+ this.mcpApps = mcpApps;
this.requestTimeoutMs = resolveMcpRequestTimeoutMs(
registration.timeoutSeconds,
);
@@ -252,7 +257,7 @@ class StdioMcpClient implements McpServerClient {
const initializeParams = {
protocolVersion: MCP_PROTOCOL_VERSION,
- capabilities: {},
+ capabilities: this.mcpApps ? createMcpAppsClientCapabilities() : {},
clientInfo: { name: "@cline/core", version: "0.0.0" },
};
await this.ensureAgentPluginDataDirectory();
@@ -362,6 +367,7 @@ class StdioMcpClient implements McpServerClient {
name?: string;
description?: string;
inputSchema?: Record;
+ _meta?: Record;
}>;
};
return (result.tools ?? [])
@@ -372,6 +378,7 @@ class StdioMcpClient implements McpServerClient {
name: string;
description?: string;
inputSchema: Record;
+ _meta?: Record;
} =>
typeof tool?.name === "string" &&
typeof tool.inputSchema === "object" &&
@@ -381,6 +388,11 @@ class StdioMcpClient implements McpServerClient {
name: tool.name,
description: tool.description,
inputSchema: tool.inputSchema,
+ ...(tool._meta &&
+ typeof tool._meta === "object" &&
+ !Array.isArray(tool._meta)
+ ? { _meta: tool._meta }
+ : {}),
}));
}
@@ -400,6 +412,26 @@ class StdioMcpClient implements McpServerClient {
);
}
+ async readResource(request: {
+ uri: string;
+ context?: AgentToolContext;
+ }): Promise {
+ const result = ReadResourceResultSchema.safeParse(
+ await this.request(
+ "resources/read",
+ { uri: request.uri },
+ undefined,
+ request.context?.signal,
+ ),
+ );
+ if (!result.success) {
+ throw new Error(
+ `MCP server "${this.registration.name}" returned an invalid resources/read result: ${result.error.message}`,
+ );
+ }
+ return result.data;
+ }
+
private spawnProcess(protocolMode: StdioProtocolMode): void {
const transport = this.registration.transport;
if (transport.type !== "stdio") {
@@ -702,6 +734,7 @@ export interface DefaultMcpServerClientFactoryOptions {
fetch?: FetchLike;
/** Keep literal configured headers on the declared MCP origin only. */
restrictConfiguredHeadersToOrigin?: boolean;
+ mcpApps?: boolean;
}
export interface ProbeMcpServerConnectionOptions
@@ -769,10 +802,15 @@ class SdkUrlMcpClient implements McpServerClient {
: undefined;
let client: Client | undefined;
try {
- client = new Client({
- name: this.options.clientName?.trim() || "@cline/core",
- version: this.options.clientVersion?.trim() || "0.0.0",
- });
+ client = new Client(
+ {
+ name: this.options.clientName?.trim() || "@cline/core",
+ version: this.options.clientVersion?.trim() || "0.0.0",
+ },
+ this.options.mcpApps
+ ? { capabilities: createMcpAppsClientCapabilities() }
+ : undefined,
+ );
const transport = createMcpSdkTransport({
registration: this.registration,
oauthProvider,
@@ -826,6 +864,7 @@ class SdkUrlMcpClient implements McpServerClient {
!Array.isArray(tool.inputSchema)
? tool.inputSchema
: {},
+ ...(tool._meta ? { _meta: tool._meta } : {}),
}));
} catch (error) {
return await this.handleOperationError(error);
@@ -855,6 +894,24 @@ class SdkUrlMcpClient implements McpServerClient {
}
}
+ async readResource(request: {
+ uri: string;
+ context?: AgentToolContext;
+ }): Promise {
+ const client = await this.ensureConnectedClient();
+ try {
+ return await client.readResource(
+ { uri: request.uri },
+ {
+ timeout: this.requestTimeoutMs,
+ signal: request.context?.signal,
+ },
+ );
+ } catch (error) {
+ return await this.handleOperationError(error);
+ }
+ }
+
private async ensureConnectedClient(): Promise {
if (!this.client) {
await this.connect();
@@ -923,7 +980,7 @@ export function createDefaultMcpServerClientFactory(
): McpServerClientFactory {
return (registration) =>
registration.transport.type === "stdio"
- ? new StdioMcpClient(registration)
+ ? new StdioMcpClient(registration, options.mcpApps)
: new SdkUrlMcpClient(registration, options);
}
diff --git a/sdk/packages/core/src/extensions/mcp/index.ts b/sdk/packages/core/src/extensions/mcp/index.ts
index c8d4043f4f..ec619bc5ff 100644
--- a/sdk/packages/core/src/extensions/mcp/index.ts
+++ b/sdk/packages/core/src/extensions/mcp/index.ts
@@ -1,3 +1,13 @@
+export type { McpAppToolMeta, McpAppToolVisibility } from "./apps";
+export {
+ createMcpAppsClientCapabilities,
+ getMcpAppToolMeta,
+ isMcpAppResourceUri,
+ isMcpToolVisibleToApp,
+ isMcpToolVisibleToModel,
+ MCP_APP_MIME_TYPE,
+ MCP_APPS_EXTENSION_ID,
+} from "./apps";
export type {
DefaultMcpServerClientFactoryOptions,
ProbeMcpServerConnectionOptions,
@@ -66,6 +76,9 @@ export type {
McpConnectionStatus,
McpManager,
McpManagerOptions,
+ McpResourceContents,
+ McpResourceReadRequest,
+ McpResourceReadResult,
McpServerClient,
McpServerClientFactory,
McpServerOAuthClientConfig,
diff --git a/sdk/packages/core/src/extensions/mcp/manager.test.ts b/sdk/packages/core/src/extensions/mcp/manager.test.ts
index cad07ed52a..adf90a8cf1 100644
--- a/sdk/packages/core/src/extensions/mcp/manager.test.ts
+++ b/sdk/packages/core/src/extensions/mcp/manager.test.ts
@@ -211,4 +211,95 @@ describe("InMemoryMcpManager", () => {
await manager.connectServer(registration.name);
expect(clientFactory).toHaveBeenCalledTimes(1);
});
+
+ it("keeps tool _meta in the cache and reads resources through the client", async () => {
+ const client = createClient({
+ listTools: vi.fn(async () => [
+ {
+ name: "show_weather",
+ inputSchema: { type: "object" },
+ _meta: { ui: { resourceUri: "ui://weather/view.html" } },
+ },
+ ]),
+ readResource: vi.fn(async () => ({
+ contents: [{ uri: "ui://weather/view.html", text: "" }],
+ })),
+ });
+ const manager = new InMemoryMcpManager({
+ clientFactory: vi.fn(async () => client),
+ });
+ await manager.registerServer({
+ name: "weather",
+ transport: { type: "streamableHttp", url: "https://mcp.example.test" },
+ });
+
+ const tools = await manager.listTools("weather");
+ expect(tools[0]._meta).toEqual({
+ ui: { resourceUri: "ui://weather/view.html" },
+ });
+ expect(
+ await manager.readResource({
+ serverName: "weather",
+ uri: "ui://weather/view.html",
+ }),
+ ).toEqual({
+ contents: [{ uri: "ui://weather/view.html", text: "" }],
+ });
+ expect(client.readResource).toHaveBeenCalledWith({
+ uri: "ui://weather/view.html",
+ context: undefined,
+ });
+ });
+
+ it("rejects resource reads when the client cannot read resources", async () => {
+ const manager = new InMemoryMcpManager({
+ clientFactory: vi.fn(async () => createClient()),
+ });
+ await manager.registerServer({
+ name: "weather",
+ transport: { type: "streamableHttp", url: "https://mcp.example.test" },
+ });
+
+ await expect(
+ manager.readResource({
+ serverName: "weather",
+ uri: "ui://weather/view.html",
+ }),
+ ).rejects.toThrow("does not support reading resources");
+ });
+
+ it("reads resources while a tool call on the same server is in flight", async () => {
+ let finishCall: (() => void) | undefined;
+ const client = createClient({
+ callTool: vi.fn(
+ () =>
+ new Promise((resolve) => {
+ finishCall = () => resolve({ ok: true });
+ }),
+ ),
+ readResource: vi.fn(async () => ({ contents: [] })),
+ });
+ const manager = new InMemoryMcpManager({
+ clientFactory: vi.fn(async () => client),
+ });
+ await manager.registerServer({
+ name: "weather",
+ transport: { type: "streamableHttp", url: "https://mcp.example.test" },
+ });
+
+ const call = manager.callTool({
+ serverName: "weather",
+ toolName: "show_weather",
+ });
+ await vi.waitFor(() => expect(client.callTool).toHaveBeenCalled());
+
+ await expect(
+ manager.readResource({
+ serverName: "weather",
+ uri: "ui://weather/view.html",
+ }),
+ ).resolves.toEqual({ contents: [] });
+ finishCall?.();
+ await call;
+ });
});
diff --git a/sdk/packages/core/src/extensions/mcp/manager.ts b/sdk/packages/core/src/extensions/mcp/manager.ts
index d3193771ed..8aff8f1a93 100644
--- a/sdk/packages/core/src/extensions/mcp/manager.ts
+++ b/sdk/packages/core/src/extensions/mcp/manager.ts
@@ -6,6 +6,8 @@ import type {
McpConnectionStatus,
McpManager,
McpManagerOptions,
+ McpResourceReadRequest,
+ McpResourceReadResult,
McpServerClient,
McpServerRegistration,
McpServerSnapshot,
@@ -37,6 +39,7 @@ function cloneTools(
name: tool.name,
description: tool.description,
inputSchema: tool.inputSchema,
+ ...(tool._meta ? { _meta: tool._meta } : {}),
}));
}
@@ -178,6 +181,30 @@ export class InMemoryMcpManager implements McpManager {
});
}
+ async readResource(
+ request: McpResourceReadRequest,
+ ): Promise {
+ const current = this.requireServer(request.serverName);
+ const client =
+ current.status === "connected" &&
+ current.client &&
+ !current.registration.disabled
+ ? current.client
+ : await this.runExclusive(request.serverName, async () =>
+ this.ensureConnectedClient(this.requireServer(request.serverName)),
+ );
+ this.requireServer(request.serverName).updatedAt = nowMs();
+ if (!client.readResource) {
+ throw new Error(
+ `MCP server "${request.serverName}" client does not support reading resources.`,
+ );
+ }
+ return client.readResource({
+ uri: request.uri,
+ context: request.context,
+ });
+ }
+
async dispose(): Promise {
const names = [...this.servers.keys()];
// One wedged server (e.g. a stdio child that never exits) must not stop
diff --git a/sdk/packages/core/src/extensions/mcp/tools.test.ts b/sdk/packages/core/src/extensions/mcp/tools.test.ts
index cee3cebc4d..fbd26ffe4a 100644
--- a/sdk/packages/core/src/extensions/mcp/tools.test.ts
+++ b/sdk/packages/core/src/extensions/mcp/tools.test.ts
@@ -20,3 +20,29 @@ describe("MCP result policy", () => {
);
});
});
+
+describe("MCP Apps tool visibility", () => {
+ const listTools = async () => [
+ {
+ name: "show_weather",
+ inputSchema: { type: "object" },
+ _meta: { ui: { resourceUri: "ui://weather/view.html" } },
+ },
+ {
+ name: "refresh_view",
+ inputSchema: { type: "object" },
+ _meta: { ui: { visibility: ["app"] } },
+ },
+ ];
+
+ it("leaves app-only tools out of the model's tool list", async () => {
+ const tools = await createMcpTools({
+ serverName: "weather",
+ provider: {
+ listTools,
+ callTool: async () => ({ content: [] }),
+ },
+ });
+ expect(tools.map((tool) => tool.name)).toEqual(["weather__show_weather"]);
+ });
+});
diff --git a/sdk/packages/core/src/extensions/mcp/tools.ts b/sdk/packages/core/src/extensions/mcp/tools.ts
index 6e41a8aef7..5ae487280b 100644
--- a/sdk/packages/core/src/extensions/mcp/tools.ts
+++ b/sdk/packages/core/src/extensions/mcp/tools.ts
@@ -1,4 +1,5 @@
import { type AgentTool, createTool } from "@cline/shared";
+import { isMcpToolVisibleToModel } from "./apps";
import { defaultMcpToolNameTransform } from "./name-transform";
import type { CreateMcpToolsOptions, McpToolDescriptor } from "./types";
@@ -19,7 +20,7 @@ export async function createMcpTools(
const descriptors = await options.provider.listTools(options.serverName);
const nameTransform = options.nameTransform ?? defaultMcpToolNameTransform;
- return descriptors.map((descriptor) => {
+ return descriptors.filter(isMcpToolVisibleToModel).map((descriptor) => {
const agentToolName = nameTransform({
serverName: options.serverName,
toolName: descriptor.name,
diff --git a/sdk/packages/core/src/extensions/mcp/types.ts b/sdk/packages/core/src/extensions/mcp/types.ts
index 646d2b4df6..6b82d25439 100644
--- a/sdk/packages/core/src/extensions/mcp/types.ts
+++ b/sdk/packages/core/src/extensions/mcp/types.ts
@@ -4,6 +4,7 @@ export interface McpToolDescriptor {
name: string;
description?: string;
inputSchema: Record;
+ _meta?: Record;
}
export interface McpToolCallRequest {
@@ -15,6 +16,25 @@ export interface McpToolCallRequest {
export type McpToolCallResult = unknown;
+export interface McpResourceReadRequest {
+ serverName: string;
+ uri: string;
+ context?: AgentToolContext;
+}
+
+export interface McpResourceContents {
+ uri: string;
+ mimeType?: string;
+ text?: string;
+ blob?: string;
+ _meta?: Record;
+}
+
+export interface McpResourceReadResult {
+ contents: McpResourceContents[];
+ _meta?: Record;
+}
+
export interface McpToolProvider {
listTools(serverName: string): Promise;
callTool(request: McpToolCallRequest): Promise;
@@ -114,6 +134,10 @@ export interface McpServerClient {
arguments?: Record;
context?: AgentToolContext;
}): Promise;
+ readResource?(request: {
+ uri: string;
+ context?: AgentToolContext;
+ }): Promise;
}
export type McpServerClientFactory = (
@@ -148,5 +172,8 @@ export interface McpManager extends McpToolProvider {
listServers(): readonly McpServerSnapshot[];
refreshTools(serverName: string): Promise;
callTool(request: McpToolCallRequest): Promise;
+ readResource?(
+ request: McpResourceReadRequest,
+ ): Promise;
dispose(): Promise;
}
diff --git a/sdk/packages/core/src/index.ts b/sdk/packages/core/src/index.ts
index ef87c5cab4..3a1dd85c03 100644
--- a/sdk/packages/core/src/index.ts
+++ b/sdk/packages/core/src/index.ts
@@ -324,20 +324,32 @@ export {
createDefaultMcpServerClientFactory,
createDisabledMcpToolPolicies,
createDisabledMcpToolPolicy,
+ createMcpAppsClientCapabilities,
createMcpTools,
DEFAULT_MCP_CONNECT_TIMEOUT_MS,
type DefaultMcpServerClientFactoryOptions,
+ getMcpAppToolMeta,
getMcpServerOAuthState,
getMcpServerOAuthStatus,
hasMcpSettingsFile,
InMemoryMcpManager,
+ isMcpAppResourceUri,
+ isMcpToolVisibleToApp,
+ isMcpToolVisibleToModel,
type LoadMcpSettingsOptions,
listMcpServerOAuthStatuses,
loadMcpSettingsFile,
+ MCP_APP_MIME_TYPE,
+ MCP_APPS_EXTENSION_ID,
+ type McpAppToolMeta,
+ type McpAppToolVisibility,
type McpConnectionStatus,
type McpManager,
type McpManagerOptions,
McpOAuthClientChangedError,
+ type McpResourceContents,
+ type McpResourceReadRequest,
+ type McpResourceReadResult,
type McpServerClient,
type McpServerClientFactory,
type McpServerOAuthClientConfig,
From dc3d7a58c97174e4de4dd46cc53801dfbe5ca092 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Miko=C5=82aj=20Kondratek?=
<19799111+mkondratek@users.noreply.github.com>
Date: Mon, 19 Oct 2026 07:34:47 +0200
Subject: [PATCH 25/29] fix(vscode): keep keyboard focus when revealing the
terminal for a command (#15061)
* fix(vscode): keep keyboard focus when revealing the terminal for a command
Every foreground run_commands execution called terminal.show() with no
argument, which makes VS Code move keyboard focus into the terminal. A user
typing in the chat input while Cline starts a command had the rest of their
keystrokes land in the shell, corrupting the running command.
Pass preserveFocus=true at both reveal sites (the per-command reveal in
runCommand and the pre-cd reveal of a reused terminal). The terminal panel
is still revealed, which is all shell-integration initialization needs.
* test(vscode): stub the command process in the reveal-only terminal test
The reveal test fed the process a never-ending stream, so its VS Code shell-execution and terminal-close listeners outlived the test. Stub run() instead; the test only checks the reveal call.
---
.../terminal/VscodeTerminalManager.test.ts | 23 +++++++++++++++++++
.../vscode/terminal/VscodeTerminalManager.ts | 8 +++++--
2 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/apps/vscode/src/hosts/vscode/terminal/VscodeTerminalManager.test.ts b/apps/vscode/src/hosts/vscode/terminal/VscodeTerminalManager.test.ts
index 8cbd172734..1cd60a6aab 100644
--- a/apps/vscode/src/hosts/vscode/terminal/VscodeTerminalManager.test.ts
+++ b/apps/vscode/src/hosts/vscode/terminal/VscodeTerminalManager.test.ts
@@ -4,6 +4,7 @@ import * as sinon from "sinon"
import * as vscode from "vscode"
import { setVscodeHostProviderMock } from "@/test/host-provider-test-utils"
import { VscodeTerminalManager } from "./VscodeTerminalManager"
+import { VscodeTerminalProcess } from "./VscodeTerminalProcess"
import { TerminalInfo, TerminalRegistry } from "./VscodeTerminalRegistry"
function createNeverEndingStream(): AsyncIterable {
@@ -128,6 +129,28 @@ describe("VscodeTerminalManager", () => {
assert.equal(terminalInfo.busy, true)
assert.equal(terminalInfo.pendingCwdChange, undefined)
assert.equal(terminalInfo.cwdResolved, undefined)
+ sinon.assert.calledOnceWithExactly(terminalInfo.terminal.show as sinon.SinonStub, true)
+ })
+
+ it("reveals the terminal without taking focus when running a command", async () => {
+ // Reveal-only test: stub the process so no command stream or VS Code
+ // event listeners outlive the test.
+ sandbox.stub(VscodeTerminalProcess.prototype, "run").resolves()
+ const showStub = sandbox.stub()
+ const terminalInfo: TerminalInfo = {
+ id: 1,
+ busy: false,
+ lastCommand: "",
+ lastActive: Date.now(),
+ terminal: {
+ shellIntegration: {},
+ show: showStub,
+ } as unknown as vscode.Terminal,
+ }
+
+ manager.runCommand(terminalInfo as unknown as Parameters[0], "echo hi")
+
+ sinon.assert.calledOnceWithExactly(showStub, true)
})
it("releases a reused terminal reservation when showing it fails", async () => {
diff --git a/apps/vscode/src/hosts/vscode/terminal/VscodeTerminalManager.ts b/apps/vscode/src/hosts/vscode/terminal/VscodeTerminalManager.ts
index 80cda975eb..eda39fdeb6 100644
--- a/apps/vscode/src/hosts/vscode/terminal/VscodeTerminalManager.ts
+++ b/apps/vscode/src/hosts/vscode/terminal/VscodeTerminalManager.ts
@@ -210,7 +210,10 @@ export class VscodeTerminalManager {
Logger.log(`[TerminalManager] Terminal ${vscodeTerminalInfo.id} busy state before: ${vscodeTerminalInfo.busy}`)
try {
- vscodeTerminalInfo.terminal.show()
+ // Reveal the terminal but keep keyboard focus where it is: focusing the
+ // terminal mid-command would send the user's in-progress chat input to
+ // the shell.
+ vscodeTerminalInfo.terminal.show(true)
} catch (error) {
vscodeTerminalInfo.busy = false
throw error
@@ -379,7 +382,8 @@ export class VscodeTerminalManager {
})
// Showing the reused terminal gives VS Code a chance to initialize shell integration.
// runCommand() below waits up to shellIntegrationTimeout for executeCommand before falling back.
- availableTerminal.terminal.show()
+ // preserveFocus keeps the user's keyboard focus (e.g. the chat input) where it was.
+ availableTerminal.terminal.show(true)
let cwdChangeResult: CwdChangeResult | undefined
try {
From 3b1ecbb1f3298848ec7932626d56c11ed00ee2c6 Mon Sep 17 00:00:00 2001
From: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
Date: Mon, 19 Oct 2026 01:39:01 -0700
Subject: [PATCH 26/29] fix(llms): stop sending native Google Search on the
Gemini API (#15194)
Web search became default-on in #13957, so every Gemini API request now
carries the googleSearch grounding tool. Free-tier keys have no grounding
quota on Gemini 3+ models, so each turn fails with 429 'You exceeded your
current quota' (and is retried 6 times). On Gemini 2.x the AI SDK cannot
combine googleSearch with function tools and drops every Cline tool.
Remove the web_search model-tool capability from the gemini provider
manifest. Vertex, which has no free tier, keeps native search.
---
sdk/packages/llms/src/providers/builtins.ts | 4 +++-
sdk/packages/llms/src/providers/model-tools.test.ts | 11 ++++++++++-
2 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/sdk/packages/llms/src/providers/builtins.ts b/sdk/packages/llms/src/providers/builtins.ts
index 5da4681bca..7b1f5cb681 100644
--- a/sdk/packages/llms/src/providers/builtins.ts
+++ b/sdk/packages/llms/src/providers/builtins.ts
@@ -1249,7 +1249,9 @@ const BUILTIN_SPEC_OVERRIDES: BuiltinSpecOverride[] = [
name: "Google Gemini",
description: "Google Gemini API",
family: "google",
- modelToolCapabilities: NATIVE_WEB_SEARCH_MODEL_TOOL_CAPABILITIES,
+ // No native Google Search: free-tier keys have no grounding quota on
+ // Gemini 3+ (every request fails with 429), and Gemini 2.x cannot
+ // combine it with function tools, so the AI SDK drops Cline's tools.
popular: 45,
capabilities: ["reasoning", "prompt-cache"],
apiKeyEnv: ["GOOGLE_GENERATIVE_AI_API_KEY", "GEMINI_API_KEY"],
diff --git a/sdk/packages/llms/src/providers/model-tools.test.ts b/sdk/packages/llms/src/providers/model-tools.test.ts
index 659f7e069d..a43ed241f1 100644
--- a/sdk/packages/llms/src/providers/model-tools.test.ts
+++ b/sdk/packages/llms/src/providers/model-tools.test.ts
@@ -13,12 +13,21 @@ describe("supportsModelTool", () => {
["anthropic", undefined],
["openai-native", undefined],
["openai-codex", undefined],
- ["gemini", undefined],
["vertex", "gemini-3.1-pro-preview"],
])("supports native web search for %s / %s", (providerId, modelId) => {
expect(supportsModelTool({ providerId, modelId }, "web_search")).toBe(true);
});
+ it("does not offer native web search on the Gemini API", () => {
+ expect(
+ supportsModelTool(
+ { providerId: "gemini", modelId: "gemini-3.5-flash-lite" },
+ "web_search",
+ ),
+ ).toBe(false);
+ expect(providerOffersModelTool("gemini", "web_search")).toBe(false);
+ });
+
it("normalizes aliases before resolving support", () => {
expect(
supportsModelTool(
From 0e4b58c1c90d582380255d3c618735f68e17ebb2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Miko=C5=82aj=20Kondratek?=
<19799111+mkondratek@users.noreply.github.com>
Date: Mon, 19 Oct 2026 12:11:26 +0200
Subject: [PATCH 27/29] fix(core): explain PowerShell quote escaping in the
run_commands description (#15115)
Models default to bash-style \" escaping, which PowerShell treats as the
end of a double-quoted string. Wrapped in cmd /c, the leftover text becomes
extra arguments, and in one reported case handed rmdir /s /q a bare \,
the root of the current drive.
For PowerShell shells only, tell the model that the backtick is the escape
character, to single-quote literal paths, to prefer cmdlets over cmd /c,
and to confirm recursive or forced deletes before running them.
---
.../src/extensions/tools/definitions.test.ts | 24 +++++++++++++++++++
.../core/src/extensions/tools/definitions.ts | 13 ++++++++++
2 files changed, 37 insertions(+)
diff --git a/sdk/packages/core/src/extensions/tools/definitions.test.ts b/sdk/packages/core/src/extensions/tools/definitions.test.ts
index 493117341c..937df0024e 100644
--- a/sdk/packages/core/src/extensions/tools/definitions.test.ts
+++ b/sdk/packages/core/src/extensions/tools/definitions.test.ts
@@ -531,6 +531,30 @@ describe("run_commands tool description", () => {
expect(description).not.toMatch(/PowerShell (?:Core|\d)/);
});
+ it.each([
+ ["powershell.exe", true],
+ ["pwsh.exe", true],
+ ["/usr/bin/pwsh", false],
+ ])("tells %s how PowerShell escapes quotes", (shell, isWindows) => {
+ const description = buildRunCommandsDescription(shell, isWindows);
+ expect(description).toContain(
+ 'PowerShell escapes with a backtick (`), not a backslash: inside double quotes, \\" ends the string.',
+ );
+ expect(description).toContain("Remove-Item -LiteralPath instead of cmd /c");
+ expect(description).toContain("-WhatIf");
+ });
+
+ it.each([
+ ["cmd", true],
+ ["C:\\Program Files\\Git\\bin\\bash.exe", true],
+ ["wsl", true],
+ ["/bin/bash", false],
+ ])("keeps PowerShell quoting guidance out of %s", (shell, isWindows) => {
+ const description = buildRunCommandsDescription(shell, isWindows);
+ expect(description).not.toContain("backtick");
+ expect(description).not.toContain("Remove-Item");
+ });
+
it("names cmd.exe with '&&' sequencing for cmd shells", () => {
const description = buildRunCommandsDescription("cmd", true);
expect(description).toContain("Commands run through cmd.exe");
diff --git a/sdk/packages/core/src/extensions/tools/definitions.ts b/sdk/packages/core/src/extensions/tools/definitions.ts
index 9f783791c8..3e2aa39963 100644
--- a/sdk/packages/core/src/extensions/tools/definitions.ts
+++ b/sdk/packages/core/src/extensions/tools/definitions.ts
@@ -422,6 +422,18 @@ const RUN_COMMANDS_SHARED_INSTRUCTIONS =
"Use for listing files, checking git status, running builds, executing tests, etc. " +
"Commands must be non-interactive. Commands that require follow-up input like pagers should be skipped or used with supported flags/env (e.g. git --no-pager, --non-interactive) to bypass the interaction steps. ";
+/**
+ * PowerShell quoting guidance. Models default to bash/C escaping, but in
+ * PowerShell a backslash is an ordinary character: `"a \"b\" c"` ends the
+ * string at the first `\"`, and the rest becomes separate arguments. Through
+ * `cmd /c` that can hand `rmdir /s /q` a bare `\`, which is the root of the
+ * current drive.
+ */
+const POWERSHELL_QUOTING_INSTRUCTIONS =
+ 'PowerShell escapes with a backtick (`), not a backslash: inside double quotes, \\" ends the string. Put literal paths in single quotes. ' +
+ "Use cmdlets such as Remove-Item -LiteralPath instead of cmd /c; cmd re-parses the quotes, and a mis-quoted path can become extra targets such as the drive root. " +
+ "Before a recursive or forced delete, confirm the exact target, for example with -WhatIf. ";
+
/**
* Build the run_commands tool description for the shell that will actually
* execute the commands. Derive the edition and wrapper guidance from the
@@ -457,6 +469,7 @@ export function buildRunCommandsDescription(
`Output beyond ~${Math.round(MAX_COMMAND_OUTPUT_CHARS / 1000)}k characters is middle-truncated (start and end preserved); filter output when you need specific sections. ` +
`Commands run through ${shellName}; quote paths and arguments for ${executable} and use ${sequencingOperator} to sequence commands. ` +
`Write commands directly; do not wrap them in another ${wrapper} invocation. ` +
+ (shellKind === "powershell" ? POWERSHELL_QUOTING_INSTRUCTIONS : "") +
"Only start another shell when you intentionally need a different shell or a separate process. " +
"Include multiple commands in the same call when they are independent and safe to run concurrently. When independent reads, searches, or edits are also needed, call those tools in the same response."
);
From 9857d19fc43abac32f1ff4b92cc5bbf104ac2d1f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Miko=C5=82aj=20Kondratek?=
<19799111+mkondratek@users.noreply.github.com>
Date: Mon, 19 Oct 2026 12:43:41 +0200
Subject: [PATCH 28/29] fix(vscode): keep the session's mode in sync when
Plan/Act is toggled during a session start (#15026)
* test(vscode): cover Plan/Act toggles that race a session start
A toggle that lands while a session is being started or replaced sees no
active session, flips only the setting, and leaves the session running with
the other mode's tools. These tests reproduce that and fail on main.
* fix(vscode): keep the session's mode in sync when Plan/Act is toggled during a session start
Starting or replacing a session detaches the outgoing one before the new one
is active. A toggle in that window saw no session, flipped only the setting,
and the session that finished starting kept the other mode's tools, so the UI
showed Act while every write was blocked as plan mode.
- Sessions record the mode they were built for.
- The toggle decides under the rebuild lock, after waiting for session starts
that run outside it (new task, edited message, checkpoint restore).
- The toggle and the rebuild compare against the session's mode rather than
the setting, which also fixes the stale mode notice the late rebuild left.
* test(vscode): release session-start waiters when the start fails
Cover a waiter that is already in place when a tracked start rejects. The
previous check only waited after the rejection, so an implementation that
rejected existing waiters would still have passed.
---
apps/vscode/src/sdk/SdkController.test.ts | 79 +++++++++-
apps/vscode/src/sdk/SdkController.ts | 21 +++
apps/vscode/src/sdk/cline-session-factory.ts | 6 +
.../src/sdk/sdk-mode-coordinator.test.ts | 111 ++++++++++++-
apps/vscode/src/sdk/sdk-mode-coordinator.ts | 34 +++-
.../src/sdk/sdk-session-lifecycle.test.ts | 50 ++++++
apps/vscode/src/sdk/sdk-session-lifecycle.ts | 39 +++++
.../sdk/sdk-task-start-coordinator.test.ts | 33 ++++
.../src/sdk/sdk-task-start-coordinator.ts | 148 +++++++++---------
9 files changed, 436 insertions(+), 85 deletions(-)
diff --git a/apps/vscode/src/sdk/SdkController.test.ts b/apps/vscode/src/sdk/SdkController.test.ts
index 08b0fe620b..f9cbda8780 100644
--- a/apps/vscode/src/sdk/SdkController.test.ts
+++ b/apps/vscode/src/sdk/SdkController.test.ts
@@ -562,9 +562,11 @@ describe("hasWorkspaceCheckpointForMessage", () => {
const readLiveMessages = vi.fn().mockResolvedValue(sdkMessages)
const readMessages = vi.fn().mockResolvedValue(sdkMessages.slice(0, 2))
const restore = vi.fn().mockRejectedValue(new Error("stop at restore"))
- const controller = {
+ // The prototype supplies the private implementation the public method delegates to.
+ const controller = Object.assign(Object.create(SdkController.prototype), {
task: { taskId: "task-a", messageStateHandler: { getClineMessages: () => messages } },
sessions: {
+ trackSessionStart: (operation: () => Promise) => operation(),
getActiveSession: () => ({
sessionId: "task-a",
isRunning: false,
@@ -584,7 +586,7 @@ describe("hasWorkspaceCheckpointForMessage", () => {
stateManager: { getGlobalSettingsKey: () => "act" },
sessionConfigBuilder: { build: async () => ({ providerId: "anthropic", apiKey: "key", modelId: "model" }) },
resolveContextMentions: async (text: string) => text,
- }
+ })
await expect(SdkController.prototype.hasWorkspaceCheckpointForMessage.call(controller as never, 3)).resolves.toBe(true)
await expect(
@@ -598,6 +600,68 @@ describe("hasWorkspaceCheckpointForMessage", () => {
expect(readMessages).not.toHaveBeenCalled()
})
+ it("runs message edits and checkpoint restores inside a tracked session start", async () => {
+ // Both read the mode setting and swap the session outside the rebuild
+ // lock, so a mode toggle must be able to wait for them to finish.
+ let tracking = false
+ const trackedRestores: boolean[] = []
+ const restore = vi.fn(async () => {
+ trackedRestores.push(tracking)
+ throw new Error("stop at restore")
+ })
+ const restoreActiveSession = vi.fn(async () => {
+ trackedRestores.push(tracking)
+ return {}
+ })
+ const controller = Object.assign(Object.create(SdkController.prototype), {
+ task: { taskId: "task-a", messageStateHandler: { getClineMessages: () => messages } },
+ sessions: {
+ trackSessionStart: async (operation: () => Promise) => {
+ tracking = true
+ try {
+ return await operation()
+ } finally {
+ tracking = false
+ }
+ },
+ restoreActiveSession,
+ getActiveSession: () => ({
+ sessionId: "task-a",
+ isRunning: false,
+ sdkHost: {
+ get: async () => ({
+ cwd: "C:/work",
+ metadata: { checkpoint: { history: [{ ref: "checkpoint-b", createdAt: 1, runCount: 2 }] } },
+ }),
+ readLiveMessages: vi.fn().mockResolvedValue(sdkMessages),
+ readMessages: vi.fn().mockResolvedValue(sdkMessages),
+ restore,
+ },
+ }),
+ },
+ taskHistory: { findHistoryItem: async () => undefined },
+ getWorkspaceRoot: async () => "C:/work",
+ stateManager: { getGlobalSettingsKey: () => "act" },
+ sessionConfigBuilder: { build: async () => ({ providerId: "anthropic", apiKey: "key", modelId: "model" }) },
+ resolveContextMentions: async (text: string) => text,
+ postStateToWebview: async () => undefined,
+ })
+
+ await expect(
+ SdkController.prototype.editMessageAndRegenerate.call(controller as never, {
+ messageTs: 3,
+ text: "continue, edited",
+ restoreWorkspace: true,
+ }),
+ ).rejects.toThrow("stop at restore")
+ await SdkController.prototype.restoreCheckpoint.call(controller as never, {
+ checkpointRunCount: 2,
+ restoreType: "workspace",
+ })
+
+ expect(trackedRestores).toEqual([true, true])
+ })
+
it("uses and disposes a temporary host for a history task", async () => {
const tempHost = {
get: vi.fn().mockResolvedValue({
@@ -799,11 +863,16 @@ describe("cloud tasks stay in the cloud", () => {
it("refuses to rebuild a cloud task's conversation as a local session", async () => {
const startNewSession = vi.fn()
- const controller = {
+ // The prototype supplies the private implementation the public method delegates to.
+ const controller = Object.assign(Object.create(SdkController.prototype), {
task: { taskId: "ses-cloud", messageStateHandler: { getClineMessages: () => [] } },
- sessions: { getActiveSession: () => undefined, startNewSession },
+ sessions: {
+ getActiveSession: () => undefined,
+ startNewSession,
+ trackSessionStart: (operation: () => Promise) => operation(),
+ },
stateManager,
- }
+ })
await expect(
SdkController.prototype.editMessageAndRegenerate.call(controller as never, { messageTs: 1, text: "edited" }),
diff --git a/apps/vscode/src/sdk/SdkController.ts b/apps/vscode/src/sdk/SdkController.ts
index c58dafa751..faf337929b 100644
--- a/apps/vscode/src/sdk/SdkController.ts
+++ b/apps/vscode/src/sdk/SdkController.ts
@@ -1764,6 +1764,18 @@ export class Controller {
images?: string[]
files?: string[]
restoreWorkspace?: boolean
+ }): Promise {
+ // Reads the mode setting and replaces the session outside the rebuild
+ // lock; tracking it makes a concurrent mode toggle wait for the result.
+ await this.sessions.trackSessionStart(() => this.performEditMessageAndRegenerate(input))
+ }
+
+ private async performEditMessageAndRegenerate(input: {
+ messageTs: number
+ text: string
+ images?: string[]
+ files?: string[]
+ restoreWorkspace?: boolean
}): Promise {
const editedText = input.text.trim()
if (!editedText && (input.images?.length ?? 0) === 0 && (input.files?.length ?? 0) === 0) {
@@ -1918,6 +1930,15 @@ export class Controller {
}
async restoreCheckpoint(input: { checkpointRunCount: number; restoreType: ClineCheckpointRestore }): Promise {
+ // Reads the mode setting and swaps the session outside the rebuild lock;
+ // tracking it makes a concurrent mode toggle wait for the result.
+ await this.sessions.trackSessionStart(() => this.performRestoreCheckpoint(input))
+ }
+
+ private async performRestoreCheckpoint(input: {
+ checkpointRunCount: number
+ restoreType: ClineCheckpointRestore
+ }): Promise {
const restoreMessages = input.restoreType === "task" || input.restoreType === "taskAndWorkspace"
const restoreWorkspace = input.restoreType === "workspace" || input.restoreType === "taskAndWorkspace"
const checkpointRunCount = Number(input.checkpointRunCount)
diff --git a/apps/vscode/src/sdk/cline-session-factory.ts b/apps/vscode/src/sdk/cline-session-factory.ts
index 126d001ed3..5645f114ab 100644
--- a/apps/vscode/src/sdk/cline-session-factory.ts
+++ b/apps/vscode/src/sdk/cline-session-factory.ts
@@ -90,6 +90,12 @@ export interface ActiveSession {
sessionId: string
/** The config used to start the active session. */
startConfig?: Pick
+ /**
+ * The mode the session's tools were built for. It can differ from the
+ * persisted mode setting while a start or rebuild is in flight, so mode
+ * switches compare against this rather than the setting.
+ */
+ mode?: Mode
/** The runtime host instance managing this session (VscodeSessionHost) */
sdkHost: SdkSessionHost
/** Unsubscribe function for session events */
diff --git a/apps/vscode/src/sdk/sdk-mode-coordinator.test.ts b/apps/vscode/src/sdk/sdk-mode-coordinator.test.ts
index 9a22b8fdf1..b8ce40bec0 100644
--- a/apps/vscode/src/sdk/sdk-mode-coordinator.test.ts
+++ b/apps/vscode/src/sdk/sdk-mode-coordinator.test.ts
@@ -2,6 +2,7 @@ import type { ClineMessage } from "@shared/ExtensionMessage"
import { beforeEach, describe, expect, it, vi } from "vitest"
import type { StateManager } from "@/core/storage/StateManager"
import { SdkModeCoordinator, type SdkModeCoordinatorOptions } from "./sdk-mode-coordinator"
+import { SdkSessionRebuildScheduler } from "./sdk-session-rebuild-scheduler"
vi.mock("@/shared/services/Logger", () => ({
Logger: {
@@ -21,6 +22,102 @@ describe("SdkModeCoordinator", () => {
vi.clearAllMocks()
})
+ describe("toggles racing a session start", () => {
+ it("applies a toggle made while an earlier switch is still replacing the session", async () => {
+ const { coordinator, options, state } = makeCoordinator({
+ activeSession: makeActiveSession({ mode: "act" }),
+ task: makeTask("old-session"),
+ mode: "act",
+ serializeRebuilds: true,
+ })
+ let current: ActiveSessionFixture | undefined = makeActiveSession({ mode: "act" })
+ options.sessions.getActiveSession.mockImplementation(() => current)
+ let finishPlanStart!: () => void
+ const planStart = new Promise((resolve) => {
+ finishPlanStart = resolve
+ })
+ options.sessions.replaceActiveSession
+ .mockImplementationOnce(async () => {
+ // The outgoing session is detached before its replacement starts,
+ // so no session is active until the plan session is up.
+ current = undefined
+ await planStart
+ current = makeActiveSession({ mode: "plan" })
+ return { startResult: { sessionId: "old-session" }, sdkHost: current.sdkHost }
+ })
+ .mockImplementationOnce(async () => {
+ current = makeActiveSession({ mode: "act" })
+ return { startResult: { sessionId: "old-session" }, sdkHost: current.sdkHost }
+ })
+
+ const toPlan = coordinator.togglePlanActMode("plan")
+ await vi.waitFor(() => expect(options.sessions.replaceActiveSession).toHaveBeenCalledOnce())
+ const toAct = coordinator.togglePlanActMode("act")
+ finishPlanStart()
+ await Promise.all([toPlan, toAct])
+
+ expect(state.mode).toBe("act")
+ expect(options.buildStartSessionInput.mock.calls.map(([, startInput]) => startInput.mode)).toEqual(["plan", "act"])
+ expect(current?.mode).toBe("act")
+ // act -> plan -> act before any message was sent cancels out.
+ expect(coordinator.consumeModeSwitchNotice("old-session")).toBeNull()
+ })
+
+ it("applies a toggle made while a new task's session is still starting", async () => {
+ const { coordinator, options, state } = makeCoordinator({ mode: "plan", task: makeTask("new-task") })
+ const planSession = makeActiveSession({ mode: "plan", isRunning: true })
+ let current: ActiveSessionFixture | undefined
+ options.sessions.getActiveSession.mockImplementation(() => current)
+ options.sessions.waitForSessionStarts.mockImplementationOnce(async () => {
+ // The task's plan session finishes starting and its first turn runs.
+ current = planSession
+ })
+
+ await coordinator.togglePlanActMode("act")
+
+ expect(state.mode).toBe("act")
+ expect(planSession.sdkHost.abort).toHaveBeenCalledWith("old-session")
+ expect(options.sessions.replaceActiveSession).toHaveBeenCalledWith(
+ expect.objectContaining({ expectedSession: planSession }),
+ )
+ expect(options.buildStartSessionInput).toHaveBeenCalledWith(expect.anything(), { cwd: "/workspace", mode: "act" })
+ expect(coordinator.consumeModeSwitchNotice("new-session")).toEqual({ from: "plan", to: "act" })
+ })
+
+ it("rebuilds when the setting already matches but the session was built for the other mode", async () => {
+ const planSession = makeActiveSession({ mode: "plan" })
+ const { coordinator, options, state } = makeCoordinator({
+ activeSession: planSession,
+ task: makeTask("old-session"),
+ mode: "act",
+ })
+
+ await coordinator.togglePlanActMode("act")
+
+ expect(state.mode).toBe("act")
+ expect(options.sessions.replaceActiveSession).toHaveBeenCalledWith(
+ expect.objectContaining({ expectedSession: planSession }),
+ )
+ expect(options.buildStartSessionInput).toHaveBeenCalledWith(expect.anything(), { cwd: "/workspace", mode: "act" })
+ expect(coordinator.consumeModeSwitchNotice("new-session")).toEqual({ from: "plan", to: "act" })
+ })
+
+ it("does not rebuild or announce a switch to the mode the session already runs in", async () => {
+ const { coordinator, options, state } = makeCoordinator({
+ activeSession: makeActiveSession({ mode: "plan" }),
+ task: makeTask("old-session"),
+ mode: "act",
+ })
+
+ await expect(coordinator.togglePlanActMode("plan")).resolves.toBe(false)
+
+ expect(state.mode).toBe("plan")
+ expect(options.sessions.replaceActiveSession).not.toHaveBeenCalled()
+ expect(options.postStateToWebview).toHaveBeenCalledOnce()
+ expect(coordinator.consumeModeSwitchNotice("old-session")).toBeNull()
+ })
+ })
+
it("preserves pending input by returning false when toggling mode without an active session", async () => {
const { coordinator, state, options } = makeCoordinator({ mode: "act" })
@@ -798,6 +895,7 @@ function makeCoordinator(input: Partial = {}) {
}),
fireAndForgetSend: vi.fn(),
setRunning: vi.fn(),
+ waitForSessionStarts: vi.fn().mockResolvedValue(undefined),
},
interactions: {
clearPending: vi.fn(),
@@ -836,6 +934,7 @@ function makeCoordinator(input: Partial = {}) {
fireAndForgetSend: ReturnType
replaceActiveSession: ReturnType
setRunning: ReturnType
+ waitForSessionStarts: ReturnType
}
interactions: SdkModeCoordinatorOptions["interactions"] & {
clearPending: ReturnType
@@ -863,6 +962,10 @@ function makeCoordinator(input: Partial = {}) {
onAutoContinueFailed: ReturnType
}
+ if (input.serializeRebuilds) {
+ options.rebuilds = new SdkSessionRebuildScheduler({ sessions: options.sessions })
+ }
+
return {
coordinator: new SdkModeCoordinator(options),
options,
@@ -880,11 +983,16 @@ interface MakeCoordinatorInput {
}
task: ReturnType
turnPhase: string
+ /** Use the real rebuild lock instead of a pass-through. */
+ serializeRebuilds: boolean
}
-function makeActiveSession(input: { isRunning?: boolean } = {}) {
+type ActiveSessionFixture = ReturnType
+
+function makeActiveSession(input: { isRunning?: boolean; mode?: "act" | "plan" } = {}) {
return {
sessionId: "old-session",
+ mode: input.mode,
sdkHost: {
abort: vi.fn().mockResolvedValue(undefined),
send: vi.fn(),
@@ -894,6 +1002,7 @@ function makeActiveSession(input: { isRunning?: boolean } = {}) {
unsubscribe: vi.fn(),
startResult: { sessionId: "old-session" },
isRunning: input.isRunning ?? false,
+ queuedPromptCount: 0,
}
}
diff --git a/apps/vscode/src/sdk/sdk-mode-coordinator.ts b/apps/vscode/src/sdk/sdk-mode-coordinator.ts
index 3a81ef3752..e849a627a1 100644
--- a/apps/vscode/src/sdk/sdk-mode-coordinator.ts
+++ b/apps/vscode/src/sdk/sdk-mode-coordinator.ts
@@ -111,17 +111,29 @@ export class SdkModeCoordinator {
}
async togglePlanActMode(modeToSwitchTo: Mode, chatContent?: ChatContent): Promise {
- const currentMode = this.options.stateManager.getGlobalSettingsKey("mode")
- if (currentMode === modeToSwitchTo) {
- return false
- }
+ // Decide under the rebuild lock, after any session start in flight has
+ // settled. Starts and rebuilds detach the outgoing session before the
+ // replacement is active, so a toggle that looked during that window
+ // would see no session, flip only the setting, and leave the session
+ // that finishes starting on the other mode's tools.
+ return this.options.rebuilds.runExclusive(async () => {
+ await this.options.sessions.waitForSessionStarts()
+ return this.performTogglePlanActMode(modeToSwitchTo, chatContent)
+ })
+ }
+ private async performTogglePlanActMode(modeToSwitchTo: Mode, chatContent?: ChatContent): Promise {
+ const currentMode = this.options.stateManager.getGlobalSettingsKey("mode")
const activeSession = this.options.sessions.getActiveSession()
// Cloud sessions are Act-only; the webview disables the toggle, this
// guards the keyboard shortcut and any other caller.
if (activeSession?.sdkHost && "isCloud" in activeSession.sdkHost) {
return false
}
+ if (currentMode === modeToSwitchTo && (activeSession?.mode ?? modeToSwitchTo) === modeToSwitchTo) {
+ return false
+ }
+
if (activeSession) {
// awaiting_followup is also used for non-plan turns, so it is not
// sufficient evidence that the user has a plan to approve. Require the
@@ -150,7 +162,7 @@ export class SdkModeCoordinator {
const userImages = chatContent?.images?.length ? chatContent.images : undefined
const userFiles = chatContent?.files?.length ? chatContent.files : undefined
const hasUserContent = !!(userPrompt || userImages || userFiles)
- const continuationSent = await this.rebuildSessionForMode(modeToSwitchTo, {
+ const continuationSent = await this.performRebuildSessionForMode(modeToSwitchTo, {
autoContinue,
userContinuationPrompt: autoContinue ? userPrompt : undefined,
userImages: autoContinue ? userImages : undefined,
@@ -191,14 +203,22 @@ export class SdkModeCoordinator {
userFiles?: string[]
},
): Promise {
- const previousMode = this.options.stateManager.getGlobalSettingsKey("mode")
+ const activeSession = this.options.sessions.getActiveSession()
+ // The mode the model is actually running under. Rolling back to it keeps
+ // the toggle coherent with the session's tools, and it is the "from" side
+ // of the mode notice.
+ const previousMode = activeSession?.mode ?? this.options.stateManager.getGlobalSettingsKey("mode")
this.options.stateManager.setGlobalState("mode", newMode)
- const activeSession = this.options.sessions.getActiveSession()
if (!activeSession) {
await this.options.postStateToWebview()
return false
}
+ if (activeSession.mode === newMode) {
+ // Only the setting had drifted; the session already has this mode's tools.
+ await this.options.postStateToWebview()
+ return false
+ }
const { sdkHost: oldManager, sessionId: oldSessionId } = activeSession
const wasRunning = activeSession.isRunning
diff --git a/apps/vscode/src/sdk/sdk-session-lifecycle.test.ts b/apps/vscode/src/sdk/sdk-session-lifecycle.test.ts
index 43bcca6aed..b3c51df89b 100644
--- a/apps/vscode/src/sdk/sdk-session-lifecycle.test.ts
+++ b/apps/vscode/src/sdk/sdk-session-lifecycle.test.ts
@@ -53,6 +53,56 @@ describe("SdkSessionLifecycle", () => {
expect(lifecycle.getActiveSession()).toBeUndefined()
})
+ it("records the mode the active session was built for", async () => {
+ const sdkHost = makeSdkHost({ startResult: { sessionId: "session-123" } })
+ mockCreateSessionHost.mockResolvedValueOnce(sdkHost)
+ const lifecycle = makeLifecycle()
+
+ await lifecycle.startNewSession({
+ config: { providerId: "anthropic", modelId: "claude-sonnet-4", mode: "plan" },
+ } as StartInput)
+
+ expect(lifecycle.getActiveSession()?.mode).toBe("plan")
+ })
+
+ it("waits for tracked session starts, including ones that fail", async () => {
+ const lifecycle = makeLifecycle()
+ let finishStart!: () => void
+ const start = lifecycle.trackSessionStart(
+ () =>
+ new Promise((resolve) => {
+ finishStart = resolve
+ }),
+ )
+ let waited = false
+ const waiting = lifecycle.waitForSessionStarts().then(() => {
+ waited = true
+ })
+
+ await new Promise((resolve) => setTimeout(resolve, 0))
+ expect(waited).toBe(false)
+
+ finishStart()
+ await start
+ await waiting
+ expect(waited).toBe(true)
+
+ // A waiter already in place when a start fails is released, not rejected:
+ // a mode toggle waiting on a failed new-task start must still go ahead.
+ let failStart!: (error: Error) => void
+ const failing = lifecycle.trackSessionStart(
+ () =>
+ new Promise((_resolve, reject) => {
+ failStart = reject
+ }),
+ )
+ const waitingOnFailure = lifecycle.waitForSessionStarts()
+ failStart(new Error("start failed"))
+ await expect(failing).rejects.toThrow("start failed")
+ await expect(waitingOnFailure).resolves.toBeUndefined()
+ await expect(lifecycle.waitForSessionStarts()).resolves.toBeUndefined()
+ })
+
it("stores the provider and model config used to start the active session", async () => {
const sdkHost = makeSdkHost({ startResult: { sessionId: "session-123" } })
mockCreateSessionHost.mockResolvedValueOnce(sdkHost)
diff --git a/apps/vscode/src/sdk/sdk-session-lifecycle.ts b/apps/vscode/src/sdk/sdk-session-lifecycle.ts
index 5ce21c68c0..33a3146b7f 100644
--- a/apps/vscode/src/sdk/sdk-session-lifecycle.ts
+++ b/apps/vscode/src/sdk/sdk-session-lifecycle.ts
@@ -7,6 +7,7 @@ import type {
StartSessionResult,
} from "@cline/core"
import { formatModeSwitchNotice, type ModeSwitchNotice } from "@cline/shared"
+import type { Mode } from "@shared/storage/types"
import { StateManager } from "@/core/storage/StateManager"
import type { VscodeTerminalManager } from "@/hosts/vscode/terminal/VscodeTerminalManager"
import { McpHub } from "@/services/mcp/McpHub"
@@ -57,6 +58,10 @@ export interface SdkSessionLifecycleOptions {
onDidBecomeIdle?: () => void
}
+function toSessionMode(mode: string | undefined): Mode | undefined {
+ return mode === "plan" || mode === "act" ? mode : undefined
+}
+
export class SdkSessionLifecycle {
private activeSession: ActiveSession | undefined
private sharedHost: SdkSessionHost | undefined
@@ -77,9 +82,41 @@ export class SdkSessionLifecycle {
* session idle, or a passive rebuild could replace it mid-turn.
*/
private turnGeneration = 0
+ /**
+ * Session starts that read the mode setting outside the rebuild lock (new
+ * task, edited message, checkpoint restore). Until one settles, the session
+ * it is building is not active yet, so a mode toggle waits for it instead
+ * of mistaking "no active session" for "nothing to rebuild".
+ */
+ private readonly pendingStarts = new Set>()
constructor(private readonly options: SdkSessionLifecycleOptions) {}
+ /**
+ * Runs a session start, from reading the mode setting until the new
+ * session is active and its first turn is sent, as one tracked unit.
+ */
+ async trackSessionStart(operation: () => Promise): Promise {
+ const run = operation()
+ const settled = run.then(
+ () => undefined,
+ () => undefined,
+ )
+ this.pendingStarts.add(settled)
+ try {
+ return await run
+ } finally {
+ this.pendingStarts.delete(settled)
+ }
+ }
+
+ /** Resolves once no tracked session start is in flight. */
+ async waitForSessionStarts(): Promise {
+ while (this.pendingStarts.size > 0) {
+ await Promise.all(this.pendingStarts)
+ }
+ }
+
getActiveSession(): ActiveSession | undefined {
return this.activeSession
}
@@ -214,6 +251,7 @@ export class SdkSessionLifecycle {
modelId: startInput.config.modelId,
}
: undefined,
+ mode: toSessionMode(startInput.config?.mode),
sdkHost,
unsubscribe: hostOverride ? this.subscribeSessionHost(hostOverride) : () => {},
startResult,
@@ -322,6 +360,7 @@ export class SdkSessionLifecycle {
modelId: input.start.config.modelId,
}
: activeSession.startConfig,
+ mode: toSessionMode(input.start?.config?.mode) ?? activeSession.mode,
startResult: restored.startResult,
isRunning: false,
queuedPromptCount: 0,
diff --git a/apps/vscode/src/sdk/sdk-task-start-coordinator.test.ts b/apps/vscode/src/sdk/sdk-task-start-coordinator.test.ts
index 280861a961..b22f533054 100644
--- a/apps/vscode/src/sdk/sdk-task-start-coordinator.test.ts
+++ b/apps/vscode/src/sdk/sdk-task-start-coordinator.test.ts
@@ -23,6 +23,37 @@ describe("SdkTaskStartCoordinator", () => {
vi.mocked(isDirectory).mockResolvedValue(false)
})
+ it("starts the session and sends the first prompt inside one tracked session start", async () => {
+ const { coordinator, options } = makeCoordinator()
+ let tracking = false
+ options.sessions.trackSessionStart.mockImplementation(async (operation: () => Promise) => {
+ tracking = true
+ try {
+ return await operation()
+ } finally {
+ tracking = false
+ }
+ })
+ const trackedCalls: string[] = []
+ options.sessionConfigBuilder.build.mockImplementation(async () => {
+ trackedCalls.push(`build:${tracking}`)
+ return { providerId: "anthropic", modelId: "model", apiKey: "key" }
+ })
+ options.sessions.startNewSession.mockImplementation((startInput?: { config?: { sessionId?: string } }) => {
+ trackedCalls.push(`start:${tracking}`)
+ return { startResult: { sessionId: startInput?.config?.sessionId ?? "session-123" }, sdkHost: { send: vi.fn() } }
+ })
+ options.sessions.fireAndForgetSend.mockImplementation(() => {
+ trackedCalls.push(`send:${tracking}`)
+ })
+
+ await coordinator.initTask("hello")
+
+ // The mode is read when the config is built, so a toggle has to wait from
+ // there until the session is active and its first turn is on its way.
+ expect(trackedCalls).toEqual(["build:true", "start:true", "send:true"])
+ })
+
it("initializes a new task, emits the task message, and sends the resolved prompt", async () => {
const { coordinator, options, state } = makeCoordinator()
@@ -269,6 +300,7 @@ function makeCoordinator(input: Partial = {}) {
sdkHost,
})),
fireAndForgetSend: vi.fn(),
+ trackSessionStart: vi.fn((operation: () => Promise) => operation()),
},
messages: {
appendAndEmit: vi.fn(),
@@ -315,6 +347,7 @@ function makeCoordinator(input: Partial = {}) {
sessions: SdkTaskStartCoordinatorOptions["sessions"] & {
startNewSession: ReturnType
fireAndForgetSend: ReturnType
+ trackSessionStart: ReturnType
}
messages: SdkTaskStartCoordinatorOptions["messages"] & {
appendAndEmit: ReturnType
diff --git a/apps/vscode/src/sdk/sdk-task-start-coordinator.ts b/apps/vscode/src/sdk/sdk-task-start-coordinator.ts
index e88ad1ca91..adae1e7557 100644
--- a/apps/vscode/src/sdk/sdk-task-start-coordinator.ts
+++ b/apps/vscode/src/sdk/sdk-task-start-coordinator.ts
@@ -75,88 +75,92 @@ export class SdkTaskStartCoordinator {
try {
await this.options.clearTask()
- const cwd = await this.options.getWorkspaceRoot()
- const mode = this.getCurrentMode()
- Logger.log(`[SdkController] Building session config: mode=${mode}, cwd=${cwd}`)
- const config = await this.options.sessionConfigBuilder.build({
- prompt,
- images,
- files,
- historyItem,
- taskSettings,
- cwd,
- mode,
- })
- providerId = config.providerId
- modelId = config.modelId
+ // Tracked from the mode read until the first prompt is sent, so a mode
+ // toggle in between waits for this session instead of missing it.
+ return await this.options.sessions.trackSessionStart(async () => {
+ const cwd = await this.options.getWorkspaceRoot()
+ const mode = this.getCurrentMode()
+ Logger.log(`[SdkController] Building session config: mode=${mode}, cwd=${cwd}`)
+ const config = await this.options.sessionConfigBuilder.build({
+ prompt,
+ images,
+ files,
+ historyItem,
+ taskSettings,
+ cwd,
+ mode,
+ })
+ providerId = config.providerId
+ modelId = config.modelId
- Logger.log(
- `[SdkController] Session config: provider=${config.providerId}, model=${config.modelId}, hasApiKey=${!!config.apiKey}`,
- )
-
- if (usesClineAccountAuth(config.providerId) && !config.apiKey) {
- Logger.warn(
- `[SdkController] ${config.providerId} provider selected but no Cline auth token — emitting auth error`,
+ Logger.log(
+ `[SdkController] Session config: provider=${config.providerId}, model=${config.modelId}, hasApiKey=${!!config.apiKey}`,
)
- // No task/session id exists yet, so this preflight auth UI path is
- // intentionally not recorded as task-joinable provider error telemetry.
- this.options.emitClineAuthError(prompt)
- return undefined
- }
- taskSessionId = config.sessionId?.trim() || createSessionId()
- const configWithSessionId = {
- ...config,
- sessionId: taskSessionId,
- }
+ if (usesClineAccountAuth(config.providerId) && !config.apiKey) {
+ Logger.warn(
+ `[SdkController] ${config.providerId} provider selected but no Cline auth token — emitting auth error`,
+ )
+ // No task/session id exists yet, so this preflight auth UI path is
+ // intentionally not recorded as task-joinable provider error telemetry.
+ this.options.emitClineAuthError(prompt)
+ return undefined
+ }
- const startInput = this.options.buildStartSessionInput(configWithSessionId, {
- prompt: prompt,
- images,
- files,
- historyItem,
- taskSettings,
- cwd,
- mode,
- })
+ taskSessionId = config.sessionId?.trim() || createSessionId()
+ const configWithSessionId = {
+ ...config,
+ sessionId: taskSessionId,
+ }
- const task = this.createAndSetTask(taskSessionId)
- this.emitInitialTaskMessage(taskSessionId, prompt ?? "", images, files)
+ const startInput = this.options.buildStartSessionInput(configWithSessionId, {
+ prompt: prompt,
+ images,
+ files,
+ historyItem,
+ taskSettings,
+ cwd,
+ mode,
+ })
- // The turn phase was already set to "streaming" (in SdkController.initTask), but the
- // webview only learns the phase through a full state post. Ship one now, in parallel
- // with the potentially slow session startup below, so the chat shows the thinking
- // indicator as soon as the task message lands instead of after startNewSession settles.
- this.options.postStateToWebview().catch((error) => {
- Logger.error("[SdkController] Failed to post state after emitting initial task message:", error)
- })
+ const task = this.createAndSetTask(taskSessionId)
+ this.emitInitialTaskMessage(taskSessionId, prompt ?? "", images, files)
- const { startResult, sdkHost } = await this.options.sessions.startNewSession(startInput)
- if (startResult.sessionId !== taskSessionId) {
- Logger.warn(
- `[SdkController] SDK returned session id ${startResult.sessionId} after requested id ${taskSessionId}`,
+ // The turn phase was already set to "streaming" (in SdkController.initTask), but the
+ // webview only learns the phase through a full state post. Ship one now, in parallel
+ // with the potentially slow session startup below, so the chat shows the thinking
+ // indicator as soon as the task message lands instead of after startNewSession settles.
+ this.options.postStateToWebview().catch((error) => {
+ Logger.error("[SdkController] Failed to post state after emitting initial task message:", error)
+ })
+
+ const { startResult, sdkHost } = await this.options.sessions.startNewSession(startInput)
+ if (startResult.sessionId !== taskSessionId) {
+ Logger.warn(
+ `[SdkController] SDK returned session id ${startResult.sessionId} after requested id ${taskSessionId}`,
+ )
+ task.taskId = startResult.sessionId
+ taskSessionId = startResult.sessionId
+ }
+
+ const newHistoryItem = this.options.createHistoryItemFromSession(
+ taskSessionId,
+ prompt ?? "",
+ configWithSessionId.modelId,
+ cwd,
)
- task.taskId = startResult.sessionId
- taskSessionId = startResult.sessionId
- }
+ await this.options.taskHistory.updateTaskHistoryItem(newHistoryItem)
+ await this.options.postStateToWebview()
- const newHistoryItem = this.options.createHistoryItemFromSession(
- taskSessionId,
- prompt ?? "",
- configWithSessionId.modelId,
- cwd,
- )
- await this.options.taskHistory.updateTaskHistoryItem(newHistoryItem)
- await this.options.postStateToWebview()
+ if (prompt?.trim() || images?.length || files?.length) {
+ Logger.log(`[SdkController] Sending prompt to session: ${taskSessionId}`)
+ const resolvedTask = await this.options.resolveContextMentions(prompt || "")
+ this.options.sessions.fireAndForgetSend(sdkHost, taskSessionId, resolvedTask, images, files)
+ }
- if (prompt?.trim() || images?.length || files?.length) {
- Logger.log(`[SdkController] Sending prompt to session: ${taskSessionId}`)
- const resolvedTask = await this.options.resolveContextMentions(prompt || "")
- this.options.sessions.fireAndForgetSend(sdkHost, taskSessionId, resolvedTask, images, files)
- }
-
- Logger.log(`[SdkController] Task initialized: ${taskSessionId}`)
- return taskSessionId
+ Logger.log(`[SdkController] Task initialized: ${taskSessionId}`)
+ return taskSessionId
+ })
} catch (error) {
this.options.captureProviderApiError?.({
sessionId: taskSessionId,
From 41e75efc53e7abbcb76564b89e6de57f78659b33 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Miko=C5=82aj=20Kondratek?=
<19799111+mkondratek@users.noreply.github.com>
Date: Mon, 19 Oct 2026 15:08:19 +0200
Subject: [PATCH 29/29] fix(vscode): honor disabled rule toggles in SDK
sessions (#14605)
* fix(vscode): persist rule toggle state for SDK loader
* fix(vscode): confine rule toggle frontmatter writes and preserve authored YAML
- Only write rule documents the SDK loader actually reads (.md, .markdown,
.txt, or the bare .clinerules file) that resolve, through symlinks, to a
regular file inside the scope's rules root (global Rules dir or the
workspace .clinerules). Anything else keeps the extension-state toggle only.
- Edit the top-level `disabled` entry line by line instead of re-dumping the
YAML block, so comments, key order, quoting, CRLF line endings and a UTF-8
BOM survive a toggle. Re-parse before writing and leave the file untouched
if the result would not parse. Skills share the helper and get the same.
- Reconcile extension state with frontmatter on rules refresh: toggles turned
off before this fix are written to the file so SDK sessions honor them, and
a file disabled by hand wins over a stale enabled toggle.
* fix(vscode): write rule toggles into every rule root the panel scans
Rebase adjustment: since the rules panel now scans both .clinerules and
.cline/rules plus every global location the shared resolver knows, the
frontmatter write and the state<->frontmatter reconcile take the same
directory lists instead of the two hardcoded roots.
* fix(vscode): make rule files authoritative for toggles after a one-time back-fill
- Match the SDK's disabled precedence: a boolean `disabled` wins, `enabled:
false` only counts when `disabled` is absent.
- Recognize quoted frontmatter keys when editing the disabled line.
- Return written/skipped/failed from the frontmatter write; on failure the
toggle handler reverts the state toggle and returns the reverted map so the
panel keeps showing what the SDK loads.
- Back-fill state toggles into frontmatter once, behind a new global state
flag; afterwards the file is the source of truth for the panel in both
directions, so removing `disabled` from a file re-enables the rule.
- Only write files the SDK loader reads: direct children of a rule root, or
the single legacy .clinerules file.
* fix(vscode): back-fill rule toggles per workspace and accept uppercase YAML booleans
- The one-time back-fill marker is now keyed per scope (global, and one entry
per workspace path), so a workspace opened after another one was migrated
still gets its pre-fix off toggles written into its rule files instead of
having them flipped on by the file-wins reconcile.
- The enabled: false matcher accepts False and FALSE, which both YAML parsers
in play read as boolean false, so re-enabling removes those lines too.
* fix(vscode): keep the workspace back-fill marker in workspace state
Each window holds its own copy of global state and the last writer wins per
key, so two windows migrating different workspaces could erase each other's
marker in the shared record. The global marker is a plain flag again and the
workspace marker moves to workspace state, keyed by workspace path, which is
per window and never shared.
* fix(vscode): report a rule toggle as failed when the file could not be edited safely
The frontmatter helper returns the document unchanged both when it already
carries the requested state and when it cannot be edited safely (malformed
YAML, or an edit that would not re-parse). The write wrapper treated both as
success, so the toggle handler kept the new state while the SDK kept loading
the old one. An unchanged document now counts as written only if it parses
and already matches the requested state; otherwise the handler reverts.
* fix(vscode): retry a failed rule back-fill and keep comments after inline disabled values
- A back-fill write that fails (read-only file, malformed frontmatter) keeps
the off toggle and leaves the scope's migration marker unset, so the next
refresh retries instead of treating the unwritten file as re-enabled.
- An entry with an inline scalar value is a single line, so an indented
comment after `disabled: true` is no longer removed with it.
* fix(vscode): track the rule back-fill per rule instead of per scope
A scope-wide migration marker forced a choice between two failure modes: mark
the scope done after a failed back-fill (the unwritten rule turns on), or keep
the whole scope pending (a rule the user re-enabled by hand gets back-filled
again). Each rule now records whether its file is authoritative. A rule joins
that set when state and file agree, when the file disables it, when its
back-fill succeeds, or when the toggle handler writes it; only a rule whose
back-fill failed stays pending and is retried on the next refresh. The global
set lives in global state and the workspace set in workspace state, replacing
the unreleased scope markers.
Also handle an inline disabled value that continues on later lines (a flow
collection or a split quoted string) by taking lines until the entry parses.
* fix(vscode): keep global rule authority records in their own settings file
Every window caches global state and persists its whole snapshot, so a window
that started before another one back-filled a global rule kept no record of
it. After the user re-enabled that rule by editing its file, refreshing the
stale window back-filled it again. The global records now live in
settings/cline-rules-frontmatter-authority.json, re-read on every refresh and
merged on every write, so windows only ever add to them. Records for deleted
rule files are dropped on write. Workspace records stay in workspace state,
which is a separate file per workspace.
* fix(vscode): make the rule file the only source of truth for rule toggles
Drop the one-time back-fill of toggles saved before the toggle wrote
frontmatter. Telling such a toggle apart from a rule the user re-enabled by
editing its file needs per-rule history, and every place to keep it
(scope flags, global state, workspace state, a settings file) failed across
multiple windows, crashes, or hand edits. The Rules panel now shows what the
frontmatter says on every refresh, and the toggle writes it. A rule switched
off before this fix shows as on after upgrading, which is what the SDK has
been loading, and is switched off once more.
Removes the per-rule authority records, the authority settings file, and the
localClineRulesFrontmatterAuthoritative workspace key. The multi-layout
refresh test now marks its disabled fixtures in frontmatter.
* fix(vscode): verify the requested state before reporting a toggle write
The rule and skill write paths trusted the frontmatter editor's output. An
edit that left a disabling flag the editor did not recognize (for example a
legacy `enabled: false` whose value is on the next line) was written and
reported as success, so the panel showed the rule or skill as on while the
SDK still excluded it. Both paths now re-parse the edited document and treat
anything not in the requested state as a failure, so the rule toggle handler
reverts and the skill write reports false without writing.
* fix(vscode): edit rule and skill frontmatter by YAML source range
The line-based editor guessed entry boundaries from line shapes. It missed a
legacy `enabled: false` whose value sits on the next line, matched
`disabled:` lines inside multi-line string values (changing unrelated
metadata while still producing valid YAML), and dropped comments on and
around the flag.
The editor now parses the frontmatter with the SDK loader's YAML parser and
splices only the source ranges of the top-level `disabled` and `enabled`
entries. Disabling sets an existing value or appends `disabled: true`.
Enabling removes those entries, or flips the value in place when the entry
carries a comment so the comment survives. Anything the SDK would reject
(invalid YAML, duplicate keys, non-boolean flags) is left untouched, and an
edit is discarded unless every other value is unchanged and the result is in
the requested state. The Rules panel reads state with the same parser.
Declares `yaml` (already a workspace dependency through @cline/core) as a
direct dependency of apps/vscode.
* test(vscode): mock @cline/core before it is loaded in the bun harness
The preload imported the real @cline/core to read its export names and then
mocked it. Mocking an already-loaded module makes bun re-link the graph, and
that re-link leaves a slice of @cline/shared's source-tree exports undefined
(stripUtf8Bom among them) for everything under sdk/packages/core, which
resolves @cline/shared to shared/src through core's tsconfig paths. Any real
SDK function the stub re-exports then threw when called from a test.
The export names now come from a child process, cached on the built package's
mtime, the mock is registered first, and the stub and @cline/llms are imported
after it.
* fix(vscode): let the SDK parser decide a rule's enabled state
The extension kept its own copy of the SDK's rules for reading a rule file's
enabled state, and every review round found a case where the copy and the
SDK disagreed: flag precedence, uppercase booleans, non-boolean values, and
now frontmatter that is not a mapping, which the SDK loads as having no
metadata but the copy treated as unloadable. A rule starting with a markdown
divider line could not be switched off.
The Rules panel, both write paths, and the editor now ask
parseRuleConfigFromMarkdown / parseSkillConfigFromMarkdown from @cline/core,
so they cannot disagree with what the SDK loads, now or after the SDK changes.
The editor still parses the block as a YAML document, but only to locate the
source ranges it edits. A file with non-mapping frontmatter is disabled by
adding a disabled: true block above it, and re-enabling restores it exactly.
A comment-only block gets the flag appended inside it.
A file the SDK does not load at all (unparseable frontmatter, non-boolean
flag, empty body) now shows as off in the panel, since nothing from it
reaches the model; switching it on fails and reverts, with the reason logged.
The bun test stub re-exports the two parsers from the SDK source.
---------
Co-authored-by: 33modeling <33modeling@gmail.com>
---
apps/vscode/package.json | 1 +
.../__tests__/cline-rules-toggles.test.ts | 7 +-
.../__tests__/cline-rules.test.ts | 229 ++++++++++++++++++
.../__tests__/frontmatter.test.ts | 220 ++++++++++++++++-
.../__tests__/skills.test.ts | 49 ++++
.../user-instructions/cline-rules.ts | 186 +++++++++++++-
.../user-instructions/frontmatter.ts | 208 +++++++++++++++-
.../instructions/user-instructions/skills.ts | 52 +---
.../file/__tests__/toggleClineRule.test.ts | 183 ++++++++++++++
.../core/controller/file/toggleClineRule.ts | 33 +++
apps/vscode/src/test/bun-test-preload.ts | 58 ++++-
.../vscode/src/test/cline-core-vitest-stub.ts | 4 +
bun.lock | 1 +
13 files changed, 1166 insertions(+), 65 deletions(-)
create mode 100644 apps/vscode/src/core/context/instructions/user-instructions/__tests__/cline-rules.test.ts
create mode 100644 apps/vscode/src/core/controller/file/__tests__/toggleClineRule.test.ts
diff --git a/apps/vscode/package.json b/apps/vscode/package.json
index 6a4ca4a708..f362ed93f2 100644
--- a/apps/vscode/package.json
+++ b/apps/vscode/package.json
@@ -548,6 +548,7 @@
"undici": "^7.29.0",
"uuid": "^11.1.0",
"vscode-uri": "^3.1.0",
+ "yaml": "^2.8.2",
"zod": "^4.3.6"
},
"c8": {
diff --git a/apps/vscode/src/core/context/instructions/user-instructions/__tests__/cline-rules-toggles.test.ts b/apps/vscode/src/core/context/instructions/user-instructions/__tests__/cline-rules-toggles.test.ts
index f19efde278..c929211186 100644
--- a/apps/vscode/src/core/context/instructions/user-instructions/__tests__/cline-rules-toggles.test.ts
+++ b/apps/vscode/src/core/context/instructions/user-instructions/__tests__/cline-rules-toggles.test.ts
@@ -19,6 +19,7 @@ function makeControllerStub(initial: {
const controller = {
stateManager: {
getGlobalSettingsKey: (key: string) => globalState.get(key) ?? {},
+ getGlobalStateKey: (key: string) => globalState.get(key),
getWorkspaceStateKey: (key: string) => workspaceState.get(key) ?? {},
setGlobalState: (key: string, value: unknown) => globalState.set(key, value),
setWorkspaceState: (key: string, value: unknown) => workspaceState.set(key, value),
@@ -75,8 +76,10 @@ describe("refreshClineRulesToggles workspace layouts", () => {
await fs.mkdir(clineRulesDir, { recursive: true })
const legacyRule = path.join(legacyDir, "a.md")
const newRule = path.join(clineRulesDir, "b.md")
- await fs.writeFile(legacyRule, "A")
- await fs.writeFile(newRule, "B")
+ // Disabled rules carry `disabled: true`, which is what the SDK loader
+ // and the panel read.
+ await fs.writeFile(legacyRule, "---\ndisabled: true\n---\nA")
+ await fs.writeFile(newRule, "---\ndisabled: true\n---\nB")
const controller = makeControllerStub({
localClineRulesToggles: {
diff --git a/apps/vscode/src/core/context/instructions/user-instructions/__tests__/cline-rules.test.ts b/apps/vscode/src/core/context/instructions/user-instructions/__tests__/cline-rules.test.ts
new file mode 100644
index 0000000000..3d1861f714
--- /dev/null
+++ b/apps/vscode/src/core/context/instructions/user-instructions/__tests__/cline-rules.test.ts
@@ -0,0 +1,229 @@
+import { afterEach, describe, it } from "bun:test"
+import { expect } from "chai"
+import fs from "fs/promises"
+import os from "os"
+import path from "path"
+import type { Controller } from "@/core/controller"
+import {
+ refreshClineRulesToggles,
+ resolveWritableRuleFile,
+ setRuleDisabledInFrontmatter,
+ syncRuleTogglesFromFrontmatter,
+} from "../cline-rules"
+import { parseYamlFrontmatter, readSdkEnabledState } from "../frontmatter"
+
+const temporaryDirectories: string[] = []
+
+async function makeTempDir(): Promise {
+ // realpath: on macOS os.tmpdir() is itself a symlink (/var -> /private/var).
+ const dir = await fs.realpath(await fs.mkdtemp(path.join(os.tmpdir(), "cline-rules-write-test-")))
+ temporaryDirectories.push(dir)
+ return dir
+}
+
+afterEach(async () => {
+ await Promise.all(temporaryDirectories.splice(0).map((dir) => fs.rm(dir, { recursive: true, force: true })))
+})
+
+describe("setRuleDisabledInFrontmatter", () => {
+ it("round-trips a rule document inside an allowed root", async () => {
+ const rulesDir = await makeTempDir()
+ const rulePath = path.join(rulesDir, "project-rule.md")
+ await fs.writeFile(rulePath, "Follow this rule")
+
+ expect(await setRuleDisabledInFrontmatter(rulePath, false, [rulesDir])).to.equal("written")
+ const disabled = parseYamlFrontmatter(await fs.readFile(rulePath, "utf-8"))
+ expect(disabled.data.disabled).to.equal(true)
+ expect(disabled.body).to.equal("Follow this rule")
+
+ expect(await setRuleDisabledInFrontmatter(rulePath, true, [rulesDir])).to.equal("written")
+ expect(await fs.readFile(rulePath, "utf-8")).to.equal("Follow this rule")
+ })
+
+ it("accepts the legacy single .clinerules file as its own root", async () => {
+ const workspace = await makeTempDir()
+ const rulePath = path.join(workspace, ".clinerules")
+ await fs.writeFile(rulePath, "Single-file rules")
+
+ expect(await setRuleDisabledInFrontmatter(rulePath, false, [rulePath])).to.equal("written")
+ expect(parseYamlFrontmatter(await fs.readFile(rulePath, "utf-8")).data.disabled).to.equal(true)
+ })
+
+ it("skips files the SDK loader does not read", async () => {
+ const rulesDir = await makeTempDir()
+ const jsonPath = path.join(rulesDir, "settings.json")
+ await fs.writeFile(jsonPath, '{"a":1}')
+
+ expect(await setRuleDisabledInFrontmatter(jsonPath, false, [rulesDir])).to.equal("skipped")
+ expect(await fs.readFile(jsonPath, "utf-8")).to.equal('{"a":1}')
+ })
+
+ it("skips paths outside the allowed roots, including through symlinks", async () => {
+ const rulesDir = await makeTempDir()
+ const elsewhere = await makeTempDir()
+ const targetPath = path.join(elsewhere, "not-a-rule.md")
+ await fs.writeFile(targetPath, "Do not touch")
+ const linkPath = path.join(rulesDir, "linked.md")
+ await fs.symlink(targetPath, linkPath)
+
+ expect(await setRuleDisabledInFrontmatter(targetPath, false, [rulesDir])).to.equal("skipped")
+ expect(await setRuleDisabledInFrontmatter(linkPath, false, [rulesDir])).to.equal("skipped")
+ expect(await resolveWritableRuleFile(linkPath, [rulesDir])).to.equal(null)
+ expect(await fs.readFile(targetPath, "utf-8")).to.equal("Do not touch")
+ })
+
+ it("skips files nested below a rules root, which the SDK loader never reads", async () => {
+ const rulesDir = await makeTempDir()
+ const nestedPath = path.join(rulesDir, "nested", "deep.md")
+ await fs.mkdir(path.dirname(nestedPath), { recursive: true })
+ await fs.writeFile(nestedPath, "Nested")
+
+ expect(await setRuleDisabledInFrontmatter(nestedPath, false, [rulesDir])).to.equal("skipped")
+ expect(await fs.readFile(nestedPath, "utf-8")).to.equal("Nested")
+ })
+
+ it("reports a failure when the rule file cannot be written", async () => {
+ const rulesDir = await makeTempDir()
+ const rulePath = path.join(rulesDir, "read-only.md")
+ await fs.writeFile(rulePath, "Locked rule")
+ await fs.chmod(rulePath, 0o444)
+ try {
+ expect(await setRuleDisabledInFrontmatter(rulePath, false, [rulesDir])).to.equal("failed")
+ expect(await fs.readFile(rulePath, "utf-8")).to.equal("Locked rule")
+ } finally {
+ await fs.chmod(rulePath, 0o644)
+ }
+ })
+
+ it("reports a failure when malformed frontmatter prevents a safe edit", async () => {
+ const rulesDir = await makeTempDir()
+ const rulePath = path.join(rulesDir, "broken.md")
+ const content = "---\npaths: [invalid\n---\nBody"
+ await fs.writeFile(rulePath, content)
+
+ expect(await setRuleDisabledInFrontmatter(rulePath, false, [rulesDir])).to.equal("failed")
+ expect(await fs.readFile(rulePath, "utf-8")).to.equal(content)
+ })
+
+ it("reports success without writing when the file already carries the requested state", async () => {
+ const rulesDir = await makeTempDir()
+ const rulePath = path.join(rulesDir, "already-off.md")
+ const content = "---\ndisabled: true\n---\nBody"
+ await fs.writeFile(rulePath, content)
+ const before = (await fs.stat(rulePath)).mtimeMs
+
+ expect(await setRuleDisabledInFrontmatter(rulePath, false, [rulesDir])).to.equal("written")
+ expect((await fs.stat(rulePath)).mtimeMs).to.equal(before)
+ })
+
+ it("rejects relative and missing paths", async () => {
+ const rulesDir = await makeTempDir()
+ expect(await setRuleDisabledInFrontmatter("relative.md", false, [rulesDir])).to.equal("skipped")
+ expect(await setRuleDisabledInFrontmatter(path.join(rulesDir, "missing.md"), false, [rulesDir])).to.equal("skipped")
+ })
+})
+
+describe("syncRuleTogglesFromFrontmatter", () => {
+ it("shows a toggle saved before the fix as on and leaves its file untouched", async () => {
+ const rulesDir = await makeTempDir()
+ const offPath = path.join(rulesDir, "off.md")
+ const onPath = path.join(rulesDir, "on.md")
+ await fs.writeFile(offPath, "Was toggled off in state only")
+ await fs.writeFile(onPath, "Still on")
+
+ const toggles = await syncRuleTogglesFromFrontmatter({ [offPath]: false, [onPath]: true }, [rulesDir])
+
+ expect(toggles).to.deep.equal({ [offPath]: true, [onPath]: true })
+ expect(await fs.readFile(offPath, "utf-8")).to.equal("Was toggled off in state only")
+ })
+
+ it("shows a rule as off when its frontmatter disables it", async () => {
+ const rulesDir = await makeTempDir()
+ const rulePath = path.join(rulesDir, "hand-edited.md")
+ const content = "---\ndisabled: true\n---\nDisabled by hand"
+ await fs.writeFile(rulePath, content)
+
+ const toggles = await syncRuleTogglesFromFrontmatter({ [rulePath]: true }, [rulesDir])
+
+ expect(toggles[rulePath]).to.equal(false)
+ expect(await fs.readFile(rulePath, "utf-8")).to.equal(content)
+ })
+
+ it("matches the SDK precedence: disabled: false beats enabled: false", async () => {
+ const rulesDir = await makeTempDir()
+ const rulePath = path.join(rulesDir, "both-flags.md")
+ await fs.writeFile(rulePath, "---\ndisabled: false\nenabled: false\n---\nInjected by the SDK")
+
+ const toggles = await syncRuleTogglesFromFrontmatter({ [rulePath]: false }, [rulesDir])
+
+ expect(toggles[rulePath]).to.equal(true)
+ })
+
+ it("shows a rule the SDK cannot load as off, whatever the stored toggle says", async () => {
+ const rulesDir = await makeTempDir()
+ const malformed = path.join(rulesDir, "malformed.md")
+ const emptyBody = path.join(rulesDir, "empty-body.md")
+ const nonBoolean = path.join(rulesDir, "non-boolean.md")
+ await fs.writeFile(malformed, "---\npaths: [invalid\n---\nBody")
+ await fs.writeFile(emptyBody, "---\nname: x\n---\n")
+ await fs.writeFile(nonBoolean, "---\ndisabled: [true]\n---\nBody")
+
+ const toggles = await syncRuleTogglesFromFrontmatter({ [malformed]: true, [emptyBody]: true, [nonBoolean]: true }, [
+ rulesDir,
+ ])
+
+ expect(toggles).to.deep.equal({ [malformed]: false, [emptyBody]: false, [nonBoolean]: false })
+ })
+
+ it("shows a rule with non-mapping frontmatter as on, since the SDK loads it", async () => {
+ const rulesDir = await makeTempDir()
+ const rulePath = path.join(rulesDir, "divider.md")
+ await fs.writeFile(rulePath, "---\nJust a divider line\n---\nBody")
+
+ const toggles = await syncRuleTogglesFromFrontmatter({ [rulePath]: false }, [rulesDir])
+
+ expect(toggles[rulePath]).to.equal(true)
+ expect(await setRuleDisabledInFrontmatter(rulePath, false, [rulesDir])).to.equal("written")
+ expect(readSdkEnabledState(await fs.readFile(rulePath, "utf-8"))).to.equal(false)
+ })
+
+ it("keeps the stored toggle for files it cannot read as rules", async () => {
+ const rulesDir = await makeTempDir()
+ const elsewhere = await makeTempDir()
+ const outside = path.join(elsewhere, "outside.md")
+ const json = path.join(rulesDir, "data.json")
+ const broken = path.join(rulesDir, "broken.md")
+ await fs.writeFile(outside, "Outside")
+ await fs.writeFile(json, "{}")
+ await fs.writeFile(broken, "---\npaths: [invalid\n---\nBody")
+
+ const toggles = await syncRuleTogglesFromFrontmatter({ [outside]: false, [json]: false, [broken]: false }, [rulesDir])
+
+ expect(toggles).to.deep.equal({ [outside]: false, [json]: false, [broken]: false })
+ })
+})
+
+describe("refreshClineRulesToggles", () => {
+ it("derives workspace toggles from the rule files", async () => {
+ const workspace = await makeTempDir()
+ const offPath = path.join(workspace, ".clinerules", "off.md")
+ const stalePath = path.join(workspace, ".clinerules", "stale.md")
+ await fs.mkdir(path.dirname(offPath), { recursive: true })
+ await fs.writeFile(offPath, "---\ndisabled: true\n---\nOff")
+ await fs.writeFile(stalePath, "Toggled off before the fix")
+ const workspaceState = new Map([["localClineRulesToggles", { [stalePath]: false }]])
+ const controller = {
+ stateManager: {
+ getGlobalSettingsKey: () => ({}),
+ getWorkspaceStateKey: (key: string) => workspaceState.get(key) ?? {},
+ setGlobalState: () => undefined,
+ setWorkspaceState: (key: string, value: unknown) => workspaceState.set(key, value),
+ },
+ } as unknown as Controller
+
+ const { localToggles } = await refreshClineRulesToggles(controller, workspace)
+
+ expect(localToggles).to.deep.equal({ [offPath]: false, [stalePath]: true })
+ expect(await fs.readFile(stalePath, "utf-8")).to.equal("Toggled off before the fix")
+ })
+})
diff --git a/apps/vscode/src/core/context/instructions/user-instructions/__tests__/frontmatter.test.ts b/apps/vscode/src/core/context/instructions/user-instructions/__tests__/frontmatter.test.ts
index cba674fce8..b69e605aae 100644
--- a/apps/vscode/src/core/context/instructions/user-instructions/__tests__/frontmatter.test.ts
+++ b/apps/vscode/src/core/context/instructions/user-instructions/__tests__/frontmatter.test.ts
@@ -1,6 +1,12 @@
import { describe, it } from "bun:test"
import { expect } from "chai"
-import { parseYamlFrontmatter } from "../frontmatter"
+import { parseDocument } from "yaml"
+import {
+ isFrontmatterDisabled,
+ parseYamlFrontmatter,
+ readSdkEnabledState,
+ updateUserInstructionMarkdownDisabledState,
+} from "../frontmatter"
describe("parseYamlFrontmatter", () => {
it("returns original content when no frontmatter", () => {
@@ -69,3 +75,215 @@ describe("parseYamlFrontmatter", () => {
expect(result.body.trim()).to.equal("# my-skill\nThis is a test skill.")
})
})
+
+describe("updateUserInstructionMarkdownDisabledState", () => {
+ it("adds disabled frontmatter when a rule is toggled off", () => {
+ const output = updateUserInstructionMarkdownDisabledState("Follow this rule", false)
+ expect(output).to.equal("---\ndisabled: true\n---\nFollow this rule")
+ })
+
+ it("preserves existing frontmatter fields when disabling", () => {
+ const input = ["---", "paths:", " - src/**", "---", "Scoped rule"].join("\n")
+ const output = updateUserInstructionMarkdownDisabledState(input, false)
+ expect(output).to.contain("disabled: true")
+ expect(output).to.contain("paths:")
+ expect(output).to.contain("Scoped rule")
+ })
+
+ it("removes disabled frontmatter when a rule is toggled back on", () => {
+ const input = ["---", "disabled: true", "---", "Follow this rule"].join("\n")
+ expect(updateUserInstructionMarkdownDisabledState(input, true)).to.equal("Follow this rule")
+ })
+
+ it("leaves malformed frontmatter untouched", () => {
+ const input = ["---", "paths: [invalid", "---", "Rule body"].join("\n")
+ expect(updateUserInstructionMarkdownDisabledState(input, false)).to.equal(input)
+ })
+})
+
+const lines = (...parts: string[]) => parts.join("\n")
+
+/** Every top-level value except the enablement flags, as the SDK parser reads it. */
+function otherValues(content: string): Record {
+ const block = content.replace(/^\uFEFF/, "").match(/^---\r?\n([\s\S]*?)\r?\n---/)?.[1] ?? ""
+ const data = (parseDocument(block).toJS() ?? {}) as Record
+ const { disabled: _disabled, enabled: _enabled, ...rest } = data
+ return rest
+}
+
+function bodyOf(content: string): string {
+ return parseYamlFrontmatter(content).body
+}
+
+describe("updateUserInstructionMarkdownDisabledState preserves authored frontmatter", () => {
+ it("keeps comments, key order, and quoting when disabling", () => {
+ const input = lines("---", "# scope this rule", "paths:", " - 'src/**'", 'name: "My rule"', "---", "Body")
+ expect(updateUserInstructionMarkdownDisabledState(input, false)).to.equal(
+ lines("---", "# scope this rule", "paths:", " - 'src/**'", 'name: "My rule"', "disabled: true", "---", "Body"),
+ )
+ })
+
+ it("sets an existing disabled value in place, keeping its comment", () => {
+ const input = lines("---", "disabled: false # important explanation", "paths:", " - src/**", "---", "Body")
+ expect(updateUserInstructionMarkdownDisabledState(input, false)).to.equal(
+ lines("---", "disabled: true # important explanation", "paths:", " - src/**", "---", "Body"),
+ )
+ })
+
+ it("keeps a commented disabled entry on re-enable and only flips its value", () => {
+ const input = lines("---", "disabled: true # important explanation", "paths:", " - src/**", "---", "Body")
+ expect(updateUserInstructionMarkdownDisabledState(input, true)).to.equal(
+ lines("---", "disabled: false # important explanation", "paths:", " - src/**", "---", "Body"),
+ )
+ })
+
+ it("keeps a comment placed before a split value", () => {
+ const input = lines("---", "disabled:", " # why this is off", " true", "name: x", "---", "Body")
+ expect(updateUserInstructionMarkdownDisabledState(input, true)).to.equal(
+ lines("---", "disabled:", " # why this is off", " false", "name: x", "---", "Body"),
+ )
+ })
+
+ it("keeps an indented comment that follows an inline disabled value", () => {
+ const input = lines("---", "disabled: true", " # keep this note", "paths:", " - src/**", "---", "Body")
+ expect(updateUserInstructionMarkdownDisabledState(input, true)).to.equal(
+ lines("---", "disabled: false", " # keep this note", "paths:", " - src/**", "---", "Body"),
+ )
+ })
+
+ it("removes uncommented disabled and enabled: false entries when re-enabling", () => {
+ const input = lines("---", "# keep me", "enabled: false", "paths:", " - src/**", "disabled: true", "---", "Body")
+ expect(updateUserInstructionMarkdownDisabledState(input, true)).to.equal(
+ lines("---", "# keep me", "paths:", " - src/**", "---", "Body"),
+ )
+ })
+
+ it("removes a legacy enabled: false whose value is on the next line", () => {
+ const input = lines("---", "disabled: true", "enabled:", " false", "---", "Body")
+ expect(updateUserInstructionMarkdownDisabledState(input, true)).to.equal("Body")
+ })
+
+ it("leaves matching text inside other values untouched", () => {
+ const input = lines("---", 'description: "first', " disabled: true", ' last"', "disabled: true", "---", "Body")
+ const output = updateUserInstructionMarkdownDisabledState(input, true)
+ expect(output).to.equal(lines("---", 'description: "first', " disabled: true", ' last"', "---", "Body"))
+ expect(otherValues(output)).to.deep.equal(otherValues(input))
+ })
+
+ it("refuses frontmatter the SDK parser rejects instead of editing it", () => {
+ const input = lines("---", 'description: "first', "disabled: true", 'last"', "disabled: true", "---", "Body")
+ expect(updateUserInstructionMarkdownDisabledState(input, true)).to.equal(input)
+ const duplicate = lines("---", "disabled: true", "disabled: false", "---", "Body")
+ expect(updateUserInstructionMarkdownDisabledState(duplicate, true)).to.equal(duplicate)
+ })
+
+ it("refuses a non-boolean flag, which makes the SDK reject the file", () => {
+ const flow = lines("---", "disabled: [", " true,", "]", "---", "Body")
+ expect(updateUserInstructionMarkdownDisabledState(flow, false)).to.equal(flow)
+ expect(updateUserInstructionMarkdownDisabledState(flow, true)).to.equal(flow)
+ const block = lines("---", "disabled: |", " multi", " line", "---", "Body")
+ expect(updateUserInstructionMarkdownDisabledState(block, false)).to.equal(block)
+ })
+
+ it("disables a document whose frontmatter is not a mapping by adding a block above it", () => {
+ // The SDK loads such a document as enabled with no metadata (the block
+ // parses as a plain scalar), so the markdown divider lines are user text.
+ const input = lines("---", "Just a divider line", "---", "Body")
+ const disabled = updateUserInstructionMarkdownDisabledState(input, false)
+ expect(disabled).to.equal(lines("---", "disabled: true", "---", "---", "Just a divider line", "---", "Body"))
+ expect(readSdkEnabledState(disabled)).to.equal(false)
+ expect(updateUserInstructionMarkdownDisabledState(disabled, true)).to.equal(input)
+ })
+
+ it("appends the flag inside a comment-only block and keeps the comment", () => {
+ const input = lines("---", "# top comment", "---", "Body")
+ const disabled = updateUserInstructionMarkdownDisabledState(input, false)
+ expect(disabled).to.equal(lines("---", "# top comment", "disabled: true", "---", "Body"))
+ expect(readSdkEnabledState(disabled)).to.equal(false)
+ expect(updateUserInstructionMarkdownDisabledState(disabled, true)).to.equal(input)
+ })
+
+ it("leaves a document the SDK does not load untouched", () => {
+ const emptyBody = lines("---", "name: x", "---", "")
+ expect(readSdkEnabledState(emptyBody)).to.equal(undefined)
+ expect(updateUserInstructionMarkdownDisabledState(emptyBody, false)).to.equal(emptyBody)
+ expect(updateUserInstructionMarkdownDisabledState(emptyBody, true)).to.equal(emptyBody)
+ })
+
+ it("does not touch a nested disabled key", () => {
+ const input = lines("---", "meta:", " disabled: true", "---", "Body")
+ expect(updateUserInstructionMarkdownDisabledState(input, false)).to.equal(
+ lines("---", "meta:", " disabled: true", "disabled: true", "---", "Body"),
+ )
+ })
+
+ it("recognizes quoted keys and uppercase booleans", () => {
+ expect(updateUserInstructionMarkdownDisabledState(lines("---", '"disabled": true', "---", "Body"), true)).to.equal("Body")
+ expect(
+ updateUserInstructionMarkdownDisabledState(lines("---", "'disabled': false", "name: x", "---", "Body"), false),
+ ).to.equal(lines("---", "'disabled': true", "name: x", "---", "Body"))
+ for (const spelling of ["False", "FALSE"]) {
+ const input = lines("---", `enabled: ${spelling}`, "paths:", " - src/**", "---", "Body")
+ expect(updateUserInstructionMarkdownDisabledState(input, true)).to.equal(
+ lines("---", "paths:", " - src/**", "---", "Body"),
+ )
+ }
+ })
+
+ it("preserves CRLF line endings", () => {
+ const input = "---\r\npaths:\r\n - src/**\r\n---\r\nBody\r\n"
+ const disabled = updateUserInstructionMarkdownDisabledState(input, false)
+ expect(disabled).to.equal("---\r\npaths:\r\n - src/**\r\ndisabled: true\r\n---\r\nBody\r\n")
+ expect(updateUserInstructionMarkdownDisabledState(disabled, true)).to.equal(input)
+ expect(updateUserInstructionMarkdownDisabledState("Body\r\n", false)).to.equal("---\r\ndisabled: true\r\n---\r\nBody\r\n")
+ })
+
+ it("preserves a UTF-8 BOM", () => {
+ const input = "\uFEFFFollow this rule"
+ const disabled = updateUserInstructionMarkdownDisabledState(input, false)
+ expect(disabled).to.equal("\uFEFF---\ndisabled: true\n---\nFollow this rule")
+ expect(updateUserInstructionMarkdownDisabledState(disabled, true)).to.equal(input)
+ })
+
+ it("is a no-op when the document already has the requested state", () => {
+ const disabled = lines("---", "disabled: true", "---", "Body")
+ expect(updateUserInstructionMarkdownDisabledState(disabled, false)).to.equal(disabled)
+ expect(updateUserInstructionMarkdownDisabledState("Body", true)).to.equal("Body")
+ })
+
+ it("never changes another value or the body, in either direction", () => {
+ const inputs = [
+ lines(
+ "---",
+ "name: n",
+ "description: |",
+ " disabled: true",
+ " enabled: false",
+ "paths:",
+ " - src/**",
+ "---",
+ "Body",
+ ),
+ lines("---", "# c", "disabled: false # keep", "tags: [a, b]", "---", "Body", "disabled: true"),
+ lines("---", 'title: "x: y"', "enabled:", " # legacy", " false", "---", "", "Body"),
+ ]
+ for (const input of inputs) {
+ for (const enabled of [true, false]) {
+ const output = updateUserInstructionMarkdownDisabledState(input, enabled)
+ expect(otherValues(output), input).to.deep.equal(otherValues(input))
+ expect(bodyOf(output), input).to.equal(bodyOf(input))
+ expect(readSdkEnabledState(output), input).to.equal(enabled)
+ }
+ }
+ })
+})
+
+describe("isFrontmatterDisabled", () => {
+ it("uses the SDK precedence: a boolean disabled wins over enabled", () => {
+ expect(isFrontmatterDisabled({ disabled: true })).to.equal(true)
+ expect(isFrontmatterDisabled({ enabled: false })).to.equal(true)
+ expect(isFrontmatterDisabled({ disabled: false, enabled: false })).to.equal(false)
+ expect(isFrontmatterDisabled({ disabled: true, enabled: true })).to.equal(true)
+ expect(isFrontmatterDisabled({})).to.equal(false)
+ })
+})
diff --git a/apps/vscode/src/core/context/instructions/user-instructions/__tests__/skills.test.ts b/apps/vscode/src/core/context/instructions/user-instructions/__tests__/skills.test.ts
index ded04ff0e7..f24dd83c8d 100644
--- a/apps/vscode/src/core/context/instructions/user-instructions/__tests__/skills.test.ts
+++ b/apps/vscode/src/core/context/instructions/user-instructions/__tests__/skills.test.ts
@@ -814,6 +814,38 @@ describe("updateSkillMarkdownDisabledState", () => {
})
})
+describe("updateSkillMarkdownDisabledState with the shared source-range editor", () => {
+ const lines = (...parts: string[]) => parts.join("\n")
+
+ it("re-enables a skill whose legacy enabled: false value is on the next line", () => {
+ const input = lines("---", "name: s", "description: d", "disabled: true", "enabled:", " false", "---", "Body")
+ expect(updateSkillMarkdownDisabledState(input, true)).to.equal(lines("---", "name: s", "description: d", "---", "Body"))
+ })
+
+ it("leaves matching text inside the description untouched", () => {
+ const input = lines(
+ "---",
+ "name: s",
+ 'description: "first',
+ " disabled: true",
+ ' last"',
+ "disabled: true",
+ "---",
+ "Body",
+ )
+ const output = updateSkillMarkdownDisabledState(input, true)
+ expect(output).to.equal(lines("---", "name: s", 'description: "first', " disabled: true", ' last"', "---", "Body"))
+ expect(parseYamlFrontmatter(output).data.description).to.equal("first disabled: true last")
+ })
+
+ it("keeps a comment on the disabled entry", () => {
+ const input = lines("---", "name: s", "description: d", "disabled: true # paused for review", "---", "Body")
+ expect(updateSkillMarkdownDisabledState(input, true)).to.equal(
+ lines("---", "name: s", "description: d", "disabled: false # paused for review", "---", "Body"),
+ )
+ })
+})
+
describe("setSkillDisabledInFrontmatter", () => {
let sandbox: sinon.SinonSandbox
let readFileStub: sinon.SinonStub
@@ -833,6 +865,23 @@ describe("setSkillDisabledInFrontmatter", () => {
afterEach(() => sandbox.restore())
+ it("does not report success when the edit leaves the skill disabled", async () => {
+ const skillPath = path.join("/home", "user", ".cline", "skills", "s", "SKILL.md")
+ readFileStub
+ .withArgs(skillPath, "utf-8")
+ .resolves(["---", "name: s", "description: d", "disabled: true", "enabled:", " false", "---", "Body"].join("\n"))
+
+ const ok = await setSkillDisabledInFrontmatter(skillPath, true)
+
+ if (ok) {
+ const written = String(writeFileStub.firstCall.args[1])
+ const data = parseYamlFrontmatter(written).data
+ expect(data.disabled !== true && data.enabled !== false).to.be.true
+ } else {
+ expect(writeFileStub.called).to.be.false
+ }
+ })
+
it("writes disabled: true to the SKILL.md when disabling a disk skill", async () => {
const skillPath = path.join("/home", "user", ".cline", "skills", "s", "SKILL.md")
readFileStub.withArgs(skillPath, "utf-8").resolves(["---", "name: s", "description: d", "---", "Body"].join("\n"))
diff --git a/apps/vscode/src/core/context/instructions/user-instructions/cline-rules.ts b/apps/vscode/src/core/context/instructions/user-instructions/cline-rules.ts
index 5403bdb0bb..4be888687d 100644
--- a/apps/vscode/src/core/context/instructions/user-instructions/cline-rules.ts
+++ b/apps/vscode/src/core/context/instructions/user-instructions/cline-rules.ts
@@ -1,8 +1,20 @@
import { resolveGlobalRulesConfigPaths, resolveWorkspaceRulesConfigPaths } from "@cline/shared/storage"
import { combineRuleToggles, synchronizeRuleToggles } from "@core/context/instructions/user-instructions/rule-helpers"
-import { ensureRulesDirectoryExists } from "@core/storage/disk"
+import { ensureRulesDirectoryExists, GlobalFileNames } from "@core/storage/disk"
import { ClineRulesToggles } from "@shared/cline-rules"
+import { getCwd, getDesktopDir } from "@utils/path"
+import * as fs from "fs/promises"
+import path from "path"
import { Controller } from "@/core/controller"
+import { Logger } from "@/shared/services/Logger"
+import { hasRequestedEnabledState, readSdkEnabledState, updateUserInstructionMarkdownDisabledState } from "./frontmatter"
+
+/**
+ * File types the SDK rule loader actually reads. Anything else that happens to
+ * live in a rules directory (images, JSON, editor scratch files) is never
+ * injected, so writing frontmatter into it would only corrupt it.
+ */
+const RULE_FILE_EXTENSIONS = new Set([".md", ".markdown", ".txt"])
/**
* Sub-directories of `.clinerules` that hold non-rule config and must not be
@@ -14,6 +26,158 @@ const CLINERULES_EXCLUDED_SUBDIRECTORIES: string[][] = [
[".clinerules", "skills"],
]
+/**
+ * The SDK loader reads only the files directly inside a rules directory (or
+ * the root itself when it is the single legacy `.clinerules` file); nested
+ * files never reach the model, so they are never written either.
+ */
+function isRuleFileOfRoot(rootPath: string, filePath: string): boolean {
+ return filePath === rootPath || path.dirname(filePath) === rootPath
+}
+
+/**
+ * Every global location a rule may live in: the Documents-based directory the
+ * Rules tab creates files in, plus the locations the shared SDK resolver loads
+ * from (e.g. ~/.cline/rules).
+ */
+async function resolveGlobalRuleDirectories(): Promise {
+ return [...new Set([await ensureRulesDirectoryExists(), ...resolveGlobalRulesConfigPaths()])]
+}
+
+/**
+ * Roots a rule toggle is allowed to write into for the given scope: the global
+ * rule directories, or this window's workspace rule locations.
+ */
+export async function resolveRuleWriteRoots(scope: "global" | "local"): Promise {
+ if (scope === "global") {
+ return resolveGlobalRuleDirectories()
+ }
+ return resolveWorkspaceRulesConfigPaths(await getCwd(getDesktopDir()))
+}
+
+/**
+ * Resolve a toggle's rule path to the real file we may write, or `null` when
+ * the path is not a rule document the SDK loads or does not resolve (through
+ * symlinks) to a direct child of one of the allowed roots.
+ */
+export async function resolveWritableRuleFile(rulePath: string, allowedRoots: ReadonlyArray): Promise {
+ if (!rulePath || !path.isAbsolute(rulePath)) {
+ return null
+ }
+ const fileName = path.basename(rulePath)
+ if (fileName !== GlobalFileNames.clineRules && !RULE_FILE_EXTENSIONS.has(path.extname(fileName).toLowerCase())) {
+ return null
+ }
+
+ let realFilePath: string
+ try {
+ realFilePath = await fs.realpath(rulePath)
+ if (!(await fs.stat(realFilePath)).isFile()) {
+ return null
+ }
+ } catch {
+ return null
+ }
+
+ for (const root of allowedRoots) {
+ try {
+ if (isRuleFileOfRoot(await fs.realpath(root), realFilePath)) {
+ return realFilePath
+ }
+ } catch {
+ // Root does not exist; nothing under it can be written.
+ }
+ }
+ return null
+}
+
+/**
+ * Outcome of persisting a toggle to a rule file:
+ * - `written`: the file now carries the requested state (or already did);
+ * - `skipped`: the path is not a rule document the SDK loads, so there was
+ * nothing to write;
+ * - `failed`: the file is a rule document but could not be read, written, or
+ * safely edited (malformed frontmatter), so the SDK will keep loading its
+ * previous state.
+ */
+export type RuleFrontmatterWriteResult = "written" | "skipped" | "failed"
+
+/**
+ * Persist a rule's UI toggle in the frontmatter consumed by the SDK rules
+ * loader, which reads `disabled` from the rule document itself rather than
+ * from the extension's toggle state. Only rule documents directly inside
+ * `allowedRoots` are written.
+ */
+export async function setRuleDisabledInFrontmatter(
+ rulePath: string,
+ enabled: boolean,
+ allowedRoots: ReadonlyArray,
+): Promise {
+ const filePath = await resolveWritableRuleFile(rulePath, allowedRoots)
+ if (!filePath) {
+ return "skipped"
+ }
+ try {
+ const content = await fs.readFile(filePath, "utf-8")
+ const updated = updateUserInstructionMarkdownDisabledState(content, enabled)
+ // The editor returns the document unchanged when it already has the
+ // requested state and when it cannot edit it safely, and an edit can
+ // leave a disabling flag it did not recognize. Only a document that ends
+ // up in the requested state counts as written.
+ if (!hasRequestedEnabledState(updated, enabled)) {
+ Logger.warn(`Rule frontmatter at ${filePath} could not be updated; leaving the document untouched`)
+ return "failed"
+ }
+ if (updated !== content) {
+ await fs.writeFile(filePath, updated)
+ }
+ return "written"
+ } catch (error) {
+ Logger.warn(`Failed to update rule frontmatter at ${filePath}:`, error)
+ return "failed"
+ }
+}
+
+/**
+ * Make the panel's toggles show what the SDK will load. The rule file is the
+ * only source of truth: frontmatter that disables a rule shows it as off, and
+ * a file without it shows the rule as on, whatever extension state says.
+ *
+ * Toggles saved before the toggle wrote frontmatter (cline/cline#13695) are
+ * deliberately not written back into their files. Telling such a toggle apart
+ * from a rule the user has since re-enabled by editing its file would need
+ * per-rule history that survives multiple windows and hand edits; a stale
+ * toggle shows as on instead, which is what the SDK has been loading.
+ *
+ * A file the SDK cannot load at all shows as off, since nothing from it
+ * reaches the model. Files outside `allowedRoots` and unreadable files keep
+ * their stored toggle.
+ */
+export async function syncRuleTogglesFromFrontmatter(
+ toggles: ClineRulesToggles,
+ allowedRoots: ReadonlyArray,
+): Promise {
+ const updated: ClineRulesToggles = { ...toggles }
+ for (const rulePath of Object.keys(toggles)) {
+ const filePath = await resolveWritableRuleFile(rulePath, allowedRoots)
+ if (!filePath) {
+ continue
+ }
+ let content: string
+ try {
+ content = await fs.readFile(filePath, "utf-8")
+ } catch {
+ continue
+ }
+ const sdkEnabled = readSdkEnabledState(content)
+ if (sdkEnabled === undefined) {
+ Logger.warn(`Rule ${filePath} cannot be loaded by the SDK (unparseable frontmatter or empty body); showing it as off`)
+ }
+ updated[rulePath] = sdkEnabled === true
+ }
+ return updated
+}
+
/**
* Synchronizes rule toggles across every directory a rule may live in.
* `synchronizeRuleToggles` prunes toggles for files outside the directory it
@@ -46,19 +210,25 @@ export async function refreshClineRulesToggles(
// plus every global location the shared SDK resolver loads rules from
// (e.g. ~/.cline/rules), so the panel shows what actually reaches the model.
const globalClineRulesToggles = controller.stateManager.getGlobalSettingsKey("globalClineRulesToggles")
- const globalClineRulesFilePath = await ensureRulesDirectoryExists()
- const globalRuleDirectories = [...new Set([globalClineRulesFilePath, ...resolveGlobalRulesConfigPaths()])]
- const updatedGlobalToggles = await synchronizeRuleTogglesAcrossDirectories(globalRuleDirectories, globalClineRulesToggles)
+ const globalRuleDirectories = await resolveGlobalRuleDirectories()
+ const updatedGlobalToggles = await syncRuleTogglesFromFrontmatter(
+ await synchronizeRuleTogglesAcrossDirectories(globalRuleDirectories, globalClineRulesToggles),
+ globalRuleDirectories,
+ )
controller.stateManager.setGlobalState("globalClineRulesToggles", updatedGlobalToggles)
// Local toggles: both supported workspace layouts — the legacy
// `.clinerules` directory (or single file) and `.cline/rules` — via the
// same shared resolver the SDK runtime loads rules with (cline/cline#14186).
const localClineRulesToggles = controller.stateManager.getWorkspaceStateKey("localClineRulesToggles")
- const updatedLocalToggles = await synchronizeRuleTogglesAcrossDirectories(
- resolveWorkspaceRulesConfigPaths(workingDirectory),
- localClineRulesToggles,
- CLINERULES_EXCLUDED_SUBDIRECTORIES,
+ const localRuleDirectories = resolveWorkspaceRulesConfigPaths(workingDirectory)
+ const updatedLocalToggles = await syncRuleTogglesFromFrontmatter(
+ await synchronizeRuleTogglesAcrossDirectories(
+ localRuleDirectories,
+ localClineRulesToggles,
+ CLINERULES_EXCLUDED_SUBDIRECTORIES,
+ ),
+ localRuleDirectories,
)
controller.stateManager.setWorkspaceState("localClineRulesToggles", updatedLocalToggles)
diff --git a/apps/vscode/src/core/context/instructions/user-instructions/frontmatter.ts b/apps/vscode/src/core/context/instructions/user-instructions/frontmatter.ts
index 9becde9909..62115fb6fd 100644
--- a/apps/vscode/src/core/context/instructions/user-instructions/frontmatter.ts
+++ b/apps/vscode/src/core/context/instructions/user-instructions/frontmatter.ts
@@ -1,5 +1,8 @@
+import { isDeepStrictEqual } from "node:util"
+import { parseRuleConfigFromMarkdown, parseSkillConfigFromMarkdown } from "@cline/core"
import { stripUtf8Bom } from "@cline/shared"
import * as yaml from "js-yaml"
+import { isMap, isScalar, parseDocument } from "yaml"
export type FrontmatterParseResult = {
data: Record
@@ -28,6 +31,15 @@ export type FrontmatterParseResult = {
parseError?: string
}
+/**
+ * Matches a leading `---` fenced YAML block. Group 1 is the YAML text, group 2
+ * the remaining document body. Mirrors the SDK's rule/skill loader regex so both
+ * sides agree on what counts as frontmatter.
+ */
+const FRONTMATTER_REGEX = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/
+
+const UTF8_BOM = "\uFEFF"
+
/**
* Parse YAML frontmatter from markdown content.
*
@@ -41,8 +53,7 @@ export function parseYamlFrontmatter(markdown: string): FrontmatterParseResult {
// regex below never matches a file that starts with "\uFEFF---" (see cline/cline#12151).
const normalizedMarkdown = stripUtf8Bom(markdown)
- const frontmatterRegex = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/
- const match = normalizedMarkdown.match(frontmatterRegex)
+ const match = normalizedMarkdown.match(FRONTMATTER_REGEX)
if (!match) {
return { data: {}, body: normalizedMarkdown, hadFrontmatter: false }
@@ -57,3 +68,196 @@ export function parseYamlFrontmatter(markdown: string): FrontmatterParseResult {
return { data: {}, body: normalizedMarkdown, hadFrontmatter: true, parseError: message }
}
}
+
+/**
+ * True when the frontmatter marks the document as disabled, with the same
+ * precedence as the SDK loader: a boolean `disabled` wins, and the legacy
+ * `enabled: false` only counts when `disabled` is absent. Used by the legacy
+ * rule loader; the SDK-facing paths below ask the SDK parser instead.
+ */
+export function isFrontmatterDisabled(data: Record): boolean {
+ if (typeof data.disabled === "boolean") {
+ return data.disabled
+ }
+ return data.enabled === false
+}
+
+export type UserInstructionKind = "rule" | "skill"
+
+const ENABLEMENT_KEYS: ReadonlyArray = ["disabled", "enabled"]
+
+type SourceRange = [number, number, number]
+
+/**
+ * Whether the SDK would load this document as enabled (`true`), as disabled
+ * (`false`), or not at all (`undefined`: frontmatter it cannot parse, a
+ * non-boolean flag, or an empty body).
+ *
+ * This is the SDK's own parser, not a reimplementation of its rules, so the
+ * Rules panel, the write paths, and the editor below can never disagree with
+ * what the SDK loads.
+ */
+export function readSdkEnabledState(content: string, kind: UserInstructionKind = "rule"): boolean | undefined {
+ try {
+ const config =
+ kind === "skill" ? parseSkillConfigFromMarkdown(content, "skill") : parseRuleConfigFromMarkdown(content, "rule")
+ return config.disabled !== true
+ } catch {
+ return undefined
+ }
+}
+
+/**
+ * True when the SDK would load the document in the requested state. Write
+ * paths check this on the edited document before writing or reporting
+ * success, so a toggle never claims a state the SDK will not load.
+ */
+export function hasRequestedEnabledState(content: string, enabled: boolean, kind: UserInstructionKind = "rule"): boolean {
+ return readSdkEnabledState(content, kind) === enabled
+}
+
+function asRecord(value: unknown): Record {
+ return value && typeof value === "object" && !Array.isArray(value) ? (value as Record) : {}
+}
+
+/** The top-level values other than the enablement flags, as the SDK reads them. */
+function otherFrontmatterValues(content: string, kind: UserInstructionKind): Record | undefined {
+ try {
+ const config =
+ kind === "skill" ? parseSkillConfigFromMarkdown(content, "skill") : parseRuleConfigFromMarkdown(content, "rule")
+ const values = { ...asRecord(config.frontmatter) }
+ for (const key of ENABLEMENT_KEYS) {
+ delete values[key]
+ }
+ return values
+ } catch {
+ return undefined
+ }
+}
+
+/**
+ * Update the `disabled` frontmatter flag shared by SDK-backed user
+ * instructions (rules and skills).
+ *
+ * The SDK's parser decides every state question (see readSdkEnabledState).
+ * The frontmatter is then parsed as a YAML document only to find the source
+ * ranges of the top-level `disabled` and `enabled` entries, and just those
+ * characters change. Everything else the author wrote, including other
+ * values, comments, key order, quoting, line endings, and a UTF-8 BOM, stays
+ * byte for byte.
+ *
+ * - Disabling sets an existing `disabled` value to `true`, or appends a
+ * `disabled: true` entry. A document with no frontmatter, or with
+ * frontmatter that is not a mapping (which the SDK loads as having no
+ * metadata), gets a new `disabled: true` block above its existing text.
+ * - Enabling removes the `disabled` entry and a legacy `enabled: false`; an
+ * entry that carries a comment keeps its line and has its value set to
+ * `false` (or `true` for `enabled`) instead, so the comment survives.
+ * Frontmatter left empty is removed entirely.
+ * - A document the SDK does not load, or an edit whose result the SDK would
+ * not load in the requested state or that would change any other value,
+ * is returned unchanged.
+ */
+export function updateUserInstructionMarkdownDisabledState(
+ content: string,
+ enabled: boolean,
+ kind: UserInstructionKind = "rule",
+): string {
+ const bom = content.startsWith(UTF8_BOM) ? UTF8_BOM : ""
+ const text = bom ? content.slice(UTF8_BOM.length) : content
+ const eol = text.includes("\r\n") ? "\r\n" : "\n"
+
+ // Nothing to do for a document the SDK does not load, or one already in
+ // the requested state.
+ const currentState = readSdkEnabledState(text, kind)
+ if (currentState === undefined || currentState === enabled) {
+ return content
+ }
+ const prependDisabledBlock = () => `${bom}---${eol}disabled: true${eol}---${eol}${text}`
+
+ const match = text.match(FRONTMATTER_REGEX)
+ if (!match) {
+ return enabled ? content : prependDisabledBlock()
+ }
+ const [, block, body] = match
+ const blockStart = text.indexOf("\n") + 1
+
+ const document = parseDocument(block)
+ if (document.errors.length > 0) {
+ return content
+ }
+ // An empty block (whitespace or comments only) is a mapping with no
+ // entries; the flag is appended inside it so the comments stay in place.
+ if (document.contents !== null && !isMap(document.contents)) {
+ // The SDK treats non-mapping frontmatter as no metadata, so the rule is
+ // enabled and nothing in the block can be edited to disable it.
+ return enabled ? content : prependDisabledBlock()
+ }
+ const before = otherFrontmatterValues(text, kind)
+ if (!before) {
+ return content
+ }
+
+ const pairs = isMap(document.contents) ? document.contents.items : []
+ const rangesFor = (key: string): { key: SourceRange; value: SourceRange } | undefined => {
+ const pair = pairs.find((item) => isScalar(item.key) && item.key.value === key)
+ const keyRange = (pair?.key as { range?: SourceRange } | undefined)?.range
+ const valueRange = (pair?.value as { range?: SourceRange } | null | undefined)?.range
+ return keyRange && valueRange ? { key: keyRange, value: valueRange } : undefined
+ }
+
+ const edits: Array<{ start: number; end: number; text: string }> = []
+ const setValue = (key: string, value: string): boolean => {
+ const ranges = rangesFor(key)
+ if (!ranges) {
+ return false
+ }
+ edits.push({ start: ranges.value[0], end: ranges.value[1], text: value })
+ return true
+ }
+ const removeEntry = (key: string, fallbackValue: string): boolean => {
+ const ranges = rangesFor(key)
+ if (!ranges) {
+ return false
+ }
+ const start = ranges.key[0]
+ const end = ranges.value[2]
+ const startsLine = start === 0 || block[start - 1] === "\n"
+ if (!startsLine || block.slice(start, end).includes("#")) {
+ return setValue(key, fallbackValue)
+ }
+ edits.push({ start, end, text: "" })
+ return true
+ }
+
+ const flags = asRecord(document.toJS())
+ if (enabled) {
+ if (rangesFor("disabled") && flags.disabled !== false && !removeEntry("disabled", "false")) {
+ return content
+ }
+ if (flags.enabled === false && !removeEntry("enabled", "true")) {
+ return content
+ }
+ } else if (rangesFor("disabled")) {
+ if (!setValue("disabled", "true")) {
+ return content
+ }
+ } else {
+ edits.push({ start: block.length, end: block.length, text: `${block.length > 0 ? eol : ""}disabled: true` })
+ }
+
+ let nextBlock = block
+ for (const edit of [...edits].sort((a, b) => b.start - a.start)) {
+ nextBlock = nextBlock.slice(0, edit.start) + edit.text + nextBlock.slice(edit.end)
+ }
+ // Removing the last entry leaves the newline that ended the entry before it.
+ if (!/\r?\n$/.test(block)) {
+ nextBlock = nextBlock.replace(/\r?\n$/, "")
+ }
+ const nextText =
+ nextBlock.trim() === "" ? body : `${text.slice(0, blockStart)}${nextBlock}${text.slice(blockStart + block.length)}`
+ if (readSdkEnabledState(nextText, kind) !== enabled || !isDeepStrictEqual(before, otherFrontmatterValues(nextText, kind))) {
+ return content
+ }
+ return `${bom}${nextText}`
+}
diff --git a/apps/vscode/src/core/context/instructions/user-instructions/skills.ts b/apps/vscode/src/core/context/instructions/user-instructions/skills.ts
index c10c65b0ec..48eda9aaa6 100644
--- a/apps/vscode/src/core/context/instructions/user-instructions/skills.ts
+++ b/apps/vscode/src/core/context/instructions/user-instructions/skills.ts
@@ -3,10 +3,9 @@ import type { GlobalInstructionsFile } from "@shared/remote-config/schema"
import type { SkillContent, SkillMetadata } from "@shared/skills"
import { fileExistsAtPath, isDirectory } from "@utils/fs"
import * as fs from "fs/promises"
-import * as yaml from "js-yaml"
import * as path from "path"
import { Logger } from "@/shared/services/Logger"
-import { parseYamlFrontmatter } from "./frontmatter"
+import { hasRequestedEnabledState, parseYamlFrontmatter, updateUserInstructionMarkdownDisabledState } from "./frontmatter"
/**
* Update the `disabled` frontmatter flag of a SKILL.md document.
@@ -15,49 +14,12 @@ import { parseYamlFrontmatter } from "./frontmatter"
* skill's enabled state from the SKILL.md frontmatter `disabled` field, not from
* the extension's UI toggle state. Toggling a skill in the VS Code sidebar must
* therefore also write this flag so the change is reflected for the model
- * (ENG-1995). This mirrors the SDK's updateSkillMarkdownEnabledState but lives in
- * the extension and uses js-yaml (the extension's frontmatter parser).
- *
- * - enabled=false → sets `disabled: true`.
- * - enabled=true → removes `disabled` (and a stale `enabled: false`), dropping
- * the frontmatter block entirely if it becomes empty.
- *
- * Returns the original content unchanged when enabling a document that has no
- * frontmatter (nothing to clear).
+ * (ENG-1995). Rules and skills share one editor; see
+ * updateUserInstructionMarkdownDisabledState for what it changes and what it
+ * refuses to edit.
*/
export function updateSkillMarkdownDisabledState(content: string, enabled: boolean): string {
- const { data, body, hadFrontmatter, parseError } = parseYamlFrontmatter(content)
-
- if (!hadFrontmatter && enabled) {
- return content
- }
-
- // parseYamlFrontmatter fails open on malformed YAML: it returns data={} and
- // body= (frontmatter block included). Serializing here
- // would prepend a second `---` block and corrupt the file, so leave it
- // untouched and let the user fix the frontmatter.
- if (parseError) {
- return content
- }
-
- if (enabled) {
- delete data.disabled
- if (data.enabled === false) {
- delete data.enabled
- }
- if (Object.keys(data).length === 0) {
- return body
- }
- return serializeSkillFrontmatter(data, body)
- }
-
- data.disabled = true
- return serializeSkillFrontmatter(data, body)
-}
-
-function serializeSkillFrontmatter(data: Record, body: string): string {
- const yamlText = yaml.dump(data, { schema: yaml.JSON_SCHEMA }).trimEnd()
- return `---\n${yamlText}\n---\n${body}`
+ return updateUserInstructionMarkdownDisabledState(content, enabled, "skill")
}
/**
@@ -71,6 +33,10 @@ export async function setSkillDisabledInFrontmatter(skillMdPath: string, enabled
try {
const content = await fs.readFile(skillMdPath, "utf-8")
const updated = updateSkillMarkdownDisabledState(content, enabled)
+ if (!hasRequestedEnabledState(updated, enabled, "skill")) {
+ Logger.warn(`Skill frontmatter at ${skillMdPath} could not be updated; leaving the document untouched`)
+ return false
+ }
if (updated !== content) {
await fs.writeFile(skillMdPath, updated)
}
diff --git a/apps/vscode/src/core/controller/file/__tests__/toggleClineRule.test.ts b/apps/vscode/src/core/controller/file/__tests__/toggleClineRule.test.ts
new file mode 100644
index 0000000000..a82685c608
--- /dev/null
+++ b/apps/vscode/src/core/controller/file/__tests__/toggleClineRule.test.ts
@@ -0,0 +1,183 @@
+import { afterEach, beforeEach, describe, expect, it } from "bun:test"
+import { RuleScope, ToggleClineRuleRequest } from "@shared/proto/cline/file"
+import fs from "fs/promises"
+import os from "os"
+import path from "path"
+import sinon from "sinon"
+import { parseYamlFrontmatter, readSdkEnabledState } from "@/core/context/instructions/user-instructions/frontmatter"
+import { HostProvider } from "@/hosts/host-provider"
+import { setVscodeHostProviderMock } from "@/test/host-provider-test-utils"
+import { toggleClineRule } from "../toggleClineRule"
+
+let sandbox: sinon.SinonSandbox
+let workspace: string
+
+beforeEach(async () => {
+ sandbox = sinon.createSandbox()
+ workspace = await fs.realpath(await fs.mkdtemp(path.join(os.tmpdir(), "cline-toggle-rule-test-")))
+ await fs.mkdir(path.join(workspace, ".clinerules"), { recursive: true })
+ setVscodeHostProviderMock()
+ // A fresh array per call: getCwd() consumes the array it receives with shift().
+ sandbox.stub(HostProvider, "workspace").get(() => ({
+ getWorkspacePaths: async () => ({ paths: [workspace] }),
+ }))
+})
+
+afterEach(async () => {
+ sandbox.restore()
+ HostProvider.reset()
+ await fs.rm(workspace, { recursive: true, force: true })
+})
+
+function createController() {
+ const localToggles: Record = {}
+ const globalState = new Map([
+ ["globalClineRulesToggles", {}],
+ ["remoteRulesToggles", {}],
+ ])
+ const workspaceState = new Map([["localClineRulesToggles", localToggles]])
+
+ return {
+ controller: {
+ stateManager: {
+ getGlobalSettingsKey: (key: string) => globalState.get(key) ?? {},
+ getWorkspaceStateKey: (key: string) => workspaceState.get(key) ?? {},
+ getGlobalStateKey: (key: string) => globalState.get(key) ?? {},
+ setGlobalState: (key: string, value: unknown) => globalState.set(key, value),
+ setWorkspaceState: (key: string, value: unknown) => workspaceState.set(key, value),
+ },
+ },
+ localToggles,
+ }
+}
+
+describe("toggleClineRule", () => {
+ it("persists a workspace rule toggle in both extension state and the rule file the SDK reads", async () => {
+ const rulePath = path.join(workspace, ".clinerules", "project-rule.md")
+ await fs.writeFile(rulePath, "Follow this rule")
+ const { controller, localToggles } = createController()
+
+ await toggleClineRule(
+ controller as never,
+ ToggleClineRuleRequest.create({ scope: RuleScope.LOCAL, rulePath, enabled: false }),
+ )
+
+ expect(localToggles[rulePath]).toBe(false)
+ expect(parseYamlFrontmatter(await fs.readFile(rulePath, "utf-8")).data.disabled).toBe(true)
+
+ await toggleClineRule(
+ controller as never,
+ ToggleClineRuleRequest.create({ scope: RuleScope.LOCAL, rulePath, enabled: true }),
+ )
+
+ expect(localToggles[rulePath]).toBe(true)
+ expect(await fs.readFile(rulePath, "utf-8")).toBe("Follow this rule")
+ })
+
+ it("also writes rules under the .cline/rules layout", async () => {
+ const rulePath = path.join(workspace, ".cline", "rules", "new-layout.md")
+ await fs.mkdir(path.dirname(rulePath), { recursive: true })
+ await fs.writeFile(rulePath, "New layout rule")
+ const { controller } = createController()
+
+ await toggleClineRule(
+ controller as never,
+ ToggleClineRuleRequest.create({ scope: RuleScope.LOCAL, rulePath, enabled: false }),
+ )
+
+ expect(parseYamlFrontmatter(await fs.readFile(rulePath, "utf-8")).data.disabled).toBe(true)
+ })
+
+ it("updates state but leaves the file alone when the path is outside the workspace rule directories", async () => {
+ const rulePath = path.join(workspace, "README.md")
+ await fs.writeFile(rulePath, "Not a rule")
+ const { controller, localToggles } = createController()
+
+ await toggleClineRule(
+ controller as never,
+ ToggleClineRuleRequest.create({ scope: RuleScope.LOCAL, rulePath, enabled: false }),
+ )
+
+ expect(localToggles[rulePath]).toBe(false)
+ expect(await fs.readFile(rulePath, "utf-8")).toBe("Not a rule")
+ })
+
+ it("reverts the state toggle when the rule file cannot be written", async () => {
+ const rulePath = path.join(workspace, ".clinerules", "read-only.md")
+ await fs.writeFile(rulePath, "Locked rule")
+ await fs.chmod(rulePath, 0o444)
+ const { controller, localToggles } = createController()
+ try {
+ const response = await toggleClineRule(
+ controller as never,
+ ToggleClineRuleRequest.create({ scope: RuleScope.LOCAL, rulePath, enabled: false }),
+ )
+
+ expect(localToggles[rulePath]).toBe(true)
+ expect(response.localClineRulesToggles?.toggles[rulePath]).toBe(true)
+ expect(await fs.readFile(rulePath, "utf-8")).toBe("Locked rule")
+ } finally {
+ await fs.chmod(rulePath, 0o644)
+ }
+ })
+
+ it("reverts the state toggle when malformed frontmatter prevents a safe edit", async () => {
+ const rulePath = path.join(workspace, ".clinerules", "broken.md")
+ const content = "---\npaths: [invalid\n---\nBody"
+ await fs.writeFile(rulePath, content)
+ const { controller, localToggles } = createController()
+
+ const response = await toggleClineRule(
+ controller as never,
+ ToggleClineRuleRequest.create({ scope: RuleScope.LOCAL, rulePath, enabled: false }),
+ )
+
+ expect(localToggles[rulePath]).toBe(true)
+ expect(response.localClineRulesToggles?.toggles[rulePath]).toBe(true)
+ expect(await fs.readFile(rulePath, "utf-8")).toBe(content)
+ })
+
+ it("re-enables a rule whose legacy enabled: false value is on the next line", async () => {
+ const rulePath = path.join(workspace, ".clinerules", "split-enabled.md")
+ await fs.writeFile(rulePath, ["---", "disabled: true", "enabled:", " false", "---", "Body"].join("\n"))
+ const { controller, localToggles } = createController()
+ localToggles[rulePath] = false
+
+ const response = await toggleClineRule(
+ controller as never,
+ ToggleClineRuleRequest.create({ scope: RuleScope.LOCAL, rulePath, enabled: true }),
+ )
+
+ expect(response.localClineRulesToggles?.toggles[rulePath]).toBe(true)
+ expect(readSdkEnabledState(await fs.readFile(rulePath, "utf-8"))).toBe(true)
+ })
+
+ it("reverts instead of reporting success when the SDK would still not load the rule as requested", async () => {
+ const rulePath = path.join(workspace, ".clinerules", "non-boolean.md")
+ const content = ["---", "disabled: [", " true,", "]", "---", "Body"].join("\n")
+ await fs.writeFile(rulePath, content)
+ const { controller, localToggles } = createController()
+
+ const response = await toggleClineRule(
+ controller as never,
+ ToggleClineRuleRequest.create({ scope: RuleScope.LOCAL, rulePath, enabled: false }),
+ )
+
+ expect(response.localClineRulesToggles?.toggles[rulePath]).toBe(true)
+ expect(localToggles[rulePath]).toBe(true)
+ expect(await fs.readFile(rulePath, "utf-8")).toBe(content)
+ })
+
+ it("does not write frontmatter into non-rule files that happen to live in .clinerules", async () => {
+ const rulePath = path.join(workspace, ".clinerules", "notes.json")
+ await fs.writeFile(rulePath, "{}")
+ const { controller } = createController()
+
+ await toggleClineRule(
+ controller as never,
+ ToggleClineRuleRequest.create({ scope: RuleScope.LOCAL, rulePath, enabled: false }),
+ )
+
+ expect(await fs.readFile(rulePath, "utf-8")).toBe("{}")
+ })
+})
diff --git a/apps/vscode/src/core/controller/file/toggleClineRule.ts b/apps/vscode/src/core/controller/file/toggleClineRule.ts
index d5bc14b099..d87c8af564 100644
--- a/apps/vscode/src/core/controller/file/toggleClineRule.ts
+++ b/apps/vscode/src/core/controller/file/toggleClineRule.ts
@@ -1,3 +1,8 @@
+import {
+ type RuleFrontmatterWriteResult,
+ resolveRuleWriteRoots,
+ setRuleDisabledInFrontmatter,
+} from "@core/context/instructions/user-instructions/cline-rules"
import { getWorkspaceBasename } from "@core/workspace"
import type { ToggleClineRuleRequest } from "@shared/proto/cline/file"
import { RuleScope, ToggleClineRules } from "@shared/proto/cline/file"
@@ -47,6 +52,34 @@ export async function toggleClineRule(controller: Controller, request: ToggleCli
throw new Error(`Invalid scope: ${scope}`)
}
+ // The SDK rule loader reads the document's `disabled` frontmatter flag, not
+ // the extension's toggle state, so file-backed global and workspace rules
+ // are written as well. The write is confined to rule documents directly
+ // inside the scope's rule roots; anything else keeps only the state toggle.
+ // If a rule file cannot be written, the state toggle is reverted so the
+ // panel keeps showing what the SDK will actually load.
+ if (scope !== RuleScope.REMOTE) {
+ let result: RuleFrontmatterWriteResult = "failed"
+ try {
+ const allowedRoots = await resolveRuleWriteRoots(scope === RuleScope.GLOBAL ? "global" : "local")
+ result = await setRuleDisabledInFrontmatter(rulePath, enabled, allowedRoots)
+ } catch (error) {
+ Logger.warn(`toggleClineRule: could not persist frontmatter for ${rulePath}`, error)
+ }
+ if (result === "failed") {
+ Logger.warn(`toggleClineRule: reverting toggle for ${rulePath}; the rule file could not be updated`)
+ if (scope === RuleScope.GLOBAL) {
+ const toggles = controller.stateManager.getGlobalSettingsKey("globalClineRulesToggles")
+ toggles[rulePath] = !enabled
+ controller.stateManager.setGlobalState("globalClineRulesToggles", toggles)
+ } else {
+ const toggles = controller.stateManager.getWorkspaceStateKey("localClineRulesToggles")
+ toggles[rulePath] = !enabled
+ controller.stateManager.setWorkspaceState("localClineRulesToggles", toggles)
+ }
+ }
+ }
+
// Track rule toggle telemetry with current task context
if (controller.task?.ulid) {
// Extract just the filename for privacy (no full paths)
diff --git a/apps/vscode/src/test/bun-test-preload.ts b/apps/vscode/src/test/bun-test-preload.ts
index 679d299ac9..34e9399471 100644
--- a/apps/vscode/src/test/bun-test-preload.ts
+++ b/apps/vscode/src/test/bun-test-preload.ts
@@ -29,20 +29,62 @@
// exports (value `undefined`) and overlay the stub on top: stub names keep stub
// behavior, every other valid import links as `undefined`.
//
-// Importing the real package here is safe: the preload runs before any test
-// file, so this is the only point the real module is linked, and we only read
-// its export *names*, never its behavior (the mock shadows it everywhere tests look).
+// The real package must never be loaded in this process before it is mocked.
+// Mocking an already-loaded module makes bun re-link the module graph, and
+// that re-link leaves a slice of `@cline/shared`'s source-tree exports
+// undefined (`stripUtf8Bom` among them) for everything under
+// sdk/packages/core, which resolves `@cline/shared` to shared/src through
+// core's tsconfig `paths`. Real SDK functions re-exported by the stub then
+// throw. So the export names come from a child process (cached on the built
+// package's mtime), the mock is registered first, and everything that might
+// pull core in is imported after it.
+
import { beforeEach as bunBeforeEach, vi as bunVi, mock } from "bun:test"
-import * as realClineCore from "@cline/core"
-import * as LlmsModels from "@cline/llms"
-import * as clineCoreStub from "./cline-core-vitest-stub"
+import { mkdirSync, readFileSync, statSync, writeFileSync } from "node:fs"
+import path from "node:path"
import * as vscodeStub from "./vscode-vitest-stub"
+function readRealClineCoreExportNames(): string[] {
+ const distEntry = path.resolve(import.meta.dir, "../../../../sdk/packages/core/dist/index.js")
+ const stamp = (() => {
+ const stat = statSync(distEntry)
+ return `${stat.mtimeMs}:${stat.size}`
+ })()
+ const cacheFile = path.resolve(import.meta.dir, "../../node_modules/.cache/cline-core-export-names.json")
+ try {
+ const cached = JSON.parse(readFileSync(cacheFile, "utf-8")) as { stamp: string; names: string[] }
+ if (cached.stamp === stamp && Array.isArray(cached.names)) {
+ return cached.names
+ }
+ } catch {
+ // No usable cache; read the names below.
+ }
+ const result = Bun.spawnSync({
+ cmd: ["bun", "-e", "console.log(JSON.stringify(Object.keys(await import('@cline/core'))))"],
+ cwd: import.meta.dir,
+ })
+ if (result.exitCode !== 0) {
+ throw new Error(`Could not read @cline/core export names: ${result.stderr.toString()}`)
+ }
+ const names = JSON.parse(result.stdout.toString()) as string[]
+ try {
+ mkdirSync(path.dirname(cacheFile), { recursive: true })
+ writeFileSync(cacheFile, JSON.stringify({ stamp, names }))
+ } catch {
+ // Cache is an optimization only.
+ }
+ return names
+}
+
const clineCoreNamespace: Record = {}
-for (const name of Object.keys(realClineCore)) {
+for (const name of readRealClineCoreExportNames()) {
clineCoreNamespace[name] = undefined
}
+mock.module("@cline/core", () => clineCoreNamespace)
+
+const clineCoreStub = await import("./cline-core-vitest-stub")
Object.assign(clineCoreNamespace, clineCoreStub)
+const LlmsModels = await import("@cline/llms")
bunBeforeEach(() => {
clineCoreStub.resetModelsFileState()
@@ -51,8 +93,6 @@ bunBeforeEach(() => {
LlmsModels.resetRegistry()
})
-mock.module("@cline/core", () => clineCoreNamespace)
-
// `vscode`: the stub provides both named exports (Position, Uri, …) and a
// default export (the namespace object). Preserve both shapes so `import * as
// vscode from "vscode"` and `import vscode from "vscode"` both work.
diff --git a/apps/vscode/src/test/cline-core-vitest-stub.ts b/apps/vscode/src/test/cline-core-vitest-stub.ts
index c377b45c76..32934cf663 100644
--- a/apps/vscode/src/test/cline-core-vitest-stub.ts
+++ b/apps/vscode/src/test/cline-core-vitest-stub.ts
@@ -58,6 +58,10 @@ export function resolveModelsRegistryPath(): string {
export function ensureCustomProvidersLoadedSync(): void {}
export { toClineCoreStartInput } from "../../../../sdk/packages/core/src/cline-core/start-input"
+export {
+ parseRuleConfigFromMarkdown,
+ parseSkillConfigFromMarkdown,
+} from "../../../../sdk/packages/core/src/extensions/config/user-instruction-config-loader"
export { isPrivateModelCatalogProvider } from "../../../../sdk/packages/core/src/services/llms/provider-defaults"
// Real implementation re-exported from the sdk source (same pattern as the
// apply-patch executors below) so store writes are reflected in the live
diff --git a/bun.lock b/bun.lock
index 7e9e0c6047..f8155a5099 100644
--- a/bun.lock
+++ b/bun.lock
@@ -452,6 +452,7 @@
"undici": "^7.29.0",
"uuid": "^11.1.0",
"vscode-uri": "^3.1.0",
+ "yaml": "^2.8.2",
"zod": "^4.3.6",
},
"devDependencies": {