feat: enable subagents (#22386)

This commit is contained in:
Abhi
2026-03-16 14:40:12 -04:00
committed by GitHub
parent 56e0865a7b
commit d43ec6c8f3
13 changed files with 111 additions and 59 deletions

View File

@@ -42,6 +42,11 @@ describe('FolderTrustDiscoveryService', () => {
await fs.mkdir(path.join(skillsDir, 'test-skill'), { recursive: true });
await fs.writeFile(path.join(skillsDir, 'test-skill', 'SKILL.md'), 'body');
// Mock agents
const agentsDir = path.join(geminiDir, 'agents');
await fs.mkdir(agentsDir);
await fs.writeFile(path.join(agentsDir, 'test-agent.md'), 'body');
// Mock settings (MCPs, Hooks, and general settings)
const settings = {
mcpServers: {
@@ -62,6 +67,7 @@ describe('FolderTrustDiscoveryService', () => {
expect(results.commands).toContain('test-cmd');
expect(results.skills).toContain('test-skill');
expect(results.agents).toContain('test-agent');
expect(results.mcps).toContain('test-mcp');
expect(results.hooks).toContain('test-hook');
expect(results.settings).toContain('general');
@@ -79,9 +85,6 @@ describe('FolderTrustDiscoveryService', () => {
allowed: ['git'],
sandbox: false,
},
experimental: {
enableAgents: true,
},
security: {
folderTrust: {
enabled: false,
@@ -98,9 +101,6 @@ describe('FolderTrustDiscoveryService', () => {
expect(results.securityWarnings).toContain(
'This project auto-approves certain tools (tools.allowed).',
);
expect(results.securityWarnings).toContain(
'This project enables autonomous agents (enableAgents).',
);
expect(results.securityWarnings).toContain(
'This project attempts to disable folder trust (security.folderTrust.enabled).',
);
@@ -158,4 +158,20 @@ describe('FolderTrustDiscoveryService', () => {
expect(results.discoveryErrors).toHaveLength(0);
expect(results.settings).toHaveLength(0);
});
it('should flag security warning for custom agents', async () => {
const geminiDir = path.join(tempDir, GEMINI_DIR);
await fs.mkdir(geminiDir, { recursive: true });
const agentsDir = path.join(geminiDir, 'agents');
await fs.mkdir(agentsDir);
await fs.writeFile(path.join(agentsDir, 'test-agent.md'), 'body');
const results = await FolderTrustDiscoveryService.discover(tempDir);
expect(results.agents).toContain('test-agent');
expect(results.securityWarnings).toContain(
'This project contains custom agents.',
);
});
});

View File

@@ -16,6 +16,7 @@ export interface FolderDiscoveryResults {
mcps: string[];
hooks: string[];
skills: string[];
agents: string[];
settings: string[];
securityWarnings: string[];
discoveryErrors: string[];
@@ -37,6 +38,7 @@ export class FolderTrustDiscoveryService {
mcps: [],
hooks: [],
skills: [],
agents: [],
settings: [],
securityWarnings: [],
discoveryErrors: [],
@@ -50,6 +52,7 @@ export class FolderTrustDiscoveryService {
await Promise.all([
this.discoverCommands(geminiDir, results),
this.discoverSkills(geminiDir, results),
this.discoverAgents(geminiDir, results),
this.discoverSettings(geminiDir, results),
]);
@@ -99,6 +102,34 @@ export class FolderTrustDiscoveryService {
}
}
private static async discoverAgents(
geminiDir: string,
results: FolderDiscoveryResults,
) {
const agentsDir = path.join(geminiDir, 'agents');
if (await this.exists(agentsDir)) {
try {
const entries = await fs.readdir(agentsDir, { withFileTypes: true });
for (const entry of entries) {
if (
entry.isFile() &&
entry.name.endsWith('.md') &&
!entry.name.startsWith('_')
) {
results.agents.push(path.basename(entry.name, '.md'));
}
}
if (results.agents.length > 0) {
results.securityWarnings.push('This project contains custom agents.');
}
} catch (e) {
results.discoveryErrors.push(
`Failed to discover agents: ${e instanceof Error ? e.message : String(e)}`,
);
}
}
}
private static async discoverSettings(
geminiDir: string,
results: FolderDiscoveryResults,
@@ -119,7 +150,7 @@ export class FolderTrustDiscoveryService {
(key) => !['mcpServers', 'hooks', '$schema'].includes(key),
);
results.securityWarnings = this.collectSecurityWarnings(settings);
results.securityWarnings.push(...this.collectSecurityWarnings(settings));
const mcpServers = settings['mcpServers'];
if (this.isRecord(mcpServers)) {
@@ -159,10 +190,6 @@ export class FolderTrustDiscoveryService {
? settings['tools']
: undefined;
const experimental = this.isRecord(settings['experimental'])
? settings['experimental']
: undefined;
const security = this.isRecord(settings['security'])
? settings['security']
: undefined;
@@ -179,10 +206,6 @@ export class FolderTrustDiscoveryService {
condition: Array.isArray(allowedTools) && allowedTools.length > 0,
message: 'This project auto-approves certain tools (tools.allowed).',
},
{
condition: experimental?.['enableAgents'] === true,
message: 'This project enables autonomous agents (enableAgents).',
},
{
condition: folderTrust?.['enabled'] === false,
message: