feat(core): enable disableLLMCorrection by default (#17223)

This commit is contained in:
Sandy Tao
2026-01-21 10:53:41 -08:00
committed by GitHub
parent eb2af84bb9
commit f79124f96e
9 changed files with 33 additions and 18 deletions
+1 -1
View File
@@ -99,7 +99,7 @@ they appear in the UI.
| Enable Tool Output Truncation | `tools.enableToolOutputTruncation` | Enable truncation of large tool outputs. | `true` | | Enable Tool Output Truncation | `tools.enableToolOutputTruncation` | Enable truncation of large tool outputs. | `true` |
| Tool Output Truncation Threshold | `tools.truncateToolOutputThreshold` | Truncate tool output if it is larger than this many characters. Set to -1 to disable. | `4000000` | | Tool Output Truncation Threshold | `tools.truncateToolOutputThreshold` | Truncate tool output if it is larger than this many characters. Set to -1 to disable. | `4000000` |
| Tool Output Truncation Lines | `tools.truncateToolOutputLines` | The number of lines to keep when truncating tool output. | `1000` | | Tool Output Truncation Lines | `tools.truncateToolOutputLines` | The number of lines to keep when truncating tool output. | `1000` |
| 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. | `false` | | 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` |
### Security ### Security
+1 -1
View File
@@ -707,7 +707,7 @@ their corresponding top-level category object in your `settings.json` file.
- **Description:** Disable LLM-based error correction for edit tools. When - **Description:** Disable LLM-based error correction for edit tools. When
enabled, tools will fail immediately if exact string matches are not found, enabled, tools will fail immediately if exact string matches are not found,
instead of attempting to self-correct. instead of attempting to self-correct.
- **Default:** `false` - **Default:** `true`
- **Requires restart:** Yes - **Requires restart:** Yes
- **`tools.enableHooks`** (boolean): - **`tools.enableHooks`** (boolean):
+1 -1
View File
@@ -1126,7 +1126,7 @@ const SETTINGS_SCHEMA = {
label: 'Disable LLM Correction', label: 'Disable LLM Correction',
category: 'Tools', category: 'Tools',
requiresRestart: true, requiresRestart: true,
default: false, default: true,
description: oneLine` description: oneLine`
Disable LLM-based error correction for edit tools. 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. When enabled, tools will fail immediately if exact string matches are not found, instead of attempting to self-correct.
+1 -1
View File
@@ -634,7 +634,7 @@ export class Config {
this._activeModel = params.model; this._activeModel = params.model;
this.enableAgents = params.enableAgents ?? false; this.enableAgents = params.enableAgents ?? false;
this.agents = params.agents ?? {}; this.agents = params.agents ?? {};
this.disableLLMCorrection = params.disableLLMCorrection ?? false; this.disableLLMCorrection = params.disableLLMCorrection ?? true;
this.planEnabled = params.plan ?? false; this.planEnabled = params.plan ?? false;
this.enableEventDrivenScheduler = this.enableEventDrivenScheduler =
params.enableEventDrivenScheduler ?? false; params.enableEventDrivenScheduler ?? false;
@@ -64,7 +64,7 @@ describe('Tool Confirmation Policy Updates', () => {
getFileFilteringOptions: () => ({}), getFileFilteringOptions: () => ({}),
getGeminiClient: () => ({}), getGeminiClient: () => ({}),
getBaseLlmClient: () => ({}), getBaseLlmClient: () => ({}),
getDisableLLMCorrection: () => false, getDisableLLMCorrection: () => true,
getIdeMode: () => false, getIdeMode: () => false,
getWorkspaceContext: () => ({ getWorkspaceContext: () => ({
isPathWithinWorkspace: () => true, isPathWithinWorkspace: () => true,
+18 -3
View File
@@ -120,7 +120,7 @@ describe('EditTool', () => {
setGeminiMdFileCount: vi.fn(), setGeminiMdFileCount: vi.fn(),
getToolRegistry: () => ({}) as any, getToolRegistry: () => ({}) as any,
isInteractive: () => false, isInteractive: () => false,
getDisableLLMCorrection: vi.fn(() => false), getDisableLLMCorrection: vi.fn(() => true),
getExperiments: () => {}, getExperiments: () => {},
} as unknown as Config; } as unknown as Config;
@@ -436,6 +436,10 @@ describe('EditTool', () => {
it('should return error if old_string is not found in file', async () => { it('should return error if old_string is not found in file', async () => {
fs.writeFileSync(filePath, 'Some content.', 'utf8'); fs.writeFileSync(filePath, 'Some content.', 'utf8');
// Enable LLM correction for this test
(mockConfig.getDisableLLMCorrection as Mock).mockReturnValue(false);
const params: EditToolParams = { const params: EditToolParams = {
file_path: filePath, file_path: filePath,
instruction: 'Replace non-existent text', instruction: 'Replace non-existent text',
@@ -455,6 +459,10 @@ describe('EditTool', () => {
const initialContent = 'This is some original text.'; const initialContent = 'This is some original text.';
const finalContent = 'This is some brand new text.'; const finalContent = 'This is some brand new text.';
fs.writeFileSync(filePath, initialContent, 'utf8'); fs.writeFileSync(filePath, initialContent, 'utf8');
// Enable LLM correction for this test
(mockConfig.getDisableLLMCorrection as Mock).mockReturnValue(false);
const params: EditToolParams = { const params: EditToolParams = {
file_path: filePath, file_path: filePath,
instruction: 'Replace original with brand new', instruction: 'Replace original with brand new',
@@ -515,6 +523,10 @@ describe('EditTool', () => {
it('should return NO_CHANGE if FixLLMEditWithInstruction determines no changes are needed', async () => { it('should return NO_CHANGE if FixLLMEditWithInstruction determines no changes are needed', async () => {
const initialContent = 'The price is $100.'; const initialContent = 'The price is $100.';
fs.writeFileSync(filePath, initialContent, 'utf8'); fs.writeFileSync(filePath, initialContent, 'utf8');
// Enable LLM correction for this test
(mockConfig.getDisableLLMCorrection as Mock).mockReturnValue(false);
const params: EditToolParams = { const params: EditToolParams = {
file_path: filePath, file_path: filePath,
instruction: 'Ensure the price is $100', instruction: 'Ensure the price is $100',
@@ -556,6 +568,9 @@ describe('EditTool', () => {
'This is the externally modified content.'; 'This is the externally modified content.';
fs.writeFileSync(filePath, initialContent, 'utf8'); fs.writeFileSync(filePath, initialContent, 'utf8');
// Enable LLM correction for this test
(mockConfig.getDisableLLMCorrection as Mock).mockReturnValue(false);
const params: EditToolParams = { const params: EditToolParams = {
file_path: filePath, file_path: filePath,
instruction: instruction:
@@ -882,11 +897,11 @@ describe('EditTool', () => {
expect(mockFixLLMEditWithInstruction).not.toHaveBeenCalled(); expect(mockFixLLMEditWithInstruction).not.toHaveBeenCalled();
}); });
it('should call FixLLMEditWithInstruction when disableLLMCorrection is false (default)', async () => { it('should call FixLLMEditWithInstruction when disableLLMCorrection is false', async () => {
const filePath = path.join(rootDir, 'enable_llm_test.txt'); const filePath = path.join(rootDir, 'enable_llm_test.txt');
fs.writeFileSync(filePath, 'Some content.', 'utf8'); fs.writeFileSync(filePath, 'Some content.', 'utf8');
// Default is false, but being explicit // Now explicit as it's not the default anymore
(mockConfig.getDisableLLMCorrection as Mock).mockReturnValue(false); (mockConfig.getDisableLLMCorrection as Mock).mockReturnValue(false);
const params: EditToolParams = { const params: EditToolParams = {
+7 -7
View File
@@ -106,7 +106,7 @@ const mockConfigInternal = {
discoverTools: vi.fn(), discoverTools: vi.fn(),
}) as unknown as ToolRegistry, }) as unknown as ToolRegistry,
isInteractive: () => false, isInteractive: () => false,
getDisableLLMCorrection: vi.fn(() => false), getDisableLLMCorrection: vi.fn(() => true),
}; };
const mockConfig = mockConfigInternal as unknown as Config; const mockConfig = mockConfigInternal as unknown as Config;
@@ -294,7 +294,7 @@ describe('WriteFileTool', () => {
proposedContent, proposedContent,
mockBaseLlmClientInstance, mockBaseLlmClientInstance,
abortSignal, abortSignal,
false, true,
); );
expect(mockEnsureCorrectEdit).not.toHaveBeenCalled(); expect(mockEnsureCorrectEdit).not.toHaveBeenCalled();
expect(result.correctedContent).toBe(correctedContent); expect(result.correctedContent).toBe(correctedContent);
@@ -339,7 +339,7 @@ describe('WriteFileTool', () => {
mockGeminiClientInstance, mockGeminiClientInstance,
mockBaseLlmClientInstance, mockBaseLlmClientInstance,
abortSignal, abortSignal,
false, true,
); );
expect(mockEnsureCorrectFileContent).not.toHaveBeenCalled(); expect(mockEnsureCorrectFileContent).not.toHaveBeenCalled();
expect(result.correctedContent).toBe(correctedProposedContent); expect(result.correctedContent).toBe(correctedProposedContent);
@@ -417,7 +417,7 @@ describe('WriteFileTool', () => {
proposedContent, proposedContent,
mockBaseLlmClientInstance, mockBaseLlmClientInstance,
abortSignal, abortSignal,
false, true,
); );
expect(confirmation).toEqual( expect(confirmation).toEqual(
expect.objectContaining({ expect.objectContaining({
@@ -468,7 +468,7 @@ describe('WriteFileTool', () => {
mockGeminiClientInstance, mockGeminiClientInstance,
mockBaseLlmClientInstance, mockBaseLlmClientInstance,
abortSignal, abortSignal,
false, true,
); );
expect(confirmation).toEqual( expect(confirmation).toEqual(
expect.objectContaining({ expect.objectContaining({
@@ -663,7 +663,7 @@ describe('WriteFileTool', () => {
proposedContent, proposedContent,
mockBaseLlmClientInstance, mockBaseLlmClientInstance,
abortSignal, abortSignal,
false, true,
); );
expect(result.llmContent).toMatch( expect(result.llmContent).toMatch(
/Successfully created and wrote to new file/, /Successfully created and wrote to new file/,
@@ -721,7 +721,7 @@ describe('WriteFileTool', () => {
mockGeminiClientInstance, mockGeminiClientInstance,
mockBaseLlmClientInstance, mockBaseLlmClientInstance,
abortSignal, abortSignal,
false, true,
); );
expect(result.llmContent).toMatch(/Successfully overwrote file/); expect(result.llmContent).toMatch(/Successfully overwrote file/);
const writtenContent = await fsService.readTextFile(filePath); const writtenContent = await fsService.readTextFile(filePath);
+1 -1
View File
@@ -357,7 +357,7 @@ export async function ensureCorrectFileContent(
content: string, content: string,
baseLlmClient: BaseLlmClient, baseLlmClient: BaseLlmClient,
abortSignal: AbortSignal, abortSignal: AbortSignal,
disableLLMCorrection: boolean = false, disableLLMCorrection: boolean = true,
): Promise<string> { ): Promise<string> {
const cachedResult = fileContentCorrectionCache.get(content); const cachedResult = fileContentCorrectionCache.get(content);
if (cachedResult) { if (cachedResult) {
+2 -2
View File
@@ -1165,8 +1165,8 @@
"disableLLMCorrection": { "disableLLMCorrection": {
"title": "Disable LLM Correction", "title": "Disable LLM Correction",
"description": "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.", "description": "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.",
"markdownDescription": "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.\n\n- Category: `Tools`\n- Requires restart: `yes`\n- Default: `false`", "markdownDescription": "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.\n\n- Category: `Tools`\n- Requires restart: `yes`\n- Default: `true`",
"default": false, "default": true,
"type": "boolean" "type": "boolean"
}, },
"enableHooks": { "enableHooks": {