feat(a2a): add agent acknowledgment command and enhance registry discovery (#22389)

This commit is contained in:
Alisa
2026-03-17 15:47:05 -07:00
committed by GitHub
parent fb9264bf80
commit 7ae39fd622
15 changed files with 250 additions and 94 deletions
@@ -19,6 +19,8 @@ import {
AuthType,
isHeadlessMode,
FatalAuthenticationError,
PolicyDecision,
PRIORITY_YOLO_ALLOW_ALL,
} from '@google/gemini-cli-core';
// Mock dependencies
@@ -325,6 +327,29 @@ describe('loadConfig', () => {
);
});
it('should pass enableAgents to Config constructor', async () => {
const settings: Settings = {
experimental: {
enableAgents: false,
},
};
await loadConfig(settings, mockExtensionLoader, taskId);
expect(Config).toHaveBeenCalledWith(
expect.objectContaining({
enableAgents: false,
}),
);
});
it('should default enableAgents to true when not provided', async () => {
await loadConfig(mockSettings, mockExtensionLoader, taskId);
expect(Config).toHaveBeenCalledWith(
expect.objectContaining({
enableAgents: true,
}),
);
});
describe('interactivity', () => {
it('should set interactive true when not headless', async () => {
vi.mocked(isHeadlessMode).mockReturnValue(false);
@@ -349,6 +374,41 @@ describe('loadConfig', () => {
});
});
describe('YOLO mode', () => {
it('should enable YOLO mode and add policy rule when GEMINI_YOLO_MODE is true', async () => {
vi.stubEnv('GEMINI_YOLO_MODE', 'true');
await loadConfig(mockSettings, mockExtensionLoader, taskId);
expect(Config).toHaveBeenCalledWith(
expect.objectContaining({
approvalMode: 'yolo',
policyEngineConfig: expect.objectContaining({
rules: expect.arrayContaining([
expect.objectContaining({
decision: PolicyDecision.ALLOW,
priority: PRIORITY_YOLO_ALLOW_ALL,
modes: ['yolo'],
allowRedirection: true,
}),
]),
}),
}),
);
});
it('should use default approval mode and empty rules when GEMINI_YOLO_MODE is not true', async () => {
vi.stubEnv('GEMINI_YOLO_MODE', 'false');
await loadConfig(mockSettings, mockExtensionLoader, taskId);
expect(Config).toHaveBeenCalledWith(
expect.objectContaining({
approvalMode: 'default',
policyEngineConfig: expect.objectContaining({
rules: [],
}),
}),
);
});
});
describe('authentication fallback', () => {
beforeEach(() => {
vi.stubEnv('USE_CCPA', 'true');
+22 -4
View File
@@ -26,6 +26,8 @@ import {
isHeadlessMode,
FatalAuthenticationError,
isCloudShell,
PolicyDecision,
PRIORITY_YOLO_ALLOW_ALL,
type TelemetryTarget,
type ConfigParameters,
type ExtensionLoader,
@@ -60,6 +62,11 @@ export async function loadConfig(
}
}
const approvalMode =
process.env['GEMINI_YOLO_MODE'] === 'true'
? ApprovalMode.YOLO
: ApprovalMode.DEFAULT;
const configParams: ConfigParameters = {
sessionId: taskId,
clientName: 'a2a-server',
@@ -74,10 +81,20 @@ export async function loadConfig(
excludeTools: settings.excludeTools || settings.tools?.exclude || undefined,
allowedTools: settings.allowedTools || settings.tools?.allowed || undefined,
showMemoryUsage: settings.showMemoryUsage || false,
approvalMode:
process.env['GEMINI_YOLO_MODE'] === 'true'
? ApprovalMode.YOLO
: ApprovalMode.DEFAULT,
approvalMode,
policyEngineConfig: {
rules:
approvalMode === ApprovalMode.YOLO
? [
{
decision: PolicyDecision.ALLOW,
priority: PRIORITY_YOLO_ALLOW_ALL,
modes: [ApprovalMode.YOLO],
allowRedirection: true,
},
]
: [],
},
mcpServers: settings.mcpServers,
cwd: workspaceDir,
telemetry: {
@@ -110,6 +127,7 @@ export async function loadConfig(
interactive: !isHeadlessMode(),
enableInteractiveShell: !isHeadlessMode(),
ptyInfo: 'auto',
enableAgents: settings.experimental?.enableAgents ?? true,
};
const fileService = new FileDiscoveryService(workspaceDir, {
@@ -112,6 +112,18 @@ describe('loadSettings', () => {
expect(result.fileFiltering?.respectGitIgnore).toBe(true);
});
it('should load experimental settings correctly', () => {
const settings = {
experimental: {
enableAgents: true,
},
};
fs.writeFileSync(USER_SETTINGS_PATH, JSON.stringify(settings));
const result = loadSettings(mockWorkspaceDir);
expect(result.experimental?.enableAgents).toBe(true);
});
it('should overwrite top-level settings from workspace (shallow merge)', () => {
const userSettings = {
showMemoryUsage: false,
@@ -48,6 +48,9 @@ export interface Settings {
enableRecursiveFileSearch?: boolean;
customIgnoreFilePaths?: string[];
};
experimental?: {
enableAgents?: boolean;
};
}
export interface SettingsError {