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.
This commit is contained in:
Akhilesh Kumar
2026-04-16 19:16:22 +00:00
parent 5f181f96f8
commit 1d5077cf0d
4 changed files with 14 additions and 6 deletions
@@ -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',
+6 -2
View File
@@ -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()
+2 -2
View File
@@ -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.' },
],
},
+5 -1
View File
@@ -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,