From 0cf502e72c8612acaa9ee48380ea1f04bb5aa223 Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 30 Apr 2026 22:10:31 +0000 Subject: [PATCH] address reviewer feedback --- .../src/services/chatRecordingService.test.ts | 41 +++++++++++++++++++ .../core/src/services/chatRecordingService.ts | 25 +++++------ 2 files changed, 54 insertions(+), 12 deletions(-) diff --git a/packages/core/src/services/chatRecordingService.test.ts b/packages/core/src/services/chatRecordingService.test.ts index b6f16ee770..a7fe74a94f 100644 --- a/packages/core/src/services/chatRecordingService.test.ts +++ b/packages/core/src/services/chatRecordingService.test.ts @@ -1295,6 +1295,47 @@ describe('ChatRecordingService', () => { expect(messages![0].content).toEqual([{ text: 'New user message' }]); expect(messages![0].type).toBe('user'); }); + + it('should correctly reconstruct sibling parts (text/media) in tool response turns', async () => { + const callId = 'tool-call-1'; + const history: Content[] = [ + { + role: 'model', + parts: [ + { functionCall: { id: callId, name: 'list_files', args: {} } }, + ], + }, + { + role: 'user', + parts: [ + { text: 'Sibling text' }, + { + functionResponse: { + id: callId, + name: 'list_files', + response: { files: [] }, + }, + }, + { inlineData: { data: 'base64data', mimeType: 'image/png' } }, + ], + }, + ]; + + chatRecordingService.updateMessagesFromHistory(history, true); + + const messages = chatRecordingService.getConversation()?.messages; + expect(messages).toHaveLength(1); + const geminiMsg = messages![0] as MessageRecord & { type: 'gemini' }; + expect(geminiMsg.toolCalls).toHaveLength(1); + + const result = geminiMsg.toolCalls![0].result as Part[]; + expect(result).toHaveLength(3); + expect(result[0]).toEqual({ text: 'Sibling text' }); + expect(result[1].functionResponse?.id).toBe(callId); + expect(result[2]).toEqual({ + inlineData: { data: 'base64data', mimeType: 'image/png' }, + }); + }); }); describe('ENOENT (missing directory) handling', () => { diff --git a/packages/core/src/services/chatRecordingService.ts b/packages/core/src/services/chatRecordingService.ts index 936dfb157c..e414b43b26 100644 --- a/packages/core/src/services/chatRecordingService.ts +++ b/packages/core/src/services/chatRecordingService.ts @@ -908,17 +908,21 @@ export class ChatRecordingService { ) { const nextTurn = history[i + 1]; const nextParts = nextTurn.parts || []; - const hasResponses = nextParts.some((p) => p.functionResponse); + const callIds = nextParts + .map((p) => p.functionResponse?.id) + .filter((id): id is string => !!id); - if (hasResponses) { + if (callIds.length > 0) { const respMap = new Map(); + let currentCallId = callIds[0]; for (const p of nextParts) { if (p.functionResponse?.id) { - if (!respMap.has(p.functionResponse.id)) { - respMap.set(p.functionResponse.id, []); - } - respMap.get(p.functionResponse.id)!.push(p); + currentCallId = p.functionResponse.id; } + if (!respMap.has(currentCallId)) { + respMap.set(currentCallId, []); + } + respMap.get(currentCallId)!.push(p); } for (const tc of geminiMsg.toolCalls!) { @@ -955,12 +959,9 @@ export class ChatRecordingService { (this.cachedConversation.messages.length === 0 && history.length > 0) || reconstruct ) { - this.cachedConversation.messages = - this.reconstructMessagesFromHistory(history); - this.updateMetadata({ lastUpdated: new Date().toISOString() }); - // Snapshot the reconstruction to ensure persistence - this.appendRecord({ - $set: { messages: this.cachedConversation.messages }, + this.updateMetadata({ + messages: this.reconstructMessagesFromHistory(history), + lastUpdated: new Date().toISOString(), }); return; }