fix(core): preserve escape sequences in string literals for modern models (#28299)

Co-authored-by: David Pierce <davidapierce@google.com>
This commit is contained in:
luisfelipe-alt
2026-07-06 17:44:05 +00:00
committed by GitHub
parent 892b35fcfb
commit 15a9429b69
3 changed files with 30 additions and 4 deletions
+2 -2
View File
@@ -85,7 +85,7 @@ const mockConfigInternal = {
getIdeMode: vi.fn(() => false),
getWorkspaceContext: () => new WorkspaceContext(rootDir, [plansDir]),
getApiKey: () => 'test-key',
getModel: () => 'test-model',
getModel: () => 'gemini-1.5-flash',
getSandbox: () => false,
getDebugMode: () => false,
getQuestion: () => undefined,
@@ -107,7 +107,7 @@ const mockConfigInternal = {
isInteractive: () => false,
getDisableLLMCorrection: vi.fn(() => true),
isPlanMode: vi.fn(() => false),
getActiveModel: () => 'test-model',
getActiveModel: () => 'gemini-1.5-flash',
storage: {
getProjectTempDir: vi.fn().mockReturnValue('/tmp/project'),
},
+13 -2
View File
@@ -55,7 +55,12 @@ import { WRITE_FILE_DEFINITION } from './definitions/coreTools.js';
import { resolveToolDeclaration } from './definitions/resolver.js';
import { detectOmissionPlaceholders } from './omissionPlaceholderDetector.js';
import { resolveAndValidatePlanPath } from '../utils/planUtils.js';
import { isGemini3Model } from '../config/models.js';
import {
isGemini3Model,
isGemini2Model,
isCustomModel,
resolveModel,
} from '../config/models.js';
import { discoverJitContext, appendJitContext } from './jit-context.js';
/**
@@ -193,7 +198,13 @@ export async function getCorrectedFileContent(
}
}
const aggressiveUnescape = !isGemini3Model(config.getActiveModel());
const activeModel = config.getActiveModel();
const resolvedModel = resolveModel(activeModel, false, false, true, config);
const aggressiveUnescape =
!isGemini3Model(resolvedModel, config) &&
!isGemini2Model(resolvedModel) &&
!isCustomModel(resolvedModel, config);
correctedContent = await ensureCorrectFileContent(
proposedContent,
@@ -245,5 +245,20 @@ describe('editCorrector', () => {
expect(result).toBe(content);
expect(mockGenerateJson).not.toHaveBeenCalled();
});
it('should preserve \\n inside string literals even when aggressiveUnescape is false (b-496211054)', async () => {
const content =
'fmt.Printf("OpenFile with FailIfExists failed: %v\\n", err)';
const result = await ensureCorrectFileContent(
content,
mockBaseLlmClientInstance,
abortSignal,
true, // disableLLMCorrection
false, // aggressiveUnescape (now false for Gemini 2.5/3.x/Custom)
);
expect(result).toBe(content);
});
});
});