From 07fe6b7d2168cecdf69ddb427870fcb09055ec59 Mon Sep 17 00:00:00 2001 From: Jiayuan Date: Wed, 14 Jan 2026 03:59:37 +0800 Subject: [PATCH] fix: correct session history parsing in ChatView - Append message chunks instead of replacing (was losing all but last chunk) - Handle tool_call_update when tool_call event was missed - Skip agent_thought_chunk for now - Store user messages in Conductor before sending prompt - Fix TypeScript errors with tool call handling Co-Authored-By: Claude Opus 4.5 --- src/main/conductor/Conductor.ts | 12 +++++ src/renderer/src/components/ChatView.tsx | 56 +++++++++++++++++++----- 2 files changed, 56 insertions(+), 12 deletions(-) diff --git a/src/main/conductor/Conductor.ts b/src/main/conductor/Conductor.ts index 782f5b91e1..802f6ded7f 100644 --- a/src/main/conductor/Conductor.ts +++ b/src/main/conductor/Conductor.ts @@ -247,6 +247,18 @@ export class Conductor { console.log(`[Conductor] Sending prompt to session ${agentSessionId}`) console.log(`[Conductor] Content: ${content.slice(0, 100)}${content.length > 100 ? '...' : ''}`) + // Store user message before sending (so it appears in history) + if (this.sessionStore && this.activeSessionId) { + const userUpdate = { + sessionId: agentSessionId, + update: { + sessionUpdate: 'user_message', + content: { type: 'text', text: content }, + }, + } + await this.sessionStore.appendUpdate(this.activeSessionId, userUpdate as any) + } + const result = await this.connection.prompt({ sessionId: agentSessionId, prompt: [{ type: 'text', text: content }], diff --git a/src/renderer/src/components/ChatView.tsx b/src/renderer/src/components/ChatView.tsx index a022c63e9b..6d306767b7 100644 --- a/src/renderer/src/components/ChatView.tsx +++ b/src/renderer/src/components/ChatView.tsx @@ -87,8 +87,12 @@ function groupUpdatesIntoMessages(updates: StoredSessionUpdate[]): Message[] { const toolCallMap = new Map() for (const stored of updates) { - const update = stored.update.update - if (!update || !('sessionUpdate' in update)) continue + // The stored.update is SessionNotification which has { sessionId, update } + const notification = stored.update + const update = notification?.update + if (!update || !('sessionUpdate' in update)) { + continue + } switch (update.sessionUpdate) { case 'user_message' as string: @@ -117,11 +121,16 @@ function groupUpdatesIntoMessages(updates: StoredSessionUpdate[]): Message[] { break case 'agent_message_chunk': + // APPEND chunks instead of replacing if ('content' in update && update.content?.type === 'text') { - currentAssistantContent = update.content.text + currentAssistantContent += update.content.text } break + case 'agent_thought_chunk': + // Skip thought chunks for now (could show them differently) + break + case 'tool_call': if ('toolCallId' in update) { const toolCall: ToolCall = { @@ -131,7 +140,7 @@ function groupUpdatesIntoMessages(updates: StoredSessionUpdate[]): Message[] { kind: update.kind, input: typeof update.rawInput === 'string' ? update.rawInput - : update.rawInput + : update.rawInput && Object.keys(update.rawInput).length > 0 ? JSON.stringify(update.rawInput, null, 2) : undefined, } @@ -141,13 +150,36 @@ function groupUpdatesIntoMessages(updates: StoredSessionUpdate[]): Message[] { break case 'tool_call_update': - if ('toolCallId' in update && toolCallMap.has(update.toolCallId)) { - const existing = toolCallMap.get(update.toolCallId)! - if (update.status) existing.status = update.status - if (update.rawOutput) { - existing.output = typeof update.rawOutput === 'string' - ? update.rawOutput - : JSON.stringify(update.rawOutput, null, 2) + if ('toolCallId' in update) { + // Get or create the tool call entry + const existingTool = toolCallMap.get(update.toolCallId) + if (existingTool) { + if (update.status) existingTool.status = update.status + if (update.title) existingTool.title = update.title + if (update.rawInput && Object.keys(update.rawInput).length > 0) { + existingTool.input = typeof update.rawInput === 'string' + ? update.rawInput + : JSON.stringify(update.rawInput, null, 2) + } + if (update.rawOutput) { + existingTool.output = typeof update.rawOutput === 'string' + ? update.rawOutput + : JSON.stringify(update.rawOutput, null, 2) + } + } else { + // Create new entry if we see update before the initial tool_call + const newTool: ToolCall = { + id: update.toolCallId, + title: update.title || 'Tool Call', + status: update.status || 'pending', + kind: update.kind ?? undefined, + } + if (update.rawInput && Object.keys(update.rawInput).length > 0) { + newTool.input = typeof update.rawInput === 'string' + ? update.rawInput + : JSON.stringify(update.rawInput, null, 2) + } + toolCallMap.set(update.toolCallId, newTool) } currentToolCalls = Array.from(toolCallMap.values()) } @@ -159,7 +191,7 @@ function groupUpdatesIntoMessages(updates: StoredSessionUpdate[]): Message[] { if (currentAssistantContent || currentToolCalls.length > 0) { messages.push({ role: 'assistant', - content: currentAssistantContent, + content: currentAssistantContent.trim(), toolCalls: currentToolCalls, }) }