From 1d5077cf0da1e332a1f28db8a8924545d928c184 Mon Sep 17 00:00:00 2001 From: Akhilesh Kumar Date: Thu, 16 Apr 2026 19:16:22 +0000 Subject: [PATCH] fix(core): Correct Gemma 4 thought extraction and model features Fixes an issue where the CLI hangs on 'Thinking...' for models (like Gemma 4) that return thought text in the 'thought' field instead of 'text'. Also updates Gemma 4 model definitions to accurately reflect their 'thinking' capabilities. --- packages/core/src/config/defaultModelConfigs.ts | 2 +- packages/core/src/core/geminiChat.ts | 8 ++++++-- packages/core/src/core/turn.test.ts | 4 ++-- packages/core/src/core/turn.ts | 6 +++++- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/packages/core/src/config/defaultModelConfigs.ts b/packages/core/src/config/defaultModelConfigs.ts index 1849b1e206..5df8da93f5 100644 --- a/packages/core/src/config/defaultModelConfigs.ts +++ b/packages/core/src/config/defaultModelConfigs.ts @@ -334,7 +334,7 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = { family: 'gemma-4', isPreview: true, isVisible: true, - features: { thinking: false, multimodalToolUse: false }, + features: { thinking: true, multimodalToolUse: false }, }, 'gemma-4-31b-it': { tier: 'pro', diff --git a/packages/core/src/core/geminiChat.ts b/packages/core/src/core/geminiChat.ts index c480c3800b..f7fece6c33 100644 --- a/packages/core/src/core/geminiChat.ts +++ b/packages/core/src/core/geminiChat.ts @@ -1072,9 +1072,13 @@ export class GeminiChat { } const thoughtPart = content.parts[0]; - if (thoughtPart.text) { + const rawText = + typeof thoughtPart.thought === 'string' + ? thoughtPart.thought + : (thoughtPart.text ?? ''); + + if (rawText) { // Extract subject and description using the same logic as turn.ts - const rawText = thoughtPart.text; const subjectStringMatches = rawText.match(/\*\*(.*?)\*\*/s); const subject = subjectStringMatches ? subjectStringMatches[1].trim() diff --git a/packages/core/src/core/turn.test.ts b/packages/core/src/core/turn.test.ts index 435323f73d..ec5466e3ee 100644 --- a/packages/core/src/core/turn.test.ts +++ b/packages/core/src/core/turn.test.ts @@ -733,7 +733,7 @@ describe('Turn', () => { }, { description: 'should yield thought events with traceId', - part: { text: '[Thought: thinking]', thought: 'thinking' }, + part: { text: '[Thought: thinking]', thought: true }, responseId: 'trace-456', expectedEvent: { type: GeminiEventType.Thought, @@ -774,7 +774,7 @@ describe('Turn', () => { { content: { parts: [ - { text: '**Planning** the solution', thought: 'planning' }, + { text: '**Planning** the solution', thought: true }, { text: 'I will help you with that.' }, ], }, diff --git a/packages/core/src/core/turn.ts b/packages/core/src/core/turn.ts index 9c0e536c48..3e3a4007f7 100644 --- a/packages/core/src/core/turn.ts +++ b/packages/core/src/core/turn.ts @@ -308,7 +308,11 @@ export class Turn { const parts = resp.candidates?.[0]?.content?.parts ?? []; for (const part of parts) { if (part.thought) { - const thought = parseThought(part.text ?? ''); + const rawThought = + typeof part.thought === 'string' + ? part.thought + : (part.text ?? ''); + const thought = parseThought(rawThought); yield { type: GeminiEventType.Thought, value: thought,