@openclaw/codex 2026.9.1 → 2026.9.3

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 (109) hide show
  1. package/README.md +2 -0
  2. package/dist/api.js +18 -23
  3. package/dist/apply-B6el6hdO.js +357 -0
  4. package/dist/{attempt-client-cleanup-DYHcRQAa.js → attempt-client-cleanup-D6cR54TV.js} +113 -49
  5. package/dist/{attempt-context-DmQUNWwT.js → attempt-context-AO4DSjE0.js} +11 -9
  6. package/dist/{event-projector-usage-C5mcrGjp.js → attempt-notifications--H8zXR5-.js} +3 -89
  7. package/dist/auth-cache-key-Kq6oerr6.js +498 -0
  8. package/dist/auth-profile-CwzO4_RG.js +43 -0
  9. package/dist/auth-profile-selection-DFu9e167.js +45 -0
  10. package/dist/{binding-connection-E6uDsPlx.js → binding-connection-QqgcPCgk.js} +18 -3
  11. package/dist/{bounded-turn-wzJrwKKe.js → bounded-turn-lRpmZHFv.js} +54 -150
  12. package/dist/build-state-6RL6qohz.js +19 -0
  13. package/dist/{capabilities-dIjNVCYH.js → capabilities-BeqLPbtM.js} +2 -1
  14. package/dist/cli-metadata.js +1 -1
  15. package/dist/client-BEKu4yDx.js +3983 -0
  16. package/dist/command-dispatch-CisT9Jqq.js +21 -0
  17. package/dist/{command-formatters-CLHhEB1Q.js → command-formatters-DeTfrapr.js} +2 -2
  18. package/dist/{command-handlers-CTGb2csu.js → command-handlers-BfIsJEuA.js} +158 -76
  19. package/dist/command-rpc-BMqRQOFX.js +226 -0
  20. package/dist/{compact-_t0HQrUS.js → compact-CGJZ2rlb.js} +89 -49
  21. package/dist/config-JDfTI4VI.js +106 -0
  22. package/dist/{config-BhmfC1s6.js → config-options-jnIFvwxD.js} +208 -654
  23. package/dist/config-runtime-BWf6JLWG.js +11 -0
  24. package/dist/config-utils-C57JiJrU.js +69 -0
  25. package/dist/conversation-binding-CxOlHiix.js +889 -0
  26. package/dist/{plugin-marketplace-discovery-CfFlKqDl.js → conversation-control-CUCrSIQI.js} +36 -155
  27. package/dist/doctor-contract-api.js +8 -9
  28. package/dist/{dynamic-tools-BU9tmlYm.js → dynamic-tools-D-JBoaLt.js} +734 -698
  29. package/dist/{effective-mcp-catalog-DzYBW4h1.js → effective-mcp-catalog-J_5Ep5Um.js} +4 -3
  30. package/dist/{elicitation-input-DMkeki8d.js → elicitation-input-DPoK8F7w.js} +8 -22
  31. package/dist/ephemeral-turn-DSwzP8YY.js +101 -0
  32. package/dist/{event-projector-assistant-message-DHRFXKbS.js → event-projector-assistant-message-BmBM4qBV.js} +23 -27
  33. package/dist/event-projector-usage-CIyrYYid.js +102 -0
  34. package/dist/{harness-DXVZ5II5.js → harness-FR6eQgyO.js} +47 -17
  35. package/dist/harness.js +1 -1
  36. package/dist/history-rejection-B4nOXNXF.js +13 -0
  37. package/dist/{image-payload-sanitizer-CnfoUPCE.js → image-payload-sanitizer-tupAr-2o.js} +29 -15
  38. package/dist/incognito-session-uhrBF6wJ.js +15 -0
  39. package/dist/index.js +413 -2893
  40. package/dist/{isolated-completion-kg9kv4iH.js → isolated-completion-DHBefrzg.js} +12 -21
  41. package/dist/{managed-binary-4-Vjz5GH.js → managed-binary-DrjjRRUD.js} +17 -84
  42. package/dist/managed-thread-store-D1t5jh3G.js +66 -0
  43. package/dist/media-understanding-provider.js +4 -1
  44. package/dist/{model-catalog-CUM68Hkl.js → model-catalog-B_6M04Wo.js} +6 -5
  45. package/dist/{models-sYnEc0gd.js → models-P9k2qAof.js} +4 -4
  46. package/dist/native-execution-policy-umd0tgh4.js +128 -0
  47. package/dist/{native-subagent-monitor-CnH147jH.js → native-subagent-monitor-BbCUKRwC.js} +76 -48
  48. package/dist/node-cli-sessions-rj0ysJwM.js +527 -0
  49. package/dist/{node-exec-server.runtime-CstNHCmC.js → node-exec-server.runtime-BY_ctYnT.js} +54 -23
  50. package/dist/plan-BMJdMOEF.js +711 -0
  51. package/dist/plugin-activation-BQK-f5sV.js +133 -0
  52. package/dist/{thread-resume-C7pyVKeW.js → plugin-app-cache-key-CdSQzWyX.js} +5 -53
  53. package/dist/{plugin-approval-roundtrip-CNe-Xrjx.js → plugin-approval-roundtrip-DeW95wB5.js} +1 -1
  54. package/dist/plugin-inventory-CoRCzWW4.js +325 -0
  55. package/dist/plugin-marketplace-discovery-3akBizzF.js +134 -0
  56. package/dist/{plugin-metadata-cache-BFrPhb2c.js → plugin-metadata-cache-DgNfRAGA.js} +13 -9
  57. package/dist/protocol-CAAcVIKF.js +275 -0
  58. package/dist/{provider-capabilities-DW5p4k9w.js → provider-capabilities-W4tfK5Y5.js} +2 -2
  59. package/dist/{rate-limits-CawQJfUS.js → rate-limits-Bqnx1N4z.js} +1 -1
  60. package/dist/request-CGvGOpeR.js +198 -0
  61. package/dist/{run-attempt-D1hJO4fX.js → run-attempt-DwKds3DN.js} +1498 -1028
  62. package/dist/{runtime-artifact-C3jVimFn.js → runtime-artifact-T-NwqeSH.js} +28 -28
  63. package/dist/sandbox-guard-BcT66fWy.js +165 -0
  64. package/dist/{session-binding-BHuTCRZQ.js → session-binding-CKSepwIC.js} +118 -324
  65. package/dist/session-binding-record-CaZjYwNS.js +256 -0
  66. package/dist/session-catalog-HaDcp7Sv.js +1533 -0
  67. package/dist/session-catalog-adoption-BKLtSrwi.js +251 -0
  68. package/dist/session-catalog-archive-D0i2pGj2.js +56 -0
  69. package/dist/session-catalog-home-id-D7-aLiNt.js +190 -0
  70. package/dist/session-catalog-node-adoption-BUuDYY8R.js +182 -0
  71. package/dist/session-catalog-node-continue-CBtc4wkI.js +238 -0
  72. package/dist/session-catalog-parsing-CdD3JhdM.js +280 -0
  73. package/dist/session-catalog-provenance-DkJHo735.js +124 -0
  74. package/dist/{session-cli-CmFEXMAM.js → session-cli-CbgaHh0f.js} +3 -2
  75. package/dist/session-history-Cz-tOOYj.js +96 -0
  76. package/dist/{session-upstream-marker-C351-5Qw.js → session-history-import-DFN7sWRU.js} +5 -49
  77. package/dist/session-history-read-cxPUxyVV.js +50 -0
  78. package/dist/session-history-worker-runtime.js +60 -0
  79. package/dist/{settled-turn-context-D3SNWtUn.js → session-history.worker-CNEvGaU5.js} +75 -69
  80. package/dist/session-history.worker.js +2 -0
  81. package/dist/{session-initialization-BeWzjGiR.js → session-initialization-Jo86C60I.js} +2 -1
  82. package/dist/{session-permission-policy-DeWVTCMj.js → session-permission-policy-B22InTp_.js} +4 -7
  83. package/dist/{session-retirement-BujDjXVF.js → session-retirement-BSNG_mhf.js} +8 -7
  84. package/dist/session-upstream-marker-D15C9NHp.js +46 -0
  85. package/dist/settled-turn-context-Du6gdUDd.js +45 -0
  86. package/dist/{settled-turn-finalizer-BVJx4yoc.js → settled-turn-finalizer-BuLUrZl2.js} +54 -42
  87. package/dist/shared-client-CVhez2Uo.js +2911 -0
  88. package/dist/{side-question-BTZAII4l.js → side-question-DLbr2vUU.js} +135 -191
  89. package/dist/source-Da-h6f7e.js +518 -0
  90. package/dist/thread-archive-guard-D1bP04Tf.js +53 -0
  91. package/dist/{thread-lifecycle-DAcEJ_Om.js → thread-lifecycle-D1pzRwHB.js} +467 -977
  92. package/dist/{thread-ownership-zGokd8i1.js → thread-ownership-D6oASVRu.js} +15 -17
  93. package/dist/{thread-policy-g4KbJPzp.js → thread-policy-D8kI7yAO.js} +2 -2
  94. package/dist/thread-resume-T5cveyxA.js +52 -0
  95. package/dist/timeout-BVw8aaM1.js +33 -0
  96. package/dist/transcript-mirror-attestation-DibE0krH.js +89 -0
  97. package/dist/{transcript-mirror-DTUxFWa_.js → transcript-mirror-t5TOccct.js} +111 -379
  98. package/dist/{transport-stdio-CyPldczm.js → transport-stdio-BGjHoYLr.js} +80 -48
  99. package/dist/{upstream-session-fork-CYlBIGVt.js → upstream-session-fork-De-sLJ2r.js} +94 -166
  100. package/dist/{usage-Bj-rrzkR.js → usage-CPPTmBvZ.js} +4 -3
  101. package/dist/version-omm6IPI3.js +12 -0
  102. package/dist/{web-search-provider.runtime-D2FWSK4w.js → web-search-provider.runtime-CSVgQL0w.js} +3 -3
  103. package/openclaw.plugin.json +22 -1
  104. package/package.json +6 -6
  105. package/dist/request-DYAI5FQE.js +0 -475
  106. package/dist/session-catalog-yyvTWFOw.js +0 -3120
  107. package/dist/session-history-C5J1AKzG.js +0 -87
  108. package/dist/shared-client-DxcfF9KX.js +0 -7494
  109. package/dist/{auth-binding-Ds_QVm-X.js → auth-binding-Co2Vfcf_.js} +1 -1
