@bitkyc08/opencodex 2.7.43-preview.20260728 → 2.8.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 (173) hide show
  1. package/README.md +8 -1
  2. package/bin/ocx.mjs +47 -22
  3. package/gui/dist/assets/index-BDjpkcRN.js +67 -0
  4. package/gui/dist/assets/index-BHsKRFh9.css +1 -0
  5. package/gui/dist/index.html +2 -2
  6. package/package.json +1 -1
  7. package/src/AGENTS.md +28 -0
  8. package/src/adapters/anthropic.ts +15 -6
  9. package/src/adapters/cursor/discovery.ts +4 -1
  10. package/src/adapters/cursor/effort-map.ts +3 -0
  11. package/src/adapters/cursor/native-exec-shell.ts +18 -6
  12. package/src/adapters/cursor/protobuf-events.ts +24 -2
  13. package/src/adapters/cursor/protobuf-request.ts +1 -2
  14. package/src/adapters/cursor/tool-definitions.ts +68 -29
  15. package/src/adapters/google-wire-compiler.ts +4 -0
  16. package/src/adapters/google.ts +128 -2
  17. package/src/adapters/identity.ts +12 -2
  18. package/src/adapters/kiro.ts +64 -7
  19. package/src/adapters/mimo-free.ts +2 -0
  20. package/src/adapters/openai-responses.ts +246 -59
  21. package/src/claude/agents-inject.ts +5 -0
  22. package/src/claude/alias.ts +94 -14
  23. package/src/claude/inbound.ts +26 -9
  24. package/src/claude/outbound.ts +6 -3
  25. package/src/cli/account-auth.ts +1 -1
  26. package/src/cli/agent-driven.ts +37 -0
  27. package/src/cli/catalog-prewarm.ts +24 -0
  28. package/src/cli/claude.ts +35 -10
  29. package/src/cli/doctor.ts +71 -19
  30. package/src/cli/help.ts +42 -6
  31. package/src/cli/index.ts +93 -19
  32. package/src/cli/interactive-confirm.ts +133 -0
  33. package/src/cli/opencode.ts +701 -0
  34. package/src/cli/provider-runtime.ts +3 -0
  35. package/src/cli/provider.ts +31 -10
  36. package/src/cli/star-prompt.ts +79 -18
  37. package/src/cli/status.ts +47 -13
  38. package/src/cli/v2.ts +10 -1
  39. package/src/codex/account-id.ts +34 -0
  40. package/src/codex/account-lifecycle.ts +4 -1
  41. package/src/codex/account-namespace-match.ts +63 -0
  42. package/src/codex/account-namespaces.ts +149 -0
  43. package/src/codex/account-pause.ts +20 -0
  44. package/src/codex/account-store.ts +2 -0
  45. package/src/codex/account-usability.ts +6 -1
  46. package/src/codex/app-server-processes.ts +511 -0
  47. package/src/codex/auth-api.ts +293 -34
  48. package/src/codex/auth-collision.ts +2 -1
  49. package/src/codex/auth-context.ts +60 -17
  50. package/src/codex/catalog/bundled.ts +9 -2
  51. package/src/codex/catalog/parsing.ts +42 -2
  52. package/src/codex/catalog/provider-fetch.ts +264 -70
  53. package/src/codex/catalog/sync.ts +45 -8
  54. package/src/codex/catalog.ts +2 -2
  55. package/src/codex/features.ts +524 -5
  56. package/src/codex/history-provider.ts +145 -1
  57. package/src/codex/inject.ts +114 -14
  58. package/src/codex/main-account.ts +2 -8
  59. package/src/codex/pool-rotation.ts +186 -0
  60. package/src/codex/quota.ts +92 -2
  61. package/src/codex/routing.ts +695 -106
  62. package/src/codex/runtime.ts +10 -1
  63. package/src/codex/shim.ts +4 -1
  64. package/src/codex/subagent-defaults.ts +550 -0
  65. package/src/codex/subagent-model-fallback.ts +2 -0
  66. package/src/codex/sync.ts +3 -0
  67. package/src/config.ts +574 -25
  68. package/src/generated/jawcode-model-metadata.ts +12 -12
  69. package/src/github/star-state.ts +191 -0
  70. package/src/images/artifacts.ts +516 -0
  71. package/src/images/fulfill-video.ts +163 -0
  72. package/src/images/fulfill.ts +111 -0
  73. package/src/images/index.ts +4 -0
  74. package/src/images/loop.ts +789 -0
  75. package/src/images/plan.ts +133 -0
  76. package/src/images/synthetic-tool.ts +133 -0
  77. package/src/images/types.ts +41 -0
  78. package/src/images/xai-client.ts +141 -0
  79. package/src/images/xai-video-client.ts +163 -0
  80. package/src/lib/admin-secrets.ts +25 -0
  81. package/src/lib/bun-binary-validator.d.mts +3 -0
  82. package/src/lib/bun-binary-validator.mjs +18 -0
  83. package/src/lib/bun-runtime.ts +6 -20
  84. package/src/lib/config-ownership.ts +327 -0
  85. package/src/lib/crash-guard.ts +2 -0
  86. package/src/lib/destination-policy.ts +132 -7
  87. package/src/lib/pinned-http.ts +151 -0
  88. package/src/lib/process-control.ts +2 -2
  89. package/src/lib/provider-outbound.ts +167 -0
  90. package/src/lib/provider-url.ts +14 -0
  91. package/src/lib/proxy-env.ts +18 -0
  92. package/src/lib/shadow-call.ts +30 -0
  93. package/src/lib/test-home-guard.ts +90 -0
  94. package/src/lib/win-exec.ts +12 -2
  95. package/src/lib/windows-elevation.ts +81 -3
  96. package/src/lib/windows-secret-acl.ts +189 -12
  97. package/src/lib/winsw.ts +2 -0
  98. package/src/oauth/anthropic-routing.ts +570 -0
  99. package/src/oauth/health.ts +6 -0
  100. package/src/oauth/index.ts +310 -75
  101. package/src/oauth/key-providers.ts +38 -8
  102. package/src/oauth/kimi.ts +2 -0
  103. package/src/oauth/kiro-credentials.ts +373 -12
  104. package/src/oauth/kiro.ts +424 -43
  105. package/src/oauth/login-cli.ts +33 -6
  106. package/src/oauth/store.ts +56 -4
  107. package/src/oauth/types.ts +11 -0
  108. package/src/providers/alibaba-region-migration.ts +16 -3
  109. package/src/providers/antigravity-models.ts +3 -0
  110. package/src/providers/api-keys.ts +13 -6
  111. package/src/providers/derive.ts +8 -2
  112. package/src/providers/key-failover.ts +24 -4
  113. package/src/providers/model-discovery.ts +356 -0
  114. package/src/providers/quota.ts +233 -29
  115. package/src/providers/registry.ts +125 -3
  116. package/src/responses/parser.ts +11 -0
  117. package/src/responses/state.ts +22 -8
  118. package/src/responses/tool-groups.ts +19 -0
  119. package/src/router.ts +19 -7
  120. package/src/server/auth-cors.ts +114 -24
  121. package/src/server/claude-messages.ts +8 -1
  122. package/src/server/gui-static.ts +30 -6
  123. package/src/server/images.ts +303 -9
  124. package/src/server/index.ts +77 -9
  125. package/src/server/lifecycle.ts +25 -1
  126. package/src/server/live.ts +75 -25
  127. package/src/server/management/agent-settings-routes.ts +106 -8
  128. package/src/server/management/combo-routes.ts +7 -0
  129. package/src/server/management/config-routes.ts +22 -7
  130. package/src/server/management/context.ts +11 -1
  131. package/src/server/management/logs-usage-routes.ts +167 -3
  132. package/src/server/management/model-routes.ts +46 -13
  133. package/src/server/management/oauth-account-routes.ts +163 -17
  134. package/src/server/management/provider-routes.ts +73 -10
  135. package/src/server/management/shared.ts +2 -2
  136. package/src/server/management/sidebar-routes.ts +39 -0
  137. package/src/server/management/system-restart.ts +172 -0
  138. package/src/server/management/system-routes.ts +33 -10
  139. package/src/server/management-api.ts +5 -3
  140. package/src/server/management-auth.ts +216 -0
  141. package/src/server/proxy-liveness.ts +14 -3
  142. package/src/server/responses/compact.ts +21 -13
  143. package/src/server/responses/core.ts +614 -172
  144. package/src/server/responses/upstream-error.ts +48 -0
  145. package/src/server/responses-image-gen-repair.ts +118 -0
  146. package/src/server/responses-item-id-repair.ts +10 -85
  147. package/src/server/sse-payload-rewrite.ts +116 -0
  148. package/src/server/startup-action-control.ts +30 -14
  149. package/src/server/system-env.ts +28 -10
  150. package/src/service.ts +284 -19
  151. package/src/storage/cleanup-job.ts +57 -0
  152. package/src/storage/cleanup.ts +1504 -28
  153. package/src/storage/policy-job.ts +387 -0
  154. package/src/storage/policy-scheduler.ts +40 -0
  155. package/src/storage/policy-worker.ts +53 -0
  156. package/src/storage/policy.ts +522 -0
  157. package/src/storage/restore-job.ts +253 -0
  158. package/src/storage/restore-worker.ts +52 -0
  159. package/src/storage/storage-mutation-coordinator.ts +109 -0
  160. package/src/storage/worker-lifecycle.ts +81 -0
  161. package/src/tray/windows.ts +34 -4
  162. package/src/types.ts +107 -1
  163. package/src/update/badge.ts +72 -0
  164. package/src/update/index.ts +36 -18
  165. package/src/update/job.ts +111 -16
  166. package/src/update/npm-invocation.d.mts +23 -0
  167. package/src/update/npm-invocation.mjs +94 -0
  168. package/src/usage/debug.ts +2 -0
  169. package/src/usage/expected-prices.ts +6 -5
  170. package/src/usage/log.ts +12 -0
  171. package/src/web-search/loop.ts +57 -16
  172. package/gui/dist/assets/index-CjKFJHSC.js +0 -65
  173. package/gui/dist/assets/index-DfVGuN88.css +0 -1
