@openclaw/codex 2026.9.1-beta.1 → 2026.9.2

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 (81) hide show
  1. package/dist/api.js +8 -9
  2. package/dist/{attempt-client-cleanup-bfsmcQ6m.js → attempt-client-cleanup-Bp1ZOnk2.js} +105 -75
  3. package/dist/attempt-context-CSazkWns.js +634 -0
  4. package/dist/{auth-binding-B4FfbcCg.js → auth-binding-Ds_QVm-X.js} +18 -3
  5. package/dist/{bounded-turn-B7iBUcuP.js → bounded-turn-DxGJRYbY.js} +53 -57
  6. package/dist/{capabilities-BRMh0aIq.js → capabilities-B1mgvpP8.js} +2 -1
  7. package/dist/cli-metadata.js +1 -1
  8. package/dist/{command-formatters-DEsIufkt.js → command-formatters-DSbGMXA0.js} +5 -4
  9. package/dist/{command-handlers-D_-1_qRp.js → command-handlers-DOJvGv6-.js} +243 -148
  10. package/dist/{compact-BglNFZrQ.js → compact-Y_xBqrHN.js} +109 -65
  11. package/dist/{config-giW8X0QA.js → config-CyapYSji.js} +328 -374
  12. package/dist/config-utils-C57JiJrU.js +69 -0
  13. package/dist/{context-compaction-activity-BOeJf7yo.js → context-compaction-activity-CMla5FPJ.js} +4 -1
  14. package/dist/{conversation-binding-data-CW2GuupV.js → conversation-binding-data-BiodpIzq.js} +2 -1
  15. package/dist/doctor-contract-api.js +144 -14
  16. package/dist/{dynamic-tools-Dnlfa--w.js → dynamic-tools-BwpvTxaX.js} +1119 -1135
  17. package/dist/{effective-mcp-catalog-CTeGrnfO.js → effective-mcp-catalog-CY9Jn4bA.js} +4 -3
  18. package/dist/{event-projector-assistant-message-C5-Ds8mA.js → event-projector-assistant-message-B9kp6iGC.js} +15 -6
  19. package/dist/event-projector-usage-ZqEVbAEY.js +212 -0
  20. package/dist/{harness-Csz0F-DK.js → harness-Czh2Sdoc.js} +65 -52
  21. package/dist/harness.js +1 -1
  22. package/dist/{image-payload-sanitizer-CnfoUPCE.js → image-payload-sanitizer-tupAr-2o.js} +29 -15
  23. package/dist/index.js +495 -457
  24. package/dist/{isolated-completion-Cv6FqygM.js → isolated-completion-CRh-51AK.js} +9 -21
  25. package/dist/{managed-binary-DFYK4DWq.js → managed-binary-DcpnJF9x.js} +117 -80
  26. package/dist/media-understanding-provider.js +1 -1
  27. package/dist/model-catalog-DT5vo6qo.js +101 -0
  28. package/dist/{models-TS3HBU-q.js → models-CcrgSMQR.js} +26 -29
  29. package/dist/{native-subagent-monitor-4Mfq2HDs.js → native-subagent-monitor-B3bvQGcg.js} +63 -122
  30. package/dist/{node-exec-server.runtime-BpWqJO1V.js → node-exec-server.runtime-nfbUOtUB.js} +10 -7
  31. package/dist/{plugin-approval-roundtrip-bUm777tR.js → plugin-approval-roundtrip-aQVdyL5g.js} +30 -3
  32. package/dist/{plugin-marketplace-discovery-B9DvaAG-.js → plugin-marketplace-discovery-B7gHXJ3d.js} +44 -30
  33. package/dist/{plugin-metadata-cache-CTCT3w5L.js → plugin-metadata-cache-BwCLTY_U.js} +6 -6
  34. package/dist/provider-capabilities-BpG9Ltc5.js +101 -0
  35. package/dist/{rate-limits-C5_D8Gmb.js → rate-limits-Fx_l4eNa.js} +3 -2
  36. package/dist/{sandbox-guard-kuWTn9C5.js → request-C8H22rPi.js} +195 -2
  37. package/dist/{run-attempt-DYc0QCBF.js → run-attempt-BzthFQSM.js} +1616 -2634
  38. package/dist/{runtime-artifact-BvyT1uyd.js → runtime-artifact-Bh_gf6-t.js} +22 -15
  39. package/dist/{session-binding-Bcynfd-_.js → session-binding-4Ki04sW-.js} +282 -399
  40. package/dist/session-binding-record-CyaXZvTe.js +270 -0
  41. package/dist/{session-catalog-DaLKVtpH.js → session-catalog-B47uwekb.js} +812 -504
  42. package/dist/{session-cli-DMc4oS2w.js → session-cli-BjLhpmS1.js} +1 -1
  43. package/dist/session-history-DWmMqiqW.js +93 -0
  44. package/dist/session-history-read-LHldwvyh.js +36 -0
  45. package/dist/session-history-worker-runtime.js +48 -0
  46. package/dist/session-history.worker-zZVcx0ME.js +267 -0
  47. package/dist/session-history.worker.js +2 -0
  48. package/dist/session-initialization-BCFVnLL4.js +75 -0
  49. package/dist/{session-permission-policy-BrNH1bjy.js → session-permission-policy-BaueHmSj.js} +2 -2
  50. package/dist/session-retirement-DNdmYdFc.js +97 -0
  51. package/dist/{session-upstream-marker-BIkusb95.js → session-upstream-marker-DReTpGz6.js} +20 -4
  52. package/dist/settled-turn-context-BOM3Y1pl.js +45 -0
  53. package/dist/settled-turn-finalizer-BI-b1sry.js +115 -0
  54. package/dist/{shared-client-DKz23hHY.js → shared-client-CKhX2kFt.js} +3659 -847
  55. package/dist/{side-question-DjA_jsNe.js → side-question-B6DWAw1A.js} +168 -81
  56. package/dist/{thread-lifecycle-L7oEkTlq.js → thread-lifecycle-DPK30jad.js} +2412 -2145
  57. package/dist/{thread-ownership-DZeuKH1j.js → thread-ownership-CbucAmmp.js} +27 -16
  58. package/dist/thread-policy-CTalhWFy.js +105 -0
  59. package/dist/{plugin-app-cache-key-C1CAdfcP.js → thread-resume-BLgqkUc1.js} +61 -9
  60. package/dist/{transcript-mirror-DsCMWBca.js → transcript-mirror-_njEB84z.js} +114 -110
  61. package/dist/transcript-mirror-attestation-Byl34PC-.js +76 -0
  62. package/dist/transport-stdio-CzTngV0j.js +728 -0
  63. package/dist/{upstream-prompt-provenance-CFmsKwr9.js → upstream-prompt-provenance-LphB8slG.js} +8 -4
  64. package/dist/upstream-session-fork-1fwbNKzQ.js +886 -0
  65. package/dist/{usage-ROIaW3wo.js → usage-i9fv5-4m.js} +3 -3
  66. package/dist/{web-search-provider.runtime-ClaNPV7N.js → web-search-provider.runtime-DKQn67A7.js} +3 -3
  67. package/openclaw.plugin.json +1 -30
  68. package/package.json +6 -6
  69. package/dist/binding-connection-BMvPX73o.js +0 -45
  70. package/dist/command-rpc-CCeCkf_v.js +0 -90
  71. package/dist/event-projector-usage-Bk1I90Bg.js +0 -328
  72. package/dist/incognito-session-ET_ufDH-.js +0 -2
  73. package/dist/model-catalog-i9rNBthX.js +0 -48
  74. package/dist/protocol-validators-VeJxxJ0U.js +0 -2421
  75. package/dist/request-DXXGHko0.js +0 -157
  76. package/dist/session-catalog-home-id-BNwAJ9D7.js +0 -18
  77. package/dist/session-retirement-CcNC3YSY.js +0 -36
  78. package/dist/settled-turn-finalizer-Dc3ApjU4.js +0 -328
  79. package/dist/thread-resume-BE9qNEW0.js +0 -30
  80. package/dist/transport-stdio-DhoGy33Z.js +0 -99
  81. package/dist/upstream-session-fork-DlaHxSLC.js +0 -326