@@ -1,13 +1,17 @@
1
1
  import { n as normalizeCodexAppServerArgs } from "./launch-args-RXQwn8zV.js";
2
- import { readFile, readdir } from "node:fs/promises";
3
2
  import { createHash, randomUUID } from "node:crypto";
4
- import { materializeWindowsSpawnProgram, resolveWindowsSpawnProgram } from "openclaw/plugin-sdk/windows-spawn";
5
3
  import { z } from "zod";
6
- import { execFile, spawn } from "node:child_process";
4
+ import { materializeWindowsSpawnProgram, resolveWindowsSpawnProgram } from "openclaw/plugin-sdk/windows-spawn";
5
+ import { readFile, readdir } from "node:fs/promises";
7
6
  import { once } from "node:events";
7
+ import { execFile, spawn } from "node:child_process";
8
8
  import { setImmediate } from "node:timers/promises";
9
9
  import { finished } from "node:stream/promises";
10
10
  //#region extensions/codex/src/app-server/transport-process-snapshot.ts
11
+ /** A zombie leader can still own running threads, reported by the ps-style l flag. */
12
+ function isDeadProcessState(state) {
13
+ return state.startsWith("Z") && !state.includes("l");
14
+ }
11
15
  const PROCESS_COLUMNS = "pid=,ppid=,pgid=,stat=,lstart=";
