feat(core): disable tool discovery by default and require explicit configuration

This commit is contained in:
Yuna Seol
2026-02-09 14:11:04 -05:00
committed by Yuna Seol
parent ce84b3cb5f
commit b4df1183ba
7 changed files with 63 additions and 0 deletions
+1
View File
@@ -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` |
+6
View File
@@ -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
+11
View File
@@ -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',
+7
View File
@@ -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);
+7
View File
@@ -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) {
+7
View File
@@ -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.",