fix: prevent duplicate codex base_url entries (#4316)

This commit is contained in:
Sean Wang
2026-06-16 17:01:01 +08:00
committed by GitHub
parent 1042fb2a32
commit caa912e3a3
2 changed files with 92 additions and 18 deletions
+50 -18
View File
@@ -400,7 +400,7 @@ export const hasTomlCommonConfigSnippet = (
const TOML_SECTION_HEADER_PATTERN = /^\s*\[([^\]\r\n]+)\]\s*$/;
const TOML_BASE_URL_PATTERN =
/^\s*base_url\s*=\s*(["'])([^"'\r\n]+)\1\s*(?:#.*)?$/;
/^\s*base_url\s*=\s*(?:"((?:\\.|[^"\\\r\n])*)"|'([^'\r\n]*)')\s*(?:#.*)?$/;
const TOML_EXPERIMENTAL_BEARER_TOKEN_PATTERN =
/^\s*experimental_bearer_token\s*=\s*(["'])([^"'\r\n]+)\1\s*(?:#.*)?$/;
const TOML_EXPERIMENTAL_BEARER_TOKEN_REPLACE_PATTERN =
@@ -553,11 +553,12 @@ const findTomlAssignmentInRange = (
): TomlAssignmentMatch | undefined => {
for (let index = startIndex; index < endIndex; index += 1) {
const match = lines[index].match(pattern);
if (match?.[2]) {
const value = match?.[2] ?? match?.[1];
if (value) {
return {
index,
sectionName,
value: match[2],
value,
};
}
}
@@ -565,6 +566,26 @@ const findTomlAssignmentInRange = (
return undefined;
};
const findTomlAssignmentsInRange = (
lines: string[],
pattern: RegExp,
startIndex: number,
endIndex: number,
sectionName?: string,
): TomlAssignmentMatch[] => {
const matches: TomlAssignmentMatch[] = [];
for (let index = startIndex; index < endIndex; index += 1) {
const match = lines[index].match(pattern);
const value = match?.[2] ?? match?.[1];
if (value) {
matches.push({ index, sectionName, value });
}
}
return matches;
};
const findTomlLineInRange = (
lines: string[],
pattern: RegExp,
@@ -595,14 +616,15 @@ const findTomlAssignments = (
}
const match = line.match(pattern);
if (!match?.[2]) {
const value = match?.[2] ?? match?.[1];
if (!value) {
return;
}
assignments.push({
index,
sectionName: currentSectionName,
value: match[2],
value,
});
});
@@ -1228,18 +1250,20 @@ export const setCodexBaseUrl = (
if (targetSectionName) {
const sectionRange = getTomlSectionRange(lines, targetSectionName);
const targetMatch = sectionRange
? findTomlAssignmentInRange(
const targetMatches = sectionRange
? findTomlAssignmentsInRange(
lines,
TOML_BASE_URL_PATTERN,
sectionRange.bodyStartIndex,
sectionRange.bodyEndIndex,
targetSectionName,
)
: undefined;
: [];
if (targetMatch) {
lines.splice(targetMatch.index, 1);
if (targetMatches.length > 0) {
for (const match of [...targetMatches].reverse()) {
lines.splice(match.index, 1);
}
return finalizeTomlText(lines);
}
}
@@ -1257,18 +1281,22 @@ export const setCodexBaseUrl = (
if (targetSectionName) {
let targetSectionRange = getTomlSectionRange(lines, targetSectionName);
const targetMatch = targetSectionRange
? findTomlAssignmentInRange(
const targetMatches = targetSectionRange
? findTomlAssignmentsInRange(
lines,
TOML_BASE_URL_PATTERN,
targetSectionRange.bodyStartIndex,
targetSectionRange.bodyEndIndex,
targetSectionName,
)
: undefined;
: [];
if (targetMatch) {
lines[targetMatch.index] = replacementLine;
if (targetMatches.length > 0) {
const [firstMatch, ...duplicateMatches] = targetMatches;
lines[firstMatch.index] = replacementLine;
for (const match of [...duplicateMatches].reverse()) {
lines.splice(match.index, 1);
}
return finalizeTomlText(lines);
}
@@ -1291,14 +1319,18 @@ export const setCodexBaseUrl = (
}
const topLevelEndIndex = getTopLevelEndIndex(lines);
const topLevelMatch = findTomlAssignmentInRange(
const topLevelMatches = findTomlAssignmentsInRange(
lines,
TOML_BASE_URL_PATTERN,
0,
topLevelEndIndex,
);
if (topLevelMatch) {
lines[topLevelMatch.index] = replacementLine;
if (topLevelMatches.length > 0) {
const [firstMatch, ...duplicateMatches] = topLevelMatches;
lines[firstMatch.index] = replacementLine;
for (const match of [...duplicateMatches].reverse()) {
lines.splice(match.index, 1);
}
return finalizeTomlText(lines);
}
@@ -63,6 +63,48 @@ describe("Codex TOML utils", () => {
expect(extractCodexModelName(output2)).toBe("new-model");
});
it("updates a double-quoted base_url containing single quotes without duplicating it", () => {
const input = [
'model_provider = "custom"',
'model = "gpt-5.4"',
"",
"[model_providers.custom]",
'name = "custom"',
"base_url = \"https://su'us.codes/v1\"",
'wire_api = "responses"',
'requires_openai_auth = true',
"",
].join("\n");
const output = setCodexBaseUrl(input, "https://su'us'd.codes/v1");
expect(extractCodexBaseUrl(output)).toBe("https://su'us'd.codes/v1");
expect(output.match(/^\s*base_url\s*=/gm)).toHaveLength(1);
expect(output).toContain("base_url = \"https://su'us'd.codes/v1\"");
});
it("collapses duplicate base_url lines when editing the active provider section", () => {
const input = [
'model_provider = "custom"',
'model = "gpt-5.4"',
"",
"[model_providers.custom]",
'name = "custom"',
'base_url = "https://old.example/v1"',
'base_url = "https://older.example/v1"',
'wire_api = "responses"',
'requires_openai_auth = true',
"",
].join("\n");
const output = setCodexBaseUrl(input, "https://new.example/v1");
expect(extractCodexBaseUrl(output)).toBe("https://new.example/v1");
expect(output.match(/^\s*base_url\s*=/gm)).toHaveLength(1);
expect(output).toContain('base_url = "https://new.example/v1"');
expect(output).not.toContain("older.example");
});
it("reads and writes base_url in the active provider section", () => {
const input = [
'model_provider = "custom"',