mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-29 22:44:45 -07:00
feat(core): implement HTTP authentication support for A2A remote agents (#20510)
Co-authored-by: Adam Weidman <adamfweidman@google.com>
This commit is contained in:
@@ -20,14 +20,22 @@ import {
|
||||
} from './a2a-client-manager.js';
|
||||
import type { RemoteAgentDefinition } from './types.js';
|
||||
import { createMockMessageBus } from '../test-utils/mock-message-bus.js';
|
||||
import { A2AAuthProviderFactory } from './auth-provider/factory.js';
|
||||
import type { A2AAuthProvider } from './auth-provider/types.js';
|
||||
|
||||
// Mock A2AClientManager
|
||||
vi.mock('./a2a-client-manager.js', () => {
|
||||
const A2AClientManager = {
|
||||
vi.mock('./a2a-client-manager.js', () => ({
|
||||
A2AClientManager: {
|
||||
getInstance: vi.fn(),
|
||||
};
|
||||
return { A2AClientManager };
|
||||
});
|
||||
},
|
||||
}));
|
||||
|
||||
// Mock A2AAuthProviderFactory
|
||||
vi.mock('./auth-provider/factory.js', () => ({
|
||||
A2AAuthProviderFactory: {
|
||||
create: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
describe('RemoteAgentInvocation', () => {
|
||||
const mockDefinition: RemoteAgentDefinition = {
|
||||
@@ -118,7 +126,7 @@ describe('RemoteAgentInvocation', () => {
|
||||
});
|
||||
|
||||
describe('Execution Logic', () => {
|
||||
it('should lazy load the agent with ADCHandler if not present', async () => {
|
||||
it('should lazy load the agent without auth handler when no auth configured', async () => {
|
||||
mockClientManager.getClient.mockReturnValue(undefined);
|
||||
mockClientManager.sendMessageStream.mockImplementation(
|
||||
async function* () {
|
||||
@@ -143,10 +151,80 @@ describe('RemoteAgentInvocation', () => {
|
||||
expect(mockClientManager.loadAgent).toHaveBeenCalledWith(
|
||||
'test-agent',
|
||||
'http://test-agent/card',
|
||||
expect.objectContaining({
|
||||
headers: expect.any(Function),
|
||||
shouldRetryWithHeaders: expect.any(Function),
|
||||
}),
|
||||
undefined,
|
||||
);
|
||||
});
|
||||
|
||||
it('should use A2AAuthProviderFactory when auth is present in definition', async () => {
|
||||
const mockAuth = {
|
||||
type: 'http' as const,
|
||||
scheme: 'Basic' as const,
|
||||
username: 'admin',
|
||||
password: 'password',
|
||||
};
|
||||
const authDefinition: RemoteAgentDefinition = {
|
||||
...mockDefinition,
|
||||
auth: mockAuth,
|
||||
};
|
||||
|
||||
const mockHandler = {
|
||||
type: 'http' as const,
|
||||
headers: vi.fn().mockResolvedValue({ Authorization: 'Basic dGVzdA==' }),
|
||||
shouldRetryWithHeaders: vi.fn(),
|
||||
} as unknown as A2AAuthProvider;
|
||||
(A2AAuthProviderFactory.create as Mock).mockResolvedValue(mockHandler);
|
||||
mockClientManager.getClient.mockReturnValue(undefined);
|
||||
mockClientManager.sendMessageStream.mockImplementation(
|
||||
async function* () {
|
||||
yield {
|
||||
kind: 'message',
|
||||
messageId: 'msg-1',
|
||||
role: 'agent',
|
||||
parts: [{ kind: 'text', text: 'Hello' }],
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
const invocation = new RemoteAgentInvocation(
|
||||
authDefinition,
|
||||
{ query: 'hi' },
|
||||
mockMessageBus,
|
||||
);
|
||||
await invocation.execute(new AbortController().signal);
|
||||
|
||||
expect(A2AAuthProviderFactory.create).toHaveBeenCalledWith({
|
||||
authConfig: mockAuth,
|
||||
agentName: 'test-agent',
|
||||
});
|
||||
expect(mockClientManager.loadAgent).toHaveBeenCalledWith(
|
||||
'test-agent',
|
||||
'http://test-agent/card',
|
||||
mockHandler,
|
||||
);
|
||||
});
|
||||
|
||||
it('should return error when auth provider factory returns undefined for configured auth', async () => {
|
||||
const authDefinition: RemoteAgentDefinition = {
|
||||
...mockDefinition,
|
||||
auth: {
|
||||
type: 'http' as const,
|
||||
scheme: 'Bearer' as const,
|
||||
token: 'secret-token',
|
||||
},
|
||||
};
|
||||
|
||||
(A2AAuthProviderFactory.create as Mock).mockResolvedValue(undefined);
|
||||
mockClientManager.getClient.mockReturnValue(undefined);
|
||||
|
||||
const invocation = new RemoteAgentInvocation(
|
||||
authDefinition,
|
||||
{ query: 'hi' },
|
||||
mockMessageBus,
|
||||
);
|
||||
const result = await invocation.execute(new AbortController().signal);
|
||||
|
||||
expect(result.error?.message).toContain(
|
||||
"Failed to create auth provider for agent 'test-agent'",
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user