Files
gemini-cli/packages/core/src/agents/a2aUtils.test.ts
T

172 lines
4.7 KiB
TypeScript

/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import { describe, it, expect } from 'vitest';
import {
extractMessageText,
extractTaskText,
extractIdsFromResponse,
} from './a2aUtils.js';
import type { Message, Task, TextPart, DataPart, FilePart } from '@a2a-js/sdk';
describe('a2aUtils', () => {
describe('extractIdsFromResponse', () => {
it('should extract IDs from a message response', () => {
const message: Message = {
kind: 'message',
role: 'agent',
messageId: 'm1',
contextId: 'ctx-1',
taskId: 'task-1',
parts: [],
};
const result = extractIdsFromResponse(message);
expect(result).toEqual({ contextId: 'ctx-1', taskId: 'task-1' });
});
it('should extract IDs from an in-progress task response', () => {
const task: Task = {
id: 'task-2',
contextId: 'ctx-2',
kind: 'task',
status: { state: 'working' },
};
const result = extractIdsFromResponse(task);
expect(result).toEqual({ contextId: 'ctx-2', taskId: 'task-2' });
});
});
describe('extractMessageText', () => {
it('should extract text from simple text parts', () => {
const message: Message = {
kind: 'message',
role: 'user',
messageId: '1',
parts: [
{ kind: 'text', text: 'Hello' } as TextPart,
{ kind: 'text', text: 'World' } as TextPart,
],
};
expect(extractMessageText(message)).toBe('Hello\nWorld');
});
it('should extract data from data parts', () => {
const message: Message = {
kind: 'message',
role: 'user',
messageId: '1',
parts: [{ kind: 'data', data: { foo: 'bar' } } as DataPart],
};
expect(extractMessageText(message)).toBe('Data: {"foo":"bar"}');
});
it('should extract file info from file parts', () => {
const message: Message = {
kind: 'message',
role: 'user',
messageId: '1',
parts: [
{
kind: 'file',
file: {
name: 'test.txt',
uri: 'file://test.txt',
mimeType: 'text/plain',
},
} as FilePart,
{
kind: 'file',
file: {
uri: 'http://example.com/doc',
mimeType: 'application/pdf',
},
} as FilePart,
],
};
// The formatting logic in a2aUtils prefers name over uri
expect(extractMessageText(message)).toContain('File: test.txt');
expect(extractMessageText(message)).toContain(
'File: http://example.com/doc',
);
});
it('should handle mixed parts', () => {
const message: Message = {
kind: 'message',
role: 'user',
messageId: '1',
parts: [
{ kind: 'text', text: 'Here is data:' } as TextPart,
{ kind: 'data', data: { value: 123 } } as DataPart,
],
};
expect(extractMessageText(message)).toBe(
'Here is data:\nData: {"value":123}',
);
});
it('should return empty string for undefined or empty message', () => {
expect(extractMessageText(undefined)).toBe('');
expect(
extractMessageText({
kind: 'message',
role: 'user',
messageId: '1',
parts: [],
} as Message),
).toBe('');
});
});
describe('extractTaskText', () => {
it('should extract basic task info (clean)', () => {
const task: Task = {
id: 'task-1',
contextId: 'ctx-1',
kind: 'task',
status: {
state: 'working',
message: {
kind: 'message',
role: 'agent',
messageId: 'm1',
parts: [{ kind: 'text', text: 'Processing...' } as TextPart],
},
},
};
const result = extractTaskText(task);
expect(result).not.toContain('ID: task-1');
expect(result).not.toContain('State: working');
expect(result).toBe('Processing...');
});
it('should extract artifacts with headers', () => {
const task: Task = {
id: 'task-1',
contextId: 'ctx-1',
kind: 'task',
status: { state: 'completed' },
artifacts: [
{
artifactId: 'art-1',
name: 'Report',
parts: [{ kind: 'text', text: 'This is the report.' } as TextPart],
},
],
};
const result = extractTaskText(task);
expect(result).toContain('Artifact (Report):');
expect(result).toContain('This is the report.');
expect(result).not.toContain('Artifacts:');
expect(result).not.toContain(' - Name: Report');
});
});
});