From 71c60e1be4cc0b69da43b600eb593cfaaf275a81 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Tue, 31 Mar 2026 16:32:32 +0900 Subject: [PATCH] fix: skip thinking param injection for GLM models in sisyphus-junior (#2967) GLM-5 has native reasoning built-in. Injecting thinking: {type: 'enabled'} causes a param conflict (400 error). Add isGlmModel() check to return base config without thinking/reasoningEffort for GLM models. - Add isGlmModel() helper to types.ts - Early return in createSisyphusJuniorAgentWithOverrides for GLM models - Add tests for isGlmModel and GLM reasoning config behavior --- src/agents/sisyphus-junior/agent.ts | 6 +++- src/agents/sisyphus-junior/index.test.ts | 38 ++++++++++++++++++++++++ src/agents/types.test.ts | 22 +++++++++++++- src/agents/types.ts | 5 ++++ 4 files changed, 69 insertions(+), 2 deletions(-) diff --git a/src/agents/sisyphus-junior/agent.ts b/src/agents/sisyphus-junior/agent.ts index 8637315fa..c8178f7fb 100644 --- a/src/agents/sisyphus-junior/agent.ts +++ b/src/agents/sisyphus-junior/agent.ts @@ -12,7 +12,7 @@ import type { AgentConfig } from "@opencode-ai/sdk" import type { AgentMode } from "../types" -import { isGptModel, isGeminiModel } from "../types" +import { isGlmModel, isGptModel, isGeminiModel } from "../types" import type { AgentOverrideConfig } from "../../config/schema" import { createAgentToolRestrictions, @@ -123,6 +123,10 @@ export function createSisyphusJuniorAgentWithOverrides( return { ...base, reasoningEffort: "medium" } as AgentConfig } + if (isGlmModel(model)) { + return base as AgentConfig + } + return { ...base, thinking: { type: "enabled", budgetTokens: 32000 }, diff --git a/src/agents/sisyphus-junior/index.test.ts b/src/agents/sisyphus-junior/index.test.ts index fa8da4cb6..dace8bf38 100644 --- a/src/agents/sisyphus-junior/index.test.ts +++ b/src/agents/sisyphus-junior/index.test.ts @@ -143,6 +143,44 @@ describe("createSisyphusJuniorAgentWithOverrides", () => { }) }) + describe("reasoning configuration", () => { + test("#given GPT model #when agent is created #then uses reasoningEffort", () => { + // given + const override = { model: "openai/gpt-5.4" } + + // when + const result = createSisyphusJuniorAgentWithOverrides(override) + + // then + expect(result.reasoningEffort).toBe("medium") + expect(result.thinking).toBeUndefined() + }) + + test("#given Claude model #when agent is created #then injects thinking", () => { + // given + const override = { model: "anthropic/claude-sonnet-4-6" } + + // when + const result = createSisyphusJuniorAgentWithOverrides(override) + + // then + expect(result.reasoningEffort).toBeUndefined() + expect(result.thinking).toEqual({ type: "enabled", budgetTokens: 32000 }) + }) + + test("#given GLM reasoning model #when agent is created #then skips injected thinking", () => { + // given + const override = { model: "z-ai/glm-5" } + + // when + const result = createSisyphusJuniorAgentWithOverrides(override) + + // then + expect(result.reasoningEffort).toBeUndefined() + expect(result.thinking).toBeUndefined() + }) + }) + describe("tool safety (task blocked, call_omo_agent allowed)", () => { test("task remains blocked, call_omo_agent is allowed via tools format", () => { // given diff --git a/src/agents/types.test.ts b/src/agents/types.test.ts index c911324fd..a214d304a 100644 --- a/src/agents/types.test.ts +++ b/src/agents/types.test.ts @@ -1,5 +1,5 @@ import { describe, test, expect } from "bun:test"; -import { isGptModel, isGeminiModel, isGpt5_4Model, isMiniMaxModel } from "./types"; +import { isGptModel, isGeminiModel, isGlmModel, isGpt5_4Model, isMiniMaxModel } from "./types"; describe("isGpt5_4Model", () => { test("detects gpt-5.4 models", () => { @@ -101,6 +101,26 @@ describe("isMiniMaxModel", () => { }); }); +describe("isGlmModel", () => { + test("#given GLM models with provider prefix #then returns true", () => { + expect(isGlmModel("z-ai/glm-5")).toBe(true); + expect(isGlmModel("opencode/glm-5")).toBe(true); + expect(isGlmModel("opencode-go/glm-5-turbo")).toBe(true); + expect(isGlmModel("opencode/glm-4.6v")).toBe(true); + }); + + test("#given GLM models without provider prefix #then returns true", () => { + expect(isGlmModel("glm-5")).toBe(true); + expect(isGlmModel("glm-5-turbo")).toBe(true); + }); + + test("#given non-GLM models #then returns false", () => { + expect(isGlmModel("openai/gpt-5.4")).toBe(false); + expect(isGlmModel("anthropic/claude-opus-4-6")).toBe(false); + expect(isGlmModel("google/gemini-3.1-pro")).toBe(false); + }); +}); + describe("isGeminiModel", () => { test("#given google provider models #then returns true", () => { expect(isGeminiModel("google/gemini-3.1-pro")).toBe(true); diff --git a/src/agents/types.ts b/src/agents/types.ts index 5f5fa6bfe..e5c03e006 100644 --- a/src/agents/types.ts +++ b/src/agents/types.ts @@ -96,6 +96,11 @@ export function isMiniMaxModel(model: string): boolean { return modelName.includes("minimax"); } +export function isGlmModel(model: string): boolean { + const modelName = extractModelName(model).toLowerCase(); + return modelName.includes("glm"); +} + export function isGeminiModel(model: string): boolean { if (GEMINI_PROVIDERS.some((prefix) => model.startsWith(prefix))) return true;