diff --git a/docs/cli/settings.md b/docs/cli/settings.md index de4b745722..7a545fb351 100644 --- a/docs/cli/settings.md +++ b/docs/cli/settings.md @@ -113,14 +113,11 @@ they appear in the UI. ### Experimental -| UI Label | Setting | Description | Default | -| ----------------------------------- | ------------------------------------------------------- | ----------------------------------------------------------------------------------- | ------- | -| Agent Skills | `experimental.skills` | Enable Agent Skills (experimental). | `false` | -| Enable Codebase Investigator | `experimental.codebaseInvestigatorSettings.enabled` | Enable the Codebase Investigator agent. | `true` | -| Codebase Investigator Max Num Turns | `experimental.codebaseInvestigatorSettings.maxNumTurns` | Maximum number of turns for the Codebase Investigator agent. | `10` | -| Use OSC 52 Paste | `experimental.useOSC52Paste` | Use OSC 52 sequence for pasting instead of clipboardy (useful for remote sessions). | `false` | -| Enable CLI Help Agent | `experimental.cliHelpAgentSettings.enabled` | Enable the CLI Help Agent. | `true` | -| Plan | `experimental.plan` | Enable planning features (Plan Mode and tools). | `false` | +| UI Label | Setting | Description | Default | +| ---------------- | ---------------------------- | ----------------------------------------------------------------------------------- | ------- | +| Agent Skills | `experimental.skills` | Enable Agent Skills (experimental). | `false` | +| Use OSC 52 Paste | `experimental.useOSC52Paste` | Use OSC 52 sequence for pasting instead of clipboardy (useful for remote sessions). | `false` | +| Plan | `experimental.plan` | Enable planning features (Plan Mode and tools). | `false` | ### HooksConfig diff --git a/docs/get-started/configuration.md b/docs/get-started/configuration.md index 2f4ab2c132..726292160e 100644 --- a/docs/get-started/configuration.md +++ b/docs/get-started/configuration.md @@ -855,43 +855,11 @@ their corresponding top-level category object in your `settings.json` file. - **Default:** `false` - **Requires restart:** Yes -- **`experimental.codebaseInvestigatorSettings.enabled`** (boolean): - - **Description:** Enable the Codebase Investigator agent. - - **Default:** `true` - - **Requires restart:** Yes - -- **`experimental.codebaseInvestigatorSettings.maxNumTurns`** (number): - - **Description:** Maximum number of turns for the Codebase Investigator - agent. - - **Default:** `10` - - **Requires restart:** Yes - -- **`experimental.codebaseInvestigatorSettings.maxTimeMinutes`** (number): - - **Description:** Maximum time for the Codebase Investigator agent (in - minutes). - - **Default:** `3` - - **Requires restart:** Yes - -- **`experimental.codebaseInvestigatorSettings.thinkingBudget`** (number): - - **Description:** The thinking budget for the Codebase Investigator agent. - - **Default:** `8192` - - **Requires restart:** Yes - -- **`experimental.codebaseInvestigatorSettings.model`** (string): - - **Description:** The model to use for the Codebase Investigator agent. - - **Default:** `"auto"` - - **Requires restart:** Yes - - **`experimental.useOSC52Paste`** (boolean): - **Description:** Use OSC 52 sequence for pasting instead of clipboardy (useful for remote sessions). - **Default:** `false` -- **`experimental.cliHelpAgentSettings.enabled`** (boolean): - - **Description:** Enable the CLI Help Agent. - - **Default:** `true` - - **Requires restart:** Yes - - **`experimental.plan`** (boolean): - **Description:** Enable planning features (Plan Mode and tools). - **Default:** `false` diff --git a/packages/cli/src/config/config.ts b/packages/cli/src/config/config.ts index 7d58eefaa3..efc1616300 100755 --- a/packages/cli/src/config/config.ts +++ b/packages/cli/src/config/config.ts @@ -764,9 +764,6 @@ export async function loadCliConfig( output: { format: (argv.outputFormat ?? settings.output?.format) as OutputFormat, }, - codebaseInvestigatorSettings: - settings.experimental?.codebaseInvestigatorSettings, - cliHelpAgentSettings: settings.experimental?.cliHelpAgentSettings, fakeResponses: argv.fakeResponses, recordResponses: argv.recordResponses, retryFetchErrors: settings.general?.retryFetchErrors, diff --git a/packages/cli/src/config/settings.test.ts b/packages/cli/src/config/settings.test.ts index ff201bcfe8..be5f3d14f9 100644 --- a/packages/cli/src/config/settings.test.ts +++ b/packages/cli/src/config/settings.test.ts @@ -2012,6 +2012,56 @@ describe('Settings Loading and Merging', () => { // Merged should also reflect it (system overrides defaults, but both are migrated) expect(settings.merged.general?.enableAutoUpdateNotification).toBe(false); }); + + it('should migrate experimental agent settings to agents overrides', () => { + const userSettingsContent = { + experimental: { + codebaseInvestigatorSettings: { + enabled: true, + maxNumTurns: 15, + maxTimeMinutes: 5, + thinkingBudget: 16384, + model: 'gemini-1.5-pro', + }, + cliHelpAgentSettings: { + enabled: false, + }, + }, + }; + + vi.mocked(fs.existsSync).mockReturnValue(true); + (fs.readFileSync as Mock).mockImplementation( + (p: fs.PathOrFileDescriptor) => { + if (p === USER_SETTINGS_PATH) + return JSON.stringify(userSettingsContent); + return '{}'; + }, + ); + + const settings = loadSettings(MOCK_WORKSPACE_DIR); + + // Verify migration to agents.overrides + expect(settings.user.settings.agents?.overrides).toMatchObject({ + codebase_investigator: { + enabled: true, + runConfig: { + maxTurns: 15, + maxTimeMinutes: 5, + }, + modelConfig: { + model: 'gemini-1.5-pro', + generateContentConfig: { + thinkingConfig: { + thinkingBudget: 16384, + }, + }, + }, + }, + cli_help: { + enabled: false, + }, + }); + }); }); describe('saveSettings', () => { diff --git a/packages/cli/src/config/settings.ts b/packages/cli/src/config/settings.ts index a9d29e56a4..d7da64195f 100644 --- a/packages/cli/src/config/settings.ts +++ b/packages/cli/src/config/settings.ts @@ -804,6 +804,14 @@ export function migrateDeprecatedSettings( anyModified = true; } } + + // Migrate experimental agent settings + anyModified ||= migrateExperimentalSettings( + settings, + loadedSettings, + scope, + removeDeprecated, + ); }; processScope(SettingScope.User); @@ -852,3 +860,100 @@ export function saveModelChange( ); } } + +function migrateExperimentalSettings( + settings: Settings, + loadedSettings: LoadedSettings, + scope: LoadableSettingScope, + removeDeprecated: boolean, +): boolean { + const experimentalSettings = settings.experimental as + | Record + | undefined; + if (experimentalSettings) { + const agentsSettings = { + ...(settings.agents as Record | undefined), + }; + const agentsOverrides = { + ...((agentsSettings['overrides'] as Record) || {}), + }; + let modified = false; + + // Migrate codebaseInvestigatorSettings -> agents.overrides.codebase_investigator + if (experimentalSettings['codebaseInvestigatorSettings']) { + const old = experimentalSettings[ + 'codebaseInvestigatorSettings' + ] as Record; + const override = { + ...(agentsOverrides['codebase_investigator'] as + | Record + | undefined), + }; + + if (old['enabled'] !== undefined) override['enabled'] = old['enabled']; + + const runConfig = { + ...(override['runConfig'] as Record | undefined), + }; + if (old['maxNumTurns'] !== undefined) + runConfig['maxTurns'] = old['maxNumTurns']; + if (old['maxTimeMinutes'] !== undefined) + runConfig['maxTimeMinutes'] = old['maxTimeMinutes']; + if (Object.keys(runConfig).length > 0) override['runConfig'] = runConfig; + + if (old['model'] !== undefined || old['thinkingBudget'] !== undefined) { + const modelConfig = { + ...(override['modelConfig'] as Record | undefined), + }; + if (old['model'] !== undefined) modelConfig['model'] = old['model']; + if (old['thinkingBudget'] !== undefined) { + const generateContentConfig = { + ...(modelConfig['generateContentConfig'] as + | Record + | undefined), + }; + const thinkingConfig = { + ...(generateContentConfig['thinkingConfig'] as + | Record + | undefined), + }; + thinkingConfig['thinkingBudget'] = old['thinkingBudget']; + generateContentConfig['thinkingConfig'] = thinkingConfig; + modelConfig['generateContentConfig'] = generateContentConfig; + } + override['modelConfig'] = modelConfig; + } + + agentsOverrides['codebase_investigator'] = override; + modified = true; + } + + // Migrate cliHelpAgentSettings -> agents.overrides.cli_help + if (experimentalSettings['cliHelpAgentSettings']) { + const old = experimentalSettings['cliHelpAgentSettings'] as Record< + string, + unknown + >; + const override = { + ...(agentsOverrides['cli_help'] as Record | undefined), + }; + if (old['enabled'] !== undefined) override['enabled'] = old['enabled']; + agentsOverrides['cli_help'] = override; + modified = true; + } + + if (modified) { + agentsSettings['overrides'] = agentsOverrides; + loadedSettings.setValue(scope, 'agents', agentsSettings); + + if (removeDeprecated) { + const newExperimental = { ...experimentalSettings }; + delete newExperimental['codebaseInvestigatorSettings']; + delete newExperimental['cliHelpAgentSettings']; + loadedSettings.setValue(scope, 'experimental', newExperimental); + } + return true; + } + } + return false; +} diff --git a/packages/cli/src/config/settingsSchema.ts b/packages/cli/src/config/settingsSchema.ts index 96ec8c9ff1..89e75f32f9 100644 --- a/packages/cli/src/config/settingsSchema.ts +++ b/packages/cli/src/config/settingsSchema.ts @@ -20,7 +20,6 @@ import { DEFAULT_TRUNCATE_TOOL_OUTPUT_LINES, DEFAULT_TRUNCATE_TOOL_OUTPUT_THRESHOLD, DEFAULT_MODEL_CONFIGS, - GEMINI_MODEL_ALIAS_AUTO, } from '@google/gemini-cli-core'; import type { CustomTheme } from '../ui/themes/theme.js'; import type { SessionRetentionSettings } from './settings.js'; @@ -1461,66 +1460,6 @@ const SETTINGS_SCHEMA = { description: 'Enable Agent Skills (experimental).', showInDialog: true, }, - codebaseInvestigatorSettings: { - type: 'object', - label: 'Codebase Investigator Settings', - category: 'Experimental', - requiresRestart: true, - default: {}, - description: 'Configuration for Codebase Investigator.', - showInDialog: false, - properties: { - enabled: { - type: 'boolean', - label: 'Enable Codebase Investigator', - category: 'Experimental', - requiresRestart: true, - default: true, - description: 'Enable the Codebase Investigator agent.', - showInDialog: true, - }, - maxNumTurns: { - type: 'number', - label: 'Codebase Investigator Max Num Turns', - category: 'Experimental', - requiresRestart: true, - default: 10, - description: - 'Maximum number of turns for the Codebase Investigator agent.', - showInDialog: true, - }, - maxTimeMinutes: { - type: 'number', - label: 'Max Time (Minutes)', - category: 'Experimental', - requiresRestart: true, - default: 3, - description: - 'Maximum time for the Codebase Investigator agent (in minutes).', - showInDialog: false, - }, - thinkingBudget: { - type: 'number', - label: 'Thinking Budget', - category: 'Experimental', - requiresRestart: true, - default: 8192, - description: - 'The thinking budget for the Codebase Investigator agent.', - showInDialog: false, - }, - model: { - type: 'string', - label: 'Model', - category: 'Experimental', - requiresRestart: true, - default: GEMINI_MODEL_ALIAS_AUTO, - description: - 'The model to use for the Codebase Investigator agent.', - showInDialog: false, - }, - }, - }, useOSC52Paste: { type: 'boolean', label: 'Use OSC 52 Paste', @@ -1531,26 +1470,6 @@ const SETTINGS_SCHEMA = { 'Use OSC 52 sequence for pasting instead of clipboardy (useful for remote sessions).', showInDialog: true, }, - cliHelpAgentSettings: { - type: 'object', - label: 'CLI Help Agent Settings', - category: 'Experimental', - requiresRestart: true, - default: {}, - description: 'Configuration for CLI Help Agent.', - showInDialog: false, - properties: { - enabled: { - type: 'boolean', - label: 'Enable CLI Help Agent', - category: 'Experimental', - requiresRestart: true, - default: true, - description: 'Enable the CLI Help Agent.', - showInDialog: true, - }, - }, - }, plan: { type: 'boolean', label: 'Plan', diff --git a/packages/cli/src/config/settings_repro.test.ts b/packages/cli/src/config/settings_repro.test.ts index 404554ddbd..de4cc9ad8e 100644 --- a/packages/cli/src/config/settings_repro.test.ts +++ b/packages/cli/src/config/settings_repro.test.ts @@ -155,8 +155,12 @@ describe('Settings Repro', () => { experimental: { useModelRouter: false, enableSubagents: false, - codebaseInvestigatorSettings: { - enabled: true, + }, + agents: { + overrides: { + codebase_investigator: { + enabled: true, + }, }, }, ui: { diff --git a/packages/cli/src/ui/components/SettingsDialog.test.tsx b/packages/cli/src/ui/components/SettingsDialog.test.tsx index b5c7eed461..c58910628f 100644 --- a/packages/cli/src/ui/components/SettingsDialog.test.tsx +++ b/packages/cli/src/ui/components/SettingsDialog.test.tsx @@ -381,7 +381,7 @@ describe('SettingsDialog', () => { await waitFor(() => { // Should wrap to last setting (without relying on exact bullet character) - expect(lastFrame()).toContain('Codebase Investigator Max Num Turns'); + expect(lastFrame()).toContain('Hook Notifications'); }); unmount(); @@ -1213,9 +1213,7 @@ describe('SettingsDialog', () => { await waitFor(() => { expect(lastFrame()).toContain('vim'); expect(lastFrame()).toContain('Vim Mode'); - expect(lastFrame()).not.toContain( - 'Codebase Investigator Max Num Turns', - ); + expect(lastFrame()).not.toContain('Hook Notifications'); }); unmount(); diff --git a/packages/core/src/agents/codebase-investigator.test.ts b/packages/core/src/agents/codebase-investigator.test.ts index c7cbee92cc..27895c9413 100644 --- a/packages/core/src/agents/codebase-investigator.test.ts +++ b/packages/core/src/agents/codebase-investigator.test.ts @@ -13,24 +13,24 @@ import { READ_FILE_TOOL_NAME, } from '../tools/tool-names.js'; import { DEFAULT_GEMINI_MODEL } from '../config/models.js'; +import { makeFakeConfig } from '../test-utils/config.js'; describe('CodebaseInvestigatorAgent', () => { + const config = makeFakeConfig(); + const agent = CodebaseInvestigatorAgent(config); + it('should have the correct agent definition', () => { - expect(CodebaseInvestigatorAgent.name).toBe('codebase_investigator'); - expect(CodebaseInvestigatorAgent.displayName).toBe( - 'Codebase Investigator Agent', - ); - expect(CodebaseInvestigatorAgent.description).toBeDefined(); + expect(agent.name).toBe('codebase_investigator'); + expect(agent.displayName).toBe('Codebase Investigator Agent'); + expect(agent.description).toBeDefined(); const inputSchema = // eslint-disable-next-line @typescript-eslint/no-explicit-any - CodebaseInvestigatorAgent.inputConfig.inputSchema as any; + agent.inputConfig.inputSchema as any; expect(inputSchema.properties['objective']).toBeDefined(); expect(inputSchema.required).toContain('objective'); - expect(CodebaseInvestigatorAgent.outputConfig?.outputName).toBe('report'); - expect(CodebaseInvestigatorAgent.modelConfig?.model).toBe( - DEFAULT_GEMINI_MODEL, - ); - expect(CodebaseInvestigatorAgent.toolConfig?.tools).toEqual([ + expect(agent.outputConfig?.outputName).toBe('report'); + expect(agent.modelConfig?.model).toBe(DEFAULT_GEMINI_MODEL); + expect(agent.toolConfig?.tools).toEqual([ LS_TOOL_NAME, READ_FILE_TOOL_NAME, GLOB_TOOL_NAME, @@ -44,7 +44,7 @@ describe('CodebaseInvestigatorAgent', () => { ExplorationTrace: ['trace'], RelevantLocations: [], }; - const processed = CodebaseInvestigatorAgent.processOutput?.(report); + const processed = agent.processOutput?.(report); expect(processed).toBe(JSON.stringify(report, null, 2)); }); }); diff --git a/packages/core/src/agents/codebase-investigator.ts b/packages/core/src/agents/codebase-investigator.ts index bdfa378c50..662ade546c 100644 --- a/packages/core/src/agents/codebase-investigator.ts +++ b/packages/core/src/agents/codebase-investigator.ts @@ -11,8 +11,15 @@ import { LS_TOOL_NAME, READ_FILE_TOOL_NAME, } from '../tools/tool-names.js'; -import { DEFAULT_GEMINI_MODEL } from '../config/models.js'; +import { + DEFAULT_THINKING_MODE, + DEFAULT_GEMINI_MODEL, + PREVIEW_GEMINI_FLASH_MODEL, + isPreviewModel, +} from '../config/models.js'; import { z } from 'zod'; +import type { Config } from '../config/config.js'; +import { ThinkingLevel } from '@google/genai'; // Define a type that matches the outputConfig schema for type safety. const CodebaseInvestigationReportSchema = z.object({ @@ -41,65 +48,82 @@ const CodebaseInvestigationReportSchema = z.object({ * A Proof-of-Concept subagent specialized in analyzing codebase structure, * dependencies, and technologies. */ -export const CodebaseInvestigatorAgent: LocalAgentDefinition< - typeof CodebaseInvestigationReportSchema -> = { - name: 'codebase_investigator', - kind: 'local', - displayName: 'Codebase Investigator Agent', - description: `The specialized tool for codebase analysis, architectural mapping, and understanding system-wide dependencies. +export const CodebaseInvestigatorAgent = ( + config: Config, +): LocalAgentDefinition => { + // Use Preview Flash model if the main model is any of the preview models. + // If the main model is not a preview model, use the default pro model. + const model = isPreviewModel(config.getModel()) + ? PREVIEW_GEMINI_FLASH_MODEL + : DEFAULT_GEMINI_MODEL; + + return { + name: 'codebase_investigator', + kind: 'local', + displayName: 'Codebase Investigator Agent', + description: `The specialized tool for codebase analysis, architectural mapping, and understanding system-wide dependencies. Invoke this tool for tasks like vague requests, bug root-cause analysis, system refactoring, comprehensive feature implementation or to answer questions about the codebase that require investigation. It returns a structured report with key file paths, symbols, and actionable architectural insights.`, - inputConfig: { - inputSchema: { - type: 'object', - properties: { - objective: { - type: 'string', - description: `A comprehensive and detailed description of the user's ultimate goal. + inputConfig: { + inputSchema: { + type: 'object', + properties: { + objective: { + type: 'string', + description: `A comprehensive and detailed description of the user's ultimate goal. You must include original user's objective as well as questions and any extra context and questions you may have.`, + }, }, - }, - required: ['objective'], - }, - }, - outputConfig: { - outputName: 'report', - description: 'The final investigation report as a JSON object.', - schema: CodebaseInvestigationReportSchema, - }, - - // The 'output' parameter is now strongly typed as CodebaseInvestigationReportSchema - processOutput: (output) => JSON.stringify(output, null, 2), - - modelConfig: { - model: DEFAULT_GEMINI_MODEL, - generateContentConfig: { - temperature: 0.1, - topP: 0.95, - thinkingConfig: { - includeThoughts: true, - thinkingBudget: -1, + required: ['objective'], }, }, - }, + outputConfig: { + outputName: 'report', + description: 'The final investigation report as a JSON object.', + schema: CodebaseInvestigationReportSchema, + }, - runConfig: { - maxTimeMinutes: 5, - maxTurns: 15, - }, + // The 'output' parameter is now strongly typed as CodebaseInvestigationReportSchema + processOutput: (output) => JSON.stringify(output, null, 2), - toolConfig: { - // Grant access only to read-only tools. - tools: [LS_TOOL_NAME, READ_FILE_TOOL_NAME, GLOB_TOOL_NAME, GREP_TOOL_NAME], - }, + modelConfig: { + model, + generateContentConfig: { + temperature: 0.1, + topP: 0.95, + thinkingConfig: isPreviewModel(model) + ? { + includeThoughts: true, + thinkingLevel: ThinkingLevel.HIGH, + } + : { + includeThoughts: true, + thinkingBudget: DEFAULT_THINKING_MODE, + }, + }, + }, - promptConfig: { - query: `Your task is to do a deep investigation of the codebase to find all relevant files, code locations, architectural mental map and insights to solve for the following user objective: + runConfig: { + maxTimeMinutes: 3, + maxTurns: 10, + }, + + toolConfig: { + // Grant access only to read-only tools. + tools: [ + LS_TOOL_NAME, + READ_FILE_TOOL_NAME, + GLOB_TOOL_NAME, + GREP_TOOL_NAME, + ], + }, + + promptConfig: { + query: `Your task is to do a deep investigation of the codebase to find all relevant files, code locations, architectural mental map and insights to solve for the following user objective: \${objective} `, - systemPrompt: `You are **Codebase Investigator**, a hyper-specialized AI agent and an expert in reverse-engineering complex software projects. You are a sub-agent within a larger development system. + systemPrompt: `You are **Codebase Investigator**, a hyper-specialized AI agent and an expert in reverse-engineering complex software projects. You are a sub-agent within a larger development system. Your **SOLE PURPOSE** is to build a complete mental model of the code relevant to a given investigation. You must identify all relevant files, understand their roles, and foresee the direct architectural consequences of potential changes. You are a sub-agent in a larger system. Your only responsibility is to provide deep, actionable context. - **DO:** Find the key modules, classes, and functions that are part of the problem and its solution. @@ -158,5 +182,6 @@ When you are finished, you **MUST** call the \`complete_task\` tool. The \`repor } \`\`\` `, - }, + }, + }; }; diff --git a/packages/core/src/agents/registry.test.ts b/packages/core/src/agents/registry.test.ts index df7dea9384..3d0cdec1a0 100644 --- a/packages/core/src/agents/registry.test.ts +++ b/packages/core/src/agents/registry.test.ts @@ -14,7 +14,8 @@ import { coreEvents, CoreEvent } from '../utils/events.js'; import { A2AClientManager } from './a2a-client-manager.js'; import { DEFAULT_GEMINI_FLASH_LITE_MODEL, - GEMINI_MODEL_ALIAS_AUTO, + DEFAULT_GEMINI_MODEL, + DEFAULT_THINKING_MODE, PREVIEW_GEMINI_FLASH_MODEL, PREVIEW_GEMINI_MODEL, PREVIEW_GEMINI_MODEL_AUTO, @@ -23,6 +24,7 @@ import * as tomlLoader from './agentLoader.js'; import { SimpleExtensionLoader } from '../utils/extensionLoader.js'; import type { ConfigParameters } from '../config/config.js'; import type { ToolRegistry } from '../tools/tool-registry.js'; +import { ThinkingLevel } from '@google/genai'; vi.mock('./agentLoader.js', () => ({ loadAgentsFromDirectory: vi @@ -127,14 +129,27 @@ describe('AgentRegistry', () => { ); }); - it('should use preview flash model for codebase investigator if main model is preview pro', async () => { - const previewConfig = makeMockedConfig({ - model: PREVIEW_GEMINI_MODEL, - codebaseInvestigatorSettings: { - enabled: true, - model: GEMINI_MODEL_ALIAS_AUTO, - }, + it('should use default model for codebase investigator for non-preview models', async () => { + const previewConfig = makeMockedConfig({ model: DEFAULT_GEMINI_MODEL }); + const previewRegistry = new TestableAgentRegistry(previewConfig); + + await previewRegistry.initialize(); + + const investigatorDef = previewRegistry.getDefinition( + 'codebase_investigator', + ) as LocalAgentDefinition; + expect(investigatorDef).toBeDefined(); + expect(investigatorDef?.modelConfig.model).toBe(DEFAULT_GEMINI_MODEL); + expect( + investigatorDef?.modelConfig.generateContentConfig?.thinkingConfig, + ).toStrictEqual({ + includeThoughts: true, + thinkingBudget: DEFAULT_THINKING_MODE, }); + }); + + it('should use preview flash model for codebase investigator if main model is preview pro', async () => { + const previewConfig = makeMockedConfig({ model: PREVIEW_GEMINI_MODEL }); const previewRegistry = new TestableAgentRegistry(previewConfig); await previewRegistry.initialize(); @@ -146,15 +161,17 @@ describe('AgentRegistry', () => { expect(investigatorDef?.modelConfig.model).toBe( PREVIEW_GEMINI_FLASH_MODEL, ); + expect( + investigatorDef?.modelConfig.generateContentConfig?.thinkingConfig, + ).toStrictEqual({ + includeThoughts: true, + thinkingLevel: ThinkingLevel.HIGH, + }); }); it('should use preview flash model for codebase investigator if main model is preview auto', async () => { const previewConfig = makeMockedConfig({ model: PREVIEW_GEMINI_MODEL_AUTO, - codebaseInvestigatorSettings: { - enabled: true, - model: GEMINI_MODEL_ALIAS_AUTO, - }, }); const previewRegistry = new TestableAgentRegistry(previewConfig); @@ -172,9 +189,13 @@ describe('AgentRegistry', () => { it('should use the model from the investigator settings', async () => { const previewConfig = makeMockedConfig({ model: PREVIEW_GEMINI_MODEL, - codebaseInvestigatorSettings: { - enabled: true, - model: DEFAULT_GEMINI_FLASH_LITE_MODEL, + agents: { + overrides: { + codebase_investigator: { + enabled: true, + modelConfig: { model: DEFAULT_GEMINI_FLASH_LITE_MODEL }, + }, + }, }, }); const previewRegistry = new TestableAgentRegistry(previewConfig); @@ -232,8 +253,12 @@ describe('AgentRegistry', () => { it('should NOT load TOML agents when enableAgents is false', async () => { const disabledConfig = makeMockedConfig({ enableAgents: false, - codebaseInvestigatorSettings: { enabled: false }, - cliHelpAgentSettings: { enabled: false }, + agents: { + overrides: { + codebase_investigator: { enabled: false }, + cli_help: { enabled: false }, + }, + }, }); const disabledRegistry = new TestableAgentRegistry(disabledConfig); @@ -254,9 +279,13 @@ describe('AgentRegistry', () => { expect(registry.getDefinition('cli_help')).toBeDefined(); }); - it('should register CLI help agent if disabled', async () => { + it('should NOT register CLI help agent if disabled', async () => { const config = makeMockedConfig({ - cliHelpAgentSettings: { enabled: false }, + agents: { + overrides: { + cli_help: { enabled: false }, + }, + }, }); const registry = new TestableAgentRegistry(config); diff --git a/packages/core/src/agents/registry.ts b/packages/core/src/agents/registry.ts index 4ca210abfa..9b317d9e3c 100644 --- a/packages/core/src/agents/registry.ts +++ b/packages/core/src/agents/registry.ts @@ -16,13 +16,7 @@ import { A2AClientManager } from './a2a-client-manager.js'; import { ADCHandler } from './remote-invocation.js'; import { type z } from 'zod'; import { debugLogger } from '../utils/debugLogger.js'; -import { - DEFAULT_GEMINI_MODEL, - GEMINI_MODEL_ALIAS_AUTO, - PREVIEW_GEMINI_FLASH_MODEL, - isPreviewModel, - isAutoModel, -} from '../config/models.js'; +import { isAutoModel } from '../config/models.js'; import { type ModelConfig, ModelConfigService, @@ -149,68 +143,8 @@ export class AgentRegistry { } private loadBuiltInAgents(): void { - const investigatorSettings = this.config.getCodebaseInvestigatorSettings(); - const cliHelpSettings = this.config.getCliHelpAgentSettings(); - const agentsSettings = this.config.getAgentsSettings(); - const agentsOverrides = agentsSettings.overrides ?? {}; - - // Only register the agent if it's enabled in the settings and not explicitly disabled via overrides. - if ( - investigatorSettings?.enabled && - agentsOverrides[CodebaseInvestigatorAgent.name]?.enabled !== false - ) { - let model; - const settingsModel = investigatorSettings.model; - // Check if the user explicitly set a model in the settings. - if (settingsModel && settingsModel !== GEMINI_MODEL_ALIAS_AUTO) { - model = settingsModel; - } else { - // Use Preview Flash model if the main model is any of the preview models - // If the main model is not preview model, use default pro model. - model = isPreviewModel(this.config.getModel()) - ? PREVIEW_GEMINI_FLASH_MODEL - : DEFAULT_GEMINI_MODEL; - } - - const agentDef = { - ...CodebaseInvestigatorAgent, - modelConfig: { - ...CodebaseInvestigatorAgent.modelConfig, - model, - generateContentConfig: { - ...CodebaseInvestigatorAgent.modelConfig.generateContentConfig, - thinkingConfig: { - ...CodebaseInvestigatorAgent.modelConfig.generateContentConfig - ?.thinkingConfig, - thinkingBudget: - investigatorSettings.thinkingBudget ?? - CodebaseInvestigatorAgent.modelConfig.generateContentConfig - ?.thinkingConfig?.thinkingBudget, - }, - }, - }, - runConfig: { - ...CodebaseInvestigatorAgent.runConfig, - maxTimeMinutes: - investigatorSettings.maxTimeMinutes ?? - CodebaseInvestigatorAgent.runConfig.maxTimeMinutes, - maxTurns: - investigatorSettings.maxNumTurns ?? - CodebaseInvestigatorAgent.runConfig.maxTurns, - }, - }; - this.registerLocalAgent(agentDef); - } - - // Register the CLI help agent if it's explicitly enabled and not explicitly disabled via overrides. - if ( - cliHelpSettings.enabled && - agentsOverrides[CliHelpAgent.name]?.enabled !== false - ) { - this.registerLocalAgent(CliHelpAgent(this.config)); - } - - // Register the generalist agent. + this.registerLocalAgent(CodebaseInvestigatorAgent(this.config)); + this.registerLocalAgent(CliHelpAgent(this.config)); this.registerLocalAgent(GeneralistAgent(this.config)); } diff --git a/packages/core/src/config/config.test.ts b/packages/core/src/config/config.test.ts index e20e4b2ef6..23b9f78025 100644 --- a/packages/core/src/config/config.test.ts +++ b/packages/core/src/config/config.test.ts @@ -941,10 +941,14 @@ describe('Server Config (config.ts)', () => { expect(wasReadFileToolRegistered).toBe(false); }); - it('should register subagents as tools when codebaseInvestigatorSettings.enabled is true', async () => { + it('should register subagents as tools when agents.overrides.codebase_investigator.enabled is true', async () => { const params: ConfigParameters = { ...baseParams, - codebaseInvestigatorSettings: { enabled: true }, + agents: { + overrides: { + codebase_investigator: { enabled: true }, + }, + }, }; const config = new Config(params); @@ -991,11 +995,15 @@ describe('Server Config (config.ts)', () => { expect(registeredWrappers).toHaveLength(1); }); - it('should not register subagents as tools when codebaseInvestigatorSettings.enabled is false', async () => { + it('should not register subagents as tools when agents are disabled', async () => { const params: ConfigParameters = { ...baseParams, - codebaseInvestigatorSettings: { enabled: false }, - cliHelpAgentSettings: { enabled: false }, + agents: { + overrides: { + codebase_investigator: { enabled: false }, + cli_help: { enabled: false }, + }, + }, }; const config = new Config(params); @@ -1010,11 +1018,6 @@ describe('Server Config (config.ts)', () => { expect(DelegateToAgentToolMock).not.toHaveBeenCalled(); }); - it('should not set default codebase investigator model in config (defaults in registry)', () => { - const config = new Config(baseParams); - expect(config.getCodebaseInvestigatorSettings()?.model).toBeUndefined(); - }); - describe('with minified tool class names', () => { beforeEach(() => { Object.defineProperty( diff --git a/packages/core/src/config/config.ts b/packages/core/src/config/config.ts index 15a1bcb85f..6bfefdc05c 100644 --- a/packages/core/src/config/config.ts +++ b/packages/core/src/config/config.ts @@ -49,7 +49,6 @@ import { DEFAULT_GEMINI_EMBEDDING_MODEL, DEFAULT_GEMINI_FLASH_MODEL, DEFAULT_GEMINI_MODEL_AUTO, - DEFAULT_THINKING_MODE, isPreviewModel, PREVIEW_GEMINI_MODEL, PREVIEW_GEMINI_MODEL_AUTO, @@ -144,14 +143,6 @@ export interface OutputSettings { format?: OutputFormat; } -export interface CodebaseInvestigatorSettings { - enabled?: boolean; - maxNumTurns?: number; - maxTimeMinutes?: number; - thinkingBudget?: number; - model?: string; -} - export interface ExtensionSetting { name: string; description: string; @@ -168,10 +159,6 @@ export interface ResolvedExtensionSetting { source?: string; } -export interface CliHelpAgentSettings { - enabled?: boolean; -} - export interface AgentRunConfig { maxTimeMinutes?: number; maxTurns?: number; @@ -368,8 +355,6 @@ export interface ConfigParameters { policyEngineConfig?: PolicyEngineConfig; output?: OutputSettings; disableModelRouterForAuth?: AuthType[]; - codebaseInvestigatorSettings?: CodebaseInvestigatorSettings; - cliHelpAgentSettings?: CliHelpAgentSettings; continueOnFailedApiCall?: boolean; retryFetchErrors?: boolean; enableShellOutputEfficiency?: boolean; @@ -513,8 +498,6 @@ export class Config { private readonly messageBus: MessageBus; private readonly policyEngine: PolicyEngine; private readonly outputSettings: OutputSettings; - private readonly codebaseInvestigatorSettings: CodebaseInvestigatorSettings; - private readonly cliHelpAgentSettings: CliHelpAgentSettings; private readonly continueOnFailedApiCall: boolean; private readonly retryFetchErrors: boolean; private readonly enableShellOutputEfficiency: boolean; @@ -688,18 +671,6 @@ export class Config { this.enableHooks = params.enableHooks ?? true; this.disabledHooks = params.disabledHooks ?? []; - this.codebaseInvestigatorSettings = { - enabled: params.codebaseInvestigatorSettings?.enabled ?? true, - maxNumTurns: params.codebaseInvestigatorSettings?.maxNumTurns ?? 10, - maxTimeMinutes: params.codebaseInvestigatorSettings?.maxTimeMinutes ?? 3, - thinkingBudget: - params.codebaseInvestigatorSettings?.thinkingBudget ?? - DEFAULT_THINKING_MODE, - model: params.codebaseInvestigatorSettings?.model, - }; - this.cliHelpAgentSettings = { - enabled: params.cliHelpAgentSettings?.enabled ?? true, - }; this.continueOnFailedApiCall = params.continueOnFailedApiCall ?? true; this.enableShellOutputEfficiency = params.enableShellOutputEfficiency ?? true; @@ -1895,14 +1866,6 @@ export class Config { return this.enableHooksUI; } - getCodebaseInvestigatorSettings(): CodebaseInvestigatorSettings { - return this.codebaseInvestigatorSettings; - } - - getCliHelpAgentSettings(): CliHelpAgentSettings { - return this.cliHelpAgentSettings; - } - async createToolRegistry(): Promise { const registry = new ToolRegistry(this, this.messageBus); @@ -1980,10 +1943,11 @@ export class Config { * Registers the DelegateToAgentTool if agents or related features are enabled. */ private registerDelegateToAgentTool(registry: ToolRegistry): void { + const agentsOverrides = this.getAgentsSettings().overrides ?? {}; if ( this.isAgentsEnabled() || - this.getCodebaseInvestigatorSettings().enabled || - this.getCliHelpAgentSettings().enabled + agentsOverrides['codebase_investigator']?.enabled !== false || + agentsOverrides['cli_help']?.enabled !== false ) { // Check if the delegate tool itself is allowed (if allowedTools is set) const allowedTools = this.getAllowedTools(); diff --git a/schemas/settings.schema.json b/schemas/settings.schema.json index ab1ae47c29..c14ac0a19e 100644 --- a/schemas/settings.schema.json +++ b/schemas/settings.schema.json @@ -1428,51 +1428,6 @@ "default": false, "type": "boolean" }, - "codebaseInvestigatorSettings": { - "title": "Codebase Investigator Settings", - "description": "Configuration for Codebase Investigator.", - "markdownDescription": "Configuration for Codebase Investigator.\n\n- Category: `Experimental`\n- Requires restart: `yes`\n- Default: `{}`", - "default": {}, - "type": "object", - "properties": { - "enabled": { - "title": "Enable Codebase Investigator", - "description": "Enable the Codebase Investigator agent.", - "markdownDescription": "Enable the Codebase Investigator agent.\n\n- Category: `Experimental`\n- Requires restart: `yes`\n- Default: `true`", - "default": true, - "type": "boolean" - }, - "maxNumTurns": { - "title": "Codebase Investigator Max Num Turns", - "description": "Maximum number of turns for the Codebase Investigator agent.", - "markdownDescription": "Maximum number of turns for the Codebase Investigator agent.\n\n- Category: `Experimental`\n- Requires restart: `yes`\n- Default: `10`", - "default": 10, - "type": "number" - }, - "maxTimeMinutes": { - "title": "Max Time (Minutes)", - "description": "Maximum time for the Codebase Investigator agent (in minutes).", - "markdownDescription": "Maximum time for the Codebase Investigator agent (in minutes).\n\n- Category: `Experimental`\n- Requires restart: `yes`\n- Default: `3`", - "default": 3, - "type": "number" - }, - "thinkingBudget": { - "title": "Thinking Budget", - "description": "The thinking budget for the Codebase Investigator agent.", - "markdownDescription": "The thinking budget for the Codebase Investigator agent.\n\n- Category: `Experimental`\n- Requires restart: `yes`\n- Default: `8192`", - "default": 8192, - "type": "number" - }, - "model": { - "title": "Model", - "description": "The model to use for the Codebase Investigator agent.", - "markdownDescription": "The model to use for the Codebase Investigator agent.\n\n- Category: `Experimental`\n- Requires restart: `yes`\n- Default: `auto`", - "default": "auto", - "type": "string" - } - }, - "additionalProperties": false - }, "useOSC52Paste": { "title": "Use OSC 52 Paste", "description": "Use OSC 52 sequence for pasting instead of clipboardy (useful for remote sessions).", @@ -1480,23 +1435,6 @@ "default": false, "type": "boolean" }, - "cliHelpAgentSettings": { - "title": "CLI Help Agent Settings", - "description": "Configuration for CLI Help Agent.", - "markdownDescription": "Configuration for CLI Help Agent.\n\n- Category: `Experimental`\n- Requires restart: `yes`\n- Default: `{}`", - "default": {}, - "type": "object", - "properties": { - "enabled": { - "title": "Enable CLI Help Agent", - "description": "Enable the CLI Help Agent.", - "markdownDescription": "Enable the CLI Help Agent.\n\n- Category: `Experimental`\n- Requires restart: `yes`\n- Default: `true`", - "default": true, - "type": "boolean" - } - }, - "additionalProperties": false - }, "plan": { "title": "Plan", "description": "Enable planning features (Plan Mode and tools).",