@openclaw/codex 2026.10.2 → 2026.10.5-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. package/dist/.setup/{account-usage-runtime-DPXsyONK.mjs → account-usage-runtime-B6S1BQU7.mjs} +8 -7
  2. package/dist/.setup/{app-server-policy-Bg4FZw1f.mjs → app-server-policy-D_zv8J7V.mjs} +3 -4
  3. package/dist/.setup/{apply-CQ3brq3z.mjs → apply-Cc1DfWPz.mjs} +40 -51
  4. package/dist/.setup/{attempt-client-cleanup-DPUGAWP2.mjs → attempt-client-cleanup-CxX4cTSi.mjs} +6 -6
  5. package/dist/.setup/attempt-terminal-jO5IMj9K.mjs +2 -0
  6. package/dist/.setup/{attempt-workspace-context-GllQy8mw.mjs → attempt-workspace-context-CcwP3DA3.mjs} +21 -18
  7. package/dist/.setup/{auth-binding-BoMwpuPN.mjs → auth-binding-BaxlhaNx.mjs} +2 -2
  8. package/dist/.setup/{auth-cache-key-BE1HXsNo.mjs → auth-cache-key-tENCQOub.mjs} +30 -41
  9. package/dist/.setup/{binding-connection-C-08ez1w.mjs → binding-connection-B7HAAZSI.mjs} +2 -2
  10. package/dist/.setup/{binding-connection.runtime-Dn2p-fdy.mjs → binding-connection.runtime-DAXn7iFl.mjs} +6 -5
  11. package/dist/.setup/{bounded-turn-9YflG60n.mjs → bounded-turn-DxtRqV8t.mjs} +21 -17
  12. package/dist/.setup/{bounded-turn-isolation-DklXNk3k.mjs → bounded-turn-isolation-BfDAo-qZ.mjs} +4 -4
  13. package/dist/.setup/{build-state-LS-A65iX.mjs → build-state-CMYRQ_We.mjs} +1 -1
  14. package/dist/.setup/{capabilities-kQntafj_.mjs → capabilities-DbOzOglY.mjs} +1 -1
  15. package/dist/.setup/{client-catalog-response-BprQziLV.mjs → client-catalog-response-B7oqHQGO.mjs} +25 -32
  16. package/dist/.setup/{client-ChJtGEdJ.mjs → client-zrCKOu_E.mjs} +198 -247
  17. package/dist/.setup/{command-dispatch-BoC9hvFs.mjs → command-dispatch-ImiHvcyW.mjs} +3 -4
  18. package/dist/.setup/{command-formatters-DV3DHhdr.mjs → command-formatters-xW9KpoSZ.mjs} +16 -26
  19. package/dist/.setup/{command-handlers-BVX2quUD.mjs → command-handlers-B8CT4ngS.mjs} +270 -360
  20. package/dist/.setup/{command-rpc-M4gYsRiV.mjs → command-rpc-HtQjCQBg.mjs} +19 -18
  21. package/dist/.setup/{compact-D3JNLG_b.mjs → compact-Do9HPeDr.mjs} +41 -61
  22. package/dist/.setup/{computer-use-CF0jsDi1.mjs → computer-use-CeF5GuCX.mjs} +109 -147
  23. package/dist/.setup/{config-0Gxk3_eq.mjs → config-C1YVVLEA.mjs} +32 -59
  24. package/dist/.setup/config-contracts.shared-D85SGEuq.mjs +4 -0
  25. package/dist/.setup/{config-options-HG_Rr3W_.mjs → config-options-DDzeNQ8m.mjs} +52 -90
  26. package/dist/.setup/{config-parsing-BQq-CHTF.mjs → config-parsing-DsWSCPHO.mjs} +19 -55
  27. package/dist/.setup/{config-runtime-cUYrqu_a.mjs → config-runtime-DWzK-k0n.mjs} +2 -2
  28. package/dist/.setup/{config-security-KAPScztc.mjs → config-security-clxAZYWX.mjs} +35 -39
  29. package/dist/.setup/config-utils-DN_YT7dE.mjs +47 -0
  30. package/dist/.setup/{context-engine-projection-CsgYSQhW.mjs → context-engine-projection-ps-yn_ci.mjs} +10 -22
  31. package/dist/.setup/{conversation-binding-7kceEUf0.mjs → conversation-binding-D78aEdkE.mjs} +85 -119
  32. package/dist/.setup/{conversation-binding-data-DJ4ix-W5.mjs → conversation-binding-data-UgLuTSQT.mjs} +9 -8
  33. package/dist/.setup/{conversation-control-BpJpPo0t.mjs → conversation-control-GXM3unE4.mjs} +7 -10
  34. package/dist/.setup/{cyber-failover-Bb1J6hS1.mjs → cyber-failover-D4dgNfFf.mjs} +2 -5
  35. package/dist/.setup/{cyber-failover-notice-XR03ef31.mjs → cyber-failover-notice-ljgGGL0s.mjs} +1 -1
  36. package/dist/.setup/{doctor-start-options-DPW9JxIE.mjs → doctor-start-options-JjTAl-q_.mjs} +5 -5
  37. package/dist/.setup/{dynamic-tool-build-BCi00feJ.mjs → dynamic-tool-build-BMiiFROa.mjs} +57 -69
  38. package/dist/.setup/{dynamic-tools-DUv6Sr6h.mjs → dynamic-tools-DPPHrGKB.mjs} +680 -709
  39. package/dist/.setup/{effective-mcp-catalog-CIdbHp1t.mjs → effective-mcp-catalog-x3JVEcJp.mjs} +11 -20
  40. package/dist/.setup/{elicitation-input-r9axtppm.mjs → elicitation-input-DXG_qaXr.mjs} +14 -20
  41. package/dist/.setup/{ephemeral-turn-U4th15a6.mjs → ephemeral-turn-Dk0wWoqi.mjs} +3 -3
  42. package/dist/.setup/{event-projector-assistant-message-BwG5TUYW.mjs → event-projector-assistant-message-CLMKN4x-.mjs} +2 -2
  43. package/dist/.setup/{event-projector-usage-03R0I2dM.mjs → event-projector-usage-BpKfdoTm.mjs} +20 -33
  44. package/dist/.setup/{event-projector-values-DTqZHizf.mjs → event-projector-values-CLvG1Hil.mjs} +4 -5
  45. package/dist/.setup/history-rejection-B4nOXNXF.mjs +13 -0
  46. package/dist/.setup/{inference-context-D-9gWlTR.mjs → inference-context-DNlGwzwy.mjs} +10 -11
  47. package/dist/.setup/{inference-dispatch-B5UKEUyC.mjs → inference-dispatch-CO6tTs4q.mjs} +5 -4
  48. package/dist/.setup/{inference-metadata-CgIf7sOx.mjs → inference-metadata-DCvcG_N_.mjs} +36 -41
  49. package/dist/.setup/{inference-proxy-DUO5E2QQ.mjs → inference-proxy-BDWV0djM.mjs} +10 -14
  50. package/dist/.setup/{isolated-completion-C6QKyyDS.mjs → isolated-completion-z0ii1a_V.mjs} +8 -8
  51. package/dist/.setup/local-runtime-attribution-CZz2DJ4q.mjs +15 -0
  52. package/dist/.setup/{managed-binary-C1VFoVPf.mjs → managed-binary-BtIjV7yN.mjs} +16 -36
  53. package/dist/.setup/{mcp-app-session-preparation-JFCtSkRp.mjs → mcp-app-session-preparation-GTx-bRGN.mjs} +24 -25
  54. package/dist/.setup/{mcp-tool-metadata-j10HhfTC.mjs → mcp-tool-metadata-DW41snf3.mjs} +1 -1
  55. package/dist/.setup/{model-catalog-DD-evckc.mjs → model-catalog-VUdFUqnH.mjs} +8 -8
  56. package/dist/.setup/{models-DaW-7tld.mjs → models-Dph0RqpR.mjs} +6 -10
  57. package/dist/.setup/{native-auth-Cjb9y7IZ.mjs → native-auth-esN5MdIv.mjs} +5 -5
  58. package/dist/.setup/{native-execution-policy-ClzpdG3D.mjs → native-execution-policy-MXEe7PB3.mjs} +11 -28
  59. package/dist/.setup/native-hook-relay-CSZpcjwq.mjs +561 -0
  60. package/dist/.setup/{native-mcp-app-ChpyWmL-.mjs → native-mcp-app-CDrrBaTE.mjs} +6 -6
  61. package/dist/.setup/native-skill-isolation-BAatEJZb.mjs +391 -0
  62. package/dist/.setup/{native-subagent-monitor-wh_-K3Vo.mjs → native-subagent-monitor-D5O_o07p.mjs} +505 -639
  63. package/dist/.setup/{native-subagent-pending-assignments-BDqhOdJp.mjs → native-subagent-pending-assignments-DmVhedNs.mjs} +11 -23
  64. package/dist/.setup/{native-task-assignments-C6KVqiN1.mjs → native-task-assignments-DimsQ9Qa.mjs} +73 -27
  65. package/dist/.setup/{node-cli-sessions-B5oNDkUS.mjs → node-cli-sessions-CzKg2nGq.mjs} +18 -26
  66. package/dist/.setup/{node-exec-server.runtime-0xSEjKYt.mjs → node-exec-server.runtime-BWkULhBM.mjs} +5 -8
  67. package/dist/.setup/{plan-CUHSuL6_.mjs → plan-QNW5zpFp.mjs} +40 -50
  68. package/dist/.setup/{plugin-activation-BcyBv8PG.mjs → plugin-activation-D7WkJMvU.mjs} +4 -5
  69. package/dist/.setup/{plugin-app-cache-key-BW8rd98k.mjs → plugin-app-cache-key-Bg9DbDI6.mjs} +18 -23
  70. package/dist/.setup/{plugin-approval-roundtrip-bPQbG8BI.mjs → plugin-approval-roundtrip-DOQ3Tibe.mjs} +4 -6
  71. package/dist/.setup/{plugin-inventory-Bf0_piTw.mjs → plugin-inventory-CYgdo14P.mjs} +28 -43
  72. package/dist/.setup/{plugin-marketplace-discovery-SQPhSuic.mjs → plugin-marketplace-discovery-BblHM3DU.mjs} +7 -10
  73. package/dist/.setup/{plugin-metadata-cache-DWnB7VMj.mjs → plugin-metadata-cache-Bi8TAPwX.mjs} +5 -10
  74. package/dist/.setup/project-doc-thread-config-BVcvnps8.mjs +490 -0
  75. package/dist/.setup/{provider-Ct6-1lsF.mjs → provider-BG5nXBnY.mjs} +4 -4
  76. package/dist/.setup/{provider-capabilities-DhkeeHJd.mjs → provider-capabilities-DtJKxDf6.mjs} +1 -1
  77. package/dist/.setup/{rate-limits-CMPy24F5.mjs → rate-limits-CI8pTPqL.mjs} +15 -32
  78. package/dist/.setup/reasoning-effort-CS9kKWB9.mjs +37 -0
  79. package/dist/.setup/{request-CZkKkN6c.mjs → request-6piO0U_P.mjs} +28 -48
  80. package/dist/.setup/{rpc-error-hmWM21RB.mjs → rpc-error-C98SHchT.mjs} +3 -6
  81. package/dist/.setup/{run-attempt-C6-678kR.mjs → run-attempt-DejV9vDW.mjs} +927 -860
  82. package/dist/.setup/{run-attempt-lifecycle-BuZgVbDA.mjs → run-attempt-lifecycle-KN4oh-7O.mjs} +13 -4
  83. package/dist/.setup/{runtime-artifact-CUTOOnKw.mjs → runtime-artifact-C13pR7tD.mjs} +18 -22
  84. package/dist/.setup/{runtime-artifact-connection-CADz3_BY.mjs → runtime-artifact-connection-jS5DeCok.mjs} +3 -3
  85. package/dist/.setup/{sandbox-guard-WqE8yPge.mjs → sandbox-guard-DIImwCy1.mjs} +4 -6
  86. package/dist/.setup/service-tier-normalization-BPgw2Wdt.mjs +9 -0
  87. package/dist/.setup/{session-binding-Ce7BqiPN.mjs → session-binding-JEHNMPsr.mjs} +13 -40
  88. package/dist/.setup/{session-binding-record-BZB8RgcF.mjs → session-binding-record-DU_0biMD.mjs} +4 -4
  89. package/dist/.setup/{session-binding-record-codec-z4ZpDn6E.mjs → session-binding-record-codec-BpH8u_G9.mjs} +16 -39
  90. package/dist/.setup/{session-binding-sidecars-BrdV95Fg.mjs → session-binding-sidecars-DD-enC8w.mjs} +49 -54
  91. package/dist/.setup/{session-catalog-adoption-CPIP4S_y.mjs → session-catalog-adoption-Ca3OYGYM.mjs} +23 -27
  92. package/dist/.setup/{session-catalog-archive-DcgwvSbF.mjs → session-catalog-archive-Bv6gV7x9.mjs} +6 -6
  93. package/dist/.setup/{session-catalog-events-Cj-b2FpC.mjs → session-catalog-events-BziNSfLx.mjs} +6 -5
  94. package/dist/.setup/{session-catalog-index-BnvC43eZ.mjs → session-catalog-index-BmaZFGEH.mjs} +111 -105
  95. package/dist/.setup/{session-catalog-index-order-nhyO0wdW.mjs → session-catalog-index-order-CTfoefow.mjs} +28 -5
  96. package/dist/.setup/{session-catalog-limits-DEU36Qlo.mjs → session-catalog-limits-BynIoOYm.mjs} +1 -1
  97. package/dist/.setup/{session-catalog-list-request-tXephOB4.mjs → session-catalog-list-request-D4MYNgDB.mjs} +11 -8
  98. package/dist/.setup/{session-catalog-native-projection-DCtsWKSF.mjs → session-catalog-native-projection-4CsufcT8.mjs} +5 -61
  99. package/dist/.setup/{session-catalog-node-adoption-7-WEQTB1.mjs → session-catalog-node-adoption-BdP9Zjqo.mjs} +2 -2
  100. package/dist/.setup/{session-catalog-node-continue-DLWBwAAO.mjs → session-catalog-node-continue-CNJibO4_.mjs} +27 -49
  101. package/dist/.setup/{session-catalog-node-lookup-Uufckwcm.mjs → session-catalog-node-lookup-BH_DBGa9.mjs} +3 -3
  102. package/dist/.setup/{session-catalog-parsing-B-qWJh2x.mjs → session-catalog-parsing-DkeoVn60.mjs} +9 -19
  103. package/dist/.setup/{session-catalog-projection-Cn0bLb-d.mjs → session-catalog-projection-CcIdJdsd.mjs} +8 -22
  104. package/dist/.setup/session-catalog-source-CdPqS9sa.mjs +58 -0
  105. package/dist/.setup/{session-cli-kH4vuGod.mjs → session-cli-GwU0izn-.mjs} +20 -41
  106. package/dist/.setup/{session-history-BogBHKLk.mjs → session-history-BO6i_pfk.mjs} +1 -1
  107. package/dist/.setup/{session-history-import-NWKPa4ZO.mjs → session-history-import-CaO8s6ta.mjs} +4 -4
  108. package/dist/.setup/{session-history-read-CNN8zwbD.mjs → session-history-read-BI_2jRED.mjs} +4 -15
  109. package/dist/.setup/{session-history.worker-Cq_4DYgN.mjs → session-history.worker-DJQfek5p.mjs} +147 -159
  110. package/dist/.setup/{session-initialization-D6dtFQkE.mjs → session-initialization-Bi_2DKhc.mjs} +3 -5
  111. package/dist/.setup/{session-permission-policy-BxIUJ0Zd.mjs → session-permission-policy-CD2MAWU8.mjs} +12 -20
  112. package/dist/.setup/{session-retirement-Bo81t4Fb.mjs → session-retirement-CcWVhLVr.mjs} +7 -7
  113. package/dist/.setup/{settled-turn-context-BZsMjkIO.mjs → settled-turn-context-BPL6D3RO.mjs} +1 -1
  114. package/dist/.setup/{settled-turn-finalizer-CFARFqNd.mjs → settled-turn-finalizer-BezKSo-Y.mjs} +12 -11
  115. package/dist/.setup/{shared-client-5NUq43f3.mjs → shared-client-BjiqpbC5.mjs} +164 -227
  116. package/dist/.setup/{side-question-oTlegAz3.mjs → side-question-YQ5FObkD.mjs} +116 -137
  117. package/dist/.setup/{source-1cabQi3x.mjs → source-Ce3XIIsU.mjs} +37 -56
  118. package/dist/.setup/thread-archive-guard-LKdwQKyr.mjs +56 -0
  119. package/dist/.setup/{thread-lifecycle--EPPTNTe.mjs → thread-lifecycle-run-BWy0LDLB.mjs} +338 -478
  120. package/dist/.setup/thread-model-selection-DcVebr8N.mjs +61 -0
  121. package/dist/.setup/{thread-ownership-T7T_iffm.mjs → thread-ownership-5X4197vk.mjs} +5 -5
  122. package/dist/.setup/{thread-ownership-queue-Dp24d7-F.mjs → thread-ownership-queue-CeyYScUC.mjs} +5 -6
  123. package/dist/.setup/{thread-policy-VtqLex1l.mjs → thread-policy-BEecBTJM.mjs} +4 -4
  124. package/dist/.setup/thread-requests-BgzJwJtS.mjs +745 -0
  125. package/dist/.setup/{thread-resume-buZujRcC.mjs → thread-resume-BXY_6o6Z.mjs} +5 -5
  126. package/dist/.setup/{timeout-CXOfNoaX.mjs → timeout-D0mEWSGG.mjs} +6 -12
  127. package/dist/.setup/{transcript-history-projection-B9a7HwUV.mjs → transcript-history-projection-DfKcoZCB.mjs} +3 -4
  128. package/dist/.setup/{transcript-mirror-BfLRARNL.mjs → transcript-mirror-Bee2o6jj.mjs} +68 -68
  129. package/dist/.setup/{transcript-mirror-attestation-YSegaktH.mjs → transcript-mirror-attestation-BzUXnrvv.mjs} +5 -2
  130. package/dist/.setup/{transport-stdio-a0HDa2Mj.mjs → transport-stdio-CRWTkKOn.mjs} +67 -77
  131. package/dist/.setup/{transport-websocket-zqJ0Cmtn.mjs → transport-websocket-DIyPfkHo.mjs} +8 -16
  132. package/dist/.setup/{turn-router-BOKSJmfw.mjs → turn-router-D8DLkZgH.mjs} +30 -31
  133. package/dist/.setup/upstream-prompt-provenance-Ccd9MFRJ.mjs +44 -0
  134. package/dist/.setup/{upstream-session-fork-C4sbIoZb.mjs → upstream-session-fork-DQZbaYMK.mjs} +50 -43
  135. package/dist/.setup/{usage-Cq21xTMZ.mjs → usage-DVR5mNJK.mjs} +4 -4
  136. package/dist/.setup/{usage-limit-error-CGJUoQu8.mjs → usage-limit-error-BEONfgt-.mjs} +12 -21
  137. package/dist/.setup/web-search-item-CvokaZOo.mjs +20 -0
  138. package/dist/.setup/{web-search-provider.runtime-DrVE7-Br.mjs → web-search-provider.runtime-CffHOpYY.mjs} +3 -3
  139. package/dist/.setup/{workspace-write-sandbox-probe-DmUHLrrl.mjs → workspace-write-sandbox-probe-BDWO2Qkh.mjs} +4 -4
  140. package/dist/api.js +15 -15
  141. package/dist/catalog-page.worker.js +1 -1
  142. package/dist/cli-metadata.js +1 -1
  143. package/dist/doctor-contract-api.js +5 -6
  144. package/dist/harness.js +32 -61
  145. package/dist/index.js +302 -416
  146. package/dist/media-understanding-provider.js +32 -43
  147. package/dist/migration-provider-api.js +1 -1
  148. package/dist/native-session-binding-api.js +1 -1
  149. package/dist/native-tool-policy.js +23 -1
  150. package/dist/provider-discovery.js +1 -1
  151. package/dist/session-history-worker-runtime.js +52 -31
  152. package/dist/session-history.worker.js +1 -1
  153. package/openclaw.plugin.json +20 -3
  154. package/package.json +7 -7
  155. package/dist/.setup/attempt-terminal-gZrxQ35N.mjs +0 -5
  156. package/dist/.setup/plugin-thread-config-deadline-C5i1S6RN.mjs +0 -124
  157. package/dist/.setup/service-tier-normalization-Cei89SW6.mjs +0 -15
  158. package/dist/.setup/shell-dynamic-tools-Bmedt1QE.mjs +0 -85
  159. package/dist/.setup/thread-archive-guard-C9frICzX.mjs +0 -60
  160. package/dist/.setup/thread-requests-Bj_Lixmv.mjs +0 -2111
  161. package/dist/.setup/upstream-prompt-provenance-fXkKbPVC.mjs +0 -37
@@ -1,88 +1,93 @@
1
1
  import { n as readCodexRuntimeModelId } from "./model-runtime-BdqzOMkU.mjs";
2
- import { g as createCodexNativeSubagentHistoryOwner } from "./native-subagent-pending-assignments-BDqhOdJp.mjs";
2
+ import { g as createCodexNativeSubagentHistoryOwner } from "./native-subagent-pending-assignments-DmVhedNs.mjs";
3
3
  import { i as isJsonObject, r as flattenCodexDynamicToolFunctions } from "./protocol-CANUwXJ3.mjs";
4
- import { i as matchesCodexNativeSubagentSubmissionBinding, m as sessionBindingIdentity, n as assertCodexBindingMayBeReplaced } from "./session-binding-record-BZB8RgcF.mjs";
5
- import { n as defineCodexBuildState } from "./build-state-LS-A65iX.mjs";
6
- import { c as shouldAutoApproveCodexAppServerApprovals, f as readCodexRequirementsToml, l as withMcpElicitationsApprovalPolicy, n as hasCodexMcpToolApprovalOverrides } from "./config-security-KAPScztc.mjs";
7
- import { c as isCodexPairedNodeRemoteExecPlacementSandbox, d as readCodexPluginConfig, f as resolveCodexPluginsPolicy, l as isCodexRemoteExecPlacementSandbox, u as isCodexSandboxExecServerEnabled } from "./config-parsing-BQq-CHTF.mjs";
4
+ import { i as matchesCodexNativeSubagentSubmissionBinding, m as sessionBindingIdentity, n as assertCodexBindingMayBeReplaced } from "./session-binding-record-DU_0biMD.mjs";
5
+ import { n as defineCodexBuildState } from "./build-state-CMYRQ_We.mjs";
6
+ import { c as withMcpElicitationsApprovalPolicy, d as readCodexRequirementsToml, n as hasCodexMcpToolApprovalOverrides, s as shouldAutoApproveCodexAppServerApprovals } from "./config-security-clxAZYWX.mjs";
7
+ import { c as isCodexPairedNodeRemoteExecPlacementSandbox, d as readCodexPluginConfig, f as resolveCodexPluginsPolicy, l as isCodexRemoteExecPlacementSandbox, u as isCodexSandboxExecServerEnabled } from "./config-parsing-DsWSCPHO.mjs";
8
8
  import { n as isCodexAppServerProxyLaunch } from "./launch-args-DbFCehO7.mjs";
9
9
  import { t as resolveCodexAppServerHomeDir } from "./auth-start-options-BPIPeEX8.mjs";
10
- import { i as resolveCodexAppServerHomeScope, l as resolveCodexModelBackedReviewerPolicyContext, o as resolveCodexComputerUseConfig } from "./config-options-HG_Rr3W_.mjs";
11
- import { c as resolveCodexAppServerPreparedApiKeyCacheKey, s as resolveCodexAppServerFallbackApiKeyCacheKey, w as retireSharedCodexAppServerClientIfCurrent } from "./auth-cache-key-BE1HXsNo.mjs";
12
- import { o as formatCodexDisplayText } from "./command-formatters-DV3DHhdr.mjs";
13
- import { a as codexPrewriteRejectionCause, i as CodexAppServerScopedRequestRejectedError, r as CodexAppServerRpcError } from "./rpc-error-hmWM21RB.mjs";
14
- import { n as waitForPromiseOrAbort } from "./timeout-CXOfNoaX.mjs";
10
+ import { i as resolveCodexAppServerHomeScope, l as resolveCodexModelBackedReviewerPolicyContext, o as resolveCodexComputerUseConfig } from "./config-options-DDzeNQ8m.mjs";
11
+ import { c as resolveCodexAppServerPreparedApiKeyCacheKey, s as resolveCodexAppServerFallbackApiKeyCacheKey, w as retireSharedCodexAppServerClientIfCurrent } from "./auth-cache-key-tENCQOub.mjs";
12
+ import { i as withCodexAppServerGitConfig } from "./transport-stdio-CRWTkKOn.mjs";
13
+ import { o as formatCodexDisplayText } from "./command-formatters-xW9KpoSZ.mjs";
14
+ import { a as codexPrewriteRejectionCause, i as CodexAppServerScopedRequestRejectedError, r as CodexAppServerRpcError } from "./rpc-error-C98SHchT.mjs";
15
+ import { n as waitForPromiseOrAbort } from "./timeout-D0mEWSGG.mjs";
15
16
  import { t as readCodexAsyncQuestions } from "./async-questions-DdhOCwGi.mjs";
16
- import { i as readCodexProviderRefusal, n as extractRawAssistantText, o as readItem, r as readCodexErrorNotificationMessage, s as readNullableString } from "./event-projector-values-DTqZHizf.mjs";
17
- import { r as readMirrorIdentity, t as attachCodexMirrorIdentity } from "./upstream-prompt-provenance-fXkKbPVC.mjs";
18
- import { n as buildCodexAppServerRuntimeFingerprint, r as buildCodexPluginAppCacheKey } from "./plugin-app-cache-key-BW8rd98k.mjs";
19
- import { i as resolveCodexBindingAppServerConnection, r as requireCodexSupervisionModelSelection, t as assertCodexSessionRuntimeOwnership } from "./binding-connection-C-08ez1w.mjs";
20
- import { n as requestCodexAppServerClientJson } from "./request-CZkKkN6c.mjs";
21
- import { n as canUseCodexModelBackedApprovalsReviewerForModel, r as resolveOpenClawExecPolicyForCodexAppServer } from "./config-0Gxk3_eq.mjs";
22
- import { a as isCodexDurableCustomMessage, c as resolveCodexContextEngineProjectionMaxChars, i as fitCodexProjectedContextForTurnStart, l as resolveCodexContinuityProjectionMaxChars, n as CodexContextAttachmentError, o as neutralizeCodexExplicitMentionSigils, r as buildCodexContinuityCalibration, s as projectContextEngineAssemblyForCodex, t as CODEX_TURN_START_TEXT_INPUT_MAX_CHARS, u as resolveProjectionPromptBudgetTokens } from "./context-engine-projection-CsgYSQhW.mjs";
23
- import { o as hasCodexMirrorOrigin, t as applyCodexTranscriptTaint } from "./transcript-mirror-attestation-YSegaktH.mjs";
24
- import { t as readCodexMirroredSessionHistoryMessages } from "./session-history-BogBHKLk.mjs";
17
+ import { i as readCodexProviderRefusal, n as extractRawResponseItemText, o as readItem, r as readCodexErrorNotificationMessage, s as readNullableString } from "./event-projector-values-CLvG1Hil.mjs";
18
+ import { i as readMirrorIdentity, n as attachCodexMirrorIdentity, t as attachCodexAssistantItemIds } from "./upstream-prompt-provenance-Ccd9MFRJ.mjs";
19
+ import { n as buildCodexAppServerRuntimeFingerprint, r as buildCodexPluginAppCacheKey } from "./plugin-app-cache-key-Bg9DbDI6.mjs";
20
+ import { i as resolveCodexBindingAppServerConnection, r as requireCodexSupervisionModelSelection, t as assertCodexSessionRuntimeOwnership } from "./binding-connection-B7HAAZSI.mjs";
21
+ import { n as requestCodexAppServerClientJson } from "./request-6piO0U_P.mjs";
22
+ import { n as canUseCodexModelBackedApprovalsReviewerForModel, r as resolveOpenClawExecPolicyForCodexAppServer } from "./config-C1YVVLEA.mjs";
23
+ import { a as isCodexDurableCustomMessage, c as resolveCodexContextEngineProjectionMaxChars, i as fitCodexProjectedContextForTurnStart, l as resolveCodexContinuityProjectionMaxChars, n as CodexContextAttachmentError, o as neutralizeCodexExplicitMentionSigils, r as buildCodexContinuityCalibration, s as projectContextEngineAssemblyForCodex, t as CODEX_TURN_START_TEXT_INPUT_MAX_CHARS, u as resolveProjectionPromptBudgetTokens } from "./context-engine-projection-ps-yn_ci.mjs";
24
+ import { a as buildCodexMirrorIdempotencyKey, i as buildCodexMirrorDedupeIdentity, s as hasCodexMirrorOrigin, t as applyCodexTranscriptTaint } from "./transcript-mirror-attestation-BzUXnrvv.mjs";
25
+ import { t as readCodexMirroredSessionHistoryMessages } from "./session-history-BO6i_pfk.mjs";
25
26
  import { i as resolveCodexAppServerAuthProfileIdForAgent, r as resolveCodexAppServerAuthProfileId } from "./auth-profile-CgHQ8Vot.mjs";
26
- import { E as isCodexContextRestartSelectionChangedError, H as prepareCodexWorkspaceReferences, I as ensureCodexAppServerClientRuntime, M as getCodexInferenceThreadQualification, U as protectCodexAppServerLiveThread, X as readRecentCodexRateLimits, Y as readCodexRateLimitsRevision, _ as retainSharedCodexAppServerClientIfCurrent, a as clearSharedCodexAppServerClientIfCurrentAndUnclaimed, c as getLeasedSharedCodexAppServerClient, dt as TURN_TERMINAL_SETTLEMENT_TIMEOUT_MS, et as resolveCodexAppServerAuthAccountCacheKey, f as readCodexAppServerClientDesktopGenerationFingerprint, h as releaseLeasedSharedCodexAppServerClient, ht as withCodexStartupTimeout, i as clearSharedCodexAppServerClientIfCurrent, j as getCodexInferenceThread, l as getSharedCodexAppServerClient, lt as CodexAppServerStartupError, mt as resolveCodexStartupTimeoutMs, s as createIsolatedCodexAppServerClient, tt as resolveCodexAppServerPreparedAuthHandoff, u as isCodexAppServerStartSelectionChangedError, ut as TURN_FINALIZE_DRAIN_ABORT_GRACE_MS, w as CodexThreadClientReplacementError, x as CODEX_APP_SERVER_CONTEXT_RESTART_SELECTION_CHANGED } from "./shared-client-5NUq43f3.mjs";
27
+ import { E as isCodexContextRestartSelectionChangedError, H as prepareCodexWorkspaceReferences, I as ensureCodexAppServerClientRuntime, M as getCodexInferenceThreadQualification, U as protectCodexAppServerLiveThread, X as readRecentCodexRateLimits, Y as readCodexRateLimitsRevision, _ as retainSharedCodexAppServerClientIfCurrent, a as clearSharedCodexAppServerClientIfCurrentAndUnclaimed, c as getLeasedSharedCodexAppServerClient, dt as TURN_TERMINAL_SETTLEMENT_TIMEOUT_MS, et as resolveCodexAppServerAuthAccountCacheKey, f as readCodexAppServerClientDesktopGenerationFingerprint, h as releaseLeasedSharedCodexAppServerClient, ht as withCodexStartupTimeout, i as clearSharedCodexAppServerClientIfCurrent, j as getCodexInferenceThread, l as getSharedCodexAppServerClient, lt as CodexAppServerStartupError, mt as resolveCodexStartupTimeoutMs, s as createIsolatedCodexAppServerClient, tt as resolveCodexAppServerPreparedAuthHandoff, u as isCodexAppServerStartSelectionChangedError, ut as TURN_FINALIZE_DRAIN_ABORT_GRACE_MS, w as CodexThreadClientReplacementError, x as CODEX_APP_SERVER_CONTEXT_RESTART_SELECTION_CHANGED } from "./shared-client-BjiqpbC5.mjs";
27
28
  import { a as isCodexResponsesOAuthRun, r as isCodexResponsesOAuth } from "./responses-oauth-twnuTaAa.mjs";
