From d6f88f8720f56631c4bfcb92e02d04c98bd0cf97 Mon Sep 17 00:00:00 2001 From: Adam Weidman <65992621+adamfweidman@users.noreply.github.com> Date: Tue, 21 Apr 2026 13:17:21 -0700 Subject: [PATCH] fix(core): remove duplicate initialize call on agents refreshed (#25670) --- packages/core/src/agents/a2aUtils.test.ts | 47 +++++++++++++++++++ packages/core/src/agents/a2aUtils.ts | 46 ++++++++++++------ .../src/config/config-agents-reload.test.ts | 8 ++-- packages/core/src/config/config.ts | 2 - 4 files changed, 82 insertions(+), 21 deletions(-) diff --git a/packages/core/src/agents/a2aUtils.test.ts b/packages/core/src/agents/a2aUtils.test.ts index f8416ae2ad..14d9fd061e 100644 --- a/packages/core/src/agents/a2aUtils.test.ts +++ b/packages/core/src/agents/a2aUtils.test.ts @@ -538,5 +538,52 @@ describe('a2aUtils', () => { expect(output).toContain('Artifact (Data):'); expect(output).not.toContain('Answer from history'); }); + + it('should return message log as activity items', () => { + const reassembler = new A2AResultReassembler(); + + reassembler.update({ + kind: 'status-update', + taskId: 't1', + contextId: 'ctx1', + status: { + state: 'working', + message: { + kind: 'message', + role: 'agent', + parts: [{ kind: 'text', text: 'Message 1' }], + } as Message, + }, + } as unknown as SendMessageResult); + + reassembler.update({ + kind: 'status-update', + taskId: 't1', + contextId: 'ctx1', + status: { + state: 'working', + message: { + kind: 'message', + role: 'agent', + parts: [{ kind: 'text', text: 'Message 2' }], + } as Message, + }, + } as unknown as SendMessageResult); + + const items = reassembler.toActivityItems(); + expect(items).toHaveLength(2); + expect(items[0]).toEqual({ + id: 'msg-0', + type: 'thought', + content: 'Message 1', + status: 'completed', + }); + expect(items[1]).toEqual({ + id: 'msg-1', + type: 'thought', + content: 'Message 2', + status: 'completed', + }); + }); }); }); diff --git a/packages/core/src/agents/a2aUtils.ts b/packages/core/src/agents/a2aUtils.ts index b617082416..db08fdb871 100644 --- a/packages/core/src/agents/a2aUtils.ts +++ b/packages/core/src/agents/a2aUtils.ts @@ -124,6 +124,7 @@ export class A2AResultReassembler { private pushMessage(message: Message | undefined) { if (!message) return; + if (message.role === 'user') return; // Skip user messages reflected by server const text = extractPartsText(message.parts, ''); if (text && this.messageLog[this.messageLog.length - 1] !== text) { this.messageLog.push(text); @@ -135,21 +136,36 @@ export class A2AResultReassembler { */ toActivityItems(): SubagentActivityItem[] { const isAuthRequired = this.messageLog.includes(AUTH_REQUIRED_MSG); - return [ - isAuthRequired - ? { - id: 'auth-required', - type: 'thought', - content: AUTH_REQUIRED_MSG, - status: 'running', - } - : { - id: 'pending', - type: 'thought', - content: 'Working...', - status: 'running', - }, - ]; + const items: SubagentActivityItem[] = []; + + if (isAuthRequired) { + items.push({ + id: 'auth-required', + type: 'thought', + content: AUTH_REQUIRED_MSG, + status: 'running', + }); + } + + this.messageLog.forEach((msg, index) => { + items.push({ + id: `msg-${index}`, + type: 'thought', + content: msg.trim(), + status: 'completed', + }); + }); + + if (items.length === 0 && !isAuthRequired) { + items.push({ + id: 'pending', + type: 'thought', + content: 'Working...', + status: 'running', + }); + } + + return items; } /** diff --git a/packages/core/src/config/config-agents-reload.test.ts b/packages/core/src/config/config-agents-reload.test.ts index 9a9eea3a65..6f4b9b7fce 100644 --- a/packages/core/src/config/config-agents-reload.test.ts +++ b/packages/core/src/config/config-agents-reload.test.ts @@ -95,8 +95,8 @@ Test System Prompt`; }); // Trigger the refresh action that follows reloading - // @ts-expect-error accessing private method for testing - await config.onAgentsRefreshed(); + + await config.getAgentRegistry().reload(); // 4. Verify the agent is UNREGISTERED const finalAgents = agentRegistry.getAllDefinitions().map((d) => d.name); @@ -237,8 +237,8 @@ Test System Prompt`; }); // Trigger the refresh action that follows reloading - // @ts-expect-error accessing private method for testing - await config.onAgentsRefreshed(); + + await config.getAgentRegistry().reload(); expect(agentRegistry.getAllDefinitions().map((d) => d.name)).toContain( agentName, diff --git a/packages/core/src/config/config.ts b/packages/core/src/config/config.ts index 8402e056ec..8b2f23c6ff 100644 --- a/packages/core/src/config/config.ts +++ b/packages/core/src/config/config.ts @@ -3829,8 +3829,6 @@ export class Config implements McpContext, AgentLoopContext { } private onAgentsRefreshed = async () => { - await this.agentRegistry.initialize(); - // Propagate updates to the active chat session const client = this.geminiClient; if (client?.isInitialized()) {