@openclaw/codex 2026.9.4 → 2026.9.6

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 (160) hide show
  1. package/assets/activity.svg +30 -0
  2. package/assets/icon.png +0 -0
  3. package/dist/.setup/account-usage-runtime-Eem_WGqY.mjs +75 -0
  4. package/dist/{apply-CvT8tW5i.js → .setup/apply-DDOi8uNx.mjs} +24 -30
  5. package/dist/.setup/async-questions-DdhOCwGi.mjs +27 -0
  6. package/dist/{attempt-client-cleanup-DKHzbwt5.js → .setup/attempt-client-cleanup-CEv1cKwF.mjs} +79 -49
  7. package/dist/.setup/attempt-terminal-gZrxQ35N.mjs +5 -0
  8. package/dist/.setup/attempt-workspace-context-DUVEn_CS.mjs +331 -0
  9. package/dist/{auth-binding-CWlKVccJ.js → .setup/auth-binding-DhLWa_7K.mjs} +1 -1
  10. package/dist/{auth-cache-key-7orQae_j.js → .setup/auth-cache-key-B2mpaI9D.mjs} +9 -81
  11. package/dist/{auth-profile-CwzO4_RG.js → .setup/auth-profile-WqZtZfXN.mjs} +1 -1
  12. package/dist/.setup/auth-profile-health-oHizqgye.mjs +53 -0
  13. package/dist/.setup/auth-profile-recovery-BREezV0L.mjs +14 -0
  14. package/dist/.setup/binding-connection-ThoatDcb.mjs +50 -0
  15. package/dist/.setup/binding-connection.runtime-yoHrABt-.mjs +48 -0
  16. package/dist/{bounded-turn-C_Hneydj.js → .setup/bounded-turn-B2HScEgT.mjs} +143 -32
  17. package/dist/{build-state-BCmg9-5p.js → .setup/build-state-C7EnDVgr.mjs} +1 -1
  18. package/dist/{capabilities-8vx68WLH.js → .setup/capabilities-CDXOOFdZ.mjs} +1 -1
  19. package/dist/{client-B57KWPQx.js → .setup/client-Cs08OXVQ.mjs} +705 -512
  20. package/dist/.setup/client-catalog-response-BMgt_4q4.mjs +285 -0
  21. package/dist/{command-dispatch-BpduNGVf.js → .setup/command-dispatch-B4JuOsOk.mjs} +8 -4
  22. package/dist/{command-formatters-lxlkNZgU.js → .setup/command-formatters-Bmqvr9tO.mjs} +8 -4
  23. package/dist/{command-handlers-tiL9iWj7.js → .setup/command-handlers-DW7Lx9oH.mjs} +137 -186
  24. package/dist/{command-rpc-CR5EOEZX.js → .setup/command-rpc-DixIj3HW.mjs} +47 -23
  25. package/dist/{compact-B_H3AOd7.js → .setup/compact-Du5UvtxA.mjs} +29 -51
  26. package/dist/{config-oIORaQ5T.js → .setup/config-BoTP_mrL.mjs} +5 -4
  27. package/dist/{config-options-CXMq1T-C.js → .setup/config-options-BvaRs51b.mjs} +50 -446
  28. package/dist/{protocol-5bh1G-H7.js → .setup/config-parsing-CcB9iPoq.mjs} +9 -51
  29. package/dist/{config-runtime-D0zGNIHu.js → .setup/config-runtime-C8Rw1m1m.mjs} +2 -2
  30. package/dist/.setup/config-security-BEReZ6go.mjs +380 -0
  31. package/dist/{conversation-binding-DsB4-O7U.js → .setup/conversation-binding-DP-gMrBP.mjs} +29 -38
  32. package/dist/{conversation-binding-data-BiodpIzq.js → .setup/conversation-binding-data-CrcyZk6O.mjs} +1 -1
  33. package/dist/{conversation-control-CtUu1b3m.js → .setup/conversation-control-uK9Jomlc.mjs} +32 -67
  34. package/dist/.setup/cyber-failover-DYwbmf1o.mjs +123 -0
  35. package/dist/.setup/cyber-failover-notice-e9G3J9-e.mjs +17 -0
  36. package/dist/{dynamic-tools-CmN5RAip.js → .setup/dynamic-tools-BDXl-8Cw.mjs} +936 -620
  37. package/dist/{effective-mcp-catalog-Bd73bqA8.js → .setup/effective-mcp-catalog-CvnvnGIe.mjs} +3 -3
  38. package/dist/{ephemeral-turn-D78_VmzO.js → .setup/ephemeral-turn-poidXgek.mjs} +9 -7
  39. package/dist/{event-projector-assistant-message-BmBM4qBV.js → .setup/event-projector-assistant-message-BsruvNrH.mjs} +8 -7
  40. package/dist/{event-projector-items-5VhsECCO.js → .setup/event-projector-items-C6L_5ZiT.mjs} +42 -8
  41. package/dist/{attempt-notifications-C9XufG6l.js → .setup/event-projector-usage-CnBS8Wa3.mjs} +102 -9
  42. package/dist/{harness-C7rRa7bm.js → .setup/harness-a_MsE4-_.mjs} +81 -21
  43. package/dist/{inference-context-Dr_mzvk4.js → .setup/inference-context-D96l9-ew.mjs} +1 -1
  44. package/dist/.setup/inference-proxy-b-aJMSxm.mjs +601 -0
  45. package/dist/{isolated-completion-DWVb5U2J.js → .setup/isolated-completion-BIZFhTNG.mjs} +18 -11
  46. package/dist/.setup/launch-args-DbFCehO7.mjs +196 -0
  47. package/dist/{managed-binary-D22rNEcR.js → .setup/managed-binary-BnshlFag.mjs} +14 -3
  48. package/dist/{managed-thread-store-D1t5jh3G.js → .setup/managed-thread-store-BMqgThVL.mjs} +48 -14
  49. package/dist/{model-catalog-Dq2n8f_p.js → .setup/model-catalog-CfXJf9Ay.mjs} +36 -12
  50. package/dist/{models-PCKOim-h.js → .setup/models-KnqBv0hE.mjs} +3 -3
  51. package/dist/.setup/native-auth-rWbGbMn3.mjs +57 -0
  52. package/dist/{native-subagent-history-DjtPloaU.js → .setup/native-subagent-history-0nYYgo0k.mjs} +43 -35
  53. package/dist/.setup/native-subagent-monitor-D3filLY2.mjs +4859 -0
  54. package/dist/{native-subagent-task-ids-BzTdT0Uw.js → .setup/native-subagent-task-ids-wb8CKZGN.mjs} +98 -44
  55. package/dist/{node-cli-sessions-DKaOmVUh.js → .setup/node-cli-sessions-r3avj02l.mjs} +86 -68
  56. package/dist/.setup/node-exec-server.runtime-BDwWXVpK.mjs +247 -0
  57. package/dist/{plan-7uG-Fp36.js → .setup/plan-CN3VwfNU.mjs} +133 -119
  58. package/dist/{plugin-activation-BYQculil.js → .setup/plugin-activation-DT3MNtqj.mjs} +7 -16
  59. package/dist/{plugin-app-cache-key-d0eKxy7b.js → .setup/plugin-app-cache-key-B2CsSdnV.mjs} +32 -44
  60. package/dist/{plugin-approval-roundtrip-Bz3FT8W5.js → .setup/plugin-approval-roundtrip-C0MZzCuP.mjs} +1 -1
  61. package/dist/{plugin-inventory-oL4Na1ZG.js → .setup/plugin-inventory-BoRei8Z4.mjs} +21 -11
  62. package/dist/{plugin-marketplace-discovery-P-Vndfqq.js → .setup/plugin-marketplace-discovery-CDOi8IFs.mjs} +4 -1
  63. package/dist/{plugin-metadata-cache-ClPJpRio.js → .setup/plugin-metadata-cache-Ctmo83k_.mjs} +226 -141
  64. package/dist/.setup/protocol-CANUwXJ3.mjs +17 -0
  65. package/dist/{provider-MQ8PVkuE.js → .setup/provider-BOsxQHOM.mjs} +9 -5
  66. package/dist/{provider-capabilities-BvCUL69A.js → .setup/provider-capabilities-BfE88FZ5.mjs} +31 -3
  67. package/dist/{rate-limits-CBMmWBr9.js → .setup/rate-limits-CMU3DUD0.mjs} +174 -151
  68. package/dist/{request-B7hEkBGq.js → .setup/request-D2L0zMrq.mjs} +130 -42
  69. package/dist/{run-attempt-CvsAAGa0.js → .setup/run-attempt-BHu11r7h.mjs} +1628 -966
  70. package/dist/.setup/run-attempt-lifecycle-B7JbY4-F.mjs +71 -0
  71. package/dist/{runtime-artifact-BJ0rXBZ_.js → .setup/runtime-artifact-CLZ8udh-.mjs} +29 -45
  72. package/dist/{sandbox-guard-BxgyoM8M.js → .setup/sandbox-guard-C2sRMOEY.mjs} +3 -3
  73. package/dist/{session-binding-CI8UuilT.js → .setup/session-binding-Cm0apEbd.mjs} +36 -83
  74. package/dist/{session-binding-record-Bcvslnhf.js → .setup/session-binding-record-BGoz8wOK.mjs} +202 -5
  75. package/dist/.setup/session-binding-sidecars-BlB5EvIS.mjs +546 -0
  76. package/dist/.setup/session-catalog-Pno1xGcl.mjs +2764 -0
  77. package/dist/{session-catalog-adoption-tcZi1IfX.js → .setup/session-catalog-adoption-BI6UTDZT.mjs} +58 -26
  78. package/dist/{session-catalog-archive-CwKg8Xz2.js → .setup/session-catalog-archive-lHBqzhaO.mjs} +6 -6
  79. package/dist/.setup/session-catalog-events-Bj6j94E_.mjs +347 -0
  80. package/dist/.setup/session-catalog-index-B9_VQIUz.mjs +1170 -0
  81. package/dist/.setup/session-catalog-index-order-hcdz07yN.mjs +48 -0
  82. package/dist/.setup/session-catalog-index-state-Dgh8ORJm.mjs +183 -0
  83. package/dist/{thread-history-page-D0JIp48V.js → .setup/session-catalog-native-projection-DowriLid.mjs} +223 -95
  84. package/dist/{session-catalog-node-adoption-B1tgDW-m.js → .setup/session-catalog-node-adoption-ITddWx_X.mjs} +25 -13
  85. package/dist/{session-catalog-node-continue-Ci-DXyJP.js → .setup/session-catalog-node-continue-6g6qi4A9.mjs} +24 -15
  86. package/dist/.setup/session-catalog-projection-zK_PUsiE.mjs +422 -0
  87. package/dist/{session-cli-DNN_jhGc.js → .setup/session-cli-irrD-uo7.mjs} +3 -3
  88. package/dist/{session-history-Cz-tOOYj.js → .setup/session-history-BrqhSCf9.mjs} +19 -19
  89. package/dist/{session-history-import-DwyijFI6.js → .setup/session-history-import-D-3wAgOP.mjs} +4 -4
  90. package/dist/{session-history-read-cxPUxyVV.js → .setup/session-history-read-B3ZfSUbF.mjs} +2 -2
  91. package/dist/{session-history.worker-BeK1YOyT.js → .setup/session-history.worker-CaCh0xF_.mjs} +10 -24
  92. package/dist/{session-initialization-Ct0_Hzmg.js → .setup/session-initialization-rcgbZiid.mjs} +2 -2
  93. package/dist/{session-permission-policy-BBmXA8Eg.js → .setup/session-permission-policy-BI1QK_98.mjs} +2 -2
  94. package/dist/{session-retirement-B2YfbAAT.js → .setup/session-retirement-BH-S6qkJ.mjs} +26 -7
  95. package/dist/{settled-turn-context-Du6gdUDd.js → .setup/settled-turn-context-fmwouT5I.mjs} +2 -2
  96. package/dist/{settled-turn-finalizer-Dn91stmc.js → .setup/settled-turn-finalizer-DiAi6Kx6.mjs} +12 -12
  97. package/dist/{shared-client-CscigXXL.js → .setup/shared-client-DA4VR4Eb.mjs} +332 -221
  98. package/dist/{side-question-BGMJQf4U.js → .setup/side-question-BJ1wSDcB.mjs} +183 -230
  99. package/dist/{source-CElXU0Oy.js → .setup/source-CUzJq5WN.mjs} +11 -10
  100. package/dist/.setup/spawn-error-CL3n6MAa.mjs +57 -0
  101. package/dist/{thread-archive-guard-DfpBr-Sz.js → .setup/thread-archive-guard-C9frICzX.mjs} +10 -3
  102. package/dist/.setup/thread-history-page-DoVpnHim.mjs +83 -0
  103. package/dist/{thread-lifecycle-DXl1-I6b.js → .setup/thread-lifecycle-B3mfz1TG.mjs} +347 -2318
  104. package/dist/{thread-ownership-BsDRTsyp.js → .setup/thread-ownership-DcTtAcXj.mjs} +6 -4
  105. package/dist/{thread-policy-BuEQfE0g.js → .setup/thread-policy-DGuQsuFC.mjs} +19 -3
  106. package/dist/.setup/thread-requests-BLvGkP2R.mjs +2205 -0
  107. package/dist/{thread-resume-DsDOZpFg.js → .setup/thread-resume-DIBXwOpE.mjs} +8 -5
  108. package/dist/.setup/timeout-C910MdAB.mjs +80 -0
  109. package/dist/{transcript-history-projection-v17wXgdK.js → .setup/transcript-history-projection-ZZpkFkJ_.mjs} +96 -61
  110. package/dist/{transcript-mirror-C5CKgNy6.js → .setup/transcript-mirror-BtHDBp1G.mjs} +224 -195
  111. package/dist/{transcript-mirror-attestation-DibE0krH.js → .setup/transcript-mirror-attestation-CzM-94NC.mjs} +4 -1
  112. package/dist/{transport-stdio-BGjHoYLr.js → .setup/transport-stdio-h2VHOskC.mjs} +274 -89
  113. package/dist/{upstream-session-fork-BZerMte_.js → .setup/upstream-session-fork-BUr4OUbC.mjs} +51 -42
  114. package/dist/{usage-tCk-mg_x.js → .setup/usage-BML0r-ua.mjs} +5 -4
  115. package/dist/.setup/usage-limit-error-DUMbefVY.mjs +166 -0
  116. package/dist/{web-search-provider.runtime-B7bGbGWq.js → .setup/web-search-provider.runtime-CDKlN-Rv.mjs} +4 -3
  117. package/dist/api.js +23 -12
  118. package/dist/catalog-page-worker-entrypoint.js +12 -0
  119. package/dist/catalog-page.worker.js +9 -0
  120. package/dist/cli-metadata.js +1 -1
  121. package/dist/doctor-contract-api.js +8 -528
  122. package/dist/harness.js +1 -1
  123. package/dist/index.js +306 -215
  124. package/dist/media-understanding-provider.js +3 -3
  125. package/dist/migration-provider-api.js +1 -1
  126. package/dist/native-tool-policy.js +12 -0
  127. package/dist/provider-discovery.js +18 -0
  128. package/dist/session-history-worker-runtime.js +36 -35
  129. package/dist/session-history.worker.js +2 -2
  130. package/dist/web-search-contract-api.js +1 -1
  131. package/openclaw.plugin.json +354 -69
  132. package/package.json +14 -8
  133. package/dist/attempt-context-D44yeDII.js +0 -636
  134. package/dist/binding-connection-D3udKbIE.js +0 -60
  135. package/dist/event-projector-usage-BfXmpOec.js +0 -102
  136. package/dist/inference-proxy-HGXKUIre.js +0 -311
  137. package/dist/launch-args-RXQwn8zV.js +0 -90
  138. package/dist/native-subagent-history-owner-Pcp7JuVF.js +0 -34
  139. package/dist/native-subagent-monitor-fQ7eIXEf.js +0 -2978
  140. package/dist/node-exec-server.runtime-Cl2vapEi.js +0 -226
  141. package/dist/rpc-error-ttN_QjEm.js +0 -30
  142. package/dist/session-catalog-ct-AH01I.js +0 -1477
  143. package/dist/session-catalog-home-id-CwhLdC03.js +0 -18
  144. package/dist/session-catalog-provenance-D-dIfRAH.js +0 -96
  145. package/dist/timeout-BVw8aaM1.js +0 -33
  146. package/dist/version-omm6IPI3.js +0 -12
  147. /package/dist/{auth-profile-selection-DFu9e167.js → .setup/auth-profile-selection-DFu9e167.mjs} +0 -0
  148. /package/dist/{config-utils-DujwEnhg.js → .setup/config-utils-DujwEnhg.mjs} +0 -0
  149. /package/dist/{context-compaction-activity-CMla5FPJ.js → .setup/context-compaction-activity-CMla5FPJ.mjs} +0 -0
  150. /package/dist/{elicitation-input-DPoK8F7w.js → .setup/elicitation-input-DPoK8F7w.mjs} +0 -0
  151. /package/dist/{history-rejection-B4nOXNXF.js → .setup/history-rejection-B4nOXNXF.mjs} +0 -0
  152. /package/dist/{image-payload-sanitizer-tupAr-2o.js → .setup/image-payload-sanitizer-tupAr-2o.mjs} +0 -0
  153. /package/dist/{incognito-session-uhrBF6wJ.js → .setup/incognito-session-uhrBF6wJ.mjs} +0 -0
  154. /package/dist/{local-runtime-attribution-B_2mnqhb.js → .setup/local-runtime-attribution-B_2mnqhb.mjs} +0 -0
  155. /package/dist/{native-execution-policy-umd0tgh4.js → .setup/native-execution-policy-umd0tgh4.mjs} +0 -0
  156. /package/dist/{rolldown-runtime-8H4AJuhK.js → .setup/rolldown-runtime-8H4AJuhK.mjs} +0 -0
  157. /package/dist/{session-binding-meta-B7aEMU7g.js → .setup/session-binding-meta-B7aEMU7g.mjs} +0 -0
  158. /package/dist/{session-upstream-marker-D15C9NHp.js → .setup/session-upstream-marker-D15C9NHp.mjs} +0 -0
  159. /package/dist/{upstream-prompt-provenance-LphB8slG.js → .setup/upstream-prompt-provenance-LphB8slG.mjs} +0 -0
  160. /package/dist/{web-search-provider.shared-BrZmlqyR.js → .setup/web-search-provider.shared-BrZmlqyR.mjs} +0 -0
