@bitkyc08/opencodex 2.38.0 → 2.39.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.
- package/bin/ocx.mjs +58 -6
- package/gui/dist/assets/index-D-lchsPw.js +112 -0
- package/gui/dist/assets/index-uvENYLin.css +1 -0
- package/gui/dist/index.html +2 -2
- package/gui/dist/provider-icons/baseten.svg +13 -0
- package/gui/dist/provider-icons/bizrouter.svg +41 -0
- package/gui/dist/provider-icons/cerebras.svg +26 -0
- package/gui/dist/provider-icons/deepinfra.svg +75 -0
- package/gui/dist/provider-icons/digitalocean.svg +10 -0
- package/gui/dist/provider-icons/featherless.svg +4 -0
- package/gui/dist/provider-icons/gajae-code.svg +410 -0
- package/gui/dist/provider-icons/hermes-agent.svg +207 -0
- package/gui/dist/provider-icons/hyperbolic.svg +18 -0
- package/gui/dist/provider-icons/kilo.svg +13 -0
- package/gui/dist/provider-icons/litellm.svg +1 -0
- package/gui/dist/provider-icons/minimax.svg +1 -0
- package/gui/dist/provider-icons/nanogpt.svg +74 -0
- package/gui/dist/provider-icons/nebius.svg +1 -0
- package/gui/dist/provider-icons/neuralwatt.svg +27 -0
- package/gui/dist/provider-icons/nous.svg +149 -0
- package/gui/dist/provider-icons/novita.svg +32 -0
- package/gui/dist/provider-icons/orcarouter.svg +175 -0
- package/gui/dist/provider-icons/parallel.svg +13 -0
- package/gui/dist/provider-icons/sambanova.svg +276 -0
- package/gui/dist/provider-icons/scaleway.svg +11 -0
- package/gui/dist/provider-icons/siliconflow.svg +18 -0
- package/gui/dist/provider-icons/synthetic.svg +12 -0
- package/gui/dist/provider-icons/together.svg +18 -0
- package/gui/dist/provider-icons/umans.svg +30 -0
- package/gui/dist/provider-icons/venice.svg +165 -0
- package/gui/dist/provider-icons/vultr.svg +15 -0
- package/gui/dist/provider-icons/zai.svg +218 -0
- package/gui/dist/provider-icons/zenmux.svg +1 -0
- package/package.json +1 -1
- package/src/adapters/cursor/live-models.ts +1 -0
- package/src/adapters/openai-responses.ts +72 -10
- package/src/bridge.ts +15 -15
- package/src/cli/dispatch.ts +54 -18
- package/src/cli/index.ts +420 -30
- package/src/cli/integrations.ts +24 -2
- package/src/cli/uninstall-plan.ts +86 -0
- package/src/codex/account-store.ts +121 -8
- package/src/codex/auth-api.ts +202 -33
- package/src/codex/catalog/provider-fetch.ts +76 -9
- package/src/codex/history-job.ts +10 -0
- package/src/codex/history-manifest.ts +35 -2
- package/src/codex/history-provider.ts +196 -19
- package/src/codex/history-worker.ts +3 -0
- package/src/codex/quota-401-recovery.ts +190 -0
- package/src/codex/quota-recovery-timing.ts +28 -0
- package/src/codex/quota.ts +6 -0
- package/src/codex/routing.ts +68 -16
- package/src/codex/subagent-model-fallback.ts +4 -1
- package/src/config/pending-teardown-names.d.mts +8 -0
- package/src/config/pending-teardown-names.mjs +69 -0
- package/src/config/pending-teardown.ts +286 -0
- package/src/generated/compatibility-version.json +84 -32
- package/src/integrations/journal.ts +12 -1
- package/src/integrations/writer.ts +82 -7
- package/src/lib/process-control.ts +30 -5
- package/src/lib/state-store-registrations.ts +8 -0
- package/src/oauth/index.ts +220 -13
- package/src/oauth/store.ts +220 -18
- package/src/responses/spill-store.ts +20 -0
- package/src/responses/state.ts +288 -2
- package/src/server/management/integration-routes.ts +36 -5
- package/src/server/management-api.ts +66 -12
- package/src/server/responses/encrypted-payload.ts +18 -1
- package/src/server/stop-teardown.ts +84 -0
- package/src/service.ts +155 -20
- package/src/update/index.ts +36 -4
- package/src/update/proxy-liveness-probe.d.mts +6 -0
- package/src/update/proxy-liveness-probe.mjs +84 -0
- package/src/update/stop-contract.d.mts +2 -0
- package/src/update/stop-contract.mjs +15 -0
- package/src/update/stop-decision.d.mts +10 -0
- package/src/update/stop-decision.mjs +34 -0
- package/src/vision/eligibility.ts +19 -1
- package/src/vision/index.ts +4 -18
- package/gui/dist/assets/index-C14iCj_Q.js +0 -112
- package/gui/dist/assets/index-D7PIz7_g.css +0 -1
package/bin/ocx.mjs
CHANGED
|
@@ -9,6 +9,9 @@
|
|
|
9
9
|
* src/cli/index.ts — only the published npm `bin` routes through here.)
|
|
10
10
|
*/
|
|
11
11
|
import { spawn, spawnSync } from "node:child_process";
|
|
12
|
+
import { STOP_HISTORY_INCOMPLETE_EXIT_CODE } from "../src/update/stop-contract.mjs";
|
|
13
|
+
import { probeProxyLiveness } from "../src/update/proxy-liveness-probe.mjs";
|
|
14
|
+
import { decidePostStopUpdate } from "../src/update/stop-decision.mjs";
|
|
12
15
|
import { randomBytes } from "node:crypto";
|
|
13
16
|
import { createRequire } from "node:module";
|
|
14
17
|
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
@@ -17,6 +20,7 @@ import { dirname, join, resolve } from "node:path";
|
|
|
17
20
|
import { fileURLToPath } from "node:url";
|
|
18
21
|
import { isRealBunBinary } from "../src/lib/bun-binary-validator.mjs";
|
|
19
22
|
import { npmInvocation } from "../src/update/npm-invocation.mjs";
|
|
23
|
+
import { hasPendingTeardownIn } from "../src/config/pending-teardown-names.mjs";
|
|
20
24
|
import {
|
|
21
25
|
npmCachePreflightFailureMessage,
|
|
22
26
|
runNpmCachePreflight,
|
|
@@ -202,7 +206,12 @@ function runNpmSelfUpdate() {
|
|
|
202
206
|
// Capture listen target before stop clears runtime-port.json (mirrors GUI/CLI update worker).
|
|
203
207
|
// Do not treat a live runtime port of 10100 as "missing" — track whether the read succeeded.
|
|
204
208
|
let bakePort = 10100;
|
|
209
|
+
// The hostname travels with the port: a proxy bound to ::1 or a specific interface is
|
|
210
|
+
// invisible to a probe that assumes 127.0.0.1, and "no answer" would then read as
|
|
211
|
+
// "stopped" for exactly the proxy the probe exists to find.
|
|
212
|
+
let bakeHostname = "127.0.0.1";
|
|
205
213
|
let sawRuntimePort = false;
|
|
214
|
+
let sawRuntimeHostname = false;
|
|
206
215
|
try {
|
|
207
216
|
const rt = JSON.parse(readFileSync(join(configDir(), "runtime-port.json"), "utf8"));
|
|
208
217
|
if (Number.isFinite(rt?.port) && rt.port > 0 && rt.port <= 65535) {
|
|
@@ -219,16 +228,29 @@ function runNpmSelfUpdate() {
|
|
|
219
228
|
}
|
|
220
229
|
if (runtimeLive) {
|
|
221
230
|
bakePort = Math.trunc(rt.port);
|
|
231
|
+
if (typeof rt?.hostname === "string" && rt.hostname.trim() !== "") {
|
|
232
|
+
bakeHostname = rt.hostname.trim();
|
|
233
|
+
sawRuntimeHostname = true;
|
|
234
|
+
}
|
|
222
235
|
sawRuntimePort = true;
|
|
223
236
|
}
|
|
224
237
|
}
|
|
225
238
|
} catch { /* fall through to config */ }
|
|
226
|
-
|
|
239
|
+
// Port and hostname resolve INDEPENDENTLY: a legacy runtime record carries a port and no
|
|
240
|
+
// hostname, and skipping config in that case probed 127.0.0.1 for a proxy bound to ::1.
|
|
241
|
+
if (!sawRuntimePort || bakeHostname === "127.0.0.1") {
|
|
227
242
|
try {
|
|
228
243
|
const cfg = JSON.parse(readFileSync(join(configDir(), "config.json"), "utf8"));
|
|
229
|
-
if (Number.isFinite(cfg?.port) && cfg.port > 0 && cfg.port <= 65535)
|
|
244
|
+
if (!sawRuntimePort && Number.isFinite(cfg?.port) && cfg.port > 0 && cfg.port <= 65535) {
|
|
245
|
+
bakePort = Math.trunc(cfg.port);
|
|
246
|
+
}
|
|
247
|
+
if (!sawRuntimeHostname && typeof cfg?.hostname === "string" && cfg.hostname.trim() !== "") {
|
|
248
|
+
bakeHostname = cfg.hostname.trim();
|
|
249
|
+
}
|
|
230
250
|
} catch { /* keep default */ }
|
|
231
251
|
}
|
|
252
|
+
// Wildcard and bracketed-IPv6 normalization lives in probeProxyLiveness, so both lanes
|
|
253
|
+
// get it from one place.
|
|
232
254
|
|
|
233
255
|
const launcher = fileURLToPath(import.meta.url);
|
|
234
256
|
|
|
@@ -343,17 +365,47 @@ function runNpmSelfUpdate() {
|
|
|
343
365
|
}
|
|
344
366
|
}
|
|
345
367
|
|
|
346
|
-
|
|
368
|
+
// An outstanding pending-teardown receipt is a fourth reason to run the stop. After a
|
|
369
|
+
// parent crashed mid-deferral the service, pid and runtime records can all be absent
|
|
370
|
+
// while the shared client config still points at a proxy that is gone; installing over
|
|
371
|
+
// that silently skips the recovery the receipt was written to trigger (#3008). Presence
|
|
372
|
+
// is the whole test here — the launcher cannot parse it, and `ocx stop` is what decides
|
|
373
|
+
// whether the obligation is safe to finish.
|
|
374
|
+
const hasPendingTeardown = hasPendingTeardownIn(readdirSync, configDir());
|
|
375
|
+
if (serviceWasInstalled || hasRuntimeState || hasPendingTeardown) {
|
|
347
376
|
console.log("⏹ Stopping the running proxy before updating...");
|
|
348
377
|
const stopRes = spawnSync(process.execPath, [launcher, "stop"], { stdio: "inherit", windowsHide: true });
|
|
349
378
|
const stillHasRuntimeState =
|
|
350
379
|
existsSync(join(configDir(), "ocx.pid")) || existsSync(join(configDir(), "runtime-port.json"));
|
|
351
|
-
|
|
380
|
+
// A history-only failure means teardown succeeded and a backup manifest is waiting for
|
|
381
|
+
// review: the proxy is down and replacing package files is safe. Every other nonzero
|
|
382
|
+
// status is a stop that did not finish, and a signal kill (status null) says nothing
|
|
383
|
+
// about whether it did - both abort, because replacing files under a live server
|
|
384
|
+
// leaves it running mixed old and new modules (#3008).
|
|
385
|
+
// The same decision the Bun updater makes, from the same module (#3008). Absent PID and
|
|
386
|
+
// runtime files are weak evidence, so the captured endpoint is asked; "unknown" aborts
|
|
387
|
+
// because a silent listener is exactly the state where replacing files is dangerous.
|
|
388
|
+
const decision = decidePostStopUpdate({
|
|
389
|
+
status: stopRes.status,
|
|
390
|
+
hasRuntimeState: stillHasRuntimeState,
|
|
391
|
+
// Re-checked AFTER the stop: a quarantined receipt lets the stop itself succeed
|
|
392
|
+
// (there is nothing left to stop), so a pre-stop check alone let the retry install
|
|
393
|
+
// over a teardown that never ran.
|
|
394
|
+
teardownOutstanding: hasPendingTeardownIn(readdirSync, configDir()),
|
|
395
|
+
liveness: probeProxyLiveness(bakePort, bakeHostname),
|
|
396
|
+
});
|
|
397
|
+
const historyOnlyStop = decision.reason === "history-only";
|
|
398
|
+
if (!decision.proceed) {
|
|
352
399
|
if (trayBeforeUpdate.restoreOnFailure) runTrayLifecycle(launcher, "start");
|
|
353
|
-
|
|
400
|
+
if (decision.reason === "teardown-outstanding") {
|
|
401
|
+
console.error("opencodex: a shared teardown from an earlier stop is still outstanding and needs manual review; aborting the update.");
|
|
402
|
+
console.error("opencodex: confirm no proxy is running, run 'ocx restore', then remove the pending-teardown file in the opencodex home.");
|
|
403
|
+
} else console.error(decision.reason === "proxy-unknown"
|
|
404
|
+
? `opencodex: could not confirm the proxy on ${bakeHostname}:${bakePort} is stopped; aborting the update. Run 'ocx stop' and retry.`
|
|
405
|
+
: "opencodex: could not stop the running proxy; aborting the update. Run 'ocx stop' and retry.");
|
|
354
406
|
process.exit(1);
|
|
355
407
|
}
|
|
356
|
-
if (historyRestoreIncomplete()) {
|
|
408
|
+
if (historyOnlyStop || historyRestoreIncomplete()) {
|
|
357
409
|
console.warn(
|
|
358
410
|
"opencodex: WARNING — Codex resume-history metadata restore is incomplete (a backup manifest remains).\n" +
|
|
359
411
|
" The DB may be busy or the manifest/target may need review; untracked routed history is intentionally unchanged.\n" +
|