mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-22 19:14:33 -07:00
feat(core): improve A2A content extraction (#20487)
Co-authored-by: Gal Zahavi <38544478+galz10@users.noreply.github.com>
This commit is contained in:
@@ -284,5 +284,68 @@ describe('a2aUtils', () => {
|
|||||||
'Analyzing...\n\nProcessing...\n\nArtifact (Code):\nprint("Done")',
|
'Analyzing...\n\nProcessing...\n\nArtifact (Code):\nprint("Done")',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should fallback to history in a task chunk if no message or artifacts exist and task is terminal', () => {
|
||||||
|
const reassembler = new A2AResultReassembler();
|
||||||
|
|
||||||
|
reassembler.update({
|
||||||
|
kind: 'task',
|
||||||
|
status: { state: 'completed' },
|
||||||
|
history: [
|
||||||
|
{
|
||||||
|
kind: 'message',
|
||||||
|
role: 'agent',
|
||||||
|
parts: [{ kind: 'text', text: 'Answer from history' }],
|
||||||
|
} as Message,
|
||||||
|
],
|
||||||
|
} as unknown as SendMessageResult);
|
||||||
|
|
||||||
|
expect(reassembler.toString()).toBe('Answer from history');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should NOT fallback to history in a task chunk if task is not terminal', () => {
|
||||||
|
const reassembler = new A2AResultReassembler();
|
||||||
|
|
||||||
|
reassembler.update({
|
||||||
|
kind: 'task',
|
||||||
|
status: { state: 'working' },
|
||||||
|
history: [
|
||||||
|
{
|
||||||
|
kind: 'message',
|
||||||
|
role: 'agent',
|
||||||
|
parts: [{ kind: 'text', text: 'Answer from history' }],
|
||||||
|
} as Message,
|
||||||
|
],
|
||||||
|
} as unknown as SendMessageResult);
|
||||||
|
|
||||||
|
expect(reassembler.toString()).toBe('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not fallback to history if artifacts exist', () => {
|
||||||
|
const reassembler = new A2AResultReassembler();
|
||||||
|
|
||||||
|
reassembler.update({
|
||||||
|
kind: 'task',
|
||||||
|
status: { state: 'completed' },
|
||||||
|
artifacts: [
|
||||||
|
{
|
||||||
|
artifactId: 'art-1',
|
||||||
|
name: 'Data',
|
||||||
|
parts: [{ kind: 'text', text: 'Artifact Content' }],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
history: [
|
||||||
|
{
|
||||||
|
kind: 'message',
|
||||||
|
role: 'agent',
|
||||||
|
parts: [{ kind: 'text', text: 'Answer from history' }],
|
||||||
|
} as Message,
|
||||||
|
],
|
||||||
|
} as unknown as SendMessageResult);
|
||||||
|
|
||||||
|
const output = reassembler.toString();
|
||||||
|
expect(output).toContain('Artifact (Data):');
|
||||||
|
expect(output).not.toContain('Answer from history');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -74,6 +74,26 @@ export class A2AResultReassembler {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// History Fallback: Some agent implementations do not populate the
|
||||||
|
// status.message in their final terminal response, instead archiving
|
||||||
|
// the final answer in the task's history array. To ensure we don't
|
||||||
|
// present an empty result, we fallback to the most recent agent message
|
||||||
|
// in the history only when the task is terminal and no other content
|
||||||
|
// (message log or artifacts) has been reassembled.
|
||||||
|
if (
|
||||||
|
isTerminalState(chunk.status?.state) &&
|
||||||
|
this.messageLog.length === 0 &&
|
||||||
|
this.artifacts.size === 0 &&
|
||||||
|
chunk.history &&
|
||||||
|
chunk.history.length > 0
|
||||||
|
) {
|
||||||
|
const lastAgentMsg = [...chunk.history]
|
||||||
|
.reverse()
|
||||||
|
.find((m) => m.role?.toLowerCase().includes('agent'));
|
||||||
|
if (lastAgentMsg) {
|
||||||
|
this.pushMessage(lastAgentMsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'message': {
|
case 'message': {
|
||||||
@@ -126,7 +146,7 @@ export class A2AResultReassembler {
|
|||||||
* Handles Text, Data (JSON), and File parts.
|
* Handles Text, Data (JSON), and File parts.
|
||||||
*/
|
*/
|
||||||
export function extractMessageText(message: Message | undefined): string {
|
export function extractMessageText(message: Message | undefined): string {
|
||||||
if (!message) {
|
if (!message || !message.parts || !Array.isArray(message.parts)) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,7 +178,6 @@ function extractPartText(part: Part): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isDataPart(part)) {
|
if (isDataPart(part)) {
|
||||||
// Attempt to format known data types if metadata exists, otherwise JSON stringify
|
|
||||||
return `Data: ${JSON.stringify(part.data)}`;
|
return `Data: ${JSON.stringify(part.data)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user