package/dist/api.js CHANGED
@@ -1,16 +1,15 @@
1
- import { a as resolveCodexAppServerStartOptionsForAgent, i as resolveCodexAppServerRuntimeOptions } from "./config-giW8X0QA.js";
2
- import { a as CODEX_APP_SERVER_VERSION, n as resolveManagedCodexAppServerStartOptions, r as resolveManagedCodexNativeCommand, t as isManagedCodexDesktopCommand } from "./managed-binary-DFYK4DWq.js";
1
+ import { a as resolveCodexAppServerStartOptionsForAgent, i as resolveCodexAppServerRuntimeOptions } from "./config-CyapYSji.js";
2
+ import { n as resolveManagedCodexAppServerStartOptions, o as CODEX_APP_SERVER_VERSION, r as resolveManagedCodexNativeCommand, t as isManagedCodexDesktopCommand } from "./managed-binary-DcpnJF9x.js";
3
+ import { listAgentIds, resolveAgentDir } from "openclaw/plugin-sdk/agent-scope-runtime";
3
4
  import path from "node:path";
4
5
  import { resolveDefaultModelForAgent } from "openclaw/plugin-sdk/agent-runtime";
5
- import { listAgentIds as listAgentIds$1, resolveAgentDir as resolveAgentDir$1 } from "openclaw/plugin-sdk/agent-scope-runtime";
6
6
  import { execFile } from "node:child_process";
