@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,21 +1,26 @@
1
- import { $t as isJsonObject, B as isCodexAppServerIndeterminateRequestCancellationError, C as withLeasedCodexAppServerClientStartSelectionRetry, Ct as ensureCodexAppServerClientRuntime, Ft as readRecentCodexRateLimits, L as isCodexAppServerApprovalRequest, Q as assertCodexThreadForkResponse, Wt as resolveCodexAppServerPreparedAuthHandoff, _t as resolveCodexToolAbortTerminalReason, c as getLeasedSharedCodexAppServerClient, dt as resolveDynamicToolCallTimeoutMs, it as readCodexTurn, m as releaseCodexAppServerClientLease, nt as readCodexDynamicToolCallParams, ot as createCodexElicitationResponse, st as handleDynamicToolCallWithTimeout, tt as assertCodexTurnStartResponse } from "./shared-client-DxcfF9KX.js";
2
- import { C as isCodexPairedNodeRemoteExecPlacementSandbox, E as readCodexPluginConfig, O as resolveOpenClawExecPolicyForCodexAppServer, T as isCodexSandboxExecServerEnabled, d as shouldAutoApproveCodexAppServerApprovals, f as withMcpElicitationsApprovalPolicy, h as resolveCodexModelBackedReviewerPolicyContext, l as hasCodexMcpToolApprovalOverrides, m as canUseCodexModelBackedApprovalsReviewerForModel, r as resolveCodexAppServerHomeScope, w as isCodexRemoteExecPlacementSandbox, y as readCodexRequirementsToml } from "./config-BhmfC1s6.js";
3
- import { d as sessionBindingIdentity } from "./session-binding-BHuTCRZQ.js";
4
- import { d as unsubscribeCodexThreadBestEffort, h as isCodexNotificationForTurn, l as retireUnsafeCodexTurnClientBestEffort, s as isCodexAlreadyTerminalInterruptError } from "./attempt-client-cleanup-DYHcRQAa.js";
5
- import { B as emitCodexNativePreToolUseFailureDiagnostic, Dt as mergeCodexThreadConfigs, E as resolveCodexAppServerRequestModelSelection, I as buildCodexNativeHookRelayConfig, L as buildCodexNativeHookRelayDisabledConfig, N as CODEX_NATIVE_HOOK_RELAY_EVENTS, O as resolveCodexBindingModelProviderFallback, S as resolveCodexWebSearchPlan, St as buildCodexPluginAppsConfigPatchFromPolicyContext, T as resolveCodexAppServerModelProvider, a as readCodexSupportedReasoningEfforts, at as filterCodexDynamicTools, dt as resolveCodexDynamicToolsLoading, o as resolveCodexAppServerReasoningEffort, t as buildCodexTemporalAdditionalContext, v as buildCodexRuntimeThreadConfig, w as CODEX_NATIVE_PERSONALITY_NONE } from "./thread-lifecycle-DAcEJ_Om.js";
6
- import { s as resolveCodexNativeExecutionBlock } from "./request-DYAI5FQE.js";
7
- import { i as refreshCodexThreadPolicy, n as CodexThreadPolicyHandoffError, r as assertCodexSupervisionThreadLineage } from "./thread-policy-g4KbJPzp.js";
8
- import { n as formatCodexUsageLimitErrorMessage } from "./rate-limits-CawQJfUS.js";
9
- import { a as resolveCodexAppServerForModelProvider, i as resolveCodexSessionPermissionCwd, n as applyCodexSessionPermissionPolicy, r as resolveCodexEffectiveSessionPermissionPolicy, t as CODEX_SESSION_PERMISSION_EXEC_MODES } from "./session-permission-policy-DeWVTCMj.js";
10
- import { n as resolveCodexBindingAppServerConnection, t as requireCodexSupervisionModelSelection } from "./binding-connection-E6uDsPlx.js";
11
- import { C as filterCodexVisionTools, T as CodexNativeToolLifecycleProjector, _ as resolveCodexMessageToolProvider, a as emitDynamicToolStartedDiagnostic, b as shouldEnableCodexAppServerNativeToolSurface, c as ensureCodexSandboxExecServerEnvironment, g as resolveCodexExternalSandboxPolicyForOpenClawSandbox, i as emitDynamicToolErrorDiagnostic, l as releaseCodexSandboxExecServerEnvironment, o as emitDynamicToolTerminalDiagnostic, r as routeCodexAppServerElicitationRequest, s as handleCodexAppServerApprovalRequest, t as createCodexDynamicToolBridge, v as resolveCodexNodePlacementToolConstructionPlan, x as shouldRequireCodexSandboxExecServerEnvironment, y as resolveCodexSandboxEnvironmentSelection } from "./dynamic-tools-BU9tmlYm.js";
12
- import { n as resolveCodexProviderWebSearchSupportForClient } from "./provider-capabilities-DW5p4k9w.js";
1
+ import { l as sessionBindingIdentity } from "./session-binding-record-CaZjYwNS.js";
2
+ import { b as readCodexRequirementsToml, c as hasCodexMcpToolApprovalOverrides, d as withMcpElicitationsApprovalPolicy, i as resolveCodexAppServerHomeScope, m as resolveCodexModelBackedReviewerPolicyContext, u as shouldAutoApproveCodexAppServerApprovals } from "./config-options-jnIFvwxD.js";
3
+ import { b as isCodexSandboxExecServerEnabled, o as isJsonObject, v as isCodexPairedNodeRemoteExecPlacementSandbox, x as readCodexPluginConfig, y as isCodexRemoteExecPlacementSandbox } from "./protocol-CAAcVIKF.js";
4
+ import { D as handleDynamicToolCallWithTimeout, E as createCodexElicitationResponse, L as resolveCodexToolAbortTerminalReason, S as readCodexDynamicToolCallParams, i as isCodexAppServerApprovalRequest, j as resolveDynamicToolCallTimeoutMs, s as isCodexAppServerIndeterminateRequestCancellationError, v as assertCodexThreadForkResponse, x as assertCodexTurnStartResponse } from "./client-BEKu4yDx.js";
5
+ import { n as formatCodexUsageLimitErrorMessage } from "./rate-limits-Bqnx1N4z.js";
6
+ import { n as resolveOpenClawExecPolicyForCodexAppServer, t as canUseCodexModelBackedApprovalsReviewerForModel } from "./config-JDfTI4VI.js";
7
+ import { i as resolveCodexBindingAppServerConnection, r as requireCodexSupervisionModelSelection } from "./binding-connection-QqgcPCgk.js";
8
+ import { F as ensureCodexAppServerClientRuntime, Z as resolveCodexAppServerPreparedAuthHandoff, c as getLeasedSharedCodexAppServerClient, m as releaseCodexAppServerClientLease, q as readRecentCodexRateLimits, x as withLeasedCodexAppServerClientStartSelectionRetry } from "./shared-client-CVhez2Uo.js";
9
+ import { d as unsubscribeCodexThreadBestEffort, l as retireUnsafeCodexTurnClientBestEffort, o as interruptCodexTurnAndWaitBestEffort } from "./attempt-client-cleanup-D6cR54TV.js";
10
+ import { t as CodexEphemeralTurn } from "./ephemeral-turn-DSwzP8YY.js";
11
+ import { B as emitCodexNativePreToolUseFailureDiagnostic, E as resolveCodexAppServerRequestModelSelection, Et as refreshCodexPluginAppApprovalPolicy, I as buildCodexNativeHookRelayConfig, L as buildCodexNativeHookRelayDisabledConfig, N as CODEX_NATIVE_HOOK_RELAY_EVENTS, O as resolveCodexBindingModelProviderFallback, S as resolveCodexWebSearchPlan, T as resolveCodexAppServerModelProvider, Tt as mergeCodexThreadConfigs, a as readCodexSupportedReasoningEfforts, ct as resolveCodexDynamicToolsLoading, nt as filterCodexDynamicTools, o as resolveCodexAppServerReasoningEffort, t as buildCodexTemporalAdditionalContext, v as buildCodexRuntimeThreadConfig, w as CODEX_NATIVE_PERSONALITY_NONE } from "./thread-lifecycle-D1pzRwHB.js";
12
+ import { o as resolveCodexSessionBinding } from "./session-binding-CKSepwIC.js";
13
+ import { i as refreshCodexThreadPolicy, n as CodexThreadPolicyHandoffError, r as assertCodexSupervisionThreadLineage } from "./thread-policy-D8kI7yAO.js";
14
+ import { t as resolveCodexNativeExecutionBlock } from "./sandbox-guard-BcT66fWy.js";
15
+ import { C as shouldRequireCodexSandboxExecServerEnvironment, S as shouldEnableCodexAppServerNativeToolSurface, T as filterCodexVisionTools, a as emitDynamicToolStartedDiagnostic, b as resolveCodexNodePlacementToolConstructionPlan, c as ensureCodexSandboxExecServerEnvironment, d as CodexNativeToolLifecycleProjector, i as emitDynamicToolErrorDiagnostic, l as releaseCodexSandboxExecServerEnvironment, o as emitDynamicToolTerminalDiagnostic, r as routeCodexAppServerElicitationRequest, s as handleCodexAppServerApprovalRequest, t as createCodexDynamicToolBridge, v as resolveCodexExternalSandboxPolicyForOpenClawSandbox, x as resolveCodexSandboxEnvironmentSelection, y as resolveCodexMessageToolProvider } from "./dynamic-tools-D-JBoaLt.js";
16
+ import { n as resolveCodexProviderWebSearchSupportForClient } from "./provider-capabilities-W4tfK5Y5.js";
17
+ import { a as resolveCodexAppServerForModelProvider, i as resolveCodexSessionPermissionCwd, n as applyCodexSessionPermissionPolicy, r as resolveCodexEffectiveSessionPermissionPolicy, t as CODEX_SESSION_PERMISSION_EXEC_MODES } from "./session-permission-policy-B22InTp_.js";
13
18
  import { readStringField } from "openclaw/plugin-sdk/string-coerce-runtime";
