@agent-proxy/gateway 0.11.1 → 0.11.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -26,8 +26,7 @@ agent-proxy install
26
26
  ```
27
27
 
28
28
  默认连接本机上游 `http://127.0.0.1:8317/v1`,网关端口为 `8320`。
29
- 默认运行目录是 `~/.agent-proxy-gateway`。首次从旧默认目录安装时,
30
- `install` 会合并用户设置并复制受管文件,保留旧目录;自定义实例目录不自动迁移。
29
+ 默认运行目录是 `~/.agent-proxy-gateway`。
31
30
  按提示输入 API Key 并选择要在 Codex 中显示的模型:
32
31
 
33
32
  - `↑` / `↓` 移动,空格勾选,回车确认。
package/dist/index.js CHANGED
@@ -13,7 +13,7 @@ var __export = (target, all) => {
13
13
 
14
14
  // src/cli.ts
15
15
  import fs21 from "fs";
16
- import path14 from "path";
16
+ import path15 from "path";
17
17
  import { createHash as createHash3 } from "crypto";
18
18
  import { execFileSync as execFileSync5 } from "child_process";
19
19
  import bytes2 from "bytes";
@@ -230,10 +230,7 @@ function managedCatalogFiles(paths) {
230
230
  return [
231
231
  catalogFileFor(paths, "cliproxy"),
232
232
  catalogFileFor(paths, "newapi"),
233
- path2.join(paths.runtimeHome, "codex-catalog.json"),
234
- path2.join(paths.runtimeHome, "zcode-catalog.json"),
235
- path2.join(paths.runtimeHome, "codebuddy-catalog.json"),
236
- path2.join(paths.runtimeHome, "workbuddy-catalog.json")
233
+ path2.join(paths.runtimeHome, "codex-catalog.json")
237
234
  ];
238
235
  }
239
236
 
@@ -1027,13 +1024,15 @@ function migrateManagedDefaultPaths(config, legacyHome, nextHome) {
1027
1024
  result.model_merge_json = path6.join(nextHome, "models.json");
1028
1025
  return result;
1029
1026
  }
1030
- function managedEntry(name) {
1031
- return ["config.json", "state.json", "models.json", "models-cache.json", "ui-token", "logs", "gateway.log", "gateway.error.log", "webui.log"].includes(name) || /^(?:cliproxy|newapi|codex|zcode|codebuddy(?:-(?:cn|intl))?|workbuddy(?:-(?:cn|intl))?|qoder(?:-(?:cn|intl))?|agy|opencode-zen)-(?:catalog|metadata)\.json$/.test(name) || /^gateway-\d[\dT:_-]*\.log$/.test(name) || /^(?:config|state)\.json\.(?:bak|backup)[\w.-]*$/.test(name);
1032
- }
1033
1027
  function prepareDefaultInstallMigration(paths, env = process.env, platform = process.platform, launchctlExecutor, manualCodexConfig = false) {
1034
1028
  if (env[RUNTIME_HOME_ENV]?.trim() || realPathOrResolve(paths.runtimeHome) !== realPathOrResolve(path6.join(paths.home, DEFAULT_RUNTIME_DIRECTORY)))
1035
1029
  return;
1036
1030
  const legacyPaths = resolvePaths({ ...env, HOME: paths.home, CODEX_CLIPROXY_HOME: path6.join(paths.home, LEGACY_RUNTIME_DIRECTORY) });
1031
+ const legacyRoot = entryStat(legacyPaths.runtimeHome);
1032
+ if (!legacyRoot || legacyRoot.isSymbolicLink())
1033
+ return;
1034
+ if (!legacyRoot.isDirectory())
1035
+ throw new Error(`Migration source is not a directory: ${legacyPaths.runtimeHome}; preserve this entry and repair it before retrying install`);
1037
1036
  const legacyConfig = readObject(legacyPaths.gatewayConfig);
1038
1037
  const legacyState = readObject(legacyPaths.stateFile);
1039
1038
  if (!legacyConfig && !legacyState)
@@ -1064,10 +1063,9 @@ function prepareDefaultInstallMigration(paths, env = process.env, platform = pro
1064
1063
  completeMigration();
1065
1064
  },
1066
1065
  apply() {
1067
- const originalEntries = new Set(fs7.existsSync(paths.runtimeHome) ? fs7.readdirSync(paths.runtimeHome) : []);
1068
1066
  const snapshots = new Map;
1069
1067
  const created = new Set;
1070
- const createdDirectories = new Set;
1068
+ const createdDirectories = new Map;
1071
1069
  let restoreOwner;
1072
1070
  let restoreWebUi;
1073
1071
  let credentialWritten = false;
@@ -1076,11 +1074,13 @@ function prepareDefaultInstallMigration(paths, env = process.env, platform = pro
1076
1074
  if (stat) {
1077
1075
  if (!stat.isDirectory())
1078
1076
  throw new Error(`Migration target is not a directory: ${directory}`);
1079
- return;
1077
+ return false;
1080
1078
  }
1081
1079
  ensureDirectory(path6.dirname(directory));
1082
1080
  fs7.mkdirSync(directory, { mode });
1083
- createdDirectories.add(directory);
1081
+ createdDirectories.set(directory, mode);
1082
+ fs7.chmodSync(directory, mode);
1083
+ return true;
1084
1084
  };
1085
1085
  const capture = (file) => {
1086
1086
  if (snapshots.has(file) || created.has(file))
@@ -1094,22 +1094,26 @@ function prepareDefaultInstallMigration(paths, env = process.env, platform = pro
1094
1094
  created.add(file);
1095
1095
  };
1096
1096
  const copy = (source, target) => {
1097
+ if (entryStat(target))
1098
+ return;
1097
1099
  const stat = fs7.lstatSync(source);
1098
1100
  if (stat.isSymbolicLink())
1099
- throw new Error(`Managed migration source is a symbolic link: ${source}; repair it before retrying install`);
1101
+ return;
1100
1102
  if (stat.isDirectory()) {
1101
- ensureDirectory(target, stat.mode & 511);
1103
+ const mode = stat.mode & 511;
1104
+ if (!ensureDirectory(target, mode | 448))
1105
+ return;
1106
+ createdDirectories.set(target, mode);
1102
1107
  for (const name of fs7.readdirSync(source))
1103
1108
  copy(path6.join(source, name), path6.join(target, name));
1109
+ fs7.chmodSync(target, mode);
1104
1110
  } else if (stat.isFile()) {
1105
- capture(target);
1106
- if (!snapshots.has(target)) {
1107
- ensureDirectory(path6.dirname(target));
1108
- fs7.copyFileSync(source, target, fs7.constants.COPYFILE_EXCL);
1109
- fs7.chmodSync(target, stat.mode & 511);
1110
- }
1111
+ ensureDirectory(path6.dirname(target));
1112
+ fs7.copyFileSync(source, target, fs7.constants.COPYFILE_EXCL);
1113
+ created.add(target);
1114
+ fs7.chmodSync(target, stat.mode & 511);
1111
1115
  } else
1112
- throw new Error(`Managed migration source is not a regular file: ${source}`);
1116
+ throw new Error(`Migration source is not a regular file: ${source}; preserve this entry and repair it before retrying install`);
1113
1117
  };
1114
1118
  const rollback = () => {
1115
1119
  const errors = [];
@@ -1122,29 +1126,42 @@ function prepareDefaultInstallMigration(paths, env = process.env, platform = pro
1122
1126
  };
1123
1127
  restore(() => restoreWebUi?.());
1124
1128
  restore(() => restoreOwner?.());
1129
+ for (const [directory, mode] of createdDirectories)
1130
+ restore(() => {
1131
+ const stat = entryStat(directory);
1132
+ if (stat?.isDirectory())
1133
+ fs7.chmodSync(directory, mode | 448);
1134
+ });
1125
1135
  if (credentialWritten)
1126
1136
  restore(() => createApiKeyStore(platform, paths.credentialsFile).delete());
1127
1137
  for (const [file, snapshot] of snapshots)
1128
1138
  restore(() => atomicWrite(file, snapshot.content, snapshot.mode));
1129
1139
  for (const file of created)
1130
1140
  restore(() => fs7.rmSync(file, { force: true }));
1131
- if (fs7.existsSync(paths.runtimeHome)) {
1132
- for (const name of fs7.readdirSync(paths.runtimeHome)) {
1133
- if (!originalEntries.has(name) && managedEntry(name))
1134
- restore(() => fs7.rmSync(path6.join(paths.runtimeHome, name), { recursive: true, force: true }));
1135
- }
1136
- }
1137
- for (const directory of [...createdDirectories].reverse()) {
1138
- if (fs7.existsSync(directory) && fs7.readdirSync(directory).length === 0)
1139
- restore(() => fs7.rmdirSync(directory));
1140
- }
1141
+ for (const [directory, mode] of [...createdDirectories].reverse())
1142
+ restore(() => {
1143
+ const stat = entryStat(directory);
1144
+ if (!stat?.isDirectory())
1145
+ return;
1146
+ if (fs7.readdirSync(directory).length === 0)
1147
+ fs7.rmdirSync(directory);
1148
+ else
1149
+ fs7.chmodSync(directory, mode);
1150
+ });
1141
1151
  if (errors.length)
1142
1152
  throw new Error(`Default installation restore incomplete: ${errors.join("; ")}`);
1143
1153
  };
1144
1154
  try {
1145
- ensureDirectory(paths.runtimeHome, fs7.statSync(legacyPaths.runtimeHome).mode & 511);
1146
- for (const name of fs7.readdirSync(legacyPaths.runtimeHome).filter(managedEntry))
1147
- copy(path6.join(legacyPaths.runtimeHome, name), path6.join(paths.runtimeHome, name));
1155
+ const sourceRoot = entryStat(legacyPaths.runtimeHome);
1156
+ if (!sourceRoot?.isDirectory())
1157
+ throw new Error(`Migration source is not a directory: ${legacyPaths.runtimeHome}; preserve this entry and repair it before retrying install`);
1158
+ const runtimeMode = sourceRoot.mode & 511;
1159
+ if (ensureDirectory(paths.runtimeHome, runtimeMode | 448))
1160
+ createdDirectories.set(paths.runtimeHome, runtimeMode);
1161
+ for (const name of fs7.readdirSync(legacyPaths.runtimeHome)) {
1162
+ if (name !== "credentials.json")
1163
+ copy(path6.join(legacyPaths.runtimeHome, name), path6.join(paths.runtimeHome, name));
1164
+ }
1148
1165
  capture(paths.gatewayConfig);
1149
1166
  const backupStamp = Date.now().toString();
1150
1167
  for (const file of [paths.gatewayConfig, paths.stateFile]) {
@@ -1197,6 +1214,8 @@ function prepareDefaultInstallMigration(paths, env = process.env, platform = pro
1197
1214
  atomicWrite(paths.stateFile, `${JSON.stringify(installedState, null, 2)}
1198
1215
  `, fs7.statSync(paths.stateFile).mode & 511);
1199
1216
  };
1217
+ if (createdDirectories.has(paths.runtimeHome))
1218
+ fs7.chmodSync(paths.runtimeHome, runtimeMode);
1200
1219
  return rollback;
1201
1220
  } catch (error) {
1202
1221
  try {
@@ -4437,11 +4456,12 @@ async function rebuildCatalog(paths, config, proxyModels, modelsConfigFile) {
4437
4456
 
4438
4457
  // src/gateway-composition.ts
4439
4458
  import { PluginRegistry as PluginRegistry2, compileModelPattern } from "@agent-proxy/plugin-api";
4440
- import { createZcodePlugin, ZCODE_MODEL_PATTERNS } from "@agent-proxy/zcode";
4441
- import { createCodebuddyPlugin, CODEBUDDY_MODEL_PATTERNS } from "@agent-proxy/codebuddy";
4442
- import { createQoderPlugin, QODER_MODEL_PATTERNS } from "@agent-proxy/qoder";
4443
- import { createAgyPlugin, AGY_MODEL_PATTERNS } from "@agent-proxy/agy";
4444
- import { createOpencodeZenPlugin, OPENCODE_ZEN_MODEL_PATTERNS } from "@agent-proxy/opencode-zen";
4459
+ import path12 from "path";
4460
+ import { createZcodePlugin, ZCODE_MODEL_PATTERNS, ZCODE_RUNTIME_ARTIFACTS } from "@agent-proxy/zcode";
4461
+ import { createCodebuddyPlugin, CODEBUDDY_MODEL_PATTERNS, CODEBUDDY_RUNTIME_ARTIFACTS } from "@agent-proxy/codebuddy";
4462
+ import { createQoderPlugin, QODER_MODEL_PATTERNS, QODER_RUNTIME_ARTIFACTS } from "@agent-proxy/qoder";
4463
+ import { createAgyPlugin, AGY_MODEL_PATTERNS, AGY_RUNTIME_ARTIFACTS } from "@agent-proxy/agy";
4464
+ import { createOpencodeZenPlugin, OPENCODE_ZEN_MODEL_PATTERNS, OPENCODE_ZEN_RUNTIME_ARTIFACTS } from "@agent-proxy/opencode-zen";
4445
4465
 
4446
4466
  // src/process-log.ts
4447
4467
  import fs12 from "fs";
@@ -5377,10 +5397,10 @@ function writeStaticCatalog(paths, config, adapterModels, ownsModel = () => fals
5377
5397
  `);
5378
5398
  return catalog;
5379
5399
  }
5380
- function applyModelCatalogToml(source, active, paths, catalogFile) {
5400
+ function applyModelCatalogToml(source, active, paths, catalogFile, managedFiles) {
5381
5401
  const configuredCatalog = readRootTomlString(source, "model_catalog_json");
5382
5402
  const legacyCatalogFile = path10.join(paths.codexHome, "cliproxy-catalog.json");
5383
- if (configuredCatalog && ![...managedCatalogFiles(paths), codexCatalogFile(paths), legacyCatalogFile].includes(configuredCatalog)) {
5403
+ if (configuredCatalog && ![...managedFiles, codexCatalogFile(paths), legacyCatalogFile].includes(configuredCatalog)) {
5384
5404
  throw new Error(`Refusing to replace unmanaged model_catalog_json: ${configuredCatalog}`);
5385
5405
  }
5386
5406
  if (configuredCatalog === undefined && hasRootTomlKey(source, "model_catalog_json")) {
@@ -5392,7 +5412,11 @@ function applyModelCatalogToml(source, active, paths, catalogFile) {
5392
5412
  };
5393
5413
  }
5394
5414
  var hash = (source) => createHash2("sha256").update(source).digest("hex");
5395
- async function updateCodexModelCatalog(paths, config, catalogSource, { refreshAdapters = false, manual: manualOverride } = {}) {
5415
+ async function updateCodexModelCatalog(paths, config, catalogSource, {
5416
+ refreshAdapters = false,
5417
+ manual: manualOverride,
5418
+ managedFiles = managedCatalogFiles(paths)
5419
+ } = {}) {
5396
5420
  const stateSource = fs14.existsSync(paths.stateFile) ? fs14.readFileSync(paths.stateFile, "utf8") : undefined;
5397
5421
  const state = stateSource === undefined ? {} : JSON.parse(stateSource);
5398
5422
  const manual = manualOverride ?? state.codexConfigManaged === false;
@@ -5400,7 +5424,7 @@ async function updateCodexModelCatalog(paths, config, catalogSource, { refreshAd
5400
5424
  const source = tomlExisted ? fs14.readFileSync(paths.configToml, "utf8") : "";
5401
5425
  const catalogPath = codexCatalogFile(paths);
5402
5426
  const active = config.upstreamOnly === true;
5403
- const { patchedToml, previousCatalog } = manual ? { patchedToml: source, previousCatalog: readRootTomlString(source, "model_catalog_json") ?? null } : applyModelCatalogToml(source, active, paths, catalogPath);
5427
+ const { patchedToml, previousCatalog } = manual ? { patchedToml: source, previousCatalog: readRootTomlString(source, "model_catalog_json") ?? null } : applyModelCatalogToml(source, active, paths, catalogPath, managedFiles);
5404
5428
  const tomlChanged = patchedToml !== source;
5405
5429
  const previousSnapshot = fs14.existsSync(catalogPath) ? fs14.readFileSync(catalogPath, "utf8") : undefined;
5406
5430
  let snapshotWritten = false;
@@ -7043,6 +7067,18 @@ var installedPatterns = [
7043
7067
  function isInstalledPluginModel(model) {
7044
7068
  return installedPatterns.some((pattern) => Boolean(pattern.match(model)));
7045
7069
  }
7070
+ function installedPluginArtifactFiles(runtimePaths = resolvePaths()) {
7071
+ return [
7072
+ ...ZCODE_RUNTIME_ARTIFACTS,
7073
+ ...CODEBUDDY_RUNTIME_ARTIFACTS,
7074
+ ...QODER_RUNTIME_ARTIFACTS,
7075
+ ...AGY_RUNTIME_ARTIFACTS,
7076
+ ...OPENCODE_ZEN_RUNTIME_ARTIFACTS
7077
+ ].map((name) => path12.join(runtimePaths.runtimeHome, name));
7078
+ }
7079
+ function managedRuntimeCatalogFiles(runtimePaths = resolvePaths()) {
7080
+ return [...managedCatalogFiles(runtimePaths), ...installedPluginArtifactFiles(runtimePaths)];
7081
+ }
7046
7082
  function createConfiguredPluginRegistry(config, dependencies = {}, processLog, runtimePaths = resolvePaths(), apiKey, catalogMode = config.upstreamOnly === true ? "manual" : "dynamic") {
7047
7083
  config = { ...config };
7048
7084
  const host = createGatewayHostServices(config, processLog, runtimePaths, apiKey);
@@ -7164,16 +7200,19 @@ function rebuildStaticCatalog2(paths, config, dependencies = {}, options = {}) {
7164
7200
  return rebuildStaticCatalog(paths, config, createCatalogSource(config, dependencies), options);
7165
7201
  }
7166
7202
  function updateCodexModelCatalog2(paths, config, dependencies = {}, options = {}) {
7167
- return updateCodexModelCatalog(paths, config, createCatalogSource(config, dependencies), options);
7203
+ return updateCodexModelCatalog(paths, config, createCatalogSource(config, dependencies), {
7204
+ ...options,
7205
+ managedFiles: managedRuntimeCatalogFiles(paths)
7206
+ });
7168
7207
  }
7169
7208
  // src/webui.ts
7170
7209
  import fs20 from "fs";
7171
- import path13 from "path";
7210
+ import path14 from "path";
7172
7211
  import { randomBytes } from "crypto";
7173
7212
 
7174
7213
  // src/app-server.ts
7175
7214
  import fs18 from "fs";
7176
- import path12 from "path";
7215
+ import path13 from "path";
7177
7216
  import { execFileSync as execFileSync4 } from "child_process";
7178
7217
  import { dlopen } from "bun:ffi";
7179
7218
  var GLOBAL_OPTIONS_WITH_VALUE = new Set([
@@ -7394,9 +7433,9 @@ function parseWindowsCommandLine(commandLine) {
7394
7433
  }
7395
7434
  function windowsSystemPath(...segments) {
7396
7435
  const systemRoot = process.env.SystemRoot || process.env.windir;
7397
- if (!systemRoot || !path12.win32.isAbsolute(systemRoot))
7436
+ if (!systemRoot || !path13.win32.isAbsolute(systemRoot))
7398
7437
  throw new Error("Windows system root is unavailable");
7399
- return path12.win32.join(systemRoot, ...segments);
7438
+ return path13.win32.join(systemRoot, ...segments);
7400
7439
  }
7401
7440
  function listWindowsProcesses() {
7402
7441
  const powershell = windowsSystemPath("System32", "WindowsPowerShell", "v1.0", "powershell.exe");
@@ -7889,14 +7928,14 @@ var REQUEST_LOG_TAIL_BYTES = 64 * 1024;
7889
7928
  var REQUEST_LOG_DEFAULT_PAGE_SIZE = 100;
7890
7929
  var REQUEST_LOG_MAX_PAGE_SIZE = 500;
7891
7930
  var RESTART_DELAY_MS = 400;
7892
- var UI_HTML_PATH = path13.resolve(import.meta.dir, "../dist/ui/index.html");
7931
+ var UI_HTML_PATH = path14.resolve(import.meta.dir, "../dist/ui/index.html");
7893
7932
  function webUiContextForInstance(configPath, defaultPaths) {
7894
7933
  const resolved = realPathOrResolve(configPath);
7895
7934
  if (resolved === realPathOrResolve(defaultPaths.gatewayConfig))
7896
7935
  return { paths: defaultPaths };
7897
7936
  return {
7898
7937
  paths: {
7899
- ...resolvePaths({ HOME: defaultPaths.home, CODEX_HOME: defaultPaths.codexHome }, path13.dirname(resolved)),
7938
+ ...resolvePaths({ HOME: defaultPaths.home, CODEX_HOME: defaultPaths.codexHome }, path14.dirname(resolved)),
7900
7939
  gatewayConfig: resolved
7901
7940
  },
7902
7941
  instanceOnly: true
@@ -8133,7 +8172,7 @@ function configResponse(paths, providerDeps, instanceOnly = false) {
8133
8172
  excludedOther
8134
8173
  },
8135
8174
  detected: {
8136
- zcode: zcodeConfigPresent(providerDeps?.zcodeHome ?? path13.join(paths.home, ".zcode")),
8175
+ zcode: zcodeConfigPresent(providerDeps?.zcodeHome ?? path14.join(paths.home, ".zcode")),
8137
8176
  codebuddy: codebuddyCredentialsPresent(codebuddyAuthDir),
8138
8177
  codebuddyAccountLabel: accountLabel ?? null,
8139
8178
  qoder: qoderSources.length > 0,
@@ -8193,7 +8232,7 @@ function requestLogsResponse(config, paths, url) {
8193
8232
  }
8194
8233
  const all = names.filter((name) => isRequestLogName(name)).flatMap((name) => {
8195
8234
  try {
8196
- const stat = fs20.statSync(path13.join(dir, name));
8235
+ const stat = fs20.statSync(path14.join(dir, name));
8197
8236
  return [{
8198
8237
  name,
8199
8238
  size: stat.size,
@@ -8871,7 +8910,7 @@ function timestamp() {
8871
8910
  return new Date().toISOString().replace(/[-:]/g, "").slice(0, 15).replace("T", "");
8872
8911
  }
8873
8912
  function backupConfig(file) {
8874
- fs21.mkdirSync(path14.dirname(file), { recursive: true });
8913
+ fs21.mkdirSync(path15.dirname(file), { recursive: true });
8875
8914
  const existed = fs21.existsSync(file);
8876
8915
  const backup = `${file}.bak-cliproxy-gateway-${timestamp()}`;
8877
8916
  if (existed)
@@ -8885,7 +8924,7 @@ function hash2(contents) {
8885
8924
  }
8886
8925
  function restoreBackup(file, record) {
8887
8926
  if (record.existed) {
8888
- fs21.mkdirSync(path14.dirname(file), { recursive: true });
8927
+ fs21.mkdirSync(path15.dirname(file), { recursive: true });
8889
8928
  fs21.copyFileSync(record.backup, file);
8890
8929
  } else {
8891
8930
  fs21.rmSync(file, { force: true });
@@ -8947,12 +8986,12 @@ function removeManagedRuntimeFiles(paths, options = {}) {
8947
8986
  for (const file of [
8948
8987
  ...options.preserveGatewayConfig ? [] : [paths.gatewayConfig],
8949
8988
  ...options.preserveState ? [] : [paths.stateFile],
8950
- ...managedCatalogFiles(paths),
8951
- path14.join(paths.runtimeHome, "catalog-metadata.json"),
8989
+ ...managedRuntimeCatalogFiles(paths),
8990
+ path15.join(paths.runtimeHome, "catalog-metadata.json"),
8952
8991
  paths.modelMergeFile,
8953
8992
  paths.stdoutLog,
8954
- path14.join(paths.runtimeHome, "webui.log"),
8955
- path14.join(paths.runtimeHome, LEGACY_STDERR_LOG)
8993
+ path15.join(paths.runtimeHome, "webui.log"),
8994
+ path15.join(paths.runtimeHome, LEGACY_STDERR_LOG)
8956
8995
  ]) {
8957
8996
  fs21.rmSync(file, { force: true });
8958
8997
  }
@@ -9173,7 +9212,7 @@ async function installCurrent(options, completeMigration) {
9173
9212
  applyRoutingMode(config, paths, upstreamOnly);
9174
9213
  const installSelector = stringOption(options, "select");
9175
9214
  if (!manualCodexConfig) {
9176
- applyModelCatalogToml(currentToml, upstreamOnly && !isSelectNone(installSelector), paths, codexCatalogFile(paths));
9215
+ applyModelCatalogToml(currentToml, upstreamOnly && !isSelectNone(installSelector), paths, codexCatalogFile(paths), managedRuntimeCatalogFiles(paths));
9177
9216
  }
9178
9217
  const previousApiKey = readApiKey(true);
9179
9218
  const apiKey = getInstallApiKey(config, previousConfig, stringOption(options, "key-env"), {
@@ -9203,7 +9242,7 @@ async function installCurrent(options, completeMigration) {
9203
9242
  console.log(`Selected ${selectedModels.length} ${upstreamLabel(config)} models.`);
9204
9243
  }
9205
9244
  config.selectedModels = selectedModels;
9206
- const { patchedToml: modelCatalogToml } = manualCodexConfig ? { patchedToml: currentToml } : applyModelCatalogToml(currentToml, upstreamOnly, paths, codexCatalogFile(paths));
9245
+ const { patchedToml: modelCatalogToml } = manualCodexConfig ? { patchedToml: currentToml } : applyModelCatalogToml(currentToml, upstreamOnly, paths, codexCatalogFile(paths), managedRuntimeCatalogFiles(paths));
9207
9246
  const previousState = switching ? fs21.readFileSync(paths.stateFile, "utf8") : undefined;
9208
9247
  const priorState = switching ? loadJson(paths.stateFile) : undefined;
9209
9248
  const previousManaged = priorState ? isCodexConfigManaged(priorState) && priorState.uninstallClientRestored !== true : true;
@@ -9416,7 +9455,7 @@ async function uninstall(options) {
9416
9455
  assertCodexHomeAvailable(paths, false);
9417
9456
  uninstallLaunchAgent(paths.launchAgent);
9418
9457
  uninstallLaunchAgent(paths.webUiLaunchAgent);
9419
- const legacyCatalogFile = path14.join(paths.codexHome, "cliproxy-catalog.json");
9458
+ const legacyCatalogFile = path15.join(paths.codexHome, "cliproxy-catalog.json");
9420
9459
  if (restoresClient) {
9421
9460
  const currentToml = fs21.existsSync(paths.configToml) ? fs21.readFileSync(paths.configToml, "utf8") : "";
9422
9461
  restoreManagedCodexToml(paths, state, currentToml);
@@ -9607,9 +9646,9 @@ async function models(options) {
9607
9646
  }
9608
9647
  const manualCodexConfig = fs21.existsSync(paths.stateFile) && !isCodexConfigManaged(loadJson(paths.stateFile));
9609
9648
  const source = fs21.existsSync(paths.configToml) ? fs21.readFileSync(paths.configToml, "utf8") : "";
9610
- const legacyCatalogFile = path14.join(paths.codexHome, "cliproxy-catalog.json");
9649
+ const legacyCatalogFile = path15.join(paths.codexHome, "cliproxy-catalog.json");
9611
9650
  if (!manualCodexConfig) {
9612
- applyModelCatalogToml(source, upstreamOnly, paths, codexCatalogFile(paths));
9651
+ applyModelCatalogToml(source, upstreamOnly, paths, codexCatalogFile(paths), managedRuntimeCatalogFiles(paths));
9613
9652
  }
9614
9653
  const { modelsConfigFile, rules } = await loadModelOverrideRules(paths, config, Boolean(modelMergeJson));
9615
9654
  const selectNone = isSelectNone(selector);
@@ -9703,7 +9742,7 @@ function serve(options) {
9703
9742
  if (!fs21.existsSync(configPath))
9704
9743
  throw new Error(`Gateway config not found: ${configPath}`);
9705
9744
  const config = loadGatewayConfig(configPath);
9706
- const isProductionInstance = configPath === realPathOrResolve(path14.join(paths.runtimeHome, "config.json"));
9745
+ const isProductionInstance = configPath === realPathOrResolve(path15.join(paths.runtimeHome, "config.json"));
9707
9746
  const processLog = isProductionInstance ? { file: paths.stdoutLog, maxBytes: config.maxGatewayLogBytes ?? 0 } : undefined;
9708
9747
  startGateway(config, loadRealtimeProviderMode(paths.configToml), paths.upstreamModelsCacheFile, { codexModelsCacheFile: paths.modelsCacheFile }, processLog, { codexModelsCacheFile: paths.modelsCacheFile }, { codexModelsCacheFile: paths.modelsCacheFile }, { codexModelsCacheFile: paths.modelsCacheFile }, { codexModelsCacheFile: paths.modelsCacheFile });
9709
9748
  if (isProductionInstance)
@@ -9735,7 +9774,7 @@ async function waitForWebUi(port, timeoutMs = 1e4) {
9735
9774
  throw new Error(`Web UI did not come up on port ${port} within ${timeoutMs / 1000}s`);
9736
9775
  }
9737
9776
  function webUiLogPath(paths) {
9738
- return path14.join(paths.runtimeHome, "webui.log");
9777
+ return path15.join(paths.runtimeHome, "webui.log");
9739
9778
  }
9740
9779
  function runWebUiForeground(paths, config, openBrowser) {
9741
9780
  const ctx = webUiContextForInstance(paths.gatewayConfig, paths);
@@ -10018,7 +10057,7 @@ async function configCommand(options) {
10018
10057
  const managesCodex = !fs21.existsSync(paths.stateFile) || isCodexConfigManaged(loadJson(paths.stateFile));
10019
10058
  if (managesCodex) {
10020
10059
  const source = fs21.existsSync(paths.configToml) ? fs21.readFileSync(paths.configToml, "utf8") : "";
10021
- applyModelCatalogToml(source, config.upstreamOnly === true, paths, codexCatalogFile(paths));
10060
+ applyModelCatalogToml(source, config.upstreamOnly === true, paths, codexCatalogFile(paths), managedRuntimeCatalogFiles(paths));
10022
10061
  }
10023
10062
  if (zcodeTarget !== undefined) {
10024
10063
  config.zcode = zcodeTarget;
@@ -10157,7 +10196,7 @@ function ownsManagedCodexConfig(paths, state, legacyBaseUrl) {
10157
10196
  function syncGatewayConfigFile(paths, configFile = paths.gatewayConfig) {
10158
10197
  if (!fs21.existsSync(configFile))
10159
10198
  return;
10160
- const managesState = realPathOrResolve(configFile) === realPathOrResolve(path14.join(paths.runtimeHome, "config.json"));
10199
+ const managesState = realPathOrResolve(configFile) === realPathOrResolve(path15.join(paths.runtimeHome, "config.json"));
10161
10200
  const raw = loadJson(configFile);
10162
10201
  if (!isJsonObject(raw))
10163
10202
  throw new Error(`Gateway config must be a JSON object: ${configFile}`);
@@ -10320,7 +10359,7 @@ async function runCli(args) {
10320
10359
  }
10321
10360
  const configOption = command === "serve" ? stringOption(options, "config") : undefined;
10322
10361
  const configPath = configOption ? realPathOrResolve(configOption) : undefined;
10323
- let paths = configPath ? { ...resolvePaths(process.env, path14.dirname(configPath)), gatewayConfig: configPath } : resolvePaths();
10362
+ let paths = configPath ? { ...resolvePaths(process.env, path15.dirname(configPath)), gatewayConfig: configPath } : resolvePaths();
10324
10363
  const migration = command === "install" ? prepareDefaultInstallMigration(paths) : undefined;
10325
10364
  paths = migration?.paths ?? resolveInstalledCodexPaths(paths);
10326
10365
  return runWithInstancePaths(paths, async () => {