@bitkyc08/opencodex 2.52.0 → 2.53.0-preview.20260913
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/gui/dist/assets/index-BBOZWGB6.css +1 -0
- package/gui/dist/assets/index-D7ynYo2K.js +128 -0
- package/gui/dist/index.html +2 -2
- package/native/remote-workspace-helper/Cargo.lock +130 -0
- package/native/remote-workspace-helper/Cargo.toml +24 -0
- package/native/remote-workspace-helper/src/main.rs +49 -0
- package/native/remote-workspace-helper/src/protocol.rs +246 -0
- package/native/remote-workspace-helper/src/sandbox/macos.rs +19 -0
- package/native/remote-workspace-helper/src/sandbox/mod.rs +77 -0
- package/native/remote-workspace-helper/src/sandbox/windows.rs +15 -0
- package/package.json +6 -1
- package/src/adapters/anthropic-image-normalize.ts +30 -2
- package/src/adapters/anthropic.ts +1 -1
- package/src/adapters/base.ts +8 -2
- package/src/adapters/cursor/cursor-errors.ts +12 -0
- package/src/adapters/cursor/thread-continuity.ts +93 -0
- package/src/adapters/cursor.ts +104 -73
- package/src/adapters/devin/cloud-direct/chat.ts +312 -23
- package/src/adapters/devin/cloud-direct/metadata.ts +31 -2
- package/src/adapters/devin/live-models.ts +70 -3
- package/src/adapters/devin.ts +281 -21
- package/src/adapters/google-wire-compiler.ts +14 -6
- package/src/adapters/google.ts +22 -8
- package/src/adapters/kiro/adapter.ts +316 -0
- package/src/adapters/kiro/conversation.ts +136 -0
- package/src/adapters/kiro/payload.ts +432 -0
- package/src/adapters/kiro/reasoning.ts +56 -0
- package/src/adapters/kiro/stream.ts +1153 -0
- package/src/adapters/kiro/usage.ts +223 -0
- package/src/adapters/kiro/wire.ts +76 -0
- package/src/adapters/kiro.ts +8 -2319
- package/src/adapters/mimo-free.ts +1 -1
- package/src/adapters/openai-chat-images.ts +101 -0
- package/src/adapters/openai-chat.ts +201 -181
- package/src/adapters/openai-responses.ts +92 -224
- package/src/adapters/registry.ts +0 -7
- package/src/adapters/run-turn-queue.ts +13 -6
- package/src/bridge.ts +14 -15
- package/src/chat/inbound.ts +29 -4
- package/src/chat/outbound.ts +145 -107
- package/src/claude/desktop-profile.ts +4 -6
- package/src/cli/account-api.ts +14 -0
- package/src/cli/account-extended.ts +1 -1
- package/src/cli/account-history.ts +60 -0
- package/src/cli/account-main.ts +80 -0
- package/src/cli/account.ts +11 -3
- package/src/cli/capabilities.ts +113 -0
- package/src/cli/catalog.ts +109 -0
- package/src/cli/dispatch.ts +9 -0
- package/src/cli/help.ts +2 -0
- package/src/cli/index.ts +2 -2
- package/src/cli/observe.ts +28 -1
- package/src/cli/opencode.ts +42 -8
- package/src/cli/provider-runtime.ts +11 -1
- package/src/cli/provider.ts +22 -2
- package/src/cli/registry.ts +21 -0
- package/src/cli/remote-workspace.ts +154 -0
- package/src/cli/status.ts +39 -7
- package/src/cli/usage-report.ts +14 -2
- package/src/client/hub-client.ts +34 -0
- package/src/client/hub-state.ts +9 -1
- package/src/codex/account-store.ts +78 -0
- package/src/codex/auth-api.ts +81 -54
- package/src/codex/auth-context.ts +45 -16
- package/src/codex/catalog/effort.ts +1 -1
- package/src/codex/catalog/metadata.ts +3 -6
- package/src/codex/catalog/native-models.ts +4 -4
- package/src/codex/catalog/parsing.ts +2 -20
- package/src/codex/catalog/provider-fetch.ts +10 -1
- package/src/codex/catalog/remote.ts +233 -0
- package/src/codex/catalog/sync.ts +403 -35
- package/src/codex/convergence.ts +1 -1
- package/src/codex/history-manifest.ts +36 -0
- package/src/codex/history-provider.ts +32 -5
- package/src/codex/inject.ts +9 -0
- package/src/codex/main-account.ts +113 -0
- package/src/codex/main-device-reauth-api.ts +89 -0
- package/src/codex/main-device-reauth.ts +217 -0
- package/src/codex/native-residue.ts +9 -2
- package/src/codex/quota-auto-refresh.ts +3 -2
- package/src/codex/quota-capacity.ts +98 -0
- package/src/codex/quota-history.ts +160 -0
- package/src/codex/quota-types.ts +8 -0
- package/src/codex/quota.ts +118 -91
- package/src/codex/refresh.ts +2 -1
- package/src/codex/routing.ts +90 -17
- package/src/codex/sync.ts +33 -4
- package/src/combos/request.ts +19 -1
- package/src/config/multi-agent-surface.ts +61 -0
- package/src/config/provider-validation.ts +176 -0
- package/src/config.ts +213 -11
- package/src/generated/compatibility-version.json +436 -168
- package/src/images/loop.ts +119 -36
- package/src/lib/admission.ts +12 -6
- package/src/lib/redact.ts +7 -0
- package/src/lib/translator-budget.ts +4 -3
- package/src/lib/windows-atomic-replace.ts +1 -0
- package/src/lib/windows-elevation.ts +1 -1
- package/src/oauth/chatgpt-device.ts +62 -5
- package/src/oauth/devin/cli-import.ts +130 -0
- package/src/oauth/devin.ts +63 -8
- package/src/oauth/index.ts +29 -14
- package/src/oauth/kiro.ts +18 -6
- package/src/oauth/login-cli.ts +9 -1
- package/src/oauth/meta-muse-device.ts +464 -0
- package/src/oauth/meta-muse.ts +123 -32
- package/src/oauth/pool-kernel.ts +9 -0
- package/src/oauth/pool-settings-capability.ts +2 -2
- package/src/oauth/store.ts +57 -0
- package/src/oauth/types.ts +31 -0
- package/src/providers/derive.ts +13 -3
- package/src/providers/devin-cli-authmode-migration.ts +57 -35
- package/src/providers/devin-provider-merge-migration.ts +240 -0
- package/src/providers/muse-key-quota.ts +117 -0
- package/src/providers/muse-subscription-usage.ts +14 -2
- package/src/providers/openai-sidecar.ts +25 -3
- package/src/providers/opencode-zen-rate-limit.ts +58 -0
- package/src/providers/provider-id-rewrite.ts +20 -5
- package/src/providers/quota-types.ts +12 -0
- package/src/providers/quota.ts +143 -102
- package/src/providers/reasoning-metadata.ts +543 -0
- package/src/providers/registry.ts +80 -49
- package/src/reasoning-effort.ts +26 -2
- package/src/remote/hub-usage.ts +32 -0
- package/src/remote-control/index.ts +192 -41
- package/src/remote-control/workspace-activation.ts +9 -0
- package/src/remote-control/workspace-agent-connection.ts +366 -0
- package/src/remote-control/workspace-claude-runtime.ts +243 -0
- package/src/remote-control/workspace-codex-runtime.ts +531 -0
- package/src/remote-control/workspace-codex-sandbox.ts +115 -0
- package/src/remote-control/workspace-command-runner.ts +748 -0
- package/src/remote-control/workspace-coordinator.ts +231 -0
- package/src/remote-control/workspace-device.ts +585 -0
- package/src/remote-control/workspace-executable.ts +43 -0
- package/src/remote-control/workspace-executor.ts +397 -0
- package/src/remote-control/workspace-hub.ts +519 -0
- package/src/remote-control/workspace-pi-runtime.ts +382 -0
- package/src/remote-control/workspace-process.ts +129 -0
- package/src/remote-control/workspace-rpc.ts +304 -0
- package/src/remote-control/workspace-runtime.ts +60 -0
- package/src/remote-control/workspace-secret-store.ts +39 -0
- package/src/remote-control/workspace-sessions.ts +799 -0
- package/src/remote-control/workspace-tool-bridge.ts +192 -0
- package/src/responses/code-mode-helper-compat.ts +22 -3
- package/src/responses/hosted-tool-policy.ts +0 -1
- package/src/responses/muse-tool-name-alias.ts +379 -0
- package/src/responses/plaintext-v2-agent-messages.ts +902 -0
- package/src/router.ts +7 -0
- package/src/routing/compatibility/behavior.ts +0 -1
- package/src/server/audio-client.ts +64 -0
- package/src/server/audio-dictation.ts +91 -0
- package/src/server/audio-live.ts +185 -0
- package/src/server/audio-transcriptions.ts +183 -0
- package/src/server/audio-upstream.ts +153 -0
- package/src/server/auth-cors.ts +61 -2
- package/src/server/chat-completions.ts +1 -1
- package/src/server/chat-native-sse.ts +92 -48
- package/src/server/chat-native.ts +37 -15
- package/src/server/hub-usage.ts +57 -0
- package/src/server/images.ts +4 -0
- package/src/server/index.ts +722 -57
- package/src/server/lifecycle.ts +5 -6
- package/src/server/live-call-bindings.ts +60 -0
- package/src/server/live.ts +12 -1
- package/src/server/management/agent-settings-routes.ts +25 -4
- package/src/server/management/api-access.ts +37 -0
- package/src/server/management/api-key-usage.ts +7 -2
- package/src/server/management/config-routes.ts +1 -18
- package/src/server/management/context.ts +15 -0
- package/src/server/management/logs-usage-routes.ts +2 -0
- package/src/server/management/oauth-account-routes.ts +39 -12
- package/src/server/management/provider-routes.ts +125 -2
- package/src/server/management/remote-workspace-routes.ts +140 -0
- package/src/server/management/route-registry.ts +15 -0
- package/src/server/management/usage-aggregate-cache.ts +14 -15
- package/src/server/management/usage-summary-cache.ts +2 -0
- package/src/server/management-api.ts +23 -0
- package/src/server/ports.ts +17 -0
- package/src/server/relay-eager.ts +4 -1
- package/src/server/relay.ts +70 -10
- package/src/server/request-decompress.ts +6 -3
- package/src/server/responses/agent-task-recovery.ts +25 -32
- package/src/server/responses/codex-auth-error.ts +11 -0
- package/src/server/responses/codex-ws-exchange.ts +52 -3
- package/src/server/responses/codex-ws-wire.ts +55 -0
- package/src/server/responses/compact.ts +9 -1
- package/src/server/responses/core.ts +337 -73
- package/src/server/responses/encrypted-payload.ts +45 -2
- package/src/server/responses/ws-upstream.ts +4 -1
- package/src/server/responses-self-named-namespace-scrub.ts +1 -3
- package/src/server/responses-undeclared-tool-guard.ts +1 -1
- package/src/server/search.ts +3 -0
- package/src/server/sse-payload-rewrite.ts +136 -51
- package/src/server/ws-bridge.ts +35 -1
- package/src/service/cli.ts +372 -0
- package/src/service/diagnostics.ts +340 -0
- package/src/service/guards.ts +303 -0
- package/src/service/health.ts +222 -0
- package/src/service/launchd.ts +853 -0
- package/src/service/orchestration.ts +617 -0
- package/src/service/repair.ts +334 -0
- package/src/service/state.ts +363 -0
- package/src/service/systemd.ts +229 -0
- package/src/service/windows-ops.ts +690 -0
- package/src/service/windows-scheduler.ts +769 -0
- package/src/service/windows-taskxml.ts +613 -0
- package/src/service.ts +22 -5550
- package/src/storage/cleanup/db.ts +258 -0
- package/src/storage/cleanup/execute.ts +358 -0
- package/src/storage/cleanup/paths.ts +189 -0
- package/src/storage/cleanup/pending.ts +140 -0
- package/src/storage/cleanup/preview.ts +292 -0
- package/src/storage/cleanup/reconcile.ts +347 -0
- package/src/storage/cleanup/restore.ts +932 -0
- package/src/storage/cleanup/satellite.ts +474 -0
- package/src/storage/cleanup/staging.ts +129 -0
- package/src/storage/cleanup/types.ts +98 -0
- package/src/storage/cleanup.ts +49 -3127
- package/src/types/accounts.ts +2 -0
- package/src/types/config.ts +13 -12
- package/src/types/provider.ts +37 -0
- package/src/types/request.ts +2 -0
- package/src/types/tools.ts +17 -5
- package/src/types.ts +1 -0
- package/src/usage/expected-prices.ts +127 -0
- package/src/usage/log.ts +58 -1
- package/src/vision/eligibility.ts +13 -2
- package/src/web-search/loop.ts +56 -3
- package/gui/dist/assets/index-CWXut3rG.js +0 -115
- package/gui/dist/assets/index-EdoPnm9_.css +0 -1
- package/src/adapters/devin-cli/acp.ts +0 -204
- package/src/adapters/devin-cli/adapter.ts +0 -345
- package/src/adapters/devin-cli/binary.ts +0 -69
- package/src/adapters/devin-cli/models.ts +0 -57
- package/src/oauth/devin-cli.ts +0 -149
- package/src/server/responses-reasoning-summary-rewrite.ts +0 -178
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { win32 } from "node:path";
|
|
2
|
+
import { loadConfig } from "../config";
|
|
3
|
+
import { serviceApiTokenFilePath } from "../lib/service-secrets";
|
|
4
|
+
import { PROXY_ENV_KEYS } from "../lib/proxy-env";
|
|
5
|
+
import { proxyIdentityAt } from "../server/proxy-liveness";
|
|
6
|
+
import { launchdListenPort } from "./launchd";
|
|
7
|
+
import { serviceLogPath } from "./state";
|
|
8
|
+
import { systemdListenPort } from "./systemd";
|
|
9
|
+
import { windowsListenPort, winswListenPort } from "./windows-ops";
|
|
10
|
+
|
|
11
|
+
export function shellQuote(value: string): string {
|
|
12
|
+
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Listen port baked into service wrappers / WinSW XML.
|
|
17
|
+
* Priority: explicit override → OCX_BAKE_PORT (update restart) → config.port → 10100.
|
|
18
|
+
* `config.port === 0` means ephemeral for interactive start; services need a stable pin,
|
|
19
|
+
* so treat 0 / invalid like unset (default 10100) instead of baking `--port 0`.
|
|
20
|
+
*/
|
|
21
|
+
export function resolveServiceListenPort(override?: number): number {
|
|
22
|
+
if (typeof override === "number" && Number.isFinite(override) && override > 0 && override <= 65535) {
|
|
23
|
+
return Math.trunc(override);
|
|
24
|
+
}
|
|
25
|
+
const baked = process.env.OCX_BAKE_PORT?.trim();
|
|
26
|
+
if (baked && /^\d+$/.test(baked)) {
|
|
27
|
+
const n = Number(baked);
|
|
28
|
+
if (n > 0 && n <= 65535) return n;
|
|
29
|
+
}
|
|
30
|
+
const configured = loadConfig().port;
|
|
31
|
+
if (typeof configured === "number" && configured > 0 && configured <= 65535) return configured;
|
|
32
|
+
return 10100;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function buildServiceShellCommand(bun: string, cli: string, port = resolveServiceListenPort()): string {
|
|
36
|
+
const tokenFile = serviceApiTokenFilePath();
|
|
37
|
+
return `if [ -f ${shellQuote(tokenFile)} ]; then OPENCODEX_API_AUTH_TOKEN="$(cat ${shellQuote(tokenFile)})"; export OPENCODEX_API_AUTH_TOKEN; fi; exec ${shellQuote(bun)} ${shellQuote(cli)} start --port ${port}`;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The same command shape, launched through a stable `ocx` executable instead of an
|
|
42
|
+
* explicit Bun + CLI pair. The token-file preamble is identical and deliberately shared
|
|
43
|
+
* in form: the service still reads the token from disk at start and never carries it in
|
|
44
|
+
* the unit.
|
|
45
|
+
*/
|
|
46
|
+
export function buildServiceLauncherShellCommand(launcher: string, port = resolveServiceListenPort()): string {
|
|
47
|
+
const tokenFile = serviceApiTokenFilePath();
|
|
48
|
+
return `if [ -f ${shellQuote(tokenFile)} ]; then OPENCODEX_API_AUTH_TOKEN="$(cat ${shellQuote(tokenFile)})"; export OPENCODEX_API_AUTH_TOKEN; fi; exec ${shellQuote(launcher)} start --port ${port}`;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Shared tail parser for the baked `--port <n>`.
|
|
53
|
+
*
|
|
54
|
+
* Terminators cover all three artifact shapes: whitespace (batch wrapper, systemd
|
|
55
|
+
* unit), `"` (systemd's quoted ExecStart), `<` (WinSW's `</arguments>`), and `&` (an
|
|
56
|
+
* XML-escaped quote). Matched LAST because every artifact carries the Bun and CLI
|
|
57
|
+
* paths ahead of the argument, and a path containing the literal must not shadow it.
|
|
58
|
+
*/
|
|
59
|
+
export function parseBakedListenPort(read: () => string): number | null {
|
|
60
|
+
try {
|
|
61
|
+
const last = [...read().matchAll(/start --port (\d{1,5})(?:\s|"|&|<|$)/gm)].at(-1);
|
|
62
|
+
if (!last) return null;
|
|
63
|
+
const n = Number(last[1]);
|
|
64
|
+
return n > 0 && n <= 65535 ? n : null;
|
|
65
|
+
} catch {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* The listen port of the INSTALLED service artifact, falling back to the configured
|
|
72
|
+
* one. Each reader returns null off its own platform, so the chain needs no platform
|
|
73
|
+
* branch — and on Windows both return null, preserving today's behavior.
|
|
74
|
+
*/
|
|
75
|
+
export function installedServiceListenPort(): number {
|
|
76
|
+
return launchdListenPort()
|
|
77
|
+
?? systemdListenPort()
|
|
78
|
+
?? windowsListenPort()
|
|
79
|
+
?? winswListenPort()
|
|
80
|
+
?? resolveServiceListenPort();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export const SERVICE_INSTALL_HEALTH_MS = 20_000;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Windows gets a longer budget because its cold start does more before the
|
|
87
|
+
* listener exists: NTFS ACL hardening and previous-session journal recovery
|
|
88
|
+
* both run first, and #3009 recorded a service that bound a few seconds past
|
|
89
|
+
* the 20s deadline and then stayed healthy. Reporting that as a terminal
|
|
90
|
+
* repair failure is worse than waiting — the caller's fallback is to start a
|
|
91
|
+
* second proxy against a port that is about to be taken.
|
|
92
|
+
*/
|
|
93
|
+
export const SERVICE_INSTALL_HEALTH_WINDOWS_MS = 45_000;
|
|
94
|
+
|
|
95
|
+
/** The health budget for the platform this is running on. */
|
|
96
|
+
export function serviceInstallHealthMs(
|
|
97
|
+
platform: NodeJS.Platform = process.platform,
|
|
98
|
+
): number {
|
|
99
|
+
return platform === "win32" ? SERVICE_INSTALL_HEALTH_WINDOWS_MS : SERVICE_INSTALL_HEALTH_MS;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Whether a proxy actually answers on the port this install/start just produced.
|
|
104
|
+
*
|
|
105
|
+
* Registration is not service: `launchctl list` reports a job that never bound, and
|
|
106
|
+
* `systemctl is-active` reports a process that bound nothing. Probing is the only
|
|
107
|
+
* thing that answers the question the user is actually asking.
|
|
108
|
+
*
|
|
109
|
+
* Probes the BAKED target rather than resolving one. `findLiveProxy` resolves through
|
|
110
|
+
* pidfile -> runtime-port -> config.port, and a service reinstall has just invalidated
|
|
111
|
+
* the first two while `resolveServiceListenPort` (OCX_BAKE_PORT precedence, config.port
|
|
112
|
+
* === 0 normalization) can disagree with the third.
|
|
113
|
+
*
|
|
114
|
+
* Soft: returns the outcome, never throws; the caller chooses between a checkmark and
|
|
115
|
+
* an actionable warning.
|
|
116
|
+
*/
|
|
117
|
+
export async function confirmServiceServing(
|
|
118
|
+
deps: {
|
|
119
|
+
port?: number;
|
|
120
|
+
hostname?: string;
|
|
121
|
+
probe?: (port: number, hostname: string) => Promise<boolean>;
|
|
122
|
+
sleep?: (ms: number) => Promise<void>;
|
|
123
|
+
now?: () => number;
|
|
124
|
+
timeoutMs?: number;
|
|
125
|
+
} = {},
|
|
126
|
+
): Promise<{ ok: true; port: number } | { ok: false; port: number }> {
|
|
127
|
+
const port = deps.port ?? installedServiceListenPort();
|
|
128
|
+
const hostname = deps.hostname ?? loadConfig().hostname ?? "127.0.0.1";
|
|
129
|
+
const now = deps.now ?? Date.now;
|
|
130
|
+
const sleep = deps.sleep ?? ((ms: number) => new Promise<void>(r => setTimeout(r, ms)));
|
|
131
|
+
const probe = deps.probe ?? (async (p, h) => !!(await proxyIdentityAt(p, { hostname: h })));
|
|
132
|
+
const deadline = now() + (deps.timeoutMs ?? serviceInstallHealthMs());
|
|
133
|
+
let waited = false;
|
|
134
|
+
for (;;) {
|
|
135
|
+
if (await probe(port, hostname)) return { ok: true, port };
|
|
136
|
+
if (now() >= deadline) break;
|
|
137
|
+
await sleep(500);
|
|
138
|
+
waited = true;
|
|
139
|
+
}
|
|
140
|
+
// The probe that ran last started before the deadline, so a service that binds
|
|
141
|
+
// during it is reported as dead (#3009). Knock once more after a short grace
|
|
142
|
+
// before calling it a failure. A zero budget means the caller asked not to
|
|
143
|
+
// wait, so it gets exactly the single probe it asked for and nothing more.
|
|
144
|
+
if (waited) {
|
|
145
|
+
await sleep(500);
|
|
146
|
+
if (await probe(port, hostname)) return { ok: true, port };
|
|
147
|
+
}
|
|
148
|
+
return { ok: false, port };
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Print the outcome of `install` / `start` / `repair` in terms of what the user cares
|
|
153
|
+
* about — is it serving? — instead of whether the manager accepted the registration.
|
|
154
|
+
*
|
|
155
|
+
* Sets `process.exitCode = 1` when nothing answers. That is deliberate: the GUI update
|
|
156
|
+
* worker reads the child's exit status, so a registered-but-silent service now makes it
|
|
157
|
+
* fall back to a direct proxy start rather than reporting a successful update over a
|
|
158
|
+
* dead port.
|
|
159
|
+
*/
|
|
160
|
+
export async function reportServiceServing(
|
|
161
|
+
verb: "installed" | "started" | "repaired" | "restarted",
|
|
162
|
+
deps: Parameters<typeof confirmServiceServing>[0] = {},
|
|
163
|
+
): Promise<void> {
|
|
164
|
+
const healthBudgetMs = deps.timeoutMs ?? serviceInstallHealthMs();
|
|
165
|
+
// Timed here rather than reported from the budget. confirmServiceServing knocks once
|
|
166
|
+
// more after a grace sleep whenever it waited at all, so the real wait is the budget
|
|
167
|
+
// plus that grace — and printing the budget states a number the run did not spend.
|
|
168
|
+
// What the reader is deciding is whether the service was still coming up, which is a
|
|
169
|
+
// judgement about elapsed time (#3009).
|
|
170
|
+
const now = deps.now ?? Date.now;
|
|
171
|
+
const startedAt = now();
|
|
172
|
+
const serving = await confirmServiceServing({ ...deps, timeoutMs: healthBudgetMs });
|
|
173
|
+
const waitedMs = Math.max(0, now() - startedAt);
|
|
174
|
+
if (serving.ok) {
|
|
175
|
+
console.log(`✅ opencodex service ${verb} and serving on port ${serving.port}.`);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
console.error(
|
|
179
|
+
`⚠️ Service ${verb}, but no proxy answered on port ${serving.port} after `
|
|
180
|
+
+ `${Math.round(waitedMs / 1000)}s.\n`
|
|
181
|
+
+ ` The manager registered the job; that is not the same as serving.\n`
|
|
182
|
+
+ ` Log: ${serviceLogPath()}\n`
|
|
183
|
+
+ ` Meanwhile: ocx start (serves in the foreground)`,
|
|
184
|
+
);
|
|
185
|
+
process.exitCode = 1;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* The command that repairs the CURRENTLY INSTALLED backend without switching it.
|
|
190
|
+
*
|
|
191
|
+
* `ocx service repair` reads the recorded backend itself, so it cannot silently switch a
|
|
192
|
+
* WinSW install to Task Scheduler the way a plain `ocx service install` would. A healthy
|
|
193
|
+
* scheduler definition needs no elevation; a stale definition can be re-registered and prompt.
|
|
194
|
+
*/
|
|
195
|
+
export function serviceRepairCommand(): string {
|
|
196
|
+
return "ocx service repair";
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Outbound proxy settings the installing shell had, resolved for baking into a service
|
|
201
|
+
* definition.
|
|
202
|
+
*
|
|
203
|
+
* A service manager does not inherit the environment of the shell that installed it, and
|
|
204
|
+
* `ExecStart=/bin/sh -lc` is dash on Ubuntu/WSL — login dash reads `.profile`, not
|
|
205
|
+
* `.bashrc`, which is where proxy exports usually live. So a user who needs a proxy to
|
|
206
|
+
* reach the upstream got a service that dialed direct: the socket was reset, the retry
|
|
207
|
+
* budget drained, and the request surfaced as `502 Provider unreachable` (#2107). The
|
|
208
|
+
* same install driven through `ocx codex-shim` worked, because that path spawns with
|
|
209
|
+
* `{ ...process.env }`.
|
|
210
|
+
*
|
|
211
|
+
* Lower-case variants are honored because curl-style tooling sets them and the runtime's
|
|
212
|
+
* own `applyProxyEnv` already treats both cases as equivalent. Only the canonical
|
|
213
|
+
* upper-case name is baked, so a definition never carries two spellings of one setting.
|
|
214
|
+
*/
|
|
215
|
+
export function resolvedProxyEnv(env: NodeJS.ProcessEnv = process.env): { name: string; value: string }[] {
|
|
216
|
+
const resolved: { name: string; value: string }[] = [];
|
|
217
|
+
for (const key of PROXY_ENV_KEYS) {
|
|
218
|
+
const value = env[key]?.trim() || env[key.toLowerCase()]?.trim();
|
|
219
|
+
if (value) resolved.push({ name: key, value });
|
|
220
|
+
}
|
|
221
|
+
return resolved;
|
|
222
|
+
}
|