@openclaw/codex 2026.9.7 → 2026.10.1-beta.1

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 (151) hide show
  1. package/README.md +8 -0
  2. package/dist/.setup/{account-usage-runtime-DFhbh1zz.mjs → account-usage-runtime-C4GFoef_.mjs} +5 -5
  3. package/dist/.setup/app-server-policy-Bg4FZw1f.mjs +23 -0
  4. package/dist/.setup/{apply-D3GcSoSa.mjs → apply-D02fLpgN.mjs} +48 -39
  5. package/dist/.setup/attempt-client-cleanup-yLjGwbwT.mjs +155 -0
  6. package/dist/.setup/{attempt-workspace-context-C5HigshI.mjs → attempt-workspace-context-CbSzT6V2.mjs} +11 -15
  7. package/dist/.setup/{auth-binding-BLWz7stm.mjs → auth-binding-BoMwpuPN.mjs} +17 -25
  8. package/dist/.setup/{auth-cache-key-Dbvq-QgB.mjs → auth-cache-key-CEd9QlIs.mjs} +244 -82
  9. package/dist/.setup/{auth-profile-B0okYl2D.mjs → auth-profile-CgHQ8Vot.mjs} +2 -1
  10. package/dist/.setup/{auth-profile-selection-DFu9e167.mjs → auth-profile-selection-hr8ocLtz.mjs} +5 -7
  11. package/dist/.setup/{binding-connection-DTtN1KrX.mjs → binding-connection-C-08ez1w.mjs} +2 -2
  12. package/dist/.setup/{binding-connection.runtime-6TpgD1M6.mjs → binding-connection.runtime-Dn2p-fdy.mjs} +3 -3
  13. package/dist/.setup/{bounded-turn-CbjoN2OW.mjs → bounded-turn-DlHlNTyS.mjs} +14 -13
  14. package/dist/.setup/{bounded-turn-isolation-B8K_ylqk.mjs → bounded-turn-isolation-DklXNk3k.mjs} +4 -4
  15. package/dist/.setup/{build-state-Da1_z0kd.mjs → build-state-CIi3Ckqu.mjs} +1 -1
  16. package/dist/.setup/{capabilities-B3WEZl4e.mjs → capabilities-kQntafj_.mjs} +1 -1
  17. package/dist/.setup/{client-N0JpgSzF.mjs → client-CBzEVDyb.mjs} +438 -160
  18. package/dist/.setup/{client-catalog-response-5HHLdcde.mjs → client-catalog-response-CmvIiDdj.mjs} +57 -25
  19. package/dist/.setup/command-authorization-AikPDtcc.mjs +15 -0
  20. package/dist/.setup/{command-dispatch-BeAoaovI.mjs → command-dispatch-BE_RdMou.mjs} +3 -3
  21. package/dist/.setup/{command-formatters-R3ckE3Co.mjs → command-formatters-DV3DHhdr.mjs} +7 -5
  22. package/dist/.setup/{command-handlers-ylTMS00z.mjs → command-handlers-DNoRq5Ps.mjs} +82 -144
  23. package/dist/.setup/{command-rpc-CGJGUQ6Y.mjs → command-rpc-B6xsq2dB.mjs} +23 -31
  24. package/dist/.setup/{compact-C2WamavS.mjs → compact-BLSAd-ru.mjs} +117 -65
  25. package/dist/.setup/{plugin-metadata-cache-DsjsL1dr.mjs → computer-use-DpolvQHw.mjs} +66 -203
  26. package/dist/.setup/{config-DKhXquav.mjs → config-0Gxk3_eq.mjs} +5 -6
  27. package/dist/.setup/{config-options-CzyWLTJt.mjs → config-options-HG_Rr3W_.mjs} +13 -23
  28. package/dist/.setup/{config-parsing-b088LyhT.mjs → config-parsing-BQq-CHTF.mjs} +41 -4
  29. package/dist/.setup/{config-runtime-C0NbLms1.mjs → config-runtime-cUYrqu_a.mjs} +2 -2
  30. package/dist/.setup/{config-security-CE-FcGw9.mjs → config-security-KAPScztc.mjs} +20 -36
  31. package/dist/.setup/{context-engine-projection-PezSESth.mjs → context-engine-projection-CsgYSQhW.mjs} +11 -14
  32. package/dist/.setup/{conversation-binding-3Min8qvP.mjs → conversation-binding-CgSSD1Qz.mjs} +36 -48
  33. package/dist/.setup/{conversation-binding-data-C746z5Pn.mjs → conversation-binding-data-DJ4ix-W5.mjs} +1 -1
  34. package/dist/.setup/{conversation-control-CEP8X5JC.mjs → conversation-control-tCg763cI.mjs} +19 -21
  35. package/dist/.setup/{cyber-failover-XV0nNRZu.mjs → cyber-failover-Bb1J6hS1.mjs} +1 -1
  36. package/dist/.setup/{cyber-failover-notice-RNpGpTyP.mjs → cyber-failover-notice-XR03ef31.mjs} +1 -1
  37. package/dist/.setup/doctor-start-options-DPW9JxIE.mjs +63 -0
  38. package/dist/.setup/dynamic-tool-build-CVrx02cH.mjs +463 -0
  39. package/dist/.setup/{dynamic-tools-DzlsLUuS.mjs → dynamic-tools-DdsymYGQ.mjs} +238 -878
  40. package/dist/.setup/{effective-mcp-catalog-CxUtC-xG.mjs → effective-mcp-catalog-BysTBZCW.mjs} +83 -11
  41. package/dist/.setup/{elicitation-input-DPoK8F7w.mjs → elicitation-input-r9axtppm.mjs} +4 -2
  42. package/dist/.setup/{ephemeral-turn-CDsPJOa2.mjs → ephemeral-turn-oPKxs3ia.mjs} +2 -2
  43. package/dist/.setup/{event-projector-assistant-message-CigreO4K.mjs → event-projector-assistant-message-YCL2wspu.mjs} +2 -2
  44. package/dist/.setup/{event-projector-values-DJSz8BTk.mjs → event-projector-values-DTqZHizf.mjs} +2 -12
  45. package/dist/.setup/{inference-dispatch-CMZtjQyz.mjs → inference-dispatch-B5UKEUyC.mjs} +12 -21
  46. package/dist/.setup/{inference-proxy-DhcXOgUE.mjs → inference-proxy-DUO5E2QQ.mjs} +6 -5
  47. package/dist/.setup/{isolated-completion-Dm3PzxJk.mjs → isolated-completion-D5gbKm6k.mjs} +8 -8
  48. package/dist/.setup/{managed-binary-kiWRhNRE.mjs → managed-binary-C1VFoVPf.mjs} +31 -38
  49. package/dist/.setup/mcp-app-session-preparation-CdqsXwZX.mjs +223 -0
  50. package/dist/.setup/mcp-tool-metadata-j10HhfTC.mjs +43 -0
  51. package/dist/.setup/{model-catalog-PAuZgJC6.mjs → model-catalog-Dj_uvusa.mjs} +7 -7
  52. package/dist/.setup/{models-DHXZtVVk.mjs → models-Du_i5G_t.mjs} +10 -7
  53. package/dist/.setup/{native-auth-CuG53tu4.mjs → native-auth-Cjb9y7IZ.mjs} +5 -6
  54. package/dist/.setup/{native-execution-policy-BxZJy5mP.mjs → native-execution-policy-ClzpdG3D.mjs} +1 -12
  55. package/dist/.setup/native-mcp-app-DV7VbfzF.mjs +310 -0
  56. package/dist/.setup/{native-subagent-monitor-Dpsmf2wz.mjs → native-subagent-monitor-CCEFO6qK.mjs} +235 -318
  57. package/dist/.setup/{native-subagent-pending-assignments-DwkCzLvD.mjs → native-subagent-pending-assignments-BDqhOdJp.mjs} +0 -4
  58. package/dist/.setup/{native-task-assignments-DMQ0g3hu.mjs → native-task-assignments-C6KVqiN1.mjs} +9 -8
  59. package/dist/.setup/{node-cli-sessions-HC4W6FLI.mjs → node-cli-sessions-B5oNDkUS.mjs} +11 -17
  60. package/dist/.setup/{node-exec-server.runtime-BgBfWQqo.mjs → node-exec-server.runtime-0xSEjKYt.mjs} +2 -2
  61. package/dist/.setup/{plan-Y-QIvrKB.mjs → plan-CUHSIOep.mjs} +67 -89
  62. package/dist/.setup/{plugin-activation-cNHRfaxU.mjs → plugin-activation-BcyBv8PG.mjs} +4 -4
  63. package/dist/.setup/{plugin-app-cache-key-BL9B5H0L.mjs → plugin-app-cache-key-BW8rd98k.mjs} +11 -15
  64. package/dist/.setup/plugin-approval-roundtrip-uAR-oQfr.mjs +109 -0
  65. package/dist/.setup/{plugin-inventory-Cky2XJUw.mjs → plugin-inventory-Bf0_piTw.mjs} +29 -51
  66. package/dist/.setup/{plugin-marketplace-discovery-D_dV9FXa.mjs → plugin-marketplace-discovery-SQPhSuic.mjs} +2 -16
  67. package/dist/.setup/plugin-metadata-cache-DWnB7VMj.mjs +84 -0
  68. package/dist/.setup/plugin-thread-config-deadline-CdRzGJt4.mjs +124 -0
  69. package/dist/.setup/{provider-DH8NSzGt.mjs → provider-BP8ZaZqn.mjs} +4 -4
  70. package/dist/.setup/provider-capabilities-Z5ZbBxqP.mjs +50 -0
  71. package/dist/.setup/{rate-limits-B7-X2TgG.mjs → rate-limits-CMPy24F5.mjs} +1 -5
  72. package/dist/.setup/{request-BHZ1nz8d.mjs → request-BH3FvYUE.mjs} +189 -49
  73. package/dist/.setup/rpc-error-hmWM21RB.mjs +57 -0
  74. package/dist/.setup/{run-attempt-D8RZUOzY.mjs → run-attempt-CgvFoW7R.mjs} +553 -727
  75. package/dist/.setup/{run-attempt-lifecycle-C-6O3Exn.mjs → run-attempt-lifecycle-BuZgVbDA.mjs} +19 -3
  76. package/dist/.setup/{runtime-artifact-DDQ-HGXf.mjs → runtime-artifact-CUTOOnKw.mjs} +5 -6
  77. package/dist/.setup/{runtime-artifact-connection-D68qQn1m.mjs → runtime-artifact-connection-CADz3_BY.mjs} +5 -4
  78. package/dist/.setup/{sandbox-guard-DjCz2eOw.mjs → sandbox-guard-WqE8yPge.mjs} +3 -3
  79. package/dist/.setup/service-tier-normalization-Cei89SW6.mjs +15 -0
  80. package/dist/.setup/{session-binding-DGCYAfvD.mjs → session-binding-Ce7BqiPN.mjs} +92 -102
  81. package/dist/.setup/session-binding-meta-Lkm5Lpf4.mjs +15 -0
  82. package/dist/.setup/session-binding-record-BZB8RgcF.mjs +179 -0
  83. package/dist/.setup/session-binding-record-codec-z4ZpDn6E.mjs +216 -0
  84. package/dist/.setup/{session-binding-sidecars-jo6H8dFr.mjs → session-binding-sidecars-BrdV95Fg.mjs} +8 -2
  85. package/dist/.setup/{session-catalog-adoption-BU_pHWG7.mjs → session-catalog-adoption-CPIP4S_y.mjs} +34 -18
  86. package/dist/.setup/{session-catalog-archive-spHfihri.mjs → session-catalog-archive-DcgwvSbF.mjs} +24 -29
  87. package/dist/.setup/{session-catalog-events-DePDzzjc.mjs → session-catalog-events-KIXOoSnQ.mjs} +5 -5
  88. package/dist/.setup/{session-catalog-index-CZvDzC6z.mjs → session-catalog-index-DPICGlxr.mjs} +361 -72
  89. package/dist/.setup/{session-catalog-index-order-BcQpHks3.mjs → session-catalog-index-order-nhyO0wdW.mjs} +1 -1
  90. package/dist/.setup/{session-catalog-limits-DDxOsQeC.mjs → session-catalog-limits-DEU36Qlo.mjs} +1 -1
  91. package/dist/.setup/{session-catalog-index-state-TeO7EyO-.mjs → session-catalog-list-request-tXephOB4.mjs} +180 -6
  92. package/dist/.setup/{session-catalog-native-projection-DjhwGL6x.mjs → session-catalog-native-projection-CTBd4EUm.mjs} +7 -6
  93. package/dist/.setup/{session-catalog-node-adoption-DgXvSGu0.mjs → session-catalog-node-adoption-7-WEQTB1.mjs} +12 -2
  94. package/dist/.setup/{session-catalog-node-continue-DjKXHBbi.mjs → session-catalog-node-continue-DLWBwAAO.mjs} +11 -15
  95. package/dist/.setup/{session-catalog-node-lookup-CtAXI5W5.mjs → session-catalog-node-lookup-Uufckwcm.mjs} +2 -2
  96. package/dist/.setup/{session-catalog-parsing-CPGaPYr-.mjs → session-catalog-parsing-B-qWJh2x.mjs} +70 -28
  97. package/dist/.setup/{session-catalog-projection-Cr5qP5Dj.mjs → session-catalog-projection-CE0_Hffi.mjs} +6 -122
  98. package/dist/.setup/{session-catalog-provenance-DoAvktcj.mjs → session-catalog-provenance-CmsOE5mh.mjs} +6 -1
  99. package/dist/.setup/{session-cli-Cn_nCqfq.mjs → session-cli-kH4vuGod.mjs} +1 -2
  100. package/dist/.setup/{session-history-D83lJWHG.mjs → session-history-BogBHKLk.mjs} +1 -1
  101. package/dist/.setup/{session-history-import-WhX-X33a.mjs → session-history-import-NWKPa4ZO.mjs} +4 -4
  102. package/dist/.setup/{session-history-read-Ov3StuL4.mjs → session-history-read-CNN8zwbD.mjs} +8 -19
  103. package/dist/.setup/{session-history.worker-MnPKncqP.mjs → session-history.worker-Cq_4DYgN.mjs} +3 -3
  104. package/dist/.setup/{session-initialization-6aveB9qb.mjs → session-initialization-D6dtFQkE.mjs} +2 -2
  105. package/dist/.setup/{session-permission-policy-Ci_fVX6y.mjs → session-permission-policy-BxIUJ0Zd.mjs} +8 -37
  106. package/dist/.setup/{session-retirement-qMTxkNx2.mjs → session-retirement-aC60o6P3.mjs} +14 -15
  107. package/dist/.setup/{settled-turn-context-D4yj4rxf.mjs → settled-turn-context-BZsMjkIO.mjs} +13 -6
  108. package/dist/.setup/{settled-turn-finalizer-BsvEabkw.mjs → settled-turn-finalizer-CDxCejjC.mjs} +8 -8
  109. package/dist/.setup/{shared-client-DqyTMYug.mjs → shared-client-DJJ3ljH2.mjs} +291 -272
  110. package/dist/.setup/{provider-capabilities-CAxoF-X1.mjs → shell-dynamic-tools-Do9lIAT1.mjs} +16 -55
  111. package/dist/.setup/{side-question-C4kCmQy1.mjs → side-question-B7T0_GEC.mjs} +99 -91
  112. package/dist/.setup/{source-CS_7GFJZ.mjs → source-DH70LqN0.mjs} +24 -40
  113. package/dist/.setup/{thread-lifecycle-DPflntEJ.mjs → thread-lifecycle-DkcoX9q-.mjs} +262 -305
  114. package/dist/.setup/{thread-ownership-roNP0l1c.mjs → thread-ownership-0aRHD9iK.mjs} +10 -8
  115. package/dist/.setup/{thread-policy-DTd-DtkX.mjs → thread-policy-CXZV97TS.mjs} +22 -21
  116. package/dist/.setup/{thread-requests-B_bRnMGN.mjs → thread-requests-COrRJcZb.mjs} +107 -98
  117. package/dist/.setup/{thread-resume-CdDaoc7T.mjs → thread-resume-rx7J68Rx.mjs} +10 -18
  118. package/dist/.setup/{transcript-history-projection-DRSifI-1.mjs → transcript-history-projection-B9a7HwUV.mjs} +11 -16
  119. package/dist/.setup/{transcript-mirror-kxmCYsuF.mjs → transcript-mirror-BfLRARNL.mjs} +64 -67
  120. package/dist/.setup/{transport-stdio-Bdegpn2V.mjs → transport-stdio-a0HDa2Mj.mjs} +27 -8
  121. package/dist/.setup/{transport-websocket-BTBE-LD9.mjs → transport-websocket-zqJ0Cmtn.mjs} +3 -8
  122. package/dist/.setup/{attempt-client-cleanup-DOP-cW5j.mjs → turn-router-CX1-EoCp.mjs} +75 -170
  123. package/dist/.setup/{upstream-session-fork-CBeVjBpT.mjs → upstream-session-fork-LYlaQnbt.mjs} +35 -46
  124. package/dist/.setup/{usage-BMzNxeR_.mjs → usage-Dmx7B0W2.mjs} +4 -4
  125. package/dist/.setup/{usage-limit-error-QXerDo3i.mjs → usage-limit-error-M8jVnITZ.mjs} +4 -4
  126. package/dist/.setup/{web-search-provider.runtime-P77OUeoo.mjs → web-search-provider.runtime-CsVmqbFm.mjs} +4 -20
  127. package/dist/.setup/websocket-data-XlRvt8Ys.mjs +6 -0
  128. package/dist/.setup/workspace-write-sandbox-probe-DmUHLrrl.mjs +118 -0
  129. package/dist/api.js +34 -54
  130. package/dist/catalog-page.worker.js +1 -1
  131. package/dist/cli-metadata.js +1 -1
  132. package/dist/doctor-contract-api.js +15 -27
  133. package/dist/harness.js +37 -22
  134. package/dist/index.js +2880 -276
  135. package/dist/media-understanding-provider.js +2 -2
  136. package/dist/migration-provider-api.js +1 -1
  137. package/dist/native-session-binding-api.js +2 -0
  138. package/dist/provider-discovery.js +1 -1
  139. package/dist/session-history-worker-runtime.js +33 -4
  140. package/dist/session-history.worker.js +1 -1
  141. package/openclaw.plugin.json +3 -3
  142. package/package.json +6 -6
  143. package/dist/.setup/config-utils-D0CXecki.mjs +0 -57
  144. package/dist/.setup/incognito-session-DWYapfwf.mjs +0 -2
  145. package/dist/.setup/managed-thread-store-BMqgThVL.mjs +0 -100
  146. package/dist/.setup/rpc-error-BlD2vuzn.mjs +0 -31
  147. package/dist/.setup/session-binding-meta-B7aEMU7g.mjs +0 -6
  148. package/dist/.setup/session-binding-record-Oe9L-CNY.mjs +0 -375
  149. package/dist/.setup/session-catalog-4sCdv5qx.mjs +0 -2610
  150. package/dist/.setup/session-catalog-list-request-CvtxrYSe.mjs +0 -170
  151. package/dist/.setup/shared-client-lifecycle-DJIgqgMw.mjs +0 -153
