diff --git a/gateway.mjs b/gateway.mjs index b04719a..e893ff1 100644 --- a/gateway.mjs +++ b/gateway.mjs @@ -2800,6 +2800,21 @@ function hasLegacyImageProfileConfig(env) { return Boolean(`${env?.CODEX_RETRY_GATEWAY_IMAGE_BASE_URL || ""}`.trim()); } +function legacyImageProfileEnvFromConfig(config) { + const baseUrl = `${config?.image_base_url || ""}`.trim(); + if (!baseUrl) { + return {}; + } + return { + CODEX_RETRY_GATEWAY_IMAGE_BASE_URL: baseUrl, + CODEX_RETRY_GATEWAY_IMAGE_AUTH_MODE: config?.image_auth_mode || DEFAULT_CONFIG.image_auth_mode, + CODEX_RETRY_GATEWAY_IMAGE_AUTH_ENV: config?.image_auth_env || "", + CODEX_RETRY_GATEWAY_IMAGE_AUTH_FILE: config?.image_auth_file || "", + CODEX_RETRY_GATEWAY_IMAGE_AUTH_JSON_PATH: config?.image_auth_json_path || "", + CODEX_RETRY_GATEWAY_IMAGE_AUTH_JSON_KEY: config?.image_auth_json_key || "", + }; +} + function buildLegacyImageProfileEnvText(env) { const pairs = IMAGE_PROFILE_ENV_KEYS .filter((key) => env?.[key] !== undefined) @@ -2812,7 +2827,7 @@ function buildLegacyImageProfileEnvText(env) { ].join("\n"); } -async function migrateLegacyImageProfile(runtime, textProfileName, textEnv = null) { +async function migrateLegacyImageProfile(runtime, textProfileName, textEnv = null, legacyConfig = null) { validateProfileName(textProfileName); const imageProfilePath = path.join(runtime.paths.imageProfilesDir, `${textProfileName}.env`); if (fs.existsSync(imageProfilePath)) { @@ -2822,17 +2837,21 @@ async function migrateLegacyImageProfile(runtime, textProfileName, textEnv = nul let env = textEnv; if (!env) { const textProfilePath = path.join(runtime.paths.profilesDir, `${textProfileName}.env`); - if (!fs.existsSync(textProfilePath)) { - return null; + if (fs.existsSync(textProfilePath)) { + env = parseEnvText((await readOptionalText(textProfilePath)) || ""); + } else { + env = {}; } - env = parseEnvText((await readOptionalText(textProfilePath)) || ""); } - if (!hasLegacyImageProfileConfig(env)) { + const sourceEnv = hasLegacyImageProfileConfig(env) + ? env + : legacyImageProfileEnvFromConfig(legacyConfig); + if (!hasLegacyImageProfileConfig(sourceEnv)) { return null; } await mkdir(runtime.paths.imageProfilesDir, { recursive: true }); - await writeFile(imageProfilePath, buildLegacyImageProfileEnvText(env), { + await writeFile(imageProfilePath, buildLegacyImageProfileEnvText(sourceEnv), { encoding: "utf8", mode: 0o600, }); @@ -3025,7 +3044,7 @@ async function ensureActiveImageProfile(runtime) { let selectedName = candidates.find((name) => fs.existsSync(path.join(runtime.paths.imageProfilesDir, `${name}.env`))) || ""; let migration = null; if (!selectedName && /^[A-Za-z0-9_.-]+$/.test(textProfileName)) { - migration = await migrateLegacyImageProfile(runtime, textProfileName); + migration = await migrateLegacyImageProfile(runtime, textProfileName, null, runtime.config); selectedName = migration?.name || ""; } if (!selectedName) { diff --git a/scripts/run-profile.mjs b/scripts/run-profile.mjs index 06aef57..b9654ab 100644 --- a/scripts/run-profile.mjs +++ b/scripts/run-profile.mjs @@ -279,8 +279,26 @@ function hasLegacyImageProfileConfig(profileEnv) { return Boolean(`${profileEnv?.CODEX_RETRY_GATEWAY_IMAGE_BASE_URL || ""}`.trim()); } -async function migrateLegacyImageProfile(profileName, profileEnv, imageProfilesDir) { - if (!hasLegacyImageProfileConfig(profileEnv)) { +function imageProfileEnvFromGatewayConfig(config) { + const baseUrl = `${config?.image_base_url || ""}`.trim(); + if (!baseUrl) { + return {}; + } + return { + CODEX_RETRY_GATEWAY_IMAGE_BASE_URL: baseUrl, + CODEX_RETRY_GATEWAY_IMAGE_AUTH_MODE: config?.image_auth_mode || "fixed_bearer", + CODEX_RETRY_GATEWAY_IMAGE_AUTH_ENV: config?.image_auth_env || "", + CODEX_RETRY_GATEWAY_IMAGE_AUTH_FILE: config?.image_auth_file || "", + CODEX_RETRY_GATEWAY_IMAGE_AUTH_JSON_PATH: config?.image_auth_json_path || "", + CODEX_RETRY_GATEWAY_IMAGE_AUTH_JSON_KEY: config?.image_auth_json_key || "", + }; +} + +async function migrateLegacyImageProfile(profileName, profileEnv, imageProfilesDir, existingGatewayConfig = null) { + const sourceEnv = hasLegacyImageProfileConfig(profileEnv) + ? profileEnv + : imageProfileEnvFromGatewayConfig(existingGatewayConfig); + if (!hasLegacyImageProfileConfig(sourceEnv)) { return null; } const imageProfilePath = path.join(imageProfilesDir, `${profileName}.env`); @@ -289,8 +307,8 @@ async function migrateLegacyImageProfile(profileName, profileEnv, imageProfilesD } const pairs = IMAGE_PROFILE_ENV_KEYS - .filter((key) => profileEnv[key] !== undefined) - .map((key) => [key, profileEnv[key]]); + .filter((key) => sourceEnv[key] !== undefined && sourceEnv[key] !== "") + .map((key) => [key, sourceEnv[key]]); await mkdir(imageProfilesDir, { recursive: true }); await writeFile( imageProfilePath, @@ -471,7 +489,13 @@ async function main() { } const { profilePath, env: profileEnv } = await loadProfileEnv(profileName, profilesDir); - const migration = await migrateLegacyImageProfile(profileName, profileEnv, imageProfilesDir); + const existingGatewayConfig = await readJsonFile(paths.configPath); + const migration = await migrateLegacyImageProfile( + profileName, + profileEnv, + imageProfilesDir, + existingGatewayConfig, + ); const requestedImageProfileName = getImageProfileName(options); const imageProfileName = resolveImageProfileName({ requestedImageProfileName, @@ -505,8 +529,6 @@ async function main() { ? Number.parseInt(`${profileEnv.CODEX_RETRY_GATEWAY_LISTEN_PORT}`, 10) : DEFAULT_LISTEN_PORT; const localGatewayBaseUrl = getGatewayBaseUrl(listenHost, listenPort); - const existingGatewayConfig = await readJsonFile(paths.configPath); - const gatewayConfig = buildProfileConfig({ profileName, profileEnv, diff --git a/scripts/test-gateway-e2e.mjs b/scripts/test-gateway-e2e.mjs index f1f0230..a3a0ced 100644 --- a/scripts/test-gateway-e2e.mjs +++ b/scripts/test-gateway-e2e.mjs @@ -611,9 +611,6 @@ async function run() { [ `CODEX_RETRY_GATEWAY_UPSTREAM_BASE_URL=http://127.0.0.1:${upstreamPort}`, "CODEX_RETRY_GATEWAY_UPSTREAM_AUTH_MODE=passthrough", - `CODEX_RETRY_GATEWAY_IMAGE_BASE_URL=http://127.0.0.1:${imageUpstreamPort}`, - "CODEX_RETRY_GATEWAY_IMAGE_AUTH_MODE=fixed_bearer", - "CODEX_RETRY_GATEWAY_IMAGE_AUTH_ENV=TEST_CODEX_RETRY_GATEWAY_IMAGE_API_KEY", "", ].join("\n"), "utf8",