@yansigit/opencodex 2.35.2-dev.20260829.13 → 2.36.1-dev.20260829.17

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.
@@ -16,7 +16,7 @@
16
16
  } catch (e) {}
17
17
  })();
18
18
  </script>
19
- <script type="module" crossorigin src="/assets/index-C8Tctiwl.js"></script>
19
+ <script type="module" crossorigin src="/assets/index-l0pKn4-2.js"></script>
20
20
  <link rel="stylesheet" crossorigin href="/assets/index-DLkXOXLC.css">
21
21
  </head>
22
22
  <body>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yansigit/opencodex",
3
- "version": "2.35.2-dev.20260829.13",
3
+ "version": "2.36.1-dev.20260829.17",
4
4
  "description": "Universal provider proxy for OpenAI Codex & Claude Code — use any LLM with Codex CLI/App/SDK and Claude Code",
5
5
  "type": "module",
6
6
  "main": "./bin/package-main.mjs",
package/src/config.ts CHANGED
@@ -109,6 +109,7 @@ import {
109
109
  atomicWriteFile,
110
110
  isMissingPathError,
111
111
  nextAtomicTempSequence,
112
+ resolveWriteTarget,
112
113
  } from "./config/atomic-write";
113
114
  export {
114
115
  AtomicWriteResidualTempError,
@@ -2180,6 +2181,19 @@ function mergeConfigDefaults(parsed: unknown): unknown {
2180
2181
  return merged;
2181
2182
  }
2182
2183
 
2184
+ function configNeedsProviderRepair(parsed: Record<string, unknown>): boolean {
2185
+ const providers = parsed.providers;
2186
+ if (parsed.defaultProvider !== undefined
2187
+ || (providers && typeof providers === "object" && !Array.isArray(providers)
2188
+ && Object.keys(providers).length > 0)) return false;
2189
+ const candidate = structuredClone(parsed);
2190
+ sanitizeAliasesForLoad(candidate);
2191
+ sanitizeRetryOn429ForLoad(candidate);
2192
+ sanitizeModelCostsForLoad(candidate);
2193
+ return !configSchema.safeParse(candidate).success
2194
+ && configSchema.safeParse(mergeConfigDefaults(candidate)).success;
2195
+ }
2196
+
2183
2197
  function schemaDiagnosticsError(error: z.ZodError): string {
2184
2198
  const details = error.issues.map(issue => {
2185
2199
  const path = issue.path.join(".") || "config";
@@ -2720,6 +2734,14 @@ export const withExpectedConfigGenerationSync: WithExpectedConfigGenerationSync
2720
2734
  */
2721
2735
  function persistConfigUnlocked(config: OcxConfig): boolean {
2722
2736
  const configPath = getConfigPath();
2737
+ // Check the resolved file target before reading it: a symlink can point from an
2738
+ // isolated test home into the protected real home, where another write guard
2739
+ // must not mask this refusal based on the target's current contents.
2740
+ assertNotRealHomeUnderTest(dirname(resolveWriteTarget(configPath)));
2741
+ const raw = readRawConfigJson();
2742
+ if (raw && configNeedsProviderRepair(raw)) {
2743
+ throw new Error("refusing to overwrite a config repaired with defaults; fix the persisted config first");
2744
+ }
2723
2745
  // External editors can add provider rows the live config deliberately does
2724
2746
  // not route with yet; merge them at the serialization boundary so an
2725
2747
  // unrelated in-process save cannot erase the provider or its overlay.
@@ -3353,7 +3375,7 @@ function warnConfigRepaired(configPath: string, error: z.ZodError): void {
3353
3375
  if (warnedConfigFallbacks.has(configPath)) return;
3354
3376
  warnedConfigFallbacks.add(configPath);
3355
3377
  const fields = error.issues.map(i => i.path.join(".") || "config").join(", ");
3356
- console.error(`opencodex config at ${configPath}: repaired missing field(s) [${fields}] with defaults. Your providers and accounts are preserved.`);
3378
+ console.error(`opencodex config at ${configPath}: repaired invalid or missing field(s) [${fields}] in memory. A providerless fallback config will not be written automatically.`);
3357
3379
  }
3358
3380
 
3359
3381
  /**
@@ -10,7 +10,7 @@
10
10
  },
11
11
  {
12
12
  "path": "package.json",
13
- "sha256": "d4d7ca044f38d4ae640587f7f21230425cb1a500ee2b56d2c8418c73812bda30"
13
+ "sha256": "92a14143a77f8c42de843d7c7652699316f4c5f829cc0aaa6cdfa0bdf1738280"
14
14
  },
15
15
  {
16
16
  "path": "scripts/model-metadata.source.json",
@@ -1166,7 +1166,7 @@
1166
1166
  },
1167
1167
  {
1168
1168
  "path": "src/config.ts",
1169
- "sha256": "4534807abf3722078ae2c6d377885a12d4e6921b376601ea6d76ccc3f677cfb9"
1169
+ "sha256": "f5fb76e03c8e27883d2522cf78daf7ef4643e36625e126683d470f4f7616d3f8"
1170
1170
  },
1171
1171
  {
1172
1172
  "path": "src/config/atomic-write.ts",
@@ -2682,7 +2682,7 @@
2682
2682
  },
2683
2683
  {
2684
2684
  "path": "src/server/index.ts",
2685
- "sha256": "5dd54908f3adb4d22b39e6d44924ef9e5e254bca2590e22e653ae0ac03f583b3"
2685
+ "sha256": "571ee5edbbff9311f3c5bf044c5330b03b8defc47dd6c05ea118ece2b91c1b3d"
2686
2686
  },
2687
2687
  {
2688
2688
  "path": "src/server/lifecycle.ts",
@@ -2702,7 +2702,7 @@
2702
2702
  },
2703
2703
  {
2704
2704
  "path": "src/server/management-api.ts",
2705
- "sha256": "f32c50a454a5bdfd738790a589badc1faf594412b014faadb8ae01b774856472"
2705
+ "sha256": "908099bead27f40d7147bac8ab156717ac8af6494a4a7caa85f3ecfc5b11c6da"
2706
2706
  },
2707
2707
  {
2708
2708
  "path": "src/server/management-auth.ts",
@@ -2710,7 +2710,7 @@
2710
2710
  },
2711
2711
  {
2712
2712
  "path": "src/server/management/agent-settings-routes.ts",
2713
- "sha256": "1fb5e34401044aedbc3164c083d0c1d37857083f3144e296d4e5ad4993bc3cee"
2713
+ "sha256": "223da28c5ed1951dbaf014ebac9e26c8035d14884b50b7985294c0d39e1c0ab8"
2714
2714
  },
2715
2715
  {
2716
2716
  "path": "src/server/management/api-access.ts",
@@ -2730,15 +2730,15 @@
2730
2730
  },
2731
2731
  {
2732
2732
  "path": "src/server/management/combo-routes.ts",
2733
- "sha256": "889a32183516f12b8dcfa66b04005210c79cafd9bf3d6d28ff480d72d1554c95"
2733
+ "sha256": "fcb5f839b6a8e4f2ea1a1f6ccd80c932efc1a68ce0ce5b3c6aeea15885942631"
2734
2734
  },
2735
2735
  {
2736
2736
  "path": "src/server/management/config-routes.ts",
2737
- "sha256": "ad0d8c16dde2c10530bdf7a2ffe5344e7fdd230cd8b71c13d297f260d3ae6e71"
2737
+ "sha256": "090f6f7ba1d80d2d23fc090134fa6dc4e7114a646d3c41dd4b08eb137255964a"
2738
2738
  },
2739
2739
  {
2740
2740
  "path": "src/server/management/context.ts",
2741
- "sha256": "87144e592ec4b66d3b5ca4f616565a6745c823595c1c59d26be16f38cc918468"
2741
+ "sha256": "48b53d840a12a08da2e22864d209099bb3832d9571360899f670956ed0e2a5fa"
2742
2742
  },
2743
2743
  {
2744
2744
  "path": "src/server/management/integration-routes.ts",
@@ -2754,11 +2754,11 @@
2754
2754
  },
2755
2755
  {
2756
2756
  "path": "src/server/management/logs-usage-routes.ts",
2757
- "sha256": "756c8d015d880a76ec4ef086c423f7a9b04fc874568b06ebb48d6f5deb3e8827"
2757
+ "sha256": "24f5aec4c42a7ae0460d60acab8242facaa1b8f27d67d96f22ebb439a85955c2"
2758
2758
  },
2759
2759
  {
2760
2760
  "path": "src/server/management/model-routes.ts",
2761
- "sha256": "5927c79c91419e5b4065c86f0bf6665cf3a178850cf08755d05960c5559a1518"
2761
+ "sha256": "eaa34ed610ea3651c48d36b47f1b34eaf7ac74b33ccfff1f5852f809d71845f2"
2762
2762
  },
2763
2763
  {
2764
2764
  "path": "src/server/management/model-rows.ts",
@@ -2766,11 +2766,11 @@
2766
2766
  },
2767
2767
  {
2768
2768
  "path": "src/server/management/native-integration-routes.ts",
2769
- "sha256": "43aa083ea1c838f2c86ce778c76fd0be362f509459d60cd8dfcddf489194fcd8"
2769
+ "sha256": "cc0c9f72afb609bae1da2caa0140b8c75c43a10b8eaaf919d0993387ad8d30e8"
2770
2770
  },
2771
2771
  {
2772
2772
  "path": "src/server/management/oauth-account-routes.ts",
2773
- "sha256": "9f1fe5834e08d8a68ec1facb2c9a89a5e389e2140a1430e689fd5748fdf1c76b"
2773
+ "sha256": "2fd9233cd2994161950747fc771e67a5724d1a961ff474fd0cd2e4693638938f"
2774
2774
  },
2775
2775
  {
2776
2776
  "path": "src/server/management/provider-capability-config.ts",
@@ -2778,11 +2778,11 @@
2778
2778
  },
2779
2779
  {
2780
2780
  "path": "src/server/management/provider-routes.ts",
2781
- "sha256": "914b7a6cb10609e062874d2af8226f6471d18b269a96e0a0e6e215412d250603"
2781
+ "sha256": "5e9d3b6985b2e498034a4d06336be2de6a6d77ddab7dc794ed3eb2979bd4ce25"
2782
2782
  },
2783
2783
  {
2784
2784
  "path": "src/server/management/replit-provider-routes.ts",
2785
- "sha256": "b4de19caa24b46ab3c0ac2281e3dd30c6673d410b0728421b6324da8f13f3363"
2785
+ "sha256": "455c81cdc658a65ac960d64747f0aa1b273cdb57d0ef7f7febc2a3b76d244d73"
2786
2786
  },
2787
2787
  {
2788
2788
  "path": "src/server/management/request-history-routes.ts",
@@ -2794,11 +2794,11 @@
2794
2794
  },
2795
2795
  {
2796
2796
  "path": "src/server/management/routing-profile-routes.ts",
2797
- "sha256": "bb36b25beb53c63a2a875a301cc27dad58e1e68503af6c7fafe1e9a75b321011"
2797
+ "sha256": "2af59cc4760eaa45aee41e2685187ed63228a8e60fe0b72c72f501ba54a5155a"
2798
2798
  },
2799
2799
  {
2800
2800
  "path": "src/server/management/shared.ts",
2801
- "sha256": "20d037194bf445da81fc3e266885344c5c3f8e252cabe46d11c4de68a71748ab"
2801
+ "sha256": "5bab0481beb8bcaf8b6a42b0b6da7b53e01bc79d9da39f10958360c56b904c1e"
2802
2802
  },
2803
2803
  {
2804
2804
  "path": "src/server/management/sidebar-routes.ts",
@@ -2994,7 +2994,7 @@
2994
2994
  },
2995
2995
  {
2996
2996
  "path": "src/server/responses/v2-routed-delegation-bridge.ts",
2997
- "sha256": "a0ea013323d54c81426a0abc42eef6682d160a9ce71e3fc209c3124034ee514b"
2997
+ "sha256": "6b4e814ea2539d51bd8e4071230954d46c045e08745fd2d586ee0d0636610b21"
2998
2998
  },
2999
2999
  {
3000
3000
  "path": "src/server/responses/ws-upstream.ts",
@@ -17,6 +17,8 @@ import {
17
17
  armClaudeCodeBaseline,
18
18
  loadConfig,
19
19
  saveConfig,
20
+ saveConfigPreservingClaudeCode,
21
+ mutatePersistedConfig,
20
22
  getConfigDir,
21
23
  websocketsEnabled,
22
24
  } from "../config";
@@ -531,6 +533,11 @@ export function warnAgentTaskRecoveryStartup(config: {
531
533
  }
532
534
 
533
535
  export function startServer(port?: number, deps: StartServerDeps = {}): Server<WsData> {
536
+ const managementApi: ManagementApiDeps = {
537
+ saveConfigPreservingClaudeCode,
538
+ mutatePersistedConfig,
539
+ ...deps.managementApi,
540
+ };
534
541
  const localAttestationSecret = deps.localAttestationSecret ?? createLocalAttestationSecret();
535
542
  const config = runModelRenameStartupMigration(runAlibabaRegionStartupMigration(runOpenAiTierStartupMigration(loadConfig())));
536
543
  warnAgentTaskRecoveryStartup(config);
@@ -1044,7 +1051,7 @@ export function startServer(port?: number, deps: StartServerDeps = {}): Server<W
1044
1051
  method: "POST",
1045
1052
  headers: { Host: req.headers.get("Host") ?? "127.0.0.1" },
1046
1053
  });
1047
- const probeResponse = await handleManagementAPI(probeRequest, new URL(probeRequest.url), config, deps.managementApi);
1054
+ const probeResponse = await handleManagementAPI(probeRequest, new URL(probeRequest.url), config, managementApi);
1048
1055
  const probe = await probeResponse?.json().catch(() => null) as { ok?: boolean; error?: string } | null;
1049
1056
  if (!probe?.ok) return jsonResponse({ ok: false, error: probe?.error ?? "AI Studio connection probe failed" }, 502, req, policy);
1050
1057
  return jsonResponse({ ok: true, sessionPath: login.sessionPath }, 200, req, policy);
@@ -1122,7 +1129,7 @@ export function startServer(port?: number, deps: StartServerDeps = {}): Server<W
1122
1129
  // gate used. Consent-bearing routes need this: request headers are forgeable
1123
1130
  // by anything holding the admin token, the credential is not.
1124
1131
  const principal = managementPrincipal(req, managementAuth, config, localManagementAuth) ?? undefined;
1125
- const mgmtResponse = await handleManagementAPI(req, url, config, deps.managementApi, principal);
1132
+ const mgmtResponse = await handleManagementAPI(req, url, config, managementApi, principal);
1126
1133
  if (mgmtResponse) return withManagementCors(mgmtResponse, req, config);
1127
1134
  return withManagementCors(formatErrorResponse(404, "not_found", `Unknown endpoint: ${req.method} ${url.pathname}`), req, config);
1128
1135
  }