12
16
  const MAX_PROCESS_CONTAINMENT_MS$1 = 2e3;
13
17
  const PROCESS_INSPECTION_MAX_BYTES = 8388608;
@@ -178,13 +182,17 @@ async function readLinuxProcesses(selected, deadline) {
178
182
  const pgid = Number(fields[2]);
179
183
  const startTicks = fields[19];
180
184
  if (commEnd < 0 || ![ppid, pgid].every(Number.isSafeInteger) || selected !== void 0 && (pgid <= 0 || ppid < 0) || !/^\d+$/.test(startTicks ?? "")) throw new ProcessInspectionError("unavailable");
181
- if (pgid > 0) rows.push({
182
- pid: Number(entry),
183
- ppid,
184
- pgid,
185
- state: fields[0],
186
- startedAt: `${bootId}:${startTicks}`
187
- });
185
+ if (pgid > 0) {
186
+ const threads = Number(fields[17]);
187
+ if (!/^[1-9]\d*$/.test(fields[17] ?? "") || !Number.isSafeInteger(threads)) throw new ProcessInspectionError("unavailable");
188
+ rows.push({
189
+ pid: Number(entry),
190
+ ppid,
191
+ pgid,
192
+ state: `${fields[0]}${threads > 1 ? "l" : ""}`,
193
+ startedAt: `${bootId}:${startTicks}`
194
+ });
195
+ }
188
196
  }