@@ -1,47 +1,42 @@
1
- import { CODEX_NATIVE_TOOL_REQUIREMENTS } from "../native-tool-policy.js";
2
1
  import { i as isJsonObject, r as flattenCodexDynamicToolFunctions, t as CODEX_OPENCLAW_DIRECT_DYNAMIC_TOOL_NAMESPACE } from "./protocol-CANUwXJ3.mjs";
3
- import { d as readCodexPluginConfig, l as isCodexRemoteExecPlacementSandbox } from "./config-parsing-b088LyhT.mjs";
4
- import { o as formatCodexDisplayText } from "./command-formatters-R3ckE3Co.mjs";
5
- import { s as readItem } from "./event-projector-values-DJSz8BTk.mjs";
6
- import { s as codexAppIdentityKey } from "./plugin-app-cache-key-BL9B5H0L.mjs";
7
- import "./config-DKhXquav.mjs";
8
- import { i as sanitizeInlineImageDataUrl, r as invalidInlineImageText } from "./session-history-read-Ov3StuL4.mjs";
9
- import { U as protectCodexAppServerLiveThread, _ as retainSharedCodexAppServerClientIfCurrent } from "./shared-client-DqyTMYug.mjs";
10
- import { a as isCodexResponsesOAuthRun } from "./responses-oauth-twnuTaAa.mjs";
11
- import { B as resolveCodexToolAbortTerminalReason, E as readCodexTurnCompletedNotification, H as failedToolResult, V as createFailedDynamicToolResponse, k as createCodexElicitationResponse, m as CodexServerRequestResolvedError } from "./client-N0JpgSzF.mjs";
12
- import { A as itemStatus, C as auditNativeToolUnfinishedStatus, N as shouldClearTerminalPresentationForNativeItem, S as auditNativeToolTerminalStatus, b as readCodexNotificationTurnId, k as itemName, v as isCodexNotificationForTurn, x as auditNativeToolName, y as readCodexNotificationThreadId } from "./attempt-client-cleanup-DOP-cW5j.mjs";
13
- import { ct as isForcedPrivateQaCodexRuntime, dt as normalizeCodexDynamicToolName, j as emitCodexNativePreToolUseFailureDiagnostic, ot as filterCodexDynamicTools, p as resolveCodexWebSearchPlan, st as filterCodexDynamicToolsForDisabledNativeSurface, ut as isSystemAgentOnlyCodexDynamicToolAllowlist } from "./thread-requests-B_bRnMGN.mjs";
14
- import { _ as waitForPluginApprovalDecision, d as mapExecDecisionToOutcome, f as requestPluginApproval, g as truncateCodexApprovalDisplayText, h as stripDanglingCodexApprovalTerminalSequence, l as approvalRequestExplicitlyUnavailable, m as sanitizeCodexApprovalVisibleText, p as requestPluginApprovalOutcome, u as codexApprovalTimeoutText } from "./native-subagent-monitor-Dpsmf2wz.mjs";
15
- import { n as resolveCodexNativeExecutionPolicy, r as resolveCodexNodeExecToolOverrides } from "./native-execution-policy-BxZJy5mP.mjs";
16
- import { a as CODEX_NODE_EXEC_DYNAMIC_TOOL_NAME, c as createNodeExecAliasDynamicTool, d as isCodexDynamicToolExcluded, i as CODEX_GATEWAY_PROCESS_DYNAMIC_TOOL_NAME, l as createSandboxExecProjection, o as createGatewayExecProjection, r as CODEX_GATEWAY_EXEC_DYNAMIC_TOOL_NAME, s as createGatewayProcessProjection, u as createSandboxProcessProjection } from "./provider-capabilities-CAxoF-X1.mjs";
2
+ import { o as formatCodexDisplayText } from "./command-formatters-DV3DHhdr.mjs";
3
+ import { o as readItem } from "./event-projector-values-DTqZHizf.mjs";
4
+ import { s as codexAppIdentityKey } from "./plugin-app-cache-key-BW8rd98k.mjs";
5
+ import { r as invalidInlineImageText } from "./session-history-read-CNN8zwbD.mjs";
6
+ import { U as protectCodexAppServerLiveThread, _ as retainSharedCodexAppServerClientIfCurrent } from "./shared-client-DJJ3ljH2.mjs";
7
+ import { F as createFailedDynamicToolResponse, I as failedToolResult, P as resolveCodexToolAbortTerminalReason, l as CodexServerRequestResolvedError, w as createCodexElicitationResponse, x as readCodexTurnCompletedNotification } from "./client-CBzEVDyb.mjs";
8
+ import { t as codexWebSocketDataToBuffer } from "./websocket-data-XlRvt8Ys.mjs";
9
+ import { _ as itemStatus, a as isCodexNotificationForTurn, b as shouldClearTerminalPresentationForNativeItem, c as auditNativeToolName, g as itemName, l as auditNativeToolTerminalStatus, o as readCodexNotificationThreadId, s as readCodexNotificationTurnId, u as auditNativeToolUnfinishedStatus } from "./turn-router-CX1-EoCp.mjs";
10
+ import { M as emitCodexNativePreToolUseFailureDiagnostic } from "./thread-requests-COrRJcZb.mjs";
11
+ import { a as requestPluginApprovalOutcome, c as truncateCodexApprovalDisplayText, i as requestPluginApproval, l as waitForPluginApprovalDecision, n as codexApprovalTimeoutText, o as sanitizeCodexApprovalVisibleText, r as mapExecDecisionToOutcome, s as stripDanglingCodexApprovalTerminalSequence, t as approvalRequestExplicitlyUnavailable } from "./plugin-approval-roundtrip-uAR-oQfr.mjs";
12
+ import { d as isCodexPassThroughMediaSource, f as mapCodexAppServerLocalWorkspacePath, p as mapCodexAppServerRemoteWorkspacePath } from "./dynamic-tool-build-CVrx02cH.mjs";
17
13
  import { createRequire } from "node:module";
18
- import { asNonArrayRecord, asOptionalRecord, isRecord, normalizeTrimmedStringList, readNonBlankString, readStringField } from "openclaw/plugin-sdk/string-coerce-runtime";
14
+ import { asNonArrayRecord, asOptionalRecord, filterStringEntries, isRecord, normalizeTrimmedStringList, readNonBlankString, readStringField } from "openclaw/plugin-sdk/string-coerce-runtime";
19
15
  import { createHash, randomUUID } from "node:crypto";
20
- import { signalProcessTree, spawnTerminalPty } from "openclaw/plugin-sdk/process-runtime";
21
16
  import { validateJsonSchemaValue } from "openclaw/plugin-sdk/json-schema-runtime";
22
17
  import { asDateTimestampMs } from "openclaw/plugin-sdk/number-runtime";
18
+ import { signalProcessTree, spawnTerminalPty } from "openclaw/plugin-sdk/process-runtime";
23
19
  import path, { posix } from "node:path";
24
20
  import { coerceErrorMessage } from "openclaw/plugin-sdk/error-runtime";
25
- import { isPathStrictlyInside, root } from "openclaw/plugin-sdk/file-access-runtime";
26
- import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
21
+ import { createBoundedRemoteFileReader, isPathStrictlyInside, root } from "openclaw/plugin-sdk/file-access-runtime";
27
22
  import { once } from "node:events";
28
23
  import { spawn } from "node:child_process";
