super-dsh 0.1.6 → 0.1.10-e
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/README.md +25 -3
- package/agent-agy/cordis.patch.yml +7 -4
- package/agent-agy/dist/agent.d.ts +12 -11
- package/agent-agy/dist/agy-auth-gateway.d.ts +124 -0
- package/agent-agy/dist/agy-auth-gateway.js +233 -0
- package/agent-agy/dist/agy-auth.d.ts +153 -0
- package/agent-agy/dist/agy-auth.js +179 -0
- package/agent-agy/dist/agy-cli-client.d.ts +39 -9
- package/agent-agy/dist/agy-cli-client.js +82 -18
- package/agent-agy/dist/agy-store.d.ts +8 -0
- package/agent-agy/dist/index.d.ts +46 -16
- package/agent-agy/dist/index.js +82 -56
- package/agent-agy/dist/models.d.ts +70 -0
- package/agent-agy/dist/models.js +102 -3
- package/agent-agy/package.json +7 -5
- package/agent-agy-sdk/cordis.patch.yml +58 -0
- package/agent-agy-sdk/dist/adapter.d.ts +15 -0
- package/agent-agy-sdk/dist/adapter.js +42 -0
- package/agent-agy-sdk/dist/agent-preset-agy.d.ts +27 -0
- package/agent-agy-sdk/dist/agent-preset-agy.js +32 -0
- package/agent-agy-sdk/dist/agent.d.ts +138 -0
- package/agent-agy-sdk/dist/agent.js +494 -0
- package/{agent-agy → agent-agy-sdk}/dist/agy-client.d.ts +26 -6
- package/{agent-agy → agent-agy-sdk}/dist/agy-client.js +43 -25
- package/agent-agy-sdk/dist/agy-sessions.d.ts +25 -0
- package/agent-agy-sdk/dist/agy-sessions.js +107 -0
- package/agent-agy-sdk/dist/agy-store.d.ts +39 -0
- package/agent-agy-sdk/dist/agy-store.js +83 -0
- package/agent-agy-sdk/dist/inbox.d.ts +26 -0
- package/agent-agy-sdk/dist/inbox.js +53 -0
- package/agent-agy-sdk/dist/index.d.ts +93 -0
- package/agent-agy-sdk/dist/index.js +476 -0
- package/agent-agy-sdk/dist/models.d.ts +41 -0
- package/agent-agy-sdk/dist/models.js +74 -0
- package/agent-agy-sdk/dist/sdk-venv.d.ts +76 -0
- package/agent-agy-sdk/dist/sdk-venv.js +173 -0
- package/agent-agy-sdk/dist/world-plugin.d.ts +10 -0
- package/agent-agy-sdk/dist/world-plugin.js +82 -0
- package/agent-agy-sdk/package.json +64 -0
- package/agent-claude/dist/adapter.js +106 -31
- package/agent-claude/dist/agent.js +154 -17
- package/agent-claude/dist/claude-client.js +84 -43
- package/agent-claude/dist/claude-launch.js +101 -0
- package/agent-claude/dist/claude-native-config.js +169 -0
- package/agent-claude/dist/claude-provider-gateway.js +340 -0
- package/agent-claude/dist/claude-providers.js +391 -0
- package/agent-claude/dist/claude-route.js +152 -0
- package/agent-claude/dist/index.js +214 -37
- package/agent-claude/dist/models.js +14 -0
- package/agent-claude/dist/sdk-runtime.js +320 -0
- package/agent-claude/package.json +6 -4
- package/agent-codex/README.md +141 -36
- package/agent-codex/cordis.patch.yml +14 -10
- package/agent-codex/dist/adapter.js +64 -28
- package/agent-codex/dist/agent.js +255 -81
- package/agent-codex/dist/app-server-approvals.js +165 -0
- package/agent-codex/dist/app-server-client.js +723 -0
- package/agent-codex/dist/app-server-events.js +432 -0
- package/agent-codex/dist/app-server-protocol.js +95 -0
- package/agent-codex/dist/app-server-wire.js +299 -0
- package/agent-codex/dist/codex-launch.js +78 -0
- package/agent-codex/dist/codex-native-config.js +392 -0
- package/agent-codex/dist/codex-provider-gateway.js +402 -0
- package/agent-codex/dist/codex-providers.js +376 -0
- package/agent-codex/dist/codex-route.js +86 -0
- package/agent-codex/dist/index.js +256 -115
- package/agent-codex/dist/permission.js +75 -1
- package/agent-codex/package.json +1 -2
- package/agent-codex-sdk/README.md +79 -0
- package/agent-codex-sdk/cordis.patch.yml +81 -0
- package/agent-codex-sdk/dist/adapter.js +91 -0
- package/agent-codex-sdk/dist/agent-preset-codex.js +32 -0
- package/agent-codex-sdk/dist/agent.js +1085 -0
- package/agent-codex-sdk/dist/codex-native-config.js +392 -0
- package/agent-codex-sdk/dist/codex-provider-gateway.js +402 -0
- package/agent-codex-sdk/dist/codex-providers.js +376 -0
- package/agent-codex-sdk/dist/codex-route.js +86 -0
- package/{agent-codex/dist/codex-client.js → agent-codex-sdk/dist/codex-sdk-client.js} +253 -32
- package/agent-codex-sdk/dist/codex-sdk-launch.js +92 -0
- package/agent-codex-sdk/dist/codex-store.js +180 -0
- package/agent-codex-sdk/dist/inbox.js +53 -0
- package/agent-codex-sdk/dist/index.js +739 -0
- package/agent-codex-sdk/dist/permission.js +71 -0
- package/agent-codex-sdk/dist/sdk-runtime.js +307 -0
- package/agent-codex-sdk/dist/session-map.js +167 -0
- package/agent-codex-sdk/dist/world-plugin.js +93 -0
- package/agent-codex-sdk/package.json +79 -0
- package/agent-codex-sdk/scripts/fetch-sdk-runtime.mjs +57 -0
- package/agent-omp/README.md +72 -55
- package/agent-omp/dist/agent.js +36 -11
- package/agent-omp/dist/index.js +92 -52
- package/agent-omp/dist/lazy-rpc.js +11 -4
- package/agent-omp/dist/omp-cli.js +114 -97
- package/agent-omp/dist/omp-store.js +12 -4
- package/agent-omp/dist/permission.js +70 -5
- package/agent-omp/dist/rpc-client.js +409 -0
- package/agent-omp/dist/world-plugin.js +36 -3
- package/agent-omp/package.json +2 -6
- package/agent-omp-sdk/README.md +103 -0
- package/agent-omp-sdk/cordis.patch.yml +108 -0
- package/agent-omp-sdk/dist/adapter.d.ts +21 -0
- package/agent-omp-sdk/dist/adapter.js +36 -0
- package/agent-omp-sdk/dist/agent-preset-omp.d.ts +31 -0
- package/agent-omp-sdk/dist/agent-preset-omp.js +32 -0
- package/agent-omp-sdk/dist/agent.d.ts +64 -0
- package/agent-omp-sdk/dist/agent.js +1178 -0
- package/agent-omp-sdk/dist/discovery.d.ts +57 -0
- package/agent-omp-sdk/dist/discovery.js +116 -0
- package/agent-omp-sdk/dist/inbox.d.ts +28 -0
- package/agent-omp-sdk/dist/inbox.js +53 -0
- package/agent-omp-sdk/dist/index.d.ts +60 -0
- package/agent-omp-sdk/dist/index.js +632 -0
- package/agent-omp-sdk/dist/knobs.d.ts +34 -0
- package/agent-omp-sdk/dist/knobs.js +50 -0
- package/agent-omp-sdk/dist/lazy-rpc.d.ts +98 -0
- package/agent-omp-sdk/dist/lazy-rpc.js +178 -0
- package/agent-omp-sdk/dist/mobile/zoom-guard.d.ts +187 -0
- package/agent-omp-sdk/dist/mobile/zoom-guard.js +294 -0
- package/agent-omp-sdk/dist/mobile-boot.d.ts +49 -0
- package/agent-omp-sdk/dist/mobile-boot.js +38 -0
- package/agent-omp-sdk/dist/models.d.ts +39 -0
- package/agent-omp-sdk/dist/models.js +299 -0
- package/agent-omp-sdk/dist/omp-cli.d.ts +67 -0
- package/agent-omp-sdk/dist/omp-cli.js +164 -0
- package/agent-omp-sdk/dist/omp-disk-discovery.d.ts +27 -0
- package/agent-omp-sdk/dist/omp-disk-discovery.js +178 -0
- package/agent-omp-sdk/dist/omp-executable.d.ts +2 -0
- package/agent-omp-sdk/dist/omp-executable.js +30 -0
- package/agent-omp-sdk/dist/omp-store.d.ts +134 -0
- package/agent-omp-sdk/dist/omp-store.js +526 -0
- package/agent-omp-sdk/dist/pairing.d.ts +7 -0
- package/agent-omp-sdk/dist/pairing.js +45 -0
- package/agent-omp-sdk/dist/permission.d.ts +138 -0
- package/agent-omp-sdk/dist/permission.js +161 -0
- package/agent-omp-sdk/dist/protocol.d.ts +189 -0
- package/agent-omp-sdk/dist/rpc-types.d.ts +77 -0
- package/agent-omp-sdk/dist/rpc-types.js +1 -0
- package/agent-omp-sdk/dist/sdk-client.d.ts +160 -0
- package/{agent-omp → agent-omp-sdk}/dist/sdk-client.js +108 -56
- package/agent-omp-sdk/dist/sdk-runtime.d.ts +211 -0
- package/agent-omp-sdk/dist/sdk-runtime.js +418 -0
- package/agent-omp-sdk/dist/sidecar-client.d.ts +87 -0
- package/agent-omp-sdk/dist/sidecar-client.js +197 -0
- package/agent-omp-sdk/dist/store/adapter.d.ts +17 -0
- package/agent-omp-sdk/dist/store/adapter.js +47 -0
- package/agent-omp-sdk/dist/store/db.d.ts +70 -0
- package/agent-omp-sdk/dist/store/db.js +210 -0
- package/agent-omp-sdk/dist/store/index.d.ts +23 -0
- package/agent-omp-sdk/dist/store/index.js +59 -0
- package/agent-omp-sdk/dist/store/reconcile.d.ts +15 -0
- package/agent-omp-sdk/dist/store/reconcile.js +51 -0
- package/agent-omp-sdk/dist/store/schema.d.ts +8 -0
- package/agent-omp-sdk/dist/store/schema.js +40 -0
- package/agent-omp-sdk/dist/transport.d.ts +49 -0
- package/agent-omp-sdk/dist/transport.js +35 -0
- package/agent-omp-sdk/dist/world-home.d.ts +4 -0
- package/agent-omp-sdk/dist/world-home.js +23 -0
- package/agent-omp-sdk/dist/world-plugin.d.ts +10 -0
- package/agent-omp-sdk/dist/world-plugin.js +137 -0
- package/agent-omp-sdk/package.json +87 -0
- package/client/index.js +1883 -287
- package/cordis.patch.yml +80 -0
- package/package.json +23 -9
- package/superd-hub/dist/a2a-delivery.d.ts +189 -0
- package/superd-hub/dist/a2a-delivery.js +240 -0
- package/superd-hub/dist/a2a-host.d.ts +76 -0
- package/superd-hub/dist/a2a-host.js +145 -0
- package/superd-hub/dist/a2a-ingest.d.ts +31 -0
- package/superd-hub/dist/a2a-ingest.js +636 -0
- package/superd-hub/dist/a2a-log.d.ts +17 -0
- package/superd-hub/dist/a2a-log.js +42 -0
- package/superd-hub/dist/a2a-row.d.ts +65 -0
- package/superd-hub/dist/a2a-row.js +162 -0
- package/superd-hub/dist/a2a-service.d.ts +357 -0
- package/superd-hub/dist/a2a-service.js +980 -0
- package/superd-hub/dist/a2a-wire.d.ts +220 -0
- package/superd-hub/dist/a2a-wire.js +305 -0
- package/superd-hub/dist/agent-ids.d.ts +10 -0
- package/superd-hub/dist/agent-ids.js +68 -0
- package/superd-hub/dist/agent-roster.d.ts +29 -18
- package/superd-hub/dist/agent-roster.js +54 -15
- package/superd-hub/dist/agent-status.d.ts +119 -0
- package/superd-hub/dist/agent-status.js +386 -0
- package/superd-hub/dist/client/agent-settings.d.ts +210 -0
- package/superd-hub/dist/client/agent-settings.js +300 -0
- package/superd-hub/dist/client/mesh-api.d.ts +134 -0
- package/superd-hub/dist/client/mesh-api.js +219 -0
- package/superd-hub/dist/client/mesh-groups.d.ts +63 -0
- package/superd-hub/dist/client/mesh-groups.js +66 -0
- package/superd-hub/dist/client/roster.d.ts +48 -0
- package/superd-hub/dist/client/roster.js +102 -0
- package/superd-hub/dist/client/runtime-settings-api.d.ts +76 -0
- package/superd-hub/dist/client/runtime-settings-api.js +137 -0
- package/superd-hub/dist/client/switch.d.ts +165 -0
- package/superd-hub/dist/client/switch.js +295 -0
- package/superd-hub/dist/exec-pty-channel.d.ts +58 -0
- package/superd-hub/dist/exec-pty-channel.js +162 -0
- package/superd-hub/dist/exec-pty-framing.d.ts +32 -0
- package/superd-hub/dist/exec-pty-framing.js +81 -0
- package/superd-hub/dist/exec-pty-rpc.d.ts +21 -0
- package/superd-hub/dist/exec-pty-rpc.js +128 -0
- package/superd-hub/dist/exec-pty-session.d.ts +76 -0
- package/superd-hub/dist/exec-pty-session.js +234 -0
- package/superd-hub/dist/exec.d.ts +56 -0
- package/superd-hub/dist/exec.js +225 -0
- package/superd-hub/dist/gateway.d.ts +39 -2
- package/superd-hub/dist/gateway.js +62 -3
- package/superd-hub/dist/hub-tool.d.ts +174 -0
- package/superd-hub/dist/hub-tool.js +464 -0
- package/superd-hub/dist/index.d.ts +15 -1
- package/superd-hub/dist/index.js +16 -0
- package/superd-hub/dist/machines.d.ts +45 -0
- package/superd-hub/dist/machines.js +125 -0
- package/superd-hub/dist/mesh-federate.d.ts +138 -0
- package/superd-hub/dist/mesh-federate.js +223 -0
- package/superd-hub/dist/mesh-gateway.d.ts +67 -0
- package/superd-hub/dist/mesh-gateway.js +408 -0
- package/superd-hub/dist/mesh-link.d.ts +274 -0
- package/superd-hub/dist/mesh-link.js +441 -0
- package/superd-hub/dist/mesh-rpc.d.ts +123 -0
- package/superd-hub/dist/mesh-rpc.js +250 -0
- package/superd-hub/dist/mux-client.d.ts +71 -0
- package/superd-hub/dist/mux-client.js +281 -0
- package/superd-hub/dist/pack-version.d.ts +2 -0
- package/superd-hub/dist/pack-version.js +30 -0
- package/superd-hub/dist/roster.d.ts +6 -0
- package/superd-hub/dist/rpc.d.ts +18 -2
- package/superd-hub/dist/rpc.js +34 -4
- package/superd-hub/dist/spawn-world.js +3 -1
- package/superd-hub/dist/switch-core.d.ts +62 -25
- package/superd-hub/dist/switch-core.js +53 -30
- package/superd-hub/dist/system-head.d.ts +22 -12
- package/superd-hub/dist/system-head.js +100 -84
- package/superd-hub/dist/wire-endpoints.d.ts +264 -0
- package/superd-hub/dist/wire-endpoints.js +180 -0
- package/superd-hub/lib/client/index.js +1883 -287
- package/superd-hub/package.json +11 -2
- package/agent-agy/dist/agent-preset-projection.d.ts +0 -31
- package/agent-agy/dist/agent-preset-projection.js +0 -33
- package/agent-claude/dist/agent-preset-projection.js +0 -30
- package/agent-codex/dist/agent-preset-projection.js +0 -37
- package/agent-codex/dist/app-home.js +0 -65
- package/agent-codex/dist/models.js +0 -152
- package/agent-codex/dist/spike.js +0 -46
- package/agent-hermes/dist/agent-preset-projection.js +0 -34
- package/agent-omp/dist/agent-preset-projection.js +0 -36
- package/agent-omp/dist/app-home.js +0 -86
- package/agent-omp/dist/sidecar-client.js +0 -195
- package/agent-pi/dist/agent-preset-projection.js +0 -29
- package/superd-hub/dist/client-shim.d.ts +0 -28
- package/superd-hub/dist/client-shim.js +0 -251
- package/superd-hub/dist/index-pass.d.ts +0 -22
- package/superd-hub/dist/index-pass.js +0 -47
- package/superd-hub/dist/labels.d.ts +0 -45
- package/superd-hub/dist/labels.js +0 -83
- /package/{agent-agy → agent-agy-sdk}/bridge/agy_bridge.py +0 -0
- /package/{agent-agy → agent-agy-sdk}/bridge/gemini_openai_server.mjs +0 -0
- /package/{agent-codex/dist/codex-events.js → agent-codex-sdk/dist/codex-sdk-events.js} +0 -0
- /package/{agent-omp → agent-omp-sdk}/dist/protocol.js +0 -0
- /package/{agent-omp → agent-omp-sdk}/sidecar/main.ts +0 -0
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex app-server stdio transport (2026-10-03, app-server line).
|
|
3
|
+
*
|
|
4
|
+
* One `codex app-server` child process, newline-delimited JSON-RPC 2.0 with the
|
|
5
|
+
* `jsonrpc` header OMITTED on the wire (official README + live probe
|
|
6
|
+
* 2026-10-03: every frame is `{"id":…,"method":…,"params":…}` or
|
|
7
|
+
* `{"id":…,"result":…}` / `{"id":…,"error":{…}}`).
|
|
8
|
+
*
|
|
9
|
+
* This module owns exactly four things and nothing else:
|
|
10
|
+
* 1. executable resolution (pin-faithful: the package's own `@openai/codex`),
|
|
11
|
+
* 2. process spawn + line framing + per-id request/response correlation,
|
|
12
|
+
* 3. dispatch of server-initiated notifications and server-requests,
|
|
13
|
+
* 4. teardown (process GROUP kill — the app-server may spawn stdio MCP
|
|
14
|
+
* children that `setsid` away; see the Hermes research §5.8).
|
|
15
|
+
*
|
|
16
|
+
* It carries NO codex semantics: no thread, no turn, no projection. Callers
|
|
17
|
+
* (`app-server-client.ts`) own all of that. Never throws into the event loop:
|
|
18
|
+
* every callback is invoked defensively.
|
|
19
|
+
*
|
|
20
|
+
* Lazy-spawn discipline (agent-adapter-dev-rules §14-i): constructing a
|
|
21
|
+
* transport touches nothing; `start()` is the ONLY thing that creates a
|
|
22
|
+
* process, and the client calls it on first real work.
|
|
23
|
+
*/
|
|
24
|
+
import { spawn } from "node:child_process";
|
|
25
|
+
import { createRequire } from "node:module";
|
|
26
|
+
/** Per-request protocol error surfaced by the server (JSON-RPC `error` object). */
|
|
27
|
+
export class CodexWireError extends Error {
|
|
28
|
+
code;
|
|
29
|
+
data;
|
|
30
|
+
constructor(method, code, message, data) {
|
|
31
|
+
super(`codex app-server ${method} failed (${code}): ${message}`);
|
|
32
|
+
this.name = "CodexWireError";
|
|
33
|
+
this.code = code;
|
|
34
|
+
this.data = data;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/** Server overload: the documented retryable backpressure code. */
|
|
38
|
+
export const SERVER_OVERLOADED_CODE = -32001;
|
|
39
|
+
const DEFAULT_REQUEST_TIMEOUT_MS = 60_000;
|
|
40
|
+
/** The codex entry script this package pins (`@openai/codex/bin/codex.js`). */
|
|
41
|
+
export function resolveCodexCommand() {
|
|
42
|
+
const override = process.env.CODEX_BIN;
|
|
43
|
+
if (override !== undefined && override.trim() !== "")
|
|
44
|
+
return override;
|
|
45
|
+
const require = createRequire(import.meta.url);
|
|
46
|
+
try {
|
|
47
|
+
// Pin-faithful: the SAME `@openai/codex` this package depends on, so the
|
|
48
|
+
// wire protocol and the binary version can never drift apart. Set
|
|
49
|
+
// CODEX_BIN to override (tests).
|
|
50
|
+
return require.resolve("@openai/codex/bin/codex.js");
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
throw new Error("cannot locate the pinned codex CLI (@openai/codex/bin/codex.js): "
|
|
54
|
+
+ `${error instanceof Error ? error.message : String(error)}. Install the package or set CODEX_BIN.`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/** True for a plain JSON object (never arrays/null). */
|
|
58
|
+
function asRecord(value) {
|
|
59
|
+
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
60
|
+
return null;
|
|
61
|
+
return value;
|
|
62
|
+
}
|
|
63
|
+
export class CodexAppServerTransport {
|
|
64
|
+
#options;
|
|
65
|
+
#child;
|
|
66
|
+
#stdout = "";
|
|
67
|
+
#stderr = "";
|
|
68
|
+
#nextId = 1;
|
|
69
|
+
#closed = false;
|
|
70
|
+
#pending = new Map();
|
|
71
|
+
constructor(options = {}) {
|
|
72
|
+
this.#options = options;
|
|
73
|
+
}
|
|
74
|
+
/** Whether a child process currently exists. */
|
|
75
|
+
get alive() {
|
|
76
|
+
return this.#child !== undefined && this.#child.exitCode === null && !this.#child.killed;
|
|
77
|
+
}
|
|
78
|
+
/** The child pid, when spawned. */
|
|
79
|
+
get pid() {
|
|
80
|
+
return this.#child?.pid;
|
|
81
|
+
}
|
|
82
|
+
/** Number of in-flight requests (observability / tests). */
|
|
83
|
+
get pendingCount() {
|
|
84
|
+
return this.#pending.size;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Spawn the child exactly once. Idempotent.
|
|
88
|
+
* @throws when the child cannot be spawned at all (bad executable).
|
|
89
|
+
*/
|
|
90
|
+
start() {
|
|
91
|
+
if (this.#child !== undefined)
|
|
92
|
+
return;
|
|
93
|
+
const command = this.#options.command ?? resolveCodexCommand();
|
|
94
|
+
const args = [...(this.#options.args ?? ["app-server"])];
|
|
95
|
+
// `detached` gives the child its own process group so teardown can kill
|
|
96
|
+
// the whole tree (stdio MCP descendants included), not just the root.
|
|
97
|
+
const child = spawn(process.execPath, [command, ...args], {
|
|
98
|
+
cwd: this.#options.cwd,
|
|
99
|
+
env: this.#options.env ?? { ...process.env },
|
|
100
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
101
|
+
detached: true,
|
|
102
|
+
});
|
|
103
|
+
this.#child = child;
|
|
104
|
+
child.stdout?.setEncoding("utf8");
|
|
105
|
+
child.stderr?.setEncoding("utf8");
|
|
106
|
+
child.stdout?.on("data", (chunk) => this.#onStdout(chunk));
|
|
107
|
+
child.stderr?.on("data", (chunk) => {
|
|
108
|
+
this.#stderr = `${this.#stderr}${chunk}`.slice(-8_192);
|
|
109
|
+
this.#options.onStderr?.(chunk);
|
|
110
|
+
});
|
|
111
|
+
child.on("error", (error) => this.#onExit(null, null, error));
|
|
112
|
+
child.on("exit", (code, signal) => this.#onExit(code, signal));
|
|
113
|
+
}
|
|
114
|
+
/** Send a request and await its result. Rejects on protocol error, timeout, or EOF. */
|
|
115
|
+
request(method, params, options = {}) {
|
|
116
|
+
if (this.#closed || this.#child === undefined) {
|
|
117
|
+
return Promise.reject(new Error("codex app-server transport is not running"));
|
|
118
|
+
}
|
|
119
|
+
const id = this.#nextId++;
|
|
120
|
+
const timeoutMs = options.timeoutMs ?? this.#options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
|
|
121
|
+
return new Promise((resolve, reject) => {
|
|
122
|
+
const entry = { method, resolve, reject };
|
|
123
|
+
if (timeoutMs > 0) {
|
|
124
|
+
entry.timer = setTimeout(() => {
|
|
125
|
+
this.#pending.delete(id);
|
|
126
|
+
reject(new Error(`codex app-server ${method} timed out after ${timeoutMs}ms`));
|
|
127
|
+
}, timeoutMs);
|
|
128
|
+
entry.timer.unref?.();
|
|
129
|
+
}
|
|
130
|
+
this.#pending.set(id, entry);
|
|
131
|
+
this.#write({ id, method, params: params ?? null });
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
/** Send a notification (no id, no answer). */
|
|
135
|
+
notify(method, params) {
|
|
136
|
+
this.#write(params === undefined ? { method } : { method, params });
|
|
137
|
+
}
|
|
138
|
+
/** Write the answer for one server-initiated request. */
|
|
139
|
+
respond(id, outcome) {
|
|
140
|
+
if (typeof id !== "number" && typeof id !== "string")
|
|
141
|
+
return;
|
|
142
|
+
this.#write({ id, ...outcome });
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Stop the child: `SIGTERM` to its process group, then `SIGKILL` after a
|
|
146
|
+
* short grace period, plus a direct `child.kill()` fallback. Idempotent and
|
|
147
|
+
* safe to call before `start()`.
|
|
148
|
+
*/
|
|
149
|
+
close(graceMs = 500) {
|
|
150
|
+
if (this.#closed)
|
|
151
|
+
return;
|
|
152
|
+
this.#closed = true;
|
|
153
|
+
this.#failAll(new Error("codex app-server transport closed"));
|
|
154
|
+
const child = this.#child;
|
|
155
|
+
if (child === undefined)
|
|
156
|
+
return;
|
|
157
|
+
const pid = child.pid;
|
|
158
|
+
const killGroup = (signal) => {
|
|
159
|
+
if (pid === undefined)
|
|
160
|
+
return;
|
|
161
|
+
try {
|
|
162
|
+
process.kill(-pid, signal);
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
// Group already gone (or the child never became a group leader).
|
|
166
|
+
}
|
|
167
|
+
try {
|
|
168
|
+
child.kill(signal);
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
// Already dead.
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
killGroup("SIGTERM");
|
|
175
|
+
const timer = setTimeout(() => killGroup("SIGKILL"), Math.max(0, graceMs));
|
|
176
|
+
timer.unref?.();
|
|
177
|
+
child.once("exit", () => clearTimeout(timer));
|
|
178
|
+
// Detach our pipes so a wedged child cannot keep this process alive.
|
|
179
|
+
child.stdin?.end();
|
|
180
|
+
}
|
|
181
|
+
#write(message) {
|
|
182
|
+
const stdin = this.#child?.stdin ?? null;
|
|
183
|
+
if (stdin === null || stdin.destroyed || !stdin.writable)
|
|
184
|
+
return;
|
|
185
|
+
try {
|
|
186
|
+
stdin.write(`${JSON.stringify(message)}\n`);
|
|
187
|
+
}
|
|
188
|
+
catch (error) {
|
|
189
|
+
this.#options.onStderr?.(`codex app-server write failed: ${String(error)}\n`);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
/** Split stdout into lines; non-JSON lines are diagnostics, never protocol. */
|
|
193
|
+
#onStdout(chunk) {
|
|
194
|
+
this.#stdout += chunk;
|
|
195
|
+
for (;;) {
|
|
196
|
+
const index = this.#stdout.indexOf("\n");
|
|
197
|
+
if (index < 0)
|
|
198
|
+
break;
|
|
199
|
+
const line = this.#stdout.slice(0, index).trim();
|
|
200
|
+
this.#stdout = this.#stdout.slice(index + 1);
|
|
201
|
+
if (line === "")
|
|
202
|
+
continue;
|
|
203
|
+
let message;
|
|
204
|
+
try {
|
|
205
|
+
message = JSON.parse(line);
|
|
206
|
+
}
|
|
207
|
+
catch {
|
|
208
|
+
this.#options.onStderr?.(`codex app-server non-JSON stdout: ${line.slice(0, 400)}\n`);
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
this.#dispatch(message);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
/** Route one decoded frame to its pending slot, a notification, or a server-request. */
|
|
215
|
+
#dispatch(message) {
|
|
216
|
+
const record = asRecord(message);
|
|
217
|
+
if (record === null)
|
|
218
|
+
return;
|
|
219
|
+
const id = record["id"];
|
|
220
|
+
const method = record["method"];
|
|
221
|
+
const hasResult = "result" in record || "error" in record;
|
|
222
|
+
if ((typeof id === "number" || typeof id === "string") && typeof method !== "string" && hasResult) {
|
|
223
|
+
this.#settle(id, record);
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
if (typeof method === "string") {
|
|
227
|
+
const params = record["params"];
|
|
228
|
+
if (typeof id === "number" || typeof id === "string") {
|
|
229
|
+
this.#handleServerRequest(id, method, params);
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
try {
|
|
233
|
+
this.#options.onNotification?.({ method, params });
|
|
234
|
+
}
|
|
235
|
+
catch (error) {
|
|
236
|
+
this.#options.onStderr?.(`codex app-server notification handler threw: ${String(error)}\n`);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
#settle(id, record) {
|
|
241
|
+
const entry = typeof id === "number" ? this.#pending.get(id) : undefined;
|
|
242
|
+
if (entry === undefined)
|
|
243
|
+
return;
|
|
244
|
+
if (typeof id === "number")
|
|
245
|
+
this.#pending.delete(id);
|
|
246
|
+
if (entry.timer !== undefined)
|
|
247
|
+
clearTimeout(entry.timer);
|
|
248
|
+
const error = asRecord(record["error"]);
|
|
249
|
+
if (error !== null) {
|
|
250
|
+
const code = typeof error["code"] === "number" ? error["code"] : -32603;
|
|
251
|
+
const message = typeof error["message"] === "string" ? error["message"] : "unknown protocol error";
|
|
252
|
+
entry.reject(new CodexWireError(entry.method, code, message, error["data"]));
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
entry.resolve(record["result"]);
|
|
256
|
+
}
|
|
257
|
+
#handleServerRequest(id, method, params) {
|
|
258
|
+
const handler = this.#options.onServerRequest;
|
|
259
|
+
if (handler === undefined) {
|
|
260
|
+
this.respond(id, { error: { code: -32601, message: `no handler for ${method}` } });
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
void (async () => {
|
|
264
|
+
try {
|
|
265
|
+
const outcome = await handler({ method, params });
|
|
266
|
+
this.respond(id, outcome);
|
|
267
|
+
}
|
|
268
|
+
catch (error) {
|
|
269
|
+
this.respond(id, { error: { code: -32603, message: error instanceof Error ? error.message : String(error) } });
|
|
270
|
+
}
|
|
271
|
+
})();
|
|
272
|
+
}
|
|
273
|
+
#onExit(code, signal, error) {
|
|
274
|
+
if (this.#child === undefined) {
|
|
275
|
+
// Spawn failure: `error` fires without `exit`.
|
|
276
|
+
this.#failAll(error ?? new Error("codex app-server failed to start"));
|
|
277
|
+
this.#options.onExit?.({ code, signal });
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
if (this.#closed && this.#pending.size === 0 && code === null && signal === null && error === undefined)
|
|
281
|
+
return;
|
|
282
|
+
const reason = error !== undefined
|
|
283
|
+
? `codex app-server failed: ${error.message}`
|
|
284
|
+
: `codex app-server exited (code=${String(code)} signal=${String(signal)})`;
|
|
285
|
+
this.#failAll(new Error(reason));
|
|
286
|
+
if (error !== undefined)
|
|
287
|
+
this.#options.onStderr?.(`${reason}\n`);
|
|
288
|
+
this.#options.onExit?.({ code, signal });
|
|
289
|
+
}
|
|
290
|
+
#failAll(error) {
|
|
291
|
+
const entries = [...this.#pending.values()];
|
|
292
|
+
this.#pending.clear();
|
|
293
|
+
for (const entry of entries) {
|
|
294
|
+
if (entry.timer !== undefined)
|
|
295
|
+
clearTimeout(entry.timer);
|
|
296
|
+
entry.reject(error);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* codex-launch.ts — how a provider reaches a `codex app-server` child
|
|
3
|
+
* (2026-10-04 on-the-fly rework).
|
|
4
|
+
*
|
|
5
|
+
* The retired design put the provider in force by REWRITING the user's
|
|
6
|
+
* `~/.codex/config.toml` before the child started. That made the user's native
|
|
7
|
+
* home the switchboard: every switch was a disk write, only ever affected the
|
|
8
|
+
* next child, and fought every other tool that owns the same file (cc-switch's
|
|
9
|
+
* whole-config rewrites, the user's own hand edits).
|
|
10
|
+
*
|
|
11
|
+
* This module replaces it with process arguments. `codex app-server -c
|
|
12
|
+
* <dotted.path>=<value>` overrides any `config.toml` value for THAT child
|
|
13
|
+
* alone (the flag's own help text: "Override a configuration value that would
|
|
14
|
+
* otherwise be loaded from `~/.codex/config.toml`. Use a dotted path."), and
|
|
15
|
+
* `ThreadStartParams`/`ThreadResumeParams` accept the same object as `config`.
|
|
16
|
+
* A provider therefore costs nothing on disk and is scoped to one process, which
|
|
17
|
+
* is exactly what a per-session provider choice needs.
|
|
18
|
+
*
|
|
19
|
+
* Measured constraints this module encodes (see
|
|
20
|
+
* `docs/test-reports/2026-10-03-codex-provider-model-switch-probe.md`):
|
|
21
|
+
*
|
|
22
|
+
* - a HYPHENATED id is fine in a dotted path (`model_providers.zhipu-cn.…`),
|
|
23
|
+
* so native table names survive verbatim as provider ids;
|
|
24
|
+
* - `model_catalog_json` is resolved against the process CWD when it arrives
|
|
25
|
+
* as an override, so the path is always absolute;
|
|
26
|
+
* - `env_key` is the one auth shape that never consults the auth manager, so a
|
|
27
|
+
* stored API key rides the CHILD's environment under a synthetic variable
|
|
28
|
+
* name. That is also what makes a keyed provider usable behind a ChatGPT
|
|
29
|
+
* login, where `requires_openai_auth` is silently shadowed.
|
|
30
|
+
*
|
|
31
|
+
* @module agent-codex/codex-launch
|
|
32
|
+
*/
|
|
33
|
+
import { tomlString, writeProviderCatalog } from "./codex-native-config.js";
|
|
34
|
+
/** The environment variable prefix for a key this adapter injects itself. */
|
|
35
|
+
const SYNTHETIC_KEY_PREFIX = "SUPERD_CODEX_KEY_";
|
|
36
|
+
/** The launch for "no provider injection at all" (the native config applies). */
|
|
37
|
+
export const NATIVE_LAUNCH = { argv: [], env: {} };
|
|
38
|
+
/** The environment variable a stored API key is handed to the child as. */
|
|
39
|
+
export function syntheticKeyName(providerId) {
|
|
40
|
+
return `${SYNTHETIC_KEY_PREFIX}${providerId.toUpperCase().replace(/[^A-Z0-9]/g, "_")}`;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* The launch that pins one provider for the life of a child process.
|
|
44
|
+
*
|
|
45
|
+
* @param worldHome - the world's DSH home (our per-provider catalogs live there).
|
|
46
|
+
* @param codexHome - the native codex home; READ ONLY (catalog template material).
|
|
47
|
+
* @param provider - the provider the child must run on.
|
|
48
|
+
* @returns the argv/env additions and the provider id they pin.
|
|
49
|
+
*/
|
|
50
|
+
export function providerLaunch(worldHome, codexHome, provider) {
|
|
51
|
+
const table = `model_providers.${provider.id}`;
|
|
52
|
+
const argv = [
|
|
53
|
+
"-c", `${table}.name=${tomlString(provider.label)}`,
|
|
54
|
+
"-c", `${table}.base_url=${tomlString(provider.baseUrl)}`,
|
|
55
|
+
"-c", `${table}.wire_api=${tomlString(provider.protocol)}`,
|
|
56
|
+
];
|
|
57
|
+
const env = {};
|
|
58
|
+
if (provider.auth.kind === "env") {
|
|
59
|
+
argv.push("-c", `${table}.env_key=${tomlString(provider.auth.name)}`);
|
|
60
|
+
}
|
|
61
|
+
else if (provider.auth.value !== "") {
|
|
62
|
+
// A key we hold: never touch auth.json, never go through the auth manager.
|
|
63
|
+
const name = syntheticKeyName(provider.id);
|
|
64
|
+
argv.push("-c", `${table}.env_key=${tomlString(name)}`);
|
|
65
|
+
env[name] = provider.auth.value;
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
// The seeded shape — the runtime's own auth.json already holds this key.
|
|
69
|
+
argv.push("-c", `${table}.requires_openai_auth=true`);
|
|
70
|
+
}
|
|
71
|
+
// Top-level defaults for this child, so a thread that does not restate the
|
|
72
|
+
// provider still lands on the right one.
|
|
73
|
+
argv.push("-c", `model_provider=${tomlString(provider.id)}`);
|
|
74
|
+
const catalog = writeProviderCatalog(worldHome, codexHome, provider);
|
|
75
|
+
if (catalog !== undefined)
|
|
76
|
+
argv.push("-c", `model_catalog_json=${tomlString(catalog)}`);
|
|
77
|
+
return { argv, env };
|
|
78
|
+
}
|