189
197
  if (Date.now() >= deadline) throw new ProcessInspectionError("deadline");
190
198
  return rows;
@@ -197,14 +205,10 @@ async function readLinuxProcesses(selected, deadline) {
197
205
  const MAX_CONTAINED_PROCESSES = 512;
198
206
  const MAX_PROCESS_CONTAINMENT_MS = 2e3;
199
207
  const MAX_PROCESS_QUIESCE_PASSES = 16;
200
- async function terminateCodexAppServerDescendants(child) {
201
- const contained = await containDescendants(child);
202
- return contained === "exited" ? contained : contained?.resume;
203
- }
204
- /** A durable spawn fact, never a command-line match, selects the orphan root. */
208
+ /** Discharges the registered root obligation, including an already-obsolete PID. */
205
209
  async function terminateCodexAppServerOrphan(expected) {
206
210
  const deadline = Date.now() + MAX_PROCESS_CONTAINMENT_MS;
207
- const result = await containDescendants({
211
+ const result = await terminateCodexAppServerDescendants({
208
212
  pid: expected.pid,
209
213
  kill: (signal) => signalProcess(expected.pid, signal ?? "SIGTERM")
210
214
  }, expected, deadline);
@@ -219,7 +223,7 @@ async function terminateCodexAppServerOrphan(expected) {
219
223
  const snapshot = await readCodexAppServerProcessSnapshot(deadline).catch(() => void 0);
220
224
  if (!snapshot?.some((row) => row.pid === process.pid)) return false;
221
225
  const current = snapshot.find((row) => row.pid === expected.pid);
222
- if (!current || !hasSameIdentity(current, expected) || current.state.startsWith("Z")) {
226
+ if (!current || !hasSameIdentity(current, expected) || isDeadProcessState(current.state)) {
223
227
  gone = true;
224
228
  return true;
225
229
  }
@@ -233,15 +237,15 @@ async function terminateCodexAppServerOrphan(expected) {
233
237
  if (contained && !gone) await signalSameRoot(contained.root, "SIGCONT", Date.now() + MAX_PROCESS_CONTAINMENT_MS);
234
238
  }
235
239
  }
236
- async function containDescendants(child, expected, deadline = Date.now() + MAX_PROCESS_CONTAINMENT_MS) {
240
+ async function terminateCodexAppServerDescendants(child, expected, deadline = Date.now() + MAX_PROCESS_CONTAINMENT_MS) {
237
241
  const rootPid = child.pid;
238
242
  if (hasExited(child)) return "exited";
239
243
  if (process.platform === "win32" || !rootPid || !child.kill) return;
240
244
  const snapshot = await readCodexAppServerProcessSnapshot(deadline).catch(() => void 0);
241
245
  if (!snapshot || Date.now() >= deadline) return;
242
246
  const root = snapshot.find((row) => row.pid === rootPid);
243
- if (!expected && (!root || root.state.startsWith("Z"))) return "exited";
244
- if (!root || !(expected ? isSameLiveProcess(root, expected) : root.ppid === process.pid) || root.state.startsWith("Z")) return;
247
+ if (!expected && (!root || isDeadProcessState(root.state))) return "exited";
248
+ if (!root || !(expected ? isSameLiveProcess(root, expected) : root.ppid === process.pid) || isDeadProcessState(root.state)) return;
245
249
  const initialDescendants = collectDescendants(snapshot, [rootPid]);
246
250
  if (initialDescendants.length > MAX_CONTAINED_PROCESSES) return;
247
251
  const stoppedDescendants = /* @__PURE__ */ new Map();
@@ -252,10 +256,25 @@ async function containDescendants(child, expected, deadline = Date.now() + MAX_P
252
256
  if (!descendants) return;
253
257
  for (const descendant of descendants.toReversed()) {
254
258
  if (Date.now() >= deadline) return;
255
- if (!descendant.state.startsWith("Z")) {
259
+ if (!isDeadProcessState(descendant.state)) {
256
260
  if (!await signalSameProcess(descendant, "SIGKILL", deadline) || Date.now() >= deadline) return;
257
261
  }
258
262
  }
263
+ const remaining = new Map(descendants.map((row) => [row.pid, row]));
264
+ while (remaining.size > 0) {
265
+ const terminationSnapshot = await readCodexAppServerProcessSnapshot(deadline, [root.pid, ...remaining.keys()]).catch(() => void 0);
266
+ if (!terminationSnapshot || Date.now() >= deadline) return;
267
+ const currentRoot = terminationSnapshot.find((row) => row.pid === root.pid);
268
+ if (!currentRoot || !isSameLiveRoot(currentRoot, root, true)) return;
269
+ const currentByPid = new Map(terminationSnapshot.map((row) => [row.pid, row]));
270
+ for (const [pid, retained] of remaining) {
271
+ const current = currentByPid.get(pid);
272
+ if (!current || !hasSameIdentity(current, retained) || isDeadProcessState(current.state)) remaining.delete(pid);
273
+ }
274
+ if (remaining.size > 0) await new Promise((resolve) => {
275
+ setTimeout(resolve, 20);
276
+ });
277
+ }
259
278
  resumeRootOnUnwind = false;
260
279
  let resumed = false;
261
280
  return {
@@ -355,7 +374,7 @@ function collectDescendants(snapshot, rootPids) {
355
374
  return descendants;
356
375
  }
357
376
  function isStoppedState(state) {
358
- return state.startsWith("T") || state.startsWith("t") || state.startsWith("Z");
377
+ return state.startsWith("T") || state.startsWith("t") || isDeadProcessState(state);
359
378
  }
360
379
  function isQuiescedState(state) {
361
380
  return isStoppedState(state) || isUninterruptibleState(state);
@@ -364,7 +383,7 @@ function isUninterruptibleState(state) {
364
383
  return state.startsWith("D") || state.startsWith("U");
365
384
  }
366
385
  function isSameLiveProcess(current, expected) {
367
- return current.pgid === expected.pgid && !current.state.startsWith("Z") && hasSameIdentity(current, expected);
386
+ return current.pgid === expected.pgid && !isDeadProcessState(current.state) && hasSameIdentity(current, expected);
368
387
  }
369
388
  function isSameLiveRoot(current, expected, requireStopped = false) {
370
389
  return current.ppid === expected.ppid && (!requireStopped || isQuiescedState(current.state)) && isSameLiveProcess(current, expected);
@@ -407,6 +426,7 @@ function signalProcess(pid, signal) {
407
426
  }
408
427
  //#endregion
409
428
  //#region extensions/codex/src/app-server/transport-process-registration.ts
429
+ const PROCESS_REGISTRATION_INSPECTION_MS = 1e4;
410
430
  const processIdentity = z.object({
411
431
  pid: z.number().int().positive().safe(),
412
432
  pgid: z.number().int().positive().safe(),
@@ -428,17 +448,17 @@ async function openProcessRegistrationStore() {
428
448
  overflowPolicy: "reject-new"
429
449
  });
430
450
  }
431
- async function reapRegisteredCodexAppServerOrphans(requestedDeadline) {
451
+ async function reapRegisteredCodexAppServerOrphans() {
432
452
  const store = await openProcessRegistrationStore();
433
- const deadline = requestedDeadline ?? Date.now() + 1e4;
453
+ const deadline = Date.now() + PROCESS_REGISTRATION_INSPECTION_MS;
434
454
  for (const entry of store.entries()) {
435
455
  if (Date.now() >= deadline) throw new Error("Codex orphan cleanup exceeded its startup budget. Retry to finish cleanup.");
436
456
  const registration = registrationSchema.parse(entry.value);
437
- const snapshot = await readCodexAppServerProcessSnapshot(void 0, [registration.parent.pid, registration.child.pid]);
457
+ const snapshot = await readCodexAppServerProcessSnapshot(deadline, [registration.parent.pid, registration.child.pid]);
438
458
  const parent = snapshot.find((row) => row.pid === registration.parent.pid);
439
- if (parent?.startedAt === registration.parent.startedAt && !parent.state.startsWith("Z")) continue;
459
+ if (parent?.startedAt === registration.parent.startedAt && !isDeadProcessState(parent.state)) continue;
440
460
  const child = snapshot.find((row) => row.pid === registration.child.pid);
441
- if (registration.child.commandFingerprint !== void 0 && child?.startedAt === registration.child.startedAt && !child.state.startsWith("Z")) {
461
+ if (registration.child.commandFingerprint !== void 0 && child?.startedAt === registration.child.startedAt && !isDeadProcessState(child.state)) {
442
462
  let command;
443
463
  try {
444
464
  command = await readCodexAppServerProcessCommand(child, deadline);
@@ -479,11 +499,12 @@ async function prepareCodexAppServerProcessRegistration() {
479
499
  return async (child) => {
480
500
  await once(child, "spawn");
481
501
  if (!child.pid) throw new ProcessInspectionError("unavailable");
482
- const snapshot = await readCodexAppServerProcessSnapshot(void 0, [child.pid]);
502
+ const deadline = Date.now() + PROCESS_REGISTRATION_INSPECTION_MS;
503
+ const snapshot = await readCodexAppServerProcessSnapshot(deadline, [child.pid]);
483
504
  const parent = snapshot.find((row) => row.pid === process.pid);
484
505
  const spawned = snapshot.find((row) => row.pid === child.pid);
485
506
  if (!parent || !spawned || spawned.ppid !== process.pid) throw new Error("Cannot register the Codex child process: its direct-parent identity is unavailable. Retry.");
486
- const command = await readCodexAppServerProcessCommand(spawned, Date.now() + 2e3);
507
+ const command = await readCodexAppServerProcessCommand(spawned, deadline);
487
508
  if (child.exitCode !== null || child.signalCode !== null) throw new Error("Cannot register the Codex child process command: the child exited during inspection. Retry.");
488
509
  const key = randomUUID();
489
510
  store.register(key, {
@@ -518,38 +539,43 @@ function closeCodexAppServerTransport(child, options = {}) {
518
539
  function beginCodexAppServerTransportClose(child, options) {
519
540
  const current = CODEX_APP_SERVER_TRANSPORT_CLOSES.get(child);
520
541
  if (current) return current;
542
+ let forced = false;
543
+ const forceKill = () => {
544
+ forced = true;
545
+ signalCodexAppServerTransport(child, "SIGKILL");
546
+ };
521
547
  const closure = {
522
548
  closing: (async () => {
523
- if (hasCodexAppServerTransportExited(child)) return true;
549
+ if (hasCodexAppServerTransportExited(child)) return "natural";
524
550
  if (process.platform === "win32" || !child.pid || !child.kill) {
525
- finishCodexAppServerTransportClose(child, options);
526
- return false;
551
+ finishCodexAppServerTransportClose(child, options, forceKill);
552
+ return "uncertain";
527
553
  }
528
- let resumeRoot;
554
+ let contained;
529
555
  try {
530
- const contained = await terminateCodexAppServerDescendants(child);
531
- if (contained === "exited") return true;
532
- resumeRoot = contained;
556
+ contained = await terminateCodexAppServerDescendants(child);
533
557
  } catch {
534
- resumeRoot = void 0;
558
+ contained = void 0;
535
559
  }
560
+ if (contained === "exited") return "natural";
536
561
  try {
537
- finishCodexAppServerTransportClose(child, options, resumeRoot);
562
+ finishCodexAppServerTransportClose(child, options, forceKill, contained?.resume);
538
563
  } catch {
539
- signalCodexAppServerTransport(child, "SIGKILL");
564
+ forceKill();
540
565
  }
541
- return false;
566
+ return contained ? "contained" : "uncertain";
542
567
  })(),
543
- naturalExit: false
568
+ naturalExit: false,
569
+ wasForced: () => forced
544
570
  };
545
571
  CODEX_APP_SERVER_TRANSPORT_CLOSES.set(child, closure);
546
572
  return closure;
547
573
  }
548
- function finishCodexAppServerTransportClose(child, options, resumeRoot) {
574
+ function finishCodexAppServerTransportClose(child, options, killTransport, resumeRoot) {
549
575
  const forceKillDelayMs = options.forceKillDelayMs ?? 1e3;
550
576
  const forceKill = setTimeout(() => {
551
577
  if (hasCodexAppServerTransportExited(child)) return;
552
- signalCodexAppServerTransport(child, "SIGKILL");
578
+ killTransport();
553
579
  }, Math.max(1, forceKillDelayMs));
554
580
  forceKill.unref?.();
555
581
  child.once("exit", () => {
@@ -570,18 +596,24 @@ function finishCodexAppServerTransportClose(child, options, resumeRoot) {
570
596
  child.stderr.unref?.();
571
597
  child.stdin.unref?.();
572
598
  }
573
- /** Closes a transport and waits briefly for an exit event. */
599
+ /** Reports physical settlement separately from confirmed process cleanup. */
574
600
  async function closeCodexAppServerTransportAndWait(child, options = {}) {
575
601
  const drained = options.drainStdio ? Promise.all([child.stdout, child.stderr].map((stream) => finished(stream, { cleanup: true }))).then(() => true, () => false) : void 0;
576
602
  const closure = beginCodexAppServerTransportClose(child, options);
577
- const naturalExit = await closure.closing;
603
+ const containment = await closure.closing;
578
604
  const settled = await waitForCodexAppServerTransportExit(child, options.exitTimeoutMs ?? 2e3, drained);
579
- closure.naturalExit = naturalExit && settled;
605
+ closure.naturalExit = containment === "natural" && settled;
580
606
  if (options.drainStdio) {
581
607
  child.stdout.destroy?.();
582
608
  child.stderr.destroy?.();
583
609
  }
584
- return settled;
610
+ return settled ? {
611
+ exited: true,
612
+ cleanup: containment === "contained" && !closure.wasForced() && child.signalCode == null ? "closed" : "uncertain"
613
+ } : {
614
+ exited: false,
615
+ cleanup: "uncertain"
616
+ };
585
617
  }
586
618
  function hasCodexAppServerTransportExited(child) {
587
619
  return child.exitCode !== null && child.exitCode !== void 0 ? true : child.signalCode !== null && child.signalCode !== void 0;