29
- import { DEFAULT_MAX_LIVE_TOOL_RESULT_CHARS, estimateToolResultTextChars, resolveLiveToolResultMaxChars, sliceToolResultTextToBudget, sliceUtf16Safe, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
24
+ import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
25
+ import { DEFAULT_MAX_LIVE_TOOL_RESULT_CHARS, estimateToolResultTextChars, resolveLiveToolResultMaxChars, safeParseJson, sliceToolResultTextToBudget, sliceUtf16Safe, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
30
26
  import { emitTrustedDiagnosticEvent } from "openclaw/plugin-sdk/diagnostic-runtime";
31
27
  import { createDeferred } from "openclaw/plugin-sdk/extension-shared";
32
- import { createStageTimingTracker, formatStageTimings } from "openclaw/plugin-sdk/time-runtime";
28
+ import { createAgentToolResultMiddlewareRunner, createCodexAppServerToolResultExtensionRunner, embeddedAgentLog, extractMessagingToolSend, extractMessagingToolSendResult, finalizeAgentToolAvailability, finalizeToolTerminalPresentation, formatApprovalDisplayPath, formatToolExecutionErrorMessage, getBeforeToolCallFailureDisposition, getChannelAgentToolMeta, getPluginToolMeta, getPluginToolSideEffectOwnerKey, hasNativeHookRelayInvocation, invokeNativeHookRelay, isDeliveredMessageToolOnlySourceReplyResult, isDeliveredMessagingToolResult, isDeliveredMessagingToolSendToCurrentSource, isMessagingTool, isReplaySafeToolCall, isToolResultError, isToolWrappedWithBeforeToolCallHook, projectPluginMessageDeliveryFact, projectRuntimeToolInputSchema, readEmbeddedMessageDeliveryFact, readToolOperatorHint, resolveNativeHookRelayDeferredToolApproval, resolveToolExecutionErrorKind, runAgentHarnessAfterToolCallHook, sanitizeToolResult, setBeforeToolCallDiagnosticsEnabled, wrapToolWithBeforeToolCallHook } from "openclaw/plugin-sdk/agent-harness-runtime";
33
29
  import { fileURLToPath, pathToFileURL } from "node:url";
34
- import { resolveAgentDir } from "openclaw/plugin-sdk/agent-runtime";
35
- import { applyEmbeddedAttemptToolsAllow, buildAgentHookContextChannelFields, buildEmbeddedAttemptToolRunContext, createAgentToolResultMiddlewareRunner, createCodexAppServerToolResultExtensionRunner, embeddedAgentLog, extractMessagingToolSend, extractMessagingToolSendResult, filterProviderNormalizableTools, finalizeAgentToolAvailability, finalizeToolTerminalPresentation, formatApprovalDisplayPath, formatToolExecutionErrorMessage, getBeforeToolCallFailureDisposition, getChannelAgentToolMeta, getPluginToolMeta, getPluginToolSideEffectOwnerKey, hasNativeHookRelayInvocation, invokeNativeHookRelay, isDeliveredMessageToolOnlySourceReplyResult, isDeliveredMessagingToolResult, isDeliveredMessagingToolSendToCurrentSource, isHostScopedAgentToolActive, isMessagingTool, isReplaySafeToolCall, isSubagentSessionKey, isToolResultError, isToolWrappedWithBeforeToolCallHook, normalizeAgentRuntimeTools, projectPluginMessageDeliveryFact, projectRuntimeToolInputSchema, readEmbeddedMessageDeliveryFact, readToolOperatorHint, resolveAttemptSpawnWorkspaceDir, resolveModelAuthMode, resolveNativeHookRelayDeferredToolApproval, resolveToolExecutionErrorKind, runAgentHarnessAfterToolCallHook, sanitizeToolResult, setBeforeToolCallDiagnosticsEnabled, supportsModelTools, wrapToolWithBeforeToolCallHook } from "openclaw/plugin-sdk/agent-harness-runtime";
30
+ import { sanitizeInlineImageDataUrl } from "openclaw/plugin-sdk/inline-image-data-url-runtime";
36
31
  import { redactToolPayloadText } from "openclaw/plugin-sdk/logging-core";
37
32
  import { formatErrorMessage as formatErrorMessage$2, redactSensitiveText as redactSensitiveText$1 } from "openclaw/plugin-sdk/security-runtime";
38
- import { copyInternalToolResultState, createAgentHarnessToolExecutionBoundaryRegistry, extractMessagingToolSourceReplyPayload, getCoreTtsToolResultMediaUrls, normalizeAcceptedSessionSpawnResult, recordAgentHarnessToolResultTelemetry, runAgentHarnessToolInvocation } from "openclaw/plugin-sdk/agent-harness-tool-runtime";
33
+ import { collectAgentHarnessMessagingMediaUrls, copyInternalToolResultState, createAgentHarnessToolExecutionBoundaryRegistry, extractMessagingToolSourceReplyPayload, getCoreTtsToolResultMediaUrls, mapAgentHarnessMessagingMediaValues, normalizeAcceptedSessionSpawnResult, recordAgentHarnessToolResultTelemetry, runAgentHarnessToolInvocation } from "openclaw/plugin-sdk/agent-harness-tool-runtime";
39
34
  import { isIP } from "node:net";
40
- import { formatMcpCodexApprovalRemedy, requiresMcpCodexToolApproval, resolveCodexScheduledToolProjectionFactory, resolveProjectedMcpCodexToolApprovalMode, runWithCronCreatorAuthorityCapabilityResolver } from "openclaw/plugin-sdk/codex-mcp-projection";
41
- import { SANDBOX_COMMAND_MAX_BUFFER_BYTES, buildRemoteCommand, isToolAllowed, prepareSandboxProcessCleanup, sanitizeEnvVars } from "openclaw/plugin-sdk/sandbox";
35
+ import { formatMcpCodexApprovalRemedy, requiresMcpCodexToolApproval, resolveProjectedMcpCodexToolApprovalMode } from "openclaw/plugin-sdk/codex-mcp-projection";
36
+ import { SANDBOX_COMMAND_MAX_BUFFER_BYTES, buildRemoteCommand, prepareSandboxProcessCleanup, sanitizeEnvVars } from "openclaw/plugin-sdk/sandbox";
42
37
  import { SsrFBlockedError, isBlockedHostnameOrIp } from "openclaw/plugin-sdk/ssrf-runtime";
43
- import { normalizeMediaReferenceForComparison, saveMediaBuffer } from "openclaw/plugin-sdk/media-store";
44
38
  import { getMediaDir } from "openclaw/plugin-sdk/media-runtime";
39
+ import { normalizeMediaReferenceForComparison, saveMediaBuffer } from "openclaw/plugin-sdk/media-store";
45
40
  import { normalizeOpenAIStrictCompatSchema } from "openclaw/plugin-sdk/provider-tools";
46
41
  //#region extensions/codex/src/app-server/event-projector-native-tool-lifecycle.ts
47
42
  function isMcpToolCallItemNotification(method, params) {
@@ -56,7 +51,6 @@ var CodexNativeToolLifecycleProjector = class {
56
51
  this.options = options;
57
52
  this.terminalPresentationClearedItemIds = /* @__PURE__ */ new Set();
58
53
  this.nativeToolOutcomeOrdinals = /* @__PURE__ */ new Map();
59
- this.startedAtByItem = /* @__PURE__ */ new Map();
60
54
  this.activeItems = /* @__PURE__ */ new Map();
61
55
  this.webSearchCompletionByItem = /* @__PURE__ */ new Map();
62
56
  this.completedItemIds = /* @__PURE__ */ new Set();
@@ -185,10 +179,9 @@ var CodexNativeToolLifecycleProjector = class {
185
179
  const approvalFailureDisposition = this.approvalFailureDispositionByItem.get(toolCallId);
186
180
  this.approvalFailureDispositionByItem.delete(toolCallId);
187
181
  this.completedItemIds.add(toolCallId);
182
+ const startedAt = this.activeItems.get(toolCallId)?.startedAt;
188
183
  this.activeItems.delete(toolCallId);
189
184
  this.webSearchCompletionByItem.delete(toolCallId);
190
- const startedAt = this.startedAtByItem.get(toolCallId);
191
- this.startedAtByItem.delete(toolCallId);
192
185
  const endedAt = options.sourceTimestampMs ?? Date.now();
193
186
  const durationMs = options.itemDurationMs ?? (startedAt === void 0 ? 0 : Math.max(0, endedAt - startedAt));
194
187
  if (preToolUseFailure) {
@@ -268,9 +261,9 @@ var CodexNativeToolLifecycleProjector = class {
268
261
  }
269
262
  recordStarted(toolCallId, toolName, unfinishedStatus, sourceTimestampMs, mcpToolCall, commandProcessId) {
270
263
  if (this.activeItems.has(toolCallId)) return;
271
- this.startedAtByItem.set(toolCallId, sourceTimestampMs ?? Date.now());
272
264
  this.activeItems.set(toolCallId, {
273
265
  toolName,
266
+ startedAt: sourceTimestampMs ?? Date.now(),
274
267
  unfinishedStatus,
275
268
  mcpToolCall,
276
269
  commandProcessId
@@ -293,201 +286,42 @@ var CodexNativeToolLifecycleProjector = class {
293
286
  }
294
287
  };
295
288
  //#endregion
296
- //#region extensions/codex/src/app-server/remote-workspace-path.ts
297
- /** Projects a gateway workspace path into the remote Codex execution workspace. */
298
- function mapCodexAppServerRemoteWorkspacePath(params) {
299
- if (!params.remoteWorkspaceRoot) return params.value;
300
- const localRoot = normalizeWorkspaceMatchPath(params.localWorkspaceRoot);
301
- const remoteRoot = normalizeWorkspaceMatchPath(params.remoteWorkspaceRoot);
302
- const normalizedValue = normalizeWorkspaceMatchPath(params.value);
303
- if (!localRoot || !remoteRoot) throw new Error("Codex remoteWorkspaceRoot requires non-empty workspace roots.");
304
- if (normalizedValue === localRoot) return remoteRoot;
305
- const prefix = `${localRoot}/`;
306
- if (!normalizedValue.startsWith(prefix)) throw new Error(`Codex remoteWorkspaceRoot is configured but cwd ${params.value} is outside OpenClaw workspace root ${params.localWorkspaceRoot}; refusing to send a gateway-local cwd to the remote Codex app-server.`);
307
- return joinRemoteWorkspacePath(remoteRoot, normalizedValue.slice(prefix.length));
308
- }
309
- /** Maps a remote workspace artifact back into the corresponding gateway workspace. */
310
- function mapCodexAppServerLocalWorkspacePath(params) {
311
- if (!params.remoteWorkspaceRoot) return params.value;
312
- const localRoot = normalizeWorkspaceMatchPath(params.localWorkspaceRoot);
313
- const remoteRoot = normalizeWorkspaceMatchPath(params.remoteWorkspaceRoot);
314
- if (!localRoot || !remoteRoot) throw new Error("Codex remoteWorkspaceRoot requires non-empty workspace roots.");
315
- const normalizedValue = normalizeWorkspaceMatchPath(params.value);
316
- if (!normalizedValue || isCodexPassThroughMediaSource(normalizedValue)) return params.value;
317
- const usesWindowsPaths = /^[a-z]:\//iu.test(remoteRoot) || remoteRoot.startsWith("//");
318
- const matchValue = usesWindowsPaths ? normalizedValue.toLowerCase() : normalizedValue;
319
- const matchRoot = usesWindowsPaths ? remoteRoot.toLowerCase() : remoteRoot;
320
- if (matchValue === matchRoot) return params.localWorkspaceRoot;
321
- const prefix = matchRoot.endsWith("/") ? matchRoot : `${matchRoot}/`;
322
- const isRemoteWorkspacePath = matchValue.startsWith(prefix);
323
- if (!isRemoteWorkspacePath && isAbsoluteWorkspacePath(normalizedValue)) throw new Error(`Codex remote workspace artifact ${params.value} is outside ${params.remoteWorkspaceRoot}.`);
324
- const suffixSegments = (isRemoteWorkspacePath ? normalizedValue.slice(prefix.length) : normalizedValue).split("/");
325
- if (suffixSegments.some((segment) => segment === "..")) throw new Error(`Codex remote workspace artifact ${params.value} must stay inside ${params.remoteWorkspaceRoot}.`);
326
- return path.join(params.localWorkspaceRoot, ...suffixSegments.filter((segment) => segment !== "."));
327
- }
328
- function normalizeWorkspaceMatchPath(value) {
329
- const normalized = value.replace(/\\/gu, "/");
330
- if (/^[a-z]:\/$/iu.test(normalized)) return normalized;
331
- return normalized.length > 1 ? normalized.replace(/[\\/]+$/u, "") : normalized;
332
- }
333
- /** Keeps remote URLs and opaque managed media references out of workspace path mapping. */
334
- function isCodexPassThroughMediaSource(value) {
335
- return /^(?:https?|mxc|buffer|media):\/\//iu.test(value) || /^data:/iu.test(value);
336
- }
337
- function isAbsoluteWorkspacePath(value) {
338
- return value.startsWith("/") || /^[a-z]:\//iu.test(value) || /^[a-z][a-z0-9+.-]*:/iu.test(value);
339
- }
340
- function joinRemoteWorkspacePath(remoteRoot, suffix) {
341
- return remoteRoot.endsWith("/") ? `${remoteRoot}${suffix}` : `${remoteRoot}/${suffix}`;
342
- }
343
- //#endregion
344
289
  //#region extensions/codex/src/app-server/remote-workspace-media.ts
345
290
  const REMOTE_WORKSPACE_MEDIA_TIMEOUT_MS = 6e4;
346
291
  const REMOTE_WORKSPACE_MEDIA_MAX_BYTES = 67108864;
347
292
  const REMOTE_WORKSPACE_MEDIA_MAX_ATTACHMENTS = 16;
348
- const CODEX_REMOTE_MEDIA_CHUNK_BYTES = 524288;
349
- const CODEX_REMOTE_COMMAND_DEFAULT_OUTPUT_BYTES = 1048576;
350
- const CODEX_BOUNDED_REMOTE_FILE_READER = [
351
- "try{",
352
- "const fs=require(\"node:fs\");",
353
- "const path=require(\"node:path\");",
354
- "const file=process.argv[1];",
355
- "const max=Number(process.argv[2]);",
356
- "const offset=Number(process.argv[3]);",
357
- "const chunk=Number(process.argv[4]);",
358
- "const workspace=process.argv[5];",
359
- "if(!Number.isSafeInteger(max)||max<0)throw Error(\"invalid media byte limit\");",
360
- "if(!Number.isSafeInteger(offset)||offset<0||!Number.isSafeInteger(chunk)||chunk<=0)throw Error(\"invalid media chunk\");",
361
- "if(fs.lstatSync(file).isSymbolicLink())throw Error(\"symbolic links are not allowed\");",
362
- "const noFollow=fs.constants.O_NOFOLLOW??0;",
363
- "const fd=fs.openSync(file,fs.constants.O_RDONLY|noFollow);",
364
- "try{",
365
- "const before=fs.fstatSync(fd);",
366
- "if(!before.isFile())throw Error(\"not a regular file\");",
367
- "if(workspace){",
368
- "const descriptor=process.platform===\"linux\"?fs.realpathSync(`/proc/self/fd/${fd}`):fs.realpathSync(file);",
369
- "const relative=path.relative(fs.realpathSync(workspace),descriptor);",
370
- "if(!relative||relative===\"..\"||relative.startsWith(`..${path.sep}`)||path.isAbsolute(relative))throw Error(\"file escapes remote workspace\");",
371
- "const verified=fs.statSync(descriptor);",
372
- "if(verified.dev!==before.dev||verified.ino!==before.ino)throw Error(\"file changed while being opened\");",
373
- "}",
374
- "if(before.size>max)throw Error(`file exceeds limit of ${max} bytes`);",
375
- "if(offset>before.size)throw Error(\"file changed while being read\");",
376
- "const expected=Math.min(chunk,before.size-offset);",
377
- "const buffer=Buffer.allocUnsafe(expected);",
378
- "let total=0;",
379
- "while(total<buffer.length){",
380
- "const count=fs.readSync(fd,buffer,total,buffer.length-total,offset+total);",
381
- "if(count===0)break;total+=count;",
382
- "}",
383
- "if(total!==expected)throw Error(\"file changed while being read\");",
384
- "const after=fs.fstatSync(fd);",
385
- "const revision=stat=>[stat.dev,stat.ino,stat.size,stat.mtimeMs,stat.ctimeMs].join(\":\");",
386
- "if(!after.isFile()||revision(after)!==revision(before))throw Error(\"file changed while being read\");",
387
- "process.stdout.write(JSON.stringify({dataBase64:buffer.toString(\"base64\"),size:before.size,revision:revision(before)}));",
388
- "}finally{fs.closeSync(fd)}",
389
- "}catch(error){process.stderr.write(error instanceof Error?error.message:String(error));process.exitCode=1}"
390
- ].join("");
391
- const MESSAGE_MEDIA_KEYS = [
392
- "media",
393
- "mediaUrl",
394
- "media_url",
395
- "path",
396
- "filePath",
397
- "fileUrl",
398
- "imageUrl",
399
- "image_url"
400
- ];
401
- const MESSAGE_MEDIA_ARRAY_KEYS = [
402
- "mediaUrls",
403
- "media_urls",
404
- "imageUrls",
405
- "image_urls"
406
- ];
407
- const ATTACHMENT_MEDIA_KEYS = [
408
- "media",
409
- "mediaUrl",
410
- "path",
411
- "filePath",
412
- "fileUrl",
413
- "url"
414
- ];
415
- function collectCodexMessageMediaUrls(record) {
416
- const urls = [];
417
- mapMessageMediaValues(record, (value) => {
418
- if (value.trim()) urls.push(value.trim());
419
- return value;
420
- });
421
- return urls;
422
- }
423
- /** Reads actual remote bytes with a cap enforced by Codex before transport. */
424
- async function readBoundedCodexRemoteWorkspaceFile(params) {
425
- if (!Number.isSafeInteger(params.maxBytes) || params.maxBytes < 0) throw new Error("Codex remote workspace upload requires a valid media byte limit.");
426
- params.signal?.throwIfAborted();
427
- const chunks = [];
428
- let offset = 0;
429
- let expectedSize;
430
- let expectedRevision;
431
- const startedAt = performance.now();
432
- do {
433
- params.signal?.throwIfAborted();
434
- const timeoutMs = params.timeoutMs === void 0 ? void 0 : Math.floor(params.timeoutMs - (performance.now() - startedAt));
435
- if (timeoutMs !== void 0 && timeoutMs <= 0) throw new Error("Codex remote workspace file transfer timed out.");
436
- let response;
437
- try {
438
- response = await params.client.request("command/exec", {
439
- command: [
440
- "node",
441
- "-e",
442
- CODEX_BOUNDED_REMOTE_FILE_READER,
443
- "--",
444
- params.path,
445
- String(params.maxBytes),
446
- String(offset),
447
- String(CODEX_REMOTE_MEDIA_CHUNK_BYTES),
448
- ...params.workspaceRoot ? [params.workspaceRoot] : []
449
- ],
293
+ /** Adapts the current app-server connection without changing its Windows output cap. */
294
+ function createCodexRemoteWorkspaceFileReader(client, authority) {
295
+ const read = createBoundedRemoteFileReader({
296
+ outputBytesCap: 1048576,
297
+ assertCurrent: authority.assertCurrent,
298
+ execute: async (command, options) => {
299
+ const response = await client.request("command/exec", {
300
+ command,
450
301
  env: {
451
302
  NODE_OPTIONS: null,
452
303
  NODE_PATH: null
453
304
  },
454
- ...timeoutMs === void 0 ? {} : { timeoutMs }
305
+ ...options.timeoutMs === void 0 ? {} : { timeoutMs: options.timeoutMs }
455
306
  }, {
456
- signal: params.signal,
457
- timeoutMs
307
+ ...options,
308
+ assertCurrent: authority.assertCurrent,
309
+ withCurrent: authority.withCurrent
310
+ }).catch((error) => {
311
+ if (error instanceof Error && /failed to spawn|executable.*not found|\bENOENT\b/iu.test(error.message)) throw new Error("Codex remote workspace file transfer requires Node.js on the remote app-server host.", { cause: error });
312
+ throw error;
458
313
  });
459
- } catch (error) {
460
- if (error instanceof Error && /failed to spawn|executable.*not found|\bENOENT\b/iu.test(error.message)) throw new Error("Codex remote workspace file transfer requires Node.js on the remote app-server host.", { cause: error });
461
- throw error;
462
- }
463
- if (!response || response.exitCode !== 0) {
464
- const detail = typeof response?.stderr === "string" ? response.stderr.trim() : "";
465
- throw new Error(`Codex remote workspace artifact could not be read: ${params.path}${detail ? `: ${detail}` : ""}`);
314
+ if (!response || response.exitCode !== 0) throw new Error(`Codex remote workspace file read failed: ${response?.stderr ?? "no response"}`);
315
+ return response.stdout;
466
316
  }
467
- if (typeof response.stdout !== "string" || response.stdout.length > CODEX_REMOTE_COMMAND_DEFAULT_OUTPUT_BYTES) throw new Error("Codex remote workspace artifact exceeded the native command output cap.");
468
- let payload;
469
- try {
470
- payload = JSON.parse(response.stdout);
471
- } catch {
472
- throw new Error("Codex remote workspace artifact returned invalid chunk data.");
473
- }
474
- if (!payload || typeof payload !== "object" || Array.isArray(payload)) throw new Error("Codex remote workspace artifact returned invalid chunk data.");
475
- const chunk = payload;
476
- if (typeof chunk.dataBase64 !== "string" || !Number.isSafeInteger(chunk.size) || chunk.size < 0 || chunk.size > params.maxBytes || typeof chunk.revision !== "string" || !chunk.revision) throw new Error("Codex remote workspace artifact returned invalid or oversized chunk data.");
477
- if (expectedSize === void 0) {
478
- expectedSize = chunk.size;
479
- expectedRevision = chunk.revision;
480
- }
481
- if (chunk.size !== expectedSize || chunk.revision !== expectedRevision) throw new Error("Codex remote workspace artifact changed during chunked transfer.");
482
- const remainingBytes = expectedSize - offset;
483
- const expectedChunkBytes = Math.min(CODEX_REMOTE_MEDIA_CHUNK_BYTES, remainingBytes);
484
- if (chunk.dataBase64.length > Math.ceil(expectedChunkBytes / 3) * 4) throw new Error("Codex remote workspace artifact returned oversized chunk data.");
485
- const buffer = Buffer.from(chunk.dataBase64, "base64");
486
- if (buffer.byteLength !== expectedChunkBytes || buffer.toString("base64") !== chunk.dataBase64) throw new Error("Codex remote workspace artifact returned invalid chunk data.");
487
- chunks.push(buffer);
488
- offset += buffer.byteLength;
489
- } while (offset < (expectedSize ?? 0));
490
- return { dataBase64: Buffer.concat(chunks, offset).toString("base64") };
317
+ });
318
+ return async (params) => {
319
+ const bytes = await read(params);
320
+ return authority.withCurrent(() => {
321
+ params.signal?.throwIfAborted();
322
+ return bytes;
323
+ });
324
+ };
491
325
  }
492
326
  /** Stages authoritative bounded remote bytes into immutable Gateway-owned media. */
493
327
  async function prepareCodexRemoteWorkspaceMessageMedia(params) {
@@ -501,7 +335,7 @@ async function prepareCodexRemoteWorkspaceMessageMedia(params) {
501
335
  const gatewayManagedPaths = /* @__PURE__ */ new Set();
502
336
  const gatewayMediaRoot = getMediaDir();
503
337
  let attachmentEntries = 0;
504
- const mappedArgs = mapMessageMediaValues(params.args, (value) => {
338
+ const mappedArgs = mapAgentHarnessMessagingMediaValues(params.args, (value) => {
505
339
  if (path.isAbsolute(value) && isPathStrictlyInside(gatewayMediaRoot, value)) {
506
340
  attachmentEntries += 1;
507
341
  gatewayManagedPaths.add(value);
@@ -547,24 +381,20 @@ async function prepareCodexRemoteWorkspaceMessageMedia(params) {
547
381
  const remainingBytes = maxBytes - totalBytes;
548
382
  const remainingMs = Math.floor(deadline - performance.now());
549
383
  if (remainingMs <= 0) throw new Error("Codex remote workspace attachment batch timed out.");
550
- const response = await readRemoteFile({
384
+ const remoteBuffer = await readRemoteFile({
551
385
  path: remotePath,
552
386
  maxBytes: remainingBytes,
553
387
  workspaceRoot: remoteWorkspaceRoot,
554
388
  signal: params.signal,
555
389
  timeoutMs: remainingMs
556
390
  });
557
- if (!response || typeof response.dataBase64 !== "string") throw new Error(`Codex remote workspace artifact returned no file data: ${remotePath}`);
558
- if (response.dataBase64.length > Math.ceil(remainingBytes / 3) * 4) throw new Error(`Codex remote workspace artifact exceeds the limit of ${remainingBytes} bytes.`);
559
- const remoteBuffer = Buffer.from(response.dataBase64, "base64");
560
- if (remoteBuffer.byteLength > remainingBytes || remoteBuffer.toString("base64") !== response.dataBase64) throw new Error(`Codex remote workspace artifact returned invalid or oversized file data: ${remotePath}`);
561
391
  totalBytes += remoteBuffer.byteLength;
562
392
  const saved = await saveMediaBuffer(remoteBuffer, void 0, "outbound", maxBytes, path.basename(remotePath));
563
393
  stagedPaths.set(localPath, saved.path);
564
394
  sourcePathsByStagedPath.set(normalizeMediaReferenceForComparison(saved.path), [...sourcePaths]);
565
395
  }
566
396
  return {
567
- args: mapMessageMediaValues(mappedArgs, (value) => stagedPaths.get(value) ?? value),
397
+ args: mapAgentHarnessMessagingMediaValues(mappedArgs, (value) => stagedPaths.get(value) ?? value),
568
398
  sourcePathsByStagedPath
569
399
  };
570
400
  }
@@ -579,32 +409,6 @@ async function assertGatewayManagedMediaPath(value, mediaRoot) {
579
409
  await opened[Symbol.asyncDispose]();
580
410
  }
581
411
  }
582
- function mapMessageMediaValues(args, mapValue) {
583
- const mapString = (value) => typeof value === "string" ? mapValue(value) : value;
584
- const mapArray = (values, map) => {
585
- const mapped = values.map(map);
586
- return mapped.some((value, index) => value !== values[index]) ? mapped : values;
587
- };
588
- const mapRecord = (record, keys, message = false) => {
589
- let mapped = record;
590
- const assign = (key, value) => {
591
- if (value !== record[key]) {
592
- if (mapped === record) mapped = { ...record };
593
- mapped[key] = value;
594
- }
595
- };
596
- for (const key of keys) assign(key, mapString(record[key]));
597
- if (message) {
598
- for (const key of MESSAGE_MEDIA_ARRAY_KEYS) {
599
- const value = record[key];
600
- if (Array.isArray(value)) assign(key, mapArray(value, mapString));
601
- }
602
- if (Array.isArray(record.attachments)) assign("attachments", mapArray(record.attachments, (attachment) => isRecord(attachment) ? mapRecord(attachment, ATTACHMENT_MEDIA_KEYS) : attachment));
603
- }
604
- return mapped;
605
- };
606
- return mapRecord(args, MESSAGE_MEDIA_KEYS, true);
607
- }
608
412
  //#endregion
609
413
  //#region extensions/codex/src/app-server/native-process-authority.ts
610
414
  const clients = /* @__PURE__ */ new WeakMap();
@@ -617,9 +421,6 @@ function getCodexNativeProcessClient(client) {
617
421
  }
618
422
  return owner;
619
423
  }
620
- function hasCodexNativeBackgroundProcesses(client, threadId) {
621
- return clients.get(client)?.hasProcesses(threadId) ?? false;
622
- }
623
424
  /** Read the native process owner's live inventory, never infer custody from a start event. */
624
425
  async function readCodexRetainedBackgroundCommands(params) {
625
426
  params.assertCurrent();
@@ -703,9 +504,6 @@ var CodexNativeProcessClient = class {
703
504
  owner.commands.add(command);
704
505
  return command;
705
506
  }
706
- hasProcesses(threadId) {
707
- return [...this.threads.get(threadId)?.values() ?? []].some((command) => command.processes.size > 0 || command.background !== void 0);
708
- }
709
507
  claim(metadata, terminate) {
710
508
  if (this.closed || !isJsonObject(metadata) || typeof metadata.threadId !== "string" || typeof metadata.toolCallId !== "string") throw new Error("Codex process start requires its admitted native command");
711
509
  const command = this.threads.get(metadata.threadId)?.get(metadata.toolCallId);
@@ -777,12 +575,13 @@ var CodexNativeProcessAuthority = class {
777
575
  throw error;
778
576
  }
779
577
  }
780
- ownsCurrentCommand(client, receipt) {
781
- return this.findCurrentCommand(client, receipt) !== void 0;
578
+ hasCurrentProcesses(client, threadId) {
579
+ this.assertCurrent();
580
+ return [...this.commands].some((command) => command.client === clients.get(client) && command.threadId === threadId && (command.processes.size > 0 || command.background?.confirmed === true));
782
581
  }
783
- findCurrentCommand(client, receipt) {
582
+ ownsCurrentCommand(client, receipt) {
784
583
  this.assertCurrent();
785
- return [...this.commands].find((command) => command.client === clients.get(client) && command.threadId === receipt.threadId && command.turnId === receipt.turnId && command.itemId === receipt.itemId && command.processes.size > 0);
584
+ return [...this.commands].some((command) => command.client === clients.get(client) && command.threadId === receipt.threadId && command.turnId === receipt.turnId && command.itemId === receipt.itemId && command.processes.size > 0);
786
585
  }
787
586
  bindTurn(client, threadId, turnId) {
788
587
  this.parentTurn = {
@@ -943,10 +742,16 @@ const CODEX_NODE_HTTP_CREDENTIAL_HEADER_NAMES = /* @__PURE__ */ new Set([
943
742
  const CODEX_NODE_HTTP_CREDENTIAL_HEADER_NAME_PATTERN = /(?:^|[-_])(?:auth(?:orization|entication)?|token|secret|api[-_]?key|apikey|key|password|passwd|pwd|passphrase|passcode|credentials?|session|jwt|assertion|verifier|sig(?:nature)?|hmac|bearer|ticket|challenge|proof|dpop|otp|totp|pin|mfa)(?:[-_]|$)/iu;
944
743
  const CODEX_NODE_HTTP_CREDENTIAL_FIELD_NAME_PATTERN = /^(?:(?:[a-z\d]+_)*(?:token|secret|password|passwd|pwd|passphrase|passcode|credentials?|authorization|api_?key|private_key|secret_key|secret_access_key|jwt|assertion|verifier|signature|hmac|bearer|ticket|(?:oauth|consumer|auth|access)_key|otp|totp|pin)|(?:device|authorization|auth|verification|mfa)_code|session(?:_id)?|jsessionid|saml(?:_?response|_?assertion)?|auth|jwt|code|sig|signature|hmac|key|pass)$/u;
945
744
  const nodeExecServerTextDecoder = new TextDecoder("utf-8", { fatal: true });
745
+ var CodexNodeExecServerDisconnectedError = class extends Error {
746
+ constructor(message) {
747
+ super(message);
748
+ this.code = "codex_node_disconnected";
749
+ this.name = "CodexNodeExecServerDisconnectedError";
750
+ }
751
+ };
946
752
  /** Produces the bounded, redacted terminal failure shared by pending and claimed node leases. */
947
753
  function createCodexNodeExecServerDisconnectError(reason, cause) {
948
- const detail = cause === void 0 ? "" : `: ${truncateUtf16Safe(redactSensitiveText$1(formatErrorMessage$2(cause), { mode: "tools" }), CODEX_NODE_EXEC_SERVER_MAX_FAILURE_DETAIL_CHARS)}`;
949
- return /* @__PURE__ */ new Error(`Codex execution node disconnected; start a fresh attempt. (${reason}${detail})`);
754
+ return new CodexNodeExecServerDisconnectedError(`Codex execution node disconnected; start a fresh attempt. (${reason}${cause === void 0 ? "" : `: ${truncateUtf16Safe(redactSensitiveText$1(formatErrorMessage$2(cause), { mode: "tools" }), CODEX_NODE_EXEC_SERVER_MAX_FAILURE_DETAIL_CHARS)}`})`);
950
755
  }
951
756
  /** Relays one authorized, single-use Codex exec-server channel without interpreting its protocol. */
952
757
  async function startCodexNodeExecServerRelay(params) {
@@ -1015,7 +820,7 @@ function sendCodexExecServerFrame(socket, frame) {
1015
820
  });
1016
821
  }
1017
822
  function normalizeCodexExecServerFrame(data) {
1018
- const frame = Array.isArray(data) ? Buffer.concat(data) : Buffer.isBuffer(data) ? data : data instanceof Uint8Array ? Buffer.from(data.buffer, data.byteOffset, data.byteLength) : Buffer.from(data);
823
+ const frame = codexWebSocketDataToBuffer(data);
1019
824
  if (frame.length > CODEX_NODE_EXEC_SERVER_MAX_MESSAGE_BYTES$1) throw new RangeError("Codex exec-server message exceeds its 64 MiB limit.");
1020
825
  if (frame.includes(10) || frame.includes(13)) throw new Error("Codex exec-server messages must occupy exactly one stdio line.");
1021
826
  return frame;
@@ -1048,12 +853,8 @@ function rejectCredentialedCodexNodeHttpRequest(request) {
1048
853
  return credentialBearing ? createCredentialedCodexNodeHttpRejection(request) : void 0;
1049
854
  }
1050
855
  function hasCredentialedCodexNodeHttpUrl(value) {
1051
- let url;
1052
- try {
1053
- url = new URL(value);
1054
- } catch {
1055
- throw new Error("Codex http/request URL must be valid.");
1056
- }
856
+ const url = URL.parse(value);
857
+ if (!url) throw new Error("Codex http/request URL must be valid.");
1057
858
  if (url.username || url.password || hasSensitiveCodexNodeText(value)) return true;
1058
859
  let fields = 0;
1059
860
  const hasCredentialedParameter = (name, parameterValue) => ++fields > CODEX_NODE_HTTP_CREDENTIAL_SCAN_MAX_FIELDS || isCodexNodeCredentialField(name) || hasSensitiveCodexNodeText(parameterValue);
@@ -1198,10 +999,8 @@ function sanitizeCodexExecServerEnvironment(record, key) {
1198
999
  const values = {};
1199
1000
  for (const [name, value] of Object.entries(environment)) {
1200
1001
  if (typeof value !== "string") throw new Error(`Codex process/start ${key} values must be strings.`);
1201
- try {
1202
- const url = new URL(value);
1203
- if (url.username || url.password) continue;
1204
- } catch {}
1002
+ const url = URL.parse(value);
1003
+ if (url?.username || url?.password) continue;
1205
1004
  values[name] = value;
1206
1005
  }
1207
1006
  record[key] = sanitizeEnvVars(values).allowed;
@@ -1426,7 +1225,6 @@ function assertResolvedFsSandboxAccess(policy, requests) {
1426
1225
  }
1427
1226
  }
1428
1227
  function resolveFsAccess(policy, rawPath) {
1429
- if (policy.unrestricted) return "write";
1430
1228
  const target = normalizeSandboxAbsolutePath(rawPath, "fs path");
1431
1229
  let selected;
1432
1230
  for (const entry of policy.entries) {
@@ -1559,7 +1357,8 @@ async function openFile(execServer, handles, params) {
1559
1357
  if (handles.has(handleId)) throw new JsonRpcProtocolError(-32600, `file read handle \`${handleId}\` already exists`);
1560
1358
  if (handles.size >= CODEX_SANDBOX_EXEC_SERVER_MAX_OPEN_FILE_READS) throw new JsonRpcProtocolError(-32600, `at most ${CODEX_SANDBOX_EXEC_SERVER_MAX_OPEN_FILE_READS} file reads may be open per connection`);
1561
1359
  const filePath = resolveExecServerPath(requireString(record.path, "path"), "read path");
1562
- assertFsSandboxAccess(execServer, record, [{
1360
+ const fsSandboxPolicy = resolveFsSandboxPolicy(execServer, record);
1361
+ assertResolvedFsSandboxAccess(fsSandboxPolicy, [{
1563
1362
  path: filePath,
1564
1363
  access: "read"
1565
1364
  }]);
@@ -1571,9 +1370,11 @@ async function openFile(execServer, handles, params) {
1571
1370
  };
1572
1371
  handles.set(handleId, handle);
1573
1372
  try {
1373
+ const readPolicy = await authorizePhysicalReadPath(fsBridge, fsSandboxPolicy, filePath, handle.abortController.signal);
1574
1374
  const stat = await fsBridge.stat({
1575
1375
  filePath,
1576
- signal: handle.abortController.signal
1376
+ signal: handle.abortController.signal,
1377
+ ...readPolicy
1577
1378
  });
1578
1379
  if (handles.get(handleId) !== handle || handle.closeRequested || handles.closed) throw new JsonRpcProtocolError(JSON_RPC_NOT_FOUND, `unknown file read handle \`${handleId}\``);
1579
1380
  if (!stat) throw new JsonRpcProtocolError(JSON_RPC_NOT_FOUND, "file not found");
@@ -1584,7 +1385,8 @@ async function openFile(execServer, handles, params) {
1584
1385
  const data = await fsBridge.readFile({
1585
1386
  filePath,
1586
1387
  maxBytes: handle.reservedBytes,
1587
- signal: handle.abortController.signal
1388
+ signal: handle.abortController.signal,
1389
+ ...readPolicy
1588
1390
  });
1589
1391
  if (handles.get(handleId) !== handle || handle.closeRequested || handles.closed) throw new JsonRpcProtocolError(JSON_RPC_NOT_FOUND, `unknown file read handle \`${handleId}\``);
1590
1392
  if (data.byteLength > handle.reservedBytes) throw new JsonRpcProtocolError(-32600, "sandbox file read exceeds the per-connection buffered file limit");
@@ -1645,17 +1447,23 @@ function requireFileReadHandleId(value) {
1645
1447
  async function readFile(execServer, params) {
1646
1448
  const record = requireObject(params, "fs/readFile params");
1647
1449
  const filePath = resolveExecServerPath(requireString(record.path, "path"), "read path");
1648
- assertFsSandboxAccess(execServer, record, [{
1450
+ const fsSandboxPolicy = resolveFsSandboxPolicy(execServer, record);
1451
+ assertResolvedFsSandboxAccess(fsSandboxPolicy, [{
1649
1452
  path: filePath,
1650
1453
  access: "read"
1651
1454
  }]);
1652
1455
  const fsBridge = execServer.fsBridge;
1653
- const stat = await fsBridge.stat({ filePath });
1456
+ const readPolicy = await authorizePhysicalReadPath(fsBridge, fsSandboxPolicy, filePath);
1457
+ const stat = await fsBridge.stat({
1458
+ filePath,
1459
+ ...readPolicy
1460
+ });
1654
1461
  if (!stat) throw new JsonRpcProtocolError(JSON_RPC_NOT_FOUND, "file not found");
1655
1462
  assertSandboxFileReadWithinLimit(stat);
1656
1463
  return { dataBase64: (await fsBridge.readFile({
1657
1464
  filePath,
1658
- maxBytes: CODEX_SANDBOX_EXEC_SERVER_MAX_READ_FILE_BYTES
1465
+ maxBytes: CODEX_SANDBOX_EXEC_SERVER_MAX_READ_FILE_BYTES,
1466
+ ...readPolicy
1659
1467
  })).toString("base64") };
1660
1468
  }
1661
1469
  async function writeFile(execServer, params) {
@@ -1708,11 +1516,16 @@ async function createDirectory(execServer, params) {
1708
1516
  async function getMetadata(execServer, params) {
1709
1517
  const record = requireObject(params, "fs/getMetadata params");
1710
1518
  const filePath = resolveExecServerPath(requireString(record.path, "path"), "metadata path");
1711
- assertFsSandboxAccess(execServer, record, [{
1519
+ const fsSandboxPolicy = resolveFsSandboxPolicy(execServer, record);
1520
+ assertResolvedFsSandboxAccess(fsSandboxPolicy, [{
1712
1521
  path: filePath,
1713
1522
  access: "read"
1714
1523
  }]);
1715
- const stat = await execServer.fsBridge.stat({ filePath });
1524
+ const readPolicy = await authorizePhysicalReadPath(execServer.fsBridge, fsSandboxPolicy, filePath);
1525
+ const stat = await execServer.fsBridge.stat({
1526
+ filePath,
1527
+ ...readPolicy
1528
+ });
1716
1529
  if (!stat) throw new JsonRpcProtocolError(JSON_RPC_NOT_FOUND, "file not found");
1717
1530
  return {
1718
1531
  isDirectory: stat.type === "directory",
@@ -1735,7 +1548,7 @@ async function listDirectoryEntries(execServer, filePath, fsSandboxPolicy) {
1735
1548
  const resolved = execServer.fsBridge.resolvePath({ filePath });
1736
1549
  if (!resolved) throw new Error(`Cannot resolve sandbox path: ${filePath}`);
1737
1550
  const result = await execServer.backend.runShellCommand({
1738
- script: "find \"$1\" -mindepth 1 -maxdepth 1 -exec sh -c 'for path do name=${path##*/}; if [ -L \"$path\" ]; then kind=o; elif [ -d \"$path\" ]; then kind=d; elif [ -f \"$path\" ]; then kind=f; else kind=o; fi; printf \"%s\\t%s\\n\" \"$kind\" \"$name\"; done' sh {} +",
1551
+ script: "find \"$1\" -mindepth 1 -maxdepth 1 -exec sh -c 'for path do name=${path##*/}; if [ -L \"$path\" ]; then kind=o; elif [ -d \"$path\" ]; then kind=d; elif [ -f \"$path\" ]; then kind=f; else kind=o; fi; printf \"%s%s\\000\" \"$kind\" \"$name\"; done' sh {} +",
1739
1552
  args: [resolved.containerPath],
1740
1553
  allowFailure: true
1741
1554
  });
@@ -1743,14 +1556,23 @@ async function listDirectoryEntries(execServer, filePath, fsSandboxPolicy) {
1743
1556
  const stderr = result.stderr.toString("utf8").trim();
1744
1557
  throw new Error(stderr || `sandbox directory listing failed with code ${result.code}`);
1745
1558
  }
1746
- return result.stdout.toString("utf8").split("\n").filter(Boolean).map((line) => {
1747
- const [kind = "o", fileName = ""] = line.split(" ");
1748
- return {
1749
- fileName,
1750
- isDirectory: kind === "d",
1751
- isFile: kind === "f"
1752
- };
1559
+ return result.stdout.toString("utf8").split("\0").filter(Boolean).map((entry) => ({
1560
+ fileName: entry.slice(1),
1561
+ isDirectory: entry[0] === "d",
1562
+ isFile: entry[0] === "f"
1563
+ }));
1564
+ }
1565
+ async function authorizePhysicalReadPath(fsBridge, policy, filePath, signal) {
1566
+ if (!policy || policy.unrestricted || !fsBridge.resolveReadPolicyPath) return {};
1567
+ const expectedPolicyPath = await fsBridge.resolveReadPolicyPath({
1568
+ filePath,
1569
+ signal
1753
1570
  });
1571
+ assertResolvedFsSandboxAccess(policy, [{
1572
+ path: expectedPolicyPath,
1573
+ access: "read"
1574
+ }]);
1575
+ return { expectedPolicyPath };
1754
1576
  }
1755
1577
  async function removePath(execServer, params) {
1756
1578
  const record = requireObject(params, "fs/remove params");
@@ -2198,7 +2020,7 @@ function readSandboxHttpResponse(params) {
2198
2020
  embeddedAgentLog.warn("codex sandbox http/request cleanup failed", { error });
2199
2021
  });
2200
2022
  if (headerResolved) {
2201
- if (params.notifications.isOpen()) params.notifications.send("http/request/bodyDelta", {
2023
+ params.notifications.send("http/request/bodyDelta", {
2202
2024
  requestId: params.requestId,
2203
2025
  seq: lastBodySeq + 1,
2204
2026
  deltaBase64: "",
@@ -2248,7 +2070,7 @@ function readSandboxHttpResponse(params) {
2248
2070
  } else if (type === "bodyDelta") {
2249
2071
  const seq = requireNumber(message.seq, "http body sequence");
2250
2072
  lastBodySeq = Math.max(lastBodySeq, seq);
2251
- if (params.notifications.isOpen()) params.notifications.send("http/request/bodyDelta", {
2073
+ params.notifications.send("http/request/bodyDelta", {
2252
2074
  requestId: params.requestId,
2253
2075
  seq,
2254
2076
  deltaBase64: typeof message.deltaBase64 === "string" ? message.deltaBase64 : "",
@@ -2875,7 +2697,7 @@ function buildEnvFromPolicy(value) {
2875
2697
  if (!value || typeof value !== "object" || Array.isArray(value)) return {};
2876
2698
  const policy = value;
2877
2699
  const inheritedEnv = readEnv(policy.set);
2878
- const includeOnly = readStringList(policy.includeOnly);
2700
+ const includeOnly = filterStringEntries(policy.includeOnly);
2879
2701
  if (includeOnly.length > 0) {
2880
2702
  const regexes = includeOnly.map(wildcardPatternToRegex);
2881
2703
  for (const key of Object.keys(inheritedEnv)) if (!regexes.some((regex) => regex.test(key))) delete inheritedEnv[key];
@@ -2886,9 +2708,6 @@ function wildcardPatternToRegex(pattern) {
2886
2708
  const escaped = pattern.replace(/[.+^${}()|[\]\\]/gu, "\\$&");
2887
2709
  return new RegExp(`^${escaped.replaceAll("*", ".*").replaceAll("?", ".")}$`, "iu");
2888
2710
  }
2889
- function readStringList(value) {
2890
- return Array.isArray(value) ? value.filter((entry) => typeof entry === "string") : [];
2891
- }
2892
2711
  //#endregion
2893
2712
  //#region extensions/codex/src/app-server/sandbox-exec-server/session.ts
2894
2713
  /** Owns the JSON-RPC protocol and resources of one sandbox execution connection. */
@@ -2903,7 +2722,6 @@ var CodexSandboxExecSession = class {
2903
2722
  this.httpRequests = /* @__PURE__ */ new Set();
2904
2723
  this.closeController = new AbortController();
2905
2724
  this.notifications = {
2906
- isOpen: transport.isOpen,
2907
2725
  signal: this.closeController.signal,
2908
2726
  send: (method, params) => {
2909
2727
  if (transport.isOpen()) transport.send({
@@ -3050,14 +2868,10 @@ async function releaseCodexSandboxExecServerEnvironment(sandbox, environment) {
3050
2868
  function canExposeLocalExecServerToAppServer(startOptions) {
3051
2869
  if (!startOptions || startOptions.transport !== "websocket") return true;
3052
2870
  if (typeof startOptions.url !== "string") return false;
3053
- try {
3054
- const host = new URL(startOptions.url).hostname.toLowerCase();
3055
- const ipHost = host.startsWith("[") && host.endsWith("]") ? host.slice(1, -1) : host;
3056
- if (host === "localhost" || ipHost === "::1") return true;
3057
- return isIP(ipHost) === 4 && ipHost.split(".")[0] === "127";
3058
- } catch {
3059
- return false;
3060
- }
2871
+ const host = URL.parse(startOptions.url)?.hostname.toLowerCase();
2872
+ if (!host) return false;
2873
+ const ipHost = host.startsWith("[") && host.endsWith("]") ? host.slice(1, -1) : host;
2874
+ return host === "localhost" || ipHost === "::1" || isIP(ipHost) === 4 && ipHost.split(".")[0] === "127";
3061
2875
  }
3062
2876
  async function acquireOpenClawExecServer(params) {
3063
2877
  const { sandbox, runtime, signal, onExecutionDisconnect } = params;
@@ -3178,16 +2992,16 @@ async function startOpenClawExecServer(sandbox) {
3178
2992
  };
3179
2993
  server.on("connection", (socket, request) => {
3180
2994
  socket.on("error", handleExecServerSocketError);
3181
- if (!isAuthorizedExecServerRequest(execServer, request)) {
2995
+ const requestUrl = new URL(request.url ?? "", "ws://127.0.0.1");
2996
+ if (requestUrl.pathname !== execServer.authPath && ("node" in execServer || !execServer.processAuthorities?.has(requestUrl.pathname))) {
3182
2997
  socket.close(1008, "unauthorized");
3183
2998
  return;
3184
2999
  }
3185
3000
  if ("node" in execServer) {
3186
- handleNodeConnection(execServer, socket, request);
3001
+ handleNodeConnection(execServer, socket, requestUrl);
3187
3002
  return;
3188
3003
  }
3189
- const requestPath = new URL(request.url ?? "", "ws://127.0.0.1").pathname;
3190
- handleConnection(execServer, socket, execServer.processAuthorities?.get(requestPath));
3004
+ handleConnection(execServer, socket, execServer.processAuthorities?.get(requestUrl.pathname));
3191
3005
  });
3192
3006
  embeddedAgentLog.info("codex sandbox exec-server started", {
3193
3007
  environmentId,
@@ -3208,10 +3022,6 @@ async function releaseOpenClawExecServer(execServer) {
3208
3022
  function buildEnvironmentId(sandbox) {
3209
3023
  return `openclaw-sandbox-${createHash("sha256").update(sandbox.runtimeId).digest("hex").slice(0, 16)}`;
3210
3024
  }
3211
- function isAuthorizedExecServerRequest(execServer, request) {
3212
- const url = new URL(request.url ?? "", "ws://127.0.0.1");
3213
- return url.pathname === execServer.authPath || !("node" in execServer) && execServer.processAuthorities?.has(url.pathname) === true;
3214
- }
3215
3025
  function readCodexPlacementNodeId(sandbox) {
3216
3026
  if (!("placementExecutionMode" in sandbox) || sandbox.placementExecutionMode !== "remote-exec" || !("placementNodeId" in sandbox) || typeof sandbox.placementNodeId !== "string" || !sandbox.placementNodeId) return;
3217
3027
  return sandbox.placementNodeId;
@@ -3225,8 +3035,8 @@ function readCodexPlacementWorkspaceIdentity(sandbox) {
3225
3035
  sessionKey: sandbox.sessionKey
3226
3036
  };
3227
3037
  }
3228
- function handleNodeConnection(execServer, socket, request) {
3229
- const leaseId = new URL(request.url ?? "", "ws://127.0.0.1").searchParams.get("lease");
3038
+ function handleNodeConnection(execServer, socket, requestUrl) {
3039
+ const leaseId = requestUrl.searchParams.get("lease");
3230
3040
  const lease = leaseId ? execServer.node.leases.get(leaseId) : void 0;
3231
3041
  if (!lease || lease.claimed || lease.closed) {
3232
3042
  socket.close(1008, "execution channel unavailable");
@@ -3283,435 +3093,7 @@ function handleExecServerSocketError(error) {
3283
3093
  embeddedAgentLog.debug("codex sandbox exec-server websocket failed", { error });
3284
3094
  }
3285
3095
  async function handleMessage(session, data) {
3286
- const buffer = Array.isArray(data) ? Buffer.concat(data) : Buffer.isBuffer(data) ? data : Buffer.from(data);
3287
- await session.handleRequest(parseRequest(buffer.toString("utf8")));
3288
- }
3289
- //#endregion
3290
- //#region extensions/codex/src/app-server/vision-tools.ts
3291
- /**
3292
- * Codex's enabled native surface includes its stable view_image loader. Keep
3293
- * OpenClaw's view_image tool only when that surface or model vision is unavailable.
3294
- */
3295
- function filterCodexVisionTools(tools, params) {
3296
- if (!params.modelHasVision || !params.nativeImageInspectionEnabled) return tools;
3297
- return tools.filter((tool) => tool.name !== "view_image");
3298
- }
3299
- //#endregion
3300
- //#region extensions/codex/src/app-server/dynamic-tool-build.ts
3301
- const CODEX_MEMORY_FLUSH_DYNAMIC_TOOL_ALLOW = /* @__PURE__ */ new Set(["read", "write"]);
3302
- const CODEX_DISABLED_NATIVE_SHELL_DYNAMIC_TOOLS = /* @__PURE__ */ new Set([
3303
- "exec",
3304
- "process",
3305
- "sandbox_exec",
3306
- "sandbox_process",
3307
- CODEX_GATEWAY_EXEC_DYNAMIC_TOOL_NAME,
3308
- CODEX_GATEWAY_PROCESS_DYNAMIC_TOOL_NAME,
3309
- CODEX_NODE_EXEC_DYNAMIC_TOOL_NAME
3310
- ]);
3311
- /** Keeps node filesystem and process ownership on its native exec-server. */
3312
- function resolveCodexNodePlacementToolConstructionPlan(sandbox, nativeToolSurfaceEnabled) {
3313
- if (!isCodexRemoteExecPlacementSandbox(sandbox) || sandbox?.backendId !== "node" || !("placementNodeId" in sandbox) || typeof sandbox.placementNodeId !== "string" || !sandbox.placementNodeId) return;
3314
- if (!nativeToolSurfaceEnabled) throw new Error("Codex node execution requires its native exec-server tool surface; adjust the session tool policy and start a fresh attempt.");
3315
- return {
3316
- includeBaseCodingTools: false,
3317
- includeShellTools: false,
3318
- includeChannelTools: true,
3319
- includeOpenClawTools: true,
3320
- includePluginTools: true
3321
- };
3322
- }
3323
- function preserveRingZeroSystemAgentTool(allTools, filteredTools) {
3324
- const openclaw = allTools.find((tool) => tool.name === "openclaw" && tool.catalogMode === "direct-only");
3325
- if (!openclaw) return filteredTools;
3326
- return [openclaw, ...filteredTools.filter((tool) => tool.name !== "openclaw")];
3327
- }
3328
- function resolveCodexMessageToolProvider(params) {
3329
- return params.messageChannel ?? params.messageProvider;
3330
- }
3331
- function resolveCodexAppServerHookChannelId(params, sandboxSessionKey) {
3332
- return buildAgentHookContextChannelFields({
3333
- sessionKey: sandboxSessionKey,
3334
- messageChannel: params.messageChannel,
3335
- messageProvider: params.messageProvider,
3336
- currentChannelId: params.currentChannelId,
3337
- messageTo: params.messageTo
3338
- }).channelId;
3339
- }
3340
- const CODEX_DYNAMIC_TOOL_BUILD_WARN_TOTAL_MS = 1e3;
3341
- const CODEX_DYNAMIC_TOOL_BUILD_WARN_STAGE_MS = 500;
3342
- function shouldWarnCodexDynamicToolBuildStageSummary(summary, profilerEnabled = false) {
3343
- const totalWarnMs = profilerEnabled ? CODEX_DYNAMIC_TOOL_BUILD_WARN_TOTAL_MS : 1e4;
3344
- const stageWarnMs = profilerEnabled ? CODEX_DYNAMIC_TOOL_BUILD_WARN_STAGE_MS : 5e3;
3345
- return summary.totalMs >= totalWarnMs || summary.stages.some((stage) => stage.durationMs >= stageWarnMs);
3346
- }
3347
- async function buildDynamicTools(input) {
3348
- const { params } = input;
3349
- const messagePolicyParams = input.ignoreDisableMessageTool ? {
3350
- ...params,
3351
- disableMessageTool: false
3352
- } : params;
3353
- const toolRunContext = buildEmbeddedAttemptToolRunContext({
3354
- ...params,
3355
- forceMessageTool: shouldForceMessageTool(messagePolicyParams)
3356
- });
3357
- if (params.disableTools) {
3358
- input.onWebSearchPolicyResolved?.(false);
3359
- return [];
3360
- }
3361
- if (!supportsModelTools(params.model)) {
3362
- input.onPersistentWebSearchPolicyResolved?.(false);
3363
- input.onWebSearchPolicyResolved?.(false);
3364
- return [];
3365
- }
3366
- const toolBuildStages = createStageTimingTracker();
3367
- const modelHasVision = params.model.input?.includes("image") ?? false;
3368
- const agentDir = params.agentDir ?? resolveAgentDir(params.config ?? {}, input.sessionAgentId);
3369
- const nativeExecutionPolicy = resolveCodexNativeExecutionPolicyForRun(params, {
3370
- agentId: input.policyAgentId,
3371
- runtimeSessionKey: input.sandboxSessionKey,
3372
- sandbox: input.sandbox
3373
- });
3374
- const webSearchPlan = resolveCodexWebSearchPlan({
3375
- config: params.config,
3376
- disableTools: params.disableTools,
3377
- nativeToolSurfaceEnabled: isCodexResponsesOAuthRun(params) || input.nativeToolSurfaceEnabled,
3378
- nativeProviderWebSearchSupport: input.nativeProviderWebSearchSupport
3379
- });
3380
- const messageToolProvider = resolveCodexMessageToolProvider(params);
3381
- const webFetchHostnameAllowlistRef = {};
3382
- const toolConstructionPlan = resolveCodexNodePlacementToolConstructionPlan(input.sandbox, input.nativeToolSurfaceEnabled);
3383
- const options = {
3384
- agentId: input.sessionAgentId,
3385
- policyAgentId: input.policyAgentId,
3386
- ...toolRunContext,
3387
- exec: {
3388
- ...params.execOverrides,
3389
- ...input.sessionPermissionPolicy ? { mode: input.sessionPermissionPolicy.execMode } : {},
3390
- ...resolveCodexNodeExecToolOverrides(nativeExecutionPolicy),
3391
- config: params.config,
3392
- elevated: params.bashElevated
3393
- },
3394
- sessionPermissionPolicy: input.sessionPermissionPolicy ? {
3395
- mode: input.sessionPermissionPolicy.mode,
3396
- root: input.sessionPermissionPolicy.root
3397
- } : void 0,
3398
- sandbox: input.sandbox,
3399
- ...toolConstructionPlan ? { toolConstructionPlan } : {},
3400
- messageProvider: messageToolProvider,
3401
- toolPolicyMessageProvider: params.messageProvider ?? params.messageChannel,
3402
- ...params.onToolResult ? { questionPrompt: {
3403
- send: params.onToolResult,
3404
- messageChannel: messageToolProvider
3405
- } } : {},
3406
- inputProvenance: params.inputProvenance,
3407
- trustedInternalHandoff: params.trustedInternalHandoff,
3408
- allowGatewaySubagentBinding: params.allowGatewaySubagentBinding || isForcedPrivateQaCodexRuntime(),
3409
- sessionKey: input.sandboxSessionKey,
3410
- runSessionKey: params.sessionKey && params.sessionKey !== input.sandboxSessionKey ? params.sessionKey : void 0,
3411
- sessionId: params.sessionId,
3412
- runId: params.runId,
3413
- agentDir,
3414
- preparedModelRuntime: params.preparedModelRuntime,
3415
- cwd: input.effectiveCwd ?? input.effectiveWorkspace,
3416
- workspaceDir: input.effectiveWorkspace,
3417
- spawnWorkspaceDir: input.effectiveCwd && input.effectiveCwd !== input.effectiveWorkspace ? input.resolvedWorkspace : resolveAttemptSpawnWorkspaceDir({
3418
- sandbox: input.sandbox,
3419
- resolvedWorkspace: input.resolvedWorkspace
3420
- }),
3421
- config: params.config,
3422
- skillsSnapshot: params.skillsSnapshot,
3423
- ...params.skillLibraryAuthoring ? { skillWorkshop: { libraryAuthoring: params.skillLibraryAuthoring } } : {},
3424
- authProfileStore: params.toolAuthProfileStore ?? params.authProfileStore,
3425
- abortSignal: input.runAbortController.signal,
3426
- emitBeforeToolCallDiagnostics: false,
3427
- modelProvider: params.model.provider,
3428
- modelId: params.modelId,
3429
- modelCompat: params.model.compat && typeof params.model.compat === "object" ? params.model.compat : void 0,
3430
- modelApi: params.model.api,
3431
- modelContextWindowTokens: params.model.contextWindow,
3432
- delegationCapability: params.delegationCapability,
3433
- modelAuthMode: resolveModelAuthMode(params.model.provider, params.config, params.toolAuthProfileStore ?? params.authProfileStore, { workspaceDir: input.effectiveWorkspace }),
3434
- suppressManagedWebSearch: false,
3435
- webFetchHostnameAllowlistRef,
3436
- hookChannelId: resolveCodexAppServerHookChannelId(params, input.sandboxSessionKey),
3437
- modelHasVision,
3438
- computerContextEpoch: input.computerContextEpoch,
3439
- oneShotCliRun: params.oneShotCliRun,
3440
- registerRunCleanup: input.registerRunCleanup,
3441
- requireExplicitMessageTarget: params.requireExplicitMessageTarget ?? isSubagentSessionKey(params.sessionKey),
3442
- disableMessageTool: input.ignoreDisableMessageTool ? false : params.disableMessageTool,
3443
- forceMessageTool: shouldForceMessageTool(messagePolicyParams),
3444
- enableHeartbeatTool: params.trigger === "heartbeat" || input.forceHeartbeatTool === true,
3445
- forceHeartbeatTool: params.trigger === "heartbeat" || input.forceHeartbeatTool === true,
3446
- onYield: (message, acknowledgment) => {
3447
- input.onYieldDetected(message, acknowledgment);
3448
- input.onCodexAppServerEvent?.({
3449
- stream: "codex_app_server.tool",
3450
- data: {
3451
- name: "sessions_yield",
3452
- message
3453
- }
3454
- });
3455
- },
3456
- claimYieldCompletion: input.claimYieldCompletion,
3457
- recordToolPrepStage: (name) => {
3458
- toolBuildStages.mark(name);
3459
- },
3460
- onToolOutcome: params.onToolOutcome,
3461
- isTurnTainted: params.isTurnTainted,
3462
- allocateToolOutcomeOrdinal: params.allocateToolOutcomeOrdinal,
3463
- cronCreatorToolAllowlistRef: input.cronCreatorToolAllowlistRef,
3464
- cronCreatorToolAllowlistCaptureRef: input.cronCreatorToolAllowlistCaptureRef,
3465
- cronCreatorAuthorityUnavailableReason: input.cronCreatorAuthorityUnavailableReason
3466
- };
3467
- input.onMessageToolTargetResolved?.(options.requireExplicitMessageTarget === true);
3468
- const buildOpenClawCodingTools = () => {
3469
- const bindingOptions = { cwd: input.effectiveCwd ?? input.effectiveWorkspace };
3470
- const createToolSurface = params.hostCapabilities.createToolSurface;
3471
- if (!createToolSurface) throw new Error("Codex tool construction requires a current host capability");
3472
- return createToolSurface(options, bindingOptions);
3473
- };
3474
- const allTools = input.resolveCronCreatorToolAuthority ? runWithCronCreatorAuthorityCapabilityResolver({
3475
- capability: params.cronCreatorAuthorityCapability,
3476
- runId: params.runId,
3477
- resolve: input.resolveCronCreatorToolAuthority,
3478
- run: buildOpenClawCodingTools
3479
- }) : buildOpenClawCodingTools();
3480
- toolBuildStages.mark("create-openclaw-coding-tools");
3481
- const preNormalizationDiagnostics = [];
3482
- const readableAllToolProjection = filterProviderNormalizableTools(allTools);
3483
- preNormalizationDiagnostics.push(...readableAllToolProjection.diagnostics);
3484
- const readableAllTools = [...readableAllToolProjection.tools];
3485
- const normallyProfiledTools = input.nativeToolSurfaceEnabled === false ? filterCodexDynamicToolsForDisabledNativeSurface(readableAllTools, input.pluginConfig, { preserveShell: shouldKeepOpenClawShellDynamicTools(input, nativeExecutionPolicy) }) : filterCodexDynamicTools(readableAllTools, input.pluginConfig);
3486
- const profileFilteredTools = (input.isHostScopedToolActive?.("openclaw") ?? isHostScopedAgentToolActive("openclaw")) && isSystemAgentOnlyCodexDynamicToolAllowlist(params.toolsAllow) ? preserveRingZeroSystemAgentTool(readableAllTools, normallyProfiledTools) : normallyProfiledTools;
3487
- const codexFilteredTools = await addNodeShellDynamicToolsIfNeeded(addGatewayShellDynamicToolsIfAvailable(addSandboxShellDynamicToolsIfAvailable(isCodexMemoryFlushRun(params) ? filterCodexMemoryFlushDynamicTools(readableAllTools) : profileFilteredTools, readableAllTools, input, nativeExecutionPolicy), readableAllTools, input, nativeExecutionPolicy), readableAllTools, input, nativeExecutionPolicy);
3488
- toolBuildStages.mark("codex-filtering");
3489
- const visionFilteredTools = filterCodexVisionTools(codexFilteredTools, {
3490
- modelHasVision,
3491
- nativeImageInspectionEnabled: input.nativeToolSurfaceEnabled === true
3492
- });
3493
- toolBuildStages.mark("vision-filtering");
3494
- const webSearchPresent = visionFilteredTools.some((tool) => tool.name === "web_search");
3495
- const persistentCodexWebSearchSurface = params.config?.tools?.web?.search?.enabled !== false && !(input.pluginConfig.codexDynamicToolsExclude ?? []).some((name) => normalizeCodexDynamicToolName(name) === "web_search");
3496
- let persistentWebSearchAllowed = webSearchPresent;
3497
- if (input.onPersistentWebSearchPolicyResolved && !webSearchPresent && persistentCodexWebSearchSurface) {
3498
- const webSearchPolicy = (await import("openclaw/plugin-sdk/agent-harness")).resolveWebSearchToolPolicy({
3499
- config: params.config,
3500
- modelProvider: params.model.provider,
3501
- modelId: params.modelId,
3502
- agentId: input.policyAgentId,
3503
- sessionKey: input.sandboxSessionKey,
3504
- sandboxToolPolicy: input.sandbox?.tools,
3505
- messageProvider: messageToolProvider,
3506
- agentAccountId: params.agentAccountId,
3507
- groupId: params.groupId,
3508
- groupChannel: params.groupChannel,
3509
- groupSpace: params.groupSpace,
3510
- spawnedBy: params.spawnedBy,
3511
- senderId: params.senderId,
3512
- senderName: params.senderName,
3513
- senderUsername: params.senderUsername,
3514
- senderE164: params.senderE164,
3515
- inputProvenance: params.inputProvenance,
3516
- trustedInternalHandoff: params.trustedInternalHandoff,
3517
- scheduledToolPolicy: params.scheduledToolPolicy
3518
- });
3519
- persistentWebSearchAllowed = webSearchPolicy.persistentAllowed && (!webSearchPolicy.allowed || isCodexMemoryFlushRun(params));
3520
- }
3521
- input.onPersistentWebSearchPolicyResolved?.(persistentWebSearchAllowed);
3522
- const filteredTools = filterCodexDynamicToolsForAllowlist(visionFilteredTools, toolRunContext.runtimeToolAllowlist);
3523
- toolBuildStages.mark("allowlist-filter");
3524
- const normalizedTools = normalizeAgentRuntimeTools({
3525
- runtimePlan: input.ignoreRuntimePlan ? void 0 : params.runtimePlan,
3526
- tools: filteredTools,
3527
- provider: params.provider,
3528
- config: params.config,
3529
- workspaceDir: input.effectiveWorkspace,
3530
- env: process.env,
3531
- modelId: params.modelId,
3532
- modelApi: params.model.api,
3533
- model: params.model,
3534
- allowProviderRuntimePluginLoad: input.ignoreRuntimePlan ? false : void 0,
3535
- onPreNormalizationSchemaDiagnostics: (diagnostics) => preNormalizationDiagnostics.push(...diagnostics)
3536
- });
3537
- toolBuildStages.mark("runtime-normalization");
3538
- const webSearchAllowed = normalizedTools.some((tool) => tool.name === "web_search");
3539
- webFetchHostnameAllowlistRef.value = webSearchAllowed ? webSearchPlan.webFetchHostnameAllowlist : void 0;
3540
- input.onWebSearchPolicyResolved?.(webSearchAllowed);
3541
- const exposedTools = placeDisabledNativeShellToolsInDirectNamespace(webSearchPlan.suppressManagedWebSearch ? normalizedTools.filter((tool) => tool.name !== "web_search") : normalizedTools, input.nativeToolSurfaceEnabled);
3542
- if (preNormalizationDiagnostics.length > 0) embeddedAgentLog.warn(`codex app-server quarantined ${preNormalizationDiagnostics.length} unsupported runtime tool schema${preNormalizationDiagnostics.length === 1 ? "" : "s"} before dynamic tool registration`, {
3543
- runId: params.runId,
3544
- sessionId: params.sessionId,
3545
- diagnostics: preNormalizationDiagnostics.map((diagnostic) => ({
3546
- index: diagnostic.toolIndex,
3547
- tool: diagnostic.toolName,
3548
- violations: diagnostic.violations.slice(0, 12),
3549
- violationCount: diagnostic.violations.length
3550
- }))
3551
- });
3552
- const summary = toolBuildStages.snapshot();
3553
- if (shouldWarnCodexDynamicToolBuildStageSummary(summary, input.profilerEnabled)) {
3554
- const phase = input.forceHeartbeatTool ? "registered-tools" : "runtime-tools";
3555
- embeddedAgentLog.warn(`codex app-server dynamic tool build timings runId=${params.runId} sessionId=${params.sessionId} phase=${phase} totalMs=${summary.totalMs} stages=${formatStageTimings(summary.stages)}`, {
3556
- runId: params.runId,
3557
- sessionId: params.sessionId,
3558
- phase,
3559
- totalMs: summary.totalMs,
3560
- stages: summary.stages,
3561
- allToolCount: readableAllTools.length,
3562
- codexFilteredToolCount: codexFilteredTools.length,
3563
- visionFilteredToolCount: visionFilteredTools.length,
3564
- filteredToolCount: filteredTools.length,
3565
- normalizedToolCount: exposedTools.length,
3566
- forceHeartbeatTool: input.forceHeartbeatTool === true,
3567
- ignoreRuntimePlan: input.ignoreRuntimePlan === true,
3568
- nativeToolSurfaceEnabled: input.nativeToolSurfaceEnabled === true
3569
- });
3570
- }
3571
- return exposedTools;
3572
- }
3573
- /** Keeps the OpenClaw Gateway execution path available beside Codex native shell. */
3574
- function addGatewayShellDynamicToolsIfAvailable(filteredTools, allTools, input, executionPolicy) {
3575
- if (isCodexMemoryFlushRun(input.params) || input.nativeToolSurfaceEnabled !== true || input.sandbox?.enabled === true || !executionPolicy.nativeToolSurfaceAllowed || executionPolicy.effectiveExecHost !== "gateway") return filteredTools;
3576
- const execTool = allTools.find((tool) => normalizeCodexDynamicToolName(tool.name) === "exec");
3577
- const processTool = allTools.find((tool) => normalizeCodexDynamicToolName(tool.name) === "process");
3578
- const existingNames = new Set(filteredTools.map((tool) => normalizeCodexDynamicToolName(tool.name)));
3579
- const execExcluded = isCodexDynamicToolExcluded(input.pluginConfig, ["exec", CODEX_GATEWAY_EXEC_DYNAMIC_TOOL_NAME]);
3580
- if (!execTool || execExcluded || existingNames.has("gateway_exec")) return filteredTools;
3581
- const processExcluded = isCodexDynamicToolExcluded(input.pluginConfig, ["process", CODEX_GATEWAY_PROCESS_DYNAMIC_TOOL_NAME]);
3582
- const processAliasAvailable = Boolean(processTool && !processExcluded && !existingNames.has("gateway_process"));
3583
- const createProjection = resolveCodexScheduledToolProjectionFactory(input.params.hostCapabilities);
3584
- if (!createProjection) return filteredTools;
3585
- const toolsToAppend = [createGatewayExecProjection(createProjection, execTool, {
3586
- processAliasAvailable,
3587
- ...input.sessionPermissionPolicy?.mode === "guarded" ? { ask: "always" } : {}
3588
- })];
3589
- if (processAliasAvailable && processTool) toolsToAppend.push(createGatewayProcessProjection(createProjection, processTool));
3590
- return [...filteredTools, ...toolsToAppend];
3591
- }
3592
- function shouldEnableCodexAppServerNativeToolSurface(params, sandbox, options = {}) {
3593
- if (isCodexResponsesOAuthRun(params) || params.pluginHarnessToolPolicyRestricted === true || isCodexMemoryFlushRun(params) || params.disableTools) return false;
3594
- if (!resolveCodexNativeExecutionPolicyForRun(params, {
3595
- agentId: options.agentId,
3596
- runtimeSessionKey: options.runtimeSessionKey,
3597
- sandbox
3598
- }).nativeToolSurfaceAllowed) return false;
3599
- const toolsAllow = params.toolsAllow;
3600
- if (toolsAllow === void 0) return canCodexAppServerNativeToolSurfaceHonorSandbox(sandbox, options);
3601
- return hasWildcardCodexToolsAllow(toolsAllow) && canCodexAppServerNativeToolSurfaceHonorSandbox(sandbox, options);
3602
- }
3603
- function resolveCodexNativeExecutionPolicyForRun(params, options = {}) {
3604
- return resolveCodexNativeExecutionPolicy({
3605
- config: params.config,
3606
- sessionKey: options.runtimeSessionKey?.trim() || params.sandboxSessionKey?.trim() || params.sessionKey?.trim() || params.sessionId,
3607
- sessionId: params.sessionId,
3608
- agentId: options.agentId,
3609
- execOverrides: params.execOverrides,
3610
- sandboxAvailable: options.sandbox === null ? false : options.sandbox?.enabled,
3611
- readRuntimeSessionEntry: true
3612
- });
3613
- }
3614
- function canCodexAppServerNativeToolSurfaceHonorSandbox(sandbox, options = {}) {
3615
- if (!sandbox?.enabled) return true;
3616
- if (options.sandboxExecServerEnabled === true && (sandbox.backend || isCodexRemoteExecPlacementSandbox(sandbox)) && canSandboxToolPolicyExposeCodexNativeToolSurface(sandbox)) return true;
3617
- return false;
3618
- }
3619
- function canSandboxToolPolicyExposeCodexNativeToolSurface(sandbox) {
3620
- return CODEX_NATIVE_TOOL_REQUIREMENTS.every((toolName) => isToolAllowed(sandbox.tools, toolName));
3621
- }
3622
- function isCodexMemoryFlushRun(params) {
3623
- return params?.trigger === "memory" && Boolean(params.memoryFlushWritePath?.trim());
3624
- }
3625
- function filterCodexMemoryFlushDynamicTools(tools) {
3626
- return tools.filter((tool) => CODEX_MEMORY_FLUSH_DYNAMIC_TOOL_ALLOW.has(normalizeCodexDynamicToolName(tool.name)));
3627
- }
3628
- /** Requires a Codex sandbox environment only when native tools must run inside OpenClaw sandboxing. */
3629
- function shouldRequireCodexSandboxExecServerEnvironment(params) {
3630
- return Boolean(isCodexRemoteExecPlacementSandbox(params.sandbox) || params.sandbox?.enabled && params.nativeToolSurfaceEnabled && params.sandboxExecServerEnabled);
3631
- }
3632
- function resolveCodexSandboxEnvironmentSelection(environment, nativeToolSurfaceEnabled) {
3633
- return nativeToolSurfaceEnabled ? environment ? [environment] : void 0 : [];
3634
- }
3635
- function resolveCodexAppServerExecutionCwd(params) {
3636
- return mapCodexAppServerRemoteWorkspacePath({
3637
- value: params.environment && params.nativeToolSurfaceEnabled ? params.environment.cwd : params.effectiveCwd,
3638
- localWorkspaceRoot: params.localWorkspaceRoot,
3639
- remoteWorkspaceRoot: params.remoteWorkspaceRoot
3640
- });
3641
- }
3642
- function resolveCodexExternalSandboxPolicyForOpenClawSandbox(sandbox) {
3643
- return {
3644
- type: "externalSandbox",
3645
- networkAccess: codexNetworkAccessForOpenClawSandbox(sandbox) ? "enabled" : "restricted"
3646
- };
3647
- }
3648
- function usesDockerNetworkConfig(sandbox) {
3649
- const backendId = sandbox?.backendId.trim().toLowerCase();
3650
- return backendId === "docker" || backendId === "podman";
3651
- }
3652
- function codexNetworkAccessForOpenClawSandbox(sandbox) {
3653
- if (!usesDockerNetworkConfig(sandbox)) return true;
3654
- const network = sandbox?.docker?.network?.trim().toLowerCase();
3655
- return Boolean(network && network !== "none");
3656
- }
3657
- function disableCodexPluginThreadConfig(pluginConfig) {
3658
- const config = readCodexPluginConfig(pluginConfig);
3659
- return {
3660
- ...config,
3661
- codexPlugins: {
3662
- ...config.codexPlugins,
3663
- enabled: false
3664
- }
3665
- };
3666
- }
3667
- /** Adds sandbox_exec/process aliases when native Code Mode cannot directly honor the sandbox. */
3668
- function addSandboxShellDynamicToolsIfAvailable(filteredTools, allTools, input, executionPolicy) {
3669
- if (isCodexMemoryFlushRun(input.params) || !executionPolicy.nativeToolSurfaceAllowed || !input.sandbox?.enabled || !input.sandbox.backendId.trim() || input.nativeToolSurfaceEnabled !== false || isCodexDynamicToolExcluded(input.pluginConfig, [
3670
- "exec",
3671
- "sandbox_exec",
3672
- "process",
3673
- "sandbox_process"
3674
- ])) return filteredTools;
3675
- const execTool = allTools.find((tool) => normalizeCodexDynamicToolName(tool.name) === "exec");
3676
- const processTool = allTools.find((tool) => normalizeCodexDynamicToolName(tool.name) === "process");
3677
- if (!execTool) return filteredTools;
3678
- const sandboxTools = [...filteredTools, createSandboxExecProjection(execTool)];
3679
- return processTool ? [...sandboxTools, createSandboxProcessProjection(processTool)] : sandboxTools;
3680
- }
3681
- async function addNodeShellDynamicToolsIfNeeded(filteredTools, allTools, input, nodePolicy) {
3682
- if (isCodexMemoryFlushRun(input.params)) return filteredTools;
3683
- const nodeExecIsDefault = nodePolicy.effectiveExecHost === "node";
3684
- const nodeExecAvailableFromAuto = nodePolicy.requestedExecHost === "auto" && nodePolicy.effectiveExecHost === "gateway";
3685
- if (!nodeExecIsDefault && !nodeExecAvailableFromAuto) return filteredTools;
3686
- const execTool = allTools.find((tool) => normalizeCodexDynamicToolName(tool.name) === "exec");
3687
- if (!execTool || isCodexDynamicToolExcluded(input.pluginConfig, ["exec", "node_exec"]) || filteredTools.some((tool) => normalizeCodexDynamicToolName(tool.name) === "node_exec")) return filteredTools;
3688
- const nodeExec = await createNodeExecAliasDynamicTool(execTool, nodePolicy.node, input.runAbortController.signal, input.nodeExecAvailability);
3689
- return nodeExec ? [...filteredTools, nodeExec] : filteredTools;
3690
- }
3691
- function shouldKeepOpenClawShellDynamicTools(input, nodePolicy) {
3692
- return !isCodexMemoryFlushRun(input.params) && input.nativeToolSurfaceEnabled === false && input.sandbox?.enabled !== true && nodePolicy.effectiveExecHost !== "node";
3693
- }
3694
- /** Keeps replacement shell tools direct even when model metadata mandates Codex Code Mode. */
3695
- function placeDisabledNativeShellToolsInDirectNamespace(tools, nativeToolSurfaceEnabled) {
3696
- if (nativeToolSurfaceEnabled !== false) return tools;
3697
- for (const tool of tools) if (CODEX_DISABLED_NATIVE_SHELL_DYNAMIC_TOOLS.has(normalizeCodexDynamicToolName(tool.name))) tool.catalogMode = "direct-only";
3698
- return tools;
3699
- }
3700
- /** Applies a normalized tool allowlist while preserving shell aliases for exec/process. */
3701
- function filterCodexDynamicToolsForAllowlist(tools, toolsAllow) {
3702
- return applyEmbeddedAttemptToolsAllow(tools, toolsAllow, {
3703
- toolMeta: getPluginToolMeta,
3704
- toolAliases: (tool) => {
3705
- const normalized = normalizeCodexDynamicToolName(tool.name);
3706
- return normalized === "sandbox_exec" || normalized === "gateway_exec" || normalized === "node_exec" ? ["exec"] : normalized === "sandbox_process" || normalized === "gateway_process" ? ["exec", "process"] : [];
3707
- }
3708
- });
3709
- }
3710
- function hasWildcardCodexToolsAllow(toolsAllow) {
3711
- return toolsAllow.some((name) => normalizeCodexDynamicToolName(name) === "*");
3712
- }
3713
- function shouldForceMessageTool(params) {
3714
- return params.disableMessageTool !== true && params.sourceReplyDeliveryMode === "message_tool_only";
3096
+ await session.handleRequest(parseRequest(codexWebSocketDataToBuffer(data).toString("utf8")));
3715
3097
  }
3716
3098
  //#endregion
3717
3099
  //#region extensions/codex/src/app-server/native-command-approval.ts
@@ -3796,12 +3178,17 @@ async function handleCodexAppServerApprovalRequest(params) {
3796
3178
  method: params.method,
3797
3179
  requestParams
3798
3180
  });
3799
- const emitEvent = (data) => emitApprovalEvent(params.paramsForRun, {
3800
- kind: context.kind,
3801
- title: context.title,
3802
- ...context.eventDetails,
3803
- ...data
3804
- });
3181
+ const emitEvent = (data) => {
3182
+ params.paramsForRun.onAgentEvent?.({
3183
+ stream: "approval",
3184
+ data: {
3185
+ kind: context.kind,
3186
+ title: context.title,
3187
+ ...context.eventDetails,
3188
+ ...data
3189
+ }
3190
+ });
3191
+ };
3805
3192
  if (params.signal?.aborted) {
3806
3193
  if (params.signal.reason instanceof CodexServerRequestResolvedError) return;
3807
3194
  recordNativeToolFailureDisposition(params, context, "cancelled");
@@ -4138,8 +3525,8 @@ function readNativeRelayPreToolUseDecision(response) {
4138
3525
  };
4139
3526
  const stdout = response.stdout?.trim();
4140
3527
  if (!stdout) return { blocked: false };
4141
- const parsed = parseRelayJsonResponse(stdout);
4142
- const output = isJsonObject(parsed?.hookSpecificOutput) ? parsed.hookSpecificOutput : void 0;
3528
+ const parsed = safeParseJson(stdout);
3529
+ const output = isJsonObject(parsed) && isJsonObject(parsed.hookSpecificOutput) ? parsed.hookSpecificOutput : void 0;
4143
3530
  if (output?.permissionDecision === "deny") return {
4144
3531
  blocked: true,
4145
3532
  reason: readStringField(output, "permissionDecisionReason") || "OpenClaw native hook policy denied Codex app-server approval.",
@@ -4151,14 +3538,6 @@ function readNativeRelayPreToolUseDecision(response) {
4151
3538
  failureDisposition: "failed"
4152
3539
  };
4153
3540
  }
4154
- function parseRelayJsonResponse(text) {
4155
- try {
4156
- const parsed = JSON.parse(text);
4157
- return isJsonObject(parsed) ? parsed : void 0;
4158
- } catch {
4159
- return;
4160
- }
4161
- }
4162
3541
  function sanitizeRelayDecisionReason(value) {
4163
3542
  return sanitizeApprovalPreview(value ? {
4164
3543
  value,
@@ -4378,12 +3757,6 @@ function approvalResolutionMessage(outcome) {
4378
3757
  function approvalEventScope(method, outcome) {
4379
3758
  return method === "item/permissions/requestApproval" ? { scope: outcome === "approved-session" ? "session" : "turn" } : {};
4380
3759
  }
4381
- function emitApprovalEvent(params, data) {
4382
- params.onAgentEvent?.({
4383
- stream: "approval",
4384
- data: { ...data }
4385
- });
4386
- }
4387
3760
  function readPolicyCommand(record) {
4388
3761
  const command = record?.command;
4389
3762
  if (typeof command === "string") return command;
@@ -4474,9 +3847,6 @@ function joinDescriptionLinesWithinLimit(lines, maxLength) {
4474
3847
  }
4475
3848
  //#endregion
4476
3849
  //#region extensions/codex/src/app-server/dynamic-tool-diagnostics.ts
4477
- /**
4478
- * Trusted diagnostics emitted around Codex dynamic tool execution lifecycle.
4479
- */
4480
3850
  function diagnosticToolIdentity(params) {
4481
3851
  return {
4482
3852
  agentId: params.agentId,
@@ -4487,14 +3857,12 @@ function diagnosticToolIdentity(params) {
4487
3857
  toolCallId: params.call.callId
4488
3858
  };
4489
3859
  }
4490
- /** Emits a start event for one Codex dynamic tool call. */
4491
3860
  function emitDynamicToolStartedDiagnostic(params) {
4492
3861
  emitTrustedDiagnosticEvent({
4493
3862
  type: "tool.execution.started",
4494
3863
  ...diagnosticToolIdentity(params)
4495
3864
  });
4496
3865
  }
4497
- /** Emits an error event for one Codex dynamic tool call. */
4498
3866
  function emitDynamicToolErrorDiagnostic(params) {
4499
3867
  emitTrustedDiagnosticEvent({
4500
3868
  type: "tool.execution.error",
@@ -5152,17 +4520,11 @@ function createCodexDynamicToolSpecs(params) {
5152
4520
  deferLoading: true
5153
4521
  });
5154
4522
  }
5155
- if (namespaceTools.length > 0) specs.push({
4523
+ for (const [name, tools] of [[CODEX_OPENCLAW_DYNAMIC_TOOL_NAMESPACE, namespaceTools], [CODEX_OPENCLAW_DIRECT_DYNAMIC_TOOL_NAMESPACE, directOnlyNamespaceTools]]) if (tools.length > 0) specs.push({
5156
4524
  type: "namespace",
5157
- name: CODEX_OPENCLAW_DYNAMIC_TOOL_NAMESPACE,
5158
- description: "",
5159
- tools: namespaceTools
5160
- });
5161
- if (directOnlyNamespaceTools.length > 0) specs.push({
5162
- type: "namespace",
5163
- name: CODEX_OPENCLAW_DIRECT_DYNAMIC_TOOL_NAMESPACE,
4525
+ name,
5164
4526
  description: "",
5165
- tools: directOnlyNamespaceTools
4527
+ tools
5166
4528
  });
5167
4529
  return specs;
5168
4530
  }
@@ -5298,6 +4660,97 @@ function finalizeCodexToolAvailability(entries) {
5298
4660
  };
5299
4661
  }
5300
4662
  //#endregion
4663
+ //#region extensions/codex/src/app-server/dynamic-tool-content.ts
4664
+ function enforceWholeSkillResult(toolName, result, maxChars) {
4665
+ if (toolName !== "skills_read" || isToolResultError(result)) return result;
4666
+ return sanitizeToolTextRuns(result.content).reduce((total, item) => total + (item.type === "text" ? estimateToolResultTextChars(item.text) : 0), 0) <= maxChars ? result : failedToolResult(`This Codex turn cannot deliver the whole skill within its ${maxChars}-character weighted output budget. No instructions were returned; use a harness with a larger instruction budget.`);
4667
+ }
4668
+ function sanitizeToolTextRuns(rawContent) {
4669
+ const content = [];
4670
+ for (let index = 0; index < rawContent.length;) {
4671
+ const item = rawContent[index];
4672
+ if (item.type !== "text") {
4673
+ content.push(item);
4674
+ index += 1;
4675
+ continue;
4676
+ }
4677
+ const textRun = [];
4678
+ while (index < rawContent.length) {
4679
+ const next = rawContent[index];
4680
+ if (next.type !== "text") break;
4681
+ textRun.push(next);
4682
+ index += 1;
4683
+ }
4684
+ const sanitizedText = sanitizeToolResult(textRun.map((entry) => entry.text).join(""));
4685
+ let offset = 0;
4686
+ content.push(...textRun.map((entry, runIndex) => {
4687
+ const targetEnd = runIndex === textRun.length - 1 ? sanitizedText.length : Math.min(sanitizedText.length, offset + entry.text.length);
4688
+ const text = sliceUtf16Safe(sanitizedText, offset, targetEnd);
4689
+ const sanitized = Object.assign({}, entry, { text });
4690
+ offset += text.length;
4691
+ return sanitized;
4692
+ }));
4693
+ }
4694
+ return content;
4695
+ }
4696
+ function convertToolContents(rawContent, maxChars) {
4697
+ const content = sanitizeToolTextRuns(rawContent);
4698
+ const totalTextChars = content.reduce((total, item) => total + (item.type === "text" ? item.text.length : 0), 0);
4699
+ if (content.reduce((total, item) => total + (item.type === "text" ? estimateToolResultTextChars(item.text) : 0), 0) <= maxChars) return content.map(convertToolContent);
4700
+ const noticeText = `...(OpenClaw truncated dynamic tool result: original ${totalTextChars} chars, weighted budget ${maxChars}; rerun with narrower args.)`;
4701
+ const notice = `\n${noticeText}`;
4702
+ const noticeChars = estimateToolResultTextChars(notice);
4703
+ let remainingTextBudget = Math.max(0, maxChars - noticeChars);
4704
+ let appendedNotice = false;
4705
+ const output = [];
4706
+ for (const item of content) {
4707
+ if (item.type !== "text") {
4708
+ output.push(convertToolContent(item));
4709
+ continue;
4710
+ }
4711
+ if (appendedNotice) continue;
4712
+ if (noticeChars >= maxChars) {
4713
+ output.push({
4714
+ type: "inputText",
4715
+ text: sliceToolResultTextToBudget(noticeText, maxChars)
4716
+ });
4717
+ appendedNotice = true;
4718
+ continue;
4719
+ }
4720
+ const text = sliceToolResultTextToBudget(item.text, remainingTextBudget);
4721
+ remainingTextBudget -= estimateToolResultTextChars(text);
4722
+ if (remainingTextBudget <= 0 || text.length < item.text.length) {
4723
+ output.push({
4724
+ type: "inputText",
4725
+ text: `${text.trimEnd()}${notice}`
4726
+ });
4727
+ appendedNotice = true;
4728
+ } else if (text.length > 0) output.push({
4729
+ type: "inputText",
4730
+ text
4731
+ });
4732
+ }
4733
+ if (!appendedNotice) output.push({
4734
+ type: "inputText",
4735
+ text: sliceToolResultTextToBudget(noticeText, maxChars)
4736
+ });
4737
+ return output;
4738
+ }
4739
+ function convertToolContent(content) {
4740
+ if (content.type === "text") return {
4741
+ type: "inputText",
4742
+ text: content.text
4743
+ };
4744
+ const imageUrl = sanitizeInlineImageDataUrl(`data:${content.mimeType};base64,${content.data}`);
4745
+ return imageUrl ? {
4746
+ type: "inputImage",
4747
+ imageUrl
4748
+ } : {
4749
+ type: "inputText",
4750
+ text: invalidInlineImageText("codex dynamic tool")
4751
+ };
4752
+ }
4753
+ //#endregion
5301
4754
  //#region extensions/codex/src/app-server/dynamic-tool-executable-projection.ts
5302
4755
  function projectCodexExecutableDynamicToolSurface(tools, hookContext) {
5303
4756
  const { tools: projectedTools, quarantinedTools } = projectCodexDynamicTools(tools);
@@ -5345,7 +4798,7 @@ function assertCodexDynamicToolInputMatchesSchema(params) {
5345
4798
  throw new Error(`Invalid arguments for tool "${params.toolName}": ${details}${omittedSuffix}.`);
5346
4799
  }
5347
4800
  function applyCurrentMessageProvider(toolName, args, currentProvider) {
5348
- const hasProvider = typeof args.provider === "string" && args.provider.trim().length > 0 ? true : typeof args.channel === "string" && args.channel.trim().length > 0;
4801
+ const hasProvider = typeof args.provider === "string" && args.provider.trim().length > 0 || typeof args.channel === "string" && args.channel.trim().length > 0;
5349
4802
  const provider = currentProvider?.trim();
5350
4803
  if (toolName !== "message" || hasProvider || !provider) return args;
5351
4804
  return {
@@ -5597,7 +5050,7 @@ function createCodexDynamicToolBridge(params) {
5597
5050
  isError: rawIsErrorForPresentation,
5598
5051
  result: event.result
5599
5052
  });
5600
- const result = await legacyExtensionRunner.applyToolResultExtensions({
5053
+ const extendedResult = await legacyExtensionRunner.applyToolResultExtensions({
5601
5054
  threadId: call.threadId,
5602
5055
  turnId: call.turnId,
5603
5056
  toolCallId: call.callId,
@@ -5605,6 +5058,7 @@ function createCodexDynamicToolBridge(params) {
5605
5058
  args: structuredClone(executedArgsForPresentation),
5606
5059
  result: middlewareResult
5607
5060
  });
5061
+ const result = enforceWholeSkillResult(toolName, extendedResult, toolResultMaxChars);
5608
5062
  presentationIsError = rawIsErrorForPresentation || isToolResultError(result);
5609
5063
  const acceptedSessionSpawn = toolName === "sessions_spawn" && !rawIsErrorForPresentation ? normalizeAcceptedSessionSpawnResult(telemetryRawResultForPresentation) : null;
5610
5064
  if (acceptedSessionSpawn) telemetry.acceptedSessionSpawns.push(acceptedSessionSpawn);
@@ -5617,11 +5071,7 @@ function createCodexDynamicToolBridge(params) {
5617
5071
  runAgentHarnessAfterToolCallHook({
5618
5072
  toolName,
5619
5073
  toolCallId: call.callId,
5620
- runId: toolResultHookContext.runId,
5621
- agentId: toolResultHookContext.agentId,
5622
- sessionId: toolResultHookContext.sessionId,
5623
- sessionKey: toolResultHookContext.sessionKey,
5624
- channelId: toolResultHookContext.channelId,
5074
+ ...toolResultHookContext,
5625
5075
  startArgs: executedArgs,
5626
5076
  result,
5627
5077
  startedAt
@@ -5645,7 +5095,7 @@ function createCodexDynamicToolBridge(params) {
5645
5095
  const autoDeliveryTtsMediaUrls = getCoreTtsToolResultMediaUrls(rawResult);
5646
5096
  recordAgentHarnessToolResultTelemetry({
5647
5097
  extractSourceReplyPayload: extractMessagingToolSourceReplyPayload,
5648
- collectMessagingMediaUrls: collectCodexMessageMediaUrls,
5098
+ collectMessagingMediaUrls: collectAgentHarnessMessagingMediaUrls,
5649
5099
  resolveMessagingMediaSourceUrls: (mediaUrls) => resolveCodexMediaSourceUrls(mediaUrls, preparedMessageMedia?.sourcePathsByStagedPath),
5650
5100
  toolName,
5651
5101
  args: executedArgs,
@@ -5688,11 +5138,7 @@ function createCodexDynamicToolBridge(params) {
5688
5138
  runAgentHarnessAfterToolCallHook({
5689
5139
  toolName,
5690
5140
  toolCallId: call.callId,
5691
- runId: toolResultHookContext.runId,
5692
- agentId: toolResultHookContext.agentId,
5693
- sessionId: toolResultHookContext.sessionId,
5694
- sessionKey: toolResultHookContext.sessionKey,
5695
- channelId: toolResultHookContext.channelId,
5141
+ ...toolResultHookContext,
5696
5142
  startArgs: executedArgs,
5697
5143
  error: errorMessage,
5698
5144
  startedAt
@@ -5783,91 +5229,5 @@ function isAsyncStartedToolResult(result) {
5783
5229
  const details = result.details;
5784
5230
  return isRecord(details) && details.async === true && details.status === "started";
5785
5231
  }
5786
- function sanitizeToolTextRuns(rawContent) {
5787
- const content = [];
5788
- for (let index = 0; index < rawContent.length;) {
5789
- const item = rawContent[index];
5790
- if (item.type !== "text") {
5791
- content.push(item);
5792
- index += 1;
5793
- continue;
5794
- }
5795
- const textRun = [];
5796
- while (index < rawContent.length) {
5797
- const next = rawContent[index];
5798
- if (next.type !== "text") break;
5799
- textRun.push(next);
5800
- index += 1;
5801
- }
5802
- const sanitizedText = sanitizeToolResult(textRun.map((entry) => entry.text).join(""));
5803
- let offset = 0;
5804
- content.push(...textRun.map((entry, runIndex) => {
5805
- const targetEnd = runIndex === textRun.length - 1 ? sanitizedText.length : Math.min(sanitizedText.length, offset + entry.text.length);
5806
- const text = sliceUtf16Safe(sanitizedText, offset, targetEnd);
5807
- const sanitized = Object.assign({}, entry, { text });
5808
- offset += text.length;
5809
- return sanitized;
5810
- }));
5811
- }
5812
- return content;
5813
- }
5814
- function convertToolContents(rawContent, maxChars) {
5815
- const content = sanitizeToolTextRuns(rawContent);
5816
- const totalTextChars = content.reduce((total, item) => total + (item.type === "text" ? item.text.length : 0), 0);
5817
- if (content.reduce((total, item) => total + (item.type === "text" ? estimateToolResultTextChars(item.text) : 0), 0) <= maxChars) return content.flatMap(convertToolContent);
5818
- const noticeText = `...(OpenClaw truncated dynamic tool result: original ${totalTextChars} chars, weighted budget ${maxChars}; rerun with narrower args.)`;
5819
- const notice = `\n${noticeText}`;
5820
- const noticeChars = estimateToolResultTextChars(notice);
5821
- let remainingTextBudget = Math.max(0, maxChars - noticeChars);
5822
- let appendedNotice = false;
5823
- const output = [];
5824
- for (const item of content) {
5825
- if (item.type !== "text") {
5826
- output.push(...convertToolContent(item));
5827
- continue;
5828
- }
5829
- if (appendedNotice) continue;
5830
- if (noticeChars >= maxChars) {
5831
- output.push({
5832
- type: "inputText",
5833
- text: sliceToolResultTextToBudget(noticeText, maxChars)
5834
- });
5835
- appendedNotice = true;
5836
- continue;
5837
- }
5838
- const text = sliceToolResultTextToBudget(item.text, remainingTextBudget);
5839
- remainingTextBudget -= estimateToolResultTextChars(text);
5840
- if (remainingTextBudget <= 0 || text.length < item.text.length) {
5841
- output.push({
5842
- type: "inputText",
5843
- text: `${text.trimEnd()}${notice}`
5844
- });
5845
- appendedNotice = true;
5846
- } else if (text.length > 0) output.push({
5847
- type: "inputText",
5848
- text
5849
- });
5850
- }
5851
- if (!appendedNotice) output.push({
5852
- type: "inputText",
5853
- text: sliceToolResultTextToBudget(noticeText, maxChars)
5854
- });
5855
- return output;
5856
- }
5857
- function convertToolContent(content) {
5858
- if (content.type === "text") return [{
5859
- type: "inputText",
5860
- text: content.text
5861
- }];
5862
- const imageUrl = sanitizeInlineImageDataUrl(`data:${content.mimeType};base64,${content.data}`);
5863
- if (!imageUrl) return [{
5864
- type: "inputText",
5865
- text: invalidInlineImageText("codex dynamic tool")
5866
- }];
5867
- return [{
5868
- type: "inputImage",
5869
- imageUrl
5870
- }];
5871
- }
5872
5232
  //#endregion
5873
- export { readCodexRetainedBackgroundCommands as C, CodexNativeToolLifecycleProjector as E, hasCodexNativeBackgroundProcesses as S, mapCodexAppServerRemoteWorkspacePath as T, shouldWarnCodexDynamicToolBuildStageSummary as _, emitDynamicToolStartedDiagnostic as a, createCodexNativePreToolUseFailureBuffer as b, buildDynamicTools as c, resolveCodexAppServerHookChannelId as d, resolveCodexExternalSandboxPolicyForOpenClawSandbox as f, shouldRequireCodexSandboxExecServerEnvironment as g, shouldEnableCodexAppServerNativeToolSurface as h, emitDynamicToolErrorDiagnostic as i, disableCodexPluginThreadConfig as l, resolveCodexSandboxEnvironmentSelection as m, projectCodexExecutableDynamicTools as n, emitDynamicToolTerminalDiagnostic as o, resolveCodexMessageToolProvider as p, routeCodexAppServerElicitationRequest as r, handleCodexAppServerApprovalRequest as s, createCodexDynamicToolBridge as t, resolveCodexAppServerExecutionCwd as u, ensureCodexSandboxExecServerEnvironment as v, readBoundedCodexRemoteWorkspaceFile as w, CodexNativeProcessAuthority as x, releaseCodexSandboxExecServerEnvironment as y };
5233
+ export { emitDynamicToolStartedDiagnostic as a, ensureCodexSandboxExecServerEnvironment as c, CodexNativeProcessAuthority as d, readCodexRetainedBackgroundCommands as f, emitDynamicToolErrorDiagnostic as i, releaseCodexSandboxExecServerEnvironment as l, CodexNativeToolLifecycleProjector as m, projectCodexExecutableDynamicTools as n, emitDynamicToolTerminalDiagnostic as o, createCodexRemoteWorkspaceFileReader as p, routeCodexAppServerElicitationRequest as r, handleCodexAppServerApprovalRequest as s, createCodexDynamicToolBridge as t, createCodexNativePreToolUseFailureBuffer as u };