28
- import { A as resolveTerminalDynamicToolBatchAction, D as isDynamicToolTerminalDiagnosticEvent, E as hasPendingDynamicToolTerminalDiagnostic, H as resolveCodexAppServerClientInstanceId, M as toCodexDynamicToolProgressResponse, N as toCodexDynamicToolProtocolResponse, O as isMatchingDynamicToolTerminalDiagnostic, T as handleDynamicToolCallWithTimeout, _ as assertCodexTurnStartResponse, a as isCodexAppServerIndeterminateRequestCancellationError, i as isCodexAppServerConnectionClosedError, j as shouldReleaseTurnAfterTerminalDynamicTool, k as resolveDynamicToolCallTimeoutMs, l as CodexServerRequestResolvedError, o as isCodexAppServerIndeterminateTransportError, r as isCodexAppServerApprovalRequest, w as createCodexElicitationResponse, x as readCodexTurnCompletedNotification, y as readCodexDynamicToolCallParams, z as CODEX_APP_SERVER_OPT_OUT_NOTIFICATION_METHODS } from "./client-ChJtGEdJ.mjs";
29
- import { n as isCodexWebSocketOpenFailure } from "./transport-websocket-zqJ0Cmtn.mjs";
30
- import { a as isCodexNotificationForTurn, b as shouldClearTerminalPresentationForNativeItem, g as itemName, i as CodexProjectionDiagnostics, n as getCodexAppServerTurnRouter, o as readCodexNotificationThreadId, t as CODEX_APP_SERVER_NATIVE_TURN_WAIT_TIMEOUT_MS, y as matchesCodexSnapshotTurn } from "./turn-router-BOKSJmfw.mjs";
31
- import { d as terminateCodexBackgroundTerminals, f as unsubscribeCodexThreadBestEffort, l as retireUnsafeCodexTurnClientBestEffort, n as CODEX_APP_SERVER_UNSUBSCRIBE_TIMEOUT_MS, o as closeCodexStartupClientBestEffort, r as CodexAppServerUnsafeSubscriptionError, s as interruptCodexTurnAndWaitBestEffort, u as shouldRetireCodexStartupClient } from "./attempt-client-cleanup-DPUGAWP2.mjs";
32
- import { r as prepareCodexAppServerAuthBinding } from "./auth-binding-BoMwpuPN.mjs";
33
- import { a as isRawFunctionToolOutputCompletionNotification, c as readNotificationItemId, i as isPendingOpenClawDynamicToolCompletionNotification, l as readRawResponseToolCallId, o as isTerminalTurnStatus, r as isCodexTurnAbortMarkerNotification, s as readCodexNotificationItem, t as CodexUsageProjection, u as updateActiveTurnItemIds } from "./event-projector-usage-03R0I2dM.mjs";
34
- import { n as listAllCodexAppServerModels } from "./models-DaW-7tld.mjs";
35
- import { B as hasCodexNativeToolCatalog, Ct as mergeCodexThreadConfigs, D as assertCodexNativeHookRelayAllowed, E as CodexManagedHooksOnlyError, F as scheduleCodexNativeHookRelayUnregister, G as areCodexDynamicToolFingerprintsCompatible, J as codexLegacyDynamicToolsFingerprint, N as resolveCodexNativeHookRelayEvents, O as buildCodexNativeHookRelayConfig, P as resolveCodexNativeHookRelayTtlMs, S as joinPresentSections, T as CODEX_NATIVE_HOOK_RELAY_TTL_GRACE_MS, V as loadCodexNativeToolCatalog, Z as fingerprintJsonObject, _t as buildCodexPluginThreadConfigInputFingerprint, b as resolveCodexAppServerThreadModelSelection, dt as isSystemAgentOnlyCodexDynamicToolAllowlist, g as buildDeveloperInstructions, j as createCodexNativeHookRelay, k as buildCodexNativeHookRelayDisabledConfig, l as isCodexNativeDelegationDisabledForRun, m as resolveCodexWebSearchPlan, mt as resolveCodexDynamicToolsLoadingForRuntime, nt as stabilizeJsonValue, q as codexDynamicToolsFingerprint, st as filterCodexDynamicTools } from "./thread-requests-Bj_Lixmv.mjs";
36
- import { _ as buildContextEngineBinding, a as buildTurnStartParams, c as assertScheduledCodexAppAuthorityRuntime, d as buildScheduledCodexAppServerConnectionIdentity, f as captureScheduledCodexAppAuthority, g as isCodexAppServerProfilerEnabled, h as resolveScheduledCodexAppCreatorCaptureDecision, i as buildTurnCollaborationMode, l as buildLegacyScheduledCodexAppRecoveryPrompt, n as buildCodexParentLocalInstructions, o as buildCodexUserInput, s as startOrResumeThread, t as buildCodexHistoryProvenancePrefix, u as buildScheduledCodexAppAuthorityInputFingerprint, v as isContextEngineBindingCompatible } from "./thread-lifecycle--EPPTNTe.mjs";
37
- import { o as createCodexSessionGenerationSupersededError, r as resolveCodexSessionBinding, s as resolveCodexRunSessionBindingAuthority, t as clearCodexBindingForClient } from "./session-binding-Ce7BqiPN.mjs";
38
- import { a as CodexToolTranscriptProjection, c as shouldEmitTranscriptToolProgress, d as resolveCodexToolProgressDetailMode, f as sanitizeCodexAgentEventRecord, i as emitCodexAgentEvent, p as sanitizeCodexToolArguments, r as CodexEventProjection, s as CodexToolProgressProjection, t as codexNativeSubagentMonitorRuntime, u as isCodexCommandBearingToolCall } from "./native-subagent-monitor-wh_-K3Vo.mjs";
39
- import { a as requestPluginApprovalOutcome } from "./plugin-approval-roundtrip-bPQbG8BI.mjs";
40
- import { n as CodexThreadPolicyHandoffError, s as restoreCodexThreadInstructionsAfterCompaction } from "./thread-policy-VtqLex1l.mjs";
41
- import { c as withExclusiveCodexAppServerThread, r as retainCodexAppServerBindingSubscription, t as isSameCodexAppServerThreadOwner } from "./thread-ownership-T7T_iffm.mjs";
42
- import { a as resolveCodexPromptError, i as refreshCodexUsageLimitPromptError, n as formatCodexTurnStartUsageLimitError, r as markCodexAuthProfileBlockedFromRateLimits, t as CodexUsageLimitPromptError } from "./usage-limit-error-CGJUoQu8.mjs";
29
+ import { D as toCodexDynamicToolProgressResponse, E as resolveDynamicToolCallTimeoutMs, L as resolveCodexAppServerClientInstanceId, M as readCodexAppServerWarningMessage, O as toCodexDynamicToolProtocolResponse, P as CODEX_APP_SERVER_OPT_OUT_NOTIFICATION_METHODS, T as handleDynamicToolCallWithTimeout, _ as assertCodexTurnStartResponse, a as isCodexAppServerIndeterminateRequestCancellationError, i as isCodexAppServerConnectionClosedError, l as CodexServerRequestResolvedError, o as isCodexAppServerIndeterminateTransportError, r as isCodexAppServerApprovalRequest, w as createCodexElicitationResponse, x as readCodexTurnCompletedNotification, y as readCodexDynamicToolCallParams } from "./client-zrCKOu_E.mjs";
30
+ import { n as isCodexWebSocketOpenFailure } from "./transport-websocket-DIyPfkHo.mjs";
31
+ import { S as shouldClearTerminalPresentationForNativeItem, _ as itemName, a as isCodexNotificationForTurn, b as matchesCodexSnapshotTurn, i as CodexProjectionDiagnostics, n as getCodexAppServerTurnRouter, o as readCodexNotificationScope, s as readCodexNotificationThreadId, t as CODEX_APP_SERVER_NATIVE_TURN_WAIT_TIMEOUT_MS, x as shouldAdvancePersistableAssistantBarrier } from "./turn-router-D8DLkZgH.mjs";
32
+ import { d as terminateCodexBackgroundTerminals, f as unsubscribeCodexThreadBestEffort, l as retireUnsafeCodexTurnClientBestEffort, n as CODEX_APP_SERVER_UNSUBSCRIBE_TIMEOUT_MS, o as closeCodexStartupClientBestEffort, r as CodexAppServerUnsafeSubscriptionError, s as interruptCodexTurnAndWaitBestEffort, u as shouldRetireCodexStartupClient } from "./attempt-client-cleanup-CxX4cTSi.mjs";
33
+ import { r as prepareCodexAppServerAuthBinding } from "./auth-binding-BaxlhaNx.mjs";
34
+ import { a as isRawFunctionToolOutputCompletionNotification, c as readRawResponseToolCallId, i as isCodexTurnAbortMarkerNotification, l as updateActiveTurnItemIds, o as isTerminalTurnStatus, r as completePendingOpenClawDynamicToolNotification, s as readCodexNotificationItem, t as CodexUsageProjection } from "./event-projector-usage-BpKfdoTm.mjs";
35
+ import { n as listAllCodexAppServerModels } from "./models-Dph0RqpR.mjs";
36
+ import { d as mergeCodexThreadConfigs } from "./project-doc-thread-config-BVcvnps8.mjs";
37
+ import { B as resolveCodexDynamicToolsLoadingForRuntime, L as isSystemAgentOnlyCodexDynamicToolAllowlist, P as filterCodexDynamicTools, V as joinPresentSections, _ as buildDeveloperInstructions, b as codexDynamicToolsFingerprint, h as resolveCodexWebSearchPlan, k as stabilizeJsonValue, l as isCodexNativeDelegationDisabledForRun, v as areCodexDynamicToolFingerprintsCompatible, w as fingerprintJsonObject, x as codexLegacyDynamicToolsFingerprint } from "./thread-requests-BgzJwJtS.mjs";
38
+ import { i as resolveCodexSessionBinding, n as createCodexSessionGenerationSupersededError, t as clearCodexBindingForClient } from "./session-binding-JEHNMPsr.mjs";
39
+ import { i as resolveCodexAppServerThreadModelSelection } from "./thread-model-selection-DcVebr8N.mjs";
40
+ import { a as resolveCodexPromptError, i as refreshCodexUsageLimitPromptError, n as formatCodexTurnStartUsageLimitError, r as markCodexAuthProfileBlockedFromRateLimits, t as CodexUsageLimitPromptError } from "./usage-limit-error-BEONfgt-.mjs";
41
+ import { c as withExclusiveCodexAppServerThread, r as retainCodexAppServerBindingSubscription, t as isSameCodexAppServerThreadOwner } from "./thread-ownership-5X4197vk.mjs";
43
42
  import { t as persistCodexContextCompactionActivity } from "./context-compaction-activity-CMla5FPJ.mjs";
44
- import { t as attemptTerminal } from "./attempt-terminal-gZrxQ35N.mjs";
45
- import { a as runCodexAgentEndHook, i as reportCodexBackgroundCleanupFailure, n as ensureCodexWorkspaceDirOnce, o as shouldKeepCodexSharedAbortOpen, r as estimateCodexAppServerProjectedTurnTokens, s as withCodexAppServerFastModeServiceTier, t as emitCodexAppServerEvent } from "./run-attempt-lifecycle-BuZgVbDA.mjs";
46
- import { t as CODEX_INFERENCE_GENERATION_KEY } from "./inference-metadata-CgIf7sOx.mjs";
47
- import "./inference-context-D-9gWlTR.mjs";
48
- import { i as createAssistantReasoningMessage, n as createAssistantCommentaryMessage, r as createAssistantMessage, t as createAssistantAsyncMessage } from "./event-projector-assistant-message-BwG5TUYW.mjs";
49
- import { a as resolveCodexExternalSandboxPolicyForOpenClawSandbox, c as shouldEnableCodexAppServerNativeToolSurface, i as resolveCodexAppServerHookChannelId, l as shouldRequireCodexSandboxExecServerEnvironment, o as resolveCodexMessageToolProvider, p as mapCodexAppServerRemoteWorkspacePath, r as resolveCodexAppServerExecutionCwd, s as resolveCodexSandboxEnvironmentSelection, t as buildDynamicTools, u as shouldWarnCodexDynamicToolBuildStageSummary } from "./dynamic-tool-build-BCi00feJ.mjs";
50
- import { n as resolveCodexPluginThreadConfigStartupPolicy, t as createCodexPluginThreadConfigStartupProvider } from "./plugin-thread-config-deadline-C5i1S6RN.mjs";
51
- import { i as resolveCodexSessionPermissionCwd, n as applyCodexSessionPermissionPolicy, r as resolveCodexEffectiveSessionPermissionPolicy } from "./session-permission-policy-BxIUJ0Zd.mjs";
52
- import { r as prepareCodexNativeMcpFormResourceContext, t as createCodexNativeMcpAppResultDetailsPreparer } from "./native-mcp-app-ChpyWmL-.mjs";
53
- import { a as emitDynamicToolStartedDiagnostic, c as ensureCodexSandboxExecServerEnvironment, d as CodexNativeProcessAuthority, f as readCodexRetainedBackgroundCommands, i as emitDynamicToolErrorDiagnostic, l as releaseCodexSandboxExecServerEnvironment, m as CodexNativeToolLifecycleProjector, n as projectCodexExecutableDynamicTools, o as emitDynamicToolTerminalDiagnostic, p as createCodexRemoteWorkspaceFileReader, r as routeCodexAppServerElicitationRequest, s as handleCodexAppServerApprovalRequest, t as createCodexDynamicToolBridge, u as createCodexNativePreToolUseFailureBuffer } from "./dynamic-tools-DUv6Sr6h.mjs";
54
- import { c as promptSnapshot, i as mirrorPromptAtTurnStartBestEffort, n as createCodexAppServerUserMessagePersistenceNotifier, o as buildCodexUserPromptMessage, s as buildResolvedCodexUserPromptMessage, t as codexTranscriptMirrorRuntime } from "./transcript-mirror-BfLRARNL.mjs";
55
- import { t as resolveCodexAppServerForModelProvider } from "./app-server-policy-Bg4FZw1f.mjs";
56
- import { a as getCodexContextFileDisplayBasename, i as getCodexContextFileBasename, n as CODEX_NATIVE_PROJECT_DOC_BASENAMES, o as isNonEmptyString, r as buildCodexWorkspaceBootstrapContext, s as normalizeCodexContextFilePath } from "./attempt-workspace-context-GllQy8mw.mjs";
57
- import { n as captureCodexSettledTurnFinalizationContext } from "./settled-turn-context-BZsMjkIO.mjs";
58
- import { t as resolveCodexProviderWebSearchSupport } from "./provider-capabilities-DhkeeHJd.mjs";
59
- import { a as runCodexComputerUseLiveTest, i as createComputerUseRequest, t as ensureCodexComputerUse } from "./computer-use-CF0jsDi1.mjs";
60
- import { asOptionalRecord, normalizeLowercaseStringOrEmpty, readNonBlankString, readStringField } from "openclaw/plugin-sdk/string-coerce-runtime";
61
- import { createHash } from "node:crypto";
43
+ import { a as CodexToolTranscriptProjection, c as isCodexCommandBearingToolCall, d as sanitizeCodexToolArguments, i as emitCodexAgentEvent, l as resolveCodexToolProgressDetailMode, o as CodexToolProgressProjection, r as CodexEventProjection, s as shouldEmitTranscriptToolProgress, t as codexNativeSubagentMonitorRuntime, u as sanitizeCodexAgentEventRecord } from "./native-subagent-monitor-D5O_o07p.mjs";
44
+ import { a as requestPluginApprovalOutcome } from "./plugin-approval-roundtrip-DOQ3Tibe.mjs";
45
+ import { n as CodexThreadPolicyHandoffError, s as restoreCodexThreadInstructionsAfterCompaction } from "./thread-policy-BEecBTJM.mjs";
46
+ import { t as attemptTerminal } from "./attempt-terminal-jO5IMj9K.mjs";
47
+ import { a as runCodexAgentEndHook, c as withCodexAppServerFastModeServiceTier, i as reportCodexBackgroundCleanupFailure, n as ensureCodexWorkspaceDirOnce, o as runCodexCleanupStep, r as estimateCodexAppServerProjectedTurnTokens, s as shouldKeepCodexSharedAbortOpen, t as emitCodexAppServerEvent } from "./run-attempt-lifecycle-KN4oh-7O.mjs";
48
+ import { t as CODEX_INFERENCE_GENERATION_KEY } from "./inference-metadata-DCvcG_N_.mjs";
49
+ import "./inference-context-DNlGwzwy.mjs";
50
+ import { i as createAssistantReasoningMessage, n as createAssistantCommentaryMessage, r as createAssistantMessage, t as createAssistantAsyncMessage } from "./event-projector-assistant-message-CLMKN4x-.mjs";
51
+ import { a as resolveCodexExternalSandboxPolicyForOpenClawSandbox, c as shouldEnableCodexAppServerNativeToolSurface, i as resolveCodexAppServerHookChannelId, l as shouldRequireCodexSandboxExecServerEnvironment, o as resolveCodexMessageToolProvider, p as mapCodexAppServerRemoteWorkspacePath, r as resolveCodexAppServerExecutionCwd, s as resolveCodexSandboxEnvironmentSelection, t as buildDynamicTools, u as shouldWarnCodexDynamicToolBuildStageSummary } from "./dynamic-tool-build-BMiiFROa.mjs";
52
+ import { a as buildCodexNativeHookRelayDisabledConfig, d as scheduleCodexNativeHookRelayUnregister, i as buildCodexNativeHookRelayConfig, l as resolveCodexNativeHookRelayEvents, n as CodexManagedHooksOnlyError, r as assertCodexNativeHookRelayAllowed, s as createCodexNativeHookRelay, t as CODEX_NATIVE_HOOK_RELAY_TTL_GRACE_MS, u as resolveCodexNativeHookRelayTtlMs } from "./native-hook-relay-CSZpcjwq.mjs";
53
+ import { a as prepareCodexPluginThreadConfigStartupProvider, c as buildLegacyScheduledCodexAppRecoveryPrompt, d as resolveScheduledCodexAppCreatorCaptureDecision, i as isContextEngineBindingCompatible, l as buildScheduledCodexAppServerConnectionIdentity, n as isCodexAppServerProfilerEnabled, o as resolveCodexPluginThreadConfigStartupPolicy, r as buildContextEngineBinding, s as assertScheduledCodexAppAuthorityRuntime, t as startOrResumeThread, u as captureScheduledCodexAppAuthority } from "./thread-lifecycle-run-BWy0LDLB.mjs";
54
+ import { i as resolveCodexSessionPermissionCwd, n as applyCodexSessionPermissionPolicy, r as resolveCodexEffectiveSessionPermissionPolicy } from "./session-permission-policy-CD2MAWU8.mjs";
55
+ import { o as hasCodexNativeToolCatalog, s as loadCodexNativeToolCatalog } from "./native-skill-isolation-BAatEJZb.mjs";
56
+ import { r as prepareCodexNativeMcpFormResourceContext, t as createCodexNativeMcpAppResultDetailsPreparer } from "./native-mcp-app-CDrrBaTE.mjs";
57
+ import { _ as invalidateCodexComputerFrame, a as handleCodexAppServerApprovalRequest, c as createCodexNativePreToolUseFailureBuffer, f as buildTurnCollaborationMode, g as buildCodexUserInput, h as readCodexRetainedBackgroundCommands, i as createCodexDynamicToolDiagnostics, l as buildCodexHistoryProvenancePrefix, m as CodexNativeProcessAuthority, n as projectCodexExecutableDynamicTools, o as ensureCodexSandboxExecServerEnvironment, p as buildTurnStartParams, r as routeCodexAppServerElicitationRequest, s as releaseCodexSandboxExecServerEnvironment, t as createCodexDynamicToolBridge, u as buildCodexParentLocalInstructions, v as createCodexRemoteWorkspaceFileReader, y as CodexNativeToolLifecycleProjector } from "./dynamic-tools-DPPHrGKB.mjs";
58
+ import { c as promptSnapshot, i as mirrorPromptAtTurnStartBestEffort, n as createCodexAppServerUserMessagePersistenceNotifier, o as buildCodexUserPromptMessage, s as buildResolvedCodexUserPromptMessage, t as codexTranscriptMirrorRuntime } from "./transcript-mirror-Bee2o6jj.mjs";
59
+ import { t as resolveCodexAppServerForModelProvider } from "./app-server-policy-D_zv8J7V.mjs";
60
+ import { a as getCodexContextFileDisplayBasename, i as getCodexContextFileBasename, n as CODEX_NATIVE_PROJECT_DOC_BASENAMES, o as isNonEmptyString, r as buildCodexWorkspaceBootstrapContext, s as normalizeCodexContextFilePath } from "./attempt-workspace-context-CcwP3DA3.mjs";
61
+ import { n as captureCodexSettledTurnFinalizationContext } from "./settled-turn-context-BPL6D3RO.mjs";
62
+ import { t as resolveCodexProviderWebSearchSupport } from "./provider-capabilities-DtJKxDf6.mjs";
63
+ import { a as runCodexComputerUseLiveTest, i as createComputerUseRequest, t as ensureCodexComputerUse } from "./computer-use-CeF5GuCX.mjs";
64
+ import { asOptionalRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalString, readNonBlankString, readStringField } from "openclaw/plugin-sdk/string-coerce-runtime";
65
+ import { createHash, randomUUID } from "node:crypto";
62
66
  import { isDeepStrictEqual } from "node:util";
63
67
  import { resolveAgentConfig, resolveSessionAgentIdsStrict } from "openclaw/plugin-sdk/agent-scope-runtime";
64
68
  import { asDateTimestampMs } from "openclaw/plugin-sdk/number-runtime";
69
+ import { truncateUtf16Safe, truncateUtf8Prefix } from "openclaw/plugin-sdk/text-utility-runtime";
65
70
  import path from "node:path";
66
71
  import fs from "node:fs/promises";
67
72
  import { isPathStrictlyInside, readFileWindowFully, root } from "openclaw/plugin-sdk/file-access-runtime";
68
73
  import { addAbortListener } from "node:events";
69
74
  import { isIncognitoSessionKey } from "openclaw/plugin-sdk/session-key-runtime";
70
75
  import { Type } from "typebox";
71
- import { truncateUtf16Safe, truncateUtf8Prefix } from "openclaw/plugin-sdk/text-utility-runtime";
72
76
  import { createDiagnosticTraceContextFromActiveScope, emitTrustedDiagnosticEvent, emitTrustedDiagnosticEventWithPrivateData, freezeDiagnosticTraceContext, onInternalDiagnosticEvent, resolveDiagnosticModelContentCapturePolicy } from "openclaw/plugin-sdk/diagnostic-runtime";
73
77
  import { createDeferred } from "openclaw/plugin-sdk/extension-shared";
74
78
  import { createStageTimingTracker, formatStageTimings } from "openclaw/plugin-sdk/time-runtime";
75
79
  import { Buffer as Buffer$1 } from "node:buffer";
76
- import { AgentHarnessPreflightError, CODEX_APP_SERVER_CONTEXT_ENGINE_HOST, FAST_MODE_AUTO_PROGRESS_KIND, HEARTBEAT_RESPONSE_TOOL_NAME, agentHarnessStructuredInput, applyEmbeddedAttemptToolsAllow, assembleHarnessContextEngine, assertContextEngineHostSupport, bootstrapHarnessContextEngine, buildAgentHookContextChannelFields, buildEmbeddedForegroundPromptContext, buildHarnessContextEngineRuntimeContext, cancelPendingAgentQuestionForSession, claimPendingAgentQuestionAnswer, classifyAgentHarnessTerminalOutcome, clearActiveEmbeddedRun, detectAndLoadAgentHarnessPromptImages, embeddedAgentLog, emptyAgentHarnessUserInputAnswers, formatErrorMessage, formatFastModeAutoProgressText, getAgentHarnessHookRunner, hasBeforeToolCallPolicy, inferToolMetaFromArgs, isActiveHarnessContextEngine, isHostScopedAgentToolActive, loadCodexBundleMcpThreadConfig, materializeRequesterScopedMcpToolsForHarnessRun, normalizeHeartbeatToolResponse, prepareWatchedSessionsHarnessContext, projectAgentHarnessTranscriptMessageForDisplay, projectAgentToolActivity, projectProgressCardChannelUpdate, resolveAgentDir as resolveAgentDir$1, resolveAgentHarnessBeforePromptBuildResult, resolveAgentRunAbortLifecycleFields, resolveAttemptFsWorkspaceOnly, resolveContextEngineOwnerPluginId, resolveFastModeForElapsed, resolveSandboxContext, resolveUserPath, runAgentCleanupStep, runAgentHarnessAfterCompactionHook, runAgentHarnessBeforeCompactionHook, runAgentHarnessLlmInputHook, runAgentHarnessLlmOutputHook, runHarnessContextEngineMaintenance, setActiveEmbeddedRun, supportsModelTools } from "openclaw/plugin-sdk/agent-harness-runtime";
77
- import { resolveAgentDir as resolveAgentDir$2 } from "openclaw/plugin-sdk/agent-runtime";
80
+ import { resolveAgentDir as resolveAgentDir$1 } from "openclaw/plugin-sdk/agent-runtime";
81
+ import { AgentHarnessPreflightError, CODEX_APP_SERVER_CONTEXT_ENGINE_HOST, FAST_MODE_AUTO_PROGRESS_KIND, HEARTBEAT_RESPONSE_TOOL_NAME, agentHarnessStructuredInput, applyEmbeddedAttemptToolsAllow, assembleHarnessContextEngine, assertContextEngineHostSupport, bootstrapHarnessContextEngine, buildAgentHookContextChannelFields, buildEmbeddedForegroundPromptContext, buildHarnessContextEngineRuntimeContext, cancelPendingAgentQuestionForSession, claimPendingAgentQuestionAnswer, classifyAgentHarnessTerminalOutcome, clearActiveEmbeddedRun, detectAndLoadAgentHarnessPromptImages, embeddedAgentLog, emptyAgentHarnessUserInputAnswers, formatErrorMessage, formatFastModeAutoProgressText, getAgentHarnessHookRunner, hasBeforeToolCallPolicy, inferToolMetaFromArgs, isActiveHarnessContextEngine, isHostScopedAgentToolActive, loadCodexBundleMcpThreadConfig, materializeRequesterScopedMcpToolsForHarnessRun, normalizeHeartbeatToolResponse, prepareWatchedSessionsHarnessContext, projectAgentHarnessTranscriptMessageForDisplay, projectAgentToolActivity, projectProgressCardChannelUpdate, resolveAgentDir as resolveAgentDir$2, resolveAgentHarnessBeforePromptBuildResult, resolveAgentRunAbortLifecycleFields, resolveAttemptFsWorkspaceOnly, resolveContextEngineOwnerPluginId, resolveFastModeForElapsed, resolveSandboxContext, resolveUserPath, runAgentHarnessAfterCompactionHook, runAgentHarnessBeforeCompactionHook, runAgentHarnessLlmInputHook, runAgentHarnessLlmOutputHook, runHarnessContextEngineMaintenance, setActiveEmbeddedRun, supportsModelTools } from "openclaw/plugin-sdk/agent-harness-runtime";
78
82
  import { loadExecApprovals } from "openclaw/plugin-sdk/exec-approvals-runtime";
79
83
  import { AgentHarnessProjectionSettlement, createAgentHarnessAttemptCancellation, createAgentHarnessAttemptDeadlineController, createAgentHarnessAttemptLifecycle, shouldIncludeAgentHarnessRuntimeContext } from "openclaw/plugin-sdk/agent-harness-attempt-runtime";
