@yansigit/opencodex 2.31.2 → 2.32.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 (118) hide show
  1. package/bin/ocx.mjs +99 -70
  2. package/gui/dist/assets/index-BG43zwVe.js +102 -0
  3. package/gui/dist/assets/index-CiSI-jrP.css +1 -0
  4. package/gui/dist/index.html +2 -2
  5. package/package.json +1 -1
  6. package/src/adapters/anthropic.ts +6 -8
  7. package/src/adapters/base.ts +2 -0
  8. package/src/adapters/command-code-project-context.ts +377 -0
  9. package/src/adapters/command-code.ts +7 -4
  10. package/src/adapters/cursor/live-models.ts +8 -0
  11. package/src/adapters/cursor/live-transport.ts +21 -0
  12. package/src/adapters/cursor/native-exec-bridge.ts +141 -0
  13. package/src/adapters/cursor/native-exec-desktop.ts +16 -0
  14. package/src/adapters/cursor/tool-definitions.ts +1 -1
  15. package/src/adapters/google-http.ts +12 -2
  16. package/src/adapters/google-wire-compiler.ts +83 -2
  17. package/src/adapters/google.ts +62 -21
  18. package/src/adapters/kiro.ts +0 -3
  19. package/src/adapters/openai-responses.ts +3 -0
  20. package/src/adapters/tool-catalog-nudge.ts +1 -1
  21. package/src/adapters/xai-web-search.ts +7 -2
  22. package/src/bridge.ts +21 -15
  23. package/src/cli/dispatch.ts +50 -2
  24. package/src/cli/doctor.ts +24 -11
  25. package/src/cli/help.ts +4 -3
  26. package/src/cli/index.ts +11 -4
  27. package/src/cli/models.ts +13 -3
  28. package/src/cli/observe.ts +20 -5
  29. package/src/cli/provider.ts +2 -1
  30. package/src/cli/registry.ts +7 -5
  31. package/src/cli/status.ts +2 -1
  32. package/src/cli/system-restart-client.ts +1 -1
  33. package/src/cli/usage-report.ts +134 -0
  34. package/src/codex/app-server-processes.ts +3 -1
  35. package/src/codex/catalog/aggregation.ts +13 -1
  36. package/src/codex/catalog/effort.ts +24 -9
  37. package/src/codex/catalog/model-metadata.ts +566 -0
  38. package/src/codex/catalog/parsing.ts +33 -0
  39. package/src/codex/catalog/provider-fetch.ts +123 -32
  40. package/src/codex/catalog/sync.ts +5 -4
  41. package/src/codex/desktop-app-restart.ts +342 -0
  42. package/src/codex/history-job.ts +32 -3
  43. package/src/codex/history-manifest.ts +112 -0
  44. package/src/codex/history-migration-guardian.ts +5 -5
  45. package/src/codex/history-provider.ts +825 -247
  46. package/src/codex/history-worker.ts +8 -5
  47. package/src/codex/inject.ts +49 -21
  48. package/src/codex/injected-marker.ts +1 -1
  49. package/src/codex/internal/history-writer.ts +4 -3
  50. package/src/codex/native-profile-startup.ts +157 -27
  51. package/src/codex/native-residue.ts +26 -33
  52. package/src/combos/failover.ts +27 -0
  53. package/src/compatibility/index.ts +26 -0
  54. package/src/compatibility/manifest.ts +253 -0
  55. package/src/compatibility/openai-responses.ts +81 -0
  56. package/src/config/atomic-write.ts +219 -0
  57. package/src/config/paths.ts +40 -0
  58. package/src/config/process-state.ts +308 -0
  59. package/src/config/provider-validation.ts +177 -0
  60. package/src/config.ts +77 -812
  61. package/src/generated/compatibility-version.json +162 -94
  62. package/src/images/plan.ts +5 -4
  63. package/src/integrations/ownership-policy.ts +141 -0
  64. package/src/integrations/ownership.ts +10 -0
  65. package/src/integrations/state.ts +44 -5
  66. package/src/integrations/writer.ts +6 -0
  67. package/src/lab/subject/behavior-fingerprint.ts +1 -1
  68. package/src/lib/bounded-body.ts +14 -2
  69. package/src/lib/process-control.ts +2 -1
  70. package/src/lib/state-store-registrations.ts +2 -0
  71. package/src/lib/tool-argument-integers.ts +56 -5
  72. package/src/oauth/health.ts +1 -1
  73. package/src/oauth/index.ts +3 -0
  74. package/src/providers/registry.ts +1 -1
  75. package/src/reasoning-effort.ts +19 -2
  76. package/src/responses/apply-patch-envelope.ts +63 -0
  77. package/src/responses/custom-tool-compat.ts +132 -38
  78. package/src/responses/parser.ts +3 -2
  79. package/src/responses/reasoning-replay-cache.ts +81 -3
  80. package/src/routing/compatibility/behavior.ts +3 -0
  81. package/src/server/auth-cors.ts +9 -7
  82. package/src/server/index.ts +102 -21
  83. package/src/server/local-management-read-client.ts +1 -1
  84. package/src/server/local-provider-reload-client.ts +1 -1
  85. package/src/server/management/agent-settings-routes.ts +1 -1
  86. package/src/server/management/config-routes.ts +4 -1
  87. package/src/server/management/context.ts +1 -1
  88. package/src/server/management/logs-usage-routes.ts +27 -6
  89. package/src/server/management/model-routes.ts +8 -4
  90. package/src/server/management/native-integration-routes.ts +2 -1
  91. package/src/server/management/provider-capability-config.ts +1 -1
  92. package/src/server/management/system-restart.ts +1 -1
  93. package/src/server/port-reclaim.ts +1 -1
  94. package/src/server/proxy-liveness.ts +2 -1
  95. package/src/server/request-log-conversation.ts +30 -0
  96. package/src/server/responses/codex-auth-error.ts +55 -0
  97. package/src/server/responses/combo-stream-preflight.ts +171 -0
  98. package/src/server/responses/compact.ts +6 -21
  99. package/src/server/responses/core.ts +242 -101
  100. package/src/server/responses/fetch-helpers.ts +2 -97
  101. package/src/server/responses-custom-tool-repair.ts +41 -5
  102. package/src/server/responses-undeclared-tool-guard.ts +156 -15
  103. package/src/service.ts +8 -4
  104. package/src/types/provider.ts +7 -0
  105. package/src/types/request.ts +12 -1
  106. package/src/types/tools.ts +87 -11
  107. package/src/types.ts +1 -1
  108. package/src/update/index.ts +5 -4
  109. package/src/update/job.ts +3 -1
  110. package/src/update/transactional-install.mjs +8 -1
  111. package/src/usage/log.ts +16 -8
  112. package/src/usage/summary.ts +201 -8
  113. package/src/vision/describe.ts +18 -13
  114. package/src/web-search/executor.ts +10 -3
  115. package/src/web-search/gemini-executor.ts +35 -13
  116. package/src/web-search/index.ts +85 -1
  117. package/gui/dist/assets/index-BAMgarF9.js +0 -102
  118. package/gui/dist/assets/index-CGoDO3uO.css +0 -1
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