From d02e9f9a61bd9f67be52ae35683af4534e435d07 Mon Sep 17 00:00:00 2001 From: Roo Code Date: Thu, 2 Oct 2025 12:45:16 +0000 Subject: [PATCH 1/2] feat: add thinking mode toggle for Z AI provider - Add zaiEnableThinking field to provider settings schema - Update Z AI provider to conditionally enable thinking mode - Add UI checkbox for thinking mode in Z AI settings component - Add translation keys for the new UI elements - Add comprehensive tests for thinking mode functionality Addresses #8465 --- packages/types/src/provider-settings.ts | 1 + src/api/providers/__tests__/zai.spec.ts | 92 +++++++++++++++++++ src/api/providers/zai.ts | 43 +++++++++ .../src/components/settings/providers/ZAi.tsx | 20 +++- webview-ui/src/i18n/locales/en/settings.json | 2 + 5 files changed, 157 insertions(+), 1 deletion(-) diff --git a/packages/types/src/provider-settings.ts b/packages/types/src/provider-settings.ts index 8434158541..97c37f7fc7 100644 --- a/packages/types/src/provider-settings.ts +++ b/packages/types/src/provider-settings.ts @@ -384,6 +384,7 @@ export type ZaiApiLine = z.infer const zaiSchema = apiModelIdProviderModelSchema.extend({ zaiApiKey: z.string().optional(), zaiApiLine: zaiApiLineSchema.optional(), + zaiEnableThinking: z.boolean().optional(), }) const fireworksSchema = apiModelIdProviderModelSchema.extend({ diff --git a/src/api/providers/__tests__/zai.spec.ts b/src/api/providers/__tests__/zai.spec.ts index 383394b703..dd6d10efa6 100644 --- a/src/api/providers/__tests__/zai.spec.ts +++ b/src/api/providers/__tests__/zai.spec.ts @@ -262,5 +262,97 @@ describe("ZAiHandler", () => { undefined, ) }) + + it("should include enable_thinking parameter when zaiEnableThinking is true", async () => { + const handlerWithThinking = new ZAiHandler({ + zaiApiKey: "test-zai-api-key", + zaiApiLine: "international", + zaiEnableThinking: true, + }) + + mockCreate.mockImplementationOnce(() => { + return { + [Symbol.asyncIterator]: () => ({ + async next() { + return { done: true } + }, + }), + } + }) + + const systemPrompt = "Test system prompt" + const messages: Anthropic.Messages.MessageParam[] = [{ role: "user", content: "Test message" }] + + const messageGenerator = handlerWithThinking.createMessage(systemPrompt, messages) + await messageGenerator.next() + + expect(mockCreate).toHaveBeenCalledWith( + expect.objectContaining({ + enable_thinking: true, + }), + undefined, + ) + }) + + it("should not include enable_thinking parameter when zaiEnableThinking is false", async () => { + const handlerWithoutThinking = new ZAiHandler({ + zaiApiKey: "test-zai-api-key", + zaiApiLine: "international", + zaiEnableThinking: false, + }) + + mockCreate.mockImplementationOnce(() => { + return { + [Symbol.asyncIterator]: () => ({ + async next() { + return { done: true } + }, + }), + } + }) + + const systemPrompt = "Test system prompt" + const messages: Anthropic.Messages.MessageParam[] = [{ role: "user", content: "Test message" }] + + const messageGenerator = handlerWithoutThinking.createMessage(systemPrompt, messages) + await messageGenerator.next() + + expect(mockCreate).toHaveBeenCalledWith( + expect.not.objectContaining({ + enable_thinking: true, + }), + undefined, + ) + }) + + it("should not include enable_thinking parameter when zaiEnableThinking is undefined", async () => { + const handlerDefault = new ZAiHandler({ + zaiApiKey: "test-zai-api-key", + zaiApiLine: "international", + }) + + mockCreate.mockImplementationOnce(() => { + return { + [Symbol.asyncIterator]: () => ({ + async next() { + return { done: true } + }, + }), + } + }) + + const systemPrompt = "Test system prompt" + const messages: Anthropic.Messages.MessageParam[] = [{ role: "user", content: "Test message" }] + + const messageGenerator = handlerDefault.createMessage(systemPrompt, messages) + await messageGenerator.next() + + expect(mockCreate).toHaveBeenCalledWith( + expect.not.objectContaining({ + enable_thinking: true, + }), + undefined, + ) + }) }) }) diff --git a/src/api/providers/zai.ts b/src/api/providers/zai.ts index ce5aab9dd9..45abb46d0c 100644 --- a/src/api/providers/zai.ts +++ b/src/api/providers/zai.ts @@ -8,8 +8,12 @@ import { ZAI_DEFAULT_TEMPERATURE, zaiApiLineConfigs, } from "@roo-code/types" +import { Anthropic } from "@anthropic-ai/sdk" +import OpenAI from "openai" import type { ApiHandlerOptions } from "../../shared/api" +import type { ApiHandlerCreateMessageMetadata } from "../index" +import { convertToOpenAiMessages } from "../transform/openai-format" import { BaseOpenAiCompatibleProvider } from "./base-openai-compatible-provider" @@ -29,4 +33,43 @@ export class ZAiHandler extends BaseOpenAiCompatibleProvider [setApiConfigurationField], ) + const handleCheckboxChange = useCallback( + (field: keyof ProviderSettings) => (event: Event) => { + const target = event.target as HTMLInputElement + setApiConfigurationField(field, target.checked) + }, + [setApiConfigurationField], + ) + return ( <>
@@ -73,6 +81,16 @@ export const ZAi = ({ apiConfiguration, setApiConfigurationField }: ZAiProps) => )}
+
+ + + +
+ {t("settings:providers.zaiEnableThinkingDescription")} +
+
) } diff --git a/webview-ui/src/i18n/locales/en/settings.json b/webview-ui/src/i18n/locales/en/settings.json index aa3199e8e8..ade692af3a 100644 --- a/webview-ui/src/i18n/locales/en/settings.json +++ b/webview-ui/src/i18n/locales/en/settings.json @@ -302,6 +302,8 @@ "getZaiApiKey": "Get Z AI API Key", "zaiEntrypoint": "Z AI Entrypoint", "zaiEntrypointDescription": "Please select the appropriate API entrypoint based on your location. If you are in China, choose open.bigmodel.cn. Otherwise, choose api.z.ai.", + "zaiEnableThinking": "Enable Thinking Mode", + "zaiEnableThinkingDescription": "Enable thinking/reasoning mode for models that support it (e.g., GLM-4.6, DeepSeek v3.2). This allows models to show their reasoning process before providing answers.", "geminiApiKey": "Gemini API Key", "getGroqApiKey": "Get Groq API Key", "groqApiKey": "Groq API Key", From 04dad3060c7442a5595ee7f5c270dbcb40266e50 Mon Sep 17 00:00:00 2001 From: Roo Code Date: Thu, 2 Oct 2025 12:47:57 +0000 Subject: [PATCH 2/2] fix: resolve TypeScript error in ZAi checkbox handler --- webview-ui/src/components/settings/providers/ZAi.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/webview-ui/src/components/settings/providers/ZAi.tsx b/webview-ui/src/components/settings/providers/ZAi.tsx index 1ef43baaa4..9b883eb071 100644 --- a/webview-ui/src/components/settings/providers/ZAi.tsx +++ b/webview-ui/src/components/settings/providers/ZAi.tsx @@ -29,11 +29,10 @@ export const ZAi = ({ apiConfiguration, setApiConfigurationField }: ZAiProps) => ) const handleCheckboxChange = useCallback( - (field: keyof ProviderSettings) => (event: Event) => { - const target = event.target as HTMLInputElement - setApiConfigurationField(field, target.checked) + (field: keyof ProviderSettings) => () => { + setApiConfigurationField(field, !apiConfiguration?.[field]) }, - [setApiConfigurationField], + [setApiConfigurationField, apiConfiguration], ) return (