@junghanacs/entwurf 0.35.0 → 0.36.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/AGENTS.md +2 -2
- package/CHANGELOG.md +338 -0
- package/CONTRIBUTING.md +1 -1
- package/DELIVERY.md +15 -0
- package/FAQ.md +3 -3
- package/README.md +30 -16
- package/VERIFY.md +14 -11
- package/demo/README.md +1 -1
- package/docs/acp-backend-rail.md +29 -3
- package/docs/setup-clean-host.md +31 -23
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/backend-adapter.js +46 -2
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/model-ids.js +67 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/models.js +9 -20
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/codex-fresh-preflight.js +4 -3
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-visible-resume.js +11 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/fresh-call-dispatch.js +27 -1
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/herdr-fresh-call.js +3 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-fresh-call.js +2 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/native-push/codex-ws-client.js +99 -18
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/pi-durable-runtime.js +3 -3
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/resume-launch-identity.js +13 -4
- package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-pi-durable.js +178 -25
- package/mcp/entwurf-bridge/dist/scripts/codex-socket-classify.js +44 -0
- package/mcp/entwurf-bridge/tsconfig.build.json +5 -0
- package/package.json +20 -15
- package/pi/pi-durable/bootstrap.mjs +12 -8
- package/pi/pi-durable/carrier/runtime.js +52 -2
- package/pi/pi-durable/carrier/subagent.js +6 -1
- package/pi/pi-durable/carrier/tui.js +31 -4
- package/pi/pi-durable/carrier-relocation.mjs +2 -2
- package/pi/pi-durable/overlay/upstream-pin.json +79 -36
- package/pi-extensions/lib/acp/backend-adapter.ts +52 -2
- package/pi-extensions/lib/acp/model-ids.js +77 -0
- package/pi-extensions/lib/acp/models.ts +15 -22
- package/pi-extensions/lib/codex-fresh-preflight.ts +4 -3
- package/pi-extensions/lib/entwurf-v2-visible-resume.ts +12 -0
- package/pi-extensions/lib/fresh-call-dispatch.ts +25 -1
- package/pi-extensions/lib/herdr-fresh-call.ts +5 -0
- package/pi-extensions/lib/mux-fresh-call.ts +3 -0
- package/pi-extensions/lib/native-push/codex-ws-client.ts +129 -18
- package/pi-extensions/lib/pi-durable-runtime.ts +4 -4
- package/pi-extensions/lib/resume-launch-identity.ts +12 -4
- package/pi-extensions/meta-bridge-pi-durable.ts +230 -34
- package/run.sh +193 -58
- package/scripts/check-acp-backend-preflight.ts +10 -2
- package/scripts/check-acp-cortex.ts +7 -6
- package/scripts/check-acp-prompt-lifecycle.ts +2 -2
- package/scripts/check-acp-provider-surface.ts +1 -1
- package/scripts/check-acp-session-reuse.ts +5 -5
- package/scripts/check-acp-stop-reason.ts +2 -2
- package/scripts/check-acp-stream-hooks.ts +2 -2
- package/scripts/check-acp-usage-accounting.ts +2 -2
- package/scripts/check-codex-app-server-launch.ts +55 -12
- package/scripts/check-codex-native-push.ts +231 -12
- package/scripts/check-fresh-call-dispatch.ts +47 -4
- package/scripts/check-gate-qualification.ts +8 -6
- package/scripts/check-probe-ordering.ts +13 -6
- package/scripts/check-resume-launch-identity.ts +38 -0
- package/scripts/codex-app-server-launch.sh +54 -29
- package/scripts/codex-socket-classify.ts +46 -0
- package/scripts/emit-pi-durable-carrier.ts +159 -168
- package/scripts/mutants/acp-cortex.json +17 -8
- package/scripts/mutants/acp-set-model-readback.json +28 -0
- package/scripts/mutants/codex-app-server-launch.json +39 -12
- package/scripts/mutants/codex-native.json +15 -0
- package/scripts/mutants/control-send-receipt.json +1 -1
- package/scripts/mutants/fresh-call-dispatch.json +11 -0
- package/scripts/mutants/herdr-dev-checkout.json +70 -0
- package/scripts/mutants/pack-install.json +3 -3
- package/scripts/mutants/pi-durable.json +282 -16
- package/scripts/mutants/pi-floor.json +5 -5
- package/scripts/mutants/resume-launch-identity.json +15 -0
- package/scripts/mutants/v2-visible-resume.json +11 -0
- package/scripts/pi-durable-contact-host.mjs +1 -1
- package/scripts/resolve-acp-bridge.ts +1 -1
- package/scripts/smoke-acp-bundled-mcp-live.ts +1 -1
- package/scripts/smoke-acp-carrier-augment-live.ts +1 -1
- package/scripts/smoke-acp-long-turn-live.ts +1 -1
- package/scripts/smoke-acp-mcp-live.ts +1 -1
- package/scripts/smoke-acp-memory-containment-live.ts +1 -1
- package/scripts/smoke-acp-ordering-probe-live.ts +1 -1
- package/scripts/smoke-acp-overlay-live.ts +1 -1
- package/scripts/smoke-acp-provider-live.ts +1 -1
- package/scripts/smoke-acp-raw-turn-live.ts +1 -1
- package/scripts/smoke-acp-session-reuse-live.ts +1 -1
- package/scripts/smoke-acp-skill-live.ts +1 -1
- package/scripts/smoke-acp-socket-citizen-live.ts +2 -2
- package/scripts/smoke-acp-v2-send-live.ts +1 -1
- package/scripts/smoke-entwurf-chain-live.ts +1 -1
- package/scripts/smoke-mux-lifecycle-live.ts +1 -1
- package/pi/pi-durable/overlay/runtime-contacts.patch +0 -283
|
@@ -3441,6 +3441,7 @@ let manifestCount: number;
|
|
|
3441
3441
|
"acp-launch-namespace": 2,
|
|
3442
3442
|
"acp-overlay": 1,
|
|
3443
3443
|
"acp-prompt-lifecycle": 15,
|
|
3444
|
+
"acp-set-model-readback": 2,
|
|
3444
3445
|
"acp-stop-reason": 6,
|
|
3445
3446
|
"acp-stream-hooks": 10,
|
|
3446
3447
|
"acp-usage-accounting": 12,
|
|
@@ -3449,10 +3450,10 @@ let manifestCount: number;
|
|
|
3449
3450
|
"bridge-boot-resume": 5,
|
|
3450
3451
|
"bridge-command-boot": 12,
|
|
3451
3452
|
"capability-cache": 3,
|
|
3452
|
-
"codex-app-server-launch":
|
|
3453
|
+
"codex-app-server-launch": 10,
|
|
3453
3454
|
"codex-caller-seat": 28,
|
|
3454
3455
|
"control-send-receipt": 19,
|
|
3455
|
-
"codex-native":
|
|
3456
|
+
"codex-native": 83,
|
|
3456
3457
|
"compaction-send-guard": 7,
|
|
3457
3458
|
"control-socket-disconnect": 4,
|
|
3458
3459
|
"demo-reproducibility": 12,
|
|
@@ -3463,10 +3464,10 @@ let manifestCount: number;
|
|
|
3463
3464
|
"pi-bridge-sender": 4,
|
|
3464
3465
|
"pi-mcp-bridge": 2,
|
|
3465
3466
|
"pi-mcp-register": 3,
|
|
3466
|
-
"pi-durable":
|
|
3467
|
+
"pi-durable": 78,
|
|
3467
3468
|
"copilot-receive": 20,
|
|
3468
3469
|
"entwurf-peers": 1,
|
|
3469
|
-
"fresh-call-dispatch":
|
|
3470
|
+
"fresh-call-dispatch": 12,
|
|
3470
3471
|
"fresh-cut": 3,
|
|
3471
3472
|
"gate-qualification": 10,
|
|
3472
3473
|
"herdr-placement": 13,
|
|
@@ -3474,6 +3475,7 @@ let manifestCount: number;
|
|
|
3474
3475
|
"herdr-plugin-profile": 14,
|
|
3475
3476
|
"herdr-activation": 34,
|
|
3476
3477
|
"herdr-plugin-build": 20,
|
|
3478
|
+
"herdr-dev-checkout": 4,
|
|
3477
3479
|
"herdr-runtime-bootstrap": 31,
|
|
3478
3480
|
"herdr-fresh-call": 38,
|
|
3479
3481
|
"herdr-supply": 11,
|
|
@@ -3497,13 +3499,13 @@ let manifestCount: number;
|
|
|
3497
3499
|
"release-gate": 24,
|
|
3498
3500
|
"retired-sent-surface": 2,
|
|
3499
3501
|
"resume-args": 6,
|
|
3500
|
-
"resume-launch-identity":
|
|
3502
|
+
"resume-launch-identity": 7,
|
|
3501
3503
|
"self-address": 8,
|
|
3502
3504
|
"setup-verdict": 14,
|
|
3503
3505
|
"source-install": 2,
|
|
3504
3506
|
"typing-call-fence": 1,
|
|
3505
3507
|
"v2-surface": 13,
|
|
3506
|
-
"v2-visible-resume":
|
|
3508
|
+
"v2-visible-resume": 18,
|
|
3507
3509
|
};
|
|
3508
3510
|
const laneTally: Record<string, number> = {};
|
|
3509
3511
|
for (const man of manifests) laneTally[man.lane] = (laneTally[man.lane] ?? 0) + man.mutants.length;
|
|
@@ -174,7 +174,7 @@ function makeRecordingConnection(calls: RecordedCall[]): AcpConnectionLike {
|
|
|
174
174
|
},
|
|
175
175
|
setSessionConfigOption: async (params) => {
|
|
176
176
|
calls.push({ method: "setSessionConfigOption", params });
|
|
177
|
-
return {};
|
|
177
|
+
return { configOptions: [{ id: "model", currentValue: (params as { value?: unknown }).value }] };
|
|
178
178
|
},
|
|
179
179
|
prompt: async (params) => {
|
|
180
180
|
calls.push({ method: "prompt", params });
|
|
@@ -381,12 +381,19 @@ function makeRecordingConnection(calls: RecordedCall[]): AcpConnectionLike {
|
|
|
381
381
|
"backend.ts still sends the clientInfo the probe mirrors",
|
|
382
382
|
);
|
|
383
383
|
// The claude adapter's enforceModel wire shape — the LIVE probe executes THIS
|
|
384
|
-
// method (emitted twin), so its shape is pinned where it lives.
|
|
384
|
+
// method (emitted twin), so its shape is pinned where it lives. Sliced to the claude
|
|
385
|
+
// adapter: the cortex adapter makes the same call, and must not satisfy this pin.
|
|
386
|
+
const claudeAdapterSrc = ADAPTER_SRC.slice(
|
|
387
|
+
ADAPTER_SRC.indexOf("export const claudeAdapter"),
|
|
388
|
+
ADAPTER_SRC.indexOf("export const cortexAdapter"),
|
|
389
|
+
);
|
|
385
390
|
assert.ok(
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
391
|
+
claudeAdapterSrc.length > 0 &&
|
|
392
|
+
claudeAdapterSrc.includes(
|
|
393
|
+
'await setConfig.call(connection, {\n\t\t\tsessionId: acpSessionId,\n\t\t\tconfigId: "model",\n\t\t\tvalue: nativeModelId,\n\t\t});',
|
|
394
|
+
) &&
|
|
395
|
+
claudeAdapterSrc.includes("confirmClaudeSetModelAnswer(answer, nativeModelId);"),
|
|
396
|
+
'claudeAdapter.enforceModel still sends setSessionConfigOption({configId:"model"}) and reads its answer back',
|
|
390
397
|
);
|
|
391
398
|
|
|
392
399
|
// Permission policy: the runner's copy must mirror backend.ts's private
|
|
@@ -42,6 +42,7 @@ import assert from "node:assert/strict";
|
|
|
42
42
|
import * as fs from "node:fs";
|
|
43
43
|
import * as os from "node:os";
|
|
44
44
|
import * as path from "node:path";
|
|
45
|
+
import { AcpModelNotCuratedError } from "../pi-extensions/lib/acp/model-ids.js";
|
|
45
46
|
import { serializeMetaIdentity, upsertMetaSession } from "../pi-extensions/lib/meta-session.ts";
|
|
46
47
|
import {
|
|
47
48
|
ResumeBackendUnsupportedError,
|
|
@@ -162,6 +163,43 @@ function main(): void {
|
|
|
162
163
|
);
|
|
163
164
|
}
|
|
164
165
|
|
|
166
|
+
// 4d. #128 — the second EXPECTED refusal. Under the `entwurf` provider Pi resolves `--model`
|
|
167
|
+
// by substring, so a retired Claude 5 id would reopen on a Cortex row. The pair judged is the
|
|
168
|
+
// one the launch would EMIT: a bare Claude id recorded under another provider is routed to
|
|
169
|
+
// `entwurf` too, so judging the recorded provider alone would let that one through.
|
|
170
|
+
{
|
|
171
|
+
const acpModelLine = (provider: string, modelId: string): string =>
|
|
172
|
+
`${JSON.stringify({ type: "model_change", provider, modelId })}\n`;
|
|
173
|
+
const settle = (gid: string): { identity?: ReturnType<typeof resolveResumeLaunchIdentity>; err?: unknown } => {
|
|
174
|
+
try {
|
|
175
|
+
return { identity: resolveResumeLaunchIdentity(gid) };
|
|
176
|
+
} catch (err) {
|
|
177
|
+
return { err };
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
const minted = (native: string, name: string, provider: string, modelId: string): string =>
|
|
181
|
+
mintRecord(native, writeTranscript(name, sessionLine(native) + acpModelLine(provider, modelId)));
|
|
182
|
+
const retired = settle(
|
|
183
|
+
minted("0199a5a5-1111-4222-8333-444455556666", "acp-retired.jsonl", "entwurf", "claude-sonnet-5"),
|
|
184
|
+
);
|
|
185
|
+
const routed = settle(
|
|
186
|
+
minted("0199b5b5-1111-4222-8333-444455556666", "acp-routed.jsonl", "anthropic", "claude-opus-5"),
|
|
187
|
+
);
|
|
188
|
+
const current = settle(
|
|
189
|
+
minted("0199c5c5-1111-4222-8333-444455556666", "acp-current.jsonl", "entwurf", "claude-sonnet-5-5"),
|
|
190
|
+
);
|
|
191
|
+
ok(
|
|
192
|
+
"4d: an entwurf-provider resume of a non-curated id is a TYPED refusal — recorded under entwurf, or a bare Claude id the launch would route to entwurf — while the exact 5.5 id resolves unchanged [QK:RESUME-ID-ACP-EXACT-CURATION]",
|
|
193
|
+
retired.err instanceof AcpModelNotCuratedError &&
|
|
194
|
+
retired.err.reason === "acp-model-not-curated" &&
|
|
195
|
+
retired.err.model === "claude-sonnet-5" &&
|
|
196
|
+
routed.err instanceof AcpModelNotCuratedError &&
|
|
197
|
+
routed.err.model === "claude-opus-5" &&
|
|
198
|
+
current.identity?.provider === "entwurf" &&
|
|
199
|
+
current.identity.model === "claude-sonnet-5-5",
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
|
|
165
203
|
const gidNoFile = mintRecord("0199dddd-1111-4222-8333-444455556666", null);
|
|
166
204
|
rejects(gidNoFile, "no recorded transcriptPath", "4: transcriptPath null → nothing to resume");
|
|
167
205
|
|
|
@@ -156,38 +156,53 @@ done
|
|
|
156
156
|
# --- is somebody already listening there? ----------------------------------
|
|
157
157
|
# Three outcomes, and they are NOT the same repair. A live socket means a second server
|
|
158
158
|
# would either lose the bind race or silently replace the endpoint every citizen's record
|
|
159
|
-
# already points at — refuse and name the holder. An indeterminate path (symlink
|
|
160
|
-
# socket, owned by another uid) is
|
|
161
|
-
#
|
|
162
|
-
#
|
|
163
|
-
#
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
159
|
+
# already points at — refuse and name the holder. An indeterminate path (a symlink that is not
|
|
160
|
+
# Codex's own alias, not a socket, owned by another uid) is refused, because a launcher that
|
|
161
|
+
# guessed past it would be clobbering something it cannot identify. A dead socket file is the
|
|
162
|
+
# ordinary leftover of a Ctrl-C, and the vendor replaces it — that one is a fact line, not a
|
|
163
|
+
# refusal. So is a dangling rendezvous alias: from Codex 0.162.1 the advertised path is a
|
|
164
|
+
# symlink into the vendor's own socket directory, and the vendor removes exactly that alias
|
|
165
|
+
# when it starts.
|
|
166
|
+
#
|
|
167
|
+
# WHAT A LAUNCH IS ALLOWED TO TRUST is decided ONCE, by the classifier delivery and preflight
|
|
168
|
+
# use (`checkCodexSocketFile`). This launcher keeps no copy of it: telling Codex's exact alias
|
|
169
|
+
# from any other symlink takes a hash and an exact readlink comparison, and a second
|
|
170
|
+
# implementation here would be the transcription `codex-socket-path` already measured drifting.
|
|
171
|
+
# It runs that classifier's COMPILED twin directly with `node`, in a checkout and in an installed
|
|
172
|
+
# package alike: `build-bridge` emits it (`pnpm install` runs it through `prepare`, and the package
|
|
173
|
+
# ships it through `prepack`), so a missing file is an incomplete installation, refused by name —
|
|
174
|
+
# never a reason to fall back to the TypeScript source. The Python below only CONNECTS to the
|
|
175
|
+
# endpoint the classifier verified, to tell a live server from a stale socket file. An answer the
|
|
176
|
+
# classifier never gives is refused right here, before it can be read as one of the probe's own
|
|
177
|
+
# verdicts.
|
|
178
|
+
#
|
|
179
|
+
# The gate's limit, stated rather than hidden: it executes this launcher on non-alias layouts
|
|
180
|
+
# and on a non-exact symlink, so it proves the launcher accepts no more than the classifier.
|
|
181
|
+
# The exact-alias accept path is proven on `checkCodexSocketFile` itself, with a sandbox socket
|
|
182
|
+
# directory. This launcher's own alias branch is NOT exercised by an existing-server LIVE
|
|
183
|
+
# diagnostic; that launch/refusal path needs its own explicitly authorised LIVE observation.
|
|
184
|
+
CLASSIFIER="$REPO_DIR/mcp/entwurf-bridge/dist/scripts/codex-socket-classify.js"
|
|
185
|
+
[ -f "$CLASSIFIER" ] \
|
|
186
|
+
|| fail "codex-app-server-classifier-missing: the compiled socket classifier is not at
|
|
187
|
+
$CLASSIFIER
|
|
188
|
+
This launcher runs it directly and keeps no other copy of it. Reinstall @junghanacs/entwurf (the
|
|
189
|
+
package ships it through prepack build-bridge), or run 'pnpm run build-bridge' in a source checkout."
|
|
190
|
+
if ! classified="$(node "$CLASSIFIER")"; then
|
|
191
|
+
fail "could not classify the control socket at $SOCK.
|
|
192
|
+
'node $CLASSIFIER' failed; it is the only classification of this socket,
|
|
193
|
+
and this launcher will not guess past it. Its output above says why."
|
|
194
|
+
fi
|
|
195
|
+
classified_word="${classified%% *}"
|
|
196
|
+
classified_detail="${classified#* }"
|
|
197
|
+
case "$classified_word" in
|
|
198
|
+
socket)
|
|
199
|
+
probe="$(python3 - "$classified_detail" <<'PY'
|
|
200
|
+
import socket, sys
|
|
186
201
|
|
|
187
202
|
probe = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
|
188
203
|
probe.settimeout(2)
|
|
189
204
|
try:
|
|
190
|
-
probe.connect(
|
|
205
|
+
probe.connect(sys.argv[1])
|
|
191
206
|
except (ConnectionRefusedError, FileNotFoundError):
|
|
192
207
|
print("stale")
|
|
193
208
|
except OSError as exc:
|
|
@@ -197,7 +212,17 @@ else:
|
|
|
197
212
|
finally:
|
|
198
213
|
probe.close()
|
|
199
214
|
PY
|
|
200
|
-
)" || fail "could not
|
|
215
|
+
)" || fail "could not probe the control socket at $classified_detail (python3 is required by this launcher)."
|
|
216
|
+
;;
|
|
217
|
+
absent) probe="absent" ;;
|
|
218
|
+
dangling) probe="stale $classified_detail" ;;
|
|
219
|
+
indeterminate) probe="indeterminate $classified_detail" ;;
|
|
220
|
+
*)
|
|
221
|
+
fail "codex-app-server-socket-probe-unrecognised: the socket classifier answered
|
|
222
|
+
'$classified_word', which is not one of socket/absent/dangling/indeterminate. Refusing to launch on a
|
|
223
|
+
reading nothing understands."
|
|
224
|
+
;;
|
|
225
|
+
esac
|
|
201
226
|
|
|
202
227
|
probe_status="${probe%% *}"
|
|
203
228
|
probe_reason="${probe#* }"
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* codex-socket-classify — classify the Codex app-server default control socket for THIS
|
|
3
|
+
* environment, through the one product classifier, and print the answer for a shell.
|
|
4
|
+
*
|
|
5
|
+
* WHY A LEAF. `entwurf codex-app-server` is a bash launcher, and it has to decide whether a
|
|
6
|
+
* launch would clobber something. From Codex 0.162.1 the advertised socket path is a
|
|
7
|
+
* rendezvous alias into a vendor-owned directory, and telling the vendor's exact alias from any
|
|
8
|
+
* other symlink takes a hash, an exact readlink comparison and ownership/mode checks. Doing that
|
|
9
|
+
* in the launcher's Python would be a second implementation of a security classification, and
|
|
10
|
+
* `codex-socket-path.ts` records what a second spelling of this socket did once (it diverged).
|
|
11
|
+
* So the launcher asks `checkCodexSocketFile`, the classifier delivery and preflight use, and
|
|
12
|
+
* only connects to what it was told.
|
|
13
|
+
*
|
|
14
|
+
* HOW IT IS REACHED. The launcher runs this file's COMPILED twin,
|
|
15
|
+
* `mcp/entwurf-bridge/dist/scripts/codex-socket-classify.js`, directly with `node` — in a checkout
|
|
16
|
+
* and in an installed package alike. There is no `run.sh` verb and no `run_ts` crossing for it:
|
|
17
|
+
* `build-bridge` emits it (`pnpm install` runs that through `prepare`, packing through `prepack`),
|
|
18
|
+
* and a missing twin is an incomplete installation the launcher refuses by name.
|
|
19
|
+
*
|
|
20
|
+
* One line on stdout, a word then a tab-separated detail:
|
|
21
|
+
* socket <connectPath> a verified socket; the launcher connects there to tell live from stale
|
|
22
|
+
* absent nothing at the advertised path
|
|
23
|
+
* dangling <reason> Codex's own alias whose socket is gone; the vendor removes it on start
|
|
24
|
+
* indeterminate <reason> anything else; the launcher refuses
|
|
25
|
+
*
|
|
26
|
+
* Reads `process.env` and takes no argument, for the reason `codex-socket-path.ts` gives: an argv
|
|
27
|
+
* seam would be a way to redirect the address. It has no daemon-root input either; the gate's
|
|
28
|
+
* exact-alias cells drive `checkCodexSocketFile` directly with a sandbox root.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
import {
|
|
32
|
+
checkCodexSocketFile,
|
|
33
|
+
resolveCodexDefaultSocketPath,
|
|
34
|
+
} from "../pi-extensions/lib/native-push/codex-ws-client.ts";
|
|
35
|
+
|
|
36
|
+
if (process.argv.length > 2) {
|
|
37
|
+
console.error("usage: codex-socket-classify (no arguments; the environment is the input)");
|
|
38
|
+
process.exit(2);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const oneLine = (text: string): string => text.replace(/[\t\r\n]+/g, " ");
|
|
42
|
+
const check = checkCodexSocketFile(resolveCodexDefaultSocketPath(process.env));
|
|
43
|
+
if (check.ok) process.stdout.write(`socket\t${check.connectPath}`);
|
|
44
|
+
else if (check.status === "dead" && check.layout === "absent") process.stdout.write("absent");
|
|
45
|
+
else if (check.status === "dead") process.stdout.write(`dangling\t${oneLine(check.reason)}`);
|
|
46
|
+
else process.stdout.write(`indeterminate\t${oneLine(check.reason)}`);
|