80
- import { getSessionEntry } from "openclaw/plugin-sdk/session-store-runtime";
84
+ import { getSessionEntry, patchSessionEntry, resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
85
+ import { pruneMapToMaxSize } from "openclaw/plugin-sdk/collection-runtime";
81
86
  import { sleepWithAbort } from "openclaw/plugin-sdk/runtime-env";
82
87
  import { acknowledgeInternalToolResult, createAgentHarnessToolExecutionRegistry } from "openclaw/plugin-sdk/agent-harness-tool-runtime";
83
- import { createNativeSessionBindingAuthority } from "openclaw/plugin-sdk/agent-harness-session-runtime";
88
+ import { createNativeSessionBindingAuthority, prepareNativeSessionGenerationAuthority } from "openclaw/plugin-sdk/agent-harness-session-runtime";
89
+ import { appendSessionYieldContext, composeSessionTranscriptWriteAssertion, hasPromptImageInput } from "openclaw/plugin-sdk/session-transcript-runtime";
84
90
  import { captureFinalCodexCronCreatorToolAllowlist, formatMcpCodexApprovalRemedy, materializeStaticMcpToolsForHarnessRun, resolveCodexMcpToolOverridesForAgent, resolveCodexTtsProvenanceTransfer } from "openclaw/plugin-sdk/codex-mcp-projection";
85
- import { appendSessionYieldContext, hasPromptImageInput } from "openclaw/plugin-sdk/session-transcript-runtime";
86
91
  import { getAgentScopedMediaLocalRoots } from "openclaw/plugin-sdk/media-local-roots";
87
92
  import { isSilentReplyPayloadText } from "openclaw/plugin-sdk/reply-chunking";
88
93
  import { generatedImageAssetFromBase64 } from "openclaw/plugin-sdk/image-generation";
@@ -135,6 +140,38 @@ function createCodexAttemptPreparationTiming(params) {
135
140
  //#endregion
136
141
  //#region extensions/codex/src/app-server/attempt-steering.ts
137
142
  const CODEX_STEER_ALL_DEBOUNCE_MS = 500;
143
+ function createCodexQuestionInputHandlers(sessionKey, assertActive) {
144
+ const questionAuthority = (kind, assertSource, toolAuthorityPreparation) => ({
145
+ kind,
146
+ toolAuthorityPreparation,
147
+ assertCurrent: () => {
148
+ assertSource?.();
149
+ assertActive();
150
+ }
151
+ });
152
+ const claimPendingUserInputAnswer = async (text, optionsLocal, assertCurrent, authorityKind = assertCurrent ? "source-bound" : "run", toolAuthorityPreparation) => {
153
+ if (optionsLocal?.isInboundUserMessage !== true || hasPromptImageInput(optionsLocal)) return false;
154
+ assertActive();
155
+ return await claimPendingAgentQuestionAnswer({
156
+ sessionKey,
157
+ text,
158
+ authority: questionAuthority(authorityKind, assertCurrent, toolAuthorityPreparation),
159
+ sourceRecorder: optionsLocal.userTurnTranscriptRecorder,
160
+ persist: optionsLocal.userTurnTranscriptRecorder ? async () => {
161
+ await optionsLocal.userTurnTranscriptRecorder?.persistApproved();
162
+ } : void 0
163
+ });
164
+ };
165
+ const cancelPendingUserInput = (resolvedBy, assertCurrent, authorityKind = assertCurrent ? "source-bound" : "run", toolAuthorityPreparation) => cancelPendingAgentQuestionForSession({
166
+ sessionKey,
167
+ resolvedBy,
168
+ authority: questionAuthority(authorityKind, assertCurrent, toolAuthorityPreparation)
169
+ });
170
+ return {
171
+ claimPendingUserInputAnswer,
172
+ cancelPendingUserInput
173
+ };
174
+ }
138
175
  var CodexSteeringAcceptedUnconfirmedError = class extends Error {
139
176
  constructor(message, options) {
140
177
  super(message, options);
@@ -177,16 +214,14 @@ function createCodexSteeringQueue(params) {
177
214
  reportItemAcceptance(item, true);
178
215
  };
179
216
  const resolveItem = (item) => {
180
- if (item.settled) return;
217
+ if (!pendingMessages.has(item)) return;
181
218
  acceptItem(item);
182
- item.settled = true;
183
219
  pendingMessages.delete(item);
184
220
  item.onQueueSettled?.();
185
221
  item.resolve();
186
222
  };
187
223
  const rejectItem = (item, error) => {
188
- if (item.settled) return;
189
- item.settled = true;
224
+ if (!pendingMessages.has(item)) return;
190
225
  pendingMessages.delete(item);
191
226
  reportItemAcceptance(item, false);
192
227
  item.onQueueSettled?.();
@@ -217,7 +252,7 @@ function createCodexSteeringQueue(params) {
217
252
  closeQueue(/* @__PURE__ */ new Error("codex app-server steering queue cancelled"));
218
253
  };
219
254
  const sendBatch = async (items) => {
220
- const pendingItems = items.filter((item) => !item.settled);
255
+ const pendingItems = items.filter((item) => pendingMessages.has(item));
221
256
  let liveItems = [];
222
257
  if (pendingItems.length === 0) return;
223
258
  let clientUserMessageId;
@@ -226,7 +261,7 @@ function createCodexSteeringQueue(params) {
226
261
  assertActive();
227
262
  const prepared = [];
228
263
  const isCurrent = (item) => {
229
- if (item.settled) return false;
264
+ if (!pendingMessages.has(item)) return false;
230
265
  try {
231
266
  item.assertCurrent();
232
267
  return true;
@@ -256,8 +291,15 @@ function createCodexSteeringQueue(params) {
256
291
  liveItems = liveItems.filter(isCurrent);
257
292
  if (liveItems.length === 0) return;
258
293
  }
294
+ const withCurrent = params.withPreparedCurrent && liveItems.some((item) => item.preparation) ? (write) => params.withPreparedCurrent(write, liveItems.flatMap((item) => item.preparation ? [{
295
+ ...item.preparation,
296
+ onRefused: (error) => {
297
+ rejectItem(item, error);
298
+ return "discarded";
299
+ }
300
+ }] : [])) : params.withCurrent;
259
301
  clientUserMessageId = `openclaw:${params.turnId}:steer:${++batchSequence}`;
260
- if (!params.withCurrent) dispatchedBatches.set(clientUserMessageId, liveItems);
302
+ if (!withCurrent) dispatchedBatches.set(clientUserMessageId, liveItems);
261
303
  const request = {
262
304
  threadId: params.threadId,
263
305
  expectedTurnId: params.turnId,
@@ -267,7 +309,7 @@ function createCodexSteeringQueue(params) {
267
309
  await params.client.request("turn/steer", request, {
268
310
  timeoutMs: params.requestTimeoutMs,
269
311
  signal: params.signal,
270
- ...params.withCurrent ? { withCurrent: params.withCurrent } : {},
312
+ ...withCurrent ? { withCurrent } : {},
271
313
  onIngressRejected: () => dispatchedBatches.delete(request.clientUserMessageId),
272
314
  assertCurrent: () => {
273
315
  assertActive();
@@ -305,7 +347,7 @@ function createCodexSteeringQueue(params) {
305
347
  params.signal.addEventListener("abort", abortQueue, { once: true });
306
348
  if (params.signal.aborted) abortQueue();
307
349
  return {
308
- async queue(text, options, assertCurrent = () => {}) {
350
+ async queue(text, options, assertCurrent = () => {}, preparation) {
309
351
  try {
310
352
  assertActive();
311
353
  assertCurrent();
@@ -318,11 +360,11 @@ function createCodexSteeringQueue(params) {
318
360
  const item = {
319
361
  ...options,
320
362
  assertCurrent,
363
+ preparation,
321
364
  acceptance: "open",
322
365
  text,
323
366
  resolve,
324
- reject,
325
- settled: false
367
+ reject
326
368
  };
327
369
  pendingMessages.add(item);
328
370
  batchedMessages.push(item);
@@ -352,6 +394,146 @@ function normalizeCodexSteerDebounceMs(value) {
352
394
  return typeof value === "number" && Number.isFinite(value) && value >= 0 ? Math.floor(value) : CODEX_STEER_ALL_DEBOUNCE_MS;
353
395
  }
354
396
  //#endregion
397
+ //#region extensions/codex/src/app-server/event-projector-steering.ts
398
+ /** Owns the raw assistant cutoffs committed before each steer in one native turn. */
399
+ var CodexSteeringAssistantSegments = class {
400
+ constructor() {
401
+ this.streamedPartialAssistantItemReplaceable = false;
402
+ this.visible = /* @__PURE__ */ new Set();
403
+ this.completed = /* @__PURE__ */ new Map();
404
+ this.handoffItems = /* @__PURE__ */ new Set();
405
+ this.handoffGeneration = 0;
406
+ this.persisted = /* @__PURE__ */ new Map();
407
+ this.pending = /* @__PURE__ */ new Map();
408
+ this.occurrences = /* @__PURE__ */ new Map();
409
+ this.receiptIds = /* @__PURE__ */ new Map();
410
+ }
411
+ beginSnapshot() {
412
+ this.pending.clear();
413
+ }
414
+ recordStream(itemId, knownFinalAnswer) {
415
+ const replace = this.streamedPartialAssistantItemId !== void 0 && this.streamedPartialAssistantItemId !== itemId;
416
+ if (replace && (!knownFinalAnswer || this.streamedPartialAssistantItemReplaceable)) this.streamedPartialAssistantItemReplaceable = true;
417
+ else if (this.streamedPartialAssistantItemId === void 0) this.streamedPartialAssistantItemReplaceable = !knownFinalAnswer;
418
+ this.streamedPartialAssistantItemId = itemId;
419
+ const replaceable = this.streamedPartialAssistantItemReplaceable;
420
+ const replacement = replace && replaceable;
421
+ if (replacement) this.visible.clear();
422
+ this.visible.add(itemId);
423
+ let occurrence = this.occurrences.get(itemId);
424
+ if (!occurrence) {
425
+ occurrence = {
426
+ ids: [],
427
+ ownedCount: 0
428
+ };
429
+ this.occurrences.set(itemId, occurrence);
430
+ }
431
+ if (!occurrence.current) {
432
+ occurrence.current = randomUUID();
433
+ occurrence.ids.push(occurrence.current);
434
+ }
435
+ return {
436
+ occurrenceId: occurrence.current,
437
+ replacement,
438
+ replaceable
439
+ };
440
+ }
441
+ clearProvisionalStream(itemId) {
442
+ if (this.streamedPartialAssistantItemId === itemId && this.streamedPartialAssistantItemReplaceable) {
443
+ this.streamedPartialAssistantItemId = void 0;
444
+ const occurrence = this.occurrences.get(itemId);
445
+ return {
446
+ itemId,
447
+ occurrenceId: occurrence?.current ?? occurrence?.ids.at(-1),
448
+ text: "",
449
+ delta: "",
450
+ replace: true
451
+ };
452
+ }
453
+ }
454
+ collectOccurrenceIds(itemIds) {
455
+ return [...new Set(itemIds.flatMap((itemId) => this.occurrences.get(itemId)?.ids ?? []))];
456
+ }
457
+ isVisible(itemId) {
458
+ return this.visible.has(itemId);
459
+ }
460
+ recordCompletion(itemId) {
461
+ if (!this.completed.has(itemId)) this.completed.set(itemId, this.handoffGeneration);
462
+ }
463
+ isCompleted(itemId) {
464
+ return this.completed.has(itemId);
465
+ }
466
+ recordHandoff(itemId) {
467
+ if (itemId && this.handoffItems.has(itemId)) return false;
468
+ if (itemId) this.handoffItems.add(itemId);
469
+ this.handoffGeneration += 1;
470
+ return true;
471
+ }
472
+ survivesHandoff(itemId) {
473
+ const completedAt = this.completed.get(itemId);
474
+ return this.persisted.has(itemId) && (completedAt === void 0 || completedAt >= this.handoffGeneration);
475
+ }
476
+ remainingText(itemId, text) {
477
+ const prefix = this.persisted.get(itemId);
478
+ return prefix && text.startsWith(prefix.text) ? text.slice(prefix.text.length) : text;
479
+ }
480
+ capture(itemId, text, completed) {
481
+ if (text === void 0) return;
482
+ const remainder = this.remainingText(itemId, text);
483
+ if (!remainder.trim() || isSilentReplyPayloadText(remainder)) return;
484
+ const prefix = this.persisted.get(itemId);
485
+ const split = prefix !== void 0 || !completed;
486
+ const segment = prefix?.nextSegment ?? 0;
487
+ const mirrorItemId = split ? `${itemId}:segment:${segment}` : itemId;
488
+ const occurrence = this.occurrences.get(itemId);
489
+ const unownedIds = occurrence?.ids.slice(occurrence.ownedCount) ?? [];
490
+ const occurrenceIds = unownedIds.length ? unownedIds : this.receiptIds.get(mirrorItemId) ?? [];
491
+ this.receiptIds.set(mirrorItemId, occurrenceIds);
492
+ this.pending.set(mirrorItemId, {
493
+ itemId,
494
+ text,
495
+ completed,
496
+ split,
497
+ segment,
498
+ occurrenceCount: occurrence?.ids.length ?? 0
499
+ });
500
+ if (occurrence) delete occurrence.current;
501
+ return {
502
+ itemId: mirrorItemId,
503
+ text: remainder,
504
+ split,
505
+ occurrenceIds
506
+ };
507
+ }
508
+ consume(mirrorItemId) {
509
+ const prefix = this.pending.get(mirrorItemId);
510
+ if (!prefix) return;
511
+ this.pending.delete(mirrorItemId);
512
+ const occurrence = this.occurrences.get(prefix.itemId);
513
+ if (occurrence) occurrence.ownedCount = Math.max(occurrence.ownedCount, prefix.occurrenceCount);
514
+ if (prefix.split) this.persisted.set(prefix.itemId, {
515
+ text: prefix.text,
516
+ nextSegment: prefix.segment + 1
517
+ });
518
+ return {
519
+ itemId: prefix.itemId,
520
+ completed: prefix.completed
521
+ };
522
+ }
523
+ adoptCompletion(sourceId, itemId, text, sourceText) {
524
+ const pending = [...this.pending.values()].find((prefix) => prefix.itemId === sourceId);
525
+ const persisted = this.persisted.get(sourceId);
526
+ const prefix = pending?.text ?? persisted?.text ?? sourceText;
527
+ if (!prefix || !text.startsWith(prefix)) return false;
528
+ if (persisted) this.persisted.set(itemId, persisted);
529
+ const occurrence = this.occurrences.get(sourceId);
530
+ if (occurrence) this.occurrences.set(itemId, occurrence);
531
+ if (pending) pending.itemId = itemId;
532
+ this.visible.delete(sourceId);
533
+ return true;
534
+ }
535
+ };
536
+ //#endregion
355
537
  //#region extensions/codex/src/app-server/event-projector-assistant.ts
356
538
  var CodexAssistantProjection = class {
357
539
  constructor(params, emitAgentEvent, matchesToolProgressEcho, nextTranscriptTimestamp, checkpointCommentary) {
@@ -373,11 +555,9 @@ var CodexAssistantProjection = class {
373
555
  this.pendingRawCommentaryEchoes = 0;
374
556
  this.rawPromotedAssistantItemIds = /* @__PURE__ */ new Set();
375
557
  this.assistantStarted = false;
376
- this.streamedPartialAssistantItemReplaceable = false;
377
558
  this.persistableAssistantBarrier = 0;
378
559
  this.persistedAssistantBoundary = false;
379
- this.persistableAssistantBarrierItemIds = /* @__PURE__ */ new Set();
380
- this.completedAssistantItemIds = /* @__PURE__ */ new Set();
560
+ this.steeringSegments = new CodexSteeringAssistantSegments();
381
561
  }
382
562
  handleNotification(method, params) {
383
563
  if (method === "model/rerouted") this.responseModel = readStringField(params, "toModel") ?? this.responseModel;
@@ -408,12 +588,7 @@ var CodexAssistantProjection = class {
408
588
  }
409
589
  const knownFinalAnswer = this.isFinalAnswerAssistantItem(itemId);
410
590
  if (knownFinalAnswer) this.emitAnswerCandidate(itemId, "candidate");
411
- const replace = this.streamedPartialAssistantItemId !== void 0 && this.streamedPartialAssistantItemId !== itemId;
412
- if (replace && (!knownFinalAnswer || this.streamedPartialAssistantItemReplaceable)) this.streamedPartialAssistantItemReplaceable = true;
413
- else if (this.streamedPartialAssistantItemId === void 0) this.streamedPartialAssistantItemReplaceable = !knownFinalAnswer;
414
- this.streamedPartialAssistantItemId = itemId;
415
- const replaceable = this.streamedPartialAssistantItemReplaceable;
416
- const replacement = replace && replaceable;
591
+ const { occurrenceId, replacement, replaceable } = this.steeringSegments.recordStream(itemId, knownFinalAnswer);
417
592
  const streamPayload = {
418
593
  text,
419
594
  delta: replacement ? "" : delta,
@@ -423,6 +598,7 @@ var CodexAssistantProjection = class {
423
598
  stream: "assistant",
424
599
  data: {
425
600
  itemId,
601
+ occurrenceId,
426
602
  ...streamPayload,
427
603
  ...replaceable ? { replaceable: true } : {}
428
604
  }
@@ -443,46 +619,35 @@ var CodexAssistantProjection = class {
443
619
  delta: item.text
444
620
  });
445
621
  }
446
- /** Codex deltas are best-effort; completed item text is authoritative (codex-rs TUI agrees). */
447
- async streamCompletedItemTail(item) {
448
- const streamed = item?.type === "agentMessage" ? this.assistantTextByItem.get(item.id) : "";
449
- if (streamed && typeof item?.text === "string" && item.text.startsWith(streamed)) await this.handleAssistantDelta({
450
- itemId: item.id,
451
- delta: item.text.slice(streamed.length)
452
- });
453
- }
454
- recordItemCompleted(item, itemId, activeItemIds) {
455
- if (itemId && item?.type === "agentMessage") this.completedAssistantItemIds.add(itemId);
456
- this.noteNativeWorkBarrier(item);
622
+ recordItemCompleted(item, notification) {
623
+ this.adoptSteeringPrefixForCompletion(item);
624
+ if (item?.type === "agentMessage" && (!notification || notification.itemId)) this.steeringSegments.recordCompletion(notification?.itemId ?? item.id);
625
+ if (notification) this.noteNativeWorkBarrier(item);
457
626
  this.rememberAssistantPhase(item);
458
- if (item?.type === "agentMessage" && itemId && !this.isNonTerminalAssistantItem(itemId) && itemId !== this.pendingRawTerminalAssistantEchoItemId) this.pendingRawTerminalAssistantEchoItemId = void 0;
459
- if (item?.type === "agentMessage" && !this.isNonTerminalAssistantItem(item.id)) {
460
- this.markLatestTerminalAssistantCandidate(item.id, activeItemIds);
461
- this.pendingRawTerminalAssistantEchoItemId = item.id;
462
- } else if (itemId && !this.isNonTerminalAssistantItem(itemId)) {
463
- this.markTerminalAssistantCandidateSupersededBy(itemId, { preserveEarlierActiveItem: true });
464
- if (this.latestTerminalAssistantCandidateSuperseded) this.pendingRawTerminalAssistantEchoItemId = void 0;
627
+ if (notification) {
628
+ const { itemId, activeItemIds } = notification;
629
+ if (item?.type === "agentMessage" && itemId && !this.isNonTerminalAssistantItem(itemId) && itemId !== this.pendingRawTerminalAssistantEchoItemId) this.pendingRawTerminalAssistantEchoItemId = void 0;
630
+ if (item?.type === "agentMessage" && !this.isNonTerminalAssistantItem(item.id)) {
631
+ this.markLatestTerminalAssistantCandidate(item.id, activeItemIds);
632
+ this.pendingRawTerminalAssistantEchoItemId = item.id;
633
+ } else if (itemId && !this.isNonTerminalAssistantItem(itemId)) {
634
+ this.markTerminalAssistantCandidateSupersededBy(itemId, { preserveEarlierActiveItem: true });
635
+ if (this.latestTerminalAssistantCandidateSuperseded) this.pendingRawTerminalAssistantEchoItemId = void 0;
636
+ }
465
637
  }
466
638
  if (item?.type === "agentMessage" && typeof item.text === "string") {
467
639
  this.rememberAssistantItem(item.id);
468
640
  this.assistantTextByItem.set(item.id, item.text);
469
- if (this.isCommentaryAssistantItem(item.id)) {
470
- this.emitCommentaryProgress({
471
- itemId: item.id,
472
- text: item.text,
473
- phase: "end"
474
- });
475
- this.pendingRawCommentaryEchoes += 1;
476
- } else if (item.text && !this.isAsyncAssistantItem(item.id) && this.isFinalAnswerAssistantItem(item.id)) this.emitAnswerCandidate(item.id, "candidate");
477
- return this.createAsyncDelivery(item.id);
478
- }
479
- }
480
- recordSnapshotItem(item) {
481
- if (item.type === "agentMessage") this.completedAssistantItemIds.add(item.id);
482
- this.rememberAssistantPhase(item);
483
- if (item.type === "agentMessage" && typeof item.text === "string") {
484
- this.rememberAssistantItem(item.id);
485
- this.assistantTextByItem.set(item.id, item.text);
641
+ if (notification) {
642
+ if (this.isCommentaryAssistantItem(item.id)) {
643
+ this.emitCommentaryProgress({
644
+ itemId: item.id,
645
+ text: item.text,
646
+ phase: "end"
647
+ });
648
+ this.pendingRawCommentaryEchoes += 1;
649
+ } else if (item.text && !this.isAsyncAssistantItem(item.id) && this.isFinalAnswerAssistantItem(item.id)) this.emitAnswerCandidate(item.id, "candidate");
650
+ }
486
651
  return this.createAsyncDelivery(item.id);
487
652
  }
488
653
  }
@@ -504,13 +669,19 @@ var CodexAssistantProjection = class {
504
669
  this.pendingRawTerminalAssistantEchoItemId = void 0;
505
670
  return;
506
671
  }
507
- const text = extractRawAssistantText(item);
672
+ const text = extractRawResponseItemText(item);
508
673
  if (text === void 0 || !text && (phase === "commentary" || activeItemIds.size > 0 || readStringField(item, "type") !== "message")) return;
509
674
  const itemId = rawItemId ?? `raw-assistant-${this.assistantItemOrder.length + 1}`;
510
675
  const isIdlessTerminalAssistantAfterCompletedWork = candidateWasSupersededBeforeRaw && rawItemId === void 0 && pendingTerminalAssistantEchoItemId === void 0 && activeItemIds.size === 0;
511
- if (text && phase !== "commentary" && candidateWasSupersededBeforeRaw && itemId !== this.streamedPartialAssistantItemId && !isIdlessTerminalAssistantAfterCompletedWork) return;
676
+ if (text && phase !== "commentary" && candidateWasSupersededBeforeRaw && itemId !== this.steeringSegments.streamedPartialAssistantItemId && !isIdlessTerminalAssistantAfterCompletedWork) return;
677
+ this.adoptSteeringPrefixForCompletion({
678
+ ...item,
679
+ type: "agentMessage",
680
+ id: itemId,
681
+ text
682
+ });
512
683
  if (phase) this.assistantPhaseByItem.set(itemId, phase);
513
- this.completedAssistantItemIds.add(itemId);
684
+ this.steeringSegments.recordCompletion(itemId);
514
685
  this.rememberAssistantItem(itemId);
515
686
  this.assistantTextByItem.set(itemId, text);
516
687
  if (!text) return;
@@ -542,6 +713,9 @@ var CodexAssistantProjection = class {
542
713
  }] : [];
543
714
  });
544
715
  }
716
+ collectTerminalAssistantItemIds() {
717
+ return this.steeringSegments.collectOccurrenceIds(this.assistantItemOrder.filter((itemId) => !this.isNonTerminalAssistantItem(itemId)));
718
+ }
545
719
  readCommentaryMessage(itemId) {
546
720
  const text = this.assistantTextByItem.get(itemId)?.trim();
547
721
  const timestamp = this.assistantTimestampByItem.get(itemId);
@@ -556,34 +730,37 @@ var CodexAssistantProjection = class {
556
730
  }] : [];
557
731
  });
558
732
  }
559
- collectCompletedAssistantMessages(completedItemIds, options) {
733
+ collectSteeringAssistantMessages(completedItemIds, options) {
734
+ this.steeringSegments.beginSnapshot();
560
735
  return this.assistantItemOrder.flatMap((itemId) => {
561
- const text = this.assistantTextByItem.get(itemId)?.trim();
562
- if (!completedItemIds.has(itemId) || this.isNonTerminalAssistantItem(itemId) || !text || isSilentReplyPayloadText(text) || this.isToolProgressEchoText(itemId, text)) return [];
563
- const message = this.createAssistantMessage(text, options);
564
- const timestamp = this.assistantTimestampByItem.get(itemId) ?? message.timestamp;
736
+ const sourceText = this.assistantTextByItem.get(itemId);
737
+ const completed = completedItemIds.has(itemId);
738
+ if (!completed && !this.steeringSegments.isVisible(itemId) || this.isNonTerminalAssistantItem(itemId) || sourceText && this.isToolProgressEchoText(itemId, sourceText.trim())) return [];
739
+ const segment = this.steeringSegments.capture(itemId, sourceText, completed);
740
+ if (!segment) return [];
741
+ const message = attachCodexAssistantItemIds(this.createAssistantMessage(segment.text, options), segment.occurrenceIds);
742
+ message.timestamp = segment.split ? this.nextTranscriptTimestamp() : this.assistantTimestampByItem.get(itemId) ?? message.timestamp;
565
743
  return [{
566
- itemId,
567
- message: {
568
- ...message,
569
- timestamp
570
- }
744
+ itemId: segment.itemId,
745
+ message
571
746
  }];
572
747
  });
573
748
  }
574
- markAssistantBoundaryPersisted(itemId) {
575
- const index = this.assistantItemOrder.indexOf(itemId);
576
- if (index >= 0) {
749
+ markSteeringMessagePersisted(mirrorItemId) {
750
+ const prefix = this.steeringSegments.consume(mirrorItemId);
751
+ if (!prefix) return;
752
+ if (prefix.completed) {
753
+ const index = this.assistantItemOrder.indexOf(prefix.itemId);
577
754
  this.persistableAssistantBarrier = Math.max(this.persistableAssistantBarrier, index + 1);
578
- this.persistedAssistantBoundary = true;
579
755
  }
756
+ this.persistedAssistantBoundary = true;
580
757
  }
581
758
  finalizeAnswerCandidate(turn) {
582
759
  if (turn.status !== "completed") {
583
760
  this.supersedeVisibleAnswerCandidate();
584
761
  return;
585
762
  }
586
- for (const itemId of this.assistantItemOrder) if (!this.completedAssistantItemIds.has(itemId) && !this.isAsyncAssistantItem(itemId) && (this.isFinalAnswerAssistantItem(itemId) || this.isCommentaryAssistantItem(itemId))) {
763
+ for (const itemId of this.assistantItemOrder) if (!this.steeringSegments.isCompleted(itemId) && !this.isAsyncAssistantItem(itemId) && (this.isFinalAnswerAssistantItem(itemId) || this.isCommentaryAssistantItem(itemId))) {
587
764
  if (itemId === this.visibleAnswerCandidateItemId) this.supersedeVisibleAnswerCandidate();
588
765
  this.assistantTextByItem.delete(itemId);
589
766
  }
@@ -607,13 +784,13 @@ var CodexAssistantProjection = class {
607
784
  this.emitAnswerCandidate(itemId, "selected");
608
785
  }
609
786
  hasAssistantItemTextForSynthesis() {
610
- return this.assistantItemOrder.some((itemId) => Boolean(itemId) && !this.isNonTerminalAssistantItem(itemId) && Boolean(this.assistantTextByItem.get(itemId)));
787
+ return this.assistantItemOrder.some((itemId) => !this.isNonTerminalAssistantItem(itemId) && Boolean(this.assistantTextByItem.get(itemId)));
611
788
  }
612
789
  createCurrentAttemptAssistantMessage(options) {
613
790
  for (let i = this.assistantItemOrder.length - 1; i >= 0; i -= 1) {
614
791
  const itemId = this.assistantItemOrder[i];
615
792
  if (!itemId || this.isNonTerminalAssistantItem(itemId) || !this.assistantTextByItem.has(itemId)) continue;
616
- const text = this.assistantTextByItem.get(itemId) ?? "";
793
+ const text = this.remainingAssistantText(itemId) ?? "";
617
794
  const normalizedText = text.trim();
618
795
  if (normalizedText && this.isToolProgressEchoText(itemId, normalizedText)) continue;
619
796
  return this.createAssistantMessage(text, options);
@@ -626,6 +803,19 @@ var CodexAssistantProjection = class {
626
803
  responseModel: this.responseModel
627
804
  } : message;
628
805
  }
806
+ remainingAssistantText(itemId) {
807
+ const text = this.assistantTextByItem.get(itemId);
808
+ return text === void 0 ? void 0 : this.steeringSegments.remainingText(itemId, text);
809
+ }
810
+ adoptSteeringPrefixForCompletion(item) {
811
+ const sourceId = this.steeringSegments.streamedPartialAssistantItemId;
812
+ if (item?.type !== "agentMessage" || !sourceId || item.id === sourceId || this.steeringSegments.isCompleted(sourceId) || this.assistantTimestampByItem.has(item.id) || this.isNonTerminalAssistantItem(sourceId) || item.delivery === "async" || item.phase !== void 0 && item.phase !== this.assistantPhaseByItem.get(sourceId)) return;
813
+ const sourceText = this.assistantTextByItem.get(sourceId);
814
+ if (!this.steeringSegments.adoptCompletion(sourceId, item.id, item.text, sourceText)) return;
815
+ if (this.visibleAnswerCandidateItemId === sourceId) this.supersedeVisibleAnswerCandidate();
816
+ this.assistantTextByItem.delete(sourceId);
817
+ this.steeringSegments.streamedPartialAssistantItemId = item.id;
818
+ }
629
819
  rememberAssistantPhase(item) {
630
820
  if (item?.type !== "agentMessage") return;
631
821
  const phase = readStringField(item, "phase");
@@ -651,9 +841,14 @@ var CodexAssistantProjection = class {
651
841
  return this.assistantPhaseByItem.get(itemId) === "final_answer";
652
842
  }
653
843
  emitCommentaryProgress(params) {
654
- const progressText = params.text.trim();
844
+ const cleared = this.steeringSegments.clearProvisionalStream(params.itemId);
845
+ if (cleared) this.emitAgentEvent({
846
+ stream: "assistant",
847
+ data: cleared
848
+ });
849
+ const progressText = params.text.trimEnd();
655
850
  const previous = this.lastCommentaryProgressEventByItem.get(params.itemId);
656
- if (!progressText || previous?.phase === params.phase && previous.text === progressText) return;
851
+ if (!progressText.trim() || previous?.phase === params.phase && previous.text === progressText) return;
657
852
  this.lastCommentaryProgressEventByItem.set(params.itemId, {
658
853
  phase: params.phase,
659
854
  text: progressText
@@ -719,21 +914,19 @@ var CodexAssistantProjection = class {
719
914
  this.supersedeVisibleAnswerCandidate();
720
915
  }
721
916
  resolveFinalAssistantText() {
722
- for (let i = this.assistantItemOrder.length - 1; i >= 0; i -= 1) {
723
- const itemId = this.assistantItemOrder[i];
724
- if (!itemId) continue;
725
- const text = this.assistantTextByItem.get(itemId)?.trim();
726
- if (this.isNonTerminalAssistantItem(itemId)) continue;
727
- if (text && !this.isToolProgressEchoText(itemId, text)) return text;
728
- }
917
+ const selectedId = this.assistantItemOrder.findLast((itemId) => {
918
+ const text = this.remainingAssistantText(itemId)?.trim();
919
+ return Boolean(text && !this.isNonTerminalAssistantItem(itemId) && !this.isToolProgressEchoText(itemId, text));
920
+ });
921
+ return selectedId ? this.remainingAssistantText(selectedId)?.trim() : void 0;
729
922
  }
730
923
  collectPersistableAssistantTexts(minIndex) {
731
924
  let texts = [];
732
925
  let replaceable = false;
733
- for (let index = minIndex; index < this.assistantItemOrder.length; index += 1) {
926
+ for (let index = 0; index < this.assistantItemOrder.length; index += 1) {
734
927
  const itemId = this.assistantItemOrder[index];
735
- if (!itemId || this.isNonTerminalAssistantItem(itemId)) continue;
736
- const text = this.assistantTextByItem.get(itemId)?.trim();
928
+ if (!itemId || this.isNonTerminalAssistantItem(itemId) || index < minIndex && !this.steeringSegments.survivesHandoff(itemId)) continue;
929
+ const text = this.remainingAssistantText(itemId)?.trim();
737
930
  if (!text || this.isToolProgressEchoText(itemId, text)) continue;
738
931
  if (isSilentReplyPayloadText(text)) {
739
932
  texts.push(text);
@@ -750,10 +943,7 @@ var CodexAssistantProjection = class {
750
943
  return texts;
751
944
  }
752
945
  noteNativeWorkBarrier(item) {
753
- if (!item || !shouldAdvancePersistableAssistantBarrier(item)) return;
754
- if (item.id && this.persistableAssistantBarrierItemIds.has(item.id)) return;
755
- if (item.id) this.persistableAssistantBarrierItemIds.add(item.id);
756
- this.persistableAssistantBarrier = this.assistantItemOrder.length;
946
+ if (item && shouldAdvancePersistableAssistantBarrier(item) && this.steeringSegments.recordHandoff(item.id)) this.persistableAssistantBarrier = this.assistantItemOrder.length;
757
947
  }
758
948
  rememberAssistantItem(itemId) {
759
949
  if (!itemId) return;
@@ -763,7 +953,7 @@ var CodexAssistantProjection = class {
763
953
  }
764
954
  if (this.isCommentaryAssistantItem(itemId)) this.checkpointCommentary?.(itemId, {
765
955
  read: () => this.readCommentaryMessage(itemId),
766
- ready: () => this.completedAssistantItemIds.has(itemId)
956
+ ready: () => this.steeringSegments.isCompleted(itemId)
767
957
  });
768
958
  }
769
959
  createAsyncDelivery(itemId) {
@@ -781,9 +971,6 @@ var CodexAssistantProjection = class {
781
971
  return this.rawPromotedAssistantItemIds.has(itemId) && this.matchesToolProgressEcho(text);
782
972
  }
783
973
  };
784
- function shouldAdvancePersistableAssistantBarrier(item) {
785
- return shouldClearTerminalPresentationForNativeItem(item) || item.type === "dynamicToolCall" || item.type === "sleep";
786
- }
787
974
  //#endregion
788
975
  //#region extensions/codex/src/app-server/event-projector-async-delivery.ts
789
976
  /** Owns authorization, exactly-once settlement, and terminal retry for async user messages. */
@@ -1106,29 +1293,9 @@ function normalizePlanStepStatus(status) {
1106
1293
  return status === "completed" ? "completed" : "pending";
1107
1294
  }
1108
1295
  function readReasoningSections(value) {
1109
- const sections = /* @__PURE__ */ new Map();
1110
- if (Array.isArray(value)) value.forEach((text, index) => {
1111
- if (typeof text === "string") sections.set(index, text);
1112
- });
1113
- return sections;
1296
+ return new Map(Array.isArray(value) ? value.flatMap((text, index) => typeof text === "string" ? [[index, text]] : []) : []);
1114
1297
  }
1115
1298
  //#endregion
1116
- //#region extensions/codex/src/app-server/event-projector-settlement.ts
1117
- var CodexProjectionSettlement = class extends AgentHarnessProjectionSettlement {
1118
- constructor(params, isActive) {
1119
- super(params, isActive, { label: "codex app-server" });
1120
- this.turnTainted = false;
1121
- }
1122
- get completedAnswer() {
1123
- const turn = this.terminalReceipt;
1124
- const answer = turn?.items?.findLast((item) => item.type === "agentMessage" && item.phase !== "commentary" && item.delivery !== "async" && typeof item.text === "string" && item.text.trim().length > 0);
1125
- return turn?.status === "completed" && answer ? {
1126
- turn,
1127
- answer
1128
- } : void 0;
1129
- }
1130
- };
1131
- //#endregion
1132
1299
  //#region extensions/codex/src/app-server/event-projector-snapshot.ts
1133
1300
  function buildCodexMessagesSnapshot(params) {
1134
1301
  const messages = promptSnapshot(params.runParams, params.turnId, params.upstreamUserText);
@@ -1157,45 +1324,24 @@ function buildCodexMessagesSnapshot(params) {
1157
1324
  function buildCodexSteeringMessagesSnapshot(params) {
1158
1325
  const asyncMessages = params.assistantProjection.collectAsyncMessages().filter(({ itemId }) => params.completedItemIds.has(itemId));
1159
1326
  const commentaryMessages = params.assistantProjection.collectCommentaryMessages().filter(({ itemId }) => params.completedItemIds.has(itemId));
1160
- const assistantMessages = params.assistantProjection.collectCompletedAssistantMessages(params.completedItemIds, {
1327
+ const assistantMessages = params.assistantProjection.collectSteeringAssistantMessages(params.completedItemIds, {
1161
1328
  tokenUsage: void 0,
1162
1329
  aborted: false,
1163
1330
  promptError: void 0
1164
1331
  });
1165
- return {
1166
- messages: buildCodexMessagesSnapshot({
1167
- runParams: params.runParams,
1168
- turnId: params.turnId,
1169
- upstreamUserText: params.upstreamUserText,
1170
- reasoningText: void 0,
1171
- asyncMessages,
1172
- commentaryMessages,
1173
- assistantMessages,
1174
- toolMessages: params.toolMessages,
1175
- lastAssistant: void 0
1176
- }).filter((message) => message.role !== "user"),
1177
- assistantBoundaryItemId: assistantMessages.at(-1)?.itemId
1178
- };
1332
+ return buildCodexMessagesSnapshot({
1333
+ runParams: params.runParams,
1334
+ turnId: params.turnId,
1335
+ upstreamUserText: params.upstreamUserText,
1336
+ reasoningText: void 0,
1337
+ asyncMessages,
1338
+ commentaryMessages,
1339
+ assistantMessages,
1340
+ toolMessages: params.toolMessages,
1341
+ lastAssistant: void 0
1342
+ }).filter((message) => message.role !== "user");
1179
1343
  }
1180
1344
  //#endregion
1181
- //#region extensions/codex/src/app-server/event-projector-terminal-failure.ts
1182
- var CodexTerminalFailureProjection = class {
1183
- constructor() {
1184
- this.promptErrorSource = null;
1185
- }
1186
- record(params) {
1187
- const refusal = readCodexProviderRefusal(params.message, params.codexErrorInfo, params);
1188
- if (!this.providerRefusal || refusal?.category === "misalignment" && this.providerRefusal.category === "misalignment" && params.misalignment != null) this.providerRefusal = refusal;
1189
- if (this.providerRefusal) return;
1190
- this.promptError = resolveCodexPromptError({
1191
- message: params.message,
1192
- codexErrorInfo: params.codexErrorInfo,
1193
- rateLimits: params.rateLimits
1194
- }) ?? params.fallbackMessage;
1195
- this.promptErrorSource = params.promptErrorSource;
1196
- }
1197
- };
1198
- //#endregion
1199
1345
  //#region extensions/codex/src/app-server/event-projector-tool-search-evidence.ts
1200
1346
  const MAX_RETAINED_SEARCHES = 16;
1201
1347
  const MAX_RETAINED_DYNAMIC_CALLS = 32;
@@ -1203,17 +1349,7 @@ const MAX_DISCOVERED_TOOLS = 32;
1203
1349
  const MAX_ID_CHARS = 256;
1204
1350
  const MAX_NAME_CHARS = 128;
1205
1351
  function readBoundedString(value, maxChars) {
1206
- if (typeof value !== "string") return;
1207
- const normalized = value.trim();
1208
- if (!normalized) return;
1209
- return normalized.slice(0, maxChars);
1210
- }
1211
- function trimOldest(map, maxSize) {
1212
- while (map.size > maxSize) {
1213
- const oldest = map.keys().next().value;
1214
- if (oldest === void 0) return;
1215
- map.delete(oldest);
1216
- }
1352
+ return normalizeOptionalString(value)?.slice(0, maxChars);
1217
1353
  }
1218
1354
  function collectToolRefs(values, output, seen, inheritedNamespace) {
1219
1355
  if (!Array.isArray(values)) return false;
@@ -1264,7 +1400,7 @@ var CodexToolSearchEvidenceProjection = class {
1264
1400
  ...execution ? { execution } : {},
1265
1401
  ...status ? { status } : {}
1266
1402
  });
1267
- trimOldest(this.calls, MAX_RETAINED_SEARCHES);
1403
+ pruneMapToMaxSize(this.calls, MAX_RETAINED_SEARCHES);
1268
1404
  return;
1269
1405
  }
1270
1406
  if (type !== "tool_search_output") return;
@@ -1281,7 +1417,7 @@ var CodexToolSearchEvidenceProjection = class {
1281
1417
  tools,
1282
1418
  truncated
1283
1419
  });
1284
- trimOldest(this.outputs, MAX_RETAINED_SEARCHES);
1420
+ pruneMapToMaxSize(this.outputs, MAX_RETAINED_SEARCHES);
1285
1421
  }
1286
1422
  recordDynamicToolCall(params) {
1287
1423
  const callId = readBoundedString(params.callId, MAX_ID_CHARS);
@@ -1295,7 +1431,7 @@ var CodexToolSearchEvidenceProjection = class {
1295
1431
  namespace: requestedNamespace,
1296
1432
  tool
1297
1433
  });
1298
- trimOldest(this.dynamicCalls, MAX_RETAINED_DYNAMIC_CALLS);
1434
+ pruneMapToMaxSize(this.dynamicCalls, MAX_RETAINED_DYNAMIC_CALLS);
1299
1435
  }
1300
1436
  recordDynamicToolResult(params) {
1301
1437
  const callId = readBoundedString(params.callId, MAX_ID_CHARS);
@@ -1338,8 +1474,7 @@ var CodexTranscriptCheckpoint = class {
1338
1474
  this.lastTimestamp = 0;
1339
1475
  this.writing = Promise.resolve();
1340
1476
  this.tainted = false;
1341
- this.closed = false;
1342
- this.abandoned = false;
1477
+ this.state = "open";
1343
1478
  this.nextTimestamp = () => {
1344
1479
  this.lastTimestamp = Math.max(Date.now(), this.lastTimestamp + 1);
1345
1480
  return this.lastTimestamp;
@@ -1356,16 +1491,16 @@ var CodexTranscriptCheckpoint = class {
1356
1491
  });
1357
1492
  };
1358
1493
  this.enqueue = (entry) => {
1359
- if (this.params.sessionTarget && !this.closed) this.pending.push(entry);
1494
+ if (this.params.sessionTarget && this.state === "open") this.pending.push(entry);
1360
1495
  };
1361
1496
  }
1362
1497
  abandon() {
1363
- this.closed = this.abandoned = true;
1498
+ this.state = "abandoned";
1364
1499
  this.pending.length = 0;
1365
1500
  }
1366
1501
  flush(close = false) {
1367
- if (this.closed) return this.writing;
1368
- this.closed = close;
1502
+ if (this.state !== "open") return this.writing;
1503
+ this.state = close ? "closed" : "open";
1369
1504
  this.writing = this.writing.then(async () => {
1370
1505
  const blocked = close ? -1 : this.pending.findIndex((entry) => entry.ready?.() === false);
1371
1506
  const count = blocked < 0 ? this.pending.length : blocked;
@@ -1381,9 +1516,9 @@ var CodexTranscriptCheckpoint = class {
1381
1516
  });
1382
1517
  try {
1383
1518
  await codexTranscriptMirrorRuntime.mirror({
1384
- assertWriteCurrent: () => {
1385
- if (this.abandoned) throw new Error("Codex transcript checkpoint was retired before write");
1386
- },
1519
+ assertWriteCurrent: createNativeSessionBindingAuthority([], () => {
1520
+ if (this.state === "abandoned") throw new Error("Codex transcript checkpoint was retired before write");
1521
+ }).assertLegacyCurrent,
1387
1522
  ...this.params.sessionTarget,
1388
1523
  sessionId: this.params.sessionId,
1389
1524
  cwd: this.params.workspaceDir,
@@ -1408,6 +1543,20 @@ var CodexTranscriptCheckpoint = class {
1408
1543
  };
1409
1544
  //#endregion
1410
1545
  //#region extensions/codex/src/app-server/event-projector-result.ts
1546
+ var CodexProjectionSettlement = class extends AgentHarnessProjectionSettlement {
1547
+ constructor(params, isActive) {
1548
+ super(params, isActive, { label: "codex app-server" });
1549
+ this.turnTainted = false;
1550
+ }
1551
+ get completedAnswer() {
1552
+ const turn = this.terminalReceipt;
1553
+ const answer = turn?.items?.findLast((item) => item.type === "agentMessage" && item.phase !== "commentary" && item.delivery !== "async" && typeof item.text === "string" && item.text.trim().length > 0);
1554
+ return turn?.status === "completed" && answer ? {
1555
+ turn,
1556
+ answer
1557
+ } : void 0;
1558
+ }
1559
+ };
1411
1560
  /** Owns per-turn projection state and builds results from the same state. */
1412
1561
  var CodexTurnProjection = class {
1413
1562
  constructor(params, threadId, turnId, options = {}) {
@@ -1421,7 +1570,7 @@ var CodexTurnProjection = class {
1421
1570
  this.activeCompactionItemIds = /* @__PURE__ */ new Set();
1422
1571
  this.projectionController = new AbortController();
1423
1572
  this.settledTurnFailureFinalizationAllowed = false;
1424
- this.terminalFailure = new CodexTerminalFailureProjection();
1573
+ this.promptErrorSource = null;
1425
1574
  this.synthesizedMissingToolResultError = null;
1426
1575
  this.aborted = false;
1427
1576
  this.usageProjection = new CodexUsageProjection();
@@ -1456,8 +1605,7 @@ var CodexTurnProjection = class {
1456
1605
  }
1457
1606
  buildResult(toolTelemetry, options) {
1458
1607
  this.eventProjection.flushPendingGuardianWarning();
1459
- const { params: runParams, turnId, completedTurn, aborted, contextTokens, contextTokensSource, completedCompactionCount, synthesizedMissingToolResultError: previousMissingToolResultError } = this;
1460
- const { promptError: initialPromptError, promptErrorSource: initialPromptErrorSource, providerRefusal } = this.terminalFailure;
1608
+ const { params: runParams, turnId, completedTurn, aborted, contextTokens, contextTokensSource, completedCompactionCount, synthesizedMissingToolResultError: previousMissingToolResultError, promptError: initialPromptError, promptErrorSource: initialPromptErrorSource, providerRefusal } = this;
1461
1609
  const upstreamUserText = this.options.upstreamUserText;
1462
1610
  const turnTainted = this.settlement.turnTainted;
1463
1611
  const observedItemCount = (/* @__PURE__ */ new Set([...this.observedItemIds, ...this.completedItemIds])).size;
@@ -1512,7 +1660,7 @@ var CodexTurnProjection = class {
1512
1660
  commentaryMessages,
1513
1661
  toolMessages: this.toolTranscriptProjection.transcriptMessages,
1514
1662
  steeringMessages: options?.steeringMessages,
1515
- lastAssistant,
1663
+ lastAssistant: lastAssistant ? attachCodexAssistantItemIds(lastAssistant, this.assistantProjection.collectTerminalAssistantItemIds()) : void 0,
1516
1664
  turnTainted
1517
1665
  });
1518
1666
  const turnFailed = completedTurn?.status === "failed";
@@ -1578,6 +1726,17 @@ var CodexTurnProjection = class {
1578
1726
  for (const toolResult of toolTelemetry.coreTtsToolResults ?? []) transferTtsProvenance?.(toolResult, result, toolAutoDeliveryMediaUrls ?? []);
1579
1727
  return result;
1580
1728
  }
1729
+ recordTerminalFailure(params) {
1730
+ const refusal = readCodexProviderRefusal(params.message, params.codexErrorInfo, params);
1731
+ if (!this.providerRefusal || refusal?.category === "misalignment" && this.providerRefusal.category === "misalignment" && params.misalignment != null) this.providerRefusal = refusal;
1732
+ if (this.providerRefusal) return;
1733
+ this.promptError = resolveCodexPromptError({
1734
+ message: params.message,
1735
+ codexErrorInfo: params.codexErrorInfo,
1736
+ rateLimits: params.rateLimits
1737
+ }) ?? params.fallbackMessage;
1738
+ this.promptErrorSource = params.promptErrorSource;
1739
+ }
1581
1740
  emitAgentEvent(event) {
1582
1741
  if (!this.projectionClosed) emitCodexAgentEvent(this.params, event);
1583
1742
  }
@@ -1594,17 +1753,17 @@ var CodexAppServerEventProjector = class extends CodexTurnProjection {
1594
1753
  return this.completedTurn?.status;
1595
1754
  }
1596
1755
  getPendingNativeCommands() {
1597
- return !this.projectionClosed && !this.aborted && !this.options.runAbortSignal?.aborted && this.completedTurn?.status === "completed" && !this.terminalFailure.promptError ? this.nativeToolLifecycleProjector.pendingCommands() : /* @__PURE__ */ new Map();
1756
+ return !this.projectionClosed && !this.aborted && !this.options.runAbortSignal?.aborted && this.completedTurn?.status === "completed" && !this.promptError ? this.nativeToolLifecycleProjector.pendingCommands() : /* @__PURE__ */ new Map();
1598
1757
  }
1599
1758
  /** Native completion owns the answer independently of unfinished host projection. */
1600
1759
  recoverCompletedAnswer() {
1601
1760
  const completed = this.settlement.completedAnswer;
1602
- if (!completed || this.aborted || this.terminalFailure.promptError) return false;
1761
+ if (!completed || this.aborted || this.promptError) return false;
1603
1762
  this.closeCompactionProgress();
1604
1763
  this.projectionController.abort();
1605
1764
  this.transcriptCheckpoint.abandon();
1606
1765
  this.completedTurn = completed.turn;
1607
- this.assistantProjection.recordSnapshotItem(completed.answer);
1766
+ this.assistantProjection.recordItemCompleted(completed.answer);
1608
1767
  this.assistantProjection.finalizeAnswerCandidate(completed.turn);
1609
1768
  return true;
1610
1769
  }
@@ -1616,7 +1775,7 @@ var CodexAppServerEventProjector = class extends CodexTurnProjection {
1616
1775
  if (!this.projectionClosed) this.nativeToolLifecycleProjector.recordMcpToolCallReceipt(notification);
1617
1776
  }
1618
1777
  buildSteeringTranscriptPrefix() {
1619
- const snapshot = buildCodexSteeringMessagesSnapshot({
1778
+ return buildCodexSteeringMessagesSnapshot({
1620
1779
  runParams: this.params,
1621
1780
  turnId: this.turnId,
1622
1781
  upstreamUserText: this.options.upstreamUserText,
@@ -1624,15 +1783,10 @@ var CodexAppServerEventProjector = class extends CodexTurnProjection {
1624
1783
  assistantProjection: this.assistantProjection,
1625
1784
  toolMessages: this.toolTranscriptProjection.transcriptMessages
1626
1785
  });
1627
- this.pendingSteeringAssistantBoundaryItemId = snapshot.assistantBoundaryItemId;
1628
- return snapshot.messages;
1629
1786
  }
1630
- markSteeringTranscriptPersisted() {
1631
- const itemId = this.pendingSteeringAssistantBoundaryItemId;
1632
- if (itemId) {
1633
- this.assistantProjection.markAssistantBoundaryPersisted(itemId);
1634
- this.pendingSteeringAssistantBoundaryItemId = void 0;
1635
- }
1787
+ markSteeringTranscriptMessagePersisted(mirrorIdentity) {
1788
+ const prefix = `${this.turnId}:assistant:`;
1789
+ if (mirrorIdentity.startsWith(prefix)) this.assistantProjection.markSteeringMessagePersisted(mirrorIdentity.slice(prefix.length));
1636
1790
  }
1637
1791
  /** Fence delayed projections before the turn's final snapshot leaves its owner. */
1638
1792
  closeProjection() {
@@ -1743,7 +1897,7 @@ var CodexAppServerEventProjector = class extends CodexTurnProjection {
1743
1897
  this.eventProjection.handleCyberPolicyError(codexErrorInfo, this.params.modelId);
1744
1898
  const compactionFailure = codexErrorInfo === "other" && this.isCompacting();
1745
1899
  this.settledTurnFailureFinalizationAllowed = codexErrorInfo === "serverOverloaded" || compactionFailure;
1746
- this.terminalFailure.record({
1900
+ this.recordTerminalFailure({
1747
1901
  message: readCodexErrorNotificationMessage(params),
1748
1902
  codexErrorInfo,
1749
1903
  misalignment: isJsonObject(params.error) ? params.error.misalignment : void 0,
@@ -1811,8 +1965,8 @@ var CodexAppServerEventProjector = class extends CodexTurnProjection {
1811
1965
  }
1812
1966
  markTimedOut() {
1813
1967
  this.aborted = true;
1814
- this.terminalFailure.promptError = "codex app-server attempt timed out";
1815
- this.terminalFailure.promptErrorSource = "prompt";
1968
+ this.promptError = "codex app-server attempt timed out";
1969
+ this.promptErrorSource = "prompt";
1816
1970
  }
1817
1971
  markAborted() {
1818
1972
  this.aborted = true;
@@ -1908,12 +2062,7 @@ var CodexAppServerEventProjector = class extends CodexTurnProjection {
1908
2062
  this.completedCompactionCount += 1;
1909
2063
  }
1910
2064
  if (!this.asyncDeliveryProjection.allows(item, true)) return;
1911
- await this.assistantProjection.streamCompletedItemTail(item);
1912
- const asyncMessage = this.assistantProjection.recordItemCompleted(item, itemId, this.activeItemIds);
1913
- if (asyncMessage) await this.asyncDeliveryProjection.deliver(asyncMessage);
1914
- if (this.projectionClosed) return;
1915
- await this.reasoningProjection.recordItem(item);
1916
- await this.settlement.project("media_projection", () => this.generatedMediaProjection.recordNative(item));
2065
+ await this.recordCompletedItemContent(item, { itemId });
1917
2066
  if (this.projectionClosed) return;
1918
2067
  if (item?.type === "contextCompaction" && itemId) {
1919
2068
  if (!this.isCompactionProjectionActive()) return;
@@ -1972,13 +2121,13 @@ var CodexAppServerEventProjector = class extends CodexTurnProjection {
1972
2121
  if (!turn || turn.id !== this.turnId) return;
1973
2122
  this.completedTurn = turn;
1974
2123
  this.eventProjection.endSafetyBuffering();
1975
- const compactionFailure = turn.status === "failed" && (this.terminalFailure.promptErrorSource === "compaction" || turn.error?.codexErrorInfo === "other" && this.isCompacting());
2124
+ const compactionFailure = turn.status === "failed" && (this.promptErrorSource === "compaction" || turn.error?.codexErrorInfo === "other" && this.isCompacting());
1976
2125
  this.settledTurnFailureFinalizationAllowed = turn.status === "failed" && (turn.error?.codexErrorInfo === "serverOverloaded" || compactionFailure);
1977
2126
  if (turn.status !== "completed") this.usageProjection.invalidateContext();
1978
2127
  if (turn.status === "failed") {
1979
2128
  const codexErrorInfo = turn.error?.codexErrorInfo;
1980
2129
  this.eventProjection.handleCyberPolicyError(codexErrorInfo, this.params.modelId);
1981
- this.terminalFailure.record({
2130
+ this.recordTerminalFailure({
1982
2131
  message: turn.error?.message,
1983
2132
  codexErrorInfo,
1984
2133
  misalignment: turn.error?.misalignment,
@@ -1997,12 +2146,7 @@ var CodexAppServerEventProjector = class extends CodexTurnProjection {
1997
2146
  for (const item of turnItems) {
1998
2147
  if (!this.asyncDeliveryProjection.allows(item)) continue;
1999
2148
  this.diagnostics.warnUnknownItemStatus(item);
2000
- await this.assistantProjection.streamCompletedItemTail(item);
2001
- const asyncMessage = this.assistantProjection.recordSnapshotItem(item);
2002
- if (asyncMessage) await this.asyncDeliveryProjection.deliver(asyncMessage);
2003
- if (this.projectionClosed) return;
2004
- await this.reasoningProjection.recordItem(item);
2005
- await this.settlement.project("media_projection", () => this.generatedMediaProjection.recordNative(item));
2149
+ await this.recordCompletedItemContent(item);
2006
2150
  if (this.projectionClosed) return;
2007
2151
  this.toolProgressProjection.recordToolMeta(item);
2008
2152
  this.toolProgressProjection.rememberCommandAggregateOutputEcho(item);
@@ -2030,10 +2174,20 @@ var CodexAppServerEventProjector = class extends CodexTurnProjection {
2030
2174
  this.assistantProjection.finalizeAnswerCandidate(turn);
2031
2175
  await this.reasoningProjection.maybeEndReasoning();
2032
2176
  }
2177
+ async recordCompletedItemContent(item, notification) {
2178
+ const asyncMessage = this.assistantProjection.recordItemCompleted(item, notification && {
2179
+ ...notification,
2180
+ activeItemIds: this.activeItemIds
2181
+ });
2182
+ if (asyncMessage) await this.asyncDeliveryProjection.deliver(asyncMessage);
2183
+ if (this.projectionClosed) return;
2184
+ await this.reasoningProjection.recordItem(item);
2185
+ await this.settlement.project("media_projection", () => this.generatedMediaProjection.recordNative(item));
2186
+ }
2033
2187
  async handleRawResponseItemCompleted(params) {
2034
2188
  const item = isJsonObject(params.item) ? params.item : void 0;
2035
2189
  if (!item) return;
2036
- if (item.role === "assistant" && extractRawAssistantText(item)) this.eventProjection.markSafetyBufferingAssistantStarted();
2190
+ if (item.role === "assistant" && extractRawResponseItemText(item)) this.eventProjection.markSafetyBufferingAssistantStarted();
2037
2191
  this.toolSearchEvidenceProjection?.recordRawResponseItem(item);
2038
2192
  this.toolTranscriptProjection.recordRawNativeToolItem(item);
2039
2193
  this.assistantProjection.handleRawResponseItemCompleted(item, this.activeItemIds);
@@ -2096,7 +2250,7 @@ var CodexCompactionPlanState = class {
2096
2250
  role: "user",
2097
2251
  content: [{
2098
2252
  type: "input_text",
2099
- text: `${RESTORED_PLAN_PREAMBLE}\n${serializePlan(this.latestPlan)}`
2253
+ text: `${RESTORED_PLAN_PREAMBLE}\n${this.latestPlan}`
2100
2254
  }]
2101
2255
  }]
2102
2256
  }, {
@@ -2111,25 +2265,19 @@ function readBoundedPlan(markdownValue, stepsValue) {
2111
2265
  steps: readPlanSteps(stepsValue)
2112
2266
  });
2113
2267
  const markdown = canonical.markdown === void 0 ? void 0 : truncateUtf8(canonical.markdown, RESTORED_PLAN_MAX_MARKDOWN_BYTES);
2114
- const steps = [];
2268
+ const plan = [];
2269
+ const restored = {
2270
+ ...markdown?.trim() ? { markdown } : {},
2271
+ plan
2272
+ };
2273
+ let serialized = markdown?.trim() ? JSON.stringify(restored) : void 0;
2115
2274
  for (const step of canonical.plan) {
2116
- const candidate = {
2117
- ...markdown?.trim() ? { markdown } : {},
2118
- steps: [...steps, step]
2119
- };
2120
- if (Buffer$1.byteLength(serializePlan(candidate), "utf8") > RESTORED_PLAN_MAX_PAYLOAD_BYTES) break;
2121
- steps.push(step);
2275
+ restored.plan.push(step);
2276
+ const candidate = JSON.stringify(restored);
2277
+ if (Buffer$1.byteLength(candidate, "utf8") > RESTORED_PLAN_MAX_PAYLOAD_BYTES) break;
2278
+ serialized = candidate;
2122
2279
  }
2123
- return markdown?.trim() || steps.length > 0 ? {
2124
- ...markdown?.trim() ? { markdown } : {},
2125
- steps
2126
- } : void 0;
2127
- }
2128
- function serializePlan(plan) {
2129
- return JSON.stringify({
2130
- markdown: plan.markdown,
2131
- plan: plan.steps
2132
- });
2280
+ return serialized;
2133
2281
  }
2134
2282
  function truncateUtf8(value, maxBytes) {
2135
2283
  if (Buffer$1.byteLength(value, "utf8") <= maxBytes) return value;
@@ -2167,9 +2315,7 @@ async function restoreCodexAttemptCompactionContext(resources) {
2167
2315
  thread.liveThreadOwnership?.assertCurrent();
2168
2316
  if (state.thread !== thread || state.client !== client) throw new Error("Codex compaction thread ownership changed");
2169
2317
  };
2170
- computerContextEpoch.value += 1;
2171
- delete computerContextEpoch.frameToolCallId;
2172
- delete computerContextEpoch.frameImageIdentity;
2318
+ invalidateCodexComputerFrame(computerContextEpoch);
2173
2319
  try {
2174
2320
  await compactionPlanState.restore({
2175
2321
  client,
@@ -2276,7 +2422,7 @@ function createCodexUserInputBridge(params) {
2276
2422
  const mode = readOwnDataString(request.params, "mode");
2277
2423
  const requestSnapshot = agentHarnessStructuredInput.snapshot(request.params, { richForm: mode === "openaiForm" || mode === "openai/form" });
2278
2424
  if (agentHarnessStructuredInput.isRecord(requestSnapshot) && readOwnDataString(requestSnapshot, "threadId") !== params.threadId) return;
2279
- const { compileCodexOrdinaryElicitation } = await import("./elicitation-input-r9axtppm.mjs");
2425
+ const { compileCodexOrdinaryElicitation } = await import("./elicitation-input-DXG_qaXr.mjs");
2280
2426
  const compiled = agentHarnessStructuredInput.isRecord(requestSnapshot) ? compileCodexOrdinaryElicitation({
2281
2427
  snapshot: requestSnapshot,
2282
2428
  turnId: params.turnId
@@ -2332,8 +2478,8 @@ function readUserInputParams(value) {
2332
2478
  const threadId = readBoundedUserInputText(snapshot, "threadId", MAX_USER_INPUT_ID);
2333
2479
  const turnId = readBoundedUserInputText(snapshot, "turnId", MAX_USER_INPUT_ID);
2334
2480
  const itemId = readBoundedUserInputText(snapshot, "itemId", MAX_USER_INPUT_ID);
2335
- const questions = readArray(snapshot, "questions", MAX_USER_INPUT_QUESTIONS);
2336
- if (!threadId || !turnId || !itemId || !questions) return;
2481
+ const questions = readValue(snapshot, "questions");
2482
+ if (!threadId || !turnId || !itemId || !Array.isArray(questions) || questions.length > MAX_USER_INPUT_QUESTIONS) return;
2337
2483
  const parsed = [];
2338
2484
  for (const questionValue of questions) {
2339
2485
  const question = readQuestion(questionValue);
@@ -2373,7 +2519,7 @@ function readOptions(value) {
2373
2519
  for (const entry of value) {
2374
2520
  if (!agentHarnessStructuredInput.isRecord(entry)) return;
2375
2521
  const label = readBoundedUserInputText(entry, "label", MAX_USER_INPUT_ID);
2376
- const description = readBoundedUserInputText(entry, "description", MAX_USER_INPUT_TEXT, true);
2522
+ const description = readBoundedUserInputText(entry, "description", MAX_USER_INPUT_TEXT);
2377
2523
  if (!label) return;
2378
2524
  options.push({
2379
2525
  label,
@@ -2385,13 +2531,9 @@ function readOptions(value) {
2385
2531
  function readValue(record, key) {
2386
2532
  return Object.hasOwn(record, key) ? record[key] : void 0;
2387
2533
  }
2388
- function readBoundedUserInputText(record, key, maximum, allowEmpty = false) {
2389
- const value = readValue(record, key);
2390
- return typeof value === "string" && value.length <= maximum && (allowEmpty || value.length > 0) ? value : void 0;
2391
- }
2392
- function readArray(record, key, maximum) {
2534
+ function readBoundedUserInputText(record, key, maximum) {
2393
2535
  const value = readValue(record, key);
2394
- return Array.isArray(value) && value.length <= maximum ? value : void 0;
2536
+ return typeof value === "string" && value.length <= maximum && value.length > 0 ? value : void 0;
2395
2537
  }
2396
2538
  function readOwnDataString(value, key) {
2397
2539
  if (!value || typeof value !== "object" || Array.isArray(value)) return;
@@ -2571,10 +2713,11 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
2571
2713
  state.activeLocalProjections -= 1;
2572
2714
  }
2573
2715
  };
2716
+ const isSteeringAvailable = () => !state.completed && !state.terminalTurnNotificationQueued && !runAbortController.signal.aborted;
2574
2717
  const assertSteeringActive = () => {
2575
2718
  connection.assertCurrent();
2576
2719
  runAbortController.signal.throwIfAborted();
2577
- if (state.completed || state.terminalTurnNotificationQueued) throw new Error("codex app-server turn is no longer accepting steering");
2720
+ if (!isSteeringAvailable()) throw new Error("codex app-server turn is no longer accepting steering");
2578
2721
  };
2579
2722
  const workspaceOnly = resolveAttemptFsWorkspaceOnly({
2580
2723
  config: params.config,
@@ -2600,6 +2743,7 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
2600
2743
  signal: runAbortController.signal,
2601
2744
  assertActive: assertSteeringActive,
2602
2745
  withCurrent: connection.withCurrent,
2746
+ withPreparedCurrent: connection.authority.withPreparedCurrent,
2603
2747
  prepareMessage: async (text, options, assertMessageCurrent) => {
2604
2748
  const attachmentNote = await connection.prepareInputAttachments({
2605
2749
  maxChars: Math.max(0, CODEX_TURN_START_TEXT_INPUT_MAX_CHARS - text.length - 2),
@@ -2650,10 +2794,7 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
2650
2794
  const messages = activeProjector.buildSteeringTranscriptPrefix();
2651
2795
  if (params.sessionTarget && messages.length > 0) {
2652
2796
  await codexTranscriptMirrorRuntime.mirror({
2653
- assertCurrent: () => {
2654
- connection.assertLegacyCurrent();
2655
- assertSteeringActive();
2656
- },
2797
+ assertCurrent: composeSessionTranscriptWriteAssertion([connection.assertLegacyCurrent, createNativeSessionBindingAuthority([], assertSteeringActive).assertLegacyCurrent]),
2657
2798
  agentId: sessionAgentId,
2658
2799
  sessionKey: contextSessionKey,
2659
2800
  sessionId: params.sessionId,
@@ -2663,10 +2804,10 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
2663
2804
  idempotencyScope: `codex-app-server:${resourceState.thread.threadId}`,
2664
2805
  runId: params.runId,
2665
2806
  runMirrorIdentityPrefix: `${activeTurnId}:`,
2807
+ onAssistantMessageOwned: (identity) => activeProjector.markSteeringTranscriptMessagePersisted(identity),
2666
2808
  config: params.config
2667
2809
  });
2668
2810
  assertSteeringActive();
2669
- activeProjector.markSteeringTranscriptPersisted();
2670
2811
  }
2671
2812
  for (const item of transcriptItems) {
2672
2813
  const recorder = item.userTurnTranscriptRecorder;
@@ -2678,38 +2819,15 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
2678
2819
  }
2679
2820
  });
2680
2821
  steeringQueueRef.current = activeSteeringQueue;
2822
+ const { claimPendingUserInputAnswer, cancelPendingUserInput } = createCodexQuestionInputHandlers(params.sessionKey ?? params.sessionId, assertSteeringActive);
2681
2823
  const injectionGuard = (assertCurrent) => () => {
2682
2824
  assertCurrent?.();
2683
2825
  assertSteeringActive();
2684
2826
  return true;
2685
2827
  };
2686
- const claimPendingUserInputAnswer = async (text, optionsLocal, assertCurrent, authorityKind = assertCurrent ? "source-bound" : "run") => {
2687
- if (optionsLocal?.isInboundUserMessage !== true || hasPromptImageInput(optionsLocal)) return false;
2688
- assertSteeringActive();
2689
- return await claimPendingAgentQuestionAnswer({
2690
- sessionKey: params.sessionKey ?? params.sessionId,
2691
- text,
2692
- authority: {
2693
- kind: authorityKind,
2694
- assertCurrent: injectionGuard(assertCurrent)
2695
- },
2696
- sourceRecorder: optionsLocal.userTurnTranscriptRecorder,
2697
- persist: optionsLocal.userTurnTranscriptRecorder ? async () => {
2698
- await optionsLocal.userTurnTranscriptRecorder?.persistApproved();
2699
- } : void 0
2700
- });
2701
- };
2702
- const cancelPendingUserInput = (resolvedBy, assertCurrent, authorityKind = assertCurrent ? "source-bound" : "run") => cancelPendingAgentQuestionForSession({
2703
- sessionKey: params.sessionKey ?? params.sessionId,
2704
- resolvedBy,
2705
- authority: {
2706
- kind: authorityKind,
2707
- assertCurrent: injectionGuard(assertCurrent)
2708
- }
2709
- });
2710
- const queueMessage = async (text, optionsLocal, assertCurrent, authorityKind = assertCurrent ? "source-bound" : "run") => {
2828
+ const queueMessage = async (text, optionsLocal, assertCurrent, authorityKind = assertCurrent ? "source-bound" : "run", preparation) => {
2711
2829
  const canClaim = injectionGuard(assertCurrent);
2712
- if (await claimPendingUserInputAnswer(text, optionsLocal, assertCurrent, authorityKind)) {
2830
+ if (await claimPendingUserInputAnswer(text, optionsLocal, assertCurrent, authorityKind, preparation)) {
2713
2831
  optionsLocal?.onQueueAccepted?.(true);
2714
2832
  optionsLocal?.onQueueSettled?.();
2715
2833
  return;
@@ -2717,7 +2835,7 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
2717
2835
  if (optionsLocal?.isInboundUserMessage === true && hasPromptImageInput(optionsLocal)) {
2718
2836
  assertSteeringActive();
2719
2837
  try {
2720
- await cancelPendingUserInput("image-reply", assertCurrent, authorityKind);
2838
+ await cancelPendingUserInput("image-reply", assertCurrent, authorityKind, preparation);
2721
2839
  } catch (error) {
2722
2840
  canClaim();
2723
2841
  if (error instanceof Error && error.name === "QuestionDispatchRefusedError") throw error;
@@ -2725,7 +2843,7 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
2725
2843
  }
2726
2844
  }
2727
2845
  try {
2728
- await activeSteeringQueue.queue(text, optionsLocal, injectionGuard(assertCurrent));
2846
+ await activeSteeringQueue.queue(text, optionsLocal, canClaim, preparation);
2729
2847
  } catch (error) {
2730
2848
  if (error instanceof CodexSteeringAcceptedUnconfirmedError) return {
2731
2849
  transcriptCommit: "unconfirmed",
@@ -2736,10 +2854,13 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
2736
2854
  };
2737
2855
  const messageInjection = {
2738
2856
  version: 2,
2739
- isAvailable: () => !state.completed && !state.terminalTurnNotificationQueued && !runAbortController.signal.aborted,
2857
+ isAvailable: isSteeringAvailable,
2740
2858
  queueMessage,
2741
2859
  claimPendingUserInputAnswer,
2742
- cancelPendingUserInput
2860
+ cancelPendingUserInput,
2861
+ claimPendingUserInputAnswerAsync: (text, options, preparation, kind) => claimPendingUserInputAnswer(text, options, preparation.assertCurrent, kind, preparation),
2862
+ cancelPendingUserInputAsync: (resolvedBy, preparation, kind) => cancelPendingUserInput(resolvedBy, preparation.assertCurrent, kind, preparation),
2863
+ queueMessageAsync: connection.authority.withPreparedCurrent ? (text, options, preparation, kind) => queueMessage(text, options, preparation.assertCurrent, kind, preparation) : void 0
2743
2864
  };
2744
2865
  const handle = {
2745
2866
  kind: "embedded",
@@ -2813,7 +2934,7 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
2813
2934
  for (const failure of pendingNativePreToolUseFailures.splice(0)) activeProjector.recordNativeToolPreToolUseFailure(failure);
2814
2935
  if (thread.preserveNativeModel !== true && thread.connectionScope !== "supervision" && !params.expectedSessionRuntimeOwnership) {
2815
2936
  const route = resourceState.turnRoute;
2816
- params.registerPluginRuntimeRefreshConsumer?.(() => resourceState.turnRoute === route && route?.signal.aborted === false && turnRuntime.turnIdRef.current === activeTurnId && !state.completed && !state.terminalTurnNotificationQueued && !runAbortController.signal.aborted);
2937
+ params.registerPluginRuntimeRefreshConsumer?.(() => resourceState.turnRoute === route && route?.signal.aborted === false && turnRuntime.turnIdRef.current === activeTurnId && isSteeringAvailable());
2817
2938
  }
2818
2939
  params.replyOperation?.attachBackend(handle);
2819
2940
  setActiveEmbeddedRun(params.sessionId, handle, params.sessionKey, params.sessionFile, sessionAgentId);
@@ -2998,17 +3119,9 @@ const CODEX_APP_SERVER_ROLLOUT_TAIL_READ_BYTES = 65536;
2998
3119
  const CODEX_APP_SERVER_BYTE_UNITS = {
2999
3120
  b: 1,
3000
3121
  k: 1024,
3001
- kb: 1024,
3002
- kib: 1024,
3003
- m: 1048576,
3004
- mb: 1048576,
3005
- mib: 1048576,
3006
- g: 1073741824,
3007
- gb: 1073741824,
3008
- gib: 1073741824,
3009
- t: 1099511627776,
3010
- tb: 1099511627776,
3011
- tib: 1099511627776
3122
+ m: 1024 ** 2,
3123
+ g: 1024 ** 3,
3124
+ t: 1024 ** 4
3012
3125
  };
3013
3126
  function parseCodexAppServerByteLimit(value) {
3014
3127
  if (typeof value === "number" && Number.isFinite(value) && value > 0) return Math.floor(value);
@@ -3018,7 +3131,8 @@ function parseCodexAppServerByteLimit(value) {
3018
3131
  const amount = Number(match[1]);
3019
3132
  if (!Number.isFinite(amount) || amount <= 0) return;
3020
3133
  const unit = (match[2] ?? "b").toLowerCase();
3021
- const multiplier = CODEX_APP_SERVER_BYTE_UNITS[unit];
3134
+ const unitPrefix = /^[kmgt](?:i?b)?$/.test(unit) ? unit.charAt(0) : unit;
3135
+ const multiplier = CODEX_APP_SERVER_BYTE_UNITS[unitPrefix];
3022
3136
  if (multiplier === void 0) return;
3023
3137
  return Math.max(1, Math.round(amount * multiplier));
3024
3138
  }
@@ -3076,8 +3190,8 @@ async function listCodexAppServerRolloutFilesForThread(agentDir, threadId, codex
3076
3190
  }
3077
3191
  async function readCodexAppServerRolloutTokenSnapshot(file, openedHandle) {
3078
3192
  let handle = openedHandle;
3079
- if (!handle) try {
3080
- handle = await fs.open(file, "r");
3193
+ try {
3194
+ handle ??= await fs.open(file, "r");
3081
3195
  } catch {
3082
3196
  return;
3083
3197
  }
@@ -3130,10 +3244,10 @@ function readCodexAppServerRolloutTokenSnapshotLine(line) {
3130
3244
  const totalTokens = typeof value === "number" && Number.isFinite(value) ? value : void 0;
3131
3245
  const windowValue = info.model_context_window ?? info.modelContextWindow;
3132
3246
  const modelContextWindow = typeof windowValue === "number" && Number.isFinite(windowValue) && windowValue > 0 ? Math.floor(windowValue) : void 0;
3133
- const snapshot = {};
3134
- if (totalTokens !== void 0) snapshot.totalTokens = totalTokens;
3135
- if (modelContextWindow !== void 0) snapshot.modelContextWindow = modelContextWindow;
3136
- return snapshot.totalTokens !== void 0 || snapshot.modelContextWindow !== void 0 ? snapshot : void 0;
3247
+ return totalTokens !== void 0 || modelContextWindow !== void 0 ? {
3248
+ totalTokens,
3249
+ modelContextWindow
3250
+ } : void 0;
3137
3251
  } catch {
3138
3252
  return;
3139
3253
  }
@@ -3151,7 +3265,6 @@ function maxDefinedNumber(values) {
3151
3265
  const nums = values.filter((value) => value !== void 0);
3152
3266
  return nums.length ? Math.max(...nums) : void 0;
3153
3267
  }
3154
- /** Clears and drops a binding when the native Codex thread is too large to resume safely. */
3155
3268
  async function rotateOversizedCodexAppServerStartupBinding(params) {
3156
3269
  const binding = params.binding;
3157
3270
  if (!binding?.threadId) return { binding };
@@ -3262,7 +3375,7 @@ async function prepareCodexAttemptConnection({ params, options }) {
3262
3375
  config: params.config,
3263
3376
  agentId: policyAgentId
3264
3377
  });
3265
- const agentDir = params.agentDir ?? resolveAgentDir$2(params.config ?? {}, sessionAgentId);
3378
+ const agentDir = params.agentDir ?? resolveAgentDir$1(params.config ?? {}, sessionAgentId);
3266
3379
  const preparedEnvironment = params.hostCapabilities.preparedEnvironment?.();
3267
3380
  const remoteExec = isCodexRemoteExecPlacementSandbox(sandbox);
3268
3381
  const assertLocalTargetSupported = (unsupported) => {
@@ -3278,16 +3391,19 @@ async function prepareCodexAttemptConnection({ params, options }) {
3278
3391
  const disableLoginShell = remoteExec || preparedEnvironment?.localProcessEnv !== void 0 || preparedEnvironment?.managedLocalIdentity === true || preparedEnvironment !== void 0 && Object.keys(preparedEnvironment.credentialScrubEnv).length > 0;
3279
3392
  let shellEnvironment = baseShellEnvironment;
3280
3393
  let shellPathPrepend;
3394
+ let shellGitConfigParameters;
3281
3395
  const withPreparedProcessEnv = (appServer) => {
3282
3396
  assertLocalTargetSupported(appServer.start.transport !== "stdio" || Boolean(appServer.remoteWorkspaceRoot));
3283
- const localToolEnv = !sandbox?.enabled && !remoteExec && appServer.start.transport === "stdio" && !isCodexAppServerProxyLaunch(appServer.start.args) && !appServer.remoteWorkspaceRoot ? preparedEnvironment?.localToolEnv : void 0;
3397
+ const ownedLocalProcess = !sandbox?.enabled && !remoteExec && appServer.start.transport === "stdio" && !isCodexAppServerProxyLaunch(appServer.start.args) && !appServer.remoteWorkspaceRoot;
3398
+ const localToolEnv = ownedLocalProcess ? preparedEnvironment?.localToolEnv : void 0;
3399
+ shellGitConfigParameters = ownedLocalProcess ? preparedEnvironment?.localGitConfigParameters : void 0;
3284
3400
  const hasLocalToolEnv = localToolEnv && Object.keys(localToolEnv).length > 0;
3285
3401
  shellPathPrepend = hasLocalToolEnv ? preparedEnvironment?.localToolPathPrepend : void 0;
3286
3402
  shellEnvironment = hasLocalToolEnv ? {
3287
3403
  ...baseShellEnvironment,
3288
3404
  ...localToolEnv
3289
3405
  } : baseShellEnvironment;
3290
- return shellEnvironment ? {
3406
+ const prepared = shellEnvironment ? {
3291
3407
  ...appServer,
3292
3408
  start: {
3293
3409
  ...appServer.start,
@@ -3297,6 +3413,10 @@ async function prepareCodexAttemptConnection({ params, options }) {
3297
3413
  }
3298
3414
  }
3299
3415
  } : appServer;
3416
+ return shellGitConfigParameters ? {
3417
+ ...prepared,
3418
+ start: withCodexAppServerGitConfig(prepared.start, shellGitConfigParameters)
3419
+ } : prepared;
3300
3420
  };
3301
3421
  let bindingIdentity = sessionBindingIdentity({
3302
3422
  sessionId: params.sessionId,
@@ -3309,10 +3429,11 @@ async function prepareCodexAttemptConnection({ params, options }) {
3309
3429
  let activeContextEngine = isActiveHarnessContextEngine(params.contextEngine) ? params.contextEngine : void 0;
3310
3430
  const isInactiveThreadBootstrapBinding = (binding) => !activeContextEngine && binding?.contextEngine?.projection?.mode === "thread_bootstrap";
3311
3431
  if (bindingIdentity.kind === "session" && bindingIdentity.sessionKey) {
3312
- const authority = await resolveCodexRunSessionBindingAuthority({
3313
- identity: bindingIdentity,
3432
+ const { state: authority } = await prepareNativeSessionGenerationAuthority({
3314
3433
  config: params.config,
3315
- storePath: params.sessionTarget?.storePath
3434
+ storePath: params.sessionTarget?.storePath,
3435
+ target: bindingIdentity,
3436
+ createSupersededError: createCodexSessionGenerationSupersededError
3316
3437
  });
3317
3438
  if (authority === "superseded") throw createCodexSessionGenerationSupersededError(bindingIdentity.sessionId);
3318
3439
  if (authority === "ephemeral") {
@@ -3408,10 +3529,7 @@ async function prepareCodexAttemptConnection({ params, options }) {
3408
3529
  };
3409
3530
  let reviewerPolicyContext = resolveReviewerPolicyContext(startupBinding);
3410
3531
  preDynamicStartupStages.mark("auth-profile");
3411
- let configuredAppServer = await resolveRuntimeOptionsForBinding(startupBinding, {
3412
- modelProvider: reviewerPolicyContext.modelProvider,
3413
- model: reviewerPolicyContext.model
3414
- });
3532
+ let configuredAppServer = await resolveRuntimeOptionsForBinding(startupBinding, reviewerPolicyContext);
3415
3533
  const effectiveWorkspace = sandbox?.enabled ? sandbox.workspaceAccess === "rw" ? resolvedWorkspace : sandbox.workspaceDir : resolvedWorkspace;
3416
3534
  const requestedCwd = params.cwd ? resolveUserPath(params.cwd) : void 0;
3417
3535
  if (sandbox?.enabled && requestedCwd && requestedCwd !== resolvedWorkspace) throw new Error("cwd override is not supported for sandboxed Codex app-server runs; omit cwd or use the agent workspace as cwd");
@@ -3425,31 +3543,30 @@ async function prepareCodexAttemptConnection({ params, options }) {
3425
3543
  const effectiveCwd = sandbox?.enabled ? effectiveWorkspace : sessionPermissionCwd;
3426
3544
  if (effectiveWorkspace !== resolvedWorkspace) await ensureCodexWorkspaceDirOnce(effectiveWorkspace);
3427
3545
  preDynamicStartupStages.mark("effective-workspace");
3428
- const applySessionPermissionPolicy = (appServer, selection) => applyCodexSessionPermissionPolicy({
3429
- appServer,
3430
- permissionMode: params.permissionMode,
3431
- sessionRoot: params.sessionRoot,
3432
- defaultRoot: effectiveWorkspace,
3433
- pluginConfig,
3434
- canUseAutoReview: canUseCodexModelBackedApprovalsReviewerForModel({
3435
- modelProvider: selection.modelProvider,
3436
- model: selection.model,
3437
- config: params.config,
3438
- env: {
3439
- ...process.env,
3440
- ...appServer.start.env,
3441
- ...shellEnvironment
3442
- },
3443
- agentDir,
3444
- homeScope: appServer.start.homeScope,
3445
- codexArgs: appServer.start.args
3446
- }),
3447
- requirementsToml,
3448
- policyLocked: startupBinding?.connectionScope === "supervision",
3449
- execMode: execPolicy.mode
3450
- });
3451
3546
  const resolveFinalAppServer = (configured, selection) => {
3452
- const session = applySessionPermissionPolicy(configured, selection);
3547
+ const session = applyCodexSessionPermissionPolicy({
3548
+ appServer: configured,
3549
+ permissionMode: params.permissionMode,
3550
+ sessionRoot: params.sessionRoot,
3551
+ defaultRoot: effectiveWorkspace,
3552
+ pluginConfig,
3553
+ canUseAutoReview: canUseCodexModelBackedApprovalsReviewerForModel({
3554
+ modelProvider: selection.modelProvider,
3555
+ model: selection.model,
3556
+ config: params.config,
3557
+ env: {
3558
+ ...process.env,
3559
+ ...configured.start.env,
3560
+ ...shellEnvironment
3561
+ },
3562
+ agentDir,
3563
+ homeScope: configured.start.homeScope,
3564
+ codexArgs: configured.start.args
3565
+ }),
3566
+ requirementsToml,
3567
+ policyLocked: startupBinding?.connectionScope === "supervision",
3568
+ execMode: execPolicy.mode
3569
+ });
3453
3570
  const trusted = resolveCodexAppServerForModelProvider({
3454
3571
  appServer: session,
3455
3572
  provider: selection.modelProvider,
@@ -3519,10 +3636,7 @@ async function prepareCodexAttemptConnection({ params, options }) {
3519
3636
  preDynamicStartupStages.mark("rotate-binding");
3520
3637
  if (startupBinding !== startupBindingBeforeRotation) {
3521
3638
  reviewerPolicyContext = resolveReviewerPolicyContext(startupBinding);
3522
- configuredAppServer = await resolveRuntimeOptionsForBinding(startupBinding, {
3523
- modelProvider: reviewerPolicyContext.modelProvider,
3524
- model: reviewerPolicyContext.model
3525
- });
3639
+ configuredAppServer = await resolveRuntimeOptionsForBinding(startupBinding, reviewerPolicyContext);
3526
3640
  appServer = resolveFinalAppServer(configuredAppServer, reviewerPolicyContext);
3527
3641
  }
3528
3642
  const sessionPermissionPolicy = resolveCodexEffectiveSessionPermissionPolicy({
@@ -3609,6 +3723,7 @@ async function prepareCodexAttemptConnection({ params, options }) {
3609
3723
  agentDir,
3610
3724
  shellEnvironment,
3611
3725
  shellPathPrepend,
3726
+ shellGitConfigParameters,
3612
3727
  disableLoginShell,
3613
3728
  bindingIdentity,
3614
3729
  bindingStore,
@@ -3710,15 +3825,7 @@ function buildCodexSystemPromptReport(params) {
3710
3825
  nonProjectContextChars: params.developerInstructions.length,
3711
3826
  hash: sha256Text(params.developerInstructions)
3712
3827
  },
3713
- injectedWorkspaceFiles: buildCodexBootstrapInjectionStats({
3714
- bootstrapFiles: params.workspaceBootstrapContext.bootstrapFiles,
3715
- injectedFiles: params.workspaceBootstrapContext.promptContextFiles ?? [],
3716
- omitReferenceFiles: params.omitWorkspaceReferences,
3717
- omitPersonalProfiles: !params.parentLocalEgress,
3718
- developerInstructionFiles: [...params.workspaceBootstrapContext.threadDeveloperInstructionFiles ?? [], ...params.workspaceBootstrapContext.personaFiles ?? []],
3719
- memoryToolRoutedBootstrapFiles: params.workspaceBootstrapContext.memoryToolRoutedBootstrapFiles ?? [],
3720
- memoryToolRouted: params.workspaceBootstrapContext.memoryToolRouted === true
3721
- }),
3828
+ injectedWorkspaceFiles: buildCodexBootstrapInjectionStats(params),
3722
3829
  skills: {
3723
3830
  promptChars: skillsPrompt.length,
3724
3831
  hash: sha256Text(skillsPrompt),
@@ -3740,27 +3847,19 @@ function buildCodexSkillReportEntries(skillsPrompt) {
3740
3847
  }
3741
3848
  function buildCodexToolReportEntry(tool) {
3742
3849
  const summary = tool.description.trim();
3850
+ const deferred = tool.deferLoading === true;
3851
+ const schema = deferred ? null : tool.inputSchema;
3852
+ let schemaChars = 0;
3853
+ if (!deferred) try {
3854
+ schemaChars = JSON.stringify(schema).length;
3855
+ } catch {
3856
+ schemaChars = 0;
3857
+ }
3858
+ const properties = isJsonObject(schema) && isJsonObject(schema.properties) ? schema.properties : null;
3743
3859
  return {
3744
3860
  name: tool.name,
3745
3861
  summaryChars: summary.length,
3746
3862
  summaryHash: sha256Text(summary),
3747
- ...tool.deferLoading === true ? {
3748
- schemaChars: 0,
3749
- schemaHash: stableJsonHash(null),
3750
- propertiesCount: null
3751
- } : buildCodexToolSchemaStats(tool.inputSchema)
3752
- };
3753
- }
3754
- function buildCodexToolSchemaStats(schema) {
3755
- const schemaChars = (() => {
3756
- try {
3757
- return JSON.stringify(schema).length;
3758
- } catch {
3759
- return 0;
3760
- }
3761
- })();
3762
- const properties = isJsonObject(schema) && isJsonObject(schema.properties) ? schema.properties : null;
3763
- return {
3764
3863
  schemaChars,
3765
3864
  schemaHash: stableJsonHash(schema),
3766
3865
  propertiesCount: properties ? Object.keys(properties).length : null
@@ -3773,17 +3872,18 @@ function stableJsonHash(value) {
3773
3872
  return sha256Text(JSON.stringify(stabilizeJsonValue(value)) ?? "null");
3774
3873
  }
3775
3874
  function buildCodexBootstrapInjectionStats(params) {
3776
- const injectedIndex = indexCodexContextFileContent(params.injectedFiles);
3777
- const developerInstructionIndex = indexCodexContextFileContent(params.developerInstructionFiles ?? []);
3778
- const memoryToolRoutedPaths = new Set((params.memoryToolRoutedBootstrapFiles ?? []).map((file) => readNonBlankString(file.path)).filter(isNonEmptyString).map(normalizeCodexContextFilePath));
3779
- return params.bootstrapFiles.map((file) => {
3875
+ const context = params.workspaceBootstrapContext;
3876
+ const readInjected = indexCodexContextFileContent(context.promptContextFiles ?? []);
3877
+ const readDeveloperInstruction = indexCodexContextFileContent([...context.threadDeveloperInstructionFiles ?? [], ...context.personaFiles ?? []]);
3878
+ const memoryToolRoutedPaths = new Set((context.memoryToolRoutedBootstrapFiles ?? []).map((file) => readNonBlankString(file.path)).filter(isNonEmptyString).map(normalizeCodexContextFilePath));
3879
+ return context.bootstrapFiles.map((file) => {
3780
3880
  const fileName = readNonBlankString(file.name);
3781
3881
  const pathValue = readNonBlankString(file.path) ?? fileName ?? "";
3782
3882
  const displayName = (fileName ?? getCodexContextFileDisplayBasename(pathValue)) || pathValue;
3783
3883
  const baseName = getCodexContextFileBasename(pathValue || fileName || "");
3784
3884
  const rawChars = file.missing ? 0 : (file.content ?? "").trimEnd().length;
3785
- const memoryToolRoutedFile = baseName === "memory.md" && params.memoryToolRouted === true && memoryToolRoutedPaths.has(normalizeCodexContextFilePath(pathValue));
3786
- const injected = memoryToolRoutedFile ? void 0 : readCodexIndexedContextFileContent(injectedIndex, pathValue, fileName) ?? readCodexIndexedContextFileContent(developerInstructionIndex, pathValue, fileName);
3885
+ const memoryToolRoutedFile = baseName === "memory.md" && context.memoryToolRouted === true && memoryToolRoutedPaths.has(normalizeCodexContextFilePath(pathValue));
3886
+ const injected = memoryToolRoutedFile ? void 0 : readInjected(pathValue, fileName) ?? readDeveloperInstruction(pathValue, fileName);
3787
3887
  if (!file.missing && injected === void 0 && CODEX_NATIVE_PROJECT_DOC_BASENAMES.has(baseName)) return {
3788
3888
  name: displayName,
3789
3889
  path: pathValue,
@@ -3793,7 +3893,7 @@ function buildCodexBootstrapInjectionStats(params) {
3793
3893
  injectedChars: null,
3794
3894
  truncated: null
3795
3895
  };
3796
- const omitted = params.omitPersonalProfiles && file.personalUser === true || memoryToolRoutedFile || params.omitReferenceFiles && readCodexIndexedContextFileContent(injectedIndex, pathValue, fileName) !== void 0;
3896
+ const omitted = !params.parentLocalEgress && file.personalUser === true || memoryToolRoutedFile || params.omitWorkspaceReferences && readInjected(pathValue, fileName) !== void 0;
3797
3897
  const injectedChars = omitted ? 0 : injected?.length ?? 0;
3798
3898
  const truncated = omitted ? false : !file.missing && injectedChars < rawChars;
3799
3899
  return {
@@ -3816,15 +3916,11 @@ function indexCodexContextFileContent(files) {
3816
3916
  const baseName = getCodexContextFileBasename(pathValue);
3817
3917
  if (baseName && !byBaseName.has(baseName)) byBaseName.set(baseName, file.content);
3818
3918
  }
3819
- return {
3820
- byPath,
3821
- byBaseName
3919
+ return (pathValue, fileName) => {
3920
+ const baseName = getCodexContextFileBasename(fileName ?? pathValue);
3921
+ return byPath.get(pathValue) ?? (fileName ? byPath.get(fileName) : void 0) ?? (baseName ? byBaseName.get(baseName) : void 0);
3822
3922
  };
3823
3923
  }
3824
- function readCodexIndexedContextFileContent(index, pathValue, fileName) {
3825
- const baseName = getCodexContextFileBasename(fileName ?? pathValue);
3826
- return index.byPath.get(pathValue) ?? (fileName ? index.byPath.get(fileName) : void 0) ?? (baseName ? index.byBaseName.get(baseName) : void 0);
3827
- }
3828
3924
  function readPositiveNumber(value) {
3829
3925
  return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.floor(value) : void 0;
3830
3926
  }
@@ -3902,7 +3998,7 @@ function resolveCodexDeliveryHintPreservedInputRange(params) {
3902
3998
  if (!deliveryHint || !promptInputRange || promptInputRange.start < 0 || promptInputRange.end < promptInputRange.start || promptInputRange.end > prompt.length || !decoratedPrompt.endsWith(promptWithoutDeliveryHint)) return;
3903
3999
  const promptWithoutDeliveryHintStart = prompt.length - promptWithoutDeliveryHint.length;
3904
4000
  const inputStart = Math.max(promptInputRange.start, promptWithoutDeliveryHintStart);
3905
- const inputEnd = Math.max(inputStart, Math.min(promptInputRange.end, promptWithoutDeliveryHint.length + promptWithoutDeliveryHintStart));
4001
+ const inputEnd = Math.max(inputStart, promptInputRange.end);
3906
4002
  const decoratedPromptSuffixStart = decoratedPrompt.length - promptWithoutDeliveryHint.length;
3907
4003
  const requestHeader = "Current user request:\n";
3908
4004
  const requestHeaderStart = decoratedPromptSuffixStart - 22;
@@ -3924,7 +4020,7 @@ function splitLeadingCodexDeliveryHint(prompt) {
3924
4020
  //#region extensions/codex/src/app-server/run-attempt-context.ts
3925
4021
  async function prepareCodexAttemptContext(runtime, attemptTools) {
3926
4022
  const { connection, runtimeParams, effectiveContextWindowInfo, effectiveContextTokenBudget, effectiveRuntimeProviderId, effectiveRuntimeModelId, hookChannelId } = runtime;
3927
- const { params, sessionAgentId, contextSessionKey, activeContextEngine, initialStartupBindingHadInactiveThreadBootstrap, effectiveWorkspace, effectiveCwd, agentDir, usesSupervisionConnection, resolvedWorkspace, initialInactiveThreadBootstrapBindingForcedFreshStart, sandbox } = connection;
4023
+ const { params, sessionAgentId, contextSessionKey, activeContextEngine, initialStartupBindingHadInactiveThreadBootstrap, effectiveWorkspace, effectiveCwd, agentDir, usesSupervisionConnection, resolvedWorkspace, sandbox } = connection;
3928
4024
  const { toolBridge } = attemptTools;
3929
4025
  const activeTranscriptTarget = {
3930
4026
  agentId: sessionAgentId,
@@ -4032,7 +4128,10 @@ async function prepareCodexAttemptContext(runtime, attemptTools) {
4032
4128
  dynamicTools: toolBridge.availableSpecs
4033
4129
  });
4034
4130
  const refreshableInstructions = joinPresentSections(skillsInstructions, workspaceBootstrapContext.sharedPersonaInstructions, workspaceBootstrapContext.memoryInstructions) || void 0;
4035
- const baseDeveloperInstructions = joinPresentSections(buildDeveloperInstructions(runtimeParams, { dynamicTools: toolBridge.availableSpecs }), agentWorkspaceDeveloperInstructions);
4131
+ const baseDeveloperInstructions = joinPresentSections(buildDeveloperInstructions(runtimeParams, {
4132
+ dynamicTools: toolBridge.availableSpecs,
4133
+ nativeCodeModeOnlyEnabled: runtime.nativeToolSurfaceEnabled && connection.appServer.codeModeOnly
4134
+ }), agentWorkspaceDeveloperInstructions);
4036
4135
  const watchedSessionsContext = await prepareCodexWatchedSessionsContext({
4037
4136
  attempt: runtimeParams,
4038
4137
  dynamicTools: toolBridge.availableSpecs,
@@ -4068,10 +4167,7 @@ async function prepareCodexAttemptContext(runtime, attemptTools) {
4068
4167
  promptContextRange: void 0,
4069
4168
  developerInstructions: baseDeveloperInstructions,
4070
4169
  contextEngineProjection: void 0,
4071
- precomputedStaleBindingContinuityProjectionApplied: false,
4072
- staleBindingContinuityForcedFreshStart: false,
4073
- noEngineContinuityProjectionApplied: false,
4074
- inactiveThreadBootstrapBindingForcedFreshStart: initialInactiveThreadBootstrapBindingForcedFreshStart
4170
+ noEngineContinuityProjectionApplied: false
4075
4171
  },
4076
4172
  codexContextProjectionMaxChars: resolveCodexContextEngineProjectionMaxChars({ contextTokenBudget: effectiveContextTokenBudget }),
4077
4173
  codexContinuityProjectionMaxChars: resolveCodexContinuityProjectionMaxChars({
@@ -4123,12 +4219,15 @@ function createCodexModelCallDiagnosticEmitter(params) {
4123
4219
  let started = false;
4124
4220
  let terminalEmitted = false;
4125
4221
  let requestPayloadBytes;
4126
- const privateData = (modelContent) => modelContent && Object.keys(modelContent).length > 0 ? { modelContent } : void 0;
4127
- const buildContent = () => ({
4128
- ...params.capture.inputMessages ? { inputMessages: params.buildInputMessages() } : {},
4129
- ...params.capture.systemPrompt ? { systemPrompt: params.buildSystemPrompt() } : {},
4130
- ...toolDefinitions ? { toolDefinitions } : {}
4131
- });
4222
+ const buildPrivateData = (terminalOutput) => {
4223
+ const modelContent = {
4224
+ ...params.capture.inputMessages ? { inputMessages: params.buildInputMessages() } : {},
4225
+ ...params.capture.systemPrompt ? { systemPrompt: params.buildSystemPrompt() } : {},
4226
+ ...toolDefinitions ? { toolDefinitions } : {},
4227
+ ...terminalOutput && params.capture.outputMessages ? terminalOutput : {}
4228
+ };
4229
+ return Object.keys(modelContent).length > 0 ? { modelContent } : void 0;
4230
+ };
4132
4231
  const emitTerminal = (type, outputMessages, fields = {}) => {
4133
4232
  if (!started || terminalEmitted) return false;
4134
4233
  terminalEmitted = true;
@@ -4138,10 +4237,7 @@ function createCodexModelCallDiagnosticEmitter(params) {
4138
4237
  durationMs: Math.max(0, now() - startedAt),
4139
4238
  ...fields,
4140
4239
  ...requestPayloadBytes !== void 0 ? { requestPayloadBytes } : {}
4141
- }, privateData({
4142
- ...buildContent(),
4143
- ...params.capture.outputMessages ? { outputMessages } : {}
4144
- }));
4240
+ }, buildPrivateData({ outputMessages }));
4145
4241
  return true;
4146
4242
  };
4147
4243
  return {
@@ -4154,7 +4250,7 @@ function createCodexModelCallDiagnosticEmitter(params) {
4154
4250
  emitTrustedDiagnosticEventWithPrivateData({
4155
4251
  type: "model.call.started",
4156
4252
  ...params.baseFields
4157
- }, privateData(buildContent()));
4253
+ }, buildPrivateData());
4158
4254
  },
4159
4255
  emitCompleted(result) {
4160
4256
  emitTerminal("model.call.completed", result.lastAssistant ? [result.lastAssistant] : result.assistantTexts);
@@ -4383,8 +4479,7 @@ function createCodexTrajectoryRecorder(trajectory) {
4383
4479
  };
4384
4480
  }
4385
4481
  function recordCodexTrajectoryContext(recorder, params) {
4386
- if (!recorder) return;
4387
- recorder.recordEvent("context.compiled", {
4482
+ recorder?.recordEvent("context.compiled", {
4388
4483
  systemPrompt: params.developerInstructions,
4389
4484
  prompt: params.prompt ?? params.attempt.prompt,
4390
4485
  imagesCount: params.attempt.images?.length ?? 0,
@@ -4411,12 +4506,11 @@ function toTrajectoryToolDefinitions(tools) {
4411
4506
  if (!tools || tools.length === 0) return;
4412
4507
  return flattenCodexDynamicToolFunctions(tools).flatMap((tool) => {
4413
4508
  const name = tool.name?.trim();
4414
- if (!name) return [];
4415
- return [{
4509
+ return name ? [{
4416
4510
  name,
4417
4511
  description: tool.description,
4418
4512
  parameters: tool.inputSchema
4419
- }];
4513
+ }] : [];
4420
4514
  }).toSorted((left, right) => left.name.localeCompare(right.name));
4421
4515
  }
4422
4516
  function normalizeCodexTrajectoryError(value) {
@@ -4432,7 +4526,7 @@ function normalizeCodexTrajectoryError(value) {
4432
4526
  //#endregion
4433
4527
  //#region extensions/codex/src/app-server/run-attempt-finalize.ts
4434
4528
  async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notifications, requestRuntime, activeTurn) {
4435
- const { prompt, state: resourceState, trajectoryRecorder, markTrajectoryEndRecorded } = resources;
4529
+ const { prompt, state: resourceState, trajectoryRecorder } = resources;
4436
4530
  const { context, systemPromptReport } = prompt;
4437
4531
  const { runtime, attemptTools, activeTranscriptTarget, hookContext } = context;
4438
4532
  const { hookRunner } = context;
@@ -4464,6 +4558,8 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
4464
4558
  readRetainedNativeCommands,
4465
4559
  steeringMessages: params.pluginRuntimeRefreshPending?.() ? turnRuntime.steeringQueueRef.current?.getAcceptedMessages() : void 0
4466
4560
  });
4561
+ const terminalAssistantSource = result.messagesSnapshot.find((message) => readMirrorIdentity(message) === `${activeTurnId}:assistant`);
4562
+ const terminalSourceKey = terminalAssistantSource?.role === "assistant" ? buildCodexMirrorIdempotencyKey(`codex-app-server:${resourceState.thread.threadId}`, buildCodexMirrorDedupeIdentity(terminalAssistantSource)) : void 0;
4467
4563
  const projectedTerminal = attemptTerminal.project(result.terminal);
4468
4564
  const isFinalAborted = () => terminalState.explicitCancellationObserved || !resourceState.executionDisconnectError && (projectedTerminal.aborted || runAbortController.signal.aborted && !state.clientClosedAbort);
4469
4565
  const currentPromptError = (fallback) => resourceState.executionDisconnectError ?? state.clientClosedPromptError ?? (state.timeout ? `codex app-server ${state.timeout.kind === "execution" ? "execution budget" : "terminal settlement"} timed out` : fallback);
@@ -4544,7 +4640,7 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
4544
4640
  for (const message of [
4545
4641
  result.lastAssistant,
4546
4642
  result.currentAttemptAssistant,
4547
- result.messagesSnapshot.find((candidate) => readMirrorIdentity(candidate) === `${activeTurnId}:assistant`)
4643
+ terminalAssistantSource
4548
4644
  ]) if (message?.role === "assistant") {
4549
4645
  if (!message.diagnostics?.some((diagnostic) => diagnostic.type === "provider_refusal") || finalAborted || finalPromptError) {
4550
4646
  message.stopReason = finalAborted ? "aborted" : finalPromptError ? "error" : "stop";
@@ -4573,11 +4669,11 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
4573
4669
  const mirrorTerminal = projectTerminalOutcome();
4574
4670
  state.pendingSettlementStage = "transcript/mirror";
4575
4671
  return codexTranscriptMirrorRuntime.mirrorBestEffort({
4576
- assertWriteCurrent: () => {
4672
+ assertWriteCurrent: createNativeSessionBindingAuthority([], () => {
4577
4673
  if (!isSettlementActive() || state.settlementWarning !== warning) throw new Error("Codex transcript settlement is no longer active");
4578
4674
  const current = projectTerminalOutcome();
4579
4675
  if (current.finalAborted !== mirrorTerminal.finalAborted || current.effectiveTimedOut !== mirrorTerminal.effectiveTimedOut || current.finalPromptError !== mirrorTerminal.finalPromptError) throw new Error("Codex transcript terminal outcome changed before write");
4580
- },
4676
+ }).assertLegacyCurrent,
4581
4677
  params,
4582
4678
  settlementWarning: warning,
4583
4679
  agentId: sessionAgentId,
@@ -4589,43 +4685,40 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
4589
4685
  turnId: activeTurnId
4590
4686
  });
4591
4687
  };
4592
- try {
4593
- if (projectionDrained && isSettlementActive() && !state.settlementWarning) mirrorOutcome = await Promise.race([
4594
- mirrorFinal(),
4595
- drainGraceElapsed.promise.then(() => unavailableMirror),
4596
- degradedSettlement.then(() => unavailableMirror)
4688
+ if (projectionDrained && isSettlementActive() && !state.settlementWarning) mirrorOutcome = await Promise.race([
4689
+ mirrorFinal(),
4690
+ drainGraceElapsed.promise.then(() => unavailableMirror),
4691
+ degradedSettlement.then(() => unavailableMirror)
4692
+ ]);
4693
+ if (state.settlementWarning && !runAbortController.signal.aborted) {
4694
+ mirrorOutcome = await Promise.race([mirrorFinal(), drainGraceElapsed.promise.then(() => unavailableMirror)]);
4695
+ if (mirrorOutcome === unavailableMirror) trajectoryRecorder?.recordEvent("turn.settlement_persistence_unavailable", {
4696
+ pendingStage: "transcript/mirror",
4697
+ threadId: resourceState.thread.threadId,
4698
+ turnId: activeTurnId
4699
+ });
4700
+ }
4701
+ if (toolState.yieldMessage && projectTerminalOutcome().turnSucceeded) {
4702
+ state.pendingSettlementStage = "transcript/yield-context";
4703
+ await Promise.race([
4704
+ appendSessionYieldContext({
4705
+ ...activeTranscriptTarget.sessionTarget,
4706
+ agentId: activeTranscriptTarget.agentId,
4707
+ sessionId: activeTranscriptTarget.sessionId,
4708
+ sessionKey: activeTranscriptTarget.sessionKey,
4709
+ config: params.config,
4710
+ message: toolState.yieldMessage,
4711
+ assertCurrent: () => {
4712
+ connection.assertLegacyCurrent();
4713
+ if (!isSettlementActive() || !projectTerminalOutcome().turnSucceeded) throw new Error("Codex yield settlement is no longer active");
4714
+ }
4715
+ }),
4716
+ drainGraceElapsed.promise,
4717
+ degradedSettlement
4597
4718
  ]);
4598
- if (state.settlementWarning && !runAbortController.signal.aborted) {
4599
- mirrorOutcome = await Promise.race([mirrorFinal(), drainGraceElapsed.promise.then(() => unavailableMirror)]);
4600
- if (mirrorOutcome === unavailableMirror) trajectoryRecorder?.recordEvent("turn.settlement_persistence_unavailable", {
4601
- pendingStage: "transcript/mirror",
4602
- threadId: resourceState.thread.threadId,
4603
- turnId: activeTurnId
4604
- });
4605
- }
4606
- if (toolState.yieldMessage && projectTerminalOutcome().turnSucceeded) {
4607
- state.pendingSettlementStage = "transcript/yield-context";
4608
- await Promise.race([
4609
- appendSessionYieldContext({
4610
- ...activeTranscriptTarget.sessionTarget,
4611
- agentId: activeTranscriptTarget.agentId,
4612
- sessionId: activeTranscriptTarget.sessionId,
4613
- sessionKey: activeTranscriptTarget.sessionKey,
4614
- config: params.config,
4615
- message: toolState.yieldMessage,
4616
- assertCurrent: () => {
4617
- connection.assertLegacyCurrent();
4618
- if (!isSettlementActive() || !projectTerminalOutcome().turnSucceeded) throw new Error("Codex yield settlement is no longer active");
4619
- }
4620
- }),
4621
- drainGraceElapsed.promise,
4622
- degradedSettlement
4623
- ]);
4624
- }
4625
- await settleReplyMedia(activeTurn, result, turnRuntime, runAbortController.signal);
4626
- } finally {
4627
- closeSettlement();
4628
4719
  }
4720
+ await settleReplyMedia(activeTurn, result, turnRuntime, runAbortController.signal);
4721
+ closeSettlement();
4629
4722
  const { effectiveTimedOut, finalPromptError, codexAppServerFailure, promptTimeoutOutcome, finalAborted, turnSucceeded, attemptSucceeded, completedTurnStatus } = projectTerminalOutcome();
4630
4723
  terminalState.settledTurnStatus = turnSucceeded ? "completed" : completedTurnStatus === "failed" && !finalAborted && !effectiveTimedOut && !state.clientClosedPromptError && !resourceState.executionDisconnectError ? "failed" : void 0;
4631
4724
  terminalState.sharedAbortAllowedAfterTerminalOutcome = shouldKeepCodexSharedAbortOpen({
@@ -4741,14 +4834,15 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
4741
4834
  yieldDetected: toolState.yieldDetected,
4742
4835
  promptError: normalizeCodexTrajectoryError(finalPromptError)
4743
4836
  });
4744
- markTrajectoryEndRecorded();
4837
+ resourceState.trajectoryEndRecorded = true;
4745
4838
  const terminalAssistantText = collectTerminalAssistantText(result);
4839
+ const terminalAssistantItemId = assistantTranscriptIdempotencyKey ?? terminalSourceKey;
4746
4840
  if (terminalAssistantText && (assistantTranscriptIdempotencyKey || (!streamState.eventEmitted || streamState.needsTerminalSnapshot) && !finalAborted && !finalPromptError)) emitCodexAppServerEvent(params, {
4747
4841
  stream: "assistant",
4748
4842
  data: {
4749
4843
  text: terminalAssistantText,
4750
- ...assistantTranscriptIdempotencyKey ? {
4751
- itemId: assistantTranscriptIdempotencyKey,
4844
+ ...terminalAssistantItemId ? {
4845
+ itemId: terminalAssistantItemId,
4752
4846
  replace: true,
4753
4847
  replaceable: true
4754
4848
  } : {}
@@ -4813,58 +4907,53 @@ function createCodexAttemptLifecycleController(resources, turnRuntime) {
4813
4907
  const { connection } = prompt.context.runtime;
4814
4908
  const { params, attemptStartedAt, runAbortController, fastModeAutoStartedAtMs, fastModeAutoProgressState } = connection;
4815
4909
  const { state, activeTurnItemIds, pendingOpenClawDynamicToolCompletionIds } = turnRuntime;
4816
- const releaseTurnAfterTerminalDynamicTool = (value) => {
4817
- if (!shouldReleaseTurnAfterTerminalDynamicTool({
4818
- completed: state.completed,
4819
- aborted: runAbortController.signal.aborted,
4820
- responseSuccess: value.response.success,
4821
- currentTurnHadNonTerminalDynamicToolResult: state.currentTurnHadNonTerminalDynamicToolResult,
4822
- activeAppServerTurnRequests: state.activeAppServerTurnRequests,
4823
- activeTurnItemIdsCount: activeTurnItemIds.size,
4824
- pendingOpenClawDynamicToolCompletionIdsCount: pendingOpenClawDynamicToolCompletionIds.size
4825
- })) return;
4826
- state.pendingTerminalDynamicToolRelease = void 0;
4827
- trajectoryRecorder?.recordEvent("turn.dynamic_tool_terminal_release", {
4828
- threadId: value.call.threadId,
4829
- turnId: value.call.turnId,
4830
- toolCallId: value.call.callId,
4831
- name: value.call.tool,
4832
- durationMs: value.durationMs
4833
- });
4834
- embeddedAgentLog.info("codex app-server turn released after terminal dynamic tool result", {
4835
- threadId: value.call.threadId,
4836
- turnId: value.call.turnId,
4837
- toolCallId: value.call.callId,
4838
- tool: value.call.tool,
4839
- durationMs: value.durationMs
4840
- });
4841
- turnRuntime.steeringQueueRef.current?.cancel();
4842
- turnRuntime.interruptTurn(value.call.turnId, { locallyCompleted: true });
4843
- turnRuntime.completeTurn();
4844
- };
4910
+ const batchHadNonTerminalResult = () => state.currentTurnHadNonTerminalDynamicToolResult && !state.currentTurnHadToolAuthoredFinalReply;
4845
4911
  const scheduleTerminalDynamicToolReleaseCheck = () => {
4846
4912
  if (state.terminalDynamicToolReleaseCheckScheduled || !state.pendingTerminalDynamicToolRelease && !state.currentTurnHadNonTerminalDynamicToolResult) return;
4847
4913
  state.terminalDynamicToolReleaseCheckScheduled = true;
4848
4914
  setImmediate(() => {
4849
4915
  state.terminalDynamicToolReleaseCheckScheduled = false;
4850
- if (state.pendingTerminalDynamicToolRelease?.response.success === true && !state.currentTurnHadNonTerminalDynamicToolResult && state.activeAppServerTurnRequests === 0 && pendingOpenClawDynamicToolCompletionIds.size === 0) turnRuntime.steeringQueueRef.current?.cancel();
4851
- const action = resolveTerminalDynamicToolBatchAction({
4852
- activeAppServerTurnRequests: state.activeAppServerTurnRequests,
4853
- activeTurnItemIdsCount: activeTurnItemIds.size,
4854
- pendingOpenClawDynamicToolCompletionIdsCount: pendingOpenClawDynamicToolCompletionIds.size,
4855
- currentTurnHadNonTerminalDynamicToolResult: state.currentTurnHadNonTerminalDynamicToolResult,
4856
- hasPendingTerminalDynamicToolRelease: state.pendingTerminalDynamicToolRelease !== void 0
4857
- });
4858
- if (action === "release-pending-terminal" && state.pendingTerminalDynamicToolRelease) releaseTurnAfterTerminalDynamicTool(state.pendingTerminalDynamicToolRelease);
4859
- else if (action === "clear-nonterminal-batch") {
4916
+ if (state.pendingTerminalDynamicToolRelease?.response.success === true && !batchHadNonTerminalResult() && state.activeAppServerTurnRequests === 0 && pendingOpenClawDynamicToolCompletionIds.size === 0) turnRuntime.steeringQueueRef.current?.cancel();
4917
+ if (state.activeAppServerTurnRequests > 0 || activeTurnItemIds.size > 0 || pendingOpenClawDynamicToolCompletionIds.size > 0) return;
4918
+ if (batchHadNonTerminalResult()) {
4860
4919
  state.pendingTerminalDynamicToolRelease = void 0;
4861
4920
  state.currentTurnHadNonTerminalDynamicToolResult = false;
4921
+ state.currentTurnHadToolAuthoredFinalReply = false;
4922
+ return;
4862
4923
  }
4924
+ const value = state.pendingTerminalDynamicToolRelease;
4925
+ if (!value || state.completed || runAbortController.signal.aborted || !value.response.success || state.activeAppServerTurnRequests !== 0 || activeTurnItemIds.size !== 0 || pendingOpenClawDynamicToolCompletionIds.size !== 0) return;
4926
+ state.pendingTerminalDynamicToolRelease = void 0;
4927
+ state.currentTurnHadToolAuthoredFinalReply = false;
4928
+ trajectoryRecorder?.recordEvent("turn.dynamic_tool_terminal_release", {
4929
+ threadId: value.call.threadId,
4930
+ turnId: value.call.turnId,
4931
+ toolCallId: value.call.callId,
4932
+ name: value.call.tool,
4933
+ durationMs: value.durationMs
4934
+ });
4935
+ embeddedAgentLog.info("codex app-server turn released after terminal dynamic tool result", {
4936
+ threadId: value.call.threadId,
4937
+ turnId: value.call.turnId,
4938
+ toolCallId: value.call.callId,
4939
+ tool: value.call.tool,
4940
+ durationMs: value.durationMs
4941
+ });
4942
+ turnRuntime.steeringQueueRef.current?.cancel();
4943
+ turnRuntime.interruptTurn(value.call.turnId, { locallyCompleted: true });
4944
+ turnRuntime.completeTurn();
4863
4945
  }).unref?.();
4864
4946
  };
4865
- const scheduleTurnReleaseAfterTerminalDynamicTool = (value) => {
4866
- state.pendingTerminalDynamicToolRelease = value;
4867
- scheduleTerminalDynamicToolReleaseCheck();
4947
+ const recordDynamicToolResult = (value) => {
4948
+ if (value.response.success && value.response.toolAuthoredFinalReply === true) state.currentTurnHadToolAuthoredFinalReply = true;
4949
+ if (value.response.terminate === true && value.response.success) {
4950
+ state.pendingTerminalDynamicToolRelease = value;
4951
+ scheduleTerminalDynamicToolReleaseCheck();
4952
+ } else if (value.response.asyncStarted === true) scheduleTerminalDynamicToolReleaseCheck();
4953
+ else {
4954
+ state.currentTurnHadNonTerminalDynamicToolResult = true;
4955
+ if (!state.currentTurnHadToolAuthoredFinalReply) state.pendingTerminalDynamicToolRelease = void 0;
4956
+ }
4868
4957
  };
4869
4958
  const { emitLifecycleStart, emitLifecycleTerminal, emitExecutionPhaseOnce } = createAgentHarnessAttemptLifecycle({
4870
4959
  attempt: params,
@@ -4944,8 +5033,8 @@ function createCodexAttemptLifecycleController(resources, turnRuntime) {
4944
5033
  }
4945
5034
  };
4946
5035
  return {
5036
+ recordDynamicToolResult,
4947
5037
  scheduleTerminalDynamicToolReleaseCheck,
4948
- scheduleTurnReleaseAfterTerminalDynamicTool,
4949
5038
  emitLifecycleStart,
4950
5039
  emitLifecycleTerminal,
4951
5040
  buildLifecycleTerminalMeta,
@@ -4956,6 +5045,78 @@ function createCodexAttemptLifecycleController(resources, turnRuntime) {
4956
5045
  };
4957
5046
  }
4958
5047
  //#endregion
5048
+ //#region extensions/codex/src/app-server/session-warnings.ts
5049
+ const MAX_WARNING_RECEIPTS = 256;
5050
+ const ULTRAFAST_REQUIREMENT_WARNING_PREFIX = "Ignoring unknown `features` requirement `ultrafast_mode` from ";
5051
+ function readWarningReceipts(entry) {
5052
+ const state = entry.pluginExtensions?.codex?.warningReceipts;
5053
+ if (!isJsonObject(state) || state.version !== 1 || state.sessionId !== entry.sessionId || state.lifecycleRevision !== (entry.lifecycleRevision ?? null) || !Array.isArray(state.hashes)) return [];
5054
+ return state.hashes.slice(0, MAX_WARNING_RECEIPTS).filter((value) => typeof value === "string" && /^[a-f0-9]{64}$/.test(value));
5055
+ }
5056
+ /** Session-owned receipts survive native reconnects and Gateway restart, but not chat reset. */
5057
+ async function projectCodexSessionWarning(params) {
5058
+ const { notification, session } = params;
5059
+ const body = isJsonObject(notification.params) ? notification.params : void 0;
5060
+ const scope = readCodexNotificationScope(body);
5061
+ const message = body ? readCodexAppServerWarningMessage(body) : "";
5062
+ if (notification.method !== "warning" && notification.method !== "configWarning" || !body || !message.startsWith(ULTRAFAST_REQUIREMENT_WARNING_PREFIX) || message.length === 62 || !session.sessionKey || scope.threadId && scope.threadId !== params.threadId) {
5063
+ params.assertCurrent();
5064
+ await params.project();
5065
+ return;
5066
+ }
5067
+ const hash = createHash("sha256").update(JSON.stringify([
5068
+ message,
5069
+ body.path ?? null,
5070
+ body.range ?? null
5071
+ ])).digest("hex");
5072
+ let foundSession = false;
5073
+ let projectionAttempted = false;
5074
+ const project = async () => {
5075
+ params.assertCurrent();
5076
+ projectionAttempted = true;
5077
+ return await params.project();
5078
+ };
5079
+ try {
5080
+ await patchSessionEntry({
5081
+ agentId: session.agentId,
5082
+ sessionKey: session.sessionKey,
5083
+ storePath: session.storePath,
5084
+ preserveActivity: true,
5085
+ requireWriteSuccess: true,
5086
+ skipMaintenance: true,
5087
+ update: async (entry) => {
5088
+ foundSession = true;
5089
+ params.assertCurrent();
5090
+ if (entry.sessionId !== session.sessionId || session.expectedLifecycleRevision !== void 0 && entry.lifecycleRevision !== session.expectedLifecycleRevision) return null;
5091
+ const hashes = readWarningReceipts(entry);
5092
+ if (hashes.includes(hash)) return null;
5093
+ if (!await project()) return null;
5094
+ params.assertCurrent();
5095
+ if (hashes.length >= MAX_WARNING_RECEIPTS) return null;
5096
+ return { pluginExtensions: {
5097
+ ...entry.pluginExtensions,
5098
+ codex: {
5099
+ ...entry.pluginExtensions?.codex,
5100
+ warningReceipts: {
5101
+ version: 1,
5102
+ sessionId: entry.sessionId,
5103
+ lifecycleRevision: entry.lifecycleRevision ?? null,
5104
+ hashes: [...hashes, hash]
5105
+ }
5106
+ }
5107
+ } };
5108
+ }
5109
+ });
5110
+ } catch (error) {
5111
+ if (projectionAttempted) throw error;
5112
+ params.assertCurrent();
5113
+ embeddedAgentLog.debug("Codex warning receipt store unavailable", { error });
5114
+ await project();
5115
+ return;
5116
+ }
5117
+ if (!foundSession) await project();
5118
+ }
5119
+ //#endregion
4959
5120
  //#region extensions/codex/src/app-server/run-attempt-notification-controller.ts
4960
5121
  function createCodexAttemptNotificationController(resources, turnRuntime, lifecycle) {
4961
5122
  const { prompt, state: resourceState, projectorRef } = resources;
@@ -4966,20 +5127,11 @@ function createCodexAttemptNotificationController(resources, turnRuntime, lifecy
4966
5127
  const { state, turnIdRef, steeringQueueRef, activeTurnItemIds, pendingOpenClawDynamicToolCompletionIds, openClawDynamicToolExecutions, completeTurn, noteProgress, deadlines } = turnRuntime;
4967
5128
  const { scheduleTerminalDynamicToolReleaseCheck, reportExecutionNotification, maybeAnnounceFastModeAutoOff } = lifecycle;
4968
5129
  const pendingNativeCommandItems = /* @__PURE__ */ new Set();
4969
- const nativeItemObservers = /* @__PURE__ */ new Set();
5130
+ let nativeItemsCompletion;
4970
5131
  const waitForNativeTerminalItems = async (signal) => {
4971
5132
  if (pendingNativeCommandItems.size === 0) return;
4972
- const completion = createDeferred();
4973
- const observe = () => {
4974
- if (pendingNativeCommandItems.size === 0) completion.resolve();
4975
- };
4976
- nativeItemObservers.add(observe);
4977
- try {
4978
- observe();
4979
- if (!await waitForPromiseOrAbort(completion.promise, signal)) signal.throwIfAborted();
4980
- } finally {
4981
- nativeItemObservers.delete(observe);
4982
- }
5133
+ const completion = nativeItemsCompletion ??= createDeferred();
5134
+ if (!await waitForPromiseOrAbort(completion.promise, signal)) signal.throwIfAborted();
4983
5135
  };
4984
5136
  const readTerminalTurn = (notification, notificationTurnId) => notification.method === "turn/completed" && isCodexNotificationForTurn(notification.params, resourceState.thread.threadId, notificationTurnId) ? readCodexTurnCompletedNotification(notification.params)?.turn : void 0;
4985
5137
  const handleNotification = async (notification) => {
@@ -5002,10 +5154,7 @@ function createCodexAttemptNotificationController(resources, turnRuntime, lifecy
5002
5154
  updateActiveTurnItemIds(notification, activeTurnItemIds);
5003
5155
  noteProgress(`notification:${notification.method}`);
5004
5156
  reportExecutionNotification(notification);
5005
- if (isPendingOpenClawDynamicToolCompletionNotification(notification, pendingOpenClawDynamicToolCompletionIds)) {
5006
- const itemId = readNotificationItemId(notification);
5007
- if (itemId) pendingOpenClawDynamicToolCompletionIds.delete(itemId);
5008
- }
5157
+ completePendingOpenClawDynamicToolNotification(notification, pendingOpenClawDynamicToolCompletionIds);
5009
5158
  if (notification.method === "item/completed") {
5010
5159
  if (activeTurnItemIds.size === 0) scheduleTerminalDynamicToolReleaseCheck();
5011
5160
  const item = readCodexNotificationItem(notification.params);
@@ -5019,9 +5168,28 @@ function createCodexAttemptNotificationController(resources, turnRuntime, lifecy
5019
5168
  }
5020
5169
  if (item?.type === "userMessage" && typeof item.clientId === "string") steeringQueueRef.current?.confirmConsumed(item.clientId);
5021
5170
  }
5022
- if (isCodexTurnAbortMarkerNotification(notification, { currentPromptTexts: [turnState.codexTurnPromptText] })) state.sawCodexInterruptMarker = true;
5171
+ if (isCodexTurnAbortMarkerNotification(notification, { currentPromptText: turnState.codexTurnPromptText })) state.sawCodexInterruptMarker = true;
5023
5172
  }
5024
- await projector.handleNotification(notification);
5173
+ if (notification.method === "warning" || notification.method === "configWarning") {
5174
+ const { params, sessionAgentId, assertCurrent } = runtime.connection;
5175
+ await projectCodexSessionWarning({
5176
+ session: {
5177
+ agentId: sessionAgentId,
5178
+ sessionId: params.sessionId,
5179
+ sessionKey: params.sessionTarget?.sessionKey ?? params.sessionKey,
5180
+ storePath: params.sessionTarget?.storePath ?? resolveStorePath(params.config?.session?.store, { agentId: sessionAgentId }),
5181
+ expectedLifecycleRevision: params.sessionTarget?.expectedLifecycleRevision
5182
+ },
5183
+ threadId: resourceState.thread.threadId,
5184
+ notification,
5185
+ assertCurrent,
5186
+ project: async () => {
5187
+ if (state.projectionClosed || projectorRef.current !== projector || turnIdRef.current !== turnId) return false;
5188
+ await projector.handleNotification(notification);
5189
+ return true;
5190
+ }
5191
+ });
5192
+ } else await projector.handleNotification(notification);
5025
5193
  if (isCurrentTurn && activeTurnItemIds.size === 0 && isRawFunctionToolOutputCompletionNotification(notification)) await maybeAnnounceFastModeAutoOff();
5026
5194
  } catch (error) {
5027
5195
  embeddedAgentLog.debug("codex app-server projector notification threw", {
@@ -5034,7 +5202,10 @@ function createCodexAttemptNotificationController(resources, turnRuntime, lifecy
5034
5202
  const item = readCodexNotificationItem(notification.params);
5035
5203
  if (item?.type === "commandExecution") pendingNativeCommandItems.delete(item.id);
5036
5204
  }
5037
- for (const observe of nativeItemObservers) observe();
5205
+ if (pendingNativeCommandItems.size === 0) {
5206
+ nativeItemsCompletion?.resolve();
5207
+ nativeItemsCompletion = void 0;
5208
+ }
5038
5209
  if (completedTurn) {
5039
5210
  if (completedTurn.status === "interrupted" && state.sawCodexInterruptMarker) projector.markAborted();
5040
5211
  completeTurn();
@@ -5105,6 +5276,7 @@ async function prepareCodexAttemptPrompt(context) {
5105
5276
  const { connection, runtimeParams, effectiveContextTokenBudget, effectiveRuntimeModelId, effectiveRuntimeProviderId } = runtime;
5106
5277
  const { params, activeContextEngine, usesSupervisionConnection, mutable, isInactiveThreadBootstrapBinding, bindingStore, bindingIdentity, agentDir, appServer, contextSessionKey, effectiveWorkspace, sandbox } = connection;
5107
5278
  const { toolBridge } = attemptTools;
5279
+ const availableToolNames = () => flattenCodexDynamicToolFunctions(toolBridge.availableSpecs).map((tool) => tool.name).filter(isNonEmptyString);
5108
5280
  const nativeHistoryProvenancePrefix = params.trigger === "user" ? buildCodexHistoryProvenancePrefix(params) : void 0;
5109
5281
  const forkedSession = !mutable.startupBinding?.threadId && params.sessionTarget ? getSessionEntry({
5110
5282
  ...params.sessionTarget,
@@ -5150,10 +5322,10 @@ async function prepareCodexAttemptPrompt(context) {
5150
5322
  };
5151
5323
  const applyContinuityProjection = async (messages) => {
5152
5324
  const projection = await projectContextEngineAssemblyForCodex({
5153
- assembledMessages: messages,
5325
+ assembledMessages: [...messages, ...params.continuation?.messages ?? []],
5154
5326
  prompt: params.prompt,
5155
5327
  maxRenderedContextChars: codexContinuityProjectionMaxChars,
5156
- toolPayloadMode: params.pluginRuntimeRefreshMessages || preserveForkedToolResults ? "preserve" : "elide",
5328
+ toolPayloadMode: params.continuation || params.pluginRuntimeRefreshMessages || preserveForkedToolResults ? "preserve" : "elide",
5157
5329
  prepareFileContext,
5158
5330
  currentUserTurnIdempotencyKey
5159
5331
  });
@@ -5172,7 +5344,7 @@ async function prepareCodexAttemptPrompt(context) {
5172
5344
  sessionKey: contextSessionKey,
5173
5345
  messages: historyState.messages,
5174
5346
  tokenBudget: effectiveContextTokenBudget,
5175
- availableTools: new Set(flattenCodexDynamicToolFunctions(toolBridge.availableSpecs).map((tool) => tool.name).filter(isNonEmptyString)),
5347
+ availableTools: new Set(availableToolNames()),
5176
5348
  citationsMode: params.config?.memory?.citations,
5177
5349
  sandboxed: sandbox?.enabled === true,
5178
5350
  modelId: effectiveRuntimeModelId,
@@ -5187,7 +5359,7 @@ async function prepareCodexAttemptPrompt(context) {
5187
5359
  });
5188
5360
  if (!assembled) throw new Error("context engine assemble returned no result");
5189
5361
  const contextEngineProjection = readContextEngineThreadBootstrapProjection(assembled.contextProjection);
5190
- const projectionDecision = contextEngineProjection ? resolveContextEngineBootstrapProjectionDecision({
5362
+ const projectionDecision = contextEngineProjection && !params.continuation ? resolveContextEngineBootstrapProjectionDecision({
5191
5363
  startupBinding: decisionStartupBinding,
5192
5364
  expectedBinding: buildContextEngineBinding({ ...runtimeParams }, contextEngineProjection),
5193
5365
  projection: contextEngineProjection,
@@ -5198,11 +5370,11 @@ async function prepareCodexAttemptPrompt(context) {
5198
5370
  reason: "per-turn-projection"
5199
5371
  };
5200
5372
  const projection = await projectContextEngineAssemblyForCodex({
5201
- assembledMessages: assembled.messages,
5373
+ assembledMessages: [...assembled.messages, ...params.continuation?.messages ?? []],
5202
5374
  prompt: params.prompt,
5203
5375
  systemPromptAddition: assembled.systemPromptAddition,
5204
5376
  maxRenderedContextChars: codexContextProjectionMaxChars,
5205
- toolPayloadMode: contextEngineProjection || params.pluginRuntimeRefreshMessages || preserveForkedToolResults ? "preserve" : "elide",
5377
+ toolPayloadMode: contextEngineProjection || params.continuation || params.pluginRuntimeRefreshMessages || preserveForkedToolResults ? "preserve" : "elide",
5206
5378
  ...projectionDecision.project ? { prepareFileContext } : {},
5207
5379
  currentUserTurnIdempotencyKey
5208
5380
  });
@@ -5230,7 +5402,7 @@ async function prepareCodexAttemptPrompt(context) {
5230
5402
  promptState.promptContextRange = projectionDecision.project ? projection.promptContextRange : void 0;
5231
5403
  promptState.developerInstructions = joinPresentSections(baseDeveloperInstructions, projection.developerInstructionAddition);
5232
5404
  } catch (assembleErr) {
5233
- if (assembleErr instanceof CodexContextAttachmentError || params.pluginRuntimeRefreshMessages) throw assembleErr;
5405
+ if (assembleErr instanceof CodexContextAttachmentError || params.continuation || params.pluginRuntimeRefreshMessages) throw assembleErr;
5234
5406
  assertProjectionCurrent();
5235
5407
  embeddedAgentLog.warn("context engine assemble failed; using Codex baseline prompt", { error: formatErrorMessage(assembleErr) });
5236
5408
  }
@@ -5248,7 +5420,7 @@ async function prepareCodexAttemptPrompt(context) {
5248
5420
  bootstrapContextRunKind: params.bootstrapContextRunKind,
5249
5421
  toolAuthority: {
5250
5422
  fingerprint: params.toolAuthorityFingerprint,
5251
- activeToolNames: () => flattenCodexDynamicToolFunctions(toolBridge.availableSpecs).map((tool) => tool.name).filter(isNonEmptyString),
5423
+ activeToolNames: availableToolNames,
5252
5424
  assertActive: connection.assertLegacyCurrent
5253
5425
  }
5254
5426
  });
@@ -5316,53 +5488,49 @@ async function prepareCodexAttemptPrompt(context) {
5316
5488
  ...parentLocalContext,
5317
5489
  skillsInstructions
5318
5490
  }) : buildTurnCollaborationMode(params).settings.developer_instructions) ?? void 0);
5319
- const rebuildCodexPromptBuildFromCurrentProjection = async () => {
5320
- turnState.promptBuild = await buildPromptFromCurrentInputs();
5321
- turnState.codexTurnPromptText = decorateCodexTurnPromptText(turnState.promptBuild);
5322
- };
5323
- const rebuildCodexTurnPromptTextFromCurrentProjection = async () => {
5491
+ const rebuildCodexPromptBuildFromCurrentProjection = async (preserveInstructions = false) => {
5324
5492
  const nextPromptBuild = await buildPromptFromCurrentInputs();
5325
- turnState.promptBuild = {
5493
+ turnState.promptBuild = preserveInstructions ? {
5326
5494
  ...turnState.promptBuild,
5327
5495
  prompt: nextPromptBuild.prompt,
5328
5496
  promptInputRange: nextPromptBuild.promptInputRange
5329
- };
5497
+ } : nextPromptBuild;
5330
5498
  turnState.codexTurnPromptText = decorateCodexTurnPromptText(nextPromptBuild);
5331
5499
  };
5332
- const selectNewerVisibleHistoryAfterBinding = (binding) => {
5500
+ const applyResumeStaleBindingContinuityProjection = async (binding) => {
5333
5501
  const cutoff = Date.parse(binding.historyCoveredThrough ?? "");
5334
- return historyState.messages.filter((message) => {
5502
+ const newerVisibleMessages = historyState.messages.filter((message) => {
5335
5503
  if (message.role !== "user" && message.role !== "assistant" && !isCodexDurableCustomMessage(message)) return false;
5336
5504
  const mirrorIdentity = readMirrorIdentity(message);
5337
5505
  const timestamp = typeof message.timestamp === "number" ? message.timestamp : typeof message.timestamp === "string" ? Date.parse(message.timestamp) : NaN;
5338
5506
  return !("idempotencyKey" in message && typeof message.idempotencyKey === "string" && message.idempotencyKey.startsWith("codex-app-server:")) && !hasCodexMirrorOrigin(message) && !mirrorIdentity?.startsWith("codex-app-server:") && Number.isFinite(timestamp) && timestamp > (Number.isFinite(cutoff) ? cutoff : 0);
5339
5507
  });
5340
- };
5341
- const applyResumeStaleBindingContinuityProjection = async (binding) => {
5342
- const newerVisibleMessages = selectNewerVisibleHistoryAfterBinding(binding);
5343
5508
  if (newerVisibleMessages.length === 0) return false;
5344
5509
  await applyContinuityProjection(newerVisibleMessages);
5345
5510
  return true;
5346
5511
  };
5512
+ let staleBindingContinuityForcedFreshStart = false;
5513
+ let inactiveThreadBootstrapBindingForcedFreshStart = connection.initialInactiveThreadBootstrapBindingForcedFreshStart;
5347
5514
  const precomputeNoContextEngineStaleBindingProjection = async () => {
5348
- promptState.precomputedStaleBindingContinuityProjectionApplied = false;
5349
- promptState.staleBindingContinuityForcedFreshStart = false;
5350
5515
  const binding = mutable.startupBinding;
5351
- if (activeContextEngine || !binding?.threadId || binding.pendingSupervisionBranch) return false;
5516
+ if (activeContextEngine || params.continuation || !binding?.threadId || binding.pendingSupervisionBranch) return false;
5352
5517
  if (isInactiveThreadBootstrapBinding(binding)) {
5353
- promptState.inactiveThreadBootstrapBindingForcedFreshStart = true;
5518
+ inactiveThreadBootstrapBindingForcedFreshStart = true;
5354
5519
  return false;
5355
5520
  }
5356
- const projected = await applyResumeStaleBindingContinuityProjection(binding);
5357
- promptState.precomputedStaleBindingContinuityProjectionApplied = projected;
5358
- return projected;
5521
+ return await applyResumeStaleBindingContinuityProjection(binding);
5359
5522
  };
5360
5523
  const applyNoContextEngineContinuityProjection = async (action, binding) => {
5361
5524
  const hasContinuity = historyState.messages.some((message) => message.role === "user" || isCodexDurableCustomMessage(message) || action === "started" && (message.role === "compactionSummary" || message.role === "branchSummary" || message.role === "assistant" && message.content.some((part) => part.type === "text" && part.text.trim())));
5362
- if (activeContextEngine || !hasContinuity && !params.pluginRuntimeRefreshMessages?.length) return false;
5363
- if (action === "resumed" && promptState.precomputedStaleBindingContinuityProjectionApplied) return true;
5364
- if (action === "started" && promptState.staleBindingContinuityForcedFreshStart) return true;
5365
- if (action === "started" && promptState.inactiveThreadBootstrapBindingForcedFreshStart) return false;
5525
+ if (activeContextEngine) return false;
5526
+ if (params.continuation) {
5527
+ await applyContinuityProjection(action === "started" ? historyState.messages : []);
5528
+ return true;
5529
+ }
5530
+ if (!hasContinuity && !params.pluginRuntimeRefreshMessages?.length) return false;
5531
+ if (action === "resumed" && precomputedStaleBindingContinuityProjectionApplied) return true;
5532
+ if (action === "started" && staleBindingContinuityForcedFreshStart) return true;
5533
+ if (action === "started" && inactiveThreadBootstrapBindingForcedFreshStart) return false;
5366
5534
  if (action === "resumed" && binding) return applyResumeStaleBindingContinuityProjection(binding);
5367
5535
  if (action === "started") {
5368
5536
  await applyContinuityProjection(historyState.messages);
@@ -5370,7 +5538,8 @@ async function prepareCodexAttemptPrompt(context) {
5370
5538
  }
5371
5539
  return false;
5372
5540
  };
5373
- if (await precomputeNoContextEngineStaleBindingProjection()) await rebuildCodexPromptBuildFromCurrentProjection();
5541
+ const precomputedStaleBindingContinuityProjectionApplied = await precomputeNoContextEngineStaleBindingProjection();
5542
+ if (precomputedStaleBindingContinuityProjectionApplied) await rebuildCodexPromptBuildFromCurrentProjection();
5374
5543
  const rotateStartupBindingForProjectedTurn = async () => {
5375
5544
  const binding = mutable.startupBinding;
5376
5545
  if (!binding?.threadId) return;
@@ -5395,9 +5564,9 @@ async function prepareCodexAttemptPrompt(context) {
5395
5564
  mutable.startupBinding = startupBindingResolution.binding;
5396
5565
  mutable.startupContextTokens = startupBindingResolution.startupContextTokens;
5397
5566
  if (mutable.startupBinding?.threadId) return;
5398
- promptState.inactiveThreadBootstrapBindingForcedFreshStart = hadInactiveThreadBootstrapBinding;
5399
- promptState.staleBindingContinuityForcedFreshStart = promptState.precomputedStaleBindingContinuityProjectionApplied && !promptState.inactiveThreadBootstrapBindingForcedFreshStart;
5400
- if (promptState.staleBindingContinuityForcedFreshStart) await applyContinuityProjection(historyState.messages);
5567
+ inactiveThreadBootstrapBindingForcedFreshStart = hadInactiveThreadBootstrapBinding;
5568
+ staleBindingContinuityForcedFreshStart = precomputedStaleBindingContinuityProjectionApplied && !inactiveThreadBootstrapBindingForcedFreshStart;
5569
+ if (staleBindingContinuityForcedFreshStart) await applyContinuityProjection(historyState.messages);
5401
5570
  if (activeContextEngine) {
5402
5571
  promptState.contextEngineProjection = void 0;
5403
5572
  await applyActiveContextEngineProjection(void 0);
@@ -5444,7 +5613,7 @@ async function prepareCodexAttemptPrompt(context) {
5444
5613
  Object.assign(systemPromptReport, buildSystemPromptReport(!workspaceReferencesIncluded));
5445
5614
  },
5446
5615
  buildRenderedCodexDeveloperInstructions,
5447
- rebuildCodexTurnPromptTextFromCurrentProjection,
5616
+ rebuildCodexTurnPromptTextFromCurrentProjection: () => rebuildCodexPromptBuildFromCurrentProjection(true),
5448
5617
  applyNoContextEngineContinuityProjection,
5449
5618
  systemPromptReport
5450
5619
  };
@@ -5472,28 +5641,22 @@ function createNativeSubagentAssignmentStore(params) {
5472
5641
  const binding = bindingStore.read(identity);
5473
5642
  if (!binding || !matchesCodexNativeSubagentSubmissionBinding(binding, owner)) throw new Error("Native assignment binding is no longer current.");
5474
5643
  };
5644
+ const mutate = (kind) => (assignment, assertSourceCurrent) => bindingStore.mutate(identity, {
5645
+ kind,
5646
+ owner,
5647
+ assignment
5648
+ }, () => {
5649
+ assertCurrent();
5650
+ assertSourceCurrent();
5651
+ });
5475
5652
  return {
5476
5653
  assertCurrent,
5477
5654
  read: () => {
5478
5655
  assertCurrent();
5479
5656
  return bindingStore.readNativeSubagentAssignments?.(identity, owner) ?? [];
5480
5657
  },
5481
- record: (assignment, assertSourceCurrent) => bindingStore.mutate(identity, {
5482
- kind: "record-native-subagent-assignment",
5483
- owner,
5484
- assignment
5485
- }, () => {
5486
- assertCurrent();
5487
- assertSourceCurrent();
5488
- }),
5489
- consume: (assignment, assertSourceCurrent) => bindingStore.mutate(identity, {
5490
- kind: "consume-native-subagent-assignment",
5491
- owner,
5492
- assignment
5493
- }, () => {
5494
- assertCurrent();
5495
- assertSourceCurrent();
5496
- })
5658
+ record: mutate("record-native-subagent-assignment"),
5659
+ consume: mutate("consume-native-subagent-assignment")
5497
5660
  };
5498
5661
  }
5499
5662
  //#endregion
@@ -5606,14 +5769,8 @@ function prepareCodexAttemptResources(prompt) {
5606
5769
  releaseSharedClientLeaseOnce();
5607
5770
  await retireSharedCodexClientForOneShotCleanup();
5608
5771
  };
5609
- const runCleanupStep = (step, operation) => runAgentCleanupStep({
5610
- runId: params.runId,
5611
- sessionId: params.sessionId,
5612
- step,
5613
- log: embeddedAgentLog,
5614
- cleanup: async () => {
5615
- await operation();
5616
- }
5772
+ const runCleanupStep = (step, operation) => runCodexCleanupStep(params, step, async () => {
5773
+ await operation();
5617
5774
  });
5618
5775
  let nativeSubagentMonitorSettlement;
5619
5776
  let nativeSubagentMonitorGeneration = 0;
@@ -5631,13 +5788,14 @@ function prepareCodexAttemptResources(prompt) {
5631
5788
  const generation = ++nativeSubagentMonitorGeneration;
5632
5789
  const sessionKey = params.sessionKey;
5633
5790
  const storePath = params.sessionTarget?.storePath;
5634
- const parentSession = sessionKey && storePath ? getSessionEntry({
5791
+ const readParentSession = () => sessionKey && storePath ? getSessionEntry({
5635
5792
  agentId: sessionAgentId,
5636
5793
  sessionKey,
5637
5794
  storePath,
5638
5795
  readConsistency: "latest",
5639
5796
  hydrateSkillPromptRefs: false
5640
5797
  }) : void 0;
5798
+ const parentSession = readParentSession();
5641
5799
  const historyOwner = createCodexNativeSubagentHistoryOwner({
5642
5800
  parentThreadId,
5643
5801
  sessionId: params.sessionId,
@@ -5647,13 +5805,7 @@ function prepareCodexAttemptResources(prompt) {
5647
5805
  const { bindingStore, bindingIdentity } = connection;
5648
5806
  const assertParentSessionCurrent = () => {
5649
5807
  if (historyOwner?.lifecycleRevision && sessionKey && storePath) {
5650
- if (getSessionEntry({
5651
- agentId: sessionAgentId,
5652
- sessionKey,
5653
- storePath,
5654
- readConsistency: "latest",
5655
- hydrateSkillPromptRefs: false
5656
- })?.lifecycleRevision !== historyOwner.lifecycleRevision) throw new Error("Native submission session lifecycle is no longer current.");
5808
+ if (readParentSession()?.lifecycleRevision !== historyOwner.lifecycleRevision) throw new Error("Native submission session lifecycle is no longer current.");
5657
5809
  }
5658
5810
  };
5659
5811
  const submissionStore = historyOwner && thread.lifecycle.preserveExistingBinding !== true ? {
@@ -5845,9 +5997,8 @@ function prepareCodexAttemptResources(prompt) {
5845
5997
  requestTimeoutMs: appServer.requestTimeoutMs,
5846
5998
  timeoutFloorMs: options.startupTimeoutFloorMs
5847
5999
  });
5848
- const requesterChannel = params.messageChannel ?? params.messageProvider;
5849
6000
  const requester = buildCodexHookRequester(params);
5850
- const buildNativeHookRelayFinalConfigPatch = async (decision) => {
6001
+ const buildNativeHookRelayFinalConfigPatch = async (decision, relayClient) => {
5851
6002
  state.nativeSpawnAdmissionInstalled = false;
5852
6003
  const previousRelay = state.nativeHookRelay;
5853
6004
  previousRelay?.unregister();
@@ -5884,7 +6035,7 @@ function prepareCodexAttemptResources(prompt) {
5884
6035
  approvalContext: {
5885
6036
  trigger: params.trigger,
5886
6037
  approvalReviewerDeviceId: params.approvalReviewerDeviceId,
5887
- turnSourceChannel: requesterChannel,
6038
+ turnSourceChannel: params.messageChannel ?? params.messageProvider,
5888
6039
  turnSourceTo: params.currentMessagingTarget ?? params.currentChannelId,
5889
6040
  turnSourceAccountId: params.agentAccountId,
5890
6041
  turnSourceThreadId: params.currentThreadTs
@@ -5905,6 +6056,12 @@ function prepareCodexAttemptResources(prompt) {
5905
6056
  tools: decision.nativeModelInputTools,
5906
6057
  readQualification: (threadId) => getCodexInferenceThreadQualification(state.client, threadId)
5907
6058
  } : void 0,
6059
+ remoteCallback: appServer.nativeHookRelay && {
6060
+ config: appServer.nativeHookRelay,
6061
+ client: relayClient,
6062
+ timeoutMs: appServer.requestTimeoutMs,
6063
+ onCleanupFailure: (error) => reportCodexBackgroundCleanupFailure(params, error)
6064
+ },
5908
6065
  assertCurrent: connection.assertLegacyCurrent,
5909
6066
  onPreToolUseFailure: (failure) => {
5910
6067
  const projector = projectorRef.current;
@@ -5940,9 +6097,6 @@ function prepareCodexAttemptResources(prompt) {
5940
6097
  nativeModelAdmission,
5941
6098
  nativeProcessAuthority,
5942
6099
  releaseNativeProcessAuthority,
5943
- markTrajectoryEndRecorded: () => {
5944
- state.trajectoryEndRecorded = true;
5945
- },
5946
6100
  releaseSharedClientLeaseAndRetireOneShotClient,
5947
6101
  releaseSandboxExecEnvironment,
5948
6102
  runCleanupStep,
@@ -5964,32 +6118,6 @@ async function prepareCodexAttemptRoute(resources, turnRuntime, notifications, h
5964
6118
  const { runAbortController } = connection;
5965
6119
  const { state, turnIdRef, completeTurn } = turnRuntime;
5966
6120
  const { noteNotificationReceived, enqueueNotification } = notifications;
5967
- const attachRouteAbort = (route) => {
5968
- const onAbort = () => {
5969
- if (state.completed || state.terminalTurnNotificationQueued || runAbortController.signal.aborted) return;
5970
- const reasonText = formatErrorMessage(route.signal.reason);
5971
- const closedClient = reasonText.includes("turn router closed");
5972
- const closeCause = route.signal.reason instanceof Error && route.signal.reason.cause instanceof Error ? route.signal.reason.cause : void 0;
5973
- state.clientClosedPromptError = closedClient ? "codex app-server client closed before turn completed" : `codex app-server turn route closed before turn completed: ${reasonText}`;
5974
- state.clientClosedDiagnostic = closedClient && closeCause ? formatErrorMessage(closeCause) : void 0;
5975
- state.clientClosedAbort = closedClient;
5976
- const activeTurnId = turnIdRef.current;
5977
- if (activeTurnId) trajectoryRecorder?.recordEvent("turn.client_closed", {
5978
- threadId: resourceState.thread.threadId,
5979
- turnId: activeTurnId
5980
- });
5981
- embeddedAgentLog.warn(state.clientClosedPromptError, {
5982
- threadId: resourceState.thread.threadId,
5983
- turnId: activeTurnId,
5984
- ...state.clientClosedDiagnostic ? { transportError: state.clientClosedDiagnostic } : {}
5985
- });
5986
- runAbortController.abort(closedClient ? "client_closed" : "turn_route_closed");
5987
- completeTurn();
5988
- };
5989
- route.signal.addEventListener("abort", onAbort, { once: true });
5990
- if (route.signal.aborted) onAbort();
5991
- return () => route.signal.removeEventListener("abort", onAbort);
5992
- };
5993
6121
  const ensureCurrentThreadRoute = async () => {
5994
6122
  if (resourceState.turnRoute?.threadId !== resourceState.thread.threadId) {
5995
6123
  await releaseCurrentRoute();
@@ -5997,7 +6125,31 @@ async function prepareCodexAttemptRoute(resources, turnRuntime, notifications, h
5997
6125
  }
5998
6126
  if (!resourceState.routeActivated) {
5999
6127
  if (!resourceState.nativeSubagentMonitor) await registerNativeSubagentMonitor(resourceState.thread.threadId);
6000
- resourceState.detachRouteAbort = attachRouteAbort(resourceState.turnRoute);
6128
+ const route = resourceState.turnRoute;
6129
+ const onAbort = () => {
6130
+ if (state.completed || state.terminalTurnNotificationQueued || runAbortController.signal.aborted) return;
6131
+ const reasonText = formatErrorMessage(route.signal.reason);
6132
+ const closedClient = reasonText.includes("turn router closed");
6133
+ const closeCause = route.signal.reason instanceof Error && route.signal.reason.cause instanceof Error ? route.signal.reason.cause : void 0;
6134
+ state.clientClosedPromptError = closedClient ? "codex app-server client closed before turn completed" : `codex app-server turn route closed before turn completed: ${reasonText}`;
6135
+ state.clientClosedDiagnostic = closedClient && closeCause ? formatErrorMessage(closeCause) : void 0;
6136
+ state.clientClosedAbort = closedClient;
6137
+ const activeTurnId = turnIdRef.current;
6138
+ if (activeTurnId) trajectoryRecorder?.recordEvent("turn.client_closed", {
6139
+ threadId: resourceState.thread.threadId,
6140
+ turnId: activeTurnId
6141
+ });
6142
+ embeddedAgentLog.warn(state.clientClosedPromptError, {
6143
+ threadId: resourceState.thread.threadId,
6144
+ turnId: activeTurnId,
6145
+ ...state.clientClosedDiagnostic ? { transportError: state.clientClosedDiagnostic } : {}
6146
+ });
6147
+ runAbortController.abort(closedClient ? "client_closed" : "turn_route_closed");
6148
+ completeTurn();
6149
+ };
6150
+ route.signal.addEventListener("abort", onAbort, { once: true });
6151
+ if (route.signal.aborted) onAbort();
6152
+ resourceState.detachRouteAbort = () => route.signal.removeEventListener("abort", onAbort);
6001
6153
  await resourceState.turnRoute.activate({
6002
6154
  onNotificationReceived: noteNotificationReceived,
6003
6155
  onNotification: enqueueNotification,
@@ -6011,29 +6163,6 @@ async function prepareCodexAttemptRoute(resources, turnRuntime, notifications, h
6011
6163
  return { ensureCurrentThreadRoute };
6012
6164
  }
6013
6165
  //#endregion
6014
- //#region extensions/codex/src/app-server/run-attempt-client-prewarm.ts
6015
- /** Starts the shared process while tools and prompt context are still being prepared. */
6016
- function prewarmCodexAttemptClient(params) {
6017
- const { connection, authProfileStore, authBindingFingerprint } = params;
6018
- const { appServer, attemptClientFactory, options, pluginConfig, runtimeArtifactRequest, startupAuthRequirement, startupClientAuthProfileId, startupPreparedAuth, agentDir, params: runParams, runAbortController } = connection;
6019
- if (options.clientFactory || attemptClientFactory !== getLeasedSharedCodexAppServerClient || runtimeArtifactRequest) return;
6020
- getSharedCodexAppServerClient({
6021
- assertCurrent: connection.assertLegacyCurrent,
6022
- startOptions: appServer.start,
6023
- pluginConfig,
6024
- ...startupPreparedAuth ? { preparedAuth: startupPreparedAuth } : { authProfileId: startupClientAuthProfileId },
6025
- authRequirement: startupAuthRequirement,
6026
- authProfileStore,
6027
- authBindingFingerprint,
6028
- agentDir,
6029
- config: runParams.config,
6030
- timeoutMs: appServer.requestTimeoutMs,
6031
- abandonSignal: runAbortController.signal
6032
- }).catch((error) => {
6033
- embeddedAgentLog.debug("codex app-server client prewarm failed", { error });
6034
- });
6035
- }
6036
- //#endregion
6037
6166
  //#region extensions/codex/src/app-server/scheduled-configured-mcp-authority.ts
6038
6167
  /** Limits fresh scheduled-authority capture to authenticated local durable operator turns. */
6039
6168
  function canResolveScheduledConfiguredMcpCreatorAuthority(params) {
@@ -6051,10 +6180,27 @@ async function prepareCodexAttemptRuntime(connection) {
6051
6180
  }) : void 0;
6052
6181
  assertScheduledCodexAppAuthorityRuntime(connection, params);
6053
6182
  const attemptAuthProfileStore = preparedAuthBinding?.authProfileStore ?? params.authProfileStore;
6054
- prewarmCodexAttemptClient({
6055
- connection,
6183
+ const clientOptions = {
6184
+ startOptions: appServer.start,
6185
+ pluginConfig,
6186
+ ...startupPreparedAuth ? { preparedAuth: startupPreparedAuth } : { authProfileId: startupClientAuthProfileId },
6187
+ authRequirement: connection.startupAuthRequirement,
6056
6188
  authProfileStore: attemptAuthProfileStore,
6057
- authBindingFingerprint: preparedAuthBinding?.fingerprint
6189
+ authBindingFingerprint: preparedAuthBinding?.fingerprint,
6190
+ ...connection.runtimeArtifactRequest ? {
6191
+ runtimeArtifactMode: "capture",
6192
+ ...connection.runtimeArtifactRequest.expected ? { expectedRuntimeArtifact: connection.runtimeArtifactRequest.expected } : {}
6193
+ } : {},
6194
+ agentDir,
6195
+ config: params.config,
6196
+ abandonSignal: runAbortController.signal,
6197
+ timeoutMs: appServer.requestTimeoutMs
6198
+ };
6199
+ if (!connection.options.clientFactory && attemptClientFactory === getLeasedSharedCodexAppServerClient && !connection.runtimeArtifactRequest) getSharedCodexAppServerClient({
6200
+ ...clientOptions,
6201
+ assertCurrent: connection.assertLegacyCurrent
6202
+ }).catch((error) => {
6203
+ embeddedAgentLog.debug("codex app-server client prewarm failed", { error });
6058
6204
  });
6059
6205
  const effectiveContextWindowInfo = usesSupervisionConnection ? void 0 : params.contextWindowInfo;
6060
6206
  const effectiveContextTokenBudget = usesSupervisionConnection ? void 0 : params.contextTokenBudget;
@@ -6099,7 +6245,7 @@ async function prepareCodexAttemptRuntime(connection) {
6099
6245
  agentDir,
6100
6246
  config: params.config
6101
6247
  });
6102
- const startupEnvApiKeyCacheKey = usesSupervisionConnection ? void 0 : startupPreparedAuth || startupAuthProfileId ? void 0 : resolveCodexAppServerFallbackApiKeyCacheKey({ startOptions: appServer.start });
6248
+ const startupEnvApiKeyCacheKey = usesSupervisionConnection || startupPreparedAuth || startupAuthProfileId ? void 0 : resolveCodexAppServerFallbackApiKeyCacheKey({ startOptions: appServer.start });
6103
6249
  preDynamicStartupStages.mark("auth-cache");
6104
6250
  const codexMcpToolOverrides = resolveCodexMcpToolOverridesForAgent(params.config, {
6105
6251
  agentId: sessionAgentId,
@@ -6147,22 +6293,9 @@ async function prepareCodexAttemptRuntime(connection) {
6147
6293
  });
6148
6294
  if (nativeToolSurfaceEnabled && sandbox?.enabled && sandbox.backend && params.hostCapabilities.retainSourceAuthority) {
6149
6295
  const client = await attemptClientFactory({
6296
+ ...clientOptions,
6150
6297
  assertCurrent: connection.assertCurrent,
6151
- startOptions: appServer.start,
6152
- pluginConfig,
6153
- ...startupPreparedAuth ? { preparedAuth: startupPreparedAuth } : { authProfileId: startupClientAuthProfileId },
6154
- authRequirement: connection.startupAuthRequirement,
6155
- authProfileStore: attemptAuthProfileStore,
6156
- authBindingFingerprint: preparedAuthBinding?.fingerprint,
6157
- ...connection.runtimeArtifactRequest ? {
6158
- runtimeArtifactMode: "capture",
6159
- ...connection.runtimeArtifactRequest.expected ? { expectedRuntimeArtifact: connection.runtimeArtifactRequest.expected } : {}
6160
- } : {},
6161
- agentId: sessionAgentId,
6162
- agentDir,
6163
- config: params.config,
6164
- abandonSignal: runAbortController.signal,
6165
- timeoutMs: appServer.requestTimeoutMs
6298
+ agentId: sessionAgentId
6166
6299
  });
6167
6300
  try {
6168
6301
  connection.assertCurrent();
@@ -6221,6 +6354,7 @@ async function prepareCodexAttemptRuntime(connection) {
6221
6354
  preDynamicStartupStages.mark("context-engine-support");
6222
6355
  return {
6223
6356
  connection,
6357
+ clientOptions,
6224
6358
  preparedAuthBinding,
6225
6359
  runtimeParams,
6226
6360
  effectiveContextWindowInfo,
@@ -6280,27 +6414,18 @@ function toTranscriptToolResultContentItem(item) {
6280
6414
  type: "text",
6281
6415
  text: typeof record.text === "string" ? record.text : ""
6282
6416
  };
6283
- if (record.type === "inputImage") return typeof record.imageUrl === "string" ? {
6417
+ if (record.type === "inputImage" && typeof record.imageUrl === "string") return {
6284
6418
  type: "image",
6285
6419
  url: record.imageUrl
6286
- } : {
6287
- type: "text",
6288
- text: formatUnsupportedCodexDynamicToolOutput(record.type)
6289
6420
  };
6421
+ const rawType = typeof record.type === "string" ? record.type.replace(/\s+/g, " ").trim() : "";
6290
6422
  return {
6291
6423
  type: "text",
6292
- text: formatUnsupportedCodexDynamicToolOutput(record.type)
6424
+ text: `[Unsupported Codex dynamic tool output: ${rawType ? truncateUtf16Safe(rawType, 80) : "unknown"}${rawType.length > 80 ? "..." : ""}]`
6293
6425
  };
6294
6426
  }
6295
- function formatUnsupportedCodexDynamicToolOutput(type) {
6296
- const rawType = typeof type === "string" ? type.replace(/\s+/g, " ").trim() : "";
6297
- return `[Unsupported Codex dynamic tool output: ${rawType ? truncateUtf16Safe(rawType, 80) : "unknown"}${rawType.length > 80 ? "..." : ""}]`;
6298
- }
6299
6427
  function resolveCodexDynamicToolDirectNames(params, registeredTools, hostSystemAgentActive = false) {
6300
- const names = [];
6301
- if (hostSystemAgentActive && isSystemAgentOnlyCodexDynamicToolAllowlist(params.toolsAllow)) names.push("openclaw");
6302
- if (registeredTools.some((tool) => tool.name === "message")) names.push("message");
6303
- return names;
6428
+ return [...hostSystemAgentActive && isSystemAgentOnlyCodexDynamicToolAllowlist(params.toolsAllow) ? ["openclaw"] : [], ...registeredTools.some((tool) => tool.name === "message") ? ["message"] : []];
6304
6429
  }
6305
6430
  //#endregion
6306
6431
  //#region extensions/codex/src/app-server/run-attempt-server-requests.ts
@@ -6318,7 +6443,7 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
6318
6443
  const autoApprove = shouldAutoApproveCodexAppServerApprovals(appServer);
6319
6444
  const { compactionPlanState, toolBridge, toolOutcomeOrdinals, suppressedDynamicToolOutcomeOrdinals, allocateCodexToolOutcomeOrdinal } = attemptTools;
6320
6445
  const { state, turnIdRef, userInputBridgeRef, openClawDynamicToolExecutions, pendingOpenClawDynamicToolCompletionIds, noteProgress } = turnRuntime;
6321
- const { emitExecutionPhaseOnce, scheduleTurnReleaseAfterTerminalDynamicTool, scheduleTerminalDynamicToolReleaseCheck } = lifecycle;
6446
+ const { emitExecutionPhaseOnce, recordDynamicToolResult, scheduleTerminalDynamicToolReleaseCheck } = lifecycle;
6322
6447
  let refreshDrain;
6323
6448
  let refreshStopping = false;
6324
6449
  const settlePluginRuntimeRefresh = async (turnId) => {
@@ -6452,24 +6577,21 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
6452
6577
  });
6453
6578
  setExecutionTimeoutMs?.(dynamicToolTimeoutMs);
6454
6579
  const toolStartedAt = Date.now();
6455
- const diagnosticContext = {
6580
+ const diagnostics = createCodexDynamicToolDiagnostics({
6456
6581
  call,
6457
6582
  agentId: sessionAgentId,
6458
6583
  runId: params.runId,
6459
6584
  sessionId: params.sessionId,
6460
6585
  sessionKey: params.sessionKey
6461
- };
6586
+ });
6462
6587
  let terminalDiagnosticObserved = false;
6463
6588
  const unsubscribeToolDiagnosticObserver = onInternalDiagnosticEvent((event) => {
6464
- if (isDynamicToolTerminalDiagnosticEvent(event) && isMatchingDynamicToolTerminalDiagnostic({
6465
- ...diagnosticContext,
6466
- event
6467
- })) terminalDiagnosticObserved = true;
6589
+ if (diagnostics.matchesTerminal(event)) terminalDiagnosticObserved = true;
6468
6590
  }, { include: DYNAMIC_TOOL_TERMINAL_DIAGNOSTIC_TYPES });
6469
6591
  try {
6470
6592
  const { execution } = openClawDynamicToolExecutions.claim(call, async () => {
6471
6593
  await projector?.transcriptCheckpoint.flush();
6472
- emitDynamicToolStartedDiagnostic(diagnosticContext);
6594
+ diagnostics.started();
6473
6595
  const response = await handleDynamicToolCallWithTimeout({
6474
6596
  call,
6475
6597
  toolBridge,
@@ -6551,30 +6673,18 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
6551
6673
  data: activity
6552
6674
  });
6553
6675
  }
6554
- if (!terminalDiagnosticObserved && !hasPendingDynamicToolTerminalDiagnostic(diagnosticContext)) emitDynamicToolTerminalDiagnostic({
6555
- ...diagnosticContext,
6556
- response,
6557
- durationMs: toolDurationMs
6558
- });
6676
+ if (!terminalDiagnosticObserved && !diagnostics.hasPendingTerminal()) diagnostics.terminal(response, toolDurationMs);
6559
6677
  pendingOpenClawDynamicToolCompletionIds.delete(call.callId);
6560
6678
  if (params.pluginRuntimeRefreshPending?.()) await settlePluginRuntimeRefresh(turnId);
6561
- else if (response.terminate === true && response.success) scheduleTurnReleaseAfterTerminalDynamicTool({
6679
+ else recordDynamicToolResult({
6562
6680
  call,
6563
6681
  response,
6564
6682
  durationMs: toolDurationMs
6565
6683
  });
6566
- else if (response.asyncStarted === true) scheduleTerminalDynamicToolReleaseCheck();
6567
- else {
6568
- state.currentTurnHadNonTerminalDynamicToolResult = true;
6569
- state.pendingTerminalDynamicToolRelease = void 0;
6570
- }
6571
6684
  return protocolResponse;
6572
6685
  } catch (error) {
6573
6686
  pendingOpenClawDynamicToolCompletionIds.delete(call.callId);
6574
- if (!terminalDiagnosticObserved && !hasPendingDynamicToolTerminalDiagnostic(diagnosticContext)) emitDynamicToolErrorDiagnostic({
6575
- ...diagnosticContext,
6576
- durationMs: Math.max(0, Date.now() - toolStartedAt)
6577
- });
6687
+ if (!terminalDiagnosticObserved && !diagnostics.hasPendingTerminal()) diagnostics.error(Math.max(0, Date.now() - toolStartedAt));
6578
6688
  await settlePluginRuntimeRefresh(turnId);
6579
6689
  throw error;
6580
6690
  } finally {
@@ -6595,7 +6705,7 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
6595
6705
  //#region extensions/codex/src/app-server/attempt-runtime-artifact.ts
6596
6706
  async function verifyStartupArtifact(params) {
6597
6707
  if (!params.request) return;
6598
- const { readCodexAppServerClientRuntimeArtifact, validateCodexAppServerRuntimeArtifact } = await import("./runtime-artifact-CUTOOnKw.mjs");
6708
+ const { readCodexAppServerClientRuntimeArtifact, validateCodexAppServerRuntimeArtifact } = await import("./runtime-artifact-C13pR7tD.mjs");
6599
6709
  const runtimeArtifact = readCodexAppServerClientRuntimeArtifact(params.client);
6600
6710
  const expected = params.request.expected;
6601
6711
  const matchesExpected = !expected || runtimeArtifact?.id === expected.id && runtimeArtifact.fingerprint === expected.fingerprint;
@@ -6612,7 +6722,7 @@ function startCodexComputerUseHealthMonitor(params) {
6612
6722
  const state = getComputerUseHealthMonitorState();
6613
6723
  const existing = state.monitors.get(params.client);
6614
6724
  if (!params.config.enabled || !params.config.healthCheckEnabled) {
6615
- if (existing) clearComputerUseHealthMonitor(params.client, existing);
6725
+ clearComputerUseHealthMonitor(params.client, existing);
6616
6726
  return {
6617
6727
  started: false,
6618
6728
  reason: params.config.enabled ? "health_disabled" : "disabled"
@@ -6632,7 +6742,7 @@ function startCodexComputerUseHealthMonitor(params) {
6632
6742
  intervalMs,
6633
6743
  reason: "already_started"
6634
6744
  };
6635
- if (existing) clearComputerUseHealthMonitor(params.client, existing);
6745
+ clearComputerUseHealthMonitor(params.client, existing);
6636
6746
  const monitor = {
6637
6747
  fingerprint,
6638
6748
  timer: setInterval(() => {
@@ -6643,8 +6753,7 @@ function startCodexComputerUseHealthMonitor(params) {
6643
6753
  };
6644
6754
  monitor.timer.unref?.();
6645
6755
  monitor.disposeCloseHandler = params.client.addCloseHandler((client) => {
6646
- const active = state.monitors.get(client);
6647
- if (active) clearComputerUseHealthMonitor(client, active);
6756
+ clearComputerUseHealthMonitor(client, state.monitors.get(client));
6648
6757
  });
6649
6758
  state.monitors.set(params.client, monitor);
6650
6759
  return {
@@ -6677,7 +6786,7 @@ async function runCodexComputerUseHealthProbe(client, config, monitor, tools) {
6677
6786
  }
6678
6787
  if (repair?.attempted && repair.warnings.length === 0) embeddedAgentLog.info("codex computer-use periodic health reloaded MCP servers", { mcpServerName: config.mcpServerName });
6679
6788
  } catch (error) {
6680
- embeddedAgentLog.warn("codex computer-use periodic health probe crashed", {
6789
+ embeddedAgentLog.warn("codex computer-use periodic health check crashed", {
6681
6790
  mcpServerName: config.mcpServerName,
6682
6791
  error: error instanceof Error ? error.message : String(error)
6683
6792
  });
@@ -6686,6 +6795,7 @@ async function runCodexComputerUseHealthProbe(client, config, monitor, tools) {
6686
6795
  }
6687
6796
  }
6688
6797
  function clearComputerUseHealthMonitor(client, monitor) {
6798
+ if (!monitor) return;
6689
6799
  clearInterval(monitor.timer);
6690
6800
  monitor.disposeCloseHandler();
6691
6801
  getComputerUseHealthMonitorState().monitors.delete(client);
@@ -6699,8 +6809,8 @@ const CODEX_APP_SERVER_STARTUP_MAX_ATTEMPTS = 3;
6699
6809
  */
6700
6810
  async function startCodexAttemptThread(params) {
6701
6811
  let pluginAppServer = params.appServer;
6702
- const startupRuntimeAuthProfileId = params.startupPreparedAuth?.kind === "profile" ? params.startupPreparedAuth.profileId : params.startupAuthProfileId ?? void 0;
6703
- const startupRuntimeAuthProfileStore = params.startupPreparedAuth?.kind === "profile" ? params.startupPreparedAuth.store : void 0;
6812
+ const startupRuntimeAuthProfileId = params.clientOptions.preparedAuth?.kind === "profile" ? params.clientOptions.preparedAuth.profileId : params.clientOptions.authProfileId ?? void 0;
6813
+ const startupRuntimeAuthProfileStore = params.clientOptions.preparedAuth?.kind === "profile" ? params.clientOptions.preparedAuth.store : void 0;
6704
6814
  let releaseSharedClientLease;
6705
6815
  let startupClientForAbandonedRequestCleanup;
6706
6816
  let releaseStartupResourcesOnTimeout;
@@ -6722,12 +6832,13 @@ async function startCodexAttemptThread(params) {
6722
6832
  },
6723
6833
  operation: async () => {
6724
6834
  const threadConfig = mergeCodexThreadConfigs(params.configuredMcpDynamicSurface ? void 0 : params.bundleMcpThreadConfig?.configPatch);
6725
- const { pluginThreadConfigRequired, pluginThreadConfigPluginConfig, resolvedPluginPolicy, enabledPluginConfigKeys } = resolveCodexPluginThreadConfigStartupPolicy({
6835
+ const pluginStartupPolicy = resolveCodexPluginThreadConfigStartupPolicy({
6726
6836
  pluginConfig: params.pluginConfig,
6727
6837
  nativeToolSurfaceEnabled: params.nativeToolSurfaceEnabled,
6728
- hostedAppsSupported: !isCodexResponsesOAuth(params.startupPreparedAuth),
6838
+ hostedAppsSupported: !isCodexResponsesOAuth(params.clientOptions.preparedAuth),
6729
6839
  scheduledRuntimeAuthority: params.buildAttemptParams().scheduledRuntimeAuthority
6730
6840
  });
6841
+ const { pluginThreadConfigRequired, resolvedPluginPolicy, enabledPluginConfigKeys } = pluginStartupPolicy;
6731
6842
  pluginAppServer = resolvedPluginPolicy?.enabled === true || params.computerUseConfig.enabled || params.nativeToolSurfaceEnabled && params.configuredMcpOwnershipVersion !== 1 && hasCodexMcpToolApprovalOverrides(params.config?.mcp?.servers, params.bundleMcpThreadConfig.userStaticServerNames, params.bundleMcpThreadConfig.configPatch?.mcp_servers) ? {
6732
6843
  ...params.appServer,
6733
6844
  approvalPolicy: withMcpElicitationsApprovalPolicy(params.appServer.approvalPolicy)
@@ -6743,20 +6854,14 @@ async function startCodexAttemptThread(params) {
6743
6854
  params.assertCurrent?.();
6744
6855
  if (startupAbandonController.signal.aborted) throw new CodexAppServerStartupError("aborted");
6745
6856
  startupClient = await params.attemptClientFactory({
6857
+ ...params.clientOptions,
6746
6858
  assertCurrent: () => {
6747
6859
  params.assertCurrent?.();
6748
6860
  params.authority?.assertLegacyCurrent();
6749
6861
  },
6750
6862
  startOptions: params.appServer.start,
6751
6863
  pluginConfig: params.pluginConfig,
6752
- ...params.startupPreparedAuth ? { preparedAuth: params.startupPreparedAuth } : { authProfileId: params.startupAuthProfileId },
6753
- authRequirement: params.startupAuthRequirement,
6754
6864
  authProfileStore: attemptParams.authProfileStore,
6755
- authBindingFingerprint: params.startupAuthBindingFingerprint,
6756
- ...params.runtimeArtifactRequest ? {
6757
- runtimeArtifactMode: "capture",
6758
- ...params.runtimeArtifactRequest.expected ? { expectedRuntimeArtifact: params.runtimeArtifactRequest.expected } : {}
6759
- } : {},
6760
6865
  agentId: params.sessionAgentId,
6761
6866
  agentDir: params.agentDir,
6762
6867
  config: params.config,
@@ -6789,7 +6894,7 @@ async function startCodexAttemptThread(params) {
6789
6894
  ensureCodexAppServerClientRuntime(activeStartupClient, {
6790
6895
  agentDir: params.agentDir,
6791
6896
  authProfileId: startupRuntimeAuthProfileId,
6792
- authMode: params.startupPreparedAuth?.kind === "api-key" || isCodexResponsesOAuth(params.startupPreparedAuth) ? "prepared-api-key" : "profile",
6897
+ authMode: params.clientOptions.preparedAuth?.kind === "api-key" || isCodexResponsesOAuth(params.clientOptions.preparedAuth) ? "prepared-api-key" : "profile",
6793
6898
  authProfileStore: startupRuntimeAuthProfileStore ?? attemptParams.authProfileStore,
6794
6899
  config: params.config
6795
6900
  });
@@ -6834,11 +6939,11 @@ async function startCodexAttemptThread(params) {
6834
6939
  appServerVersion: activeStartupClient.getServerVersion(),
6835
6940
  runtimeIdentity: startupRuntimeIdentity
6836
6941
  });
6837
- const basePluginThreadConfigInputFingerprint = pluginThreadConfigRequired ? buildCodexPluginThreadConfigInputFingerprint({
6838
- pluginConfig: pluginThreadConfigPluginConfig,
6839
- appCacheKey: pluginAppCacheKey
6840
- }) : void 0;
6841
- const pluginThreadConfigInputFingerprint = basePluginThreadConfigInputFingerprint ? buildScheduledCodexAppAuthorityInputFingerprint(basePluginThreadConfigInputFingerprint, attemptParams.scheduledRuntimeAuthority) : void 0;
6942
+ const createPluginThreadConfig = prepareCodexPluginThreadConfigStartupProvider({
6943
+ startupPolicy: pluginStartupPolicy,
6944
+ appCacheKey: pluginAppCacheKey,
6945
+ scheduledRuntimeAuthority: attemptParams.scheduledRuntimeAuthority
6946
+ });
6842
6947
  embeddedAgentLog.debug("codex plugin thread config eligibility", buildCodexPluginThreadConfigEligibilityLogData({
6843
6948
  sessionId: attemptParams.sessionId,
6844
6949
  sessionKey: attemptParams.sessionKey ?? "",
@@ -6930,10 +7035,9 @@ async function startCodexAttemptThread(params) {
6930
7035
  config: threadConfig,
6931
7036
  shellEnvironment: params.shellEnvironment,
6932
7037
  shellPathPrepend: params.shellPathPrepend,
7038
+ shellGitConfigParameters: params.shellGitConfigParameters,
6933
7039
  disableLoginShell: params.disableLoginShell,
6934
- finalConfigPatch: params.finalConfigPatch,
6935
7040
  buildFinalConfigPatch: params.buildFinalConfigPatch,
6936
- nativeHookRelayGeneration: params.nativeHookRelayGeneration,
6937
7041
  nativeHookRelayRequired: params.nativeHookRelayRequired,
6938
7042
  nativeModelAdmission: params.nativeModelAdmission,
6939
7043
  nativeCodeModeEnabled: params.nativeToolSurfaceEnabled,
@@ -6947,18 +7051,13 @@ async function startCodexAttemptThread(params) {
6947
7051
  appServerRuntimeFingerprint,
6948
7052
  contextEngineProjection: params.contextEngineProjection,
6949
7053
  signal,
6950
- pluginThreadConfig: pluginThreadConfigRequired ? createCodexPluginThreadConfigStartupProvider({
6951
- inputFingerprint: pluginThreadConfigInputFingerprint,
6952
- enabledPluginConfigKeys,
6953
- policy: resolvedPluginPolicy,
7054
+ pluginThreadConfig: createPluginThreadConfig?.({
6954
7055
  requestTimeoutMs: params.appServer.requestTimeoutMs,
6955
7056
  signal,
6956
- pluginConfig: pluginThreadConfigPluginConfig,
6957
7057
  client: activeStartupClient,
6958
7058
  configCwd: startupExecutionCwd,
6959
- appCacheKey: pluginAppCacheKey,
6960
7059
  scheduledRuntimeAuthority: attemptParams.scheduledRuntimeAuthority
6961
- }) : void 0
7060
+ })
6962
7061
  });
6963
7062
  try {
6964
7063
  const startupThread = await startOrResumeThread(buildThreadLifecycleParams(startupAbandonController.signal, reserveStartupThread));
@@ -7088,10 +7187,10 @@ async function startCodexAttemptRuntime(resources) {
7088
7187
  const { prompt, state, trajectoryRecorder, startupTimeoutMs, buildNativeHookRelayFinalConfigPatch } = resources;
7089
7188
  const { context, turnState, rebuildCodexTurnPromptTextFromCurrentProjection, applyNoContextEngineContinuityProjection } = prompt;
7090
7189
  const { runtime, attemptTools, promptState } = context;
7091
- const { connection, runtimeParams, preparedAuthBinding, startupAuthAccountCacheKey, startupEnvApiKeyCacheKey, bundleMcpThreadConfig, nativeToolSurfaceEnabled, nativeProviderWebSearchSupport, effectiveRuntimeModelId, sandboxExecServerEnabled } = runtime;
7190
+ const { connection, runtimeParams, clientOptions, startupAuthAccountCacheKey, startupEnvApiKeyCacheKey, bundleMcpThreadConfig, nativeToolSurfaceEnabled, nativeProviderWebSearchSupport, effectiveRuntimeModelId, sandboxExecServerEnabled } = runtime;
7092
7191
  const { toolBridge, toolState } = attemptTools;
7093
7192
  const developerInstructions = joinPresentSections(turnState.promptBuild.developerInstructions, attemptTools.configuredMcp?.diagnosticNotice);
7094
- const { params, attemptClientFactory, bindingStore, appServer, pluginConfig, computerUseConfig, startupClientAuthProfileId, runtimeArtifactRequest, startupPreparedAuth, agentDir, sessionAgentId, effectiveWorkspace, effectiveCwd, sandbox, runAbortController, usesSupervisionConnection, resolveReviewerPolicyContext, resolveRuntimeOptionsForCurrentBinding, startupAuthProfileId, startupAuthRequirement } = connection;
7193
+ const { params, attemptClientFactory, bindingStore, appServer, pluginConfig, computerUseConfig, runtimeArtifactRequest, agentDir, sessionAgentId, effectiveWorkspace, effectiveCwd, sandbox, runAbortController, usesSupervisionConnection, resolveReviewerPolicyContext, resolveRuntimeOptionsForCurrentBinding, startupAuthProfileId } = connection;
7095
7194
  let pluginAppServer = withCodexAppServerFastModeServiceTier(appServer, runtimeParams);
7096
7195
  const loopDetectionEnabled = (sessionAgentId && params.config ? resolveAgentConfig(params.config, sessionAgentId)?.tools?.loopDetection?.enabled : void 0) ?? params.config?.tools?.loopDetection?.enabled ?? false;
7097
7196
  try {
@@ -7108,17 +7207,15 @@ async function startCodexAttemptRuntime(resources) {
7108
7207
  appServer: pluginAppServer,
7109
7208
  pluginConfig,
7110
7209
  computerUseConfig,
7111
- startupAuthProfileId: startupClientAuthProfileId,
7112
- startupAuthRequirement,
7113
- startupAuthBindingFingerprint: preparedAuthBinding?.fingerprint,
7210
+ clientOptions,
7114
7211
  ...runtimeArtifactRequest ? { runtimeArtifactRequest } : {},
7115
- startupPreparedAuth,
7116
7212
  startupAuthAccountCacheKey,
7117
7213
  startupEnvApiKeyCacheKey,
7118
7214
  agentDir,
7119
7215
  config: params.config,
7120
7216
  shellEnvironment: connection.shellEnvironment,
7121
7217
  shellPathPrepend: connection.shellPathPrepend,
7218
+ shellGitConfigParameters: connection.shellGitConfigParameters,
7122
7219
  disableLoginShell: connection.disableLoginShell,
7123
7220
  buildAttemptParams: () => ({ ...runtimeParams }),
7124
7221
  ...effectiveRuntimeModelId !== runtimeParams.modelId ? { runtimeModelId: effectiveRuntimeModelId } : {},
@@ -7166,10 +7263,7 @@ async function startCodexAttemptRuntime(resources) {
7166
7263
  if (usesSupervisionConnection && (state.thread.connectionScope !== "supervision" || state.thread.supervisionSourceThreadId !== connection.mutable.startupBinding?.supervisionSourceThreadId)) throw new Error("Codex supervised thread lost its private connection ownership");
7167
7264
  if (state.thread.lifecycle.action === "started" || state.thread.lifecycle.action === "forked") {
7168
7265
  const activePolicy = resolveReviewerPolicyContext(state.thread);
7169
- const activeConfig = await resolveRuntimeOptionsForCurrentBinding({
7170
- modelProvider: activePolicy.modelProvider,
7171
- model: activePolicy.model
7172
- });
7266
+ const activeConfig = await resolveRuntimeOptionsForCurrentBinding(activePolicy);
7173
7267
  connection.assertCurrent();
7174
7268
  const activeAppServer = resolveCodexAppServerForModelProvider({
7175
7269
  appServer: activeConfig,
@@ -7226,10 +7320,11 @@ function resolveInactiveCodexHeartbeatResponseDescriptor(params) {
7226
7320
  description: descriptor.description
7227
7321
  } : void 0;
7228
7322
  }
7229
- /** Keeps the thread-stable heartbeat endpoint executable on ordinary Codex turns. */
7230
- function createInactiveCodexHeartbeatResponseTool(descriptor) {
7323
+ function selectInactiveCodexHeartbeatResponseTool(params) {
7324
+ if (params.disableTools) return;
7325
+ const descriptor = params.descriptor;
7231
7326
  if (descriptor.name !== HEARTBEAT_RESPONSE_TOOL_NAME) throw new Error(`Expected ${HEARTBEAT_RESPONSE_TOOL_NAME}, received ${descriptor.name}`);
7232
- return {
7327
+ const tool = {
7233
7328
  name: descriptor.name,
7234
7329
  label: descriptor.name,
7235
7330
  description: descriptor.description,
@@ -7250,10 +7345,7 @@ function createInactiveCodexHeartbeatResponseTool(descriptor) {
7250
7345
  };
7251
7346
  }
7252
7347
  };
7253
- }
7254
- function selectInactiveCodexHeartbeatResponseTool(params) {
7255
- if (params.disableTools) return;
7256
- const allowed = applyEmbeddedAttemptToolsAllow([createInactiveCodexHeartbeatResponseTool(params.descriptor)], params.toolsAllow);
7348
+ const allowed = applyEmbeddedAttemptToolsAllow([tool], params.toolsAllow);
7257
7349
  return filterCodexDynamicTools(allowed, params.pluginConfig)[0];
7258
7350
  }
7259
7351
  //#endregion
@@ -7405,23 +7497,11 @@ async function prepareCodexAttemptTools(runtime) {
7405
7497
  let scopedMcpTools;
7406
7498
  let toolDisposal;
7407
7499
  const disposeTools = (reason) => toolDisposal ??= (async () => {
7408
- await runAgentCleanupStep({
7409
- runId: params.runId,
7410
- sessionId: params.sessionId,
7411
- step: "codex-dynamic-tool-cleanup",
7412
- log: embeddedAgentLog,
7413
- cleanup: async () => {
7414
- const errors = (await Promise.allSettled(runCleanups.splice(0).map(async (cleanup) => await cleanup(reason)))).flatMap((result) => result.status === "rejected" ? [result.reason] : []);
7415
- if (params.oneShotCliRun && errors.length) throw new AggregateError(errors, "Codex tool cleanup failed");
7416
- }
7417
- });
7418
- for (const [step, materialized] of [["codex-scoped-mcp-dispose", scopedMcpTools], ["codex-configured-mcp-dispose", configuredMcp]]) await runAgentCleanupStep({
7419
- runId: params.runId,
7420
- sessionId: params.sessionId,
7421
- step,
7422
- log: embeddedAgentLog,
7423
- cleanup: async () => materialized?.dispose()
7500
+ await runCodexCleanupStep(params, "codex-dynamic-tool-cleanup", async () => {
7501
+ const errors = (await Promise.allSettled(runCleanups.splice(0).map(async (cleanup) => await cleanup(reason)))).flatMap((result) => result.status === "rejected" ? [result.reason] : []);
7502
+ if (params.oneShotCliRun && errors.length) throw new AggregateError(errors, "Codex tool cleanup failed");
7424
7503
  });
7504
+ for (const [step, materialized] of [["codex-scoped-mcp-dispose", scopedMcpTools], ["codex-configured-mcp-dispose", configuredMcp]]) await runCodexCleanupStep(params, step, async () => materialized?.dispose());
7425
7505
  })();
7426
7506
  try {
7427
7507
  const tools = await buildDynamicTools({
@@ -7452,7 +7532,7 @@ async function prepareCodexAttemptTools(runtime) {
7452
7532
  sessionId: params.sessionId,
7453
7533
  runId: params.runId,
7454
7534
  agentId: policyAgentId,
7455
- agentDir: agentDir ?? resolveAgentDir$1(params.config ?? {}, sessionAgentId),
7535
+ agentDir: agentDir ?? resolveAgentDir$2(params.config ?? {}, sessionAgentId),
7456
7536
  agentAccountId: params.agentAccountId,
7457
7537
  messageProvider: params.messageProvider ?? params.messageChannel,
7458
7538
  messageChannel: params.messageChannel,
@@ -7706,14 +7786,12 @@ async function resolveCodexExplicitSkillInputs(params) {
7706
7786
  async function prepareCodexProviderReviewContinuation(params) {
7707
7787
  const acknowledgment = params.acknowledgment;
7708
7788
  if (!acknowledgment) return;
7709
- let nativeChanged = false;
7710
- let dispatched = false;
7711
- let dispose = () => {};
7789
+ let state = "prepared";
7712
7790
  const assertCurrent = () => {
7713
7791
  params.signal.throwIfAborted();
7714
7792
  params.assertCurrent();
7715
7793
  acknowledgment.read();
7716
- if (nativeChanged) throw new Error("The native provider review changed before dispatch");
7794
+ if (state === "changed") throw new Error("The native provider review changed before dispatch");
7717
7795
  };
7718
7796
  assertCurrent();
7719
7797
  const snapshot = acknowledgment.read();
@@ -7729,16 +7807,16 @@ async function prepareCodexProviderReviewContinuation(params) {
7729
7807
  assertCurrent();
7730
7808
  const { review } = snapshot;
7731
7809
  if (review.nativeThreadId !== params.turnStartParams.threadId || !review.review?.continuation) throw new Error("Provider review no longer matches the native thread");
7732
- dispose = params.client.addNotificationHandler((notification) => {
7810
+ const dispose = params.client.addNotificationHandler((notification) => {
7733
7811
  const event = notification.params;
7734
7812
  if (!isJsonObject(event) || event.threadId !== review.nativeThreadId) return;
7735
- if (notification.method === "turn/started") nativeChanged = true;
7813
+ if (notification.method === "turn/started") state = "changed";
7736
7814
  else if (notification.method === "turn/completed" || notification.method === "error" && event.willRetry !== true) {
7737
7815
  const turn = isJsonObject(event.turn) ? event.turn : void 0;
7738
7816
  const turnId = turn?.id ?? event.turnId;
7739
7817
  const error = isJsonObject(turn?.error) ? turn.error : isJsonObject(event.error) ? event.error : void 0;
7740
7818
  const failure = readCodexProviderRefusal(typeof error?.message === "string" ? error.message : void 0, error?.codexErrorInfo, { misalignment: error?.misalignment });
7741
- if (turnId !== review.nativeTurnId || turn && turn.status !== "failed" || failure?.category !== "misalignment" || error?.misalignment != null && !isDeepStrictEqual(failure.review, review.review)) nativeChanged = true;
7819
+ if (turnId !== review.nativeTurnId || turn && turn.status !== "failed" || failure?.category !== "misalignment" || error?.misalignment != null && !isDeepStrictEqual(failure.review, review.review)) state = "changed";
7742
7820
  }
7743
7821
  });
7744
7822
  try {
@@ -7772,13 +7850,13 @@ async function prepareCodexProviderReviewContinuation(params) {
7772
7850
  dispose,
7773
7851
  dispatch: () => {
7774
7852
  assertCurrent();
7775
- if (dispatched) throw new Error("Provider review continuation already dispatched");
7776
- dispatched = true;
7853
+ if (state === "dispatched") throw new Error("Provider review continuation already dispatched");
7854
+ state = "dispatched";
7777
7855
  dispose();
7778
7856
  },
7779
7857
  accept: async (turnId) => {
7780
7858
  assertCurrent();
7781
- if (!dispatched) throw new Error("Provider review continuation has not dispatched");
7859
+ if (state !== "dispatched") throw new Error("Provider review continuation has not dispatched");
7782
7860
  await acknowledgment.acceptNativeTurn({
7783
7861
  nativeThreadId: params.turnStartParams.threadId,
7784
7862
  nativeTurnId: turnId,
@@ -7872,14 +7950,6 @@ async function prepareCodexAttemptTurnRequest(resources, turnRuntime, ensureCurr
7872
7950
  embeddedAgentLog.debug("codex app-server model call diagnostic ended with error", { error: formatErrorMessage(error) });
7873
7951
  }
7874
7952
  });
7875
- const throwIfTurnStartAcceptedAfterAbort = () => {
7876
- if (!runAbortController.signal.aborted) return;
7877
- const reason = runAbortController.signal.reason;
7878
- if (reason instanceof Error) throw reason;
7879
- const error = new Error(typeof reason === "string" && reason.length > 0 ? reason : "codex app-server turn start aborted before acceptance");
7880
- error.name = "AbortError";
7881
- throw error;
7882
- };
7883
7953
  const prepareWorkspaceReferences = () => {
7884
7954
  const references = prepareCodexWorkspaceReferences(resourceState.client, resourceState.thread.threadId, workspaceBootstrapContext.promptContext);
7885
7955
  prompt.refreshWorkspaceReferences(references.include);
@@ -7926,7 +7996,7 @@ async function prepareCodexAttemptTurnRequest(resources, turnRuntime, ensureCurr
7926
7996
  enabled: fastMode === "ultrafast" && turnAppServer.enableUltrafast !== false,
7927
7997
  serviceTier: turnStartParams.serviceTier,
7928
7998
  model: turnStartParams.model ?? model,
7929
- modelProvider,
7999
+ modelProvider: modelProvider ?? effectiveRuntimeProviderId,
7930
8000
  client: turnClient,
7931
8001
  timeoutMs: Math.min(params.timeoutMs, 2500),
7932
8002
  signal: runAbortController.signal,
@@ -8032,7 +8102,13 @@ async function prepareCodexAttemptTurnRequest(resources, turnRuntime, ensureCurr
8032
8102
  assertTurnCurrent();
8033
8103
  resourceState.nativeSubagentMonitor?.bindTurn(acceptedTurnId, modelMapping);
8034
8104
  if (upstreamUserText.includes(workspaceBootstrapContext.promptContext ?? "")) references.accepted();
8035
- throwIfTurnStartAcceptedAfterAbort();
8105
+ if (runAbortController.signal.aborted) {
8106
+ const reason = runAbortController.signal.reason;
8107
+ if (reason instanceof Error) throw reason;
8108
+ const error = new Error(typeof reason === "string" && reason.length > 0 ? reason : "codex app-server turn start aborted before acceptance");
8109
+ error.name = "AbortError";
8110
+ throw error;
8111
+ }
8036
8112
  await continuation?.accept(acceptedTurnId);
8037
8113
  return {
8038
8114
  turn: startedTurn,
@@ -8092,7 +8168,7 @@ async function prepareCodexAttemptTurnRequest(resources, turnRuntime, ensureCurr
8092
8168
  //#endregion
8093
8169
  //#region extensions/codex/src/app-server/run-attempt-turn-start.ts
8094
8170
  async function startCodexAttemptTurn(resources, turnRuntime, notifications, requestRuntime) {
8095
- const { prompt, state: resourceState, trajectoryRecorder, markTrajectoryEndRecorded } = resources;
8171
+ const { prompt, state: resourceState, trajectoryRecorder } = resources;
8096
8172
  const { context, turnState, systemPromptReport } = prompt;
8097
8173
  const { runtime, historyState, hookContext, hookRunner } = context;
8098
8174
  const { connection, runtimeParams } = runtime;
@@ -8152,11 +8228,7 @@ async function startCodexAttemptTurn(resources, turnRuntime, notifications, requ
8152
8228
  threadId: resourceState.thread.threadId
8153
8229
  }
8154
8230
  });
8155
- try {
8156
- started = await startCodexTurn();
8157
- } catch (retryError) {
8158
- turnStartError = retryError;
8159
- }
8231
+ started = await startCodexTurn();
8160
8232
  }
8161
8233
  } catch (retrySetupError) {
8162
8234
  turnStartError = retrySetupError;
@@ -8191,7 +8263,7 @@ async function startCodexAttemptTurn(resources, turnRuntime, notifications, requ
8191
8263
  aborted: runAbortController.signal.aborted,
8192
8264
  promptError: message
8193
8265
  });
8194
- markTrajectoryEndRecorded();
8266
+ resourceState.trajectoryEndRecorded = true;
8195
8267
  runAgentHarnessLlmOutputHook({
8196
8268
  event: {
8197
8269
  ...buildLlmOutputEvent(),
@@ -8223,35 +8295,26 @@ async function startCodexAttemptTurn(resources, turnRuntime, notifications, requ
8223
8295
  ctx: hookContext,
8224
8296
  hookRunner
8225
8297
  });
8226
- if (usageLimitError) {
8227
- await markCodexAuthProfileBlockedFromRateLimits({
8228
- params,
8229
- authProfileId: startupAuthProfileId,
8230
- rateLimits: usageLimitError.rateLimitsForProfile
8231
- });
8232
- return { result: buildCodexTurnStartFailureResult({
8233
- params,
8234
- message: usageLimitError.message,
8235
- promptError: new CodexUsageLimitPromptError(usageLimitError.message),
8236
- messagesSnapshot,
8237
- systemPromptReport
8238
- }) };
8239
- }
8240
- if (isCodexContextRestartSelectionChangedError(turnStartError)) return { result: {
8241
- ...buildCodexTurnStartFailureResult({
8242
- params,
8243
- message,
8244
- messagesSnapshot,
8245
- systemPromptReport
8246
- }),
8247
- codexAppServerFailure: {
8248
- kind: "client_closed_before_turn_completed",
8249
- transport: appServer.start.transport,
8250
- threadId: resourceState.thread.threadId,
8251
- replaySafe: true
8252
- }
8253
- } };
8254
- throw turnStartError;
8298
+ if (usageLimitError) await markCodexAuthProfileBlockedFromRateLimits({
8299
+ params,
8300
+ authProfileId: startupAuthProfileId,
8301
+ rateLimits: usageLimitError.rateLimitsForProfile
8302
+ });
8303
+ else if (!isCodexContextRestartSelectionChangedError(turnStartError)) throw turnStartError;
8304
+ const result = buildCodexTurnStartFailureResult({
8305
+ params,
8306
+ message,
8307
+ ...usageLimitError ? { promptError: new CodexUsageLimitPromptError(usageLimitError.message) } : {},
8308
+ messagesSnapshot,
8309
+ systemPromptReport
8310
+ });
8311
+ if (!usageLimitError) result.codexAppServerFailure = {
8312
+ kind: "client_closed_before_turn_completed",
8313
+ transport: appServer.start.transport,
8314
+ threadId: resourceState.thread.threadId,
8315
+ replaySafe: true
8316
+ };
8317
+ return { result };
8255
8318
  }
8256
8319
  }
8257
8320
  if (!started) throw new Error("codex app-server turn/start failed without an error");
@@ -8285,6 +8348,7 @@ var CodexAttemptState = class {
8285
8348
  this.projectionClosed = false;
8286
8349
  this.terminalDynamicToolReleaseCheckScheduled = false;
8287
8350
  this.currentTurnHadNonTerminalDynamicToolResult = false;
8351
+ this.currentTurnHadToolAuthoredFinalReply = false;
8288
8352
  }
8289
8353
  };
8290
8354
  function createCodexAttemptTurnState(resources) {
@@ -8420,10 +8484,13 @@ function createCodexAttemptTurnState(resources) {
8420
8484
  //#endregion
8421
8485
  //#region extensions/codex/src/app-server/run-attempt.ts
8422
8486
  async function runCodexAppServerAttempt(params, options) {
8423
- if (params.requireWorkspaceOnly === true && (params.disableTools === true || typeof params.hostCapabilities?.createToolSurface !== "function")) throw new Error("Codex required-root execution requires an enabled host-mediated tool surface");
8487
+ if (params.requireWorkspaceOnly === true && (params.disableTools === true || typeof params.hostCapabilities?.createToolSurfaceAsync !== "function")) throw new Error("Codex required-root execution requires an enabled host-mediated tool surface");
8424
8488
  const preparation = createCodexAttemptPreparationTiming(params);
8425
8489
  const connection = await preparation.measure("connection", () => prepareCodexAttemptConnection({
8426
- params,
8490
+ params: params.continuation ? {
8491
+ ...params,
8492
+ prompt: `${params.continuation.prompt}\n\n${params.prompt}`
8493
+ } : params,
8427
8494
  options
8428
8495
  }));
8429
8496
  try {