14
- import { buildAgentHookContextChannelFields, embeddedAgentLog, formatErrorMessage, registerNativeHookRelay, resolveAgentDir, resolveAttemptSpawnWorkspaceDir, resolveModelAuthMode, resolveSandboxContext, supportsModelTools } from "openclaw/plugin-sdk/agent-harness-runtime";
15
19
  import { randomUUID } from "node:crypto";
20
+ import { resolveSessionAgentIdsStrict } from "openclaw/plugin-sdk/agent-scope-runtime";
16
21
  import { isDeepStrictEqual } from "node:util";
17
22
  import { resolveAgentWorkspaceDir } from "openclaw/plugin-sdk/agent-runtime";
18
- import { resolveSessionAgentIdsStrict } from "openclaw/plugin-sdk/agent-scope-runtime";
23
+ import { buildAgentHookContextChannelFields, embeddedAgentLog, formatErrorMessage, registerNativeHookRelay, resolveAgentDir as resolveAgentDir$2, resolveAttemptSpawnWorkspaceDir, resolveModelAuthMode, resolveSandboxContext, supportsModelTools } from "openclaw/plugin-sdk/agent-harness-runtime";
19
24
  import { loadExecApprovals } from "openclaw/plugin-sdk/exec-approvals-runtime";
20
25
  import { loadCodexBundleMcpApprovalConfig, resolveCodexMcpToolOverridesForAgent } from "openclaw/plugin-sdk/codex-mcp-projection";