@@ -1,123 +1,428 @@
1
- import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
2
- import { l as resolveCodexAppServerUserHomeDir, o as isJsonObject } from "./protocol-5bh1G-H7.js";
3
- import { r as MIN_SUPPORTED_CODEX_APP_SERVER_VERSION, t as CODEX_APP_SERVER_VERSION } from "./version-omm6IPI3.js";
4
- import { a as hasCodexAppServerNaturalExit, i as closeCodexAppServerTransportAndWait, r as closeCodexAppServerTransport, t as createStdioTransport } from "./transport-stdio-BGjHoYLr.js";
5
- import { t as CodexAppServerRpcError } from "./rpc-error-ttN_QjEm.js";
6
- import "./config-oIORaQ5T.js";
7
- import { n as resolveCodexAppServerRuntimeOptions } from "./config-runtime-D0zGNIHu.js";
1
+ import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.mjs";
2
+ import { p as resolveCodexAppServerUserHomeDir } from "./config-security-BEReZ6go.mjs";
3
+ import { d as recordCodexCatalogResponseSource, i as reuseCodexCatalogPreview, o as closeCodexCatalogClientSource, s as codexCatalogSourceForClient } from "./session-catalog-native-projection-DowriLid.mjs";
4
+ import { a as stringifyCodexAppServerMessage, c as isRpcResponse, i as readCodexCatalogDecodeRoute, n as projectCodexCatalogMessage, o as CodexAppServerMessageDecoder, r as listenCodexAppServerLines, s as redactCodexAppServerLinePreview } from "./client-catalog-response-BMgt_4q4.mjs";
5
+ import { i as isJsonObject } from "./protocol-CANUwXJ3.mjs";
6
+ import { c as MIN_SUPPORTED_CODEX_APP_SERVER_VERSION, s as CODEX_APP_SERVER_VERSION } from "./managed-binary-BnshlFag.mjs";
7
+ import { a as closeCodexAppServerTransportAndWait, i as closeCodexAppServerTransport, o as hasCodexAppServerNaturalExit, t as createStdioTransport } from "./transport-stdio-h2VHOskC.mjs";
8
+ import { a as CODEX_APP_SERVER_OVERLOADED_ERROR_CODE, o as CodexAppServerRpcError } from "./timeout-C910MdAB.mjs";
9
+ import "./config-BoTP_mrL.mjs";
10
+ import { n as resolveCodexAppServerRuntimeOptions } from "./config-runtime-C8Rw1m1m.mjs";
11
+ import { codexCatalogPageWorkerEntrypoint } from "../catalog-page-worker-entrypoint.js";
8
12
  import { isRecord, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
9
13
  import { randomUUID } from "node:crypto";
10
- import { addTimerTimeoutGraceMs, parseStrictNonNegativeInteger } from "openclaw/plugin-sdk/number-runtime";
14
+ import { addSafeTimeoutDelayGraceMs, addTimerTimeoutGraceMs, parseStrictNonNegativeInteger } from "openclaw/plugin-sdk/number-runtime";
15
+ import { normalizeJsonSchemaForTypeBox } from "openclaw/plugin-sdk/json-schema-runtime";
11
16
  import path from "node:path";
12
17
  import { EventEmitter } from "node:events";
13
18
  import { coerceErrorMessage, toStringifiedError } from "openclaw/plugin-sdk/error-runtime";
14
19
  import { sliceUtf16Safe, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
20
+ import { hasPendingInternalDiagnosticEvent } from "openclaw/plugin-sdk/diagnostic-runtime";
21
+ import { createDeferred } from "openclaw/plugin-sdk/extension-shared";
15
22
  import { OPENCLAW_VERSION, embeddedAgentLog, formatToolExecutionErrorMessage, normalizeQuestionTimeoutSeconds, resolveToolExecutionErrorKind } from "openclaw/plugin-sdk/agent-harness-runtime";
16
- import { createInterface } from "node:readline";
17
23
  import { parse } from "semver";
18
- import { hasPendingInternalDiagnosticEvent } from "openclaw/plugin-sdk/diagnostic-runtime";
24
+ import { copyInternalToolResultState, runWithAsyncWorkResources } from "openclaw/plugin-sdk/agent-harness-tool-runtime";
19
25
  import { Compile } from "typebox/compile";
20
26
  import net from "node:net";
21
27
  import { PassThrough, Writable } from "node:stream";
22
28
  import { StringDecoder } from "node:string_decoder";
23
- import WebSocket from "ws";
24
- //#region extensions/codex/src/app-server/protocol-json.ts
25
- function isRpcResponse(message) {
26
- return "id" in message && !("method" in message);
29
+ import { WebSocket } from "openclaw/plugin-sdk/websocket-runtime";
30
+ //#region extensions/codex/src/app-server/client-catalog-worker.ts
31
+ const INLINE_CATALOG_MAX_BYTES = 65536;
32
+ /** Late responses retain their decode route after cancellation removes the waiter. */
33
+ function codexCatalogRequestId(method, params, sequence, catalogPreview) {
34
+ const kind = catalogPreview ? method === "thread/list" ? "list" : method === "thread/read" && isJsonObject(params) && params.includeTurns !== true ? "thread" : void 0 : void 0;
35
+ return kind ? Number.MAX_SAFE_INTEGER - 2 * sequence - (kind === "thread" ? 1 : 0) : sequence;
27
36
  }
28
- //#endregion
29
- //#region extensions/codex/src/app-server/dynamic-tool-response-state.ts
30
- /** Retains the host-owned app preview without adding it to Codex's response payload. */
31
- function withDynamicToolTranscriptDetails(response, details) {
32
- if (details === void 0) return response;
33
- Object.defineProperty(response, "transcriptDetails", {
34
- configurable: true,
35
- enumerable: false,
36
- value: details
37
- });
38
- return response;
39
- }
40
- function withDynamicToolTerminalResolution(response, terminalResolution) {
41
- if (terminalResolution) {
42
- Object.defineProperties(response, {
43
- terminalResolution: {
44
- configurable: true,
45
- enumerable: false,
46
- value: terminalResolution
47
- },
48
- executionStarted: {
49
- configurable: true,
50
- enumerable: false,
51
- value: terminalResolution.executionStarted
52
- },
53
- ...terminalResolution.executedArguments ? { executedArguments: {
54
- configurable: true,
55
- enumerable: false,
56
- value: terminalResolution.executedArguments
57
- } } : {}
37
+ /** Each physical client owns one decoder, including incomplete-line recovery state. */
38
+ var CodexCatalogWorker = class {
39
+ constructor() {
40
+ this.closed = false;
41
+ }
42
+ get continuation() {
43
+ return this.continuationRoute;
44
+ }
45
+ async decode(line, route, attempts, projections) {
46
+ if (this.closed) return;
47
+ if (!this.continuationRoute && route !== "unresolved" && line.byteLength <= INLINE_CATALOG_MAX_BYTES) {
48
+ let parsed;
49
+ try {
50
+ parsed = JSON.parse(line.toString("utf8"));
51
+ } catch {}
52
+ if (parsed !== void 0) {
53
+ await Promise.resolve();
54
+ if (this.closed) return;
55
+ const attempt = attempts.get(route.id);
56
+ const projection = attempt ? projections.get(attempt) : void 0;
57
+ return projectCodexCatalogMessage(parsed, {
58
+ route,
59
+ remainingRows: attempt ? projection?.remainingRows : 0
60
+ }, projection?.preview);
61
+ }
62
+ }
63
+ if (!this.pool) {
64
+ const { resolveRuntimeWorkerUrl, WorkerTaskPool } = await import("openclaw/plugin-sdk/process-runtime");
65
+ if (this.closed) return;
66
+ this.pool = new WorkerTaskPool({
67
+ workerUrl: resolveRuntimeWorkerUrl(codexCatalogPageWorkerEntrypoint),
68
+ maxWorkers: 1,
69
+ maxPendingTasks: 1,
70
+ maxPendingBytes: Number.MAX_SAFE_INTEGER,
71
+ idleTimeoutMs: 0,
72
+ restartOnError: false
73
+ });
74
+ }
75
+ const attempt = route === "unresolved" ? void 0 : attempts.get(route.id);
76
+ const remainingRows = attempt ? projections.get(attempt)?.remainingRows : 0;
77
+ let catalogRows;
78
+ if (route === "unresolved") {
79
+ catalogRows = /* @__PURE__ */ new Map();
80
+ for (const [id, pending] of attempts) {
81
+ const projection = projections.get(pending);
82
+ if (typeof id === "number" && projection) catalogRows.set(id, projection.remainingRows);
83
+ }
84
+ }
85
+ const bytes = line.byteOffset === 0 && line.byteLength === line.buffer.byteLength && line.buffer instanceof ArrayBuffer ? new Uint8Array(line.buffer) : Uint8Array.from(line);
86
+ const decoded = await this.pool.run({
87
+ bytes,
88
+ route,
89
+ remainingRows,
90
+ catalogRows
91
+ }, {
92
+ inputBytes: bytes.byteLength,
93
+ transferList: (input) => [input.bytes.buffer]
58
94
  });
59
- withDynamicToolSideEffectEvidence(response, terminalResolution.sideEffectEvidence);
95
+ if (this.closed) return;
96
+ this.continuationRoute = decoded.pending ? route : void 0;
97
+ return decoded;
60
98
  }
61
- return response;
99
+ close(error) {
100
+ this.closed = true;
101
+ this.continuationRoute = void 0;
102
+ return this.pool?.close(error) ?? Promise.resolve();
103
+ }
104
+ };
105
+ //#endregion
106
+ //#region extensions/codex/src/app-server/client-diagnostics.ts
107
+ function observeCodexAppServerStderr(stderr, consume) {
108
+ stderr.setEncoding("utf8");
109
+ stderr.on("data", (chunk) => {
110
+ const text = consume(chunk).trim();
111
+ if (text) embeddedAgentLog.debug(`codex app-server stderr: ${text}`);
112
+ });
113
+ stderr.on("error", (error) => embeddedAgentLog.warn("codex app-server stderr stream failed", { error }));
114
+ }
115
+ function appendBoundedTail(current, next, maxLength) {
116
+ const combined = `${current}${next}`;
117
+ return combined.length > maxLength ? sliceUtf16Safe(combined, -maxLength) : combined;
118
+ }
119
+ function buildCodexAppServerExitError(code, signal, stderrTail) {
120
+ const stderrPreview = redactCodexAppServerLinePreview(stderrTail);
121
+ const suffix = stderrPreview ? ` stderr=${JSON.stringify(stderrPreview)}` : "";
122
+ return /* @__PURE__ */ new Error(`codex app-server exited: code=${formatExitValue(code)} signal=${formatExitValue(signal)}${suffix}`);
123
+ }
124
+ function logCodexAppServerParseFailure(value, error, fragmentCount) {
125
+ const linePreview = redactCodexAppServerLinePreview(value);
126
+ const suffix = fragmentCount > 1 ? ` fragments=${fragmentCount}` : "";
127
+ embeddedAgentLog.warn("failed to parse codex app-server message", {
128
+ error,
129
+ errorMessage: coerceErrorMessage(error),
130
+ fragmentCount,
131
+ linePreview,
132
+ consoleMessage: `failed to parse codex app-server message${suffix}: preview=${JSON.stringify(linePreview)}`
133
+ });
62
134
  }
63
- function withDynamicToolExecutionState(response, state) {
64
- Object.defineProperties(response, {
65
- executedArguments: {
66
- configurable: true,
67
- enumerable: false,
68
- value: state.executedArguments
135
+ function formatExitValue(value) {
136
+ if (value === null || value === void 0) return "null";
137
+ if (typeof value === "string" || typeof value === "number") return String(value);
138
+ return "unknown";
139
+ }
140
+ //#endregion
141
+ //#region extensions/codex/src/app-server/notification-policy.ts
142
+ const CODEX_APP_SERVER_OPT_OUT_NOTIFICATION_METHODS = [
143
+ "account/login/completed",
144
+ "app/list/updated",
145
+ "command/exec/outputDelta",
146
+ "deprecationNotice",
147
+ "externalAgentConfig/import/completed",
148
+ "externalAgentConfig/import/progress",
149
+ "fs/changed",
150
+ "fuzzyFileSearch/sessionCompleted",
151
+ "fuzzyFileSearch/sessionUpdated",
152
+ "mcpServer/event/stream/notification",
153
+ "mcpServer/oauthLogin/completed",
154
+ "mcpServer/startupStatus/updated",
155
+ "process/exited",
156
+ "process/outputDelta",
157
+ "project/changed",
158
+ "remoteControl/status/changed",
159
+ "thread/environment/connected",
160
+ "thread/environment/disconnected",
161
+ "thread/goal/cleared",
162
+ "thread/project/updated",
163
+ "thread/queue/changed",
164
+ "thread/realtime/closed",
165
+ "thread/realtime/error",
166
+ "thread/realtime/item/completed",
167
+ "thread/realtime/item/started",
168
+ "thread/realtime/item/transcript/delta",
169
+ "thread/realtime/itemAdded",
170
+ "thread/realtime/outputAudio/delta",
171
+ "thread/realtime/sdp",
172
+ "thread/realtime/started",
173
+ "thread/realtime/transcript/delta",
174
+ "thread/realtime/transcript/done",
175
+ "windows/worldWritableWarning",
176
+ "windowsSandbox/setupCompleted",
177
+ "turn/diff/updated",
178
+ "item/fileChange/outputDelta",
179
+ "thread/compacted"
180
+ ];
181
+ //#endregion
182
+ //#region extensions/codex/src/app-server/client-initialize.ts
183
+ function buildCodexAppServerInitializeParams() {
184
+ return {
185
+ clientInfo: {
186
+ name: "openclaw",
187
+ title: "OpenClaw",
188
+ version: OPENCLAW_VERSION
69
189
  },
70
- executionStarted: {
71
- configurable: true,
72
- enumerable: false,
73
- value: state.executionStarted
190
+ capabilities: {
191
+ experimentalApi: true,
192
+ optOutNotificationMethods: [...CODEX_APP_SERVER_OPT_OUT_NOTIFICATION_METHODS],
193
+ extensions: {
194
+ "openai/standard-form-input": {},
195
+ "openai/form": {},
196
+ "io.modelcontextprotocol/ui": { mimeTypes: ["text/html;profile=mcp-app"] }
197
+ }
74
198
  }
75
- });
76
- return withDynamicToolSideEffectEvidence(response, state.sideEffectEvidence === true);
199
+ };
77
200
  }
78
- function withDynamicToolSideEffectEvidence(response, sideEffectEvidence) {
79
- if (!sideEffectEvidence) {
80
- delete response.sideEffectEvidence;
81
- return response;
201
+ //#endregion
202
+ //#region extensions/codex/src/app-server/client-response.ts
203
+ /** Settles one wire attempt and reports newly observed native execution. */
204
+ function dispatchCodexAppServerResponse(response, attempts, catalogResponses, source, previewStates) {
205
+ const pending = attempts.get(response.id);
206
+ if (!pending) return false;
207
+ attempts.delete(response.id);
208
+ if (response.error) {
209
+ const error = new CodexAppServerRpcError(response.error, pending.method);
210
+ pending.reject(error, error.code === CODEX_APP_SERVER_OVERLOADED_ERROR_CODE);
211
+ return false;
82
212
  }
83
- Object.defineProperty(response, "sideEffectEvidence", {
84
- configurable: true,
85
- enumerable: false,
86
- value: true
87
- });
88
- return response;
213
+ const nativeExecution = pending.method === "thread/backgroundTerminals/list" && isJsonObject(response.result) && Array.isArray(response.result.data) && response.result.data.length > 0;
214
+ const cache = catalogResponses.get(pending)?.preview;
215
+ if (cache && previewStates && isJsonObject(response.result) && Array.isArray(response.result.data)) try {
216
+ for (const [index, row] of response.result.data.entries()) if (isJsonObject(row) && typeof row.id === "string" && row.ephemeral !== true) {
217
+ const preview = reuseCodexCatalogPreview({
218
+ id: row.id,
219
+ path: typeof row.path === "string" ? row.path : null,
220
+ updatedAt: typeof row.updatedAt === "number" ? row.updatedAt : null,
221
+ recencyAt: typeof row.recencyAt === "number" ? row.recencyAt : null
222
+ }, previewStates[index], cache);
223
+ if (preview !== void 0) row.preview = preview;
224
+ }
225
+ } catch (error) {
226
+ pending.reject(error instanceof Error ? error : new Error("Codex catalog projection failed", { cause: error }), false);
227
+ return false;
228
+ }
229
+ recordCodexCatalogResponseSource(pending.method, response.result, source);
230
+ pending.resolve(response.result);
231
+ return nativeExecution;
89
232
  }
233
+ //#endregion
234
+ //#region extensions/codex/src/app-server/request-attempt.ts
235
+ /** One wire attempt; local waiter expiry need not imply a native response. */
236
+ function createCodexRequestAttempt(params) {
237
+ let pending = true;
238
+ let mayHaveWritten = false;
239
+ const waiters = /* @__PURE__ */ new Set();
240
+ const diagnostics = params.diagnosticIdentity ? {
241
+ ...params.diagnosticIdentity,
242
+ waiterOrdinal: 0,
243
+ attemptCreatedAtMs: performance.now(),
244
+ firstPossibleWriteAtMs: null,
245
+ wireOutcomeAtWaiterSettlement: "retained-pending",
246
+ wireObservedAtMs: null
247
+ } : void 0;
248
+ const finish = (outcome) => {
249
+ if (!pending) return false;
250
+ pending = false;
251
+ if (diagnostics) {
252
+ diagnostics.wireOutcomeAtWaiterSettlement = outcome;
253
+ diagnostics.wireObservedAtMs = performance.now();
254
+ }
255
+ params.onSettled();
256
+ return true;
257
+ };
258
+ const rejectWaiters = (error, outcome) => {
259
+ for (const waiter of waiters) waiter.reject(error, outcome);
260
+ };
261
+ const currentWaiterError = (waiter) => {
262
+ if (!params.retainWritten) return;
263
+ if (waiter.signal?.aborted) return {
264
+ error: params.cancellationError("aborted", mayHaveWritten, waiter.signal.reason),
265
+ outcome: "aborted"
266
+ };
267
+ if (waiter.deadline !== void 0 && performance.now() >= waiter.deadline) return {
268
+ error: params.cancellationError("timed out", mayHaveWritten),
269
+ outcome: "timed-out"
270
+ };
271
+ try {
272
+ waiter.assertCurrent?.();
273
+ } catch (error) {
274
+ return {
275
+ error: toStringifiedError(error),
276
+ outcome: "authority-rejected"
277
+ };
278
+ }
279
+ if (waiter.signal?.aborted) return {
280
+ error: params.cancellationError("aborted", mayHaveWritten, waiter.signal.reason),
281
+ outcome: "aborted"
282
+ };
283
+ if (waiter.deadline !== void 0 && performance.now() >= waiter.deadline) return {
284
+ error: params.cancellationError("timed out", mayHaveWritten),
285
+ outcome: "timed-out"
286
+ };
287
+ };
288
+ return {
289
+ method: params.method,
290
+ get pending() {
291
+ return pending;
292
+ },
293
+ wait(options, deadline) {
294
+ const { timeoutMs, signal, assertCurrent, disposition, overloadAttemptOrdinal } = options;
295
+ let observe = options.attemptWaiterFinished;
296
+ return new Promise((resolve, reject) => {
297
+ if (!pending) {
298
+ reject(/* @__PURE__ */ new Error("Codex request attempt is already settled"));
299
+ return;
300
+ }
301
+ let timer;
302
+ let removeAbort;
303
+ const waiterOrdinal = diagnostics ? ++diagnostics.waiterOrdinal : 0;
304
+ const waiterAttachedAtMs = diagnostics && observe ? performance.now() : 0;
305
+ const cleanup = () => {
306
+ clearTimeout(timer);
307
+ timer = void 0;
308
+ removeAbort?.();
309
+ removeAbort = void 0;
310
+ };
311
+ const detach = (waiterOutcome) => {
312
+ if (!waiters.delete(waiter)) return false;
313
+ cleanup();
314
+ if (waiters.size === 0 && (!params.retainWritten || !mayHaveWritten)) finish(mayHaveWritten ? "correlation-closed" : "not-written");
315
+ const callback = observe;
316
+ observe = void 0;
317
+ if (diagnostics && callback) try {
318
+ callback({
319
+ ...diagnostics,
320
+ waiterOrdinal,
321
+ disposition,
322
+ overloadAttemptOrdinal,
323
+ waiterAttachedAtMs,
324
+ waiterSettledAtMs: performance.now(),
325
+ waiterOutcome
326
+ });
327
+ } catch {}
328
+ return true;
329
+ };
330
+ const waiter = {
331
+ resolve: (value) => {
332
+ if (!detach("resolved")) return;
333
+ resolve(value);
334
+ },
335
+ reject: (error, outcome) => {
336
+ if (detach(outcome)) reject(error);
337
+ },
338
+ cleanup,
339
+ signal,
340
+ ...params.retainWritten ? {
341
+ deadline,
342
+ assertCurrent
343
+ } : {}
344
+ };
345
+ waiters.add(waiter);
346
+ if (params.retainWritten && deadline !== void 0 && performance.now() >= deadline) {
347
+ waiter.reject(params.cancellationError("timed out", mayHaveWritten), "timed-out");
348
+ return;
349
+ }
350
+ if (timeoutMs && Number.isFinite(timeoutMs) && timeoutMs > 0) {
351
+ const remaining = params.retainWritten && deadline !== void 0 ? deadline - performance.now() : timeoutMs;
352
+ timer = setTimeout(() => waiter.reject(params.cancellationError("timed out", mayHaveWritten), "timed-out"), Math.max(params.retainWritten ? 1 : 100, remaining));
353
+ timer.unref?.();
354
+ }
355
+ if (signal) {
356
+ const abort = () => waiter.reject(params.cancellationError("aborted", mayHaveWritten, signal.reason), "aborted");
357
+ signal.addEventListener("abort", abort, { once: true });
358
+ removeAbort = () => signal.removeEventListener("abort", abort);
359
+ if (signal.aborted) abort();
360
+ }
361
+ });
362
+ },
363
+ resolve(value) {
364
+ if (!finish("native-ok")) return;
365
+ params.onResponse?.(mayHaveWritten);
366
+ for (const waiter of waiters) {
367
+ const error = currentWaiterError(waiter);
368
+ if (error) waiter.reject(error.error, error.outcome);
369
+ else waiter.resolve(value);
370
+ }
371
+ },
372
+ reject(error, definitelyNotEnqueued = false) {
373
+ if (finish(definitelyNotEnqueued ? "ingress-rejected" : "native-error")) {
374
+ if (definitelyNotEnqueued) mayHaveWritten = false;
375
+ params.onResponse?.(mayHaveWritten);
376
+ for (const waiter of waiters) {
377
+ const current = currentWaiterError(waiter);
378
+ waiter.reject(current?.error ?? params.localError(error, mayHaveWritten), current?.outcome ?? "native-error");
379
+ }
380
+ }
381
+ },
382
+ close(error) {
383
+ if (finish("correlation-closed")) rejectWaiters(params.localError(error, mayHaveWritten), "client-closed");
384
+ },
385
+ failLocal(error) {
386
+ if (!pending) return;
387
+ if (!params.retainWritten || !mayHaveWritten) finish(mayHaveWritten ? "correlation-closed" : "not-written");
388
+ rejectWaiters(params.localError(error, mayHaveWritten), "local-failed");
389
+ },
390
+ markWritten() {
391
+ mayHaveWritten = true;
392
+ if (diagnostics && diagnostics.firstPossibleWriteAtMs === null) diagnostics.firstPossibleWriteAtMs = performance.now();
393
+ },
394
+ cleanup() {
395
+ for (const waiter of waiters) waiter.cleanup();
396
+ }
397
+ };
398
+ }
399
+ //#endregion
400
+ //#region extensions/codex/src/app-server/dynamic-tool-response-state.ts
90
401
  function createFailedDynamicToolResponse(message, options) {
91
- const response = {
402
+ return {
92
403
  contentItems: [{
93
404
  type: "inputText",
94
405
  text: message
95
406
  }],
96
- success: false
407
+ success: false,
408
+ diagnosticTerminalReason: options?.terminalReason ?? "failed",
409
+ diagnosticTerminalType: "error",
410
+ executionStarted: options?.executionStarted,
411
+ executedArguments: options?.executedArguments,
412
+ sideEffectEvidence: options?.sideEffectEvidence === true || void 0
97
413
  };
98
- Object.defineProperties(response, {
99
- diagnosticTerminalReason: {
100
- configurable: true,
101
- enumerable: false,
102
- value: options?.terminalReason ?? "failed"
103
- },
104
- diagnosticTerminalType: {
105
- configurable: true,
106
- enumerable: false,
107
- value: "error"
414
+ }
415
+ function failedToolResult(message, status = "failed") {
416
+ return {
417
+ content: [{
418
+ type: "text",
419
+ text: message
420
+ }],
421
+ details: {
422
+ status,
423
+ error: message
108
424
  }
109
- });
110
- if (options?.executionStarted !== void 0) Object.defineProperty(response, "executionStarted", {
111
- configurable: true,
112
- enumerable: false,
113
- value: options.executionStarted
114
- });
115
- if (options?.executedArguments !== void 0) Object.defineProperty(response, "executedArguments", {
116
- configurable: true,
117
- enumerable: false,
118
- value: options.executedArguments
119
- });
120
- return withDynamicToolSideEffectEvidence(response, options?.sideEffectEvidence === true);
425
+ };
121
426
  }
122
427
  //#endregion
123
428
  //#region extensions/codex/src/app-server/tool-abort-terminal-reason.ts
@@ -153,7 +458,7 @@ function resolveCodexToolAbortTerminalReason(signal) {
153
458
  */
154
459
  /** Default timeout for Codex dynamic tool calls. */
155
460
  const CODEX_DYNAMIC_TOOL_TIMEOUT_MS = 9e4;
156
- /** Hard cap for per-call Codex dynamic tool timeout overrides. */
461
+ /** Hard cap for ordinary per-call Codex dynamic tool timeout overrides. */
157
462
  const CODEX_DYNAMIC_TOOL_MAX_TIMEOUT_MS = 6e5;
158
463
  const CODEX_DYNAMIC_TOOL_TIMEOUT_SECONDS_GRACE_MS = 3e4;
159
464
  const CODEX_DYNAMIC_IMAGE_GENERATION_TOOL_TIMEOUT_MS = 12e4;
@@ -213,11 +518,13 @@ function formatDynamicToolTimeoutDetails(params) {
213
518
  }
214
519
  };
215
520
  }
216
- /**
217
- * Runs a dynamic tool call with run-abort and the budget prepared by
218
- * resolveDynamicToolCallTimeoutMs, preserving tool-specific completion grace.
219
- */
220
521
  async function handleDynamicToolCallWithTimeout(params) {
522
+ return await runWithAsyncWorkResources((onAcquired) => executeDynamicToolCallWithTimeout(params, (release) => onAcquired({
523
+ release,
524
+ releaseBeforeResultWhenIdle: true
525
+ })));
526
+ }
527
+ async function executeDynamicToolCallWithTimeout(params, retainCleanup) {
221
528
  let didNotifyAgentToolResult = false;
222
529
  const conservativeRaceResponses = /* @__PURE__ */ new WeakSet();
223
530
  const finalizeTerminal = (response) => {
@@ -227,15 +534,25 @@ async function handleDynamicToolCallWithTimeout(params) {
227
534
  const terminalResolution = params.observeToolTerminal?.({
228
535
  toolCallId: params.call.callId,
229
536
  toolName: params.call.tool,
230
- result: response,
537
+ result: copyInternalToolResultState(response, {
538
+ ...response,
539
+ details: response.transcriptDetails
540
+ }),
231
541
  arguments: response.executedArguments ?? executionSnapshot?.executedArguments ?? params.call.arguments,
232
542
  ...params.toolMeta ? { meta: params.toolMeta } : {},
233
543
  ...ownerKey ? { ownerMutation: { ownerKey } } : {},
544
+ replaySafe: ownerKey ? false : response.replaySafe,
234
545
  ...observedExecutionStarted !== void 0 ? { executionStarted: observedExecutionStarted } : {},
235
546
  outcome: response.success ? "success" : "failure",
236
547
  ...!response.success ? { failure: { error: readDynamicToolResponseText(response) } } : {}
237
548
  });
238
- return withDynamicToolTerminalResolution(response, terminalResolution);
549
+ if (terminalResolution) {
550
+ response.terminalResolution = terminalResolution;
551
+ response.executionStarted = terminalResolution.executionStarted;
552
+ response.executedArguments = terminalResolution.executedArguments ?? response.executedArguments;
553
+ response.sideEffectEvidence = terminalResolution.sideEffectEvidence || void 0;
554
+ }
555
+ return response;
239
556
  };
240
557
  const createFailedAfterPossibleDispatch = (message, terminalReason) => {
241
558
  const response = createFailedDynamicToolResponse(message, {
@@ -285,15 +602,26 @@ async function handleDynamicToolCallWithTimeout(params) {
285
602
  const controller = new AbortController();
286
603
  let timeout;
287
604
  let timedOut = false;
605
+ let toolCallSettled = false;
606
+ let completedSuccessfully = false;
607
+ let operationReleased = false;
288
608
  let resolveAbort;
289
609
  const abortFromRun = () => {
290
610
  const message = "OpenClaw dynamic tool call aborted.";
291
611
  const terminalReason = resolveCodexToolAbortTerminalReason(params.signal);
292
- params.onFallbackSelected?.();
293
612
  controller.abort(params.signal.reason ?? /* @__PURE__ */ new Error(message));
613
+ if (toolCallSettled) return;
614
+ params.onFallbackSelected?.();
294
615
  notifyFailedToolResult(message, terminalReason);
295
616
  resolveAbort?.(createFailedAfterPossibleDispatch(message, terminalReason));
296
617
  };
618
+ const releaseOperation = () => {
619
+ if (operationReleased) return;
620
+ operationReleased = true;
621
+ params.signal.removeEventListener("abort", abortFromRun);
622
+ if (!controller.signal.aborted) controller.abort(/* @__PURE__ */ new Error("OpenClaw dynamic tool call finished."));
623
+ };
624
+ retainCleanup(releaseOperation);
297
625
  const abortPromise = new Promise((resolve) => {
298
626
  resolveAbort = resolve;
299
627
  });
@@ -331,7 +659,9 @@ async function handleDynamicToolCallWithTimeout(params) {
331
659
  timeoutPromise
332
660
  ]);
333
661
  if (!response.success && !didNotifyAgentToolResult) notifyFailedToolResult(readDynamicToolResponseText(response), response.diagnosticTerminalReason ?? "failed");
334
- return finalizeTerminal(response);
662
+ const terminal = finalizeTerminal(response);
663
+ completedSuccessfully = terminal.success;
664
+ return terminal;
335
665
  } catch (error) {
336
666
  const terminalReason = params.signal.aborted ? resolveCodexToolAbortTerminalReason(params.signal) : resolveToolExecutionErrorKind(error);
337
667
  const message = formatToolExecutionErrorMessage(error, "OpenClaw dynamic tool call failed.");
@@ -339,9 +669,9 @@ async function handleDynamicToolCallWithTimeout(params) {
339
669
  return finalizeTerminal(createFailedAfterPossibleDispatch(message, terminalReason));
340
670
  } finally {
341
671
  if (timeout) clearTimeout(timeout);
342
- params.signal.removeEventListener("abort", abortFromRun);
672
+ toolCallSettled = true;
343
673
  resolveAbort = void 0;
344
- if (!timedOut && !controller.signal.aborted) controller.abort(/* @__PURE__ */ new Error("OpenClaw dynamic tool call finished."));
674
+ if (!completedSuccessfully || timedOut || controller.signal.aborted) releaseOperation();
345
675
  }
346
676
  }
347
677
  function readDynamicToolResponseText(response) {
@@ -413,6 +743,10 @@ function hasPendingDynamicToolTerminalDiagnostic(params) {
413
743
  /** Resolves per-tool timeout, applying media/message defaults and hard caps. */
414
744
  function resolveDynamicToolCallTimeoutMs(params) {
415
745
  const args = isJsonObject(params.call.arguments) ? params.call.arguments : void 0;
746
+ if (params.call.tool === "node_exec") {
747
+ const executionTimeoutMs = params.toolBridge?.availableTools.find((tool) => tool.name === params.call.tool)?.getExecutionTimeoutMs?.(params.call.arguments);
748
+ if (executionTimeoutMs !== void 0) return addSafeTimeoutDelayGraceMs(executionTimeoutMs, CODEX_DYNAMIC_TOOL_TIMEOUT_SECONDS_GRACE_MS);
749
+ }
416
750
  if (params.call.tool === "openclaw" || params.call.tool === "ask_user" || params.call.tool === "secrets" && args?.action === "request") try {
417
751
  const timeoutSeconds = params.call.tool === "openclaw" ? void 0 : args?.timeoutSeconds;
418
752
  return normalizeQuestionTimeoutSeconds(timeoutSeconds) * 1e3 + CODEX_DYNAMIC_TOOL_TIMEOUT_SECONDS_GRACE_MS;
@@ -459,7 +793,6 @@ function readConfiguredDynamicToolTimeoutMs(toolName, config) {
459
793
  const capabilityTimeoutMs = readTimeoutSecondsAsMs(config?.tools?.media?.image?.timeoutSeconds);
460
794
  return Math.max(capabilityTimeoutMs ?? CODEX_DYNAMIC_IMAGE_TOOL_TIMEOUT_MS, ...candidates.map((entry) => readTimeoutSecondsAsMs(entry.timeoutSeconds) ?? capabilityTimeoutMs ?? CODEX_DYNAMIC_IMAGE_TOOL_TIMEOUT_MS));
461
795
  }
462
- if (toolName === "message") return CODEX_DYNAMIC_MESSAGE_TOOL_TIMEOUT_MS;
463
796
  }
464
797
  function readTimeoutSecondsAsMs(value) {
465
798
  const seconds = readPositiveFiniteTimeoutMs(value);
@@ -2808,60 +3141,16 @@ const threadStartResponseSchema = materializeCodexSchema(ThreadStartResponse_def
2808
3141
  const turnCompletedNotificationSchema = materializeCodexSchema(TurnCompletedNotification_default);
2809
3142
  const turnStartResponseSchema = materializeCodexSchema(TurnStartResponse_default);
2810
3143
  function compileCodexSchema(schema) {
2811
- const validator = Compile(normalizeJsonSchemaNode(schema));
3144
+ if (typeof schema !== "boolean" && !isRecord(schema)) throw new TypeError("Generated Codex schema must be an object or boolean");
3145
+ const validator = Compile(normalizeJsonSchemaForTypeBox(schema));
2812
3146
  return {
2813
3147
  check: (value) => validator.Check(value),
2814
3148
  errors: (value) => [...validator.Errors(value)]
2815
3149
  };
2816
3150
  }
2817
- const schemaMapKeywords = /* @__PURE__ */ new Set([
2818
- "$defs",
2819
- "definitions",
2820
- "dependentSchemas",
2821
- "patternProperties",
2822
- "properties"
2823
- ]);
2824
- const schemaValueKeywords = /* @__PURE__ */ new Set([
2825
- "additionalItems",
2826
- "additionalProperties",
2827
- "contains",
2828
- "else",
2829
- "if",
2830
- "items",
2831
- "not",
2832
- "propertyNames",
2833
- "then",
2834
- "unevaluatedItems",
2835
- "unevaluatedProperties"
2836
- ]);
2837
- const schemaArrayKeywords = /* @__PURE__ */ new Set([
2838
- "allOf",
2839
- "anyOf",
2840
- "oneOf",
2841
- "prefixItems"
2842
- ]);
2843
3151
  function schemaTypeIncludes(schema, type) {
2844
3152
  return schema.type === type || Array.isArray(schema.type) && schema.type.includes(type);
2845
3153
  }
2846
- function normalizeSchemaMap(value) {
2847
- if (!isRecord(value)) return value;
2848
- return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, normalizeJsonSchemaNode(entry)]));
2849
- }
2850
- function expandJsonSchemaTypeArray(schema) {
2851
- const { type, ...rest } = schema;
2852
- if (!Array.isArray(type)) return schema;
2853
- return { anyOf: type.map((entry) => Object.assign({}, rest, { type: entry })) };
2854
- }
2855
- function normalizeJsonSchemaNode(schema) {
2856
- if (Array.isArray(schema)) return schema.map((entry) => normalizeJsonSchemaNode(entry));
2857
- if (!isRecord(schema)) return schema;
2858
- const normalizedSchema = expandJsonSchemaTypeArray(schema);
2859
- return Object.fromEntries(Object.entries(normalizedSchema).map(([key, value]) => {
2860
- if (schemaMapKeywords.has(key)) return [key, normalizeSchemaMap(value)];
2861
- if (schemaValueKeywords.has(key) || schemaArrayKeywords.has(key)) return [key, normalizeJsonSchemaNode(value)];
2862
- return [key, value];
2863
- }));
2864
- }
2865
3154
  function readDefault(schema) {
2866
3155
  if (!isRecord(schema) || !Object.hasOwn(schema, "default")) return;
2867
3156
  return structuredClone(schema.default);
@@ -2950,14 +3239,15 @@ function assertCodexThreadAcceptsDirectInput(thread) {
2950
3239
  }
2951
3240
  /** Asserts and normalizes a Codex turn/start response. */
2952
3241
  function assertCodexTurnStartResponse(value) {
2953
- const normalized = normalizeWithDefaults(turnStartResponseSchema, normalizeTurnEnvelope(value));
3242
+ const normalized = normalizeWithDefaults(turnStartResponseSchema, value);
2954
3243
  return assertCodexShape(validateTurnStartResponse, normalized, "turn/start response");
2955
3244
  }
2956
- /** Only the current text prompt may be echoed; capabilities and historical items are not passive. */
2957
- function assertCodexPassiveTurnItems(items, prompt, taskLabel) {
3245
+ /** Prompt echoes and attested managed-hook continuations cannot admit native capabilities. */
3246
+ function assertCodexPassiveTurnItems(items, prompt, taskLabel, options = {}) {
2958
3247
  let promptEchoSeen = false;
2959
3248
  for (const item of items) {
2960
3249
  if (item.type === "agentMessage" || item.type === "reasoning") continue;
3250
+ if (item.type === "hookPrompt" && options.allowManagedHookPrompts === true && Array.isArray(item.fragments) && item.fragments.length > 0 && item.fragments.every((fragment) => isJsonObject(fragment) && typeof fragment.text === "string" && typeof fragment.hookRunId === "string" && fragment.hookRunId.trim().length > 0)) continue;
2961
3251
  if (item.type === "userMessage" && !promptEchoSeen) {
2962
3252
  const content = Array.isArray(item.content) ? item.content : [];
2963
3253
  const input = content[0];
@@ -2981,13 +3271,10 @@ function readCodexErrorNotification(value) {
2981
3271
  function assertCodexModelListResponse(value) {
2982
3272
  return assertCodexShape(validateModelListResponse, normalizeWithDefaults(modelListResponseSchema, value), "model/list response");
2983
3273
  }
2984
- /** Reads and normalizes a Codex turn object. */
2985
- function readCodexTurn(value) {
2986
- return readCodexShape(validateTurnStartResponse, normalizeWithDefaults(turnStartResponseSchema, { turn: normalizeTurn(value) }))?.turn;
2987
- }
2988
3274
  /** Reads a Codex turn/completed notification payload if it matches the protocol schema. */
2989
3275
  function readCodexTurnCompletedNotification(value) {
2990
- return readCodexShape(validateTurnCompletedNotification, normalizeWithDefaults(turnCompletedNotificationSchema, normalizeTurnEnvelope(value)));
3276
+ const notification = readCodexShape(validateTurnCompletedNotification, normalizeWithDefaults(turnCompletedNotificationSchema, value));
3277
+ return notification?.turn.status === "inProgress" ? void 0 : notification;
2991
3278
  }
2992
3279
  function assertCodexShape(validate, value, label) {
2993
3280
  if (validate.check(value)) return value;
@@ -2996,62 +3283,141 @@ function assertCodexShape(validate, value, label) {
2996
3283
  function readCodexShape(validate, value) {
2997
3284
  return validate.check(value) ? value : void 0;
2998
3285
  }
2999
- function normalizeTurn(value) {
3000
- if (!value || typeof value !== "object" || Array.isArray(value)) return value;
3001
- return {
3002
- error: null,
3003
- startedAt: null,
3004
- completedAt: null,
3005
- durationMs: null,
3006
- ...value,
3007
- items: Array.isArray(value.items) ? value.items.map(normalizeThreadItem) : []
3008
- };
3286
+ function formatValidationErrors(validate, value) {
3287
+ const errors = validate.errors(value);
3288
+ if (!errors || errors.length === 0) return "schema validation failed";
3289
+ return errors.map((error) => {
3290
+ const message = error.message?.trim() || "schema validation failed";
3291
+ return error.instancePath ? `${error.instancePath} ${message}` : message;
3292
+ }).join("; ");
3009
3293
  }
3010
- function normalizeThreadItem(value) {
3011
- if (!value || typeof value !== "object" || Array.isArray(value)) return value;
3012
- switch (value.type) {
3013
- case "agentMessage": return {
3014
- phase: null,
3015
- delivery: null,
3016
- memoryCitation: null,
3017
- ...value
3294
+ //#endregion
3295
+ //#region extensions/codex/src/app-server/server-requests.ts
3296
+ var CodexServerRequestResolvedError = class extends Error {
3297
+ constructor() {
3298
+ super("Codex server request resolved by another client");
3299
+ this.name = "CodexServerRequestResolvedError";
3300
+ }
3301
+ };
3302
+ /** Physical-client owner for inbound requests, cancellation, and response deadlines. */
3303
+ var CodexServerRequests = class {
3304
+ constructor(respond) {
3305
+ this.respond = respond;
3306
+ this.handlers = /* @__PURE__ */ new Set();
3307
+ this.active = /* @__PURE__ */ new Map();
3308
+ }
3309
+ resolve(params) {
3310
+ if (!isJsonObject(params) || typeof params.threadId !== "string") return;
3311
+ const id = params.requestId;
3312
+ if (typeof id !== "string" && typeof id !== "number") return;
3313
+ const request = this.active.get(id);
3314
+ if (request?.threadId === params.threadId) {
3315
+ this.active.delete(id);
3316
+ request.controller.abort(new CodexServerRequestResolvedError());
3317
+ }
3318
+ }
3319
+ close(error) {
3320
+ const requests = [...this.active.values()];
3321
+ this.active.clear();
3322
+ for (const request of requests) request.controller.abort(error);
3323
+ }
3324
+ async handle(request) {
3325
+ const controller = new AbortController();
3326
+ const entry = {
3327
+ threadId: isJsonObject(request.params) ? request.params.threadId : void 0,
3328
+ controller
3018
3329
  };
3019
- case "plan": return {
3020
- text: "",
3021
- ...value
3330
+ this.active.set(request.id, entry);
3331
+ const deadline = createDeferred();
3332
+ const onAbort = () => deadline.resolve(void 0);
3333
+ controller.signal.addEventListener("abort", onAbort, { once: true });
3334
+ let timeout;
3335
+ let timeoutMs = resolveDynamicToolServerRequestTimeoutMs(readCodexDynamicToolCallParams(request.params));
3336
+ let settled = false;
3337
+ let executionTimeoutResolved = false;
3338
+ const armTimeout = () => {
3339
+ clearTimeout(timeout);
3340
+ timeout = setTimeout(() => {
3341
+ embeddedAgentLog.warn("codex app-server server request timed out", {
3342
+ id: request.id,
3343
+ method: request.method,
3344
+ timeoutMs
3345
+ });
3346
+ deadline.resolve(timeoutServerRequestResponse(timeoutMs));
3347
+ controller.abort(/* @__PURE__ */ new Error("codex app-server server request timed out"));
3348
+ }, timeoutMs);
3349
+ timeout.unref?.();
3022
3350
  };
3023
- case "reasoning": return {
3024
- summary: [],
3025
- content: [],
3026
- ...value
3351
+ const setExecutionTimeoutMs = (executionTimeoutMs) => {
3352
+ if (settled || controller.signal.aborted || executionTimeoutResolved || !Number.isFinite(executionTimeoutMs) || executionTimeoutMs <= 0) return;
3353
+ executionTimeoutResolved = true;
3354
+ timeoutMs = addSafeTimeoutDelayGraceMs(executionTimeoutMs, 3e4);
3355
+ armTimeout();
3027
3356
  };
3028
- case "dynamicToolCall": return {
3029
- namespace: null,
3030
- arguments: null,
3031
- status: "completed",
3032
- contentItems: null,
3033
- success: null,
3034
- durationMs: null,
3035
- ...value
3357
+ const dynamicTool = request.method === "item/tool/call";
3358
+ if (dynamicTool) armTimeout();
3359
+ const run = async () => {
3360
+ for (const handler of this.handlers) {
3361
+ if (controller.signal.aborted) return;
3362
+ const result = await handler(request, controller.signal, dynamicTool ? setExecutionTimeoutMs : void 0);
3363
+ if (result !== void 0) return result;
3364
+ }
3036
3365
  };
3037
- default: return value;
3366
+ try {
3367
+ const result = await Promise.race([run(), deadline.promise]);
3368
+ if (this.active.get(request.id) === entry) this.respond({
3369
+ id: request.id,
3370
+ result: result === void 0 ? defaultServerRequestResponse(request) : result
3371
+ });
3372
+ } catch (error) {
3373
+ if (this.active.get(request.id) === entry) {
3374
+ embeddedAgentLog.warn("codex app-server server request handler failed", {
3375
+ id: request.id,
3376
+ method: request.method,
3377
+ error
3378
+ });
3379
+ this.respond({
3380
+ id: request.id,
3381
+ error: {
3382
+ code: -32603,
3383
+ message: coerceErrorMessage(error)
3384
+ }
3385
+ });
3386
+ }
3387
+ } finally {
3388
+ settled = true;
3389
+ clearTimeout(timeout);
3390
+ controller.signal.removeEventListener("abort", onAbort);
3391
+ if (this.active.get(request.id) === entry) this.active.delete(request.id);
3392
+ }
3038
3393
  }
3394
+ };
3395
+ function defaultServerRequestResponse(request) {
3396
+ if (request.method === "item/tool/call") return {
3397
+ contentItems: [{
3398
+ type: "inputText",
3399
+ text: "OpenClaw did not register a handler for this app-server tool call."
3400
+ }],
3401
+ success: false
3402
+ };
3403
+ if (request.method === "item/commandExecution/requestApproval" || request.method === "item/fileChange/requestApproval") return { decision: "decline" };
3404
+ if (request.method === "item/permissions/requestApproval") return {
3405
+ permissions: {},
3406
+ scope: "turn"
3407
+ };
3408
+ if (request.method === "item/tool/requestUserInput") return { answers: {} };
3409
+ if (request.method === "mcpServer/elicitation/request") return createCodexElicitationResponse("decline", null, { message: "OpenClaw has no interactive handler for this elicitation." });
3410
+ return {};
3039
3411
  }
3040
- function normalizeTurnEnvelope(value) {
3041
- if (!value || typeof value !== "object" || Array.isArray(value) || !("turn" in value)) return value;
3412
+ function timeoutServerRequestResponse(timeoutMs) {
3042
3413
  return {
3043
- ...value,
3044
- turn: normalizeTurn(value.turn)
3414
+ contentItems: [{
3415
+ type: "inputText",
3416
+ text: `OpenClaw dynamic tool call timed out after ${timeoutMs}ms before sending a response to Codex.`
3417
+ }],
3418
+ success: false
3045
3419
  };
3046
3420
  }
3047
- function formatValidationErrors(validate, value) {
3048
- const errors = validate.errors(value);
3049
- if (!errors || errors.length === 0) return "schema validation failed";
3050
- return errors.map((error) => {
3051
- const message = error.message?.trim() || "schema validation failed";
3052
- return error.instancePath ? `${error.instancePath} ${message}` : message;
3053
- }).join("; ");
3054
- }
3055
3421
  //#endregion
3056
3422
  //#region extensions/codex/src/app-server/transport-websocket.ts
3057
3423
  /**
@@ -3085,6 +3451,7 @@ function createWebSocketTransport(options) {
3085
3451
  const stdinDecoder = new StringDecoder("utf8");
3086
3452
  let pendingLine = "";
3087
3453
  let killed = false;
3454
+ let exitCode = null;
3088
3455
  let pingTimeout;
3089
3456
  let pongTimeout;
3090
3457
  let expectedPong;
@@ -3160,12 +3527,18 @@ function createWebSocketTransport(options) {
3160
3527
  socket.once("close", (code, reason) => {
3161
3528
  clearConnectionHealthTimers();
3162
3529
  killed = true;
3530
+ exitCode = code;
3163
3531
  events.emit("exit", code, reason.toString("utf8"));
3164
3532
  });
3165
3533
  socket.on("message", (data) => {
3166
3534
  if (options.transport === "websocket") recordConnectionActivity();
3167
- const text = websocketFrameToText(data);
3168
- stdout.write(text.endsWith("\n") ? text : `${text}\n`);
3535
+ const frame = websocketFrameToBuffer(data);
3536
+ const writable = stdout.write(frame);
3537
+ const delimited = frame.at(-1) === 10 || stdout.write(Buffer.from("\n"));
3538
+ if (!writable || !delimited) socket.pause();
3539
+ });
3540
+ stdout.on("drain", () => {
3541
+ if (socket.readyState === WebSocket.OPEN) socket.resume();
3169
3542
  });
3170
3543
  const stdin = new Writable({
3171
3544
  write(chunk, _encoding, callback) {
@@ -3196,12 +3569,17 @@ function createWebSocketTransport(options) {
3196
3569
  get killed() {
3197
3570
  return killed;
3198
3571
  },
3199
- kill: () => {
3572
+ get exitCode() {
3573
+ return exitCode;
3574
+ },
3575
+ kill: (signal) => {
3200
3576
  killed = true;
3201
3577
  clearConnectionHealthTimers();
3202
- socket.close();
3578
+ if (signal === "SIGKILL") socket.terminate();
3579
+ else socket.close();
3203
3580
  },
3204
- once: (event, listener) => events.once(event, listener)
3581
+ once: (event, listener) => events.once(event, listener),
3582
+ off: (event, listener) => events.off(event, listener)
3205
3583
  };
3206
3584
  }
3207
3585
  /** Opens the owner-scoped Codex control socket used by the WebSocket upgrade. */
@@ -3218,11 +3596,11 @@ function resolveCodexAppServerUnixSocketPath(options) {
3218
3596
  if (!url.startsWith("unix://")) throw new Error("codex app-server unix transport requires a unix:// URL");
3219
3597
  return url.slice(7) || path.join(resolveCodexAppServerUserHomeDir(options.env ?? process.env), "app-server-control", "app-server-control.sock");
3220
3598
  }
3221
- function websocketFrameToText(data) {
3222
- if (typeof data === "string") return data;
3223
- if (Buffer.isBuffer(data)) return data.toString("utf8");
3224
- if (Array.isArray(data)) return Buffer.concat(data).toString("utf8");
3225
- return Buffer.from(data).toString("utf8");
3599
+ function websocketFrameToBuffer(data) {
3600
+ if (typeof data === "string") return Buffer.from(data);
3601
+ if (Buffer.isBuffer(data)) return data;
3602
+ if (Array.isArray(data)) return Buffer.concat(data);
3603
+ return Buffer.from(data);
3226
3604
  }
3227
3605
  //#endregion
3228
3606
  //#region extensions/codex/src/app-server/client.ts
@@ -3244,16 +3622,11 @@ var client_exports = /* @__PURE__ */ __exportAll({
3244
3622
  isUnsupportedCodexAppServerVersionError: () => isUnsupportedCodexAppServerVersionError,
3245
3623
  resolveCodexAppServerClientInstanceId: () => resolveCodexAppServerClientInstanceId
3246
3624
  });
3247
- const CODEX_APP_SERVER_PARSE_LOG_MAX = 500;
3248
- const CODEX_APP_SERVER_PARSE_BUFFER_MAX = 8388608;
3249
- const CODEX_APP_SERVER_PARSE_BUFFER_MAX_LINES = 1e3;
3250
3625
  const CODEX_APP_SERVER_STDERR_TAIL_MAX = 2e3;
3251
- const CODEX_APP_SERVER_OVERLOADED_ERROR_CODE = -32001;
3252
3626
  const CODEX_APP_SERVER_OVERLOAD_MAX_RETRIES = 3;
3253
3627
  const CODEX_APP_SERVER_OVERLOAD_RETRY_BASE_MS = 50;
3254
3628
  const CODEX_APP_SERVER_PENDING_STARTUP_WARNINGS_MAX = 32;
3255
3629
  const CODEX_APP_SERVER_CLIENT_INSTANCE_IDS = /* @__PURE__ */ new WeakMap();
3256
- const UNPAIRED_SURROGATE_RE = /[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g;
3257
3630
  /** Process-local generation fence for bindings tied to one app-server client instance. */
3258
3631
  function getCodexAppServerClientInstanceId(client) {
3259
3632
  const current = CODEX_APP_SERVER_CLIENT_INSTANCE_IDS.get(client);
@@ -3267,11 +3640,12 @@ function resolveCodexAppServerClientInstanceId(client) {
3267
3640
  }
3268
3641
  /** Codex rejects this exact code before enqueueing, including mutating requests. */
3269
3642
  function isCodexAppServerOverloadError(error) {
3270
- return error instanceof CodexAppServerRpcError && error.code === CODEX_APP_SERVER_OVERLOADED_ERROR_CODE;
3643
+ return error instanceof CodexAppServerRpcError && error.code === -32001;
3271
3644
  }
3272
3645
  var CodexAppServerLocalRequestCancellationError = class extends Error {
3273
- constructor(method, reason, mayHaveWritten) {
3274
- super(`${method} ${reason}`);
3646
+ constructor(method, reason, mayHaveWritten, cause) {
3647
+ const detail = cause instanceof Error || typeof cause === "string" ? coerceErrorMessage(cause) : void 0;
3648
+ super(`${method} ${reason}${detail ? `: ${detail}` : ""}`, { cause });
3275
3649
  this.reason = reason;
3276
3650
  this.mayHaveWritten = mayHaveWritten;
3277
3651
  this.code = "CODEX_APP_SERVER_LOCAL_REQUEST_CANCELLED";
@@ -3321,8 +3695,11 @@ function isCodexAppServerConnectionClosedError(error) {
3321
3695
  var CodexAppServerClient = class CodexAppServerClient {
3322
3696
  constructor(child) {
3323
3697
  this.instanceId = randomUUID();
3698
+ this.decoder = new CodexAppServerMessageDecoder(logCodexAppServerParseFailure);
3699
+ this.catalogWorker = new CodexCatalogWorker();
3324
3700
  this.pending = /* @__PURE__ */ new Map();
3325
- this.requestHandlers = /* @__PURE__ */ new Set();
3701
+ this.catalogResponses = /* @__PURE__ */ new WeakMap();
3702
+ this.serverRequests = new CodexServerRequests((response) => this.writeMessage(response));
3326
3703
  this.notificationHandlers = /* @__PURE__ */ new Set();
3327
3704
  this.pendingStartupWarnings = [];
3328
3705
  this.closeHandlers = /* @__PURE__ */ new Set();
@@ -3336,24 +3713,21 @@ var CodexAppServerClient = class CodexAppServerClient {
3336
3713
  this.privateTransportSecrets = /* @__PURE__ */ new Set();
3337
3714
  this.privateStderrPending = "";
3338
3715
  this.child = child;
3339
- this.lines = createInterface({ input: child.stdout });
3340
- this.lines.on("line", (line) => this.handleLine(line));
3341
- this.lines.on("error", (error) => this.closeWithError(toStringifiedError(error)));
3716
+ this.closeMessageReader = listenCodexAppServerLines(child.stdout, (line) => {
3717
+ const route = this.catalogWorker.continuation ?? (this.decoder.hasPending ? void 0 : readCodexCatalogDecodeRoute(line));
3718
+ if (route) return this.decodeCatalogLine(line, route);
3719
+ return this.handleParsedMessage(this.decoder.parse(line.toString("utf8")));
3720
+ }, (error) => this.closeWithError(toStringifiedError(error)));
3342
3721
  child.stdout.on("error", (error) => this.closeWithError(toStringifiedError(error)));
3343
- child.stderr.setEncoding("utf8");
3344
- child.stderr.on("data", (chunk) => {
3722
+ observeCodexAppServerStderr(child.stderr, (chunk) => {
3345
3723
  const text = this.redactPrivateStderr(chunk);
3346
3724
  this.stderrTail = appendBoundedTail(this.stderrTail, text, CODEX_APP_SERVER_STDERR_TAIL_MAX);
3347
- const trimmed = text.trim();
3348
- if (trimmed) embeddedAgentLog.debug(`codex app-server stderr: ${trimmed}`);
3349
- });
3350
- child.stderr.on("error", (error) => {
3351
- embeddedAgentLog.warn("codex app-server stderr stream failed", { error });
3725
+ return text;
3352
3726
  });
3353
3727
  child.once("error", (error) => this.closeWithError(toStringifiedError(error)));
3354
3728
  child.once("exit", (code, signal) => {
3355
3729
  this.transportExited = true;
3356
- this.closeWithError(buildCodexAppServerExitError(code, signal, this.stderrTail));
3730
+ this.closeWithError(child.startupFailure?.error ?? buildCodexAppServerExitError(code, signal, this.stderrTail));
3357
3731
  });
3358
3732
  child.stdin.on?.("error", (error) => this.closeWithError(toStringifiedError(error)));
3359
3733
  }
@@ -3375,7 +3749,7 @@ var CodexAppServerClient = class CodexAppServerClient {
3375
3749
  return client;
3376
3750
  } catch (error) {
3377
3751
  assertCurrent?.();
3378
- if (client?.transportExited && hasCodexAppServerNaturalExit(client.child)) throw buildCodexAppServerExitError(client.child.exitCode, client.child.signalCode, client.stderrTail);
3752
+ if (client?.transportExited && hasCodexAppServerNaturalExit(client.child)) throw client.child.startupFailure?.error ?? buildCodexAppServerExitError(client.child.exitCode, client.child.signalCode, client.stderrTail);
3379
3753
  const stderr = client?.getStderrDiagnostic();
3380
3754
  throw stderr ? new Error(`${coerceErrorMessage(error)}; stderr=${JSON.stringify(stderr)}`, { cause: error }) : error;
3381
3755
  }
@@ -3387,21 +3761,8 @@ var CodexAppServerClient = class CodexAppServerClient {
3387
3761
  /** Performs the app-server initialize handshake and validates protocol version. */
3388
3762
  async initialize() {
3389
3763
  if (this.initialized) return;
3390
- const response = await this.request("initialize", {
3391
- clientInfo: {
3392
- name: "openclaw",
3393
- title: "OpenClaw",
3394
- version: OPENCLAW_VERSION
3395
- },
3396
- capabilities: {
3397
- experimentalApi: true,
3398
- extensions: {
3399
- "openai/standard-form-input": {},
3400
- "openai/form": {},
3401
- "io.modelcontextprotocol/ui": { mimeTypes: ["text/html;profile=mcp-app"] }
3402
- }
3403
- }
3404
- });
3764
+ const response = await this.request("initialize", buildCodexAppServerInitializeParams());
3765
+ this.child.startupFailure?.complete();
3405
3766
  this.serverVersion = assertSupportedCodexAppServerVersion(response);
3406
3767
  this.runtimeIdentity = buildCodexAppServerRuntimeIdentity(response, this.serverVersion);
3407
3768
  this.notify("initialized");
@@ -3431,9 +3792,10 @@ var CodexAppServerClient = class CodexAppServerClient {
3431
3792
  getModelCatalogRevision() {
3432
3793
  return this.modelCatalogRevision;
3433
3794
  }
3434
- /** Installs the spawn-owner check run before config-loading thread requests. */
3435
- setThreadSessionRequestGuard(guard) {
3795
+ /** Installs the spawn-owner guard and retirement for config-loading thread requests. */
3796
+ setThreadSessionRequestGuard(guard, retireAfterIndeterminateRequest) {
3436
3797
  this.threadSessionRequestGuard = guard;
3798
+ this.retireAfterIndeterminateThreadRequest = retireAfterIndeterminateRequest;
3437
3799
  }
3438
3800
  /** Returns the local transport PID for scoped child-process cleanup, when available. */
3439
3801
  getTransportPid() {
@@ -3442,12 +3804,13 @@ var CodexAppServerClient = class CodexAppServerClient {
3442
3804
  request(method, params, optionsInput) {
3443
3805
  const options = optionsInput ?? {};
3444
3806
  if (this.closed) return Promise.reject(this.closeError ?? /* @__PURE__ */ new Error("codex app-server client is closed"));
3445
- if (options.signal?.aborted) return Promise.reject(new CodexAppServerLocalRequestCancellationError(method, "aborted", false));
3807
+ if (options.signal?.aborted) return Promise.reject(new CodexAppServerLocalRequestCancellationError(method, "aborted", false, options.signal?.reason));
3446
3808
  const guard = method === "thread/start" || method === "thread/resume" || method === "thread/fork" ? this.threadSessionRequestGuard : void 0;
3447
3809
  if (guard) {
3810
+ const retire = this.retireAfterIndeterminateThreadRequest;
3448
3811
  if (!options.signal && !(options.timeoutMs !== void 0 && Number.isFinite(options.timeoutMs) && options.timeoutMs > 0)) return Promise.reject(/* @__PURE__ */ new TypeError(`${method} requires a positive finite timeout or abort signal`));
3449
3812
  return (async () => {
3450
- const guardStartedAt = Date.now();
3813
+ const guardStartedAt = performance.now();
3451
3814
  const timeoutMessage = `${method} timed out`;
3452
3815
  const abortMessage = `${method} aborted`;
3453
3816
  let releaseGuard;
@@ -3460,19 +3823,22 @@ var CodexAppServerClient = class CodexAppServerClient {
3460
3823
  });
3461
3824
  } catch (error) {
3462
3825
  if (error instanceof Error && error.message === timeoutMessage) throw new CodexAppServerLocalRequestCancellationError(method, "timed out", false);
3463
- if (error instanceof Error && error.message === abortMessage) throw new CodexAppServerLocalRequestCancellationError(method, "aborted", false);
3826
+ if (error instanceof Error && error.message === abortMessage) throw new CodexAppServerLocalRequestCancellationError(method, "aborted", false, options.signal?.reason);
3464
3827
  throw error;
3465
3828
  }
3466
3829
  let released = false;
3830
+ let removeExitHandler;
3467
3831
  const release = () => {
3468
3832
  if (released) return;
3469
3833
  released = true;
3834
+ removeExitHandler?.();
3470
3835
  releaseGuard();
3471
3836
  };
3472
3837
  let releaseWhenRequestSettles = true;
3473
3838
  let requestMayHaveWritten = false;
3839
+ let nativeResponded = false;
3474
3840
  try {
3475
- const elapsedMs = Date.now() - guardStartedAt;
3841
+ const elapsedMs = performance.now() - guardStartedAt;
3476
3842
  const remainingTimeoutMs = options.timeoutMs === void 0 ? void 0 : options.timeoutMs - elapsedMs;
3477
3843
  if (remainingTimeoutMs !== void 0 && remainingTimeoutMs <= 0) throw new CodexAppServerLocalRequestCancellationError(method, "timed out", false);
3478
3844
  return await this.requestWithOverloadRetry(method, params, {
@@ -3480,11 +3846,17 @@ var CodexAppServerClient = class CodexAppServerClient {
3480
3846
  ...remainingTimeoutMs !== void 0 ? { timeoutMs: remainingTimeoutMs } : {}
3481
3847
  }, (mayHaveWritten) => {
3482
3848
  requestMayHaveWritten = mayHaveWritten;
3849
+ nativeResponded = !mayHaveWritten;
3850
+ }, () => {
3851
+ nativeResponded = true;
3852
+ if (!releaseWhenRequestSettles) release();
3483
3853
  });
3484
3854
  } catch (error) {
3485
3855
  if (requestMayHaveWritten && !(error instanceof CodexAppServerRpcError)) {
3486
3856
  releaseWhenRequestSettles = false;
3487
- await this.closeAndRunAfterExit(release, method);
3857
+ if (nativeResponded) release();
3858
+ else removeExitHandler = this.addTransportExitHandler(release);
3859
+ if (!retire?.()) await this.closeAndRunAfterExit(release, method);
3488
3860
  }
3489
3861
  throw error;
3490
3862
  } finally {
@@ -3494,17 +3866,17 @@ var CodexAppServerClient = class CodexAppServerClient {
3494
3866
  }
3495
3867
  return this.requestWithOverloadRetry(method, params, options);
3496
3868
  }
3497
- async requestWithOverloadRetry(method, params, options, onWriteStateChange) {
3498
- const deadline = options.timeoutMs !== void 0 && Number.isFinite(options.timeoutMs) ? Date.now() + options.timeoutMs : void 0;
3869
+ async requestWithOverloadRetry(method, params, options, onWriteStateChange, onResponse) {
3870
+ const deadline = options.timeoutMs !== void 0 && Number.isFinite(options.timeoutMs) ? performance.now() + options.timeoutMs : void 0;
3499
3871
  for (let retry = 0;; retry += 1) {
3500
- if (options.signal?.aborted) throw new CodexAppServerLocalRequestCancellationError(method, "aborted", false);
3501
- const remainingTimeoutMs = deadline === void 0 ? void 0 : deadline - Date.now();
3872
+ if (options.signal?.aborted) throw new CodexAppServerLocalRequestCancellationError(method, "aborted", false, options.signal?.reason);
3873
+ const remainingTimeoutMs = deadline === void 0 ? void 0 : deadline - performance.now();
3502
3874
  if (remainingTimeoutMs !== void 0 && remainingTimeoutMs <= 0) throw new CodexAppServerLocalRequestCancellationError(method, "timed out", false);
3503
3875
  try {
3504
3876
  return await this.requestOnce(method, params, {
3505
3877
  ...options,
3506
3878
  ...remainingTimeoutMs !== void 0 ? { timeoutMs: remainingTimeoutMs } : {}
3507
- }, onWriteStateChange);
3879
+ }, retry + 1, onWriteStateChange, deadline, onResponse);
3508
3880
  } catch (error) {
3509
3881
  if (!isCodexAppServerOverloadError(error) || retry >= CODEX_APP_SERVER_OVERLOAD_MAX_RETRIES) throw error;
3510
3882
  onWriteStateChange?.(false);
@@ -3514,8 +3886,8 @@ var CodexAppServerClient = class CodexAppServerClient {
3514
3886
  }
3515
3887
  }
3516
3888
  async waitForOverloadRetry(method, backoffMs, deadline, signal) {
3517
- if (signal?.aborted) throw new CodexAppServerLocalRequestCancellationError(method, "aborted", false);
3518
- const remainingMs = deadline === void 0 ? void 0 : deadline - Date.now();
3889
+ if (signal?.aborted) throw new CodexAppServerLocalRequestCancellationError(method, "aborted", false, signal?.reason);
3890
+ const remainingMs = deadline === void 0 ? void 0 : deadline - performance.now();
3519
3891
  if (remainingMs !== void 0 && remainingMs <= 0) throw new CodexAppServerLocalRequestCancellationError(method, "timed out", false);
3520
3892
  const delayMs = remainingMs === void 0 ? backoffMs : Math.min(backoffMs, remainingMs);
3521
3893
  await new Promise((resolve, reject) => {
@@ -3526,7 +3898,7 @@ var CodexAppServerClient = class CodexAppServerClient {
3526
3898
  timer.unref?.();
3527
3899
  const abortListener = () => {
3528
3900
  cleanup();
3529
- reject(new CodexAppServerLocalRequestCancellationError(method, "aborted", false));
3901
+ reject(new CodexAppServerLocalRequestCancellationError(method, "aborted", false, signal?.reason));
3530
3902
  };
3531
3903
  const cleanup = () => {
3532
3904
  clearTimeout(timer);
@@ -3536,69 +3908,55 @@ var CodexAppServerClient = class CodexAppServerClient {
3536
3908
  if (signal?.aborted) abortListener();
3537
3909
  });
3538
3910
  }
3539
- requestOnce(method, params, options, onWriteStateChange) {
3911
+ requestOnce(method, params, options, overloadAttemptOrdinal, onWriteStateChange, deadline, onResponse) {
3540
3912
  if (this.closed) return Promise.reject(this.closeError ?? /* @__PURE__ */ new Error("codex app-server client is closed"));
3541
- if (options.signal?.aborted) return Promise.reject(new CodexAppServerLocalRequestCancellationError(method, "aborted", false));
3542
- const id = this.nextId++;
3913
+ if (options.signal?.aborted) return Promise.reject(new CodexAppServerLocalRequestCancellationError(method, "aborted", false, options.signal?.reason));
3914
+ const id = codexCatalogRequestId(method, params, this.nextId++, options.catalogPreview);
3543
3915
  if (method === "account/login/start" || method === "account/logout" || method === "config/value/write" || method === "config/batchWrite") this.modelCatalogRevision += 1;
3544
3916
  const message = {
3545
3917
  id,
3546
3918
  method,
3547
3919
  params
3548
3920
  };
3549
- return new Promise((resolve, reject) => {
3550
- let timeout;
3551
- let cleanupAbort;
3552
- let mayHaveWritten = false;
3553
- const cleanup = () => {
3554
- if (timeout) {
3555
- clearTimeout(timeout);
3556
- timeout = void 0;
3557
- }
3558
- cleanupAbort?.();
3559
- cleanupAbort = void 0;
3560
- };
3561
- const rejectPending = (error) => {
3562
- if (!this.pending.has(id)) return;
3563
- this.pending.delete(id);
3564
- cleanup();
3565
- reject(mayHaveWritten && !(error instanceof CodexAppServerRpcError) && !isCodexAppServerIndeterminateRequestCancellationError(error) && !isCodexAppServerIndeterminateTransportError(error) ? new CodexAppServerIndeterminateTransportError(method, error) : error);
3566
- };
3567
- if (options.timeoutMs && Number.isFinite(options.timeoutMs) && options.timeoutMs > 0) {
3568
- timeout = setTimeout(() => rejectPending(new CodexAppServerLocalRequestCancellationError(method, "timed out", mayHaveWritten)), Math.max(100, options.timeoutMs));
3569
- timeout.unref?.();
3570
- }
3571
- if (options.signal) {
3572
- const abortListener = () => rejectPending(new CodexAppServerLocalRequestCancellationError(method, "aborted", mayHaveWritten));
3573
- options.signal.addEventListener("abort", abortListener, { once: true });
3574
- cleanupAbort = () => options.signal?.removeEventListener("abort", abortListener);
3575
- }
3576
- this.pending.set(id, {
3577
- method,
3578
- resolve: (value) => {
3579
- cleanup();
3580
- resolve(value);
3581
- },
3582
- reject: (error) => {
3583
- cleanup();
3584
- reject(mayHaveWritten && !(error instanceof CodexAppServerRpcError) && !isCodexAppServerIndeterminateRequestCancellationError(error) && !isCodexAppServerIndeterminateTransportError(error) ? new CodexAppServerIndeterminateTransportError(method, error) : error);
3585
- },
3586
- cleanup
3587
- });
3588
- if (options.signal?.aborted) {
3589
- rejectPending(new CodexAppServerLocalRequestCancellationError(method, "aborted", false));
3590
- return;
3591
- }
3592
- try {
3593
- options.assertCurrent?.();
3594
- this.writeMessage(message, (error) => rejectPending(error), () => {
3595
- mayHaveWritten = true;
3596
- onWriteStateChange?.(true);
3597
- });
3598
- } catch (error) {
3599
- rejectPending(toStringifiedError(error));
3600
- }
3921
+ const attempt = createCodexRequestAttempt({
3922
+ method,
3923
+ retainWritten: onResponse !== void 0,
3924
+ ...method === "thread/list" ? { diagnosticIdentity: {
3925
+ clientInstanceId: this.instanceId,
3926
+ rpcId: id
3927
+ } } : {},
3928
+ onResponse: onResponse ? (mayHaveWritten) => {
3929
+ onWriteStateChange?.(mayHaveWritten);
3930
+ onResponse();
3931
+ } : void 0,
3932
+ onSettled: () => {
3933
+ if (this.pending.get(id) === attempt) this.pending.delete(id);
3934
+ },
3935
+ cancellationError: (reason, written, cause) => new CodexAppServerLocalRequestCancellationError(method, reason, written, cause),
3936
+ localError: (error, written) => written && !(error instanceof CodexAppServerRpcError) && !isCodexAppServerIndeterminateRequestCancellationError(error) && !isCodexAppServerIndeterminateTransportError(error) ? new CodexAppServerIndeterminateTransportError(method, error) : error
3937
+ });
3938
+ this.pending.set(id, attempt);
3939
+ if (options.catalogPreview) this.catalogResponses.set(attempt, {
3940
+ preview: options.catalogPreviewCache,
3941
+ remainingRows: options.catalogRows
3601
3942
  });
3943
+ const result = attempt.wait({
3944
+ ...options,
3945
+ assertCurrent: void 0,
3946
+ disposition: "new",
3947
+ overloadAttemptOrdinal
3948
+ }, deadline);
3949
+ if (!attempt.pending) return result;
3950
+ try {
3951
+ options.assertCurrent?.();
3952
+ if (attempt.pending) this.writeMessage(message, (error) => attempt.failLocal(error), () => {
3953
+ attempt.markWritten();
3954
+ onWriteStateChange?.(true);
3955
+ });
3956
+ } catch (error) {
3957
+ attempt.failLocal(toStringifiedError(error));
3958
+ }
3959
+ return result;
3602
3960
  }
3603
3961
  /** Sends a fire-and-forget JSON-RPC notification to the app-server. */
3604
3962
  notify(method, params) {
@@ -3609,8 +3967,8 @@ var CodexAppServerClient = class CodexAppServerClient {
3609
3967
  }
3610
3968
  /** Registers a handler for app-server requests sent back to OpenClaw. */
3611
3969
  addRequestHandler(handler) {
3612
- this.requestHandlers.add(handler);
3613
- return () => this.requestHandlers.delete(handler);
3970
+ this.serverRequests.handlers.add(handler);
3971
+ return () => this.serverRequests.handlers.delete(handler);
3614
3972
  }
3615
3973
  /** Registers a notification handler and returns its disposer. */
3616
3974
  addNotificationHandler(handler) {
@@ -3641,7 +3999,7 @@ var CodexAppServerClient = class CodexAppServerClient {
3641
3999
  /** Closes the transport and waits for shutdown according to transport policy. */
3642
4000
  async closeAndWait(options) {
3643
4001
  this.markClosed(/* @__PURE__ */ new Error("codex app-server client is closed"));
3644
- const result = await closeCodexAppServerTransportAndWait(this.child, options);
4002
+ const [result] = await Promise.all([closeCodexAppServerTransportAndWait(this.child, options), this.catalogWorkerClosed]);
3645
4003
  return this.nativeExecutionObserved ? {
3646
4004
  ...result,
3647
4005
  cleanup: "uncertain"
@@ -3707,65 +4065,16 @@ var CodexAppServerClient = class CodexAppServerClient {
3707
4065
  this.privateStderrPending = held ? text.slice(-held) : "";
3708
4066
  return held ? text.slice(0, -held) : text;
3709
4067
  }
3710
- handleLine(line) {
3711
- const rawLine = line.endsWith("\r") ? line.slice(0, -1) : line;
3712
- if (this.pendingParse) {
3713
- this.handlePendingParseLine(rawLine);
3714
- return;
3715
- }
3716
- const trimmed = rawLine.trim();
3717
- if (!trimmed) return;
3718
- let parsed;
3719
- try {
3720
- parsed = JSON.parse(trimmed);
3721
- } catch (error) {
3722
- if (shouldBufferCodexAppServerParseFailure(trimmed, error)) {
3723
- this.pendingParse = {
3724
- text: trimmed,
3725
- lineCount: 1,
3726
- firstError: error
3727
- };
3728
- return;
3729
- }
3730
- logCodexAppServerParseFailure(trimmed, error, 1);
3731
- return;
3732
- }
3733
- this.handleParsedMessage(parsed);
3734
- }
3735
- handlePendingParseLine(line) {
3736
- const pending = this.pendingParse;
3737
- if (!pending) return;
3738
- const candidate = `${pending.text}\\n${line}`;
3739
- let parsed;
3740
- try {
3741
- parsed = JSON.parse(candidate);
3742
- } catch (error) {
3743
- const lineCount = pending.lineCount + 1;
3744
- if (shouldBufferCodexAppServerParseFailure(candidate.trim(), error) && candidate.length <= CODEX_APP_SERVER_PARSE_BUFFER_MAX && lineCount <= CODEX_APP_SERVER_PARSE_BUFFER_MAX_LINES) {
3745
- this.pendingParse = {
3746
- text: candidate,
3747
- lineCount,
3748
- firstError: pending.firstError
3749
- };
3750
- return;
3751
- }
3752
- this.pendingParse = void 0;
3753
- logCodexAppServerParseFailure(candidate, error, lineCount);
3754
- return;
3755
- }
3756
- this.pendingParse = void 0;
3757
- this.handleParsedMessage(parsed);
3758
- }
3759
- handleParsedMessage(parsed) {
3760
- if (!parsed || typeof parsed !== "object") return;
4068
+ handleParsedMessage(parsed, previewStates) {
4069
+ if (this.closed || !parsed || typeof parsed !== "object") return;
3761
4070
  const message = parsed;
3762
4071
  if (isRpcResponse(message)) {
3763
- this.handleResponse(message);
4072
+ this.handleResponse(message, previewStates);
3764
4073
  return;
3765
4074
  }
3766
4075
  if (!("method" in message)) return;
3767
4076
  if ("id" in message && message.id !== void 0) {
3768
- this.handleServerRequest({
4077
+ this.serverRequests.handle({
3769
4078
  id: message.id,
3770
4079
  method: message.method,
3771
4080
  params: message.params
@@ -3777,79 +4086,19 @@ var CodexAppServerClient = class CodexAppServerClient {
3777
4086
  params: message.params
3778
4087
  });
3779
4088
  }
3780
- handleResponse(response) {
3781
- const pending = this.pending.get(response.id);
3782
- if (!pending) return;
3783
- this.pending.delete(response.id);
3784
- if (response.error) {
3785
- pending.reject(new CodexAppServerRpcError(response.error, pending.method));
3786
- return;
3787
- }
3788
- if (pending.method === "thread/backgroundTerminals/list" && isJsonObject(response.result) && Array.isArray(response.result.data) && response.result.data.length > 0) this.nativeExecutionObserved = true;
3789
- pending.resolve(response.result);
4089
+ async decodeCatalogLine(line, route) {
4090
+ const decoded = await this.catalogWorker.decode(line, route, this.pending, this.catalogResponses);
4091
+ if (!decoded || this.closed) return;
4092
+ for (const failure of decoded.failures) logCodexAppServerParseFailure(failure.value, failure.error, failure.fragmentCount);
4093
+ if (decoded.projectionError) this.pending.get(decoded.projectionError.id)?.reject(decoded.projectionError.error, false);
4094
+ else if (decoded.message) this.handleParsedMessage(decoded.message, decoded.previewStates);
3790
4095
  }
3791
- async handleServerRequest(request) {
3792
- try {
3793
- const result = await this.runServerRequestHandlers(request);
3794
- if (result !== void 0) {
3795
- this.writeMessage({
3796
- id: request.id,
3797
- result
3798
- });
3799
- return;
3800
- }
3801
- this.writeMessage({
3802
- id: request.id,
3803
- result: defaultServerRequestResponse(request)
3804
- });
3805
- } catch (error) {
3806
- const message = coerceErrorMessage(error);
3807
- embeddedAgentLog.warn("codex app-server server request handler failed", {
3808
- id: request.id,
3809
- method: request.method,
3810
- error
3811
- });
3812
- this.writeMessage({
3813
- id: request.id,
3814
- error: {
3815
- code: -32603,
3816
- message
3817
- }
3818
- });
3819
- }
3820
- }
3821
- async runServerRequestHandlers(request) {
3822
- const controller = new AbortController();
3823
- if (request.method !== "item/tool/call") return await this.runServerRequestHandlersWithoutTimeout(request, controller.signal);
3824
- const timeoutMs = resolveDynamicToolServerRequestTimeoutMs(readCodexDynamicToolCallParams(request.params));
3825
- const timeoutResponse = timeoutServerRequestResponse(timeoutMs);
3826
- let timeout;
3827
- try {
3828
- return await Promise.race([this.runServerRequestHandlersWithoutTimeout(request, controller.signal), new Promise((resolve) => {
3829
- timeout = setTimeout(() => {
3830
- embeddedAgentLog.warn("codex app-server server request timed out", {
3831
- id: request.id,
3832
- method: request.method,
3833
- timeoutMs
3834
- });
3835
- controller.abort(/* @__PURE__ */ new Error("codex app-server server request timed out"));
3836
- resolve(timeoutResponse);
3837
- }, timeoutMs);
3838
- timeout.unref?.();
3839
- })]);
3840
- } finally {
3841
- if (timeout) clearTimeout(timeout);
3842
- }
3843
- }
3844
- async runServerRequestHandlersWithoutTimeout(request, signal) {
3845
- for (const handler of this.requestHandlers) {
3846
- if (signal.aborted) return;
3847
- const result = await handler(request, signal);
3848
- if (result !== void 0) return result;
3849
- }
4096
+ handleResponse(response, previewStates) {
4097
+ this.nativeExecutionObserved = dispatchCodexAppServerResponse(response, this.pending, this.catalogResponses, codexCatalogSourceForClient(this), previewStates) || this.nativeExecutionObserved;
3850
4098
  }
3851
4099
  handleNotification(notification) {
3852
4100
  const params = notification.params;
4101
+ if (notification.method === "serverRequest/resolved") this.serverRequests.resolve(params);
3853
4102
  if (notification.method === "item/commandExecution/outputDelta" || notification.method === "item/commandExecution/terminalInteraction" || isJsonObject(params) && (isJsonObject(params.item) && params.item.type === "commandExecution" || isJsonObject(params.turn) && Array.isArray(params.turn.items) && params.turn.items.some((item) => isJsonObject(item) && item.type === "commandExecution"))) this.nativeExecutionObserved = true;
3854
4103
  if (notification.method === "account/updated") this.modelCatalogRevision += 1;
3855
4104
  if (this.notificationHandlers.size === 0 && notification.method === "configWarning") {
@@ -3871,15 +4120,22 @@ var CodexAppServerClient = class CodexAppServerClient {
3871
4120
  markClosed(error) {
3872
4121
  if (this.closed) return false;
3873
4122
  this.closed = true;
4123
+ closeCodexCatalogClientSource(this);
3874
4124
  this.closeError = error;
3875
- this.lines.close();
4125
+ this.closeMessageReader();
4126
+ this.decoder.clear();
4127
+ this.catalogWorkerClosed = this.catalogWorker.close(error);
4128
+ this.catalogWorkerClosed?.catch((closeError) => {
4129
+ embeddedAgentLog.warn("codex catalog worker shutdown failed", { error: closeError });
4130
+ });
4131
+ this.serverRequests.close(error);
3876
4132
  this.rejectPendingRequests(error);
3877
4133
  return true;
3878
4134
  }
3879
4135
  rejectPendingRequests(error) {
3880
4136
  for (const pending of this.pending.values()) {
3881
4137
  pending.cleanup();
3882
- pending.reject(error);
4138
+ pending.close(error);
3883
4139
  }
3884
4140
  this.pending.clear();
3885
4141
  for (const handler of this.closeHandlers) try {
@@ -3889,35 +4145,6 @@ var CodexAppServerClient = class CodexAppServerClient {
3889
4145
  }
3890
4146
  }
3891
4147
  };
3892
- function defaultServerRequestResponse(request) {
3893
- if (request.method === "item/tool/call") return {
3894
- contentItems: [{
3895
- type: "inputText",
3896
- text: "OpenClaw did not register a handler for this app-server tool call."
3897
- }],
3898
- success: false
3899
- };
3900
- if (request.method === "item/commandExecution/requestApproval" || request.method === "item/fileChange/requestApproval") return { decision: "decline" };
3901
- if (request.method === "item/permissions/requestApproval") return {
3902
- permissions: {},
3903
- scope: "turn"
3904
- };
3905
- if (request.method === "item/tool/requestUserInput") return { answers: {} };
3906
- if (request.method === "mcpServer/elicitation/request") return createCodexElicitationResponse("decline", null, { message: "OpenClaw has no interactive handler for this elicitation." });
3907
- return {};
3908
- }
3909
- function stringifyCodexAppServerMessage(message) {
3910
- return JSON.stringify(message, (_key, value) => typeof value === "string" ? value.replace(UNPAIRED_SURROGATE_RE, "") : value) ?? "null";
3911
- }
3912
- function timeoutServerRequestResponse(timeoutMs) {
3913
- return {
3914
- contentItems: [{
3915
- type: "inputText",
3916
- text: `OpenClaw dynamic tool call timed out after ${timeoutMs}ms before sending a response to Codex.`
3917
- }],
3918
- success: false
3919
- };
3920
- }
3921
4148
  /** Raised when the initialize handshake detects an unsupported app-server version. */
3922
4149
  var CodexAppServerVersionError = class extends Error {
3923
4150
  constructor(detectedVersion) {
@@ -3932,7 +4159,7 @@ function assertSupportedCodexAppServerVersion(response) {
3932
4159
  if (!detectedVersion) throw new CodexAppServerVersionError(detectedVersion);
3933
4160
  const detected = parse(detectedVersion);
3934
4161
  if (!detected || detected.compare("0.149.0") < 0) throw new CodexAppServerVersionError(detectedVersion);
3935
- if (detected.compare("0.153.4") > 0) embeddedAgentLog.warn("codex app-server is newer than OpenClaw's managed runtime; continuing with normal startup validation", {
4162
+ if (detected.compare("0.155.1") > 0) embeddedAgentLog.warn("codex app-server is newer than OpenClaw's managed runtime; continuing with normal startup validation", {
3936
4163
  detectedVersion,
3937
4164
  validatedVersion: CODEX_APP_SERVER_VERSION
3938
4165
  });
@@ -3958,35 +4185,6 @@ function buildCodexAppServerRuntimeIdentity(response, serverVersion) {
3958
4185
  function readCodexVersionFromUserAgent(userAgent) {
3959
4186
  return (userAgent?.match(/^[^/]+\/(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?)(?:[\s(]|$)/))?.[1];
3960
4187
  }
3961
- function redactCodexAppServerLinePreview(value) {
3962
- const redacted = value.replace(/\s+/g, " ").trim().replace(/(Bearer\s+)[A-Za-z0-9._~+/-]+/gi, "$1<redacted>").replace(/("(?:api_?key|authorization|token|access_token|refresh_token)"\s*:\s*")([^"]+)(")/gi, "$1<redacted>$3").replace(/\b([a-z0-9_]*(?:api_?key|authorization|access_token|refresh_token|token))(\s*=\s*)(["']?)[^\s"']+(\3)/gi, "$1$2$3<redacted>$4");
3963
- return redacted.length > CODEX_APP_SERVER_PARSE_LOG_MAX ? `${truncateUtf16Safe(redacted, CODEX_APP_SERVER_PARSE_LOG_MAX)}...` : redacted;
3964
- }
3965
- function appendBoundedTail(current, next, maxLength) {
3966
- const combined = `${current}${next}`;
3967
- return combined.length > maxLength ? sliceUtf16Safe(combined, -maxLength) : combined;
3968
- }
3969
- function buildCodexAppServerExitError(code, signal, stderrTail) {
3970
- const stderrPreview = redactCodexAppServerLinePreview(stderrTail);
3971
- const suffix = stderrPreview ? ` stderr=${JSON.stringify(stderrPreview)}` : "";
3972
- return /* @__PURE__ */ new Error(`codex app-server exited: code=${formatExitValue(code)} signal=${formatExitValue(signal)}${suffix}`);
3973
- }
3974
- function shouldBufferCodexAppServerParseFailure(value, error) {
3975
- if (!value.startsWith("{") && !value.startsWith("[")) return false;
3976
- const message = coerceErrorMessage(error);
3977
- return message.includes("Unterminated string") || message.includes("Unexpected end of JSON input");
3978
- }
3979
- function logCodexAppServerParseFailure(value, error, fragmentCount) {
3980
- const linePreview = redactCodexAppServerLinePreview(value);
3981
- const suffix = fragmentCount > 1 ? ` fragments=${fragmentCount}` : "";
3982
- embeddedAgentLog.warn("failed to parse codex app-server message", {
3983
- error,
3984
- errorMessage: coerceErrorMessage(error),
3985
- fragmentCount,
3986
- linePreview,
3987
- consoleMessage: `failed to parse codex app-server message${suffix}: preview=${JSON.stringify(linePreview)}`
3988
- });
3989
- }
3990
4188
  const CODEX_APP_SERVER_APPROVAL_REQUEST_METHODS = /* @__PURE__ */ new Set([
3991
4189
  "item/commandExecution/requestApproval",
3992
4190
  "item/fileChange/requestApproval",
@@ -3996,10 +4194,5 @@ const CODEX_APP_SERVER_APPROVAL_REQUEST_METHODS = /* @__PURE__ */ new Set([
3996
4194
  function isCodexAppServerApprovalRequest(method) {
3997
4195
  return CODEX_APP_SERVER_APPROVAL_REQUEST_METHODS.has(method);
3998
4196
  }
3999
- function formatExitValue(value) {
4000
- if (value === null || value === void 0) return "null";
4001
- if (typeof value === "string" || typeof value === "number") return String(value);
4002
- return "unknown";
4003
- }
4004
4197
  //#endregion
4005
- export { isMatchingDynamicToolTerminalDiagnostic as A, withDynamicToolTranscriptDetails as B, readCodexErrorNotification as C, handleDynamicToolCallWithTimeout as D, createCodexElicitationResponse as E, toCodexDynamicToolProgressResponse as F, toCodexDynamicToolProtocolResponse as I, resolveCodexToolAbortTerminalReason as L, resolveTerminalDynamicToolBatchAction as M, shouldBlockTerminalReleaseForNonTerminalDynamicToolResult as N, hasPendingDynamicToolTerminalDiagnostic as O, shouldReleaseTurnAfterTerminalDynamicTool as P, createFailedDynamicToolResponse as R, readCodexDynamicToolCallParams as S, readCodexTurnCompletedNotification as T, assertCodexThreadAcceptsDirectInput as _, isCodexAppServerBrokenPipeError as a, assertCodexThreadStartResponse as b, isCodexAppServerIndeterminateTransportError as c, isCodexAppServerRequestTimeoutError as d, isUnsupportedCodexAppServerVersionError as f, assertCodexPassiveTurnItems as g, assertCodexModelListResponse as h, isCodexAppServerApprovalRequest as i, resolveDynamicToolCallTimeoutMs as j, isDynamicToolTerminalDiagnosticEvent as k, isCodexAppServerOverloadError as l, CodexThreadDirectInputError as m, client_exports as n, isCodexAppServerConnectionClosedError as o, resolveCodexAppServerClientInstanceId as p, getCodexAppServerClientInstanceId as r, isCodexAppServerIndeterminateRequestCancellationError as s, CodexAppServerClient as t, isCodexAppServerPrewriteRequestCancellationError as u, assertCodexThreadForkResponse as v, readCodexTurn as w, assertCodexTurnStartResponse as x, assertCodexThreadResumeResponse as y, withDynamicToolExecutionState as z };
4198
+ export { isMatchingDynamicToolTerminalDiagnostic as A, CODEX_APP_SERVER_OPT_OUT_NOTIFICATION_METHODS as B, readCodexDynamicToolCallParams as C, handleDynamicToolCallWithTimeout as D, createCodexElicitationResponse as E, toCodexDynamicToolProgressResponse as F, toCodexDynamicToolProtocolResponse as I, resolveCodexToolAbortTerminalReason as L, resolveTerminalDynamicToolBatchAction as M, shouldBlockTerminalReleaseForNonTerminalDynamicToolResult as N, hasPendingDynamicToolTerminalDiagnostic as O, shouldReleaseTurnAfterTerminalDynamicTool as P, createFailedDynamicToolResponse as R, assertCodexTurnStartResponse as S, readCodexTurnCompletedNotification as T, assertCodexPassiveTurnItems as _, isCodexAppServerBrokenPipeError as a, assertCodexThreadResumeResponse as b, isCodexAppServerIndeterminateTransportError as c, isCodexAppServerRequestTimeoutError as d, isUnsupportedCodexAppServerVersionError as f, assertCodexModelListResponse as g, CodexThreadDirectInputError as h, isCodexAppServerApprovalRequest as i, resolveDynamicToolCallTimeoutMs as j, isDynamicToolTerminalDiagnosticEvent as k, isCodexAppServerOverloadError as l, CodexServerRequestResolvedError as m, client_exports as n, isCodexAppServerConnectionClosedError as o, resolveCodexAppServerClientInstanceId as p, getCodexAppServerClientInstanceId as r, isCodexAppServerIndeterminateRequestCancellationError as s, CodexAppServerClient as t, isCodexAppServerPrewriteRequestCancellationError as u, assertCodexThreadAcceptsDirectInput as v, readCodexErrorNotification as w, assertCodexThreadStartResponse as x, assertCodexThreadForkResponse as y, failedToolResult as z };