package/README.md CHANGED
@@ -240,11 +240,15 @@ next Codex session. opencodex keeps these behaviors:
240
240
 
241
241
  - **Existing sessions keep affinity.** A thread id is bound to the selected account and reused on
242
242
  later turns, so a long request or a mobile/SSH-attached session keeps using the same account.
243
+ Pausing an account clears its affinity map: in-flight requests keep captured credentials, but
244
+ subsequent turns are re-routed and cannot reuse the paused account.
243
245
  - **New sessions can auto-route.** When auto-switch is enabled, opencodex compares the hottest known
244
246
  quota window across 5h, weekly, and 30d usage, then picks a lower-usage eligible account for new
245
247
  sessions once the active account crosses the threshold.
246
248
  - **Quota lookup is built in.** The dashboard can refresh all account quotas in one click, and the
247
- request log labels pool traffic with non-PII account ordinals.
249
+ request log labels pool traffic with non-PII account ordinals. **Pause exhausted** refreshes
250
+ eligible accounts that have credentials and pauses only those whose relevant quota window is
251
+ freshly confirmed at 100%; accounts without credentials and unknown or failed refreshes stay unchanged.
248
252
  - **Failures fail closed.** Token failures mark reauthentication instead of falling back to another
249
253
  credential silently; 429 quota responses put the account in cooldown and can fail over future work