21
26
  //#region extensions/codex/src/app-server/side-question.ts
@@ -50,7 +55,15 @@ async function runCodexAppServerSideQuestion(params, options) {
50
55
  agentId: params.agentId,
51
56
  config: params.cfg
52
57
  });
53
- const binding = await options.bindingStore.read(bindingIdentity);
58
+ const hostCapabilities = params.hostCapabilities;
59
+ const { binding, assertCurrent } = await resolveCodexSessionBinding({
60
+ bindingStore: options.bindingStore,
61
+ identity: bindingIdentity,
62
+ config: params.cfg,
63
+ storePath: params.storePath,
64
+ assertCurrent: hostCapabilities.assertActive,
65
+ signal: params.opts?.abortSignal
66
+ });
54
67
  if (!binding?.threadId) throw new Error("Codex /btw needs an active Codex thread. Send a normal message first, then try /btw again.");
55
68
  if (isCodexPairedNodeRemoteExecPlacementSandbox(params.sandbox)) throw new Error("Normal Codex turns are supported on nodes, but /btw is not yet bound to the active placement.");
56
69
  const pluginConfig = readCodexPluginConfig(options.pluginConfig);
@@ -219,10 +232,9 @@ async function runCodexAppServerSideQuestion(params, options) {
219
232
  };
220
233
  let client = await getLeasedSharedCodexAppServerClient(clientOptions);
221
234
  const clientLease = { client };
222
- const collector = new CodexSideQuestionCollector(params, () => readRecentCodexRateLimits(client));
235
+ let collector;
223
236
  const runAbortController = new AbortController();
224
237
  let nativeToolLifecycleProjector;
225
- const pendingNativeToolNotifications = [];
226
238
  const pendingNativePreToolUseFailures = [];
227
239
  let nativePreToolUseFailureFallbackActive = false;
228
240
  let nativeToolRunWasAbortedBeforeCleanup;
@@ -248,26 +260,17 @@ async function runCodexAppServerSideQuestion(params, options) {
248
260
  }
249
261
  flushPendingNativePreToolUseFailures();
250
262
  };
251
- const handleNotification = (notification) => {
252
- collector.handleNotification(notification);
253
- if (notification.method !== "item/started" && notification.method !== "item/completed" && notification.method !== "rawResponseItem/completed" && notification.method !== "turn/completed") return;
254
- if (!nativeToolLifecycleProjector) {
255
- pendingNativeToolNotifications.push(notification);
256
- return;
257
- }
258
- nativeToolLifecycleProjector.handleNotification(notification);
259
- };
260
- let removeNotificationHandler = client.addNotificationHandler(handleNotification);
261
263
  const abortFromUpstream = () => runAbortController.abort(params.opts?.abortSignal?.reason ?? "codex_side_question_abort");
262
264
  if (params.opts?.abortSignal?.aborted) abortFromUpstream();
263
265
  else params.opts?.abortSignal?.addEventListener("abort", abortFromUpstream, { once: true });
264
266
  let childThreadId;
267
+ let pluginAppPolicyContext = binding.pluginAppPolicyContext;
265
268
  let childClient;
266
269
  let policyWriteUncertain = false;
267
270
  let turnId;
268
271
  let sandboxEnvironment;
272
+ let sandboxDisconnectError;
269
273
  let sandboxEnvironmentClient;
270
- let removeRequestHandler;
271
274
  let nativeHookRelay;
272
275
  const activeDynamicToolCalls = /* @__PURE__ */ new Set();
