fix(utils): save config (#578)

## Description

When `saveConfig` is called, the project doc is incorrectly saved into
user instructions. This change ensures that only user instructions are
saved to `instructions.md` during saveConfig, preventing data
corruption.

close: #576

---------

Co-authored-by: Thibault Sottiaux <tibo@openai.com>
This commit is contained in:
Luci
2025-04-25 08:32:33 +08:00
committed by GitHub
parent 58f0e5ab74
commit c38c2a59c7
2 changed files with 48 additions and 2 deletions

View File

@@ -157,6 +157,7 @@ export const PRETTY_PRINT = Boolean(process.env["PRETTY_PRINT"] || "");
export const PROJECT_DOC_MAX_BYTES = 32 * 1024; // 32 kB
const PROJECT_DOC_FILENAMES = ["codex.md", ".codex.md", "CODEX.md"];
const PROJECT_DOC_SEPARATOR = "\n\n--- project-doc ---\n\n";
export function discoverProjectDocPath(startDir: string): string | null {
const cwd = resolvePath(startDir);
@@ -311,7 +312,7 @@ export const loadConfig = (
const combinedInstructions = [userInstructions, projectDoc]
.filter((s) => s && s.trim() !== "")
.join("\n\n--- project-doc ---\n\n");
.join(PROJECT_DOC_SEPARATOR);
// Treat empty string ("" or whitespace) as absence so we can fall back to
// the latest DEFAULT_MODEL.
@@ -462,5 +463,9 @@ export const saveConfig = (
writeFileSync(targetPath, JSON.stringify(configToSave, null, 2), "utf-8");
}
writeFileSync(instructionsPath, config.instructions, "utf-8");
// Take everything before the first PROJECT_DOC_SEPARATOR (or the whole string if none).
const [userInstructions = ""] = config.instructions.split(
PROJECT_DOC_SEPARATOR,
);
writeFileSync(instructionsPath, userInstructions, "utf-8");
};

View File

@@ -234,3 +234,44 @@ test("loads and saves providers correctly", () => {
expect(mergedConfig.providers["openai"]).toBeDefined();
}
});
test("saves and loads instructions with project doc separator correctly", () => {
const userInstructions = "user specific instructions";
const projectDoc = "project specific documentation";
const combinedInstructions = `${userInstructions}\n\n--- project-doc ---\n\n${projectDoc}`;
const testConfig = {
model: "test-model",
instructions: combinedInstructions,
notify: false,
};
saveConfig(testConfig, testConfigPath, testInstructionsPath);
expect(memfs[testInstructionsPath]).toBe(userInstructions);
const loadedConfig = loadConfig(testConfigPath, testInstructionsPath, {
disableProjectDoc: true,
});
expect(loadedConfig.instructions).toBe(userInstructions);
});
test("handles empty user instructions when saving with project doc separator", () => {
const projectDoc = "project specific documentation";
const combinedInstructions = `\n\n--- project-doc ---\n\n${projectDoc}`;
const testConfig = {
model: "test-model",
instructions: combinedInstructions,
notify: false,
};
saveConfig(testConfig, testConfigPath, testInstructionsPath);
expect(memfs[testInstructionsPath]).toBe("");
const loadedConfig = loadConfig(testConfigPath, testInstructionsPath, {
disableProjectDoc: true,
});
expect(loadedConfig.instructions).toBe("");
});