250
254
  to another eligible pool account.
@@ -505,6 +509,9 @@ The public docs — install, providers, routing, sidecars, Codex integration, Co
505
509
  Maintainer source-of-truth notes live under [`structure/`](./structure). Historical investigations remain under [`docs/`](./docs).
506
510
  Contributor setup lives in [`CONTRIBUTING.md`](./CONTRIBUTING.md), and security reporting guidance
507
511
  lives in [`SECURITY.md`](./SECURITY.md).
512
+ Report undisclosed vulnerabilities privately through
513
+ [GitHub private vulnerability reporting](https://github.com/lidge-jun/opencodex/security/advisories/new),
514
+ not a public issue.
508
515
 
509
516
  ## Development
510
517
 
package/bin/ocx.mjs CHANGED
@@ -10,10 +10,12 @@
10
10
  */
11
11
  import { spawn, spawnSync } from "node:child_process";
12
12
  import { createRequire } from "node:module";
13
- import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
13
+ import { existsSync, readFileSync, readdirSync } from "node:fs";
14
14
  import { homedir } from "node:os";
15
15
  import { dirname, join, resolve } from "node:path";
16
16
  import { fileURLToPath } from "node:url";
17
+ import { isRealBunBinary } from "../src/lib/bun-binary-validator.mjs";
18
+ import { npmInvocation } from "../src/update/npm-invocation.mjs";
17
19
  import { handoffWindowsTrayForUpdate, planWindowsTrayUpdate } from "../src/update/tray-update-plan.mjs";
18
20
 
19
21
  const PKG = "@bitkyc08/opencodex";
@@ -29,10 +31,6 @@ function isBunGlobalInstall() {
29
31
  return /[\\/]\.bun[\\/]/.test(here);
30
32
  }
31
33
 
32
- function npmBin() {
33
- return process.platform === "win32" ? "npm.cmd" : "npm";
34
- }
35
-
36
34
  function currentPackageVersion() {
37
35
  try {
38
36
  return JSON.parse(readFileSync(join(here, "..", "package.json"), "utf8")).version ?? "?";
@@ -115,15 +113,17 @@ function runTrayLifecycle(launcher, action) {
115
113
  function runNpmSelfUpdate() {
116
114
  const current = currentPackageVersion();
117
115
  const tag = updateTag(current);
118
- const npm = npmBin();
119
- // Node ≥18.20/20.12 refuses to spawn .cmd/.bat without a shell (CVE-2024-27980
120
- // hardening) spawning "npm.cmd" shell-less throws EINVAL on Windows.
121
- const winShell = process.platform === "win32";
122
- const latestResult = spawnSync(npm, ["view", `${PKG}@${tag}`, "version"], {
116
+ const latestInvocation = npmInvocation(["view", `${PKG}@${tag}`, "version"]);
117
+ const installInvocation = npmInvocation(["install", "-g", `${PKG}@${tag}`]);
118
+ if (!latestInvocation || !installInvocation) {
119
+ console.error("opencodex: could not resolve npm from a trusted absolute PATH entry; aborting before stopping the proxy.");
120
+ process.exit(1);
121
+ }
122
+ const latestResult = spawnSync(latestInvocation.file, latestInvocation.args, {
123
123
  encoding: "utf8",
124
124
  timeout: 12000,
125
125
  windowsHide: true,
126
- shell: winShell,
126
+ ...latestInvocation.options,
127
127
  });
128
128
  const latest = latestResult.status === 0 ? latestResult.stdout.trim() : "";
129
129
 
@@ -221,12 +221,12 @@ function runNpmSelfUpdate() {
221
221
  }
222
222
  }
223
223
 
224
- console.log(`Updating${latest ? ` to v${latest}` : ""}...\n$ ${npm} install -g ${PKG}@${tag}`);
225
- const res = spawnSync(npm, ["install", "-g", `${PKG}@${tag}`], {
224
+ console.log(`Updating${latest ? ` to v${latest}` : ""}...\n$ npm install -g ${PKG}@${tag}`);
225
+ const res = spawnSync(installInvocation.file, installInvocation.args, {
226
226
  stdio: "inherit",
227
227
  timeout: 180000,
228
228
  windowsHide: true,
229
- shell: winShell,
229
+ ...installInvocation.options,
230
230
  });
231
231
  if (res.status === 0) {
232
232
  console.log(`\nUpdated${latest ? ` to v${latest}` : ""}.`);
@@ -278,7 +278,7 @@ function runNpmSelfUpdate() {
278
278
  process.exit(0);
279
279
  }
280
280
  if (trayBeforeUpdate.restoreOnFailure) runTrayLifecycle(launcher, "start");
281
- console.error(`\nUpdate failed (${npm} exit ${res.status ?? "?"}). Try manually: ${npm} install -g ${PKG}@${tag}`);
281
+ console.error(`\nUpdate failed (npm exit ${res.status ?? "?"}). Try manually: npm install -g ${PKG}@${tag}`);
282
282
  process.exit(1);
283
283
  }
284
284
 
@@ -288,18 +288,14 @@ function bunBinDir() {
288
288
  return dirname(require.resolve("bun/package.json"));
289
289
  }
290
290
 
291
- // The `bun` package ships a tiny ASCII placeholder at bin/bun.exe until its
292
- // postinstall downloads the real ~60MB binary. --ignore-scripts / pnpm leave
293
- // the ~450-byte stub in place, which is NOT executable (ENOEXEC). A size gate
294
- // cleanly distinguishes the stub from a real binary on every platform.
295
- const REAL_BUN_MIN_BYTES = 1_000_000;
291
+ const BUN_OVERRIDE_ENV = "OPENCODEX_BUN_PATH";
296
292
 
297
293
  function findBunBinary(bunDir) {
298
294
  // The npm `bun` package ships the binary as bin/bun.exe on every platform;
299
295
  // probe bin/bun too for forward compatibility.
300
296
  for (const name of ["bun.exe", "bun"]) {
301
297
  const p = join(bunDir, "bin", name);
302
- if (existsSync(p) && statSync(p).size >= REAL_BUN_MIN_BYTES) return p;
298
+ if (isRealBunBinary(p)) return p;
303
299
  }
304
300
  return null;
305
301
  }
@@ -318,6 +314,17 @@ function fail(msg) {
318
314
  }
319
315
 
320
316
  function resolveBun() {
317
+ // Keep direct npm-launcher starts aligned with durable service/shim installs:
318
+ // a valid explicit runtime must win even when the bundled dependency exists.
319
+ const override = process.env[BUN_OVERRIDE_ENV]?.trim();
320
+ if (override) {
321
+ const overridePath = resolve(override);
322
+ if (isRealBunBinary(overridePath)) return overridePath;
323
+ console.error(
324
+ `opencodex: ${BUN_OVERRIDE_ENV} is missing, unreadable, or not a complete Bun binary; falling back to the bundled runtime.`,
325
+ );
326
+ }
327
+
321
328
  let bunDir;
322
329
  try {
323
330
  bunDir = bunBinDir();
@@ -362,7 +369,25 @@ const bun = resolveBun();
362
369
  // signal delivered only to this launcher (Codex app, IDE terminal, service wrapper,
363
370
  // or `kill -INT <launcherPid>`) killed the launcher and ORPHANED the Bun proxy —
364
371
  // port left bound, pid/runtime-port files left behind, Codex config not restored.
365
- const child = spawn(bun, [cliPath, ...process.argv.slice(2)], { stdio: "inherit" });
372
+ //
373
+ // Provenance seam for issue #701: THIS launcher runs under Node, which does not
374
+ // auto-load a project `.env`/`.env.local`; the Bun child does, before any opencodex
375
+ // code evaluates. So this is the last point that can still tell a real shell export
376
+ // from a working-directory dotenv value, and we record which Anthropic credential
377
+ // slots already existed. `src/cli/claude.ts` then treats anything present in the Bun
378
+ // child but missing from this list as ambient project pollution rather than user auth,
379
+ // which stopped a project dotenv from silently moving a claude.ai subscriber onto API
380
+ // billing. An EMPTY value is meaningful (the launcher ran and saw no slots) and is
381
+ // distinct from the variable being absent (no launcher at all — change nothing), so
382
+ // this must stay a plain assignment and never be collapsed to a falsy check.
383
+ // Disabling Bun's dotenv wholesale with --no-env-file is NOT an option: config
384
+ // interpolation and provider settings legitimately read the project environment.
385
+ const preBunAnthropicSlots = ["ANTHROPIC_API_KEY", "ANTHROPIC_AUTH_TOKEN"]
386
+ .filter(name => typeof process.env[name] === "string" && process.env[name] !== "");
387
+ const child = spawn(bun, [cliPath, ...process.argv.slice(2)], {
388
+ stdio: "inherit",
389
+ env: { ...process.env, OCX_PRE_BUN_ANTHROPIC_ENV: preBunAnthropicSlots.join(",") },
390
+ });
366
391
 
367
392
  // Windows has no real POSIX signals (no SIGHUP); forwarding is best-effort there.
368
393
  const FORWARDED = process.platform === "win32" ? ["SIGINT", "SIGTERM"] : ["SIGINT", "SIGTERM", "SIGHUP"];