273
276
  const releaseSandboxEnvironment = async () => {
@@ -280,6 +283,7 @@ async function runCodexAppServerSideQuestion(params, options) {
280
283
  const ensureSandboxEnvironment = async (targetClient) => {
281
284
  if (!sandboxEnvironmentRequired || sandboxEnvironmentClient === targetClient) return;
282
285
  await releaseSandboxEnvironment();
286
+ assertCurrent();
283
287
  const environment = await ensureCodexSandboxExecServerEnvironment({
284
288
  client: targetClient,
285
289
  sandbox: params.sandbox ?? null,
@@ -288,7 +292,7 @@ async function runCodexAppServerSideQuestion(params, options) {
288
292
  timeoutMs: appServer.requestTimeoutMs,
289
293
  signal: runAbortController.signal,
290
294
  onExecutionDisconnect: (error) => {
291
- collector.reject(error);
295
+ sandboxDisconnectError = error;
292
296
  embeddedAgentLog.warn(error.message);
293
297
  runAbortController.abort("client_closed");
294
298
  }
@@ -298,6 +302,7 @@ async function runCodexAppServerSideQuestion(params, options) {
298
302
  sandboxEnvironmentClient = targetClient;
299
303
  };
300
304
  try {
305
+ assertCurrent();
301
306
  const autoApproveMcpTools = shouldAutoApproveCodexAppServerApprovals(appServer);
302
307
  const projectedMcpServers = loadCodexBundleMcpApprovalConfig({
303
308
  workspaceDir: agentWorkspaceDir,
@@ -337,7 +342,9 @@ async function runCodexAppServerSideQuestion(params, options) {
337
342
  } : {},
338
343
  config: params.cfg
339
344
  });
340
- const registerRequestHandler = (targetClient) => targetClient.addRequestHandler(async (request) => {
345
+ const handleServerRequest = async (request, _scope, requestSignal) => {
346
+ const signal = AbortSignal.any([requestSignal, runAbortController.signal]);
347
+ if (signal.aborted) return;
341
348
  if (!childThreadId || !turnId) return;
342
349
  if (request.method === "mcpServer/elicitation/request") {
343
350
  const approvalResult = await routeCodexAppServerElicitationRequest({
@@ -348,8 +355,8 @@ async function runCodexAppServerSideQuestion(params, options) {
348
355
  autoApproveMcpTools,
349
356
  projectedMcpServers,
350
357
  getActiveMcpToolCall: (serverName) => nativeToolLifecycleProjector?.getActiveMcpToolCall(serverName),
351
- pluginAppPolicyContext: binding.pluginAppPolicyContext,
352
- signal: runAbortController.signal
358
+ pluginAppPolicyContext,
359
+ signal
353
360
  });
354
361
  return approvalResult.kind === "handled" ? approvalResult.response : createCodexElicitationResponse("decline", null, { message: "OpenClaw Codex side questions do not support interactive MCP input." });
355
362
  }
@@ -362,7 +369,7 @@ async function runCodexAppServerSideQuestion(params, options) {
362
369
  turnId,
363
370
  nativeHookRelay,
364
371
  autoApprove: autoApproveMcpTools,
365
- signal: runAbortController.signal,
372
+ signal,
366
373
  onNativeToolFailureDisposition: (itemId, disposition) => nativeToolLifecycleProjector?.recordApprovalFailureDisposition(itemId, disposition)
367
374
  });
368
375
  if (request.method !== "item/tool/call") return;
@@ -384,7 +391,7 @@ async function runCodexAppServerSideQuestion(params, options) {
384
391
  const toolCall = handleDynamicToolCallWithTimeout({
385
392
  call,
386
393
  toolBridge,
387
- signal: runAbortController.signal,
394
+ signal,
388
395
  timeoutMs,
389
396
  observeToolTerminal: sideRunParams.observeToolTerminal
390
397
  });
@@ -404,25 +411,20 @@ async function runCodexAppServerSideQuestion(params, options) {
404
411
  emitDynamicToolErrorDiagnostic({
405
412
  ...diagnosticContext,
406
413
  durationMs: Math.max(0, Date.now() - toolStartedAt),
407
- terminalReason: runAbortController.signal.aborted ? resolveCodexToolAbortTerminalReason(runAbortController.signal) : "failed"
414
+ terminalReason: signal.aborted ? resolveCodexToolAbortTerminalReason(signal) : "failed"
408
415
  });
409
416
  throw error;
410
417
  } finally {
411
418
  activeDynamicToolCalls.delete(toolCall);
412
419
  }
413
- });
414
- removeRequestHandler = registerRequestHandler(client);
415
- const rebindClientHandlers = (nextClient) => {
416
- removeRequestHandler?.();
417
- removeNotificationHandler();
420
+ };
421
+ const selectClient = (nextClient) => {
418
422
  client = nextClient;
419
423
  ensureCodexAppServerClientRuntime(client, {
420
424
  agentDir: params.agentDir,
421
425
  authProfileId: connection.requestAuthProfileId,
422
426
  config: params.cfg
423
427
  });
424
- removeNotificationHandler = client.addNotificationHandler(handleNotification);
425
- removeRequestHandler = registerRequestHandler(client);
426
428
  };
427
429
  const serviceTier = binding.serviceTier ?? appServer.serviceTier;
428
430
  const nativeHookRelayEvents = resolveCodexSideNativeHookRelayEvents({
@@ -450,6 +452,7 @@ async function runCodexAppServerSideQuestion(params, options) {
450
452
  loopDetectionPreToolUseRelay: appServer.loopDetectionPreToolUseRelay,
451
453
  signal: runAbortController.signal,
452
454
  hostCapabilities: sideRunParams.hostCapabilities,
455
+ assertCurrent,
453
456
  onPreToolUseFailure: (failure) => {
454
457
  if (nativePreToolUseFailureFallbackActive) emitNativePreToolUseFailure(failure);
455
458
  else if (nativeToolLifecycleProjector) nativeToolLifecycleProjector.recordPreToolUseFailure(failure, nativeToolRunWasAbortedBeforeCleanup);
@@ -466,27 +469,54 @@ async function runCodexAppServerSideQuestion(params, options) {
466
469
  nativeCodeModeEnabled: nativeToolSurfaceEnabled,
467
470
  nativeCodeModeOnlyEnabled: appServer.codeModeOnly
468
471
  });
469
- const pluginAppsConfigPatch = binding.pluginAppPolicyContext ? buildCodexPluginAppsConfigPatchFromPolicyContext(binding.pluginAppPolicyContext) : void 0;
470
- const threadConfig = mergeCodexThreadConfigs(nativeHookRelayConfig, runtimeThreadConfig, pluginAppsConfigPatch, appServer.networkProxy?.configPatch) ?? runtimeThreadConfig;
471
472
  const sideThreadId = await withLeasedCodexAppServerClientStartSelectionRetry({
472
473
  lease: clientLease,
473
474
  options: clientOptions,
474
475
  signal: runAbortController.signal,
475
476
  run: async (forkClient, requestOptions) => options.bindingStore.withLease(bindingIdentity, async () => {
477
+ const assertCurrentBinding = () => {
478
+ assertCurrent();
479
+ runAbortController.signal.throwIfAborted();
480
+ if (!isDeepStrictEqual(options.bindingStore.read(bindingIdentity), binding)) throw new Error("Codex side-question binding changed before fork");
481
+ };
482
+ const currentRequestOptions = () => {
483
+ const scoped = requestOptions();
484
+ return {
485
+ ...scoped,
486
+ assertCurrent: () => {
487
+ scoped.assertCurrent();
488
+ assertCurrentBinding();
489
+ }
490
+ };
491
+ };
492
+ assertCurrentBinding();
476
493
  if (binding.connectionScope === "supervision") {
477
- params.hostCapabilities.assertActive();
478
494
  const { thread } = await forkClient.request("thread/read", {
479
495
  threadId: binding.threadId,
480
496
  includeTurns: false
481
- }, requestOptions());
482
- params.hostCapabilities.assertActive();
483
- if (!isDeepStrictEqual(await options.bindingStore.read(bindingIdentity), binding)) throw new Error("Codex side-question binding changed before fork");
484
- params.hostCapabilities.assertActive();
497
+ }, currentRequestOptions());
498
+ assertCurrentBinding();
485
499
  assertCodexSupervisionThreadLineage(binding, thread);
486
500
  }
487
501
  await ensureSandboxEnvironment(forkClient);
488
- params.hostCapabilities.assertActive();
502
+ assertCurrentBinding();
489
503
  const executionCwd = sandboxEnvironment?.cwd ?? cwd;
504
+ let pluginAppsConfigPatch;
505
+ if (binding.pluginAppPolicyContext) {
506
+ const refreshed = await refreshCodexPluginAppApprovalPolicy({
507
+ policyContext: binding.pluginAppPolicyContext,
508
+ configCwd: executionCwd,
509
+ request: (method, requestParams) => {
510
+ assertCurrentBinding();
511
+ return forkClient.request(method, requestParams, currentRequestOptions());
512
+ }
513
+ }).finally(assertCurrentBinding);
514
+ pluginAppPolicyContext = refreshed.policyContext;
515
+ pluginAppsConfigPatch = refreshed.configPatch;
516
+ for (const diagnostic of refreshed.diagnostics) embeddedAgentLog.warn(diagnostic.message);
517
+ }
518
+ assertCurrentBinding();
519
+ const threadConfig = mergeCodexThreadConfigs(nativeHookRelayConfig, runtimeThreadConfig, pluginAppsConfigPatch, appServer.networkProxy?.configPatch) ?? runtimeThreadConfig;
490
520
  const response = assertCodexThreadForkResponse(await forkCodexSideThread(forkClient, {
491
521
  threadId: binding.threadId,
492
522
  model: modelSelection.model,
@@ -502,14 +532,24 @@ async function runCodexAppServerSideQuestion(params, options) {
502
532
  ephemeral: true,
503
533
  excludeTurns: true,
504
534
  threadSource: "user"
505
- }, requestOptions()));
535
+ }, currentRequestOptions()));
506
536
  if (!response.thread.id.trim() || response.thread.id === binding.threadId) {
507
537
  await retireUnsafeCodexTurnClientBestEffort(forkClient, "unsafe side child identity");
508
538
  throw new Error("Codex side fork returned an unsafe child identity");
509
539
  }
510
540
  childThreadId = response.thread.id;
511
541
  childClient = forkClient;
542
+ collector = new CodexEphemeralTurn(forkClient, childThreadId, {
543
+ textMode: "last",
544
+ onRequest: handleServerRequest,
545
+ onAssistantMessageStart: async () => {
546
+ await params.opts?.onAssistantMessageStart?.();
547
+ },
548
+ onNotification: (notification) => nativeToolLifecycleProjector?.handleNotification(notification)
549
+ });
550
+ if (nativeHookRelay) collector.route.signal.addEventListener("abort", nativeHookRelay.unregister, { once: true });
512
551
  try {
552
+ assertCurrentBinding();
513
553
  if (supervisionModelSelection && (response.model !== supervisionModelSelection.model || response.modelProvider !== supervisionModelSelection.modelProvider)) throw new Error("Codex supervised side thread did not preserve its native model and provider");
514
554
  const scoped = requestOptions();
515
555
  await refreshCodexThreadPolicy({
@@ -519,7 +559,7 @@ async function runCodexAppServerSideQuestion(params, options) {
519
559
  ...scoped,
520
560
  signal: runAbortController.signal,
521
561
  assertCurrent: () => {
522
- params.hostCapabilities.assertActive();
562
+ assertCurrent();
523
563
  runAbortController.signal.throwIfAborted();
524
564
  scoped.assertCurrent();
525
565
  }
@@ -530,14 +570,14 @@ async function runCodexAppServerSideQuestion(params, options) {
530
570
  }
531
571
  return response.thread.id;
532
572
  }),
533
- onClientChange: rebindClientHandlers
573
+ onClientChange: selectClient
534
574
  });
535
575
  const effort = usesSupervisionConnection ? void 0 : resolveCodexAppServerReasoningEffort({
536
576
  thinkLevel: params.resolvedThinkLevel ?? "off",
537
577
  modelId: modelSelection.model,
538
578
  supportedReasoningEfforts: readCodexSupportedReasoningEfforts(params.runtimeModel?.compat)
539
579
  });
540
- turnId = assertCodexTurnStartResponse(await client.request("turn/start", {
580
+ const turnResponse = assertCodexTurnStartResponse(await client.request("turn/start", {
541
581
  threadId: sideThreadId,
542
582
  input: [{
543
583
  type: "text",
@@ -566,51 +606,64 @@ async function runCodexAppServerSideQuestion(params, options) {
566
606
  }
567
607
  }, {
568
608
  timeoutMs: appServer.requestTimeoutMs,
569
- signal: runAbortController.signal
609
+ signal: runAbortController.signal,
610
+ assertCurrent
570
611
  }).catch((error) => {
571
612
  if (isCodexAppServerIndeterminateRequestCancellationError(error)) turnId = "";
572
613
  throw error;
573
- })).turn.id;
574
- collector.setTurn(sideThreadId, turnId);
614
+ }));
615
+ turnId = turnResponse.turn.id;
616
+ assertCurrent();
575
617
  nativeToolLifecycleProjector = new CodexNativeToolLifecycleProjector({
576
618
  ...sideRunParams,
577
619
  agentId: sessionAgentId
578
620
  }, sideThreadId, turnId, { runAbortSignal: runAbortController.signal });
579
621
  for (const failure of pendingNativePreToolUseFailures) nativeToolLifecycleProjector.recordPreToolUseFailure(failure);
580
622
  pendingNativePreToolUseFailures.length = 0;
581
- for (const notification of pendingNativeToolNotifications) nativeToolLifecycleProjector.handleNotification(notification);
582
- pendingNativeToolNotifications.length = 0;
583
- let text;
623
+ if (!collector) throw new Error("Codex side thread route was not reserved");
624
+ let result;
584
625
  try {
585
- text = await collector.wait({
626
+ result = await collector.wait(turnResponse.turn, {
586
627
  signal: runAbortController.signal,
587
- timeoutMs: SIDE_QUESTION_COMPLETION_TIMEOUT_MS
628
+ abortError: () => sandboxDisconnectError ?? /* @__PURE__ */ new Error("Codex /btw was aborted."),
629
+ timeout: {
630
+ ms: SIDE_QUESTION_COMPLETION_TIMEOUT_MS,
631
+ error: new CodexSideQuestionTimeoutError("Codex /btw timed out waiting for the side thread to finish.")
632
+ }
588
633
  });
589
634
  } catch (error) {
590
635
  if (error instanceof CodexSideQuestionTimeoutError && !runAbortController.signal.aborted) runAbortController.abort(error);
591
636
  throw error;
592
637
  }
593
- const trimmed = text.trim();
638
+ if (result.error || result.turn?.status === "failed") throw formatCodexErrorMessage(result.error ?? { error: {
639
+ message: result.turn?.error?.message ?? null,
640
+ codexErrorInfo: result.turn?.error?.codexErrorInfo ?? null
641
+ } }, readRecentCodexRateLimits(client));
642
+ if (result.turn?.status === "interrupted") throw new Error("Codex /btw side thread was interrupted.");
643
+ const trimmed = result.text;
644
+ assertCurrent();
594
645
  if (!trimmed) throw new Error("Codex /btw completed without an answer.");
595
- return { text: trimmed };
646
+ return {
647
+ text: trimmed,
648
+ usage: result.usage
649
+ };
596
650
  } finally {
597
651
  try {
598
652
  const runWasAbortedBeforeCleanup = runAbortController.signal.aborted;
599
653
  nativeToolRunWasAbortedBeforeCleanup = runWasAbortedBeforeCleanup;
600
654
  params.opts?.abortSignal?.removeEventListener("abort", abortFromUpstream);
601
- removeRequestHandler?.();
602
655
  if (!runAbortController.signal.aborted) runAbortController.abort("codex_side_question_finished");
603
656
  await Promise.allSettled(activeDynamicToolCalls);
604
657
  try {
605
658
  await cleanupCodexSideThread(childClient ?? client, {
606
659
  threadId: childThreadId,
607
660
  turnId,
608
- interrupt: !collector.completed,
661
+ interrupt: !collector?.completed,
609
662
  timeoutMs: appServer.requestTimeoutMs
610
663
  });
611
664
  } finally {
612
665
  if (policyWriteUncertain && childClient) await retireUnsafeCodexTurnClientBestEffort(childClient, "side policy handoff");
613
- removeNotificationHandler();
666
+ collector?.route.release();
614
667
  try {
615
668
  nativeToolLifecycleProjector?.finalizeActive(runWasAbortedBeforeCleanup);
616
669
  } finally {
@@ -653,7 +706,7 @@ function registerCodexSideNativeHookRelay(params) {
653
706
  }),
654
707
  signal: params.signal,
655
708
  runBeforeToolCall: params.hostCapabilities.runBeforeToolCall,
656
- assertActive: params.hostCapabilities.assertActive,
709
+ assertActive: params.assertCurrent,
657
710
  onPreToolUseFailure: params.onPreToolUseFailure,
658
711
  command: { timeoutMs: params.options.gatewayTimeoutMs }
659
712
  });
@@ -739,6 +792,13 @@ async function createCodexSideToolBridge(input) {
739
792
  workspaceDir: input.cwd
740
793
  });
741
794
  const toolConstructionPlan = resolveCodexNodePlacementToolConstructionPlan(sandbox, input.nativeToolSurfaceEnabled);
795
+ const publishSideToolResult = input.params.opts?.onToolResult;
796
+ const questionPrompt = publishSideToolResult ? {
797
+ send: async (payload) => {
798
+ await publishSideToolResult(payload);
799
+ },
800
+ ...input.params.messageChannel ? { messageChannel: input.params.messageChannel } : {}
801
+ } : void 0;
742
802
  const allTools = createOpenClawCodingTools({
743
803
  agentId: input.sessionAgentId,
744
804
  requesterThinkingLevel: input.params.resolvedThinkLevel ?? "off",
@@ -748,7 +808,7 @@ async function createCodexSideToolBridge(input) {
748
808
  exec: input.sessionPermissionPolicy && { mode: input.sessionPermissionPolicy.execMode },
749
809
  sessionPermissionPolicy: input.sessionPermissionPolicy,
750
810
  runId: input.runId,
751
- agentDir: input.params.agentDir ?? resolveAgentDir(input.params.cfg ?? {}, input.sessionAgentId),
811
+ agentDir: input.params.agentDir ?? resolveAgentDir$2(input.params.cfg ?? {}, input.sessionAgentId),
752
812
  workspaceDir: input.cwd,
753
813
  spawnWorkspaceDir: resolveAttemptSpawnWorkspaceDir({
754
814
  sandbox,
@@ -794,6 +854,7 @@ async function createCodexSideToolBridge(input) {
794
854
  }).channelId,
795
855
  sandbox,
796
856
  ...toolConstructionPlan ? { toolConstructionPlan } : {},
857
+ ...questionPrompt ? { questionPrompt } : {},
797
858
  emitBeforeToolCallDiagnostics: false,
798
859
  modelHasVision: runtimeModel.input?.includes("image") ?? false,
799
860
  requireExplicitMessageTarget: true
@@ -861,14 +922,12 @@ function isMissingCodexParentThreadError(error) {
861
922
  }
862
923
  async function cleanupCodexSideThread(client, params) {
863
924
  if (!params.threadId) return;
864
- if (params.interrupt && params.turnId !== void 0) try {
865
- await client.request("turn/interrupt", {
925
+ if (params.interrupt && params.turnId !== void 0) {
926
+ if (!await interruptCodexTurnAndWaitBestEffort(client, {
866
927
  threadId: params.threadId,
867
- turnId: params.turnId
868
- }, { timeoutMs: params.timeoutMs });
869
- } catch (error) {
870
- if (!isCodexAlreadyTerminalInterruptError(error)) {
871
- embeddedAgentLog.debug("codex /btw side thread interrupt cleanup failed", { error });
928
+ turnId: params.turnId,
929
+ timeoutMs: params.timeoutMs
930
+ })) {
872
931
  await retireUnsafeCodexTurnClientBestEffort(client, "side turn interrupt");
873
932
  return;
874
933
  }
@@ -878,121 +937,6 @@ async function cleanupCodexSideThread(client, params) {
878
937
  timeoutMs: params.timeoutMs
879
938
  })) await retireUnsafeCodexTurnClientBestEffort(client, "side thread unsubscribe");
880
939
  }
881
- var CodexSideQuestionCollector = class {
882
- constructor(params, readRecentRateLimits) {
883
- this.params = params;
884
- this.readRecentRateLimits = readRecentRateLimits;
885
- this.pendingNotifications = [];
886
- this.assistantStarted = false;
887
- this.assistantText = "";
888
- this.completed = false;
889
- }
890
- setTurn(threadId, turnId) {
891
- this.threadId = threadId;
892
- this.turnId = turnId;
893
- const pending = this.pendingNotifications;
894
- this.pendingNotifications = [];
895
- for (const notification of pending) this.handleNotification(notification);
896
- }
897
- handleNotification(notification) {
898
- const params = isJsonObject(notification.params) ? notification.params : void 0;
899
- if (!params) return;
900
- if (!this.threadId || !this.turnId) {
901
- this.pendingNotifications.push(notification);
902
- return;
903
- }
904
- if (!isCodexNotificationForTurn(params, this.threadId, this.turnId)) return;
905
- if (notification.method === "item/agentMessage/delta") {
906
- this.appendAssistantDelta(params);
907
- return;
908
- }
909
- if (notification.method === "turn/completed") {
910
- this.completeFromTurn(params);
911
- return;
912
- }
913
- if (notification.method === "error" && params.willRetry !== true) this.reject(formatCodexErrorMessage(params, this.readRecentRateLimits()));
914
- }
915
- wait(options) {
916
- if (this.terminalError) return Promise.reject(this.terminalError);
917
- if (this.completed) return Promise.resolve(this.finalText ?? this.assistantText);
918
- if (options.signal?.aborted) return Promise.reject(/* @__PURE__ */ new Error("Codex /btw was aborted."));
919
- return new Promise((resolve, reject) => {
920
- let timeout;
921
- const cleanup = () => {
922
- if (timeout) {
923
- clearTimeout(timeout);
924
- timeout = void 0;
925
- }
926
- options.signal?.removeEventListener("abort", abort);
927
- };
928
- const abort = () => {
929
- cleanup();
930
- this.settle = void 0;
931
- reject(/* @__PURE__ */ new Error("Codex /btw was aborted."));
932
- };
933
- timeout = setTimeout(() => {
934
- cleanup();
935
- this.settle = void 0;
936
- reject(new CodexSideQuestionTimeoutError("Codex /btw timed out waiting for the side thread to finish."));
937
- }, Math.max(100, options.timeoutMs));
938
- timeout.unref?.();
939
- options.signal?.addEventListener("abort", abort, { once: true });
940
- this.settle = {
941
- resolve: (text) => {
942
- cleanup();
943
- resolve(text);
944
- },
945
- reject: (error) => {
946
- cleanup();
947
- reject(error);
948
- }
949
- };
950
- });
951
- }
952
- async appendAssistantDelta(params) {
953
- const delta = readStringField(params, "delta") ?? "";
954
- if (!delta) return;
955
- if (!this.assistantStarted) {
956
- this.assistantStarted = true;
957
- await this.params.opts?.onAssistantMessageStart?.();
958
- }
959
- this.assistantText += delta;
960
- }
961
- completeFromTurn(params) {
962
- const turn = readCodexTurn(params.turn);
963
- if (!turn || turn.id !== this.turnId) return;
964
- this.completed = true;
965
- if (turn.status === "failed") {
966
- this.reject(formatCodexUsageLimitErrorMessage({
967
- message: turn.error?.message,
968
- codexErrorInfo: turn.error?.codexErrorInfo,
969
- rateLimits: this.readRecentRateLimits()
970
- }) ?? turn.error?.message ?? "Codex /btw side thread failed.");
971
- return;
972
- }
973
- if (turn.status === "interrupted") {
974
- this.reject("Codex /btw side thread was interrupted.");
975
- return;
976
- }
977
- const finalText = collectAssistantText(turn) || this.assistantText;
978
- this.resolve(finalText);
979
- }
980
- resolve(text) {
981
- this.finalText = text;
982
- const settle = this.settle;
983
- this.settle = void 0;
984
- settle?.resolve(text);
985
- }
986
- reject(error) {
987
- this.terminalError = error instanceof Error ? error : new Error(error);
988
- const settle = this.settle;
989
- this.settle = void 0;
990
- settle?.reject(this.terminalError);
991
- }
992
- };
993
- function collectAssistantText(turn) {
994
- return (turn.items ?? []).filter((item) => item.type === "agentMessage" && typeof item.text === "string").map((item) => item.text.trim()).filter(Boolean).at(-1) ?? "";
995
- }
996
940
  function formatCodexErrorMessage(params, rateLimits) {
997
941
  const error = isJsonObject(params.error) ? params.error : void 0;
998
942
  const message = formatCodexUsageLimitErrorMessage({