7
7
  import { fileURLToPath } from "node:url";
8
8
  import { resolveEffectiveAgentRuntime } from "openclaw/plugin-sdk/command-auth-native";
9
- import { getHealthCheck } from "openclaw/plugin-sdk/health";
10
9
  //#region extensions/codex/src/doctor.ts
11
10
  const CODEX_MANAGED_APP_SERVER_CHECK_ID = "codex/managed-app-server";
12
11
  const CODEX_VERSION_TIMEOUT_MS = 5e3;
13
- const CODEX_VERSION_MAX_BUFFER_BYTES = 64 * 1024;
12
+ const CODEX_VERSION_MAX_BUFFER_BYTES = 65536;
14
13
  function managedCodexFinding(params) {
15
14
  return {
16
15
  checkId: CODEX_MANAGED_APP_SERVER_CHECK_ID,
@@ -68,7 +67,7 @@ function createCodexManagedAppServerHealthCheck(params) {
68
67
  if (start.transport !== "stdio" || start.commandSource !== "managed") return [];
69
68
  const env = ctx.env ?? process.env;
70
69
  let resolved;
71
- for (const agentId of listAgentIds$1(ctx.cfg)) {
70
+ for (const agentId of listAgentIds(ctx.cfg)) {
72
71
  const model = resolveDefaultModelForAgent({
73
72
  cfg: ctx.cfg,
74
73
  agentId
@@ -81,7 +80,7 @@ function createCodexManagedAppServerHealthCheck(params) {
81
80
  }) !== "codex") continue;
82
81
  const agentStart = resolveAgentStartOptions({
83
82
  startOptions: start,
84
- agentDir: resolveAgentDir$1(ctx.cfg, agentId, env),
83
+ agentDir: resolveAgentDir(ctx.cfg, agentId, env),
85
84
  env
86
85
  });
87
86
  try {
@@ -117,7 +116,7 @@ function createCodexManagedAppServerHealthCheck(params) {
117
116
  })];
118
117
  }
119
118
  const detectedVersion = parseCodexVersion(`${output.stdout}\n${output.stderr}`);
120
- if (detectedVersion !== "0.150.1") return [managedCodexFinding({
119
+ if (detectedVersion !== "0.153.4") return [managedCodexFinding({
121
120
  message: detectedVersion ? `Managed Codex app-server version mismatch: expected ${CODEX_APP_SERVER_VERSION}, detected ${detectedVersion}.` : `Managed Codex app-server did not report a parseable version; expected ${CODEX_APP_SERVER_VERSION}.`,
122
121
  path: nativeCommand,
123
122
  requirement: `the exact OpenClaw-pinned Codex version ${CODEX_APP_SERVER_VERSION}`,
@@ -128,7 +127,7 @@ function createCodexManagedAppServerHealthCheck(params) {
128
127
  };
129
128
  }
130
129
  function registerCodexManagedAppServerDoctorChecks$1(host, deps) {
131
- if (getHealthCheck("codex/managed-app-server")) return;
130
+ if (host.getHealthCheck("codex/managed-app-server")) return;
132
131
  host.registerHealthCheck(createCodexManagedAppServerHealthCheck({
133
132
  pluginRoot: host.pluginRoot,
134
133
  deps
@@ -1,10 +1,24 @@
1
- import { G as CodexAppServerRpcError, _ as retireSharedCodexAppServerClientIfCurrent, tt as unsubscribeCodexAppServerLiveThread, vt as isJsonObject } from "./shared-client-DKz23hHY.js";
1
+ import { B as isJsonObject } from "./config-CyapYSji.js";
2
+ import { Nt as unsubscribeCodexAppServerLiveThread, q as CodexAppServerRpcError, y as retireSharedCodexAppServerClientIfCurrent } from "./shared-client-CKhX2kFt.js";
2
3
  import { asFiniteNumber, normalizeOptionalString, normalizeOptionalString as normalizeOptionalString$1, readStringField } from "openclaw/plugin-sdk/string-coerce-runtime";
3
4
  import { createDeferred } from "openclaw/plugin-sdk/extension-shared";
4
5
  import { embeddedAgentLog } from "openclaw/plugin-sdk/agent-harness-runtime";
5
6
  import { redactSensitiveText } from "openclaw/plugin-sdk/logging-core";
6
7
  import { sanitizeTerminalText } from "openclaw/plugin-sdk/text-chunking";
7
8
  //#region extensions/codex/src/app-server/event-projector-values.ts
9
+ const BIO_POLICY_SAFETY_ACCESS_BLOCK_PREFIX = "This content was flagged for possible biological risk.";
10
+ /** Project only Codex's explicit refusal contracts; other policy errors retain their own paths. */
11
+ function readCodexProviderRefusal(message, codexErrorInfo) {
12
+ if (!message) return;
13
+ if (codexErrorInfo === "cyberPolicy") return {
14
+ category: "cyber",
15
+ message
16
+ };
17
+ return message.startsWith(BIO_POLICY_SAFETY_ACCESS_BLOCK_PREFIX) ? {
18
+ category: "bio",
19
+ message
20
+ } : void 0;
21
+ }
8
22
  function readNonEmptyString(record, key) {
9
23
  return normalizeOptionalString$1(record[key]);
10
24
  }
@@ -70,6 +84,10 @@ function readItem(value) {
70
84
  }
71
85
  //#endregion
72
86
  //#region extensions/codex/src/app-server/event-projector-items.ts
87
+ function matchesCodexSnapshotTurn(item, turnId) {
88
+ const itemTurnId = readItemString(item, "turnId");
89
+ return itemTurnId === void 0 || itemTurnId === turnId;
90
+ }
73
91
  function itemKind(item) {
74
92
  switch (item.type) {
75
93
  case "dynamicToolCall":
@@ -330,28 +348,35 @@ var ClientTurnRouter = class {
330
348
  const turnId = requireId(options.turnId, "turn id");
331
349
  if (options.signal?.aborted) return {
332
350
  completion: Promise.resolve(false),
351
+ state: "unconfirmed",
352
+ settledSignal: AbortSignal.abort(),
333
353
  cancel: () => {}
334
354
  };
335
- if (this.routes.get(threadId)?.completedNativeTurnIds.delete(turnId)) return {
355
+ if (this.routes.get(threadId)?.completedNativeTurnIds.has(turnId)) return {
336
356
  completion: Promise.resolve(true),
357
+ state: "confirmed",
358
+ settledSignal: AbortSignal.abort(),
337
359
  cancel: () => {}
338
360
  };
339
361
  const { promise: completion, resolve: settle } = createDeferred();
362
+ const settlement = new AbortController();
340
363
  const watchers = this.nativeTurnCompletionWatchers.get(threadId) ?? /* @__PURE__ */ new Set();
341
364
  this.nativeTurnCompletionWatchers.set(threadId, watchers);
342
- let settled = false;
365
+ let state = "pending";
343
366
  const finish = (completed) => {
344
- if (settled) return;
345
- settled = true;
367
+ if (state !== "pending") return;
368
+ state = completed ? "confirmed" : "unconfirmed";
346
369
  watchers.delete(watcher);
347
370
  if (watchers.size === 0) this.nativeTurnCompletionWatchers.delete(threadId);
348
371
  clearTimeout(timeout);
349
372
  options.signal?.removeEventListener("abort", abort);
373
+ settlement.abort();
350
374
  settle(completed);
351
375
  };
352
376
  const watcher = {
353
377
  turnId,
354
- finish
378
+ finish,
379
+ onStarted: options.onStarted
355
380
  };
356
381
  watchers.add(watcher);
357
382
  const timeout = setTimeout(() => finish(false), Math.max(1, options.timeoutMs));
@@ -360,6 +385,10 @@ var ClientTurnRouter = class {
360
385
  options.signal?.addEventListener("abort", abort, { once: true });
361
386
  return {
362
387
  completion,
388
+ settledSignal: settlement.signal,
389
+ get state() {
390
+ return state;
391
+ },
363
392
  cancel: () => finish(false)
364
393
  };
365
394
  }
@@ -432,6 +461,7 @@ var ClientTurnRouter = class {
432
461
  if (!watchers && !route) return;
433
462
  if (scope.turnId && watchers) {
434
463
  for (const watcher of watchers) if (watcher.turnId === scope.turnId && notification.method === "turn/completed") watcher.finish(true);
464
+ else if (watcher.turnId === scope.turnId && notification.method === "turn/started") watcher.onStarted?.();
435
465
  }
436
466
  if (!route) return;
437
467
  const routeScope = {
@@ -439,12 +469,15 @@ var ClientTurnRouter = class {
439
469
  ...scope.turnId ? { turnId: scope.turnId } : {}
440
470
  };
441
471
  const receivedAtMs = Date.now();
442
- if (route.gate !== "bound" && scope.turnId) {
443
- if (notification.method === "turn/started") route.observedNativeTurn = {
444
- id: scope.turnId,
445
- completed: false
446
- };
447
- else if (notification.method === "turn/completed") {
472
+ if (scope.turnId && (route.gate !== "bound" || scope.turnId === route.turnId)) {
473
+ if (notification.method === "turn/started") {
474
+ route.completedNativeTurnIds.delete(scope.turnId);
475
+ route.observedNativeTurn = {
476
+ id: scope.turnId,
477
+ completed: false
478
+ };
479
+ } else if (notification.method === "turn/completed") {
480
+ if (route.gate === "bound") route.completedNativeTurnIds.clear();
448
481
  route.completedNativeTurnIds.add(scope.turnId);
449
482
  if (!route.observedNativeTurn || route.observedNativeTurn.completed || route.observedNativeTurn.id === scope.turnId) route.observedNativeTurn = {
450
483
  id: scope.turnId,
@@ -560,7 +593,7 @@ var ClientTurnRouter = class {
560
593
  await Promise.race([route.notificationTail, route.ended.promise]);
561
594
  }
562
595
  async drainNotifications(route) {
563
- await route.notificationTail;
596
+ await Promise.race([route.notificationTail, route.ended.promise]);
564
597
  }
565
598
  release(route, error = /* @__PURE__ */ new Error("codex app-server thread route is released")) {
566
599
  if (route.released) return;
@@ -622,8 +655,8 @@ const CODEX_APP_SERVER_INTERRUPT_TIMEOUT_MS = 5e3;
622
655
  const CODEX_APP_SERVER_UNSUBSCRIBE_TIMEOUT_MS = 5e3;
623
656
  const CODEX_NO_ACTIVE_TURN_ERROR_CODE = -32600;
624
657
  const CODEX_NO_ACTIVE_TURN_ERROR_MESSAGE = "no active turn to interrupt";
625
- /** Identifies Codex's exact proof that an interrupt target already finished. */
626
- function isCodexAlreadyTerminalInterruptError(error) {
658
+ /** Codex also reports this before an accepted turn publishes its start event. */
659
+ function isCodexNoActiveTurnInterruptError(error) {
627
660
  return error instanceof CodexAppServerRpcError && error.code === CODEX_NO_ACTIVE_TURN_ERROR_CODE && error.message === CODEX_NO_ACTIVE_TURN_ERROR_MESSAGE;
628
661
  }
629
662
  /** Raised when a thread subscription may be live on a client OpenClaw no longer controls. */
@@ -640,18 +673,10 @@ function isCodexAppServerUnsafeSubscriptionError(error) {
640
673
  function assertCodexThreadResumeSubscription(requestedThreadId, returnedThreadId) {
641
674
  if (returnedThreadId !== requestedThreadId) throw new CodexAppServerUnsafeSubscriptionError(`Codex thread/resume returned ${returnedThreadId} for ${requestedThreadId}`);
642
675
  }
643
- async function closeClientAndWaitIfAvailable(client) {
644
- const closeable = client;
645
- if (typeof closeable.closeAndWait === "function") {
646
- await closeable.closeAndWait();
647
- return;
648
- }
649
- closeable.close?.();
650
- }
651
676
  async function closeCodexStartupClientBestEffort(client) {
652
677
  if (!client) return;
653
678
  const retiredSharedClient = retireSharedCodexAppServerClientIfCurrent(client);
654
- if (!retiredSharedClient || retiredSharedClient.closed) await closeClientAndWaitIfAvailable(client);
679
+ if (!retiredSharedClient || retiredSharedClient.closed) await client.closeAndWait();
655
680
  }
656
681
  /** Retires an unsafe turn client without replacing an already-authoritative failure. */
657
682
  async function retireUnsafeCodexTurnClientBestEffort(client, operation) {
@@ -679,29 +704,75 @@ async function interruptCodexTurnAndWaitBestEffort(client, params) {
679
704
  threadId: params.threadId,
680
705
  turnId: params.turnId
681
706
  };
682
- let completion;
707
+ let cancelWatch;
683
708
  try {
684
- completion = params.turnId ? getCodexAppServerTurnRouter(client).watchNativeTurnCompletion({
709
+ if (!params.turnId) {
710
+ await client.request("turn/interrupt", requestParams, { timeoutMs });
711
+ return true;
712
+ }
713
+ const deadline = Date.now() + timeoutMs;
714
+ const started = createDeferred();
715
+ const completion = getCodexAppServerTurnRouter(client).watchNativeTurnCompletion({
685
716
  threadId: params.threadId,
686
717
  turnId: params.turnId,
687
- timeoutMs
688
- }) : void 0;
689
- await client.request("turn/interrupt", requestParams, { timeoutMs });
690
- return completion ? await completion.completion : true;
718
+ timeoutMs,
719
+ onStarted: () => started.resolve(true)
720
+ });
721
+ cancelWatch = completion.cancel;
722
+ if (completion.state !== "pending") return await completion.completion;
723
+ const requestInterrupt = async () => {
724
+ try {
725
+ await client.request("turn/interrupt", requestParams, {
726
+ timeoutMs: Math.max(1, deadline - Date.now()),
727
+ signal: completion.settledSignal
728
+ });
729
+ return true;
730
+ } catch (error) {
731
+ if (completion.state === "confirmed") return true;
732
+ if (isCodexNoActiveTurnInterruptError(error)) return false;
733
+ throw error;
734
+ }
735
+ };
736
+ if (!await requestInterrupt()) {
737
+ if (await Promise.race([completion.completion.then(() => false), started.promise]) && completion.state === "pending" && Date.now() < deadline) await requestInterrupt();
738
+ }
739
+ return await completion.completion;
691
740
  } catch (error) {
692
- if (isCodexAlreadyTerminalInterruptError(error)) return true;
693
741
  embeddedAgentLog.debug("codex app-server turn interrupt failed during abort", { error });
694
742
  return false;
695
743
  } finally {
696
- completion?.cancel();
744
+ cancelWatch?.();
745
+ }
746
+ }
747
+ /** Stops native terminals on the cancelled thread without retiring peer threads. */
748
+ async function terminateCodexBackgroundTerminals(client, threadId) {
749
+ const options = {
750
+ timeoutMs: CODEX_APP_SERVER_INTERRUPT_TIMEOUT_MS,
751
+ signal: AbortSignal.timeout(CODEX_APP_SERVER_INTERRUPT_TIMEOUT_MS)
752
+ };
753
+ try {
754
+ const { data } = await client.request("thread/backgroundTerminals/list", { threadId }, options);
755
+ for (const { processId } of data) await client.request("thread/backgroundTerminals/terminate", {
756
+ threadId,
757
+ processId
758
+ }, options);
759
+ if (data.length > 0) {
760
+ if ((await client.request("thread/backgroundTerminals/list", {
761
+ threadId,
762
+ limit: 1
763
+ }, options)).data.length > 0) throw new Error("native background terminals remain running");
764
+ }
765
+ } catch (cause) {
766
+ throw new Error("Codex background-terminal cleanup failed; inspect the thread's running terminals before starting more work.", { cause });
697
767
  }
698
768
  }
699
769
  /** Unsubscribes from a thread while swallowing cleanup-only failures. */
700
770
  async function unsubscribeCodexThreadBestEffort(client, params) {
701
771
  try {
702
- await unsubscribeCodexAppServerLiveThread(client, params.threadId, params.timeoutMs);
772
+ await unsubscribeCodexAppServerLiveThread(client, params.threadId, params.timeoutMs, params.assertCurrent);
703
773
  return true;
704
774
  } catch (error) {
775
+ params.assertCurrent?.();
705
776
  embeddedAgentLog.debug("codex app-server thread unsubscribe cleanup failed", {
706
777
  threadId: params.threadId,
707
778
  error
@@ -709,46 +780,5 @@ async function unsubscribeCodexThreadBestEffort(client, params) {
709
780
  return false;
710
781
  }
711
782
  }
712
- /**
713
- * Retires the shared client after a timed-out turn so later runs do not reuse a
714
- * potentially wedged app-server connection.
715
- */
716
- async function retireCodexAppServerClientAfterTimedOutTurn(client, params) {
717
- const retiredSharedClient = retireSharedCodexAppServerClientIfCurrent(client, { failActiveLeases: params.suspectPhysicalClient });
718
- const detachedSharedClient = Boolean(retiredSharedClient);
719
- if (!(params.suspectPhysicalClient && (retiredSharedClient?.closed ?? false))) {
720
- await interruptCodexTurnAndWaitBestEffort(client, {
721
- threadId: params.threadId,
722
- turnId: params.turnId,
723
- timeoutMs: CODEX_APP_SERVER_INTERRUPT_TIMEOUT_MS
724
- });
725
- await unsubscribeCodexThreadBestEffort(client, {
726
- threadId: params.threadId,
727
- timeoutMs: CODEX_APP_SERVER_UNSUBSCRIBE_TIMEOUT_MS
728
- });
729
- }
730
- let closedClient = retiredSharedClient?.closed ?? false;
731
- if (!detachedSharedClient) {
732
- const close = client.close;
733
- if (typeof close === "function") try {
734
- close.call(client);
735
- closedClient = true;
736
- } catch (error) {
737
- embeddedAgentLog.debug("codex app-server client close failed during timeout cleanup", {
738
- threadId: params.threadId,
739
- turnId: params.turnId,
740
- error
741
- });
742
- }
743
- }
744
- embeddedAgentLog.warn("codex app-server client retired after timed-out turn", {
745
- threadId: params.threadId,
746
- turnId: params.turnId,
747
- reason: params.reason,
748
- detachedSharedClient,
749
- closedClient,
750
- activeSharedClientLeases: retiredSharedClient?.activeLeases ?? 0
751
- });
752
- }
753
783
  //#endregion
754
- export { shouldSynthesizeToolProgressForItem as A, readNullableString as B, isSideEffectingNativeToolItem as C, itemTitle as D, itemStatus as E, readItem as F, readItemString as I, readNonEmptyString as L, normalizeOptionalString$1 as M, readCodexErrorNotificationMessage as N, shouldClearTerminalPresentationForNativeItem as O, readHookOutputEntries as P, readNonEmptyStringArray as R, isNonSuccessItemStatus as S, itemName as T, splitPlanText as V, readCodexNotificationTurnId as _, closeCodexStartupClientBestEffort as a, auditNativeToolUnfinishedStatus as b, isCodexAppServerUnsafeSubscriptionError as c, unsubscribeCodexThreadBestEffort as d, CODEX_APP_SERVER_NATIVE_TURN_WAIT_TIMEOUT_MS as f, readCodexNotificationThreadId as g, isCodexNotificationForTurn as h, assertCodexThreadResumeSubscription as i, extractRawAssistantText as j, shouldRecordNativeToolTranscript as k, retireCodexAppServerClientAfterTimedOutTurn as l, CodexProjectionDiagnostics as m, CODEX_APP_SERVER_UNSUBSCRIBE_TIMEOUT_MS as n, interruptCodexTurnAndWaitBestEffort as o, getCodexAppServerTurnRouter as p, CodexAppServerUnsafeSubscriptionError as r, isCodexAlreadyTerminalInterruptError as s, CODEX_APP_SERVER_INTERRUPT_TIMEOUT_MS as t, retireUnsafeCodexTurnClientBestEffort as u, auditNativeToolName as v, itemKind as w, isMutatingNativeToolItem as x, auditNativeToolTerminalStatus as y, readNonNegativeInteger as z };
784
+ export { shouldRecordNativeToolTranscript as A, readNonEmptyStringArray as B, isSideEffectingNativeToolItem as C, itemTitle as D, itemStatus as E, readCodexProviderRefusal as F, readNullableString as H, readHookOutputEntries as I, readItem as L, extractRawAssistantText as M, normalizeOptionalString$1 as N, matchesCodexSnapshotTurn as O, readCodexErrorNotificationMessage as P, readItemString as R, isNonSuccessItemStatus as S, itemName as T, splitPlanText as U, readNonNegativeInteger as V, readCodexNotificationTurnId as _, closeCodexStartupClientBestEffort as a, auditNativeToolUnfinishedStatus as b, isCodexNoActiveTurnInterruptError as c, unsubscribeCodexThreadBestEffort as d, CODEX_APP_SERVER_NATIVE_TURN_WAIT_TIMEOUT_MS as f, readCodexNotificationThreadId as g, isCodexNotificationForTurn as h, assertCodexThreadResumeSubscription as i, shouldSynthesizeToolProgressForItem as j, shouldClearTerminalPresentationForNativeItem as k, retireUnsafeCodexTurnClientBestEffort as l, CodexProjectionDiagnostics as m, CODEX_APP_SERVER_UNSUBSCRIBE_TIMEOUT_MS as n, interruptCodexTurnAndWaitBestEffort as o, getCodexAppServerTurnRouter as p, CodexAppServerUnsafeSubscriptionError as r, isCodexAppServerUnsafeSubscriptionError as s, CODEX_APP_SERVER_INTERRUPT_TIMEOUT_MS as t, terminateCodexBackgroundTerminals as u, auditNativeToolName as v, itemKind as w, isMutatingNativeToolItem as x, auditNativeToolTerminalStatus as y, readNonEmptyString as z };