diff --git a/packages/cli/src/config/config.test.ts b/packages/cli/src/config/config.test.ts index 995be3fc61..334236fd85 100644 --- a/packages/cli/src/config/config.test.ts +++ b/packages/cli/src/config/config.test.ts @@ -3632,6 +3632,8 @@ describe('loadCliConfig acpMode and clientName', () => { it('should set acpMode to true and detect clientName when --acp flag is used', async () => { process.argv = ['node', 'script.js', '--acp']; vi.stubEnv('TERM_PROGRAM', 'vscode'); + vi.stubEnv('VSCODE_GIT_ASKPASS_MAIN', ''); + vi.stubEnv('ANTIGRAVITY_CLI_ALIAS', ''); const argv = await parseArguments(createTestMergedSettings()); const config = await loadCliConfig( createTestMergedSettings(), @@ -3645,6 +3647,8 @@ describe('loadCliConfig acpMode and clientName', () => { it('should set acpMode to true but leave clientName undefined for generic terminals', async () => { process.argv = ['node', 'script.js', '--acp']; vi.stubEnv('TERM_PROGRAM', 'iTerm.app'); // Generic terminal + vi.stubEnv('VSCODE_GIT_ASKPASS_MAIN', ''); + vi.stubEnv('ANTIGRAVITY_CLI_ALIAS', ''); const argv = await parseArguments(createTestMergedSettings()); const config = await loadCliConfig( createTestMergedSettings(), diff --git a/packages/core/src/agents/local-executor.test.ts b/packages/core/src/agents/local-executor.test.ts index f8758cd935..d73428d50a 100644 --- a/packages/core/src/agents/local-executor.test.ts +++ b/packages/core/src/agents/local-executor.test.ts @@ -33,6 +33,7 @@ import { type PartListUnion, type Tool, type CallableTool, + type FunctionDeclaration, } from '@google/genai'; import type { Config } from '../config/config.js'; import { MockTool } from '../test-utils/mock-tool.js'; @@ -560,6 +561,34 @@ describe('LocalAgentExecutor', () => { getToolSpy.mockRestore(); }); + + it('should not duplicate schemas when instantiated tools are provided in toolConfig', async () => { + // Create an instantiated mock tool + const instantiatedTool = new MockTool({ name: 'instantiated_tool' }); + + // Create an agent definition containing the instantiated tool + const definition = createTestDefinition([instantiatedTool]); + + // Create the executor + const executor = await LocalAgentExecutor.create( + definition, + mockConfig, + onActivity, + ); + + // Extract the prepared tools list using the private method + const toolsList = ( + executor as unknown as { prepareToolsList: () => FunctionDeclaration[] } + ).prepareToolsList(); + + // Filter for the specific tool schema + const foundSchemas = ( + toolsList as unknown as FunctionDeclaration[] + ).filter((t: FunctionDeclaration) => t.name === 'instantiated_tool'); + + // Assert that there is exactly ONE schema for this tool + expect(foundSchemas).toHaveLength(1); + }); }); describe('run (Execution Loop and Logic)', () => { diff --git a/packages/core/src/agents/local-executor.ts b/packages/core/src/agents/local-executor.ts index 6a9dfe0151..fccd95aed6 100644 --- a/packages/core/src/agents/local-executor.ts +++ b/packages/core/src/agents/local-executor.ts @@ -1209,17 +1209,12 @@ export class LocalAgentExecutor { if (toolConfig) { for (const toolRef of toolConfig.tools) { - if (typeof toolRef === 'string') { - // The names were already expanded and loaded into the registry during creation. - } else if (typeof toolRef === 'object' && 'schema' in toolRef) { - // Tool instance with an explicit schema property. - toolsList.push(toolRef.schema); - } else { + if (typeof toolRef === 'object' && !('schema' in toolRef)) { // Raw `FunctionDeclaration` object. toolsList.push(toolRef); } } - // Add schemas from tools that were explicitly registered by name or wildcard. + // Add schemas from tools that were explicitly registered by name, wildcard, or instance. toolsList.push(...this.toolRegistry.getFunctionDeclarations()); }