@yansigit/opencodex 2.31.3 → 2.33.0

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.
Files changed (176) hide show
  1. package/README.md +2 -2
  2. package/bin/ocx.mjs +99 -70
  3. package/gui/dist/assets/index-DKLr4LTE.js +102 -0
  4. package/gui/dist/assets/index-DrSQdTRd.css +1 -0
  5. package/gui/dist/index.html +2 -2
  6. package/package.json +6 -5
  7. package/src/adapters/anthropic.ts +25 -13
  8. package/src/adapters/azure.ts +20 -4
  9. package/src/adapters/base.ts +5 -1
  10. package/src/adapters/command-code.ts +42 -10
  11. package/src/adapters/cursor/live-models.ts +8 -0
  12. package/src/adapters/cursor/live-transport.ts +1 -1
  13. package/src/adapters/cursor/native-exec-desktop.ts +16 -0
  14. package/src/adapters/cursor/protobuf-events.ts +158 -7
  15. package/src/adapters/cursor/protobuf-request.ts +33 -15
  16. package/src/adapters/cursor/request-builder.ts +4 -3
  17. package/src/adapters/cursor/tool-definitions.ts +27 -1
  18. package/src/adapters/cursor/types.ts +4 -3
  19. package/src/adapters/cursor.ts +9 -0
  20. package/src/adapters/google-antigravity-replay.ts +2 -2
  21. package/src/adapters/google-antigravity-wire.ts +7 -0
  22. package/src/adapters/google-errors.ts +6 -2
  23. package/src/adapters/google-http.ts +30 -7
  24. package/src/adapters/google-truncation.ts +5 -0
  25. package/src/adapters/google-wire-compiler.ts +38 -6
  26. package/src/adapters/google.ts +154 -33
  27. package/src/adapters/kiro-tools.ts +20 -9
  28. package/src/adapters/kiro.ts +0 -3
  29. package/src/adapters/openai-chat.ts +9 -0
  30. package/src/adapters/openai-responses.ts +4 -1
  31. package/src/adapters/tool-catalog-nudge.ts +1 -1
  32. package/src/adapters/xai-web-search.ts +7 -2
  33. package/src/bridge.ts +133 -24
  34. package/src/claude/context-windows.ts +16 -9
  35. package/src/cli/dispatch.ts +50 -2
  36. package/src/cli/doctor.ts +26 -13
  37. package/src/cli/help.ts +4 -3
  38. package/src/cli/index.ts +20 -6
  39. package/src/cli/models.ts +13 -3
  40. package/src/cli/observe.ts +20 -5
  41. package/src/cli/provider.ts +8 -1
  42. package/src/cli/registry.ts +7 -5
  43. package/src/cli/status.ts +25 -1
  44. package/src/cli/system-restart-client.ts +1 -1
  45. package/src/cli/usage-report.ts +134 -0
  46. package/src/codex/app-server-processes.ts +3 -1
  47. package/src/codex/auth-api.ts +4 -2
  48. package/src/codex/autostart-health.ts +16 -0
  49. package/src/codex/catalog/aggregation.ts +12 -0
  50. package/src/codex/catalog/effort.ts +42 -12
  51. package/src/codex/catalog/metadata.ts +27 -1
  52. package/src/codex/catalog/model-metadata.ts +593 -0
  53. package/src/codex/catalog/parsing.ts +71 -27
  54. package/src/codex/catalog/provider-fetch.ts +189 -33
  55. package/src/codex/catalog/sync.ts +6 -5
  56. package/src/codex/convergence.ts +5 -0
  57. package/src/codex/desktop-app-restart.ts +342 -0
  58. package/src/codex/history-job.ts +32 -3
  59. package/src/codex/history-manifest.ts +112 -0
  60. package/src/codex/history-migration-guardian.ts +5 -5
  61. package/src/codex/history-provider.ts +825 -247
  62. package/src/codex/history-worker.ts +8 -5
  63. package/src/codex/inject.ts +49 -21
  64. package/src/codex/injected-marker.ts +1 -1
  65. package/src/codex/internal/history-writer.ts +4 -3
  66. package/src/codex/native-profile-startup.ts +157 -27
  67. package/src/codex/native-residue.ts +26 -33
  68. package/src/codex/shim.ts +56 -3
  69. package/src/combos/failover.ts +27 -0
  70. package/src/compatibility/index.ts +26 -0
  71. package/src/compatibility/manifest.ts +253 -0
  72. package/src/compatibility/openai-responses.ts +81 -0
  73. package/src/config/atomic-write.ts +219 -0
  74. package/src/config/paths.ts +40 -0
  75. package/src/config/process-state.ts +308 -0
  76. package/src/config/provider-validation.ts +214 -0
  77. package/src/config.ts +153 -814
  78. package/src/generated/compatibility-version.json +232 -148
  79. package/src/images/loop.ts +37 -6
  80. package/src/images/plan.ts +5 -4
  81. package/src/integrations/ownership-policy.ts +141 -0
  82. package/src/integrations/ownership.ts +10 -0
  83. package/src/integrations/state.ts +44 -5
  84. package/src/integrations/writer.ts +6 -0
  85. package/src/lib/azure-identity.ts +154 -0
  86. package/src/lib/bounded-body.ts +14 -2
  87. package/src/lib/debug.ts +42 -0
  88. package/src/lib/errors.ts +14 -0
  89. package/src/lib/process-control.ts +2 -1
  90. package/src/lib/provider-outbound.ts +45 -33
  91. package/src/lib/provider-tls-profile.ts +309 -0
  92. package/src/lib/proxy-env.ts +49 -0
  93. package/src/lib/redact.ts +10 -1
  94. package/src/lib/state-store-registrations.ts +2 -0
  95. package/src/lib/tool-argument-integers.ts +56 -5
  96. package/src/oauth/antigravity-routing.ts +282 -236
  97. package/src/oauth/callback-server.ts +22 -2
  98. package/src/oauth/command-code.ts +5 -16
  99. package/src/oauth/google-antigravity.ts +42 -5
  100. package/src/oauth/health.ts +1 -1
  101. package/src/oauth/index.ts +15 -3
  102. package/src/oauth/kimi.ts +9 -1
  103. package/src/oauth/open-browser-choice.ts +26 -0
  104. package/src/oauth/store.ts +6 -0
  105. package/src/providers/antigravity-quota.ts +3 -1
  106. package/src/providers/api-keys.ts +2 -1
  107. package/src/providers/auto-compact-budget.ts +65 -0
  108. package/src/providers/derive.ts +4 -0
  109. package/src/providers/key-failover.ts +5 -1
  110. package/src/providers/openai-tiers.ts +5 -0
  111. package/src/providers/provider-id-rewrite.ts +1 -0
  112. package/src/providers/quota.ts +59 -13
  113. package/src/providers/registry.ts +4 -2
  114. package/src/providers/request-pacing.ts +33 -6
  115. package/src/providers/xai-transport.ts +21 -0
  116. package/src/reasoning-effort.ts +19 -2
  117. package/src/responses/apply-patch-envelope.ts +63 -0
  118. package/src/responses/custom-tool-compat.ts +132 -38
  119. package/src/responses/google-provider-options.ts +36 -0
  120. package/src/responses/namespace-tool-compat.ts +84 -4
  121. package/src/responses/parser.ts +14 -2
  122. package/src/responses/provider-opaque-metadata.ts +3 -3
  123. package/src/responses/reasoning-replay-cache.ts +81 -3
  124. package/src/responses/schema.ts +37 -0
  125. package/src/responses/state.ts +94 -4
  126. package/src/router.ts +8 -2
  127. package/src/server/auth-cors.ts +37 -7
  128. package/src/server/images.ts +19 -35
  129. package/src/server/index.ts +102 -21
  130. package/src/server/local-management-read-client.ts +1 -1
  131. package/src/server/local-provider-reload-client.ts +1 -1
  132. package/src/server/management/agent-settings-routes.ts +206 -16
  133. package/src/server/management/combo-routes.ts +6 -0
  134. package/src/server/management/config-routes.ts +35 -6
  135. package/src/server/management/context.ts +1 -1
  136. package/src/server/management/logs-usage-routes.ts +27 -6
  137. package/src/server/management/model-routes.ts +8 -4
  138. package/src/server/management/model-rows.ts +4 -0
  139. package/src/server/management/native-integration-routes.ts +2 -1
  140. package/src/server/management/oauth-account-routes.ts +25 -4
  141. package/src/server/management/provider-capability-config.ts +1 -1
  142. package/src/server/management/provider-routes.ts +113 -15
  143. package/src/server/management/routing-profile-routes.ts +3 -0
  144. package/src/server/management/system-restart.ts +1 -1
  145. package/src/server/port-reclaim.ts +1 -1
  146. package/src/server/proxy-liveness.ts +2 -1
  147. package/src/server/request-log-conversation.ts +30 -0
  148. package/src/server/request-log.ts +21 -0
  149. package/src/server/responses/agent-task-recovery.ts +1 -1
  150. package/src/server/responses/codex-auth-error.ts +55 -0
  151. package/src/server/responses/combo-stream-preflight.ts +171 -0
  152. package/src/server/responses/compact.ts +36 -22
  153. package/src/server/responses/core.ts +584 -247
  154. package/src/server/responses/empty-completion-guard.ts +35 -6
  155. package/src/server/responses/fetch-helpers.ts +20 -102
  156. package/src/server/responses/v2-native-parent-override.ts +59 -0
  157. package/src/server/responses/ws-upstream.ts +75 -2
  158. package/src/server/responses-custom-tool-repair.ts +41 -5
  159. package/src/server/responses-undeclared-tool-guard.ts +241 -18
  160. package/src/service.ts +9 -5
  161. package/src/types/config.ts +16 -1
  162. package/src/types/provider.ts +16 -0
  163. package/src/types/request.ts +34 -1
  164. package/src/types/tools.ts +114 -11
  165. package/src/types.ts +7 -1
  166. package/src/update/index.ts +5 -4
  167. package/src/update/job.ts +3 -1
  168. package/src/update/transactional-install.mjs +8 -1
  169. package/src/usage/log.ts +16 -8
  170. package/src/usage/summary.ts +201 -8
  171. package/src/vision/describe.ts +18 -13
  172. package/src/web-search/executor.ts +10 -3
  173. package/src/web-search/gemini-executor.ts +6 -4
  174. package/src/web-search/loop.ts +42 -6
  175. package/gui/dist/assets/index-CGoDO3uO.css +0 -1
  176. package/gui/dist/assets/index-Cxt5fZMP.js +0 -102
package/README.md CHANGED
@@ -53,7 +53,7 @@ account while existing threads stay pinned to the account that started them.
53
53
  ### For humans
54
54
 
55
55
  ```bash
56
- npm install -g @yansigit/opencodex # Node 18+; the Bun runtime is bundled automatically
56
+ npm install -g @yansigit/opencodex # Node 22+; the Bun runtime is bundled automatically
57
57
  ocx start # or `ocx service` to run it in the background
58
58
  ```
59
59
 
@@ -128,7 +128,7 @@ already contain an unused version.
128
128
  | Linux (x64 / arm64) | Fully supported | systemd (user unit) |
129
129
  | Windows (x64) | Fully supported | Task Scheduler (hidden) / opt-in native service (`--native`, WinSW) |
130
130
 
131
- Requires [Node](https://nodejs.org) 18+. The Bun runtime is bundled on `npm install` — no separate
131
+ Requires [Node](https://nodejs.org) 22+. The Bun runtime is bundled on `npm install` — no separate
132
132
  Bun install needed, no WSL needed on Windows. If npm blocked the bundled runtime's install scripts,
133
133
  see the [installation docs](https://opencodex.me/getting-started/installation/).
134
134
 
package/bin/ocx.mjs CHANGED
@@ -235,11 +235,90 @@ function runNpmSelfUpdate() {
235
235
  } catch { /* keep default */ }
236
236
  }
237
237
 
238
+ const launcher = fileURLToPath(import.meta.url);
239
+
240
+ function startProxyDirectly() {
241
+ if (!existsSync(launcher)) {
242
+ console.error("opencodex: cannot restart the proxy because the launcher is missing; reinstall opencodex manually.");
243
+ return;
244
+ }
245
+ const env = { ...process.env };
246
+ delete env.OCX_SERVICE;
247
+ console.log(`Attempting to restart the proxy on port ${bakePort}.`);
248
+ const child = spawn(process.execPath, [launcher, "start", "--port", String(bakePort)], {
249
+ detached: true,
250
+ stdio: "ignore",
251
+ windowsHide: true,
252
+ env,
253
+ });
254
+ child.on("error", error => {
255
+ console.error(`opencodex: direct proxy restart failed: ${error.message}`);
256
+ });
257
+ child.unref();
258
+ }
259
+
260
+ function refreshBackgroundServiceOrStartDirect() {
261
+ const prevBake = process.env.OCX_BAKE_PORT;
262
+ process.env.OCX_BAKE_PORT = String(bakePort);
263
+ try {
264
+ let svc = spawnSync(process.execPath, serviceRefreshArgs(), { stdio: "inherit", windowsHide: true });
265
+ // `serviceWasInstalled` is inferred from service-state.json alone, which can be
266
+ // STALE — present while the registration is gone. Repair refuses that case by
267
+ // design, and its thrown Error is indistinguishable from any other failure at
268
+ // this layer (plain Error, inherited stdio, generic exit status). So ask for
269
+ // structured state instead of parsing the failure: install only when the
270
+ // diagnostic says the service is genuinely absent. Installing after ANY repair
271
+ // failure would resurrect the elevation prompt this change exists to avoid, and
272
+ // could re-register a service the user just uninstalled.
273
+ if (svc.status !== 0 && readServiceInstalledFromStatus(launcher) === false) {
274
+ console.log("No registered service found — installing it instead.");
275
+ svc = spawnSync(process.execPath, serviceInstallArgs(), { stdio: "inherit", windowsHide: true });
276
+ }
277
+ let needDirectStart = svc.status !== 0;
278
+ if (!needDirectStart) {
279
+ // Exit 0 can still leave stale/missing assets that never bring the proxy
280
+ // back — match the GUI/CLI fallthrough so /healthz is not left dead.
281
+ try {
282
+ const st = spawnSync(process.execPath, [launcher, "status", "--json"], {
283
+ encoding: "utf8",
284
+ timeout: 20_000,
285
+ windowsHide: true,
286
+ });
287
+ if (st.status === 0 && typeof st.stdout === "string" && st.stdout.trim()) {
288
+ const parsed = JSON.parse(st.stdout);
289
+ const proxyUp = parsed?.proxy?.running === true || parsed?.proxy?.health?.ok === true;
290
+ const viable = parsed?.startup?.serviceViable === true;
291
+ if (!proxyUp && !viable) needDirectStart = true;
292
+ } else {
293
+ // status failed or empty — fail closed to direct start (match CLI).
294
+ needDirectStart = true;
295
+ }
296
+ } catch {
297
+ needDirectStart = true;
298
+ }
299
+ }
300
+ if (needDirectStart) {
301
+ // A repair needs no elevation, but it can still fail — or exit 0 while leaving
302
+ // a non-viable manager. Fall back to a direct detached proxy start so the
303
+ // update never leaves the user without a running proxy.
304
+ console.warn(
305
+ svc.status === 0
306
+ ? "opencodex: service refresh left a non-viable manager — starting the proxy directly instead."
307
+ : "opencodex: service refresh failed — starting the proxy directly instead.",
308
+ );
309
+ console.warn(" Run 'ocx service repair' to see why the background service could not restart.");
310
+ startProxyDirectly();
311
+ }
312
+ } finally {
313
+ if (prevBake === undefined) delete process.env.OCX_BAKE_PORT;
314
+ else process.env.OCX_BAKE_PORT = prevBake;
315
+ }
316
+ }
317
+
238
318
  // Never replace package files under a live proxy — stop it first (full `ocx stop`
239
319
  // semantics: graceful drain, service stop, native Codex restore). Gate on the service
240
320
  // and the runtime-port record too: a service-managed or orphaned proxy can be live
241
321
  // while ocx.pid is stale/missing.
242
- const launcher = fileURLToPath(import.meta.url);
243
322
  if (trayBeforeUpdate.stopBeforeReplacement) {
244
323
  console.log("⏹ Handing off the Windows tray before updating...");
245
324
  try {
@@ -257,6 +336,17 @@ function runNpmSelfUpdate() {
257
336
  }
258
337
  const hasRuntimeState =
259
338
  existsSync(join(configDir(), "ocx.pid")) || existsSync(join(configDir(), "runtime-port.json"));
339
+
340
+ function recoverStoppedRuntimeAfterFailure() {
341
+ if (serviceWasInstalled) {
342
+ console.warn("opencodex: update failed after stopping the proxy — restoring the previous background service.");
343
+ refreshBackgroundServiceOrStartDirect();
344
+ } else if (hasRuntimeState) {
345
+ console.warn("opencodex: update failed after stopping the proxy — restarting the previous version directly.");
346
+ startProxyDirectly();
347
+ }
348
+ }
349
+
260
350
  if (serviceWasInstalled || hasRuntimeState) {
261
351
  console.log("⏹ Stopping the running proxy before updating...");
262
352
  const stopRes = spawnSync(process.execPath, [launcher, "stop"], { stdio: "inherit", windowsHide: true });
@@ -269,9 +359,9 @@ function runNpmSelfUpdate() {
269
359
  }
270
360
  if (historyRestoreIncomplete()) {
271
361
  console.warn(
272
- "opencodex: WARNING — Codex resume history was NOT restored (history DB locked; Codex app/IDE open?).\n" +
273
- " Routed threads stay hidden in the native Codex app until restored.\n" +
274
- " After the update: close the Codex app, then run 'ocx stop' once to restore.",
362
+ "opencodex: WARNING — Codex resume-history metadata restore is incomplete (a backup manifest remains).\n" +
363
+ " The DB may be busy or the manifest/target may need review; untracked routed history is intentionally unchanged.\n" +
364
+ " After the update: close the Codex app, run 'ocx doctor', then run 'ocx stop' once to retry.",
275
365
  );
276
366
  }
277
367
  }
@@ -317,7 +407,8 @@ function runNpmSelfUpdate() {
317
407
  // it recreates the #1849 destruction path. Report and stop; the boot probe and the
318
408
  // recovery marker cover the swap-window states.
319
409
  console.error(`opencodex: transactional update failed unexpectedly (${error?.message ?? error}). ` +
320
- "The live install was not knowingly modified; run 'ocx update' again or reinstall with npm install -g.");
410
+ `The live install was not knowingly modified; run 'ocx update' again or reinstall with ` +
411
+ `npm install -g --allow-scripts=bun ${PKG}@${tag}.`);
321
412
  res = { status: 1 };
322
413
  }
323
414
  if (res.status === 0) {
@@ -337,77 +428,15 @@ function runNpmSelfUpdate() {
337
428
  // launcher so the new files write the baked paths and the service restarts.
338
429
  if (serviceWasInstalled) {
339
430
  console.log("Refreshing the background service with the updated files...");
340
- const prevBake = process.env.OCX_BAKE_PORT;
341
- process.env.OCX_BAKE_PORT = String(bakePort);
342
- try {
343
- let svc = spawnSync(process.execPath, serviceRefreshArgs(), { stdio: "inherit", windowsHide: true });
344
- // `serviceWasInstalled` is inferred from service-state.json alone, which can be
345
- // STALE — present while the registration is gone. Repair refuses that case by
346
- // design, and its thrown Error is indistinguishable from any other failure at
347
- // this layer (plain Error, inherited stdio, generic exit status). So ask for
348
- // structured state instead of parsing the failure: install only when the
349
- // diagnostic says the service is genuinely absent. Installing after ANY repair
350
- // failure would resurrect the elevation prompt this change exists to avoid, and
351
- // could re-register a service the user just uninstalled.
352
- if (svc.status !== 0 && readServiceInstalledFromStatus(launcher) === false) {
353
- console.log("No registered service found — installing it instead.");
354
- svc = spawnSync(process.execPath, serviceInstallArgs(), { stdio: "inherit", windowsHide: true });
355
- }
356
- let needDirectStart = svc.status !== 0;
357
- if (!needDirectStart) {
358
- // Exit 0 can still leave stale/missing assets that never bring the proxy
359
- // back — match the GUI/CLI fallthrough so /healthz is not left dead.
360
- try {
361
- const st = spawnSync(process.execPath, [launcher, "status", "--json"], {
362
- encoding: "utf8",
363
- timeout: 20_000,
364
- windowsHide: true,
365
- });
366
- if (st.status === 0 && typeof st.stdout === "string" && st.stdout.trim()) {
367
- const parsed = JSON.parse(st.stdout);
368
- const proxyUp = parsed?.proxy?.running === true || parsed?.proxy?.health?.ok === true;
369
- const viable = parsed?.startup?.serviceViable === true;
370
- if (!proxyUp && !viable) needDirectStart = true;
371
- } else {
372
- // status failed or empty — fail closed to direct start (match CLI).
373
- needDirectStart = true;
374
- }
375
- } catch {
376
- needDirectStart = true;
377
- }
378
- }
379
- if (needDirectStart) {
380
- // A repair needs no elevation, but it can still fail — or exit 0 while leaving
381
- // a non-viable manager. Fall back to a direct detached proxy start so the
382
- // update never leaves the user without a running proxy.
383
- console.warn(
384
- svc.status === 0
385
- ? "opencodex: service refresh left a non-viable manager — starting the proxy directly instead."
386
- : "opencodex: service refresh failed — starting the proxy directly instead.",
387
- );
388
- console.warn(" Run 'ocx service repair' to see why the background service could not restart.");
389
- const env = { ...process.env };
390
- delete env.OCX_SERVICE;
391
- const child = spawn(process.execPath, [launcher, "start", "--port", String(bakePort)], {
392
- detached: true,
393
- stdio: "ignore",
394
- windowsHide: true,
395
- env,
396
- });
397
- child.unref();
398
- console.log(`Proxy starting on port ${bakePort}.`);
399
- }
400
- } finally {
401
- if (prevBake === undefined) delete process.env.OCX_BAKE_PORT;
402
- else process.env.OCX_BAKE_PORT = prevBake;
403
- }
431
+ refreshBackgroundServiceOrStartDirect();
404
432
  } else {
405
433
  console.log("Restart the proxy: ocx start");
406
434
  }
407
435
  process.exit(0);
408
436
  }
409
437
  if (trayBeforeUpdate.restoreOnFailure) runTrayLifecycle(launcher, "start");
410
- console.error(`\nUpdate failed (npm exit ${res.status ?? "?"}). Try manually: npm install -g ${PKG}@${tag}`);
438
+ recoverStoppedRuntimeAfterFailure();
439
+ console.error(`\nUpdate failed (npm exit ${res.status ?? "?"}). Try manually: npm install -g --allow-scripts=bun ${PKG}@${tag}`);
411
440
  process.exit(1);
412
441
  }
413
442