diff --git a/packages/app/src/components/prompt-input/submit.ts b/packages/app/src/components/prompt-input/submit.ts
index 9387bcb1db..77f605ebed 100644
--- a/packages/app/src/components/prompt-input/submit.ts
+++ b/packages/app/src/components/prompt-input/submit.ts
@@ -73,12 +73,16 @@ export function createPromptSubmit(input: PromptSubmitInput) {
const abort = async () => {
const sessionID = params.id
if (!sessionID) return Promise.resolve()
+
+ globalSync.todo.set(sessionID, [])
+ const [, setStore] = globalSync.child(sdk.directory)
+ setStore("todo", sessionID, [])
+
const queued = pending.get(sessionID)
if (queued) {
queued.abort.abort()
queued.cleanup()
pending.delete(sessionID)
- globalSync.todo.set(sessionID, undefined)
return Promise.resolve()
}
return sdk.client.session
@@ -86,9 +90,6 @@ export function createPromptSubmit(input: PromptSubmitInput) {
sessionID,
})
.catch(() => {})
- .finally(() => {
- globalSync.todo.set(sessionID, undefined)
- })
}
const restoreCommentItems = (items: CommentItem[]) => {
diff --git a/packages/app/src/i18n/ar.ts b/packages/app/src/i18n/ar.ts
index d35c63df77..44189b25ac 100644
--- a/packages/app/src/i18n/ar.ts
+++ b/packages/app/src/i18n/ar.ts
@@ -134,7 +134,8 @@ export const dict = {
"provider.connect.oauth.code.invalid": "رمز التفويض غير صالح",
"provider.connect.oauth.auto.visit.prefix": "قم بزيارة ",
"provider.connect.oauth.auto.visit.link": "هذا الرابط",
- "provider.connect.oauth.auto.visit.suffix": " وأدخل الرمز أدناه لتوصيل حسابك واستخدام نماذج {{provider}} في Kilo.",
+ "provider.connect.oauth.auto.visit.suffix":
+ " وأدخل الرمز أدناه لتوصيل حسابك واستخدام نماذج {{provider}} في Kilo.",
"provider.connect.oauth.auto.confirmationCode": "رمز التأكيد",
"provider.connect.toast.connected.title": "تم توصيل {{provider}}",
"provider.connect.toast.connected.description": "نماذج {{provider}} متاحة الآن للاستخدام.",
diff --git a/packages/app/src/i18n/fr.ts b/packages/app/src/i18n/fr.ts
index eb21fd5c3b..ed2a879fd7 100644
--- a/packages/app/src/i18n/fr.ts
+++ b/packages/app/src/i18n/fr.ts
@@ -389,7 +389,8 @@ export const dict = {
"toast.session.unshare.failed.description": "Une erreur s'est produite lors de l'annulation du partage de la session",
"toast.session.listFailed.title": "Échec du chargement des sessions pour {{project}}",
"toast.update.title": "Mise à jour disponible",
- "toast.update.description": "Une nouvelle version d'Kilo ({{version}}) est maintenant disponible pour installation.",
+ "toast.update.description":
+ "Une nouvelle version d'Kilo ({{version}}) est maintenant disponible pour installation.",
"toast.update.action.installRestart": "Installer et redémarrer",
"toast.update.action.notYet": "Pas encore",
"error.page.title": "Quelque chose s'est mal passé",
@@ -523,7 +524,8 @@ export const dict = {
"sidebar.workspaces.enable": "Activer les espaces de travail",
"sidebar.workspaces.disable": "Désactiver les espaces de travail",
"sidebar.gettingStarted.title": "Commencer",
- "sidebar.gettingStarted.line1": "Kilo inclut des modèles gratuits pour que vous puissiez commencer immédiatement.",
+ "sidebar.gettingStarted.line1":
+ "Kilo inclut des modèles gratuits pour que vous puissiez commencer immédiatement.",
"sidebar.gettingStarted.line2":
"Connectez n'importe quel fournisseur pour utiliser des modèles, y compris Claude, GPT, Gemini etc.",
"sidebar.project.recentSessions": "Sessions récentes",
diff --git a/packages/app/src/i18n/th.ts b/packages/app/src/i18n/th.ts
index 09dbc5bce2..243d1ce21b 100644
--- a/packages/app/src/i18n/th.ts
+++ b/packages/app/src/i18n/th.ts
@@ -146,7 +146,8 @@ export const dict = {
"provider.connect.oauth.code.invalid": "รหัสการอนุญาตไม่ถูกต้อง",
"provider.connect.oauth.auto.visit.prefix": "เยี่ยมชม ",
"provider.connect.oauth.auto.visit.link": "ลิงก์นี้",
- "provider.connect.oauth.auto.visit.suffix": " และป้อนรหัสด้านล่างเพื่อเชื่อมต่อบัญชีและใช้โมเดล {{provider}} ใน Kilo",
+ "provider.connect.oauth.auto.visit.suffix":
+ " และป้อนรหัสด้านล่างเพื่อเชื่อมต่อบัญชีและใช้โมเดล {{provider}} ใน Kilo",
"provider.connect.oauth.auto.confirmationCode": "รหัสยืนยัน",
"provider.connect.toast.connected.title": "{{provider}} ที่เชื่อมต่อแล้ว",
"provider.connect.toast.connected.description": "โมเดล {{provider}} พร้อมใช้งานแล้ว",
diff --git a/packages/app/src/i18n/zht.ts b/packages/app/src/i18n/zht.ts
index 006ed3a57e..29a71b178b 100644
--- a/packages/app/src/i18n/zht.ts
+++ b/packages/app/src/i18n/zht.ts
@@ -147,7 +147,8 @@ export const dict = {
"provider.connect.oauth.code.invalid": "授權碼無效",
"provider.connect.oauth.auto.visit.prefix": "造訪 ",
"provider.connect.oauth.auto.visit.link": "此連結",
- "provider.connect.oauth.auto.visit.suffix": " 並輸入以下程式碼,以連線你的帳戶並在 Kilo 中使用 {{provider}} 模型。",
+ "provider.connect.oauth.auto.visit.suffix":
+ " 並輸入以下程式碼,以連線你的帳戶並在 Kilo 中使用 {{provider}} 模型。",
"provider.connect.oauth.auto.confirmationCode": "確認碼",
"provider.connect.toast.connected.title": "{{provider}} 已連線",
"provider.connect.toast.connected.description": "現在可以使用 {{provider}} 模型了。",
diff --git a/packages/app/src/pages/layout/sidebar-items.tsx b/packages/app/src/pages/layout/sidebar-items.tsx
index 6fb7ce6319..0a461ca79f 100644
--- a/packages/app/src/pages/layout/sidebar-items.tsx
+++ b/packages/app/src/pages/layout/sidebar-items.tsx
@@ -32,7 +32,9 @@ export const ProjectIcon = (props: { project: LocalProject; class?: string; noti
0 && props.notify }}
diff --git a/packages/app/src/pages/session.tsx b/packages/app/src/pages/session.tsx
index 3235dde05e..4920d48d59 100644
--- a/packages/app/src/pages/session.tsx
+++ b/packages/app/src/pages/session.tsx
@@ -1199,6 +1199,7 @@ export default function Page() {
comments.clear()
resumeScroll()
}}
+ onResponseSubmit={resumeScroll}
setPromptDockRef={(el) => {
promptDock = el
}}
diff --git a/packages/app/src/pages/session/composer/session-composer-region.tsx b/packages/app/src/pages/session/composer/session-composer-region.tsx
index bb3abe5893..f0784b0c57 100644
--- a/packages/app/src/pages/session/composer/session-composer-region.tsx
+++ b/packages/app/src/pages/session/composer/session-composer-region.tsx
@@ -16,6 +16,7 @@ export function SessionComposerRegion(props: {
newSessionWorktree: string
onNewSessionWorktreeReset: () => void
onSubmit: () => void
+ onResponseSubmit: () => void
setPromptDockRef: (el: HTMLDivElement) => void
onModeAction?: (input: { mode: string; text: string; description?: string }) => void // kilocode_change
}) {
@@ -59,7 +60,11 @@ export function SessionComposerRegion(props: {
{(request) => (
{/* kilocode_change: add onModeAction */}
-
+
)}
@@ -70,7 +75,10 @@ export function SessionComposerRegion(props: {
{
+ props.onResponseSubmit()
+ props.state.decide(response)
+ }}
/>
)}
diff --git a/packages/app/src/pages/session/composer/session-question-dock.tsx b/packages/app/src/pages/session/composer/session-question-dock.tsx
index 3c11fd122b..88addeb63d 100644
--- a/packages/app/src/pages/session/composer/session-question-dock.tsx
+++ b/packages/app/src/pages/session/composer/session-question-dock.tsx
@@ -11,6 +11,7 @@ import { useSDK } from "@/context/sdk"
// kilocode_change start - add onModeAction prop for mode-switching support
export const SessionQuestionDock: Component<{
request: QuestionRequest
+ onSubmit: () => void
onModeAction?: (input: { mode: string; text: string; description?: string }) => void
}> = (props) => {
// kilocode_change end
@@ -120,6 +121,7 @@ export const SessionQuestionDock: Component<{
const reply = async (answers: QuestionAnswer[]) => {
if (store.sending) return
+ props.onSubmit()
setStore("sending", true)
try {
await sdk.client.question.reply({ requestID: props.request.id, answers })
@@ -133,6 +135,7 @@ export const SessionQuestionDock: Component<{
const reject = async () => {
if (store.sending) return
+ props.onSubmit()
setStore("sending", true)
try {
await sdk.client.question.reject({ requestID: props.request.id })
diff --git a/packages/desktop/src/index.tsx b/packages/desktop/src/index.tsx
index 81015d5678..9e0ce8f0a6 100644
--- a/packages/desktop/src/index.tsx
+++ b/packages/desktop/src/index.tsx
@@ -472,12 +472,10 @@ render(() => {
}
return (
-
- {(defaultServer) => (
-
-
-
- )}
+
+
+
+
)
}}
@@ -492,19 +490,34 @@ type ServerReadyData = { url: string; password: string | null }
// Gate component that waits for the server to be ready
function ServerGate(props: { children: (data: Accessor) => JSX.Element }) {
const [serverData] = createResource(() => commands.awaitInitialization(new Channel() as any))
- if (serverData.state === "errored") throw serverData.error
return (
-
+
+
+
+
Failed to start server
+
+ {String(serverData.error ?? "Unknown error")}
+
+
}
>
- {(data) => props.children(data)}
+
+
+
+
+ }
+ >
+ {(data) => props.children(data)}
+
)
}
diff --git a/packages/opencode/package.json b/packages/opencode/package.json
index ff768f55a7..23e00fe707 100644
--- a/packages/opencode/package.json
+++ b/packages/opencode/package.json
@@ -80,15 +80,13 @@
"@gitlab/opencode-gitlab-auth": "1.3.3",
"@hono/standard-validator": "0.1.5",
"@hono/zod-validator": "catalog:",
- "@kilocode/kilo-gateway": "workspace:*",
- "@kilocode/kilo-telemetry": "workspace:*",
- "@kilocode/plugin": "workspace:*",
- "@kilocode/sdk": "workspace:*",
"@modelcontextprotocol/sdk": "1.25.2",
"@octokit/graphql": "9.0.2",
"@octokit/rest": "catalog:",
"@openauthjs/openauth": "catalog:",
+ "@kilocode/plugin": "workspace:*",
"@opencode-ai/script": "workspace:*",
+ "@kilocode/sdk": "workspace:*",
"@opencode-ai/util": "workspace:*",
"@openrouter/ai-sdk-provider": "1.5.4",
"@opentui/core": "0.1.79",
@@ -122,7 +120,6 @@
"opentui-spinner": "0.0.6",
"partial-json": "0.1.7",
"remeda": "catalog:",
- "simple-git": "3.31.1",
"solid-js": "catalog:",
"strip-ansi": "7.1.2",
"tree-sitter-bash": "0.25.0",
@@ -133,7 +130,10 @@
"xdg-basedir": "5.1.0",
"yargs": "18.0.0",
"zod": "catalog:",
- "zod-to-json-schema": "3.24.5"
+ "zod-to-json-schema": "3.24.5",
+ "@kilocode/kilo-gateway": "workspace:*",
+ "@kilocode/kilo-telemetry": "workspace:*",
+ "simple-git": "3.31.1"
},
"overrides": {
"drizzle-orm": "1.0.0-beta.12-a5629fb"
diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx
index 299d515ed3..4910b1d41d 100644
--- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx
+++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx
@@ -100,6 +100,7 @@ const context = createContext<{
showThinking: () => boolean
showTimestamps: () => boolean
showDetails: () => boolean
+ showGenericToolOutput: () => boolean
diffWrapMode: () => "word" | "none"
sync: ReturnType
}>()
@@ -154,6 +155,7 @@ export function Session() {
const [showHeader, setShowHeader] = kv.signal("header_visible", true)
const [diffWrapMode] = kv.signal<"word" | "none">("diff_wrap_mode", "word")
const [animationsEnabled, setAnimationsEnabled] = kv.signal("animations_enabled", true)
+ const [showGenericToolOutput, setShowGenericToolOutput] = kv.signal("generic_tool_output_visibility", false)
const wide = createMemo(() => dimensions().width > 120)
const sidebarVisible = createMemo(() => {
@@ -606,6 +608,15 @@ export function Session() {
dialog.clear()
},
},
+ {
+ title: showGenericToolOutput() ? "Hide generic tool output" : "Show generic tool output",
+ value: "session.toggle.generic_tool_output",
+ category: "Session",
+ onSelect: (dialog) => {
+ setShowGenericToolOutput((prev) => !prev)
+ dialog.clear()
+ },
+ },
{
title: "Page up",
value: "session.page.up",
@@ -980,6 +991,7 @@ export function Session() {
showThinking,
showTimestamps,
showDetails,
+ showGenericToolOutput,
diffWrapMode,
sync,
}}
@@ -1517,10 +1529,40 @@ type ToolProps = {
part: ToolPart
}
function GenericTool(props: ToolProps) {
+ const { theme } = useTheme()
+ const ctx = use()
+ const output = createMemo(() => props.output?.trim() ?? "")
+ const [expanded, setExpanded] = createSignal(false)
+ const lines = createMemo(() => output().split("\n"))
+ const maxLines = 3
+ const overflow = createMemo(() => lines().length > maxLines)
+ const limited = createMemo(() => {
+ if (expanded() || !overflow()) return output()
+ return [...lines().slice(0, maxLines), "…"].join("\n")
+ })
+
return (
-
- {props.tool} {input(props.input)}
-
+
+ {props.tool} {input(props.input)}
+
+ }
+ >
+ setExpanded((prev) => !prev) : undefined}
+ >
+
+ {limited()}
+
+ {expanded() ? "Click to collapse" : "Click to expand"}
+
+
+
+
)
}
diff --git a/packages/opencode/src/provider/transform.ts b/packages/opencode/src/provider/transform.ts
index 146d14e2d0..7f6c44b858 100644
--- a/packages/opencode/src/provider/transform.ts
+++ b/packages/opencode/src/provider/transform.ts
@@ -349,6 +349,10 @@ export namespace ProviderTransform {
if (!model.capabilities.reasoning) return {}
const id = model.id.toLowerCase()
+ const isAnthropicAdaptive = ["opus-4-6", "opus-4.6", "sonnet-4-6", "sonnet-4.6"].some((v) =>
+ model.api.id.includes(v),
+ )
+ const adaptiveEfforts = ["low", "medium", "high", "max"]
if (
id.includes("deepseek") ||
id.includes("minimax") ||
@@ -401,6 +405,19 @@ export namespace ProviderTransform {
// TODO: YOU CANNOT SET max_tokens if this is set!!!
case "@ai-sdk/gateway":
if (model.id.includes("anthropic")) {
+ if (isAnthropicAdaptive) {
+ return Object.fromEntries(
+ adaptiveEfforts.map((effort) => [
+ effort,
+ {
+ thinking: {
+ type: "adaptive",
+ },
+ effort,
+ },
+ ]),
+ )
+ }
return {
high: {
thinking: {
@@ -537,10 +554,9 @@ export namespace ProviderTransform {
case "@ai-sdk/google-vertex/anthropic":
// https://v5.ai-sdk.dev/providers/ai-sdk-providers/google-vertex#anthropic-provider
- if (model.api.id.includes("opus-4-6") || model.api.id.includes("opus-4.6")) {
- const efforts = ["low", "medium", "high", "max"]
+ if (isAnthropicAdaptive) {
return Object.fromEntries(
- efforts.map((effort) => [
+ adaptiveEfforts.map((effort) => [
effort,
{
thinking: {
@@ -569,10 +585,9 @@ export namespace ProviderTransform {
case "@ai-sdk/amazon-bedrock":
// https://v5.ai-sdk.dev/providers/ai-sdk-providers/amazon-bedrock
- if (model.api.id.includes("opus-4-6") || model.api.id.includes("opus-4.6")) {
- const efforts = ["low", "medium", "high", "max"]
+ if (isAnthropicAdaptive) {
return Object.fromEntries(
- efforts.map((effort) => [
+ adaptiveEfforts.map((effort) => [
effort,
{
reasoningConfig: {
diff --git a/packages/opencode/test/provider/transform.test.ts b/packages/opencode/test/provider/transform.test.ts
index 8e7b08a65b..c18698e5a3 100644
--- a/packages/opencode/test/provider/transform.test.ts
+++ b/packages/opencode/test/provider/transform.test.ts
@@ -1022,79 +1022,6 @@ describe("ProviderTransform.message - anthropic empty content filtering", () =>
})
})
-describe("ProviderTransform.message - OpenRouter/Kilo Gateway thinking stripping", () => {
- const claudeViaGateway = {
- id: "openrouter/anthropic/claude-3-5-sonnet",
- providerID: "openrouter",
- api: {
- id: "anthropic/claude-3-5-sonnet",
- url: "https://openrouter.ai",
- npm: "@kilocode/kilo-gateway",
- },
- name: "Claude 3.5 Sonnet (Gateway)",
- capabilities: {
- temperature: true,
- reasoning: true,
- attachment: true,
- toolcall: true,
- input: { text: true, audio: false, image: true, video: false, pdf: true },
- output: { text: true, audio: false, image: false, video: false, pdf: false },
- interleaved: false,
- },
- cost: {
- input: 0,
- output: 0,
- cache: { read: 0, write: 0 },
- },
- limit: {
- context: 200000,
- output: 8192,
- },
- status: "active",
- options: {},
- headers: {},
- } as any
-
- test("drops messages that become empty after stripping thinking/reasoning", () => {
- const msgs = [
- { role: "user", content: "Hello" },
- {
- role: "assistant",
- content: [{ type: "thinking", text: "..." }, { type: "reasoning", text: "..." }, { type: "redacted_thinking" }],
- },
- { role: "user", content: "World" },
- ] as any[]
-
- const result = ProviderTransform.message(msgs, claudeViaGateway, {})
-
- expect(result).toHaveLength(2)
- expect(result[0].content).toBe("Hello")
- expect(result[1].content).toBe("World")
- })
-
- test("keeps messages that still contain supported parts after stripping", () => {
- const msgs = [
- {
- role: "assistant",
- content: [
- { type: "thinking", text: "..." },
- { type: "text", text: "Answer" },
- ],
- },
- ] as any[]
-
- const result = ProviderTransform.message(msgs, claudeViaGateway, {})
-
- expect(result).toHaveLength(1)
- expect(result[0].content).toHaveLength(1)
- // applyCaching adds providerOptions because model.api.id includes "anthropic"
- const part = result[0].content[0] as any
- expect(part.type).toEqual("text")
- expect(part.text).toEqual("Answer")
- expect(part.providerOptions?.openrouter?.cacheControl).toEqual({ type: "ephemeral" })
- })
-})
-
describe("ProviderTransform.message - strip openai metadata when store=false", () => {
const openaiModel = {
id: "openai/gpt-5",
@@ -1637,746 +1564,902 @@ describe("ProviderTransform.variants", () => {
...overrides,
})
- describe("ProviderTransform.variants", () => {
- test("returns empty object when model has no reasoning capabilities", () => {
- const model = createMockModel({
- capabilities: { reasoning: false },
- })
- const result = ProviderTransform.variants(model)
- expect(result).toEqual({})
+ test("returns empty object when model has no reasoning capabilities", () => {
+ const model = createMockModel({
+ capabilities: { reasoning: false },
})
+ const result = ProviderTransform.variants(model)
+ expect(result).toEqual({})
+ })
- test("deepseek returns empty object", () => {
+ test("deepseek returns empty object", () => {
+ const model = createMockModel({
+ id: "deepseek/deepseek-chat",
+ providerID: "deepseek",
+ api: {
+ id: "deepseek-chat",
+ url: "https://api.deepseek.com",
+ npm: "@ai-sdk/openai-compatible",
+ },
+ })
+ const result = ProviderTransform.variants(model)
+ expect(result).toEqual({})
+ })
+
+ test("minimax returns empty object", () => {
+ const model = createMockModel({
+ id: "minimax/minimax-model",
+ providerID: "minimax",
+ api: {
+ id: "minimax-model",
+ url: "https://api.minimax.com",
+ npm: "@ai-sdk/openai-compatible",
+ },
+ })
+ const result = ProviderTransform.variants(model)
+ expect(result).toEqual({})
+ })
+
+ test("glm returns empty object", () => {
+ const model = createMockModel({
+ id: "glm/glm-4",
+ providerID: "glm",
+ api: {
+ id: "glm-4",
+ url: "https://api.glm.com",
+ npm: "@ai-sdk/openai-compatible",
+ },
+ })
+ const result = ProviderTransform.variants(model)
+ expect(result).toEqual({})
+ })
+
+ test("mistral returns empty object", () => {
+ const model = createMockModel({
+ id: "mistral/mistral-large",
+ providerID: "mistral",
+ api: {
+ id: "mistral-large-latest",
+ url: "https://api.mistral.com",
+ npm: "@ai-sdk/mistral",
+ },
+ })
+ const result = ProviderTransform.variants(model)
+ expect(result).toEqual({})
+ })
+
+ describe("@openrouter/ai-sdk-provider", () => {
+ test("returns empty object for non-qualifying models", () => {
const model = createMockModel({
- id: "deepseek/deepseek-chat",
- providerID: "deepseek",
+ id: "openrouter/test-model",
+ providerID: "openrouter",
api: {
- id: "deepseek-chat",
- url: "https://api.deepseek.com",
- npm: "@ai-sdk/openai-compatible",
+ id: "test-model",
+ url: "https://openrouter.ai",
+ npm: "@openrouter/ai-sdk-provider",
},
})
const result = ProviderTransform.variants(model)
expect(result).toEqual({})
})
- test("minimax returns empty object", () => {
+ test("gpt models return OPENAI_EFFORTS with reasoning", () => {
const model = createMockModel({
- id: "minimax/minimax-model",
- providerID: "minimax",
+ id: "openrouter/gpt-4",
+ providerID: "openrouter",
api: {
- id: "minimax-model",
- url: "https://api.minimax.com",
- npm: "@ai-sdk/openai-compatible",
+ id: "gpt-4",
+ url: "https://openrouter.ai",
+ npm: "@openrouter/ai-sdk-provider",
+ },
+ })
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual(["none", "minimal", "low", "medium", "high", "xhigh"])
+ expect(result.low).toEqual({ reasoning: { effort: "low" } })
+ expect(result.high).toEqual({ reasoning: { effort: "high" } })
+ })
+
+ test("gemini-3 returns OPENAI_EFFORTS with reasoning", () => {
+ const model = createMockModel({
+ id: "openrouter/gemini-3-5-pro",
+ providerID: "openrouter",
+ api: {
+ id: "gemini-3-5-pro",
+ url: "https://openrouter.ai",
+ npm: "@openrouter/ai-sdk-provider",
+ },
+ })
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual(["none", "minimal", "low", "medium", "high", "xhigh"])
+ })
+
+ test("grok-4 returns empty object", () => {
+ const model = createMockModel({
+ id: "openrouter/grok-4",
+ providerID: "openrouter",
+ api: {
+ id: "grok-4",
+ url: "https://openrouter.ai",
+ npm: "@openrouter/ai-sdk-provider",
},
})
const result = ProviderTransform.variants(model)
expect(result).toEqual({})
})
- test("glm returns empty object", () => {
+ test("grok-3-mini returns low and high with reasoning", () => {
const model = createMockModel({
- id: "glm/glm-4",
- providerID: "glm",
+ id: "openrouter/grok-3-mini",
+ providerID: "openrouter",
api: {
- id: "glm-4",
- url: "https://api.glm.com",
- npm: "@ai-sdk/openai-compatible",
+ id: "grok-3-mini",
+ url: "https://openrouter.ai",
+ npm: "@openrouter/ai-sdk-provider",
},
})
const result = ProviderTransform.variants(model)
- expect(result).toEqual({})
+ expect(Object.keys(result)).toEqual(["low", "high"])
+ expect(result.low).toEqual({ reasoning: { effort: "low" } })
+ expect(result.high).toEqual({ reasoning: { effort: "high" } })
})
+ })
- test("mistral returns empty object", () => {
+ // kilocode_change start
+ describe("@kilocode/kilo-gateway", () => {
+ test("claude models return empty variants (reasoning disabled)", () => {
const model = createMockModel({
- id: "mistral/mistral-large",
- providerID: "mistral",
+ id: "kilo/anthropic/claude-sonnet-4",
+ providerID: "kilo",
api: {
- id: "mistral-large-latest",
- url: "https://api.mistral.com",
- npm: "@ai-sdk/mistral",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(result).toEqual({})
- })
-
- describe("@openrouter/ai-sdk-provider", () => {
- test("returns empty object for non-qualifying models", () => {
- const model = createMockModel({
- id: "openrouter/test-model",
- providerID: "openrouter",
- api: {
- id: "test-model",
- url: "https://openrouter.ai",
- npm: "@openrouter/ai-sdk-provider",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(result).toEqual({})
- })
-
- test("gpt models return OPENAI_EFFORTS with reasoning", () => {
- const model = createMockModel({
- id: "openrouter/gpt-4",
- providerID: "openrouter",
- api: {
- id: "gpt-4",
- url: "https://openrouter.ai",
- npm: "@openrouter/ai-sdk-provider",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(Object.keys(result)).toEqual(["none", "minimal", "low", "medium", "high", "xhigh"])
- expect(result.low).toEqual({ reasoning: { effort: "low" } })
- expect(result.high).toEqual({ reasoning: { effort: "high" } })
- })
-
- test("gemini-3 returns OPENAI_EFFORTS with reasoning", () => {
- const model = createMockModel({
- id: "openrouter/gemini-3-5-pro",
- providerID: "openrouter",
- api: {
- id: "gemini-3-5-pro",
- url: "https://openrouter.ai",
- npm: "@openrouter/ai-sdk-provider",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(Object.keys(result)).toEqual(["none", "minimal", "low", "medium", "high", "xhigh"])
- })
-
- test("grok-4 returns empty object", () => {
- const model = createMockModel({
- id: "openrouter/grok-4",
- providerID: "openrouter",
- api: {
- id: "grok-4",
- url: "https://openrouter.ai",
- npm: "@openrouter/ai-sdk-provider",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(result).toEqual({})
- })
-
- test("grok-3-mini returns low and high with reasoning", () => {
- const model = createMockModel({
- id: "openrouter/grok-3-mini",
- providerID: "openrouter",
- api: {
- id: "grok-3-mini",
- url: "https://openrouter.ai",
- npm: "@openrouter/ai-sdk-provider",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(Object.keys(result)).toEqual(["low", "high"])
- expect(result.low).toEqual({ reasoning: { effort: "low" } })
- expect(result.high).toEqual({ reasoning: { effort: "high" } })
- })
- })
-
- // kilocode_change start
- describe("@kilocode/kilo-gateway", () => {
- test("claude models return empty variants (reasoning disabled)", () => {
- const model = createMockModel({
- id: "kilo/anthropic/claude-sonnet-4",
- providerID: "kilo",
- api: {
- id: "anthropic/claude-sonnet-4",
- url: "https://gateway.kilo.ai",
- npm: "@kilocode/kilo-gateway",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(Object.keys(result)).toEqual([])
- })
-
- test("anthropic models in api.id return empty variants (reasoning disabled)", () => {
- const model = createMockModel({
- id: "kilo/anthropic/claude-opus-4",
- providerID: "kilo",
- api: {
- id: "anthropic/claude-opus-4",
- url: "https://gateway.kilo.ai",
- npm: "@kilocode/kilo-gateway",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(Object.keys(result)).toEqual([])
- })
-
- test("gpt models return OPENAI_EFFORTS with reasoning and encrypted content", () => {
- const model = createMockModel({
- id: "kilo/openai/gpt-5",
- providerID: "kilo",
- api: {
- id: "openai/gpt-5",
- url: "https://gateway.kilo.ai",
- npm: "@kilocode/kilo-gateway",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(Object.keys(result)).toEqual(["none", "minimal", "low", "medium", "high", "xhigh"])
- expect(result.low).toEqual({
- reasoningEffort: "low",
- reasoningSummary: "auto",
- include: ["reasoning.encrypted_content"],
- })
- })
-
- test("gemini-3 models return OPENAI_EFFORTS with reasoning and encrypted content", () => {
- const model = createMockModel({
- id: "kilo/google/gemini-3-pro",
- providerID: "kilo",
- api: {
- id: "google/gemini-3-pro",
- url: "https://gateway.kilo.ai",
- npm: "@kilocode/kilo-gateway",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(Object.keys(result)).toEqual(["none", "minimal", "low", "medium", "high", "xhigh"])
- })
-
- test("non-qualifying models return empty object", () => {
- const model = createMockModel({
- id: "kilo/meta/llama-4",
- providerID: "kilo",
- api: {
- id: "meta/llama-4",
- url: "https://gateway.kilo.ai",
- npm: "@kilocode/kilo-gateway",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(result).toEqual({})
- })
-
- test("grok-3-mini returns low and high with reasoning", () => {
- const model = createMockModel({
- id: "kilo/x-ai/grok-3-mini",
- providerID: "kilo",
- api: {
- id: "x-ai/grok-3-mini",
- url: "https://gateway.kilo.ai",
- npm: "@kilocode/kilo-gateway",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(Object.keys(result)).toEqual(["low", "high"])
- expect(result.low).toEqual({ reasoning: { effort: "low" } })
- expect(result.high).toEqual({ reasoning: { effort: "high" } })
- })
-
- test("codex models return OPENAI_EFFORTS with object-based reasoning format", () => {
- const model = createMockModel({
- id: "kilo/openai/gpt-5.2-codex",
- providerID: "kilo",
- api: {
- id: "openai/gpt-5.2-codex",
- url: "https://gateway.kilo.ai",
- npm: "@kilocode/kilo-gateway",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(Object.keys(result)).toEqual(["none", "minimal", "low", "medium", "high", "xhigh"])
- expect(result.low).toEqual({ reasoning: { effort: "low" } })
- expect(result.high).toEqual({ reasoning: { effort: "high" } })
- expect(result.xhigh).toEqual({ reasoning: { effort: "xhigh" } })
- })
- })
- // kilocode_change end
-
- describe("@ai-sdk/gateway", () => {
- test("anthropic models return anthropic thinking options", () => {
- const model = createMockModel({
id: "anthropic/claude-sonnet-4",
- providerID: "gateway",
- api: {
- id: "anthropic/claude-sonnet-4",
- url: "https://gateway.ai",
- npm: "@ai-sdk/gateway",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(Object.keys(result)).toEqual(["high", "max"])
- expect(result.high).toEqual({
- thinking: {
- type: "enabled",
- budgetTokens: 16000,
- },
- })
- expect(result.max).toEqual({
- thinking: {
- type: "enabled",
- budgetTokens: 31999,
- },
- })
+ url: "https://gateway.kilo.ai",
+ npm: "@kilocode/kilo-gateway",
+ },
})
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual([])
+ })
- test("returns OPENAI_EFFORTS with reasoningEffort", () => {
- const model = createMockModel({
- id: "gateway/gateway-model",
- providerID: "gateway",
- api: {
- id: "gateway-model",
- url: "https://gateway.ai",
- npm: "@ai-sdk/gateway",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(Object.keys(result)).toEqual(["none", "minimal", "low", "medium", "high", "xhigh"])
- expect(result.low).toEqual({ reasoningEffort: "low" })
- expect(result.high).toEqual({ reasoningEffort: "high" })
+ test("anthropic models in api.id return empty variants (reasoning disabled)", () => {
+ const model = createMockModel({
+ id: "kilo/anthropic/claude-opus-4",
+ providerID: "kilo",
+ api: {
+ id: "anthropic/claude-opus-4",
+ url: "https://gateway.kilo.ai",
+ npm: "@kilocode/kilo-gateway",
+ },
+ })
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual([])
+ })
+
+ test("gpt models return OPENAI_EFFORTS with reasoning and encrypted content", () => {
+ const model = createMockModel({
+ id: "kilo/openai/gpt-5",
+ providerID: "kilo",
+ api: {
+ id: "openai/gpt-5",
+ url: "https://gateway.kilo.ai",
+ npm: "@kilocode/kilo-gateway",
+ },
+ })
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual(["none", "minimal", "low", "medium", "high", "xhigh"])
+ expect(result.low).toEqual({
+ reasoningEffort: "low",
+ reasoningSummary: "auto",
+ include: ["reasoning.encrypted_content"],
})
})
- describe("@ai-sdk/github-copilot", () => {
- test("standard models return low, medium, high", () => {
- const model = createMockModel({
+ test("gemini-3 models return OPENAI_EFFORTS with reasoning and encrypted content", () => {
+ const model = createMockModel({
+ id: "kilo/google/gemini-3-pro",
+ providerID: "kilo",
+ api: {
+ id: "google/gemini-3-pro",
+ url: "https://gateway.kilo.ai",
+ npm: "@kilocode/kilo-gateway",
+ },
+ })
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual(["none", "minimal", "low", "medium", "high", "xhigh"])
+ })
+
+ test("non-qualifying models return empty object", () => {
+ const model = createMockModel({
+ id: "kilo/meta/llama-4",
+ providerID: "kilo",
+ api: {
+ id: "meta/llama-4",
+ url: "https://gateway.kilo.ai",
+ npm: "@kilocode/kilo-gateway",
+ },
+ })
+ const result = ProviderTransform.variants(model)
+ expect(result).toEqual({})
+ })
+
+ test("grok-3-mini returns low and high with reasoning", () => {
+ const model = createMockModel({
+ id: "kilo/x-ai/grok-3-mini",
+ providerID: "kilo",
+ api: {
+ id: "x-ai/grok-3-mini",
+ url: "https://gateway.kilo.ai",
+ npm: "@kilocode/kilo-gateway",
+ },
+ })
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual(["low", "high"])
+ expect(result.low).toEqual({ reasoning: { effort: "low" } })
+ expect(result.high).toEqual({ reasoning: { effort: "high" } })
+ })
+
+ test("codex models return OPENAI_EFFORTS with object-based reasoning format", () => {
+ const model = createMockModel({
+ id: "kilo/openai/gpt-5.2-codex",
+ providerID: "kilo",
+ api: {
+ id: "openai/gpt-5.2-codex",
+ url: "https://gateway.kilo.ai",
+ npm: "@kilocode/kilo-gateway",
+ },
+ })
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual(["none", "minimal", "low", "medium", "high", "xhigh"])
+ expect(result.low).toEqual({ reasoning: { effort: "low" } })
+ expect(result.high).toEqual({ reasoning: { effort: "high" } })
+ expect(result.xhigh).toEqual({ reasoning: { effort: "xhigh" } })
+ })
+ })
+ // kilocode_change end
+
+ describe("@ai-sdk/gateway", () => {
+ test("anthropic sonnet 4.6 models return adaptive thinking options", () => {
+ const model = createMockModel({
+ id: "anthropic/claude-sonnet-4-6",
+ providerID: "gateway",
+ api: {
+ id: "anthropic/claude-sonnet-4-6",
+ url: "https://gateway.ai",
+ npm: "@ai-sdk/gateway",
+ },
+ })
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual(["low", "medium", "high", "max"])
+ expect(result.medium).toEqual({
+ thinking: {
+ type: "adaptive",
+ },
+ effort: "medium",
+ })
+ })
+
+ test("anthropic sonnet 4.6 dot-format models return adaptive thinking options", () => {
+ const model = createMockModel({
+ id: "anthropic/claude-sonnet-4-6",
+ providerID: "gateway",
+ api: {
+ id: "anthropic/claude-sonnet-4.6",
+ url: "https://gateway.ai",
+ npm: "@ai-sdk/gateway",
+ },
+ })
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual(["low", "medium", "high", "max"])
+ expect(result.medium).toEqual({
+ thinking: {
+ type: "adaptive",
+ },
+ effort: "medium",
+ })
+ })
+
+ test("anthropic opus 4.6 dot-format models return adaptive thinking options", () => {
+ const model = createMockModel({
+ id: "anthropic/claude-opus-4-6",
+ providerID: "gateway",
+ api: {
+ id: "anthropic/claude-opus-4.6",
+ url: "https://gateway.ai",
+ npm: "@ai-sdk/gateway",
+ },
+ })
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual(["low", "medium", "high", "max"])
+ expect(result.high).toEqual({
+ thinking: {
+ type: "adaptive",
+ },
+ effort: "high",
+ })
+ })
+
+ test("anthropic models return anthropic thinking options", () => {
+ const model = createMockModel({
+ id: "anthropic/claude-sonnet-4",
+ providerID: "gateway",
+ api: {
+ id: "anthropic/claude-sonnet-4",
+ url: "https://gateway.ai",
+ npm: "@ai-sdk/gateway",
+ },
+ })
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual(["high", "max"])
+ expect(result.high).toEqual({
+ thinking: {
+ type: "enabled",
+ budgetTokens: 16000,
+ },
+ })
+ expect(result.max).toEqual({
+ thinking: {
+ type: "enabled",
+ budgetTokens: 31999,
+ },
+ })
+ })
+
+ test("returns OPENAI_EFFORTS with reasoningEffort", () => {
+ const model = createMockModel({
+ id: "gateway/gateway-model",
+ providerID: "gateway",
+ api: {
+ id: "gateway-model",
+ url: "https://gateway.ai",
+ npm: "@ai-sdk/gateway",
+ },
+ })
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual(["none", "minimal", "low", "medium", "high", "xhigh"])
+ expect(result.low).toEqual({ reasoningEffort: "low" })
+ expect(result.high).toEqual({ reasoningEffort: "high" })
+ })
+ })
+
+ describe("@ai-sdk/github-copilot", () => {
+ test("standard models return low, medium, high", () => {
+ const model = createMockModel({
+ id: "gpt-4.5",
+ providerID: "github-copilot",
+ api: {
id: "gpt-4.5",
- providerID: "github-copilot",
- api: {
- id: "gpt-4.5",
- url: "https://api.githubcopilot.com",
- npm: "@ai-sdk/github-copilot",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(Object.keys(result)).toEqual(["low", "medium", "high"])
- expect(result.low).toEqual({
- reasoningEffort: "low",
- reasoningSummary: "auto",
- include: ["reasoning.encrypted_content"],
- })
+ url: "https://api.githubcopilot.com",
+ npm: "@ai-sdk/github-copilot",
+ },
})
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual(["low", "medium", "high"])
+ expect(result.low).toEqual({
+ reasoningEffort: "low",
+ reasoningSummary: "auto",
+ include: ["reasoning.encrypted_content"],
+ })
+ })
- test("gpt-5.1-codex-max includes xhigh", () => {
- const model = createMockModel({
+ test("gpt-5.1-codex-max includes xhigh", () => {
+ const model = createMockModel({
+ id: "gpt-5.1-codex-max",
+ providerID: "github-copilot",
+ api: {
id: "gpt-5.1-codex-max",
- providerID: "github-copilot",
- api: {
- id: "gpt-5.1-codex-max",
- url: "https://api.githubcopilot.com",
- npm: "@ai-sdk/github-copilot",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(Object.keys(result)).toEqual(["low", "medium", "high", "xhigh"])
+ url: "https://api.githubcopilot.com",
+ npm: "@ai-sdk/github-copilot",
+ },
})
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual(["low", "medium", "high", "xhigh"])
+ })
- test("gpt-5.1-codex-mini does not include xhigh", () => {
- const model = createMockModel({
+ test("gpt-5.1-codex-mini does not include xhigh", () => {
+ const model = createMockModel({
+ id: "gpt-5.1-codex-mini",
+ providerID: "github-copilot",
+ api: {
id: "gpt-5.1-codex-mini",
- providerID: "github-copilot",
- api: {
- id: "gpt-5.1-codex-mini",
- url: "https://api.githubcopilot.com",
- npm: "@ai-sdk/github-copilot",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(Object.keys(result)).toEqual(["low", "medium", "high"])
+ url: "https://api.githubcopilot.com",
+ npm: "@ai-sdk/github-copilot",
+ },
})
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual(["low", "medium", "high"])
+ })
- test("gpt-5.1-codex does not include xhigh", () => {
- const model = createMockModel({
+ test("gpt-5.1-codex does not include xhigh", () => {
+ const model = createMockModel({
+ id: "gpt-5.1-codex",
+ providerID: "github-copilot",
+ api: {
id: "gpt-5.1-codex",
- providerID: "github-copilot",
- api: {
- id: "gpt-5.1-codex",
- url: "https://api.githubcopilot.com",
- npm: "@ai-sdk/github-copilot",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(Object.keys(result)).toEqual(["low", "medium", "high"])
+ url: "https://api.githubcopilot.com",
+ npm: "@ai-sdk/github-copilot",
+ },
})
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual(["low", "medium", "high"])
+ })
- test("gpt-5.2 includes xhigh", () => {
- const model = createMockModel({
+ test("gpt-5.2 includes xhigh", () => {
+ const model = createMockModel({
+ id: "gpt-5.2",
+ providerID: "github-copilot",
+ api: {
id: "gpt-5.2",
- providerID: "github-copilot",
- api: {
- id: "gpt-5.2",
- url: "https://api.githubcopilot.com",
- npm: "@ai-sdk/github-copilot",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(Object.keys(result)).toEqual(["low", "medium", "high", "xhigh"])
- expect(result.xhigh).toEqual({
- reasoningEffort: "xhigh",
- reasoningSummary: "auto",
- include: ["reasoning.encrypted_content"],
- })
+ url: "https://api.githubcopilot.com",
+ npm: "@ai-sdk/github-copilot",
+ },
})
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual(["low", "medium", "high", "xhigh"])
+ expect(result.xhigh).toEqual({
+ reasoningEffort: "xhigh",
+ reasoningSummary: "auto",
+ include: ["reasoning.encrypted_content"],
+ })
+ })
- test("gpt-5.2-codex includes xhigh", () => {
- const model = createMockModel({
+ test("gpt-5.2-codex includes xhigh", () => {
+ const model = createMockModel({
+ id: "gpt-5.2-codex",
+ providerID: "github-copilot",
+ api: {
id: "gpt-5.2-codex",
- providerID: "github-copilot",
- api: {
- id: "gpt-5.2-codex",
- url: "https://api.githubcopilot.com",
- npm: "@ai-sdk/github-copilot",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(Object.keys(result)).toEqual(["low", "medium", "high", "xhigh"])
+ url: "https://api.githubcopilot.com",
+ npm: "@ai-sdk/github-copilot",
+ },
})
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual(["low", "medium", "high", "xhigh"])
+ })
+ })
+
+ describe("@ai-sdk/cerebras", () => {
+ test("returns WIDELY_SUPPORTED_EFFORTS with reasoningEffort", () => {
+ const model = createMockModel({
+ id: "cerebras/llama-4",
+ providerID: "cerebras",
+ api: {
+ id: "llama-4-sc",
+ url: "https://api.cerebras.ai",
+ npm: "@ai-sdk/cerebras",
+ },
+ })
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual(["low", "medium", "high"])
+ expect(result.low).toEqual({ reasoningEffort: "low" })
+ expect(result.high).toEqual({ reasoningEffort: "high" })
+ })
+ })
+
+ describe("@ai-sdk/togetherai", () => {
+ test("returns WIDELY_SUPPORTED_EFFORTS with reasoningEffort", () => {
+ const model = createMockModel({
+ id: "togetherai/llama-4",
+ providerID: "togetherai",
+ api: {
+ id: "llama-4-sc",
+ url: "https://api.togetherai.com",
+ npm: "@ai-sdk/togetherai",
+ },
+ })
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual(["low", "medium", "high"])
+ expect(result.low).toEqual({ reasoningEffort: "low" })
+ expect(result.high).toEqual({ reasoningEffort: "high" })
+ })
+ })
+
+ describe("@ai-sdk/xai", () => {
+ test("grok-3 returns empty object", () => {
+ const model = createMockModel({
+ id: "xai/grok-3",
+ providerID: "xai",
+ api: {
+ id: "grok-3",
+ url: "https://api.x.ai",
+ npm: "@ai-sdk/xai",
+ },
+ })
+ const result = ProviderTransform.variants(model)
+ expect(result).toEqual({})
})
- describe("@ai-sdk/cerebras", () => {
- test("returns WIDELY_SUPPORTED_EFFORTS with reasoningEffort", () => {
- const model = createMockModel({
- id: "cerebras/llama-4",
- providerID: "cerebras",
- api: {
- id: "llama-4-sc",
- url: "https://api.cerebras.ai",
- npm: "@ai-sdk/cerebras",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(Object.keys(result)).toEqual(["low", "medium", "high"])
- expect(result.low).toEqual({ reasoningEffort: "low" })
- expect(result.high).toEqual({ reasoningEffort: "high" })
+ test("grok-3-mini returns low and high with reasoningEffort", () => {
+ const model = createMockModel({
+ id: "xai/grok-3-mini",
+ providerID: "xai",
+ api: {
+ id: "grok-3-mini",
+ url: "https://api.x.ai",
+ npm: "@ai-sdk/xai",
+ },
})
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual(["low", "high"])
+ expect(result.low).toEqual({ reasoningEffort: "low" })
+ expect(result.high).toEqual({ reasoningEffort: "high" })
})
+ })
- describe("@ai-sdk/togetherai", () => {
- test("returns WIDELY_SUPPORTED_EFFORTS with reasoningEffort", () => {
- const model = createMockModel({
- id: "togetherai/llama-4",
- providerID: "togetherai",
- api: {
- id: "llama-4-sc",
- url: "https://api.togetherai.com",
- npm: "@ai-sdk/togetherai",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(Object.keys(result)).toEqual(["low", "medium", "high"])
- expect(result.low).toEqual({ reasoningEffort: "low" })
- expect(result.high).toEqual({ reasoningEffort: "high" })
+ describe("@ai-sdk/deepinfra", () => {
+ test("returns WIDELY_SUPPORTED_EFFORTS with reasoningEffort", () => {
+ const model = createMockModel({
+ id: "deepinfra/llama-4",
+ providerID: "deepinfra",
+ api: {
+ id: "llama-4-sc",
+ url: "https://api.deepinfra.com",
+ npm: "@ai-sdk/deepinfra",
+ },
})
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual(["low", "medium", "high"])
+ expect(result.low).toEqual({ reasoningEffort: "low" })
+ expect(result.high).toEqual({ reasoningEffort: "high" })
})
+ })
- describe("@ai-sdk/xai", () => {
- test("grok-3 returns empty object", () => {
- const model = createMockModel({
- id: "xai/grok-3",
- providerID: "xai",
- api: {
- id: "grok-3",
- url: "https://api.x.ai",
- npm: "@ai-sdk/xai",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(result).toEqual({})
- })
-
- test("grok-3-mini returns low and high with reasoningEffort", () => {
- const model = createMockModel({
- id: "xai/grok-3-mini",
- providerID: "xai",
- api: {
- id: "grok-3-mini",
- url: "https://api.x.ai",
- npm: "@ai-sdk/xai",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(Object.keys(result)).toEqual(["low", "high"])
- expect(result.low).toEqual({ reasoningEffort: "low" })
- expect(result.high).toEqual({ reasoningEffort: "high" })
+ describe("@ai-sdk/openai-compatible", () => {
+ test("returns WIDELY_SUPPORTED_EFFORTS with reasoningEffort", () => {
+ const model = createMockModel({
+ id: "custom-provider/custom-model",
+ providerID: "custom-provider",
+ api: {
+ id: "custom-model",
+ url: "https://api.custom.com",
+ npm: "@ai-sdk/openai-compatible",
+ },
})
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual(["low", "medium", "high"])
+ expect(result.low).toEqual({ reasoningEffort: "low" })
+ expect(result.high).toEqual({ reasoningEffort: "high" })
})
+ })
- describe("@ai-sdk/deepinfra", () => {
- test("returns WIDELY_SUPPORTED_EFFORTS with reasoningEffort", () => {
- const model = createMockModel({
- id: "deepinfra/llama-4",
- providerID: "deepinfra",
- api: {
- id: "llama-4-sc",
- url: "https://api.deepinfra.com",
- npm: "@ai-sdk/deepinfra",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(Object.keys(result)).toEqual(["low", "medium", "high"])
- expect(result.low).toEqual({ reasoningEffort: "low" })
- expect(result.high).toEqual({ reasoningEffort: "high" })
- })
- })
-
- describe("@ai-sdk/openai-compatible", () => {
- test("returns WIDELY_SUPPORTED_EFFORTS with reasoningEffort", () => {
- const model = createMockModel({
- id: "custom-provider/custom-model",
- providerID: "custom-provider",
- api: {
- id: "custom-model",
- url: "https://api.custom.com",
- npm: "@ai-sdk/openai-compatible",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(Object.keys(result)).toEqual(["low", "medium", "high"])
- expect(result.low).toEqual({ reasoningEffort: "low" })
- expect(result.high).toEqual({ reasoningEffort: "high" })
- })
- })
-
- describe("@ai-sdk/azure", () => {
- test("o1-mini returns empty object", () => {
- const model = createMockModel({
+ describe("@ai-sdk/azure", () => {
+ test("o1-mini returns empty object", () => {
+ const model = createMockModel({
+ id: "o1-mini",
+ providerID: "azure",
+ api: {
id: "o1-mini",
- providerID: "azure",
- api: {
- id: "o1-mini",
- url: "https://azure.com",
- npm: "@ai-sdk/azure",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(result).toEqual({})
+ url: "https://azure.com",
+ npm: "@ai-sdk/azure",
+ },
})
+ const result = ProviderTransform.variants(model)
+ expect(result).toEqual({})
+ })
- test("standard azure models return custom efforts with reasoningSummary", () => {
- const model = createMockModel({
+ test("standard azure models return custom efforts with reasoningSummary", () => {
+ const model = createMockModel({
+ id: "o1",
+ providerID: "azure",
+ api: {
id: "o1",
- providerID: "azure",
- api: {
- id: "o1",
- url: "https://azure.com",
- npm: "@ai-sdk/azure",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(Object.keys(result)).toEqual(["low", "medium", "high"])
- expect(result.low).toEqual({
- reasoningEffort: "low",
- reasoningSummary: "auto",
- include: ["reasoning.encrypted_content"],
- })
+ url: "https://azure.com",
+ npm: "@ai-sdk/azure",
+ },
})
-
- test("gpt-5 adds minimal effort", () => {
- const model = createMockModel({
- id: "gpt-5",
- providerID: "azure",
- api: {
- id: "gpt-5",
- url: "https://azure.com",
- npm: "@ai-sdk/azure",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(Object.keys(result)).toEqual(["minimal", "low", "medium", "high"])
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual(["low", "medium", "high"])
+ expect(result.low).toEqual({
+ reasoningEffort: "low",
+ reasoningSummary: "auto",
+ include: ["reasoning.encrypted_content"],
})
})
- describe("@ai-sdk/openai", () => {
- test("gpt-5-pro returns empty object", () => {
- const model = createMockModel({
+ test("gpt-5 adds minimal effort", () => {
+ const model = createMockModel({
+ id: "gpt-5",
+ providerID: "azure",
+ api: {
+ id: "gpt-5",
+ url: "https://azure.com",
+ npm: "@ai-sdk/azure",
+ },
+ })
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual(["minimal", "low", "medium", "high"])
+ })
+ })
+
+ describe("@ai-sdk/openai", () => {
+ test("gpt-5-pro returns empty object", () => {
+ const model = createMockModel({
+ id: "gpt-5-pro",
+ providerID: "openai",
+ api: {
id: "gpt-5-pro",
- providerID: "openai",
- api: {
- id: "gpt-5-pro",
- url: "https://api.openai.com",
- npm: "@ai-sdk/openai",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(result).toEqual({})
+ url: "https://api.openai.com",
+ npm: "@ai-sdk/openai",
+ },
})
+ const result = ProviderTransform.variants(model)
+ expect(result).toEqual({})
+ })
- test("standard openai models return custom efforts with reasoningSummary", () => {
- const model = createMockModel({
+ test("standard openai models return custom efforts with reasoningSummary", () => {
+ const model = createMockModel({
+ id: "gpt-5",
+ providerID: "openai",
+ api: {
id: "gpt-5",
- providerID: "openai",
- api: {
- id: "gpt-5",
- url: "https://api.openai.com",
- npm: "@ai-sdk/openai",
- },
- release_date: "2024-06-01",
- })
- const result = ProviderTransform.variants(model)
- expect(Object.keys(result)).toEqual(["minimal", "low", "medium", "high"])
- expect(result.low).toEqual({
- reasoningEffort: "low",
- reasoningSummary: "auto",
- include: ["reasoning.encrypted_content"],
- })
+ url: "https://api.openai.com",
+ npm: "@ai-sdk/openai",
+ },
+ release_date: "2024-06-01",
})
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual(["minimal", "low", "medium", "high"])
+ expect(result.low).toEqual({
+ reasoningEffort: "low",
+ reasoningSummary: "auto",
+ include: ["reasoning.encrypted_content"],
+ })
+ })
- test("models after 2025-11-13 include 'none' effort", () => {
- const model = createMockModel({
+ test("models after 2025-11-13 include 'none' effort", () => {
+ const model = createMockModel({
+ id: "gpt-5-nano",
+ providerID: "openai",
+ api: {
id: "gpt-5-nano",
- providerID: "openai",
- api: {
- id: "gpt-5-nano",
- url: "https://api.openai.com",
- npm: "@ai-sdk/openai",
- },
- release_date: "2025-11-14",
- })
- const result = ProviderTransform.variants(model)
- expect(Object.keys(result)).toEqual(["none", "minimal", "low", "medium", "high"])
+ url: "https://api.openai.com",
+ npm: "@ai-sdk/openai",
+ },
+ release_date: "2025-11-14",
})
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual(["none", "minimal", "low", "medium", "high"])
+ })
- test("models after 2025-12-04 include 'xhigh' effort", () => {
- const model = createMockModel({
- id: "openai/gpt-5-chat",
- providerID: "openai",
- api: {
- id: "gpt-5-chat",
- url: "https://api.openai.com",
- npm: "@ai-sdk/openai",
- },
- release_date: "2025-12-05",
- })
- const result = ProviderTransform.variants(model)
- expect(Object.keys(result)).toEqual(["none", "minimal", "low", "medium", "high", "xhigh"])
+ test("models after 2025-12-04 include 'xhigh' effort", () => {
+ const model = createMockModel({
+ id: "openai/gpt-5-chat",
+ providerID: "openai",
+ api: {
+ id: "gpt-5-chat",
+ url: "https://api.openai.com",
+ npm: "@ai-sdk/openai",
+ },
+ release_date: "2025-12-05",
+ })
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual(["none", "minimal", "low", "medium", "high", "xhigh"])
+ })
+ })
+
+ describe("@ai-sdk/anthropic", () => {
+ test("sonnet 4.6 returns adaptive thinking options", () => {
+ const model = createMockModel({
+ id: "anthropic/claude-sonnet-4-6",
+ providerID: "anthropic",
+ api: {
+ id: "claude-sonnet-4-6",
+ url: "https://api.anthropic.com",
+ npm: "@ai-sdk/anthropic",
+ },
+ })
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual(["low", "medium", "high", "max"])
+ expect(result.high).toEqual({
+ thinking: {
+ type: "adaptive",
+ },
+ effort: "high",
})
})
- describe("@ai-sdk/anthropic", () => {
- test("returns high and max with thinking config", () => {
- const model = createMockModel({
- id: "anthropic/claude-4",
- providerID: "anthropic",
- api: {
- id: "claude-4",
- url: "https://api.anthropic.com",
- npm: "@ai-sdk/anthropic",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(Object.keys(result)).toEqual(["high", "max"])
- expect(result.high).toEqual({
- thinking: {
- type: "enabled",
- budgetTokens: 16000,
- },
- })
- expect(result.max).toEqual({
- thinking: {
- type: "enabled",
- budgetTokens: 31999,
- },
- })
+ test("returns high and max with thinking config", () => {
+ const model = createMockModel({
+ id: "anthropic/claude-4",
+ providerID: "anthropic",
+ api: {
+ id: "claude-4",
+ url: "https://api.anthropic.com",
+ npm: "@ai-sdk/anthropic",
+ },
+ })
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual(["high", "max"])
+ expect(result.high).toEqual({
+ thinking: {
+ type: "enabled",
+ budgetTokens: 16000,
+ },
+ })
+ expect(result.max).toEqual({
+ thinking: {
+ type: "enabled",
+ budgetTokens: 31999,
+ },
+ })
+ })
+ })
+
+ describe("@ai-sdk/amazon-bedrock", () => {
+ test("anthropic sonnet 4.6 returns adaptive reasoning options", () => {
+ const model = createMockModel({
+ id: "bedrock/anthropic-claude-sonnet-4-6",
+ providerID: "bedrock",
+ api: {
+ id: "anthropic.claude-sonnet-4-6",
+ url: "https://bedrock.amazonaws.com",
+ npm: "@ai-sdk/amazon-bedrock",
+ },
+ })
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual(["low", "medium", "high", "max"])
+ expect(result.max).toEqual({
+ reasoningConfig: {
+ type: "adaptive",
+ maxReasoningEffort: "max",
+ },
})
})
- describe("@ai-sdk/amazon-bedrock", () => {
- test("returns WIDELY_SUPPORTED_EFFORTS with reasoningConfig", () => {
- const model = createMockModel({
- id: "bedrock/llama-4",
- providerID: "bedrock",
- api: {
- id: "llama-4-sc",
- url: "https://bedrock.amazonaws.com",
- npm: "@ai-sdk/amazon-bedrock",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(Object.keys(result)).toEqual(["low", "medium", "high"])
- expect(result.low).toEqual({
- reasoningConfig: {
- type: "enabled",
- maxReasoningEffort: "low",
- },
- })
+ test("returns WIDELY_SUPPORTED_EFFORTS with reasoningConfig", () => {
+ const model = createMockModel({
+ id: "bedrock/llama-4",
+ providerID: "bedrock",
+ api: {
+ id: "llama-4-sc",
+ url: "https://bedrock.amazonaws.com",
+ npm: "@ai-sdk/amazon-bedrock",
+ },
+ })
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual(["low", "medium", "high"])
+ expect(result.low).toEqual({
+ reasoningConfig: {
+ type: "enabled",
+ maxReasoningEffort: "low",
+ },
+ })
+ })
+ })
+
+ describe("@ai-sdk/google", () => {
+ test("gemini-2.5 returns high and max with thinkingConfig and thinkingBudget", () => {
+ const model = createMockModel({
+ id: "google/gemini-2.5-pro",
+ providerID: "google",
+ api: {
+ id: "gemini-2.5-pro",
+ url: "https://generativelanguage.googleapis.com",
+ npm: "@ai-sdk/google",
+ },
+ })
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual(["high", "max"])
+ expect(result.high).toEqual({
+ thinkingConfig: {
+ includeThoughts: true,
+ thinkingBudget: 16000,
+ },
+ })
+ expect(result.max).toEqual({
+ thinkingConfig: {
+ includeThoughts: true,
+ thinkingBudget: 24576,
+ },
})
})
- describe("@ai-sdk/google", () => {
- test("gemini-2.5 returns high and max with thinkingConfig and thinkingBudget", () => {
- const model = createMockModel({
- id: "google/gemini-2.5-pro",
- providerID: "google",
- api: {
- id: "gemini-2.5-pro",
- url: "https://generativelanguage.googleapis.com",
- npm: "@ai-sdk/google",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(Object.keys(result)).toEqual(["high", "max"])
- expect(result.high).toEqual({
- thinkingConfig: {
- includeThoughts: true,
- thinkingBudget: 16000,
- },
- })
- expect(result.max).toEqual({
- thinkingConfig: {
- includeThoughts: true,
- thinkingBudget: 24576,
- },
- })
+ test("other gemini models return low and high with thinkingLevel", () => {
+ const model = createMockModel({
+ id: "google/gemini-2.0-pro",
+ providerID: "google",
+ api: {
+ id: "gemini-2.0-pro",
+ url: "https://generativelanguage.googleapis.com",
+ npm: "@ai-sdk/google",
+ },
})
-
- test("other gemini models return low and high with thinkingLevel", () => {
- const model = createMockModel({
- id: "google/gemini-2.0-pro",
- providerID: "google",
- api: {
- id: "gemini-2.0-pro",
- url: "https://generativelanguage.googleapis.com",
- npm: "@ai-sdk/google",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(Object.keys(result)).toEqual(["low", "high"])
- expect(result.low).toEqual({
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual(["low", "high"])
+ expect(result.low).toEqual({
+ thinkingConfig: {
includeThoughts: true,
thinkingLevel: "low",
- })
- expect(result.high).toEqual({
+ },
+ })
+ expect(result.high).toEqual({
+ thinkingConfig: {
includeThoughts: true,
thinkingLevel: "high",
- })
+ },
})
})
+ })
- describe("@ai-sdk/google-vertex", () => {
- test("gemini-2.5 returns high and max with thinkingConfig and thinkingBudget", () => {
- const model = createMockModel({
- id: "google-vertex/gemini-2.5-pro",
- providerID: "google-vertex",
- api: {
- id: "gemini-2.5-pro",
- url: "https://vertexai.googleapis.com",
- npm: "@ai-sdk/google-vertex",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(Object.keys(result)).toEqual(["high", "max"])
+ describe("@ai-sdk/google-vertex", () => {
+ test("gemini-2.5 returns high and max with thinkingConfig and thinkingBudget", () => {
+ const model = createMockModel({
+ id: "google-vertex/gemini-2.5-pro",
+ providerID: "google-vertex",
+ api: {
+ id: "gemini-2.5-pro",
+ url: "https://vertexai.googleapis.com",
+ npm: "@ai-sdk/google-vertex",
+ },
})
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual(["high", "max"])
+ })
- test("other vertex models return low and high with thinkingLevel", () => {
- const model = createMockModel({
- id: "google-vertex/gemini-2.0-pro",
- providerID: "google-vertex",
- api: {
- id: "gemini-2.0-pro",
- url: "https://vertexai.googleapis.com",
- npm: "@ai-sdk/google-vertex",
- },
- })
- const result = ProviderTransform.variants(model)
- expect(Object.keys(result)).toEqual(["low", "high"])
+ test("other vertex models return low and high with thinkingLevel", () => {
+ const model = createMockModel({
+ id: "google-vertex/gemini-2.0-pro",
+ providerID: "google-vertex",
+ api: {
+ id: "gemini-2.0-pro",
+ url: "https://vertexai.googleapis.com",
+ npm: "@ai-sdk/google-vertex",
+ },
})
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual(["low", "high"])
+ })
+ })
+
+ describe("@ai-sdk/cohere", () => {
+ test("returns empty object", () => {
+ const model = createMockModel({
+ id: "cohere/command-r",
+ providerID: "cohere",
+ api: {
+ id: "command-r",
+ url: "https://api.cohere.com",
+ npm: "@ai-sdk/cohere",
+ },
+ })
+ const result = ProviderTransform.variants(model)
+ expect(result).toEqual({})
+ })
+ })
+
+ describe("@ai-sdk/groq", () => {
+ test("returns none and WIDELY_SUPPORTED_EFFORTS with thinkingLevel", () => {
+ const model = createMockModel({
+ id: "groq/llama-4",
+ providerID: "groq",
+ api: {
+ id: "llama-4-sc",
+ url: "https://api.groq.com",
+ npm: "@ai-sdk/groq",
+ },
+ })
+ const result = ProviderTransform.variants(model)
+ expect(Object.keys(result)).toEqual(["none", "low", "medium", "high"])
+ expect(result.none).toEqual({
+ reasoningEffort: "none",
+ })
+ expect(result.low).toEqual({
+ reasoningEffort: "low",
+ })
+ })
+ })
+
+ describe("@ai-sdk/perplexity", () => {
+ test("returns empty object", () => {
+ const model = createMockModel({
+ id: "perplexity/sonar-plus",
+ providerID: "perplexity",
+ api: {
+ id: "sonar-plus",
+ url: "https://api.perplexity.ai",
+ npm: "@ai-sdk/perplexity",
+ },
+ })
+ const result = ProviderTransform.variants(model)
+ expect(result).toEqual({})
})
})