fix(think-mode): disable thinking parameter for Z.ai GLM models

Z.ai GLM models don't support thinking/reasoning parameters.
Ensure these are omitted entirely to prevent empty responses.

Fixes #980

Community-reported-by: @iserifith
This commit is contained in:
YeonGyu-Kim
2026-02-14 14:03:32 +09:00
parent daf011c616
commit 9f52e48e8f
4 changed files with 73 additions and 8 deletions

View File

@@ -10,6 +10,45 @@ export function clearThinkModeState(sessionID: string): void {
}
export function createThinkModeHook() {
function isDisabledThinkingConfig(config: Record<string, unknown>): boolean {
const thinkingConfig = config.thinking
if (
typeof thinkingConfig === "object" &&
thinkingConfig !== null &&
"type" in thinkingConfig &&
(thinkingConfig as { type?: string }).type === "disabled"
) {
return true
}
const providerOptions = config.providerOptions
if (typeof providerOptions !== "object" || providerOptions === null) {
return false
}
return Object.values(providerOptions as Record<string, unknown>).some(
(providerConfig) => {
if (typeof providerConfig !== "object" || providerConfig === null) {
return false
}
const providerConfigMap = providerConfig as Record<string, unknown>
const extraBody = providerConfigMap.extra_body
if (typeof extraBody !== "object" || extraBody === null) {
return false
}
const extraBodyMap = extraBody as Record<string, unknown>
const extraThinking = extraBodyMap.thinking
return (
typeof extraThinking === "object" &&
extraThinking !== null &&
(extraThinking as { type?: string }).type === "disabled"
)
}
)
}
return {
"chat.params": async (output: ThinkModeInput, sessionID: string): Promise<void> => {
const promptText = extractPromptText(output.parts)
@@ -75,7 +114,9 @@ export function createThinkModeHook() {
sessionID,
provider: currentModel.providerID,
})
} else {
} else if (
!isDisabledThinkingConfig(thinkingConfig as Record<string, unknown>)
) {
Object.assign(output.message, thinkingConfig)
state.thinkingConfigInjected = true
log("Think mode: thinking config injected", {
@@ -83,6 +124,11 @@ export function createThinkModeHook() {
provider: currentModel.providerID,
config: thinkingConfig,
})
} else {
log("Think mode: skipping disabled thinking config", {
sessionID,
provider: currentModel.providerID,
})
}
}

View File

@@ -352,6 +352,25 @@ describe("createThinkModeHook integration", () => {
})
describe("Agent-level thinking configuration respect", () => {
it("should omit Z.ai GLM disabled thinking config", async () => {
//#given a Z.ai GLM model with think prompt
const hook = createThinkModeHook()
const input = createMockInput(
"zai-coding-plan",
"glm-4.7",
"ultrathink mode"
)
//#when think mode resolves Z.ai thinking configuration
await hook["chat.params"](input, sessionID)
//#then thinking config should be omitted from request
const message = input.message as MessageWithInjectedProps
expect(input.message.model?.modelID).toBe("glm-4.7")
expect(message.thinking).toBeUndefined()
expect(message.providerOptions).toBeUndefined()
})
it("should NOT inject thinking config when agent has thinking disabled", async () => {
// given agent with thinking explicitly disabled
const hook = createThinkModeHook()

View File

@@ -470,10 +470,12 @@ describe("think-mode switcher", () => {
describe("Z.AI GLM-4.7 provider support", () => {
describe("getThinkingConfig for zai-coding-plan", () => {
it("should return thinking config for glm-4.7", () => {
// given zai-coding-plan provider with glm-4.7 model
//#given a Z.ai GLM model
const config = getThinkingConfig("zai-coding-plan", "glm-4.7")
// then should return zai-coding-plan thinking config
//#when thinking config is resolved
//#then thinking type is "disabled"
expect(config).not.toBeNull()
expect(config?.providerOptions).toBeDefined()
const zaiOptions = (config?.providerOptions as Record<string, unknown>)?.[
@@ -482,8 +484,7 @@ describe("think-mode switcher", () => {
expect(zaiOptions?.extra_body).toBeDefined()
const extraBody = zaiOptions?.extra_body as Record<string, unknown>
expect(extraBody?.thinking).toBeDefined()
expect((extraBody?.thinking as Record<string, unknown>)?.type).toBe("enabled")
expect((extraBody?.thinking as Record<string, unknown>)?.clear_thinking).toBe(false)
expect((extraBody?.thinking as Record<string, unknown>)?.type).toBe("disabled")
})
it("should return thinking config for glm-4.6v (multimodal)", () => {
@@ -505,7 +506,7 @@ describe("think-mode switcher", () => {
})
describe("HIGH_VARIANT_MAP for GLM", () => {
it("should NOT have high variant for glm-4.7 (thinking enabled by default)", () => {
it("should NOT have high variant for glm-4.7", () => {
// given glm-4.7 model
const variant = getHighVariant("glm-4.7")

View File

@@ -154,8 +154,7 @@ export const THINKING_CONFIGS = {
"zai-coding-plan": {
extra_body: {
thinking: {
type: "enabled",
clear_thinking: false,
type: "disabled",
},
},
},