mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-12 21:03:05 -07:00
feat(core): disable tool discovery by default and require explicit configuration
This commit is contained in:
@@ -103,6 +103,7 @@ they appear in the UI.
|
||||
| -------------------------------- | ------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
|
||||
| Enable Interactive Shell | `tools.shell.enableInteractiveShell` | Use node-pty for an interactive shell experience. Fallback to child_process still applies. | `true` |
|
||||
| Show Color | `tools.shell.showColor` | Show color in shell output. | `false` |
|
||||
| Enable Tool Discovery | `tools.enableToolDiscovery` | Enables the tool discovery feature using `tools.discoveryCommand`. | `false` |
|
||||
| Use Ripgrep | `tools.useRipgrep` | Use ripgrep for file content search instead of the fallback implementation. Provides faster search performance. | `true` |
|
||||
| Tool Output Truncation Threshold | `tools.truncateToolOutputThreshold` | Maximum characters to show when truncating large tool outputs. Set to 0 or negative to disable truncation. | `40000` |
|
||||
| Disable LLM Correction | `tools.disableLLMCorrection` | Disable LLM-based error correction for edit tools. When enabled, tools will fail immediately if exact string matches are not found, instead of attempting to self-correct. | `true` |
|
||||
|
||||
@@ -753,6 +753,12 @@ their corresponding top-level category object in your `settings.json` file.
|
||||
- **Default:** `undefined`
|
||||
- **Requires restart:** Yes
|
||||
|
||||
- **`tools.enableToolDiscovery`** (boolean):
|
||||
- **Description:** Enables the tool discovery feature using
|
||||
`tools.discoveryCommand`.
|
||||
- **Default:** `false`
|
||||
- **Requires restart:** Yes
|
||||
|
||||
- **`tools.callCommand`** (string):
|
||||
- **Description:** Defines a custom shell command for invoking discovered
|
||||
tools. The command must take the tool name as the first argument, read JSON
|
||||
|
||||
@@ -1190,6 +1190,17 @@ const SETTINGS_SCHEMA = {
|
||||
description: 'Command to run for tool discovery.',
|
||||
showInDialog: false,
|
||||
},
|
||||
enableToolDiscovery: {
|
||||
type: 'boolean',
|
||||
label: 'Enable Tool Discovery',
|
||||
category: 'Tools',
|
||||
requiresRestart: true,
|
||||
default: false,
|
||||
description: oneLine`
|
||||
Enables the tool discovery feature using \`tools.discoveryCommand\`.
|
||||
`,
|
||||
showInDialog: true,
|
||||
},
|
||||
callCommand: {
|
||||
type: 'string',
|
||||
label: 'Tool Call Command',
|
||||
|
||||
@@ -388,6 +388,7 @@ export interface ConfigParameters {
|
||||
/** @deprecated Use Policy Engine instead */
|
||||
excludeTools?: string[];
|
||||
toolDiscoveryCommand?: string;
|
||||
enableToolDiscovery?: boolean;
|
||||
toolCallCommand?: string;
|
||||
mcpServerCommand?: string;
|
||||
mcpServers?: Record<string, MCPServerConfig>;
|
||||
@@ -524,6 +525,7 @@ export class Config {
|
||||
/** @deprecated Use Policy Engine instead */
|
||||
private readonly excludeTools: string[] | undefined;
|
||||
private readonly toolDiscoveryCommand: string | undefined;
|
||||
private readonly enableToolDiscovery: boolean;
|
||||
private readonly toolCallCommand: string | undefined;
|
||||
private readonly mcpServerCommand: string | undefined;
|
||||
private readonly mcpEnabled: boolean;
|
||||
@@ -696,6 +698,7 @@ export class Config {
|
||||
this.allowedTools = params.allowedTools;
|
||||
this.excludeTools = params.excludeTools;
|
||||
this.toolDiscoveryCommand = params.toolDiscoveryCommand;
|
||||
this.enableToolDiscovery = params.enableToolDiscovery ?? false;
|
||||
this.toolCallCommand = params.toolCallCommand;
|
||||
this.mcpServerCommand = params.mcpServerCommand;
|
||||
this.mcpServers = params.mcpServers;
|
||||
@@ -1534,6 +1537,10 @@ export class Config {
|
||||
return this.toolDiscoveryCommand;
|
||||
}
|
||||
|
||||
getEnableToolDiscovery(): boolean {
|
||||
return this.enableToolDiscovery;
|
||||
}
|
||||
|
||||
getToolCallCommand(): string | undefined {
|
||||
return this.toolCallCommand;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import fs from 'node:fs';
|
||||
import { MockTool } from '../test-utils/mock-tool.js';
|
||||
import { ToolErrorType } from './tool-error.js';
|
||||
import type { MessageBus } from '../confirmation-bus/message-bus.js';
|
||||
import { debugLogger } from '../utils/debugLogger.js';
|
||||
|
||||
vi.mock('node:fs');
|
||||
|
||||
@@ -216,6 +217,7 @@ describe('ToolRegistry', () => {
|
||||
unsubscribe: vi.fn(),
|
||||
} as unknown as MessageBus;
|
||||
let mockConfigGetToolDiscoveryCommand: ReturnType<typeof vi.spyOn>;
|
||||
let mockConfigGetEnableToolDiscovery: ReturnType<typeof vi.spyOn>;
|
||||
let mockConfigGetExcludedTools: MockInstance<
|
||||
typeof Config.prototype.getExcludeTools
|
||||
>;
|
||||
@@ -242,6 +244,12 @@ describe('ToolRegistry', () => {
|
||||
config,
|
||||
'getToolDiscoveryCommand',
|
||||
);
|
||||
mockConfigGetEnableToolDiscovery = vi.spyOn(
|
||||
config,
|
||||
'getEnableToolDiscovery',
|
||||
);
|
||||
mockConfigGetEnableToolDiscovery.mockReturnValue(true);
|
||||
|
||||
mockConfigGetExcludedTools = vi.spyOn(config, 'getExcludeTools');
|
||||
vi.spyOn(config, 'getMcpServers');
|
||||
vi.spyOn(config, 'getMcpServerCommand');
|
||||
@@ -472,6 +480,22 @@ describe('ToolRegistry', () => {
|
||||
});
|
||||
|
||||
describe('discoverTools', () => {
|
||||
it('should warn and skip discovery if enableToolDiscovery is false', async () => {
|
||||
const discoveryCommand = 'my-discovery-command';
|
||||
mockConfigGetToolDiscoveryCommand.mockReturnValue(discoveryCommand);
|
||||
mockConfigGetEnableToolDiscovery.mockReturnValue(false);
|
||||
|
||||
const warnSpy = vi.spyOn(debugLogger, 'warn');
|
||||
const mockSpawn = vi.mocked(spawn);
|
||||
|
||||
await toolRegistry.discoverAllTools();
|
||||
|
||||
expect(warnSpy).toHaveBeenCalledWith(
|
||||
expect.stringContaining('Tool discovery is disabled by default'),
|
||||
);
|
||||
expect(mockSpawn).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should will preserve tool parametersJsonSchema during discovery from command', async () => {
|
||||
const discoveryCommand = 'my-discovery-command';
|
||||
mockConfigGetToolDiscoveryCommand.mockReturnValue(discoveryCommand);
|
||||
|
||||
@@ -314,6 +314,13 @@ export class ToolRegistry {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.config.getEnableToolDiscovery()) {
|
||||
debugLogger.warn(
|
||||
'Tool discovery is disabled by default. Please enable it in settings to use discovered tools.',
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const cmdParts = parse(discoveryCmd);
|
||||
if (cmdParts.length === 0) {
|
||||
|
||||
@@ -1251,6 +1251,13 @@
|
||||
"markdownDescription": "Command to run for tool discovery.\n\n- Category: `Tools`\n- Requires restart: `yes`",
|
||||
"type": "string"
|
||||
},
|
||||
"enableToolDiscovery": {
|
||||
"title": "Enable Tool Discovery",
|
||||
"description": "Enables the tool discovery feature using `tools.discoveryCommand`.",
|
||||
"markdownDescription": "Enables the tool discovery feature using `tools.discoveryCommand`.\n\n- Category: `Tools`\n- Requires restart: `yes`\n- Default: `false`",
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"callCommand": {
|
||||
"title": "Tool Call Command",
|
||||
"description": "Defines a custom shell command for invoking discovered tools. The command must take the tool name as the first argument, read JSON arguments from stdin, and emit JSON results on stdout.",
|
||||
|
||||
Reference in New Issue
Block a user