@openclaw/codex 2026.10.1-beta.2 → 2026.10.5-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. package/dist/.setup/{account-usage-runtime-DGqFpAud.mjs → account-usage-runtime-QBZsvZS8.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-CXTudl9p.mjs → apply-CBMV8LN0.mjs} +40 -51
  4. package/dist/.setup/{attempt-client-cleanup-BH0hW2xU.mjs → attempt-client-cleanup-t-kd_1ys.mjs} +6 -6
  5. package/dist/.setup/attempt-terminal-jO5IMj9K.mjs +2 -0
  6. package/dist/.setup/{attempt-workspace-context-BY0jprWJ.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-CGm0UJOr.mjs → auth-cache-key-DyfUvsSa.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-pGsfXcmH.mjs → bounded-turn-CyQVQwGe.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-CqQnsg7T.mjs → build-state-CzLMy1S9.mjs} +1 -1
  14. package/dist/.setup/{capabilities-kQntafj_.mjs → capabilities-DbOzOglY.mjs} +1 -1
  15. package/dist/.setup/{client-catalog-response-Bqp7WG51.mjs → client-catalog-response-DsbEAtpd.mjs} +25 -32
  16. package/dist/.setup/{client-C8lgBOoO.mjs → client-y7nO6X9c.mjs} +198 -247
  17. package/dist/.setup/{command-dispatch-DhBbFIQ5.mjs → command-dispatch-uA9lz2Kf.mjs} +3 -4
  18. package/dist/.setup/{command-formatters-DV3DHhdr.mjs → command-formatters-xW9KpoSZ.mjs} +16 -26
  19. package/dist/.setup/{command-handlers-ztOOzm6O.mjs → command-handlers-VBaJnpZo.mjs} +270 -360
  20. package/dist/.setup/{command-rpc-CuC5fPom.mjs → command-rpc-C9VxOLuG.mjs} +19 -18
  21. package/dist/.setup/{compact-tUb9AYfH.mjs → compact-CD8xJxXS.mjs} +41 -61
  22. package/dist/.setup/{computer-use-BBN9y326.mjs → computer-use-CiToXF5C.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-B3MNMVzb.mjs → conversation-binding-CTSLDM9S.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-CYsMlCuE.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-C8xGEXmR.mjs → dynamic-tool-build-D731PCdv.mjs} +57 -69
  38. package/dist/.setup/{dynamic-tools-DyERJnR6.mjs → dynamic-tools-D0pYbxHH.mjs} +689 -710
  39. package/dist/.setup/{effective-mcp-catalog-C26Mio5l.mjs → effective-mcp-catalog-1hWFKghy.mjs} +11 -20
  40. package/dist/.setup/{elicitation-input-r9axtppm.mjs → elicitation-input-DXG_qaXr.mjs} +14 -20
  41. package/dist/.setup/{ephemeral-turn-D8VcDTNo.mjs → ephemeral-turn-Cphy5Qr_.mjs} +3 -3
  42. package/dist/.setup/{event-projector-assistant-message-BN7CNUB5.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-C0jrcplS.mjs → isolated-completion-Bhqd2yBq.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-BxN0_CYe.mjs → mcp-app-session-preparation-DqSvxFqc.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-DZyNeDKG.mjs → model-catalog-B227ST3D.mjs} +6 -6
  56. package/dist/.setup/{models-DSseKSMg.mjs → models-DdRyi93L.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-BUWIOrSr.mjs +561 -0
  60. package/dist/.setup/{native-mcp-app-CqcPVmhH.mjs → native-mcp-app-CjxJQ4F7.mjs} +6 -6
  61. package/dist/.setup/native-skill-isolation-UMVoNjZz.mjs +391 -0
  62. package/dist/.setup/{native-subagent-monitor-BUYOUp9X.mjs → native-subagent-monitor-iHc8oLg5.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-BJ37d2Og.mjs → plan-C_F3aio0.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-CuahdPLC.mjs → plugin-approval-roundtrip-BSV-51ig.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-BnwHVD_z.mjs → provider-BJ4xhaGX.mjs} +4 -4
  76. package/dist/.setup/{provider-capabilities-D68Whix6.mjs → provider-capabilities-CjRaV3bx.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-jSbhc1sg.mjs → request-Y8dmbqZ3.mjs} +28 -48
  80. package/dist/.setup/{rpc-error-hmWM21RB.mjs → rpc-error-C98SHchT.mjs} +3 -6
  81. package/dist/.setup/{run-attempt-BLDZeYLD.mjs → run-attempt-Dx7a4Mfm.mjs} +927 -849
  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-Bdjw9HEn.mjs → session-catalog-events-DzFlXNUe.mjs} +6 -5
  94. package/dist/.setup/{session-catalog-index-DufISKJ6.mjs → session-catalog-index-DozvkUPd.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-D6IiLtMb.mjs → session-catalog-native-projection-rCKnZud1.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-8aHNwzWD.mjs → session-catalog-projection-DDVmALHj.mjs} +8 -22
  104. package/dist/.setup/session-catalog-source-CygTGmrb.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-Czbchv_O.mjs → session-retirement-IoS3zr17.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-DjZsIwbZ.mjs → settled-turn-finalizer-X-Fylp-u.mjs} +12 -11
  115. package/dist/.setup/{shared-client-qhyYWbew.mjs → shared-client-ByIwuAC-.mjs} +172 -229
  116. package/dist/.setup/{side-question-D3NJlgbl.mjs → side-question-BDUdozFy.mjs} +116 -137
  117. package/dist/.setup/{source-BYu0T780.mjs → source-Bxbqf3S1.mjs} +37 -56
  118. package/dist/.setup/thread-archive-guard-LKdwQKyr.mjs +56 -0
  119. package/dist/.setup/{thread-lifecycle-Cbz_7ySv.mjs → thread-lifecycle-run-CfP4PnEf.mjs} +348 -484
  120. package/dist/.setup/thread-model-selection-DcVebr8N.mjs +61 -0
  121. package/dist/.setup/{thread-ownership-DwuSrt3s.mjs → thread-ownership-Be53aiaG.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-DoNxbhqt.mjs → thread-policy-CHgY-KNl.mjs} +4 -4
  124. package/dist/.setup/thread-requests-BgzJwJtS.mjs +745 -0
  125. package/dist/.setup/{thread-resume-BT6NHMkM.mjs → thread-resume-B2EmMcgE.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-sS69wYnI.mjs → turn-router-DKDAziUW.mjs} +30 -31
  133. package/dist/.setup/upstream-prompt-provenance-Ccd9MFRJ.mjs +44 -0
  134. package/dist/.setup/{upstream-session-fork-ChSld66u.mjs → upstream-session-fork-Djp_yssT.mjs} +50 -43
  135. package/dist/.setup/{usage-D8e8Xiqf.mjs → usage-DQA-peQC.mjs} +4 -4
  136. package/dist/.setup/{usage-limit-error-GbT-5NcW.mjs → usage-limit-error-2t3KBqiX.mjs} +12 -21
  137. package/dist/.setup/web-search-item-CvokaZOo.mjs +20 -0
  138. package/dist/.setup/{web-search-provider.runtime-dL2GD1Kl.mjs → web-search-provider.runtime-BsuCMNix.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-B8LGaZNW.mjs +0 -124
  157. package/dist/.setup/service-tier-normalization-Cei89SW6.mjs +0 -15
  158. package/dist/.setup/shell-dynamic-tools-D3Brj3g9.mjs +0 -85
  159. package/dist/.setup/thread-archive-guard-C9frICzX.mjs +0 -60
  160. package/dist/.setup/thread-requests-CL1e8Wmx.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-CqQnsg7T.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-CzLMy1S9.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-CGm0UJOr.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-DyfUvsSa.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-jSbhc1sg.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-Y8dmbqZ3.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-qhyYWbew.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-ByIwuAC-.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-C8lgBOoO.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-sS69wYnI.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-BH0hW2xU.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-DSseKSMg.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-CL1e8Wmx.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-Cbz_7ySv.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-BUYOUp9X.mjs";
39
- import { a as requestPluginApprovalOutcome } from "./plugin-approval-roundtrip-CuahdPLC.mjs";
40
- import { n as CodexThreadPolicyHandoffError, s as restoreCodexThreadInstructionsAfterCompaction } from "./thread-policy-DoNxbhqt.mjs";
41
- import { c as withExclusiveCodexAppServerThread, r as retainCodexAppServerBindingSubscription, t as isSameCodexAppServerThreadOwner } from "./thread-ownership-DwuSrt3s.mjs";
42
- import { a as resolveCodexPromptError, i as refreshCodexUsageLimitPromptError, n as formatCodexTurnStartUsageLimitError, r as markCodexAuthProfileBlockedFromRateLimits, t as CodexUsageLimitPromptError } from "./usage-limit-error-GbT-5NcW.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-y7nO6X9c.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-DKDAziUW.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-t-kd_1ys.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-DdRyi93L.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-2t3KBqiX.mjs";
41
+ import { c as withExclusiveCodexAppServerThread, r as retainCodexAppServerBindingSubscription, t as isSameCodexAppServerThreadOwner } from "./thread-ownership-Be53aiaG.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-BN7CNUB5.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-C8xGEXmR.mjs";
50
- import { n as resolveCodexPluginThreadConfigStartupPolicy, t as createCodexPluginThreadConfigStartupProvider } from "./plugin-thread-config-deadline-B8LGaZNW.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-CqcPVmhH.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-DyERJnR6.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-BY0jprWJ.mjs";
57
- import { n as captureCodexSettledTurnFinalizationContext } from "./settled-turn-context-BZsMjkIO.mjs";
58
- import { t as resolveCodexProviderWebSearchSupport } from "./provider-capabilities-D68Whix6.mjs";
59
- import { a as runCodexComputerUseLiveTest, i as createComputerUseRequest, t as ensureCodexComputerUse } from "./computer-use-BBN9y326.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-iHc8oLg5.mjs";
44
+ import { a as requestPluginApprovalOutcome } from "./plugin-approval-roundtrip-BSV-51ig.mjs";
45
+ import { n as CodexThreadPolicyHandoffError, s as restoreCodexThreadInstructionsAfterCompaction } from "./thread-policy-CHgY-KNl.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-D731PCdv.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-BUWIOrSr.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-CfP4PnEf.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-UMVoNjZz.mjs";
56
+ import { r as prepareCodexNativeMcpFormResourceContext, t as createCodexNativeMcpAppResultDetailsPreparer } from "./native-mcp-app-CjxJQ4F7.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-D0pYbxHH.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-CjRaV3bx.mjs";
63
+ import { a as runCodexComputerUseLiveTest, i as createComputerUseRequest, t as ensureCodexComputerUse } from "./computer-use-CiToXF5C.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,38 +619,35 @@ var CodexAssistantProjection = class {
443
619
  delta: item.text
444
620
  });
445
621
  }
446
- recordItemCompleted(item, itemId, activeItemIds) {
447
- if (itemId && item?.type === "agentMessage") this.completedAssistantItemIds.add(itemId);
448
- 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);
449
626
  this.rememberAssistantPhase(item);
450
- if (item?.type === "agentMessage" && itemId && !this.isNonTerminalAssistantItem(itemId) && itemId !== this.pendingRawTerminalAssistantEchoItemId) this.pendingRawTerminalAssistantEchoItemId = void 0;
451
- if (item?.type === "agentMessage" && !this.isNonTerminalAssistantItem(item.id)) {
452
- this.markLatestTerminalAssistantCandidate(item.id, activeItemIds);
453
- this.pendingRawTerminalAssistantEchoItemId = item.id;
454
- } else if (itemId && !this.isNonTerminalAssistantItem(itemId)) {
455
- this.markTerminalAssistantCandidateSupersededBy(itemId, { preserveEarlierActiveItem: true });
456
- 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
+ }
457
637
  }
458
638
  if (item?.type === "agentMessage" && typeof item.text === "string") {
459
639
  this.rememberAssistantItem(item.id);
460
640
  this.assistantTextByItem.set(item.id, item.text);
461
- if (this.isCommentaryAssistantItem(item.id)) {
462
- this.emitCommentaryProgress({
463
- itemId: item.id,
464
- text: item.text,
465
- phase: "end"
466
- });
467
- this.pendingRawCommentaryEchoes += 1;
468
- } else if (item.text && !this.isAsyncAssistantItem(item.id) && this.isFinalAnswerAssistantItem(item.id)) this.emitAnswerCandidate(item.id, "candidate");
469
- return this.createAsyncDelivery(item.id);
470
- }
471
- }
472
- recordSnapshotItem(item) {
473
- if (item.type === "agentMessage") this.completedAssistantItemIds.add(item.id);
474
- this.rememberAssistantPhase(item);
475
- if (item.type === "agentMessage" && typeof item.text === "string") {
476
- this.rememberAssistantItem(item.id);
477
- 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
+ }
478
651
  return this.createAsyncDelivery(item.id);
479
652
  }
480
653
  }
@@ -496,13 +669,19 @@ var CodexAssistantProjection = class {
496
669
  this.pendingRawTerminalAssistantEchoItemId = void 0;
497
670
  return;
498
671
  }
499
- const text = extractRawAssistantText(item);
672
+ const text = extractRawResponseItemText(item);
500
673
  if (text === void 0 || !text && (phase === "commentary" || activeItemIds.size > 0 || readStringField(item, "type") !== "message")) return;
501
674
  const itemId = rawItemId ?? `raw-assistant-${this.assistantItemOrder.length + 1}`;
502
675
  const isIdlessTerminalAssistantAfterCompletedWork = candidateWasSupersededBeforeRaw && rawItemId === void 0 && pendingTerminalAssistantEchoItemId === void 0 && activeItemIds.size === 0;
503
- 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
+ });
504
683
  if (phase) this.assistantPhaseByItem.set(itemId, phase);
505
- this.completedAssistantItemIds.add(itemId);
684
+ this.steeringSegments.recordCompletion(itemId);
506
685
  this.rememberAssistantItem(itemId);
507
686
  this.assistantTextByItem.set(itemId, text);
508
687
  if (!text) return;
@@ -534,6 +713,9 @@ var CodexAssistantProjection = class {
534
713
  }] : [];
535
714
  });
536
715
  }
716
+ collectTerminalAssistantItemIds() {
717
+ return this.steeringSegments.collectOccurrenceIds(this.assistantItemOrder.filter((itemId) => !this.isNonTerminalAssistantItem(itemId)));
718
+ }
537
719
  readCommentaryMessage(itemId) {
538
720
  const text = this.assistantTextByItem.get(itemId)?.trim();
539
721
  const timestamp = this.assistantTimestampByItem.get(itemId);
@@ -548,34 +730,37 @@ var CodexAssistantProjection = class {
548
730
  }] : [];
549
731
  });
550
732
  }
551
- collectCompletedAssistantMessages(completedItemIds, options) {
733
+ collectSteeringAssistantMessages(completedItemIds, options) {
734
+ this.steeringSegments.beginSnapshot();
552
735
  return this.assistantItemOrder.flatMap((itemId) => {
553
- const text = this.assistantTextByItem.get(itemId)?.trim();
554
- if (!completedItemIds.has(itemId) || this.isNonTerminalAssistantItem(itemId) || !text || isSilentReplyPayloadText(text) || this.isToolProgressEchoText(itemId, text)) return [];
555
- const message = this.createAssistantMessage(text, options);
556
- 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;
557
743
  return [{
558
- itemId,
559
- message: {
560
- ...message,
561
- timestamp
562
- }
744
+ itemId: segment.itemId,
745
+ message
563
746
  }];
564
747
  });
565
748
  }
566
- markAssistantBoundaryPersisted(itemId) {
567
- const index = this.assistantItemOrder.indexOf(itemId);
568
- 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);
569
754
  this.persistableAssistantBarrier = Math.max(this.persistableAssistantBarrier, index + 1);
570
- this.persistedAssistantBoundary = true;
571
755
  }
756
+ this.persistedAssistantBoundary = true;
572
757
  }
573
758
  finalizeAnswerCandidate(turn) {
574
759
  if (turn.status !== "completed") {
575
760
  this.supersedeVisibleAnswerCandidate();
576
761
  return;
577
762
  }
578
- 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))) {
579
764
  if (itemId === this.visibleAnswerCandidateItemId) this.supersedeVisibleAnswerCandidate();
580
765
  this.assistantTextByItem.delete(itemId);
581
766
  }
@@ -599,13 +784,13 @@ var CodexAssistantProjection = class {
599
784
  this.emitAnswerCandidate(itemId, "selected");
600
785
  }
601
786
  hasAssistantItemTextForSynthesis() {
602
- 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)));
603
788
  }
604
789
  createCurrentAttemptAssistantMessage(options) {
605
790
  for (let i = this.assistantItemOrder.length - 1; i >= 0; i -= 1) {
606
791
  const itemId = this.assistantItemOrder[i];
607
792
  if (!itemId || this.isNonTerminalAssistantItem(itemId) || !this.assistantTextByItem.has(itemId)) continue;
608
- const text = this.assistantTextByItem.get(itemId) ?? "";
793
+ const text = this.remainingAssistantText(itemId) ?? "";
609
794
  const normalizedText = text.trim();
610
795
  if (normalizedText && this.isToolProgressEchoText(itemId, normalizedText)) continue;
611
796
  return this.createAssistantMessage(text, options);
@@ -618,6 +803,19 @@ var CodexAssistantProjection = class {
618
803
  responseModel: this.responseModel
619
804
  } : message;
620
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
+ }
621
819
  rememberAssistantPhase(item) {
622
820
  if (item?.type !== "agentMessage") return;
623
821
  const phase = readStringField(item, "phase");
@@ -643,9 +841,14 @@ var CodexAssistantProjection = class {
643
841
  return this.assistantPhaseByItem.get(itemId) === "final_answer";
644
842
  }
645
843
  emitCommentaryProgress(params) {
646
- 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();
647
850
  const previous = this.lastCommentaryProgressEventByItem.get(params.itemId);
648
- if (!progressText || previous?.phase === params.phase && previous.text === progressText) return;
851
+ if (!progressText.trim() || previous?.phase === params.phase && previous.text === progressText) return;
649
852
  this.lastCommentaryProgressEventByItem.set(params.itemId, {
650
853
  phase: params.phase,
651
854
  text: progressText
@@ -711,21 +914,19 @@ var CodexAssistantProjection = class {
711
914
  this.supersedeVisibleAnswerCandidate();
712
915
  }
713
916
  resolveFinalAssistantText() {
714
- for (let i = this.assistantItemOrder.length - 1; i >= 0; i -= 1) {
715
- const itemId = this.assistantItemOrder[i];
716
- if (!itemId) continue;
717
- const text = this.assistantTextByItem.get(itemId)?.trim();
718
- if (this.isNonTerminalAssistantItem(itemId)) continue;
719
- if (text && !this.isToolProgressEchoText(itemId, text)) return text;
720
- }
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;
721
922
  }
722
923
  collectPersistableAssistantTexts(minIndex) {
723
924
  let texts = [];
724
925
  let replaceable = false;
725
- for (let index = minIndex; index < this.assistantItemOrder.length; index += 1) {
926
+ for (let index = 0; index < this.assistantItemOrder.length; index += 1) {
726
927
  const itemId = this.assistantItemOrder[index];
727
- if (!itemId || this.isNonTerminalAssistantItem(itemId)) continue;
728
- 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();
729
930
  if (!text || this.isToolProgressEchoText(itemId, text)) continue;
730
931
  if (isSilentReplyPayloadText(text)) {
731
932
  texts.push(text);
@@ -742,10 +943,7 @@ var CodexAssistantProjection = class {
742
943
  return texts;
743
944
  }
744
945
  noteNativeWorkBarrier(item) {
745
- if (!item || !shouldAdvancePersistableAssistantBarrier(item)) return;
746
- if (item.id && this.persistableAssistantBarrierItemIds.has(item.id)) return;
747
- if (item.id) this.persistableAssistantBarrierItemIds.add(item.id);
748
- this.persistableAssistantBarrier = this.assistantItemOrder.length;
946
+ if (item && shouldAdvancePersistableAssistantBarrier(item) && this.steeringSegments.recordHandoff(item.id)) this.persistableAssistantBarrier = this.assistantItemOrder.length;
749
947
  }
750
948
  rememberAssistantItem(itemId) {
751
949
  if (!itemId) return;
@@ -755,7 +953,7 @@ var CodexAssistantProjection = class {
755
953
  }
756
954
  if (this.isCommentaryAssistantItem(itemId)) this.checkpointCommentary?.(itemId, {
757
955
  read: () => this.readCommentaryMessage(itemId),
758
- ready: () => this.completedAssistantItemIds.has(itemId)
956
+ ready: () => this.steeringSegments.isCompleted(itemId)
759
957
  });
760
958
  }
761
959
  createAsyncDelivery(itemId) {
@@ -773,9 +971,6 @@ var CodexAssistantProjection = class {
773
971
  return this.rawPromotedAssistantItemIds.has(itemId) && this.matchesToolProgressEcho(text);
774
972
  }
775
973
  };
776
- function shouldAdvancePersistableAssistantBarrier(item) {
777
- return shouldClearTerminalPresentationForNativeItem(item) || item.type === "dynamicToolCall" || item.type === "sleep";
778
- }
779
974
  //#endregion
780
975
  //#region extensions/codex/src/app-server/event-projector-async-delivery.ts
781
976
  /** Owns authorization, exactly-once settlement, and terminal retry for async user messages. */
@@ -1098,29 +1293,9 @@ function normalizePlanStepStatus(status) {
1098
1293
  return status === "completed" ? "completed" : "pending";
1099
1294
  }
1100
1295
  function readReasoningSections(value) {
1101
- const sections = /* @__PURE__ */ new Map();
1102
- if (Array.isArray(value)) value.forEach((text, index) => {
1103
- if (typeof text === "string") sections.set(index, text);
1104
- });
1105
- return sections;
1296
+ return new Map(Array.isArray(value) ? value.flatMap((text, index) => typeof text === "string" ? [[index, text]] : []) : []);
1106
1297
  }
1107
1298
  //#endregion
1108
- //#region extensions/codex/src/app-server/event-projector-settlement.ts
1109
- var CodexProjectionSettlement = class extends AgentHarnessProjectionSettlement {
1110
- constructor(params, isActive) {
1111
- super(params, isActive, { label: "codex app-server" });
1112
- this.turnTainted = false;
1113
- }
1114
- get completedAnswer() {
1115
- const turn = this.terminalReceipt;
1116
- const answer = turn?.items?.findLast((item) => item.type === "agentMessage" && item.phase !== "commentary" && item.delivery !== "async" && typeof item.text === "string" && item.text.trim().length > 0);
1117
- return turn?.status === "completed" && answer ? {
1118
- turn,
1119
- answer
1120
- } : void 0;
1121
- }
1122
- };
1123
- //#endregion
1124
1299
  //#region extensions/codex/src/app-server/event-projector-snapshot.ts
1125
1300
  function buildCodexMessagesSnapshot(params) {
1126
1301
  const messages = promptSnapshot(params.runParams, params.turnId, params.upstreamUserText);
@@ -1149,45 +1324,24 @@ function buildCodexMessagesSnapshot(params) {
1149
1324
  function buildCodexSteeringMessagesSnapshot(params) {
1150
1325
  const asyncMessages = params.assistantProjection.collectAsyncMessages().filter(({ itemId }) => params.completedItemIds.has(itemId));
1151
1326
  const commentaryMessages = params.assistantProjection.collectCommentaryMessages().filter(({ itemId }) => params.completedItemIds.has(itemId));
1152
- const assistantMessages = params.assistantProjection.collectCompletedAssistantMessages(params.completedItemIds, {
1327
+ const assistantMessages = params.assistantProjection.collectSteeringAssistantMessages(params.completedItemIds, {
1153
1328
  tokenUsage: void 0,
1154
1329
  aborted: false,
1155
1330
  promptError: void 0
1156
1331
  });
1157
- return {
1158
- messages: buildCodexMessagesSnapshot({
1159
- runParams: params.runParams,
1160
- turnId: params.turnId,
1161
- upstreamUserText: params.upstreamUserText,
1162
- reasoningText: void 0,
1163
- asyncMessages,
1164
- commentaryMessages,
1165
- assistantMessages,
1166
- toolMessages: params.toolMessages,
1167
- lastAssistant: void 0
1168
- }).filter((message) => message.role !== "user"),
1169
- assistantBoundaryItemId: assistantMessages.at(-1)?.itemId
1170
- };
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");
1171
1343
  }
1172
1344
  //#endregion
1173
- //#region extensions/codex/src/app-server/event-projector-terminal-failure.ts
1174
- var CodexTerminalFailureProjection = class {
1175
- constructor() {
1176
- this.promptErrorSource = null;
1177
- }
1178
- record(params) {
1179
- const refusal = readCodexProviderRefusal(params.message, params.codexErrorInfo, params);
1180
- if (!this.providerRefusal || refusal?.category === "misalignment" && this.providerRefusal.category === "misalignment" && params.misalignment != null) this.providerRefusal = refusal;
1181
- if (this.providerRefusal) return;
1182
- this.promptError = resolveCodexPromptError({
1183
- message: params.message,
1184
- codexErrorInfo: params.codexErrorInfo,
1185
- rateLimits: params.rateLimits
1186
- }) ?? params.fallbackMessage;
1187
- this.promptErrorSource = params.promptErrorSource;
1188
- }
1189
- };
1190
- //#endregion
1191
1345
  //#region extensions/codex/src/app-server/event-projector-tool-search-evidence.ts
1192
1346
  const MAX_RETAINED_SEARCHES = 16;
1193
1347
  const MAX_RETAINED_DYNAMIC_CALLS = 32;
@@ -1195,17 +1349,7 @@ const MAX_DISCOVERED_TOOLS = 32;
1195
1349
  const MAX_ID_CHARS = 256;
1196
1350
  const MAX_NAME_CHARS = 128;
1197
1351
  function readBoundedString(value, maxChars) {
1198
- if (typeof value !== "string") return;
1199
- const normalized = value.trim();
1200
- if (!normalized) return;
1201
- return normalized.slice(0, maxChars);
1202
- }
1203
- function trimOldest(map, maxSize) {
1204
- while (map.size > maxSize) {
1205
- const oldest = map.keys().next().value;
1206
- if (oldest === void 0) return;
1207
- map.delete(oldest);
1208
- }
1352
+ return normalizeOptionalString(value)?.slice(0, maxChars);
1209
1353
  }
1210
1354
  function collectToolRefs(values, output, seen, inheritedNamespace) {
1211
1355
  if (!Array.isArray(values)) return false;
@@ -1256,7 +1400,7 @@ var CodexToolSearchEvidenceProjection = class {
1256
1400
  ...execution ? { execution } : {},
1257
1401
  ...status ? { status } : {}
1258
1402
  });
1259
- trimOldest(this.calls, MAX_RETAINED_SEARCHES);
1403
+ pruneMapToMaxSize(this.calls, MAX_RETAINED_SEARCHES);
1260
1404
  return;
1261
1405
  }
1262
1406
  if (type !== "tool_search_output") return;
@@ -1273,7 +1417,7 @@ var CodexToolSearchEvidenceProjection = class {
1273
1417
  tools,
1274
1418
  truncated
1275
1419
  });
1276
- trimOldest(this.outputs, MAX_RETAINED_SEARCHES);
1420
+ pruneMapToMaxSize(this.outputs, MAX_RETAINED_SEARCHES);
1277
1421
  }
1278
1422
  recordDynamicToolCall(params) {
1279
1423
  const callId = readBoundedString(params.callId, MAX_ID_CHARS);
@@ -1287,7 +1431,7 @@ var CodexToolSearchEvidenceProjection = class {
1287
1431
  namespace: requestedNamespace,
1288
1432
  tool
1289
1433
  });
1290
- trimOldest(this.dynamicCalls, MAX_RETAINED_DYNAMIC_CALLS);
1434
+ pruneMapToMaxSize(this.dynamicCalls, MAX_RETAINED_DYNAMIC_CALLS);
1291
1435
  }
1292
1436
  recordDynamicToolResult(params) {
1293
1437
  const callId = readBoundedString(params.callId, MAX_ID_CHARS);
@@ -1330,8 +1474,7 @@ var CodexTranscriptCheckpoint = class {
1330
1474
  this.lastTimestamp = 0;
1331
1475
  this.writing = Promise.resolve();
1332
1476
  this.tainted = false;
1333
- this.closed = false;
1334
- this.abandoned = false;
1477
+ this.state = "open";
1335
1478
  this.nextTimestamp = () => {
1336
1479
  this.lastTimestamp = Math.max(Date.now(), this.lastTimestamp + 1);
1337
1480
  return this.lastTimestamp;
@@ -1348,16 +1491,16 @@ var CodexTranscriptCheckpoint = class {
1348
1491
  });
1349
1492
  };
1350
1493
  this.enqueue = (entry) => {
1351
- if (this.params.sessionTarget && !this.closed) this.pending.push(entry);
1494
+ if (this.params.sessionTarget && this.state === "open") this.pending.push(entry);
1352
1495
  };
1353
1496
  }
1354
1497
  abandon() {
1355
- this.closed = this.abandoned = true;
1498
+ this.state = "abandoned";
1356
1499
  this.pending.length = 0;
1357
1500
  }
1358
1501
  flush(close = false) {
1359
- if (this.closed) return this.writing;
1360
- this.closed = close;
1502
+ if (this.state !== "open") return this.writing;
1503
+ this.state = close ? "closed" : "open";
1361
1504
  this.writing = this.writing.then(async () => {
1362
1505
  const blocked = close ? -1 : this.pending.findIndex((entry) => entry.ready?.() === false);
1363
1506
  const count = blocked < 0 ? this.pending.length : blocked;
@@ -1373,9 +1516,9 @@ var CodexTranscriptCheckpoint = class {
1373
1516
  });
1374
1517
  try {
1375
1518
  await codexTranscriptMirrorRuntime.mirror({
1376
- assertWriteCurrent: () => {
1377
- if (this.abandoned) throw new Error("Codex transcript checkpoint was retired before write");
1378
- },
1519
+ assertWriteCurrent: createNativeSessionBindingAuthority([], () => {
1520
+ if (this.state === "abandoned") throw new Error("Codex transcript checkpoint was retired before write");
1521
+ }).assertLegacyCurrent,
1379
1522
  ...this.params.sessionTarget,
1380
1523
  sessionId: this.params.sessionId,
1381
1524
  cwd: this.params.workspaceDir,
@@ -1400,6 +1543,20 @@ var CodexTranscriptCheckpoint = class {
1400
1543
  };
1401
1544
  //#endregion
1402
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
+ };
1403
1560
  /** Owns per-turn projection state and builds results from the same state. */
1404
1561
  var CodexTurnProjection = class {
1405
1562
  constructor(params, threadId, turnId, options = {}) {
@@ -1413,7 +1570,7 @@ var CodexTurnProjection = class {
1413
1570
  this.activeCompactionItemIds = /* @__PURE__ */ new Set();
1414
1571
  this.projectionController = new AbortController();
1415
1572
  this.settledTurnFailureFinalizationAllowed = false;
1416
- this.terminalFailure = new CodexTerminalFailureProjection();
1573
+ this.promptErrorSource = null;
1417
1574
  this.synthesizedMissingToolResultError = null;
1418
1575
  this.aborted = false;
1419
1576
  this.usageProjection = new CodexUsageProjection();
@@ -1448,8 +1605,7 @@ var CodexTurnProjection = class {
1448
1605
  }
1449
1606
  buildResult(toolTelemetry, options) {
1450
1607
  this.eventProjection.flushPendingGuardianWarning();
1451
- const { params: runParams, turnId, completedTurn, aborted, contextTokens, contextTokensSource, completedCompactionCount, synthesizedMissingToolResultError: previousMissingToolResultError } = this;
1452
- 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;
1453
1609
  const upstreamUserText = this.options.upstreamUserText;
1454
1610
  const turnTainted = this.settlement.turnTainted;
1455
1611
  const observedItemCount = (/* @__PURE__ */ new Set([...this.observedItemIds, ...this.completedItemIds])).size;
@@ -1504,7 +1660,7 @@ var CodexTurnProjection = class {
1504
1660
  commentaryMessages,
1505
1661
  toolMessages: this.toolTranscriptProjection.transcriptMessages,
1506
1662
  steeringMessages: options?.steeringMessages,
1507
- lastAssistant,
1663
+ lastAssistant: lastAssistant ? attachCodexAssistantItemIds(lastAssistant, this.assistantProjection.collectTerminalAssistantItemIds()) : void 0,
1508
1664
  turnTainted
1509
1665
  });
1510
1666
  const turnFailed = completedTurn?.status === "failed";
@@ -1570,6 +1726,17 @@ var CodexTurnProjection = class {
1570
1726
  for (const toolResult of toolTelemetry.coreTtsToolResults ?? []) transferTtsProvenance?.(toolResult, result, toolAutoDeliveryMediaUrls ?? []);
1571
1727
  return result;
1572
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
+ }
1573
1740
  emitAgentEvent(event) {
1574
1741
  if (!this.projectionClosed) emitCodexAgentEvent(this.params, event);
1575
1742
  }
@@ -1586,17 +1753,17 @@ var CodexAppServerEventProjector = class extends CodexTurnProjection {
1586
1753
  return this.completedTurn?.status;
1587
1754
  }
1588
1755
  getPendingNativeCommands() {
1589
- 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();
1590
1757
  }
1591
1758
  /** Native completion owns the answer independently of unfinished host projection. */
1592
1759
  recoverCompletedAnswer() {
1593
1760
  const completed = this.settlement.completedAnswer;
1594
- if (!completed || this.aborted || this.terminalFailure.promptError) return false;
1761
+ if (!completed || this.aborted || this.promptError) return false;
1595
1762
  this.closeCompactionProgress();
1596
1763
  this.projectionController.abort();
1597
1764
  this.transcriptCheckpoint.abandon();
1598
1765
  this.completedTurn = completed.turn;
1599
- this.assistantProjection.recordSnapshotItem(completed.answer);
1766
+ this.assistantProjection.recordItemCompleted(completed.answer);
1600
1767
  this.assistantProjection.finalizeAnswerCandidate(completed.turn);
1601
1768
  return true;
1602
1769
  }
@@ -1608,7 +1775,7 @@ var CodexAppServerEventProjector = class extends CodexTurnProjection {
1608
1775
  if (!this.projectionClosed) this.nativeToolLifecycleProjector.recordMcpToolCallReceipt(notification);
1609
1776
  }
1610
1777
  buildSteeringTranscriptPrefix() {
1611
- const snapshot = buildCodexSteeringMessagesSnapshot({
1778
+ return buildCodexSteeringMessagesSnapshot({
1612
1779
  runParams: this.params,
1613
1780
  turnId: this.turnId,
1614
1781
  upstreamUserText: this.options.upstreamUserText,
@@ -1616,15 +1783,10 @@ var CodexAppServerEventProjector = class extends CodexTurnProjection {
1616
1783
  assistantProjection: this.assistantProjection,
1617
1784
  toolMessages: this.toolTranscriptProjection.transcriptMessages
1618
1785
  });
1619
- this.pendingSteeringAssistantBoundaryItemId = snapshot.assistantBoundaryItemId;
1620
- return snapshot.messages;
1621
1786
  }
1622
- markSteeringTranscriptPersisted() {
1623
- const itemId = this.pendingSteeringAssistantBoundaryItemId;
1624
- if (itemId) {
1625
- this.assistantProjection.markAssistantBoundaryPersisted(itemId);
1626
- this.pendingSteeringAssistantBoundaryItemId = void 0;
1627
- }
1787
+ markSteeringTranscriptMessagePersisted(mirrorIdentity) {
1788
+ const prefix = `${this.turnId}:assistant:`;
1789
+ if (mirrorIdentity.startsWith(prefix)) this.assistantProjection.markSteeringMessagePersisted(mirrorIdentity.slice(prefix.length));
1628
1790
  }
1629
1791
  /** Fence delayed projections before the turn's final snapshot leaves its owner. */
1630
1792
  closeProjection() {
@@ -1735,7 +1897,7 @@ var CodexAppServerEventProjector = class extends CodexTurnProjection {
1735
1897
  this.eventProjection.handleCyberPolicyError(codexErrorInfo, this.params.modelId);
1736
1898
  const compactionFailure = codexErrorInfo === "other" && this.isCompacting();
1737
1899
  this.settledTurnFailureFinalizationAllowed = codexErrorInfo === "serverOverloaded" || compactionFailure;
1738
- this.terminalFailure.record({
1900
+ this.recordTerminalFailure({
1739
1901
  message: readCodexErrorNotificationMessage(params),
1740
1902
  codexErrorInfo,
1741
1903
  misalignment: isJsonObject(params.error) ? params.error.misalignment : void 0,
@@ -1803,8 +1965,8 @@ var CodexAppServerEventProjector = class extends CodexTurnProjection {
1803
1965
  }
1804
1966
  markTimedOut() {
1805
1967
  this.aborted = true;
1806
- this.terminalFailure.promptError = "codex app-server attempt timed out";
1807
- this.terminalFailure.promptErrorSource = "prompt";
1968
+ this.promptError = "codex app-server attempt timed out";
1969
+ this.promptErrorSource = "prompt";
1808
1970
  }
1809
1971
  markAborted() {
1810
1972
  this.aborted = true;
@@ -1900,11 +2062,7 @@ var CodexAppServerEventProjector = class extends CodexTurnProjection {
1900
2062
  this.completedCompactionCount += 1;
1901
2063
  }
1902
2064
  if (!this.asyncDeliveryProjection.allows(item, true)) return;
1903
- const asyncMessage = this.assistantProjection.recordItemCompleted(item, itemId, this.activeItemIds);
1904
- if (asyncMessage) await this.asyncDeliveryProjection.deliver(asyncMessage);
1905
- if (this.projectionClosed) return;
1906
- await this.reasoningProjection.recordItem(item);
1907
- await this.settlement.project("media_projection", () => this.generatedMediaProjection.recordNative(item));
2065
+ await this.recordCompletedItemContent(item, { itemId });
1908
2066
  if (this.projectionClosed) return;
1909
2067
  if (item?.type === "contextCompaction" && itemId) {
1910
2068
  if (!this.isCompactionProjectionActive()) return;
@@ -1963,13 +2121,13 @@ var CodexAppServerEventProjector = class extends CodexTurnProjection {
1963
2121
  if (!turn || turn.id !== this.turnId) return;
1964
2122
  this.completedTurn = turn;
1965
2123
  this.eventProjection.endSafetyBuffering();
1966
- 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());
1967
2125
  this.settledTurnFailureFinalizationAllowed = turn.status === "failed" && (turn.error?.codexErrorInfo === "serverOverloaded" || compactionFailure);
1968
2126
  if (turn.status !== "completed") this.usageProjection.invalidateContext();
1969
2127
  if (turn.status === "failed") {
1970
2128
  const codexErrorInfo = turn.error?.codexErrorInfo;
1971
2129
  this.eventProjection.handleCyberPolicyError(codexErrorInfo, this.params.modelId);
1972
- this.terminalFailure.record({
2130
+ this.recordTerminalFailure({
1973
2131
  message: turn.error?.message,
1974
2132
  codexErrorInfo,
1975
2133
  misalignment: turn.error?.misalignment,
@@ -1988,11 +2146,7 @@ var CodexAppServerEventProjector = class extends CodexTurnProjection {
1988
2146
  for (const item of turnItems) {
1989
2147
  if (!this.asyncDeliveryProjection.allows(item)) continue;
1990
2148
  this.diagnostics.warnUnknownItemStatus(item);
1991
- const asyncMessage = this.assistantProjection.recordSnapshotItem(item);
1992
- if (asyncMessage) await this.asyncDeliveryProjection.deliver(asyncMessage);
1993
- if (this.projectionClosed) return;
1994
- await this.reasoningProjection.recordItem(item);
1995
- await this.settlement.project("media_projection", () => this.generatedMediaProjection.recordNative(item));
2149
+ await this.recordCompletedItemContent(item);
1996
2150
  if (this.projectionClosed) return;
1997
2151
  this.toolProgressProjection.recordToolMeta(item);
1998
2152
  this.toolProgressProjection.rememberCommandAggregateOutputEcho(item);
@@ -2020,10 +2174,20 @@ var CodexAppServerEventProjector = class extends CodexTurnProjection {
2020
2174
  this.assistantProjection.finalizeAnswerCandidate(turn);
2021
2175
  await this.reasoningProjection.maybeEndReasoning();
2022
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
+ }
2023
2187
  async handleRawResponseItemCompleted(params) {
2024
2188
  const item = isJsonObject(params.item) ? params.item : void 0;
2025
2189
  if (!item) return;
2026
- if (item.role === "assistant" && extractRawAssistantText(item)) this.eventProjection.markSafetyBufferingAssistantStarted();
2190
+ if (item.role === "assistant" && extractRawResponseItemText(item)) this.eventProjection.markSafetyBufferingAssistantStarted();
2027
2191
  this.toolSearchEvidenceProjection?.recordRawResponseItem(item);
2028
2192
  this.toolTranscriptProjection.recordRawNativeToolItem(item);
2029
2193
  this.assistantProjection.handleRawResponseItemCompleted(item, this.activeItemIds);
@@ -2086,7 +2250,7 @@ var CodexCompactionPlanState = class {
2086
2250
  role: "user",
2087
2251
  content: [{
2088
2252
  type: "input_text",
2089
- text: `${RESTORED_PLAN_PREAMBLE}\n${serializePlan(this.latestPlan)}`
2253
+ text: `${RESTORED_PLAN_PREAMBLE}\n${this.latestPlan}`
2090
2254
  }]
2091
2255
  }]
2092
2256
  }, {
@@ -2101,25 +2265,19 @@ function readBoundedPlan(markdownValue, stepsValue) {
2101
2265
  steps: readPlanSteps(stepsValue)
2102
2266
  });
2103
2267
  const markdown = canonical.markdown === void 0 ? void 0 : truncateUtf8(canonical.markdown, RESTORED_PLAN_MAX_MARKDOWN_BYTES);
2104
- 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;
2105
2274
  for (const step of canonical.plan) {
2106
- const candidate = {
2107
- ...markdown?.trim() ? { markdown } : {},
2108
- steps: [...steps, step]
2109
- };
2110
- if (Buffer$1.byteLength(serializePlan(candidate), "utf8") > RESTORED_PLAN_MAX_PAYLOAD_BYTES) break;
2111
- 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;
2112
2279
  }
2113
- return markdown?.trim() || steps.length > 0 ? {
2114
- ...markdown?.trim() ? { markdown } : {},
2115
- steps
2116
- } : void 0;
2117
- }
2118
- function serializePlan(plan) {
2119
- return JSON.stringify({
2120
- markdown: plan.markdown,
2121
- plan: plan.steps
2122
- });
2280
+ return serialized;
2123
2281
  }
2124
2282
  function truncateUtf8(value, maxBytes) {
2125
2283
  if (Buffer$1.byteLength(value, "utf8") <= maxBytes) return value;
@@ -2157,9 +2315,7 @@ async function restoreCodexAttemptCompactionContext(resources) {
2157
2315
  thread.liveThreadOwnership?.assertCurrent();
2158
2316
  if (state.thread !== thread || state.client !== client) throw new Error("Codex compaction thread ownership changed");
2159
2317
  };
2160
- computerContextEpoch.value += 1;
2161
- delete computerContextEpoch.frameToolCallId;
2162
- delete computerContextEpoch.frameImageIdentity;
2318
+ invalidateCodexComputerFrame(computerContextEpoch);
2163
2319
  try {
2164
2320
  await compactionPlanState.restore({
2165
2321
  client,
@@ -2266,7 +2422,7 @@ function createCodexUserInputBridge(params) {
2266
2422
  const mode = readOwnDataString(request.params, "mode");
2267
2423
  const requestSnapshot = agentHarnessStructuredInput.snapshot(request.params, { richForm: mode === "openaiForm" || mode === "openai/form" });
2268
2424
  if (agentHarnessStructuredInput.isRecord(requestSnapshot) && readOwnDataString(requestSnapshot, "threadId") !== params.threadId) return;
2269
- const { compileCodexOrdinaryElicitation } = await import("./elicitation-input-r9axtppm.mjs");
2425
+ const { compileCodexOrdinaryElicitation } = await import("./elicitation-input-DXG_qaXr.mjs");
2270
2426
  const compiled = agentHarnessStructuredInput.isRecord(requestSnapshot) ? compileCodexOrdinaryElicitation({
2271
2427
  snapshot: requestSnapshot,
2272
2428
  turnId: params.turnId
@@ -2322,8 +2478,8 @@ function readUserInputParams(value) {
2322
2478
  const threadId = readBoundedUserInputText(snapshot, "threadId", MAX_USER_INPUT_ID);
2323
2479
  const turnId = readBoundedUserInputText(snapshot, "turnId", MAX_USER_INPUT_ID);
2324
2480
  const itemId = readBoundedUserInputText(snapshot, "itemId", MAX_USER_INPUT_ID);
2325
- const questions = readArray(snapshot, "questions", MAX_USER_INPUT_QUESTIONS);
2326
- 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;
2327
2483
  const parsed = [];
2328
2484
  for (const questionValue of questions) {
2329
2485
  const question = readQuestion(questionValue);
@@ -2363,7 +2519,7 @@ function readOptions(value) {
2363
2519
  for (const entry of value) {
2364
2520
  if (!agentHarnessStructuredInput.isRecord(entry)) return;
2365
2521
  const label = readBoundedUserInputText(entry, "label", MAX_USER_INPUT_ID);
2366
- const description = readBoundedUserInputText(entry, "description", MAX_USER_INPUT_TEXT, true);
2522
+ const description = readBoundedUserInputText(entry, "description", MAX_USER_INPUT_TEXT);
2367
2523
  if (!label) return;
2368
2524
  options.push({
2369
2525
  label,
@@ -2375,13 +2531,9 @@ function readOptions(value) {
2375
2531
  function readValue(record, key) {
2376
2532
  return Object.hasOwn(record, key) ? record[key] : void 0;
2377
2533
  }
2378
- function readBoundedUserInputText(record, key, maximum, allowEmpty = false) {
2379
- const value = readValue(record, key);
2380
- return typeof value === "string" && value.length <= maximum && (allowEmpty || value.length > 0) ? value : void 0;
2381
- }
2382
- function readArray(record, key, maximum) {
2534
+ function readBoundedUserInputText(record, key, maximum) {
2383
2535
  const value = readValue(record, key);
2384
- return Array.isArray(value) && value.length <= maximum ? value : void 0;
2536
+ return typeof value === "string" && value.length <= maximum && value.length > 0 ? value : void 0;
2385
2537
  }
2386
2538
  function readOwnDataString(value, key) {
2387
2539
  if (!value || typeof value !== "object" || Array.isArray(value)) return;
@@ -2561,10 +2713,11 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
2561
2713
  state.activeLocalProjections -= 1;
2562
2714
  }
2563
2715
  };
2716
+ const isSteeringAvailable = () => !state.completed && !state.terminalTurnNotificationQueued && !runAbortController.signal.aborted;
2564
2717
  const assertSteeringActive = () => {
2565
2718
  connection.assertCurrent();
2566
2719
  runAbortController.signal.throwIfAborted();
2567
- 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");
2568
2721
  };
2569
2722
  const workspaceOnly = resolveAttemptFsWorkspaceOnly({
2570
2723
  config: params.config,
@@ -2590,6 +2743,7 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
2590
2743
  signal: runAbortController.signal,
2591
2744
  assertActive: assertSteeringActive,
2592
2745
  withCurrent: connection.withCurrent,
2746
+ withPreparedCurrent: connection.authority.withPreparedCurrent,
2593
2747
  prepareMessage: async (text, options, assertMessageCurrent) => {
2594
2748
  const attachmentNote = await connection.prepareInputAttachments({
2595
2749
  maxChars: Math.max(0, CODEX_TURN_START_TEXT_INPUT_MAX_CHARS - text.length - 2),
@@ -2640,10 +2794,7 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
2640
2794
  const messages = activeProjector.buildSteeringTranscriptPrefix();
2641
2795
  if (params.sessionTarget && messages.length > 0) {
2642
2796
  await codexTranscriptMirrorRuntime.mirror({
2643
- assertCurrent: () => {
2644
- connection.assertLegacyCurrent();
2645
- assertSteeringActive();
2646
- },
2797
+ assertCurrent: composeSessionTranscriptWriteAssertion([connection.assertLegacyCurrent, createNativeSessionBindingAuthority([], assertSteeringActive).assertLegacyCurrent]),
2647
2798
  agentId: sessionAgentId,
2648
2799
  sessionKey: contextSessionKey,
2649
2800
  sessionId: params.sessionId,
@@ -2653,10 +2804,10 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
2653
2804
  idempotencyScope: `codex-app-server:${resourceState.thread.threadId}`,
2654
2805
  runId: params.runId,
2655
2806
  runMirrorIdentityPrefix: `${activeTurnId}:`,
2807
+ onAssistantMessageOwned: (identity) => activeProjector.markSteeringTranscriptMessagePersisted(identity),
2656
2808
  config: params.config
2657
2809
  });
2658
2810
  assertSteeringActive();
2659
- activeProjector.markSteeringTranscriptPersisted();
2660
2811
  }
2661
2812
  for (const item of transcriptItems) {
2662
2813
  const recorder = item.userTurnTranscriptRecorder;
@@ -2668,38 +2819,15 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
2668
2819
  }
2669
2820
  });
2670
2821
  steeringQueueRef.current = activeSteeringQueue;
2822
+ const { claimPendingUserInputAnswer, cancelPendingUserInput } = createCodexQuestionInputHandlers(params.sessionKey ?? params.sessionId, assertSteeringActive);
2671
2823
  const injectionGuard = (assertCurrent) => () => {
2672
2824
  assertCurrent?.();
2673
2825
  assertSteeringActive();
2674
2826
  return true;
2675
2827
  };
2676
- const claimPendingUserInputAnswer = async (text, optionsLocal, assertCurrent, authorityKind = assertCurrent ? "source-bound" : "run") => {
2677
- if (optionsLocal?.isInboundUserMessage !== true || hasPromptImageInput(optionsLocal)) return false;
2678
- assertSteeringActive();
2679
- return await claimPendingAgentQuestionAnswer({
2680
- sessionKey: params.sessionKey ?? params.sessionId,
2681
- text,
2682
- authority: {
2683
- kind: authorityKind,
2684
- assertCurrent: injectionGuard(assertCurrent)
2685
- },
2686
- sourceRecorder: optionsLocal.userTurnTranscriptRecorder,
2687
- persist: optionsLocal.userTurnTranscriptRecorder ? async () => {
2688
- await optionsLocal.userTurnTranscriptRecorder?.persistApproved();
2689
- } : void 0
2690
- });
2691
- };
2692
- const cancelPendingUserInput = (resolvedBy, assertCurrent, authorityKind = assertCurrent ? "source-bound" : "run") => cancelPendingAgentQuestionForSession({
2693
- sessionKey: params.sessionKey ?? params.sessionId,
2694
- resolvedBy,
2695
- authority: {
2696
- kind: authorityKind,
2697
- assertCurrent: injectionGuard(assertCurrent)
2698
- }
2699
- });
2700
- const queueMessage = async (text, optionsLocal, assertCurrent, authorityKind = assertCurrent ? "source-bound" : "run") => {
2828
+ const queueMessage = async (text, optionsLocal, assertCurrent, authorityKind = assertCurrent ? "source-bound" : "run", preparation) => {
2701
2829
  const canClaim = injectionGuard(assertCurrent);
2702
- if (await claimPendingUserInputAnswer(text, optionsLocal, assertCurrent, authorityKind)) {
2830
+ if (await claimPendingUserInputAnswer(text, optionsLocal, assertCurrent, authorityKind, preparation)) {
2703
2831
  optionsLocal?.onQueueAccepted?.(true);
2704
2832
  optionsLocal?.onQueueSettled?.();
2705
2833
  return;
@@ -2707,7 +2835,7 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
2707
2835
  if (optionsLocal?.isInboundUserMessage === true && hasPromptImageInput(optionsLocal)) {
2708
2836
  assertSteeringActive();
2709
2837
  try {
2710
- await cancelPendingUserInput("image-reply", assertCurrent, authorityKind);
2838
+ await cancelPendingUserInput("image-reply", assertCurrent, authorityKind, preparation);
2711
2839
  } catch (error) {
2712
2840
  canClaim();
2713
2841
  if (error instanceof Error && error.name === "QuestionDispatchRefusedError") throw error;
@@ -2715,7 +2843,7 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
2715
2843
  }
2716
2844
  }
2717
2845
  try {
2718
- await activeSteeringQueue.queue(text, optionsLocal, injectionGuard(assertCurrent));
2846
+ await activeSteeringQueue.queue(text, optionsLocal, canClaim, preparation);
2719
2847
  } catch (error) {
2720
2848
  if (error instanceof CodexSteeringAcceptedUnconfirmedError) return {
2721
2849
  transcriptCommit: "unconfirmed",
@@ -2726,10 +2854,13 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
2726
2854
  };
2727
2855
  const messageInjection = {
2728
2856
  version: 2,
2729
- isAvailable: () => !state.completed && !state.terminalTurnNotificationQueued && !runAbortController.signal.aborted,
2857
+ isAvailable: isSteeringAvailable,
2730
2858
  queueMessage,
2731
2859
  claimPendingUserInputAnswer,
2732
- 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
2733
2864
  };
2734
2865
  const handle = {
2735
2866
  kind: "embedded",
@@ -2803,7 +2934,7 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
2803
2934
  for (const failure of pendingNativePreToolUseFailures.splice(0)) activeProjector.recordNativeToolPreToolUseFailure(failure);
2804
2935
  if (thread.preserveNativeModel !== true && thread.connectionScope !== "supervision" && !params.expectedSessionRuntimeOwnership) {
2805
2936
  const route = resourceState.turnRoute;
2806
- 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());
2807
2938
  }
2808
2939
  params.replyOperation?.attachBackend(handle);
2809
2940
  setActiveEmbeddedRun(params.sessionId, handle, params.sessionKey, params.sessionFile, sessionAgentId);
@@ -2988,17 +3119,9 @@ const CODEX_APP_SERVER_ROLLOUT_TAIL_READ_BYTES = 65536;
2988
3119
  const CODEX_APP_SERVER_BYTE_UNITS = {
2989
3120
  b: 1,
2990
3121
  k: 1024,
2991
- kb: 1024,
2992
- kib: 1024,
2993
- m: 1048576,
2994
- mb: 1048576,
2995
- mib: 1048576,
2996
- g: 1073741824,
2997
- gb: 1073741824,
2998
- gib: 1073741824,
2999
- t: 1099511627776,
3000
- tb: 1099511627776,
3001
- tib: 1099511627776
3122
+ m: 1024 ** 2,
3123
+ g: 1024 ** 3,
3124
+ t: 1024 ** 4
3002
3125
  };
3003
3126
  function parseCodexAppServerByteLimit(value) {
3004
3127
  if (typeof value === "number" && Number.isFinite(value) && value > 0) return Math.floor(value);
@@ -3008,7 +3131,8 @@ function parseCodexAppServerByteLimit(value) {
3008
3131
  const amount = Number(match[1]);
3009
3132
  if (!Number.isFinite(amount) || amount <= 0) return;
3010
3133
  const unit = (match[2] ?? "b").toLowerCase();
3011
- 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];
3012
3136
  if (multiplier === void 0) return;
3013
3137
  return Math.max(1, Math.round(amount * multiplier));
3014
3138
  }
@@ -3066,8 +3190,8 @@ async function listCodexAppServerRolloutFilesForThread(agentDir, threadId, codex
3066
3190
  }
3067
3191
  async function readCodexAppServerRolloutTokenSnapshot(file, openedHandle) {
3068
3192
  let handle = openedHandle;
3069
- if (!handle) try {
3070
- handle = await fs.open(file, "r");
3193
+ try {
3194
+ handle ??= await fs.open(file, "r");
3071
3195
  } catch {
3072
3196
  return;
3073
3197
  }
@@ -3120,10 +3244,10 @@ function readCodexAppServerRolloutTokenSnapshotLine(line) {
3120
3244
  const totalTokens = typeof value === "number" && Number.isFinite(value) ? value : void 0;
3121
3245
  const windowValue = info.model_context_window ?? info.modelContextWindow;
3122
3246
  const modelContextWindow = typeof windowValue === "number" && Number.isFinite(windowValue) && windowValue > 0 ? Math.floor(windowValue) : void 0;
3123
- const snapshot = {};
3124
- if (totalTokens !== void 0) snapshot.totalTokens = totalTokens;
3125
- if (modelContextWindow !== void 0) snapshot.modelContextWindow = modelContextWindow;
3126
- 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;
3127
3251
  } catch {
3128
3252
  return;
3129
3253
  }
@@ -3141,7 +3265,6 @@ function maxDefinedNumber(values) {
3141
3265
  const nums = values.filter((value) => value !== void 0);
3142
3266
  return nums.length ? Math.max(...nums) : void 0;
3143
3267
  }
3144
- /** Clears and drops a binding when the native Codex thread is too large to resume safely. */
3145
3268
  async function rotateOversizedCodexAppServerStartupBinding(params) {
3146
3269
  const binding = params.binding;
3147
3270
  if (!binding?.threadId) return { binding };
@@ -3252,7 +3375,7 @@ async function prepareCodexAttemptConnection({ params, options }) {
3252
3375
  config: params.config,
3253
3376
  agentId: policyAgentId
3254
3377
  });
3255
- const agentDir = params.agentDir ?? resolveAgentDir$2(params.config ?? {}, sessionAgentId);
3378
+ const agentDir = params.agentDir ?? resolveAgentDir$1(params.config ?? {}, sessionAgentId);
3256
3379
  const preparedEnvironment = params.hostCapabilities.preparedEnvironment?.();
3257
3380
  const remoteExec = isCodexRemoteExecPlacementSandbox(sandbox);
3258
3381
  const assertLocalTargetSupported = (unsupported) => {
@@ -3268,16 +3391,19 @@ async function prepareCodexAttemptConnection({ params, options }) {
3268
3391
  const disableLoginShell = remoteExec || preparedEnvironment?.localProcessEnv !== void 0 || preparedEnvironment?.managedLocalIdentity === true || preparedEnvironment !== void 0 && Object.keys(preparedEnvironment.credentialScrubEnv).length > 0;
3269
3392
  let shellEnvironment = baseShellEnvironment;
3270
3393
  let shellPathPrepend;
3394
+ let shellGitConfigParameters;
3271
3395
  const withPreparedProcessEnv = (appServer) => {
3272
3396
  assertLocalTargetSupported(appServer.start.transport !== "stdio" || Boolean(appServer.remoteWorkspaceRoot));
3273
- 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;
3274
3400
  const hasLocalToolEnv = localToolEnv && Object.keys(localToolEnv).length > 0;
3275
3401
  shellPathPrepend = hasLocalToolEnv ? preparedEnvironment?.localToolPathPrepend : void 0;
3276
3402
  shellEnvironment = hasLocalToolEnv ? {
3277
3403
  ...baseShellEnvironment,
3278
3404
  ...localToolEnv
3279
3405
  } : baseShellEnvironment;
3280
- return shellEnvironment ? {
3406
+ const prepared = shellEnvironment ? {
3281
3407
  ...appServer,
3282
3408
  start: {
3283
3409
  ...appServer.start,
@@ -3287,6 +3413,10 @@ async function prepareCodexAttemptConnection({ params, options }) {
3287
3413
  }
3288
3414
  }
3289
3415
  } : appServer;
3416
+ return shellGitConfigParameters ? {
3417
+ ...prepared,
3418
+ start: withCodexAppServerGitConfig(prepared.start, shellGitConfigParameters)
3419
+ } : prepared;
3290
3420
  };
3291
3421
  let bindingIdentity = sessionBindingIdentity({
3292
3422
  sessionId: params.sessionId,
@@ -3299,10 +3429,11 @@ async function prepareCodexAttemptConnection({ params, options }) {
3299
3429
  let activeContextEngine = isActiveHarnessContextEngine(params.contextEngine) ? params.contextEngine : void 0;
3300
3430
  const isInactiveThreadBootstrapBinding = (binding) => !activeContextEngine && binding?.contextEngine?.projection?.mode === "thread_bootstrap";
3301
3431
  if (bindingIdentity.kind === "session" && bindingIdentity.sessionKey) {
3302
- const authority = await resolveCodexRunSessionBindingAuthority({
3303
- identity: bindingIdentity,
3432
+ const { state: authority } = await prepareNativeSessionGenerationAuthority({
3304
3433
  config: params.config,
3305
- storePath: params.sessionTarget?.storePath
3434
+ storePath: params.sessionTarget?.storePath,
3435
+ target: bindingIdentity,
3436
+ createSupersededError: createCodexSessionGenerationSupersededError
3306
3437
  });
3307
3438
  if (authority === "superseded") throw createCodexSessionGenerationSupersededError(bindingIdentity.sessionId);
3308
3439
  if (authority === "ephemeral") {
@@ -3398,10 +3529,7 @@ async function prepareCodexAttemptConnection({ params, options }) {
3398
3529
  };
3399
3530
  let reviewerPolicyContext = resolveReviewerPolicyContext(startupBinding);
3400
3531
  preDynamicStartupStages.mark("auth-profile");
3401
- let configuredAppServer = await resolveRuntimeOptionsForBinding(startupBinding, {
3402
- modelProvider: reviewerPolicyContext.modelProvider,
3403
- model: reviewerPolicyContext.model
3404
- });
3532
+ let configuredAppServer = await resolveRuntimeOptionsForBinding(startupBinding, reviewerPolicyContext);
3405
3533
  const effectiveWorkspace = sandbox?.enabled ? sandbox.workspaceAccess === "rw" ? resolvedWorkspace : sandbox.workspaceDir : resolvedWorkspace;
3406
3534
  const requestedCwd = params.cwd ? resolveUserPath(params.cwd) : void 0;
3407
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");
@@ -3415,31 +3543,30 @@ async function prepareCodexAttemptConnection({ params, options }) {
3415
3543
  const effectiveCwd = sandbox?.enabled ? effectiveWorkspace : sessionPermissionCwd;
3416
3544
  if (effectiveWorkspace !== resolvedWorkspace) await ensureCodexWorkspaceDirOnce(effectiveWorkspace);
3417
3545
  preDynamicStartupStages.mark("effective-workspace");
3418
- const applySessionPermissionPolicy = (appServer, selection) => applyCodexSessionPermissionPolicy({
3419
- appServer,
3420
- permissionMode: params.permissionMode,
3421
- sessionRoot: params.sessionRoot,
3422
- defaultRoot: effectiveWorkspace,
3423
- pluginConfig,
3424
- canUseAutoReview: canUseCodexModelBackedApprovalsReviewerForModel({
3425
- modelProvider: selection.modelProvider,
3426
- model: selection.model,
3427
- config: params.config,
3428
- env: {
3429
- ...process.env,
3430
- ...appServer.start.env,
3431
- ...shellEnvironment
3432
- },
3433
- agentDir,
3434
- homeScope: appServer.start.homeScope,
3435
- codexArgs: appServer.start.args
3436
- }),
3437
- requirementsToml,
3438
- policyLocked: startupBinding?.connectionScope === "supervision",
3439
- execMode: execPolicy.mode
3440
- });
3441
3546
  const resolveFinalAppServer = (configured, selection) => {
3442
- 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
+ });
3443
3570
  const trusted = resolveCodexAppServerForModelProvider({
3444
3571
  appServer: session,
3445
3572
  provider: selection.modelProvider,
@@ -3509,10 +3636,7 @@ async function prepareCodexAttemptConnection({ params, options }) {
3509
3636
  preDynamicStartupStages.mark("rotate-binding");
3510
3637
  if (startupBinding !== startupBindingBeforeRotation) {
3511
3638
  reviewerPolicyContext = resolveReviewerPolicyContext(startupBinding);
3512
- configuredAppServer = await resolveRuntimeOptionsForBinding(startupBinding, {
3513
- modelProvider: reviewerPolicyContext.modelProvider,
3514
- model: reviewerPolicyContext.model
3515
- });
3639
+ configuredAppServer = await resolveRuntimeOptionsForBinding(startupBinding, reviewerPolicyContext);
3516
3640
  appServer = resolveFinalAppServer(configuredAppServer, reviewerPolicyContext);
3517
3641
  }
3518
3642
  const sessionPermissionPolicy = resolveCodexEffectiveSessionPermissionPolicy({
@@ -3599,6 +3723,7 @@ async function prepareCodexAttemptConnection({ params, options }) {
3599
3723
  agentDir,
3600
3724
  shellEnvironment,
3601
3725
  shellPathPrepend,
3726
+ shellGitConfigParameters,
3602
3727
  disableLoginShell,
3603
3728
  bindingIdentity,
3604
3729
  bindingStore,
@@ -3700,15 +3825,7 @@ function buildCodexSystemPromptReport(params) {
3700
3825
  nonProjectContextChars: params.developerInstructions.length,
3701
3826
  hash: sha256Text(params.developerInstructions)
3702
3827
  },
3703
- injectedWorkspaceFiles: buildCodexBootstrapInjectionStats({
3704
- bootstrapFiles: params.workspaceBootstrapContext.bootstrapFiles,
3705
- injectedFiles: params.workspaceBootstrapContext.promptContextFiles ?? [],
3706
- omitReferenceFiles: params.omitWorkspaceReferences,
3707
- omitPersonalProfiles: !params.parentLocalEgress,
3708
- developerInstructionFiles: [...params.workspaceBootstrapContext.threadDeveloperInstructionFiles ?? [], ...params.workspaceBootstrapContext.personaFiles ?? []],
3709
- memoryToolRoutedBootstrapFiles: params.workspaceBootstrapContext.memoryToolRoutedBootstrapFiles ?? [],
3710
- memoryToolRouted: params.workspaceBootstrapContext.memoryToolRouted === true
3711
- }),
3828
+ injectedWorkspaceFiles: buildCodexBootstrapInjectionStats(params),
3712
3829
  skills: {
3713
3830
  promptChars: skillsPrompt.length,
3714
3831
  hash: sha256Text(skillsPrompt),
@@ -3730,27 +3847,19 @@ function buildCodexSkillReportEntries(skillsPrompt) {
3730
3847
  }
3731
3848
  function buildCodexToolReportEntry(tool) {
3732
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;
3733
3859
  return {
3734
3860
  name: tool.name,
3735
3861
  summaryChars: summary.length,
3736
3862
  summaryHash: sha256Text(summary),
3737
- ...tool.deferLoading === true ? {
3738
- schemaChars: 0,
3739
- schemaHash: stableJsonHash(null),
3740
- propertiesCount: null
3741
- } : buildCodexToolSchemaStats(tool.inputSchema)
3742
- };
3743
- }
3744
- function buildCodexToolSchemaStats(schema) {
3745
- const schemaChars = (() => {
3746
- try {
3747
- return JSON.stringify(schema).length;
3748
- } catch {
3749
- return 0;
3750
- }
3751
- })();
3752
- const properties = isJsonObject(schema) && isJsonObject(schema.properties) ? schema.properties : null;
3753
- return {
3754
3863
  schemaChars,
3755
3864
  schemaHash: stableJsonHash(schema),
3756
3865
  propertiesCount: properties ? Object.keys(properties).length : null
@@ -3763,17 +3872,18 @@ function stableJsonHash(value) {
3763
3872
  return sha256Text(JSON.stringify(stabilizeJsonValue(value)) ?? "null");
3764
3873
  }
3765
3874
  function buildCodexBootstrapInjectionStats(params) {
3766
- const injectedIndex = indexCodexContextFileContent(params.injectedFiles);
3767
- const developerInstructionIndex = indexCodexContextFileContent(params.developerInstructionFiles ?? []);
3768
- const memoryToolRoutedPaths = new Set((params.memoryToolRoutedBootstrapFiles ?? []).map((file) => readNonBlankString(file.path)).filter(isNonEmptyString).map(normalizeCodexContextFilePath));
3769
- 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) => {
3770
3880
  const fileName = readNonBlankString(file.name);
3771
3881
  const pathValue = readNonBlankString(file.path) ?? fileName ?? "";
3772
3882
  const displayName = (fileName ?? getCodexContextFileDisplayBasename(pathValue)) || pathValue;
3773
3883
  const baseName = getCodexContextFileBasename(pathValue || fileName || "");
3774
3884
  const rawChars = file.missing ? 0 : (file.content ?? "").trimEnd().length;
3775
- const memoryToolRoutedFile = baseName === "memory.md" && params.memoryToolRouted === true && memoryToolRoutedPaths.has(normalizeCodexContextFilePath(pathValue));
3776
- 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);
3777
3887
  if (!file.missing && injected === void 0 && CODEX_NATIVE_PROJECT_DOC_BASENAMES.has(baseName)) return {
3778
3888
  name: displayName,
3779
3889
  path: pathValue,
@@ -3783,7 +3893,7 @@ function buildCodexBootstrapInjectionStats(params) {
3783
3893
  injectedChars: null,
3784
3894
  truncated: null
3785
3895
  };
3786
- 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;
3787
3897
  const injectedChars = omitted ? 0 : injected?.length ?? 0;
3788
3898
  const truncated = omitted ? false : !file.missing && injectedChars < rawChars;
3789
3899
  return {
@@ -3806,15 +3916,11 @@ function indexCodexContextFileContent(files) {
3806
3916
  const baseName = getCodexContextFileBasename(pathValue);
3807
3917
  if (baseName && !byBaseName.has(baseName)) byBaseName.set(baseName, file.content);
3808
3918
  }
3809
- return {
3810
- byPath,
3811
- 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);
3812
3922
  };
3813
3923
  }
3814
- function readCodexIndexedContextFileContent(index, pathValue, fileName) {
3815
- const baseName = getCodexContextFileBasename(fileName ?? pathValue);
3816
- return index.byPath.get(pathValue) ?? (fileName ? index.byPath.get(fileName) : void 0) ?? (baseName ? index.byBaseName.get(baseName) : void 0);
3817
- }
3818
3924
  function readPositiveNumber(value) {
3819
3925
  return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.floor(value) : void 0;
3820
3926
  }
@@ -3892,7 +3998,7 @@ function resolveCodexDeliveryHintPreservedInputRange(params) {
3892
3998
  if (!deliveryHint || !promptInputRange || promptInputRange.start < 0 || promptInputRange.end < promptInputRange.start || promptInputRange.end > prompt.length || !decoratedPrompt.endsWith(promptWithoutDeliveryHint)) return;
3893
3999
  const promptWithoutDeliveryHintStart = prompt.length - promptWithoutDeliveryHint.length;
3894
4000
  const inputStart = Math.max(promptInputRange.start, promptWithoutDeliveryHintStart);
3895
- const inputEnd = Math.max(inputStart, Math.min(promptInputRange.end, promptWithoutDeliveryHint.length + promptWithoutDeliveryHintStart));
4001
+ const inputEnd = Math.max(inputStart, promptInputRange.end);
3896
4002
  const decoratedPromptSuffixStart = decoratedPrompt.length - promptWithoutDeliveryHint.length;
3897
4003
  const requestHeader = "Current user request:\n";
3898
4004
  const requestHeaderStart = decoratedPromptSuffixStart - 22;
@@ -3914,7 +4020,7 @@ function splitLeadingCodexDeliveryHint(prompt) {
3914
4020
  //#region extensions/codex/src/app-server/run-attempt-context.ts
3915
4021
  async function prepareCodexAttemptContext(runtime, attemptTools) {
3916
4022
  const { connection, runtimeParams, effectiveContextWindowInfo, effectiveContextTokenBudget, effectiveRuntimeProviderId, effectiveRuntimeModelId, hookChannelId } = runtime;
3917
- 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;
3918
4024
  const { toolBridge } = attemptTools;
3919
4025
  const activeTranscriptTarget = {
3920
4026
  agentId: sessionAgentId,
@@ -4022,7 +4128,10 @@ async function prepareCodexAttemptContext(runtime, attemptTools) {
4022
4128
  dynamicTools: toolBridge.availableSpecs
4023
4129
  });
4024
4130
  const refreshableInstructions = joinPresentSections(skillsInstructions, workspaceBootstrapContext.sharedPersonaInstructions, workspaceBootstrapContext.memoryInstructions) || void 0;
4025
- 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);
4026
4135
  const watchedSessionsContext = await prepareCodexWatchedSessionsContext({
4027
4136
  attempt: runtimeParams,
4028
4137
  dynamicTools: toolBridge.availableSpecs,
@@ -4058,10 +4167,7 @@ async function prepareCodexAttemptContext(runtime, attemptTools) {
4058
4167
  promptContextRange: void 0,
4059
4168
  developerInstructions: baseDeveloperInstructions,
4060
4169
  contextEngineProjection: void 0,
4061
- precomputedStaleBindingContinuityProjectionApplied: false,
4062
- staleBindingContinuityForcedFreshStart: false,
4063
- noEngineContinuityProjectionApplied: false,
4064
- inactiveThreadBootstrapBindingForcedFreshStart: initialInactiveThreadBootstrapBindingForcedFreshStart
4170
+ noEngineContinuityProjectionApplied: false
4065
4171
  },
4066
4172
  codexContextProjectionMaxChars: resolveCodexContextEngineProjectionMaxChars({ contextTokenBudget: effectiveContextTokenBudget }),
4067
4173
  codexContinuityProjectionMaxChars: resolveCodexContinuityProjectionMaxChars({
@@ -4113,12 +4219,15 @@ function createCodexModelCallDiagnosticEmitter(params) {
4113
4219
  let started = false;
4114
4220
  let terminalEmitted = false;
4115
4221
  let requestPayloadBytes;
4116
- const privateData = (modelContent) => modelContent && Object.keys(modelContent).length > 0 ? { modelContent } : void 0;
4117
- const buildContent = () => ({
4118
- ...params.capture.inputMessages ? { inputMessages: params.buildInputMessages() } : {},
4119
- ...params.capture.systemPrompt ? { systemPrompt: params.buildSystemPrompt() } : {},
4120
- ...toolDefinitions ? { toolDefinitions } : {}
4121
- });
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
+ };
4122
4231
  const emitTerminal = (type, outputMessages, fields = {}) => {
4123
4232
  if (!started || terminalEmitted) return false;
4124
4233
  terminalEmitted = true;
@@ -4128,10 +4237,7 @@ function createCodexModelCallDiagnosticEmitter(params) {
4128
4237
  durationMs: Math.max(0, now() - startedAt),
4129
4238
  ...fields,
4130
4239
  ...requestPayloadBytes !== void 0 ? { requestPayloadBytes } : {}
4131
- }, privateData({
4132
- ...buildContent(),
4133
- ...params.capture.outputMessages ? { outputMessages } : {}
4134
- }));
4240
+ }, buildPrivateData({ outputMessages }));
4135
4241
  return true;
4136
4242
  };
4137
4243
  return {
@@ -4144,7 +4250,7 @@ function createCodexModelCallDiagnosticEmitter(params) {
4144
4250
  emitTrustedDiagnosticEventWithPrivateData({
4145
4251
  type: "model.call.started",
4146
4252
  ...params.baseFields
4147
- }, privateData(buildContent()));
4253
+ }, buildPrivateData());
4148
4254
  },
4149
4255
  emitCompleted(result) {
4150
4256
  emitTerminal("model.call.completed", result.lastAssistant ? [result.lastAssistant] : result.assistantTexts);
@@ -4373,8 +4479,7 @@ function createCodexTrajectoryRecorder(trajectory) {
4373
4479
  };
4374
4480
  }
4375
4481
  function recordCodexTrajectoryContext(recorder, params) {
4376
- if (!recorder) return;
4377
- recorder.recordEvent("context.compiled", {
4482
+ recorder?.recordEvent("context.compiled", {
4378
4483
  systemPrompt: params.developerInstructions,
4379
4484
  prompt: params.prompt ?? params.attempt.prompt,
4380
4485
  imagesCount: params.attempt.images?.length ?? 0,
@@ -4401,12 +4506,11 @@ function toTrajectoryToolDefinitions(tools) {
4401
4506
  if (!tools || tools.length === 0) return;
4402
4507
  return flattenCodexDynamicToolFunctions(tools).flatMap((tool) => {
4403
4508
  const name = tool.name?.trim();
4404
- if (!name) return [];
4405
- return [{
4509
+ return name ? [{
4406
4510
  name,
4407
4511
  description: tool.description,
4408
4512
  parameters: tool.inputSchema
4409
- }];
4513
+ }] : [];
4410
4514
  }).toSorted((left, right) => left.name.localeCompare(right.name));
4411
4515
  }
4412
4516
  function normalizeCodexTrajectoryError(value) {
@@ -4422,7 +4526,7 @@ function normalizeCodexTrajectoryError(value) {
4422
4526
  //#endregion
4423
4527
  //#region extensions/codex/src/app-server/run-attempt-finalize.ts
4424
4528
  async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notifications, requestRuntime, activeTurn) {
4425
- const { prompt, state: resourceState, trajectoryRecorder, markTrajectoryEndRecorded } = resources;
4529
+ const { prompt, state: resourceState, trajectoryRecorder } = resources;
4426
4530
  const { context, systemPromptReport } = prompt;
4427
4531
  const { runtime, attemptTools, activeTranscriptTarget, hookContext } = context;
4428
4532
  const { hookRunner } = context;
@@ -4454,6 +4558,8 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
4454
4558
  readRetainedNativeCommands,
4455
4559
  steeringMessages: params.pluginRuntimeRefreshPending?.() ? turnRuntime.steeringQueueRef.current?.getAcceptedMessages() : void 0
4456
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;
4457
4563
  const projectedTerminal = attemptTerminal.project(result.terminal);
4458
4564
  const isFinalAborted = () => terminalState.explicitCancellationObserved || !resourceState.executionDisconnectError && (projectedTerminal.aborted || runAbortController.signal.aborted && !state.clientClosedAbort);
4459
4565
  const currentPromptError = (fallback) => resourceState.executionDisconnectError ?? state.clientClosedPromptError ?? (state.timeout ? `codex app-server ${state.timeout.kind === "execution" ? "execution budget" : "terminal settlement"} timed out` : fallback);
@@ -4534,7 +4640,7 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
4534
4640
  for (const message of [
4535
4641
  result.lastAssistant,
4536
4642
  result.currentAttemptAssistant,
4537
- result.messagesSnapshot.find((candidate) => readMirrorIdentity(candidate) === `${activeTurnId}:assistant`)
4643
+ terminalAssistantSource
4538
4644
  ]) if (message?.role === "assistant") {
4539
4645
  if (!message.diagnostics?.some((diagnostic) => diagnostic.type === "provider_refusal") || finalAborted || finalPromptError) {
4540
4646
  message.stopReason = finalAborted ? "aborted" : finalPromptError ? "error" : "stop";
@@ -4563,11 +4669,11 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
4563
4669
  const mirrorTerminal = projectTerminalOutcome();
4564
4670
  state.pendingSettlementStage = "transcript/mirror";
4565
4671
  return codexTranscriptMirrorRuntime.mirrorBestEffort({
4566
- assertWriteCurrent: () => {
4672
+ assertWriteCurrent: createNativeSessionBindingAuthority([], () => {
4567
4673
  if (!isSettlementActive() || state.settlementWarning !== warning) throw new Error("Codex transcript settlement is no longer active");
4568
4674
  const current = projectTerminalOutcome();
4569
4675
  if (current.finalAborted !== mirrorTerminal.finalAborted || current.effectiveTimedOut !== mirrorTerminal.effectiveTimedOut || current.finalPromptError !== mirrorTerminal.finalPromptError) throw new Error("Codex transcript terminal outcome changed before write");
4570
- },
4676
+ }).assertLegacyCurrent,
4571
4677
  params,
4572
4678
  settlementWarning: warning,
4573
4679
  agentId: sessionAgentId,
@@ -4579,43 +4685,40 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
4579
4685
  turnId: activeTurnId
4580
4686
  });
4581
4687
  };
4582
- try {
4583
- if (projectionDrained && isSettlementActive() && !state.settlementWarning) mirrorOutcome = await Promise.race([
4584
- mirrorFinal(),
4585
- drainGraceElapsed.promise.then(() => unavailableMirror),
4586
- 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
4587
4718
  ]);
4588
- if (state.settlementWarning && !runAbortController.signal.aborted) {
4589
- mirrorOutcome = await Promise.race([mirrorFinal(), drainGraceElapsed.promise.then(() => unavailableMirror)]);
4590
- if (mirrorOutcome === unavailableMirror) trajectoryRecorder?.recordEvent("turn.settlement_persistence_unavailable", {
4591
- pendingStage: "transcript/mirror",
4592
- threadId: resourceState.thread.threadId,
4593
- turnId: activeTurnId
4594
- });
4595
- }
4596
- if (toolState.yieldMessage && projectTerminalOutcome().turnSucceeded) {
4597
- state.pendingSettlementStage = "transcript/yield-context";
4598
- await Promise.race([
4599
- appendSessionYieldContext({
4600
- ...activeTranscriptTarget.sessionTarget,
4601
- agentId: activeTranscriptTarget.agentId,
4602
- sessionId: activeTranscriptTarget.sessionId,
4603
- sessionKey: activeTranscriptTarget.sessionKey,
4604
- config: params.config,
4605
- message: toolState.yieldMessage,
4606
- assertCurrent: () => {
4607
- connection.assertLegacyCurrent();
4608
- if (!isSettlementActive() || !projectTerminalOutcome().turnSucceeded) throw new Error("Codex yield settlement is no longer active");
4609
- }
4610
- }),
4611
- drainGraceElapsed.promise,
4612
- degradedSettlement
4613
- ]);
4614
- }
4615
- await settleReplyMedia(activeTurn, result, turnRuntime, runAbortController.signal);
4616
- } finally {
4617
- closeSettlement();
4618
4719
  }
4720
+ await settleReplyMedia(activeTurn, result, turnRuntime, runAbortController.signal);
4721
+ closeSettlement();
4619
4722
  const { effectiveTimedOut, finalPromptError, codexAppServerFailure, promptTimeoutOutcome, finalAborted, turnSucceeded, attemptSucceeded, completedTurnStatus } = projectTerminalOutcome();
4620
4723
  terminalState.settledTurnStatus = turnSucceeded ? "completed" : completedTurnStatus === "failed" && !finalAborted && !effectiveTimedOut && !state.clientClosedPromptError && !resourceState.executionDisconnectError ? "failed" : void 0;
4621
4724
  terminalState.sharedAbortAllowedAfterTerminalOutcome = shouldKeepCodexSharedAbortOpen({
@@ -4731,14 +4834,15 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
4731
4834
  yieldDetected: toolState.yieldDetected,
4732
4835
  promptError: normalizeCodexTrajectoryError(finalPromptError)
4733
4836
  });
4734
- markTrajectoryEndRecorded();
4837
+ resourceState.trajectoryEndRecorded = true;
4735
4838
  const terminalAssistantText = collectTerminalAssistantText(result);
4839
+ const terminalAssistantItemId = assistantTranscriptIdempotencyKey ?? terminalSourceKey;
4736
4840
  if (terminalAssistantText && (assistantTranscriptIdempotencyKey || (!streamState.eventEmitted || streamState.needsTerminalSnapshot) && !finalAborted && !finalPromptError)) emitCodexAppServerEvent(params, {
4737
4841
  stream: "assistant",
4738
4842
  data: {
4739
4843
  text: terminalAssistantText,
4740
- ...assistantTranscriptIdempotencyKey ? {
4741
- itemId: assistantTranscriptIdempotencyKey,
4844
+ ...terminalAssistantItemId ? {
4845
+ itemId: terminalAssistantItemId,
4742
4846
  replace: true,
4743
4847
  replaceable: true
4744
4848
  } : {}
@@ -4803,58 +4907,53 @@ function createCodexAttemptLifecycleController(resources, turnRuntime) {
4803
4907
  const { connection } = prompt.context.runtime;
4804
4908
  const { params, attemptStartedAt, runAbortController, fastModeAutoStartedAtMs, fastModeAutoProgressState } = connection;
4805
4909
  const { state, activeTurnItemIds, pendingOpenClawDynamicToolCompletionIds } = turnRuntime;
4806
- const releaseTurnAfterTerminalDynamicTool = (value) => {
4807
- if (!shouldReleaseTurnAfterTerminalDynamicTool({
4808
- completed: state.completed,
4809
- aborted: runAbortController.signal.aborted,
4810
- responseSuccess: value.response.success,
4811
- currentTurnHadNonTerminalDynamicToolResult: state.currentTurnHadNonTerminalDynamicToolResult,
4812
- activeAppServerTurnRequests: state.activeAppServerTurnRequests,
4813
- activeTurnItemIdsCount: activeTurnItemIds.size,
4814
- pendingOpenClawDynamicToolCompletionIdsCount: pendingOpenClawDynamicToolCompletionIds.size
4815
- })) return;
4816
- state.pendingTerminalDynamicToolRelease = void 0;
4817
- trajectoryRecorder?.recordEvent("turn.dynamic_tool_terminal_release", {
4818
- threadId: value.call.threadId,
4819
- turnId: value.call.turnId,
4820
- toolCallId: value.call.callId,
4821
- name: value.call.tool,
4822
- durationMs: value.durationMs
4823
- });
4824
- embeddedAgentLog.info("codex app-server turn released after terminal dynamic tool result", {
4825
- threadId: value.call.threadId,
4826
- turnId: value.call.turnId,
4827
- toolCallId: value.call.callId,
4828
- tool: value.call.tool,
4829
- durationMs: value.durationMs
4830
- });
4831
- turnRuntime.steeringQueueRef.current?.cancel();
4832
- turnRuntime.interruptTurn(value.call.turnId, { locallyCompleted: true });
4833
- turnRuntime.completeTurn();
4834
- };
4910
+ const batchHadNonTerminalResult = () => state.currentTurnHadNonTerminalDynamicToolResult && !state.currentTurnHadToolAuthoredFinalReply;
4835
4911
  const scheduleTerminalDynamicToolReleaseCheck = () => {
4836
4912
  if (state.terminalDynamicToolReleaseCheckScheduled || !state.pendingTerminalDynamicToolRelease && !state.currentTurnHadNonTerminalDynamicToolResult) return;
4837
4913
  state.terminalDynamicToolReleaseCheckScheduled = true;
4838
4914
  setImmediate(() => {
4839
4915
  state.terminalDynamicToolReleaseCheckScheduled = false;
4840
- if (state.pendingTerminalDynamicToolRelease?.response.success === true && !state.currentTurnHadNonTerminalDynamicToolResult && state.activeAppServerTurnRequests === 0 && pendingOpenClawDynamicToolCompletionIds.size === 0) turnRuntime.steeringQueueRef.current?.cancel();
4841
- const action = resolveTerminalDynamicToolBatchAction({
4842
- activeAppServerTurnRequests: state.activeAppServerTurnRequests,
4843
- activeTurnItemIdsCount: activeTurnItemIds.size,
4844
- pendingOpenClawDynamicToolCompletionIdsCount: pendingOpenClawDynamicToolCompletionIds.size,
4845
- currentTurnHadNonTerminalDynamicToolResult: state.currentTurnHadNonTerminalDynamicToolResult,
4846
- hasPendingTerminalDynamicToolRelease: state.pendingTerminalDynamicToolRelease !== void 0
4847
- });
4848
- if (action === "release-pending-terminal" && state.pendingTerminalDynamicToolRelease) releaseTurnAfterTerminalDynamicTool(state.pendingTerminalDynamicToolRelease);
4849
- 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()) {
4850
4919
  state.pendingTerminalDynamicToolRelease = void 0;
4851
4920
  state.currentTurnHadNonTerminalDynamicToolResult = false;
4921
+ state.currentTurnHadToolAuthoredFinalReply = false;
4922
+ return;
4852
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();
4853
4945
  }).unref?.();
4854
4946
  };
4855
- const scheduleTurnReleaseAfterTerminalDynamicTool = (value) => {
4856
- state.pendingTerminalDynamicToolRelease = value;
4857
- 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
+ }
4858
4957
  };
4859
4958
  const { emitLifecycleStart, emitLifecycleTerminal, emitExecutionPhaseOnce } = createAgentHarnessAttemptLifecycle({
4860
4959
  attempt: params,
@@ -4934,8 +5033,8 @@ function createCodexAttemptLifecycleController(resources, turnRuntime) {
4934
5033
  }
4935
5034
  };
4936
5035
  return {
5036
+ recordDynamicToolResult,
4937
5037
  scheduleTerminalDynamicToolReleaseCheck,
4938
- scheduleTurnReleaseAfterTerminalDynamicTool,
4939
5038
  emitLifecycleStart,
4940
5039
  emitLifecycleTerminal,
4941
5040
  buildLifecycleTerminalMeta,
@@ -4946,6 +5045,78 @@ function createCodexAttemptLifecycleController(resources, turnRuntime) {
4946
5045
  };
4947
5046
  }
4948
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
4949
5120
  //#region extensions/codex/src/app-server/run-attempt-notification-controller.ts
4950
5121
  function createCodexAttemptNotificationController(resources, turnRuntime, lifecycle) {
4951
5122
  const { prompt, state: resourceState, projectorRef } = resources;
@@ -4956,20 +5127,11 @@ function createCodexAttemptNotificationController(resources, turnRuntime, lifecy
4956
5127
  const { state, turnIdRef, steeringQueueRef, activeTurnItemIds, pendingOpenClawDynamicToolCompletionIds, openClawDynamicToolExecutions, completeTurn, noteProgress, deadlines } = turnRuntime;
4957
5128
  const { scheduleTerminalDynamicToolReleaseCheck, reportExecutionNotification, maybeAnnounceFastModeAutoOff } = lifecycle;
4958
5129
  const pendingNativeCommandItems = /* @__PURE__ */ new Set();
4959
- const nativeItemObservers = /* @__PURE__ */ new Set();
5130
+ let nativeItemsCompletion;
4960
5131
  const waitForNativeTerminalItems = async (signal) => {
4961
5132
  if (pendingNativeCommandItems.size === 0) return;
4962
- const completion = createDeferred();
4963
- const observe = () => {
4964
- if (pendingNativeCommandItems.size === 0) completion.resolve();
4965
- };
4966
- nativeItemObservers.add(observe);
4967
- try {
4968
- observe();
4969
- if (!await waitForPromiseOrAbort(completion.promise, signal)) signal.throwIfAborted();
4970
- } finally {
4971
- nativeItemObservers.delete(observe);
4972
- }
5133
+ const completion = nativeItemsCompletion ??= createDeferred();
5134
+ if (!await waitForPromiseOrAbort(completion.promise, signal)) signal.throwIfAborted();
4973
5135
  };
4974
5136
  const readTerminalTurn = (notification, notificationTurnId) => notification.method === "turn/completed" && isCodexNotificationForTurn(notification.params, resourceState.thread.threadId, notificationTurnId) ? readCodexTurnCompletedNotification(notification.params)?.turn : void 0;
4975
5137
  const handleNotification = async (notification) => {
@@ -4992,10 +5154,7 @@ function createCodexAttemptNotificationController(resources, turnRuntime, lifecy
4992
5154
  updateActiveTurnItemIds(notification, activeTurnItemIds);
4993
5155
  noteProgress(`notification:${notification.method}`);
4994
5156
  reportExecutionNotification(notification);
4995
- if (isPendingOpenClawDynamicToolCompletionNotification(notification, pendingOpenClawDynamicToolCompletionIds)) {
4996
- const itemId = readNotificationItemId(notification);
4997
- if (itemId) pendingOpenClawDynamicToolCompletionIds.delete(itemId);
4998
- }
5157
+ completePendingOpenClawDynamicToolNotification(notification, pendingOpenClawDynamicToolCompletionIds);
4999
5158
  if (notification.method === "item/completed") {
5000
5159
  if (activeTurnItemIds.size === 0) scheduleTerminalDynamicToolReleaseCheck();
5001
5160
  const item = readCodexNotificationItem(notification.params);
@@ -5009,9 +5168,28 @@ function createCodexAttemptNotificationController(resources, turnRuntime, lifecy
5009
5168
  }
5010
5169
  if (item?.type === "userMessage" && typeof item.clientId === "string") steeringQueueRef.current?.confirmConsumed(item.clientId);
5011
5170
  }
5012
- if (isCodexTurnAbortMarkerNotification(notification, { currentPromptTexts: [turnState.codexTurnPromptText] })) state.sawCodexInterruptMarker = true;
5171
+ if (isCodexTurnAbortMarkerNotification(notification, { currentPromptText: turnState.codexTurnPromptText })) state.sawCodexInterruptMarker = true;
5013
5172
  }
5014
- 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);
5015
5193
  if (isCurrentTurn && activeTurnItemIds.size === 0 && isRawFunctionToolOutputCompletionNotification(notification)) await maybeAnnounceFastModeAutoOff();
5016
5194
  } catch (error) {
5017
5195
  embeddedAgentLog.debug("codex app-server projector notification threw", {
@@ -5024,7 +5202,10 @@ function createCodexAttemptNotificationController(resources, turnRuntime, lifecy
5024
5202
  const item = readCodexNotificationItem(notification.params);
5025
5203
  if (item?.type === "commandExecution") pendingNativeCommandItems.delete(item.id);
5026
5204
  }
5027
- for (const observe of nativeItemObservers) observe();
5205
+ if (pendingNativeCommandItems.size === 0) {
5206
+ nativeItemsCompletion?.resolve();
5207
+ nativeItemsCompletion = void 0;
5208
+ }
5028
5209
  if (completedTurn) {
5029
5210
  if (completedTurn.status === "interrupted" && state.sawCodexInterruptMarker) projector.markAborted();
5030
5211
  completeTurn();
@@ -5095,6 +5276,7 @@ async function prepareCodexAttemptPrompt(context) {
5095
5276
  const { connection, runtimeParams, effectiveContextTokenBudget, effectiveRuntimeModelId, effectiveRuntimeProviderId } = runtime;
5096
5277
  const { params, activeContextEngine, usesSupervisionConnection, mutable, isInactiveThreadBootstrapBinding, bindingStore, bindingIdentity, agentDir, appServer, contextSessionKey, effectiveWorkspace, sandbox } = connection;
5097
5278
  const { toolBridge } = attemptTools;
5279
+ const availableToolNames = () => flattenCodexDynamicToolFunctions(toolBridge.availableSpecs).map((tool) => tool.name).filter(isNonEmptyString);
5098
5280
  const nativeHistoryProvenancePrefix = params.trigger === "user" ? buildCodexHistoryProvenancePrefix(params) : void 0;
5099
5281
  const forkedSession = !mutable.startupBinding?.threadId && params.sessionTarget ? getSessionEntry({
5100
5282
  ...params.sessionTarget,
@@ -5140,10 +5322,10 @@ async function prepareCodexAttemptPrompt(context) {
5140
5322
  };
5141
5323
  const applyContinuityProjection = async (messages) => {
5142
5324
  const projection = await projectContextEngineAssemblyForCodex({
5143
- assembledMessages: messages,
5325
+ assembledMessages: [...messages, ...params.continuation?.messages ?? []],
5144
5326
  prompt: params.prompt,
5145
5327
  maxRenderedContextChars: codexContinuityProjectionMaxChars,
5146
- toolPayloadMode: params.pluginRuntimeRefreshMessages || preserveForkedToolResults ? "preserve" : "elide",
5328
+ toolPayloadMode: params.continuation || params.pluginRuntimeRefreshMessages || preserveForkedToolResults ? "preserve" : "elide",
5147
5329
  prepareFileContext,
5148
5330
  currentUserTurnIdempotencyKey
5149
5331
  });
@@ -5162,7 +5344,7 @@ async function prepareCodexAttemptPrompt(context) {
5162
5344
  sessionKey: contextSessionKey,
5163
5345
  messages: historyState.messages,
5164
5346
  tokenBudget: effectiveContextTokenBudget,
5165
- availableTools: new Set(flattenCodexDynamicToolFunctions(toolBridge.availableSpecs).map((tool) => tool.name).filter(isNonEmptyString)),
5347
+ availableTools: new Set(availableToolNames()),
5166
5348
  citationsMode: params.config?.memory?.citations,
5167
5349
  sandboxed: sandbox?.enabled === true,
5168
5350
  modelId: effectiveRuntimeModelId,
@@ -5177,7 +5359,7 @@ async function prepareCodexAttemptPrompt(context) {
5177
5359
  });
5178
5360
  if (!assembled) throw new Error("context engine assemble returned no result");
5179
5361
  const contextEngineProjection = readContextEngineThreadBootstrapProjection(assembled.contextProjection);
5180
- const projectionDecision = contextEngineProjection ? resolveContextEngineBootstrapProjectionDecision({
5362
+ const projectionDecision = contextEngineProjection && !params.continuation ? resolveContextEngineBootstrapProjectionDecision({
5181
5363
  startupBinding: decisionStartupBinding,
5182
5364
  expectedBinding: buildContextEngineBinding({ ...runtimeParams }, contextEngineProjection),
5183
5365
  projection: contextEngineProjection,
@@ -5188,11 +5370,11 @@ async function prepareCodexAttemptPrompt(context) {
5188
5370
  reason: "per-turn-projection"
5189
5371
  };
5190
5372
  const projection = await projectContextEngineAssemblyForCodex({
5191
- assembledMessages: assembled.messages,
5373
+ assembledMessages: [...assembled.messages, ...params.continuation?.messages ?? []],
5192
5374
  prompt: params.prompt,
5193
5375
  systemPromptAddition: assembled.systemPromptAddition,
5194
5376
  maxRenderedContextChars: codexContextProjectionMaxChars,
5195
- toolPayloadMode: contextEngineProjection || params.pluginRuntimeRefreshMessages || preserveForkedToolResults ? "preserve" : "elide",
5377
+ toolPayloadMode: contextEngineProjection || params.continuation || params.pluginRuntimeRefreshMessages || preserveForkedToolResults ? "preserve" : "elide",
5196
5378
  ...projectionDecision.project ? { prepareFileContext } : {},
5197
5379
  currentUserTurnIdempotencyKey
5198
5380
  });
@@ -5220,7 +5402,7 @@ async function prepareCodexAttemptPrompt(context) {
5220
5402
  promptState.promptContextRange = projectionDecision.project ? projection.promptContextRange : void 0;
5221
5403
  promptState.developerInstructions = joinPresentSections(baseDeveloperInstructions, projection.developerInstructionAddition);
5222
5404
  } catch (assembleErr) {
5223
- if (assembleErr instanceof CodexContextAttachmentError || params.pluginRuntimeRefreshMessages) throw assembleErr;
5405
+ if (assembleErr instanceof CodexContextAttachmentError || params.continuation || params.pluginRuntimeRefreshMessages) throw assembleErr;
5224
5406
  assertProjectionCurrent();
5225
5407
  embeddedAgentLog.warn("context engine assemble failed; using Codex baseline prompt", { error: formatErrorMessage(assembleErr) });
5226
5408
  }
@@ -5238,7 +5420,7 @@ async function prepareCodexAttemptPrompt(context) {
5238
5420
  bootstrapContextRunKind: params.bootstrapContextRunKind,
5239
5421
  toolAuthority: {
5240
5422
  fingerprint: params.toolAuthorityFingerprint,
5241
- activeToolNames: () => flattenCodexDynamicToolFunctions(toolBridge.availableSpecs).map((tool) => tool.name).filter(isNonEmptyString),
5423
+ activeToolNames: availableToolNames,
5242
5424
  assertActive: connection.assertLegacyCurrent
5243
5425
  }
5244
5426
  });
@@ -5306,53 +5488,49 @@ async function prepareCodexAttemptPrompt(context) {
5306
5488
  ...parentLocalContext,
5307
5489
  skillsInstructions
5308
5490
  }) : buildTurnCollaborationMode(params).settings.developer_instructions) ?? void 0);
5309
- const rebuildCodexPromptBuildFromCurrentProjection = async () => {
5310
- turnState.promptBuild = await buildPromptFromCurrentInputs();
5311
- turnState.codexTurnPromptText = decorateCodexTurnPromptText(turnState.promptBuild);
5312
- };
5313
- const rebuildCodexTurnPromptTextFromCurrentProjection = async () => {
5491
+ const rebuildCodexPromptBuildFromCurrentProjection = async (preserveInstructions = false) => {
5314
5492
  const nextPromptBuild = await buildPromptFromCurrentInputs();
5315
- turnState.promptBuild = {
5493
+ turnState.promptBuild = preserveInstructions ? {
5316
5494
  ...turnState.promptBuild,
5317
5495
  prompt: nextPromptBuild.prompt,
5318
5496
  promptInputRange: nextPromptBuild.promptInputRange
5319
- };
5497
+ } : nextPromptBuild;
5320
5498
  turnState.codexTurnPromptText = decorateCodexTurnPromptText(nextPromptBuild);
5321
5499
  };
5322
- const selectNewerVisibleHistoryAfterBinding = (binding) => {
5500
+ const applyResumeStaleBindingContinuityProjection = async (binding) => {
5323
5501
  const cutoff = Date.parse(binding.historyCoveredThrough ?? "");
5324
- return historyState.messages.filter((message) => {
5502
+ const newerVisibleMessages = historyState.messages.filter((message) => {
5325
5503
  if (message.role !== "user" && message.role !== "assistant" && !isCodexDurableCustomMessage(message)) return false;
5326
5504
  const mirrorIdentity = readMirrorIdentity(message);
5327
5505
  const timestamp = typeof message.timestamp === "number" ? message.timestamp : typeof message.timestamp === "string" ? Date.parse(message.timestamp) : NaN;
5328
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);
5329
5507
  });
5330
- };
5331
- const applyResumeStaleBindingContinuityProjection = async (binding) => {
5332
- const newerVisibleMessages = selectNewerVisibleHistoryAfterBinding(binding);
5333
5508
  if (newerVisibleMessages.length === 0) return false;
5334
5509
  await applyContinuityProjection(newerVisibleMessages);
5335
5510
  return true;
5336
5511
  };
5512
+ let staleBindingContinuityForcedFreshStart = false;
5513
+ let inactiveThreadBootstrapBindingForcedFreshStart = connection.initialInactiveThreadBootstrapBindingForcedFreshStart;
5337
5514
  const precomputeNoContextEngineStaleBindingProjection = async () => {
5338
- promptState.precomputedStaleBindingContinuityProjectionApplied = false;
5339
- promptState.staleBindingContinuityForcedFreshStart = false;
5340
5515
  const binding = mutable.startupBinding;
5341
- if (activeContextEngine || !binding?.threadId || binding.pendingSupervisionBranch) return false;
5516
+ if (activeContextEngine || params.continuation || !binding?.threadId || binding.pendingSupervisionBranch) return false;
5342
5517
  if (isInactiveThreadBootstrapBinding(binding)) {
5343
- promptState.inactiveThreadBootstrapBindingForcedFreshStart = true;
5518
+ inactiveThreadBootstrapBindingForcedFreshStart = true;
5344
5519
  return false;
5345
5520
  }
5346
- const projected = await applyResumeStaleBindingContinuityProjection(binding);
5347
- promptState.precomputedStaleBindingContinuityProjectionApplied = projected;
5348
- return projected;
5521
+ return await applyResumeStaleBindingContinuityProjection(binding);
5349
5522
  };
5350
5523
  const applyNoContextEngineContinuityProjection = async (action, binding) => {
5351
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())));
5352
- if (activeContextEngine || !hasContinuity && !params.pluginRuntimeRefreshMessages?.length) return false;
5353
- if (action === "resumed" && promptState.precomputedStaleBindingContinuityProjectionApplied) return true;
5354
- if (action === "started" && promptState.staleBindingContinuityForcedFreshStart) return true;
5355
- 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;
5356
5534
  if (action === "resumed" && binding) return applyResumeStaleBindingContinuityProjection(binding);
5357
5535
  if (action === "started") {
5358
5536
  await applyContinuityProjection(historyState.messages);
@@ -5360,7 +5538,8 @@ async function prepareCodexAttemptPrompt(context) {
5360
5538
  }
5361
5539
  return false;
5362
5540
  };
5363
- if (await precomputeNoContextEngineStaleBindingProjection()) await rebuildCodexPromptBuildFromCurrentProjection();
5541
+ const precomputedStaleBindingContinuityProjectionApplied = await precomputeNoContextEngineStaleBindingProjection();
5542
+ if (precomputedStaleBindingContinuityProjectionApplied) await rebuildCodexPromptBuildFromCurrentProjection();
5364
5543
  const rotateStartupBindingForProjectedTurn = async () => {
5365
5544
  const binding = mutable.startupBinding;
5366
5545
  if (!binding?.threadId) return;
@@ -5385,9 +5564,9 @@ async function prepareCodexAttemptPrompt(context) {
5385
5564
  mutable.startupBinding = startupBindingResolution.binding;
5386
5565
  mutable.startupContextTokens = startupBindingResolution.startupContextTokens;
5387
5566
  if (mutable.startupBinding?.threadId) return;
5388
- promptState.inactiveThreadBootstrapBindingForcedFreshStart = hadInactiveThreadBootstrapBinding;
5389
- promptState.staleBindingContinuityForcedFreshStart = promptState.precomputedStaleBindingContinuityProjectionApplied && !promptState.inactiveThreadBootstrapBindingForcedFreshStart;
5390
- if (promptState.staleBindingContinuityForcedFreshStart) await applyContinuityProjection(historyState.messages);
5567
+ inactiveThreadBootstrapBindingForcedFreshStart = hadInactiveThreadBootstrapBinding;
5568
+ staleBindingContinuityForcedFreshStart = precomputedStaleBindingContinuityProjectionApplied && !inactiveThreadBootstrapBindingForcedFreshStart;
5569
+ if (staleBindingContinuityForcedFreshStart) await applyContinuityProjection(historyState.messages);
5391
5570
  if (activeContextEngine) {
5392
5571
  promptState.contextEngineProjection = void 0;
5393
5572
  await applyActiveContextEngineProjection(void 0);
@@ -5434,7 +5613,7 @@ async function prepareCodexAttemptPrompt(context) {
5434
5613
  Object.assign(systemPromptReport, buildSystemPromptReport(!workspaceReferencesIncluded));
5435
5614
  },
5436
5615
  buildRenderedCodexDeveloperInstructions,
5437
- rebuildCodexTurnPromptTextFromCurrentProjection,
5616
+ rebuildCodexTurnPromptTextFromCurrentProjection: () => rebuildCodexPromptBuildFromCurrentProjection(true),
5438
5617
  applyNoContextEngineContinuityProjection,
5439
5618
  systemPromptReport
5440
5619
  };
@@ -5462,28 +5641,22 @@ function createNativeSubagentAssignmentStore(params) {
5462
5641
  const binding = bindingStore.read(identity);
5463
5642
  if (!binding || !matchesCodexNativeSubagentSubmissionBinding(binding, owner)) throw new Error("Native assignment binding is no longer current.");
5464
5643
  };
5644
+ const mutate = (kind) => (assignment, assertSourceCurrent) => bindingStore.mutate(identity, {
5645
+ kind,
5646
+ owner,
5647
+ assignment
5648
+ }, () => {
5649
+ assertCurrent();
5650
+ assertSourceCurrent();
5651
+ });
5465
5652
  return {
5466
5653
  assertCurrent,
5467
5654
  read: () => {
5468
5655
  assertCurrent();
5469
5656
  return bindingStore.readNativeSubagentAssignments?.(identity, owner) ?? [];
5470
5657
  },
5471
- record: (assignment, assertSourceCurrent) => bindingStore.mutate(identity, {
5472
- kind: "record-native-subagent-assignment",
5473
- owner,
5474
- assignment
5475
- }, () => {
5476
- assertCurrent();
5477
- assertSourceCurrent();
5478
- }),
5479
- consume: (assignment, assertSourceCurrent) => bindingStore.mutate(identity, {
5480
- kind: "consume-native-subagent-assignment",
5481
- owner,
5482
- assignment
5483
- }, () => {
5484
- assertCurrent();
5485
- assertSourceCurrent();
5486
- })
5658
+ record: mutate("record-native-subagent-assignment"),
5659
+ consume: mutate("consume-native-subagent-assignment")
5487
5660
  };
5488
5661
  }
5489
5662
  //#endregion
@@ -5596,14 +5769,8 @@ function prepareCodexAttemptResources(prompt) {
5596
5769
  releaseSharedClientLeaseOnce();
5597
5770
  await retireSharedCodexClientForOneShotCleanup();
5598
5771
  };
5599
- const runCleanupStep = (step, operation) => runAgentCleanupStep({
5600
- runId: params.runId,
5601
- sessionId: params.sessionId,
5602
- step,
5603
- log: embeddedAgentLog,
5604
- cleanup: async () => {
5605
- await operation();
5606
- }
5772
+ const runCleanupStep = (step, operation) => runCodexCleanupStep(params, step, async () => {
5773
+ await operation();
5607
5774
  });
5608
5775
  let nativeSubagentMonitorSettlement;
5609
5776
  let nativeSubagentMonitorGeneration = 0;
@@ -5621,13 +5788,14 @@ function prepareCodexAttemptResources(prompt) {
5621
5788
  const generation = ++nativeSubagentMonitorGeneration;
5622
5789
  const sessionKey = params.sessionKey;
5623
5790
  const storePath = params.sessionTarget?.storePath;
5624
- const parentSession = sessionKey && storePath ? getSessionEntry({
5791
+ const readParentSession = () => sessionKey && storePath ? getSessionEntry({
5625
5792
  agentId: sessionAgentId,
5626
5793
  sessionKey,
5627
5794
  storePath,
5628
5795
  readConsistency: "latest",
5629
5796
  hydrateSkillPromptRefs: false
5630
5797
  }) : void 0;
5798
+ const parentSession = readParentSession();
5631
5799
  const historyOwner = createCodexNativeSubagentHistoryOwner({
5632
5800
  parentThreadId,
5633
5801
  sessionId: params.sessionId,
@@ -5637,13 +5805,7 @@ function prepareCodexAttemptResources(prompt) {
5637
5805
  const { bindingStore, bindingIdentity } = connection;
5638
5806
  const assertParentSessionCurrent = () => {
5639
5807
  if (historyOwner?.lifecycleRevision && sessionKey && storePath) {
5640
- if (getSessionEntry({
5641
- agentId: sessionAgentId,
5642
- sessionKey,
5643
- storePath,
5644
- readConsistency: "latest",
5645
- hydrateSkillPromptRefs: false
5646
- })?.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.");
5647
5809
  }
5648
5810
  };
5649
5811
  const submissionStore = historyOwner && thread.lifecycle.preserveExistingBinding !== true ? {
@@ -5832,11 +5994,11 @@ function prepareCodexAttemptResources(prompt) {
5832
5994
  };
5833
5995
  const startupTimeoutMs = resolveCodexStartupTimeoutMs({
5834
5996
  timeoutMs: params.timeoutMs,
5997
+ requestTimeoutMs: appServer.requestTimeoutMs,
5835
5998
  timeoutFloorMs: options.startupTimeoutFloorMs
5836
5999
  });
5837
- const requesterChannel = params.messageChannel ?? params.messageProvider;
5838
6000
  const requester = buildCodexHookRequester(params);
5839
- const buildNativeHookRelayFinalConfigPatch = async (decision) => {
6001
+ const buildNativeHookRelayFinalConfigPatch = async (decision, relayClient) => {
5840
6002
  state.nativeSpawnAdmissionInstalled = false;
5841
6003
  const previousRelay = state.nativeHookRelay;
5842
6004
  previousRelay?.unregister();
@@ -5873,7 +6035,7 @@ function prepareCodexAttemptResources(prompt) {
5873
6035
  approvalContext: {
5874
6036
  trigger: params.trigger,
5875
6037
  approvalReviewerDeviceId: params.approvalReviewerDeviceId,
5876
- turnSourceChannel: requesterChannel,
6038
+ turnSourceChannel: params.messageChannel ?? params.messageProvider,
5877
6039
  turnSourceTo: params.currentMessagingTarget ?? params.currentChannelId,
5878
6040
  turnSourceAccountId: params.agentAccountId,
5879
6041
  turnSourceThreadId: params.currentThreadTs
@@ -5894,6 +6056,12 @@ function prepareCodexAttemptResources(prompt) {
5894
6056
  tools: decision.nativeModelInputTools,
5895
6057
  readQualification: (threadId) => getCodexInferenceThreadQualification(state.client, threadId)
5896
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
+ },
5897
6065
  assertCurrent: connection.assertLegacyCurrent,
5898
6066
  onPreToolUseFailure: (failure) => {
5899
6067
  const projector = projectorRef.current;
@@ -5929,9 +6097,6 @@ function prepareCodexAttemptResources(prompt) {
5929
6097
  nativeModelAdmission,
5930
6098
  nativeProcessAuthority,
5931
6099
  releaseNativeProcessAuthority,
5932
- markTrajectoryEndRecorded: () => {
5933
- state.trajectoryEndRecorded = true;
5934
- },
5935
6100
  releaseSharedClientLeaseAndRetireOneShotClient,
5936
6101
  releaseSandboxExecEnvironment,
5937
6102
  runCleanupStep,
@@ -5953,32 +6118,6 @@ async function prepareCodexAttemptRoute(resources, turnRuntime, notifications, h
5953
6118
  const { runAbortController } = connection;
5954
6119
  const { state, turnIdRef, completeTurn } = turnRuntime;
5955
6120
  const { noteNotificationReceived, enqueueNotification } = notifications;
5956
- const attachRouteAbort = (route) => {
5957
- const onAbort = () => {
5958
- if (state.completed || state.terminalTurnNotificationQueued || runAbortController.signal.aborted) return;
5959
- const reasonText = formatErrorMessage(route.signal.reason);
5960
- const closedClient = reasonText.includes("turn router closed");
5961
- const closeCause = route.signal.reason instanceof Error && route.signal.reason.cause instanceof Error ? route.signal.reason.cause : void 0;
5962
- state.clientClosedPromptError = closedClient ? "codex app-server client closed before turn completed" : `codex app-server turn route closed before turn completed: ${reasonText}`;
5963
- state.clientClosedDiagnostic = closedClient && closeCause ? formatErrorMessage(closeCause) : void 0;
5964
- state.clientClosedAbort = closedClient;
5965
- const activeTurnId = turnIdRef.current;
5966
- if (activeTurnId) trajectoryRecorder?.recordEvent("turn.client_closed", {
5967
- threadId: resourceState.thread.threadId,
5968
- turnId: activeTurnId
5969
- });
5970
- embeddedAgentLog.warn(state.clientClosedPromptError, {
5971
- threadId: resourceState.thread.threadId,
5972
- turnId: activeTurnId,
5973
- ...state.clientClosedDiagnostic ? { transportError: state.clientClosedDiagnostic } : {}
5974
- });
5975
- runAbortController.abort(closedClient ? "client_closed" : "turn_route_closed");
5976
- completeTurn();
5977
- };
5978
- route.signal.addEventListener("abort", onAbort, { once: true });
5979
- if (route.signal.aborted) onAbort();
5980
- return () => route.signal.removeEventListener("abort", onAbort);
5981
- };
5982
6121
  const ensureCurrentThreadRoute = async () => {
5983
6122
  if (resourceState.turnRoute?.threadId !== resourceState.thread.threadId) {
5984
6123
  await releaseCurrentRoute();
@@ -5986,7 +6125,31 @@ async function prepareCodexAttemptRoute(resources, turnRuntime, notifications, h
5986
6125
  }
5987
6126
  if (!resourceState.routeActivated) {
5988
6127
  if (!resourceState.nativeSubagentMonitor) await registerNativeSubagentMonitor(resourceState.thread.threadId);
5989
- 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);
5990
6153
  await resourceState.turnRoute.activate({
5991
6154
  onNotificationReceived: noteNotificationReceived,
5992
6155
  onNotification: enqueueNotification,
@@ -6000,29 +6163,6 @@ async function prepareCodexAttemptRoute(resources, turnRuntime, notifications, h
6000
6163
  return { ensureCurrentThreadRoute };
6001
6164
  }
6002
6165
  //#endregion
6003
- //#region extensions/codex/src/app-server/run-attempt-client-prewarm.ts
6004
- /** Starts the shared process while tools and prompt context are still being prepared. */
6005
- function prewarmCodexAttemptClient(params) {
6006
- const { connection, authProfileStore, authBindingFingerprint } = params;
6007
- const { appServer, attemptClientFactory, options, pluginConfig, runtimeArtifactRequest, startupAuthRequirement, startupClientAuthProfileId, startupPreparedAuth, agentDir, params: runParams, runAbortController } = connection;
6008
- if (options.clientFactory || attemptClientFactory !== getLeasedSharedCodexAppServerClient || runtimeArtifactRequest) return;
6009
- getSharedCodexAppServerClient({
6010
- assertCurrent: connection.assertLegacyCurrent,
6011
- startOptions: appServer.start,
6012
- pluginConfig,
6013
- ...startupPreparedAuth ? { preparedAuth: startupPreparedAuth } : { authProfileId: startupClientAuthProfileId },
6014
- authRequirement: startupAuthRequirement,
6015
- authProfileStore,
6016
- authBindingFingerprint,
6017
- agentDir,
6018
- config: runParams.config,
6019
- timeoutMs: appServer.requestTimeoutMs,
6020
- abandonSignal: runAbortController.signal
6021
- }).catch((error) => {
6022
- embeddedAgentLog.debug("codex app-server client prewarm failed", { error });
6023
- });
6024
- }
6025
- //#endregion
6026
6166
  //#region extensions/codex/src/app-server/scheduled-configured-mcp-authority.ts
6027
6167
  /** Limits fresh scheduled-authority capture to authenticated local durable operator turns. */
6028
6168
  function canResolveScheduledConfiguredMcpCreatorAuthority(params) {
@@ -6040,10 +6180,27 @@ async function prepareCodexAttemptRuntime(connection) {
6040
6180
  }) : void 0;
6041
6181
  assertScheduledCodexAppAuthorityRuntime(connection, params);
6042
6182
  const attemptAuthProfileStore = preparedAuthBinding?.authProfileStore ?? params.authProfileStore;
6043
- prewarmCodexAttemptClient({
6044
- connection,
6183
+ const clientOptions = {
6184
+ startOptions: appServer.start,
6185
+ pluginConfig,
6186
+ ...startupPreparedAuth ? { preparedAuth: startupPreparedAuth } : { authProfileId: startupClientAuthProfileId },
6187
+ authRequirement: connection.startupAuthRequirement,
6045
6188
  authProfileStore: attemptAuthProfileStore,
6046
- 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 });
6047
6204
  });
6048
6205
  const effectiveContextWindowInfo = usesSupervisionConnection ? void 0 : params.contextWindowInfo;
6049
6206
  const effectiveContextTokenBudget = usesSupervisionConnection ? void 0 : params.contextTokenBudget;
@@ -6088,7 +6245,7 @@ async function prepareCodexAttemptRuntime(connection) {
6088
6245
  agentDir,
6089
6246
  config: params.config
6090
6247
  });
6091
- 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 });
6092
6249
  preDynamicStartupStages.mark("auth-cache");
6093
6250
  const codexMcpToolOverrides = resolveCodexMcpToolOverridesForAgent(params.config, {
6094
6251
  agentId: sessionAgentId,
@@ -6136,22 +6293,9 @@ async function prepareCodexAttemptRuntime(connection) {
6136
6293
  });
6137
6294
  if (nativeToolSurfaceEnabled && sandbox?.enabled && sandbox.backend && params.hostCapabilities.retainSourceAuthority) {
6138
6295
  const client = await attemptClientFactory({
6296
+ ...clientOptions,
6139
6297
  assertCurrent: connection.assertCurrent,
6140
- startOptions: appServer.start,
6141
- pluginConfig,
6142
- ...startupPreparedAuth ? { preparedAuth: startupPreparedAuth } : { authProfileId: startupClientAuthProfileId },
6143
- authRequirement: connection.startupAuthRequirement,
6144
- authProfileStore: attemptAuthProfileStore,
6145
- authBindingFingerprint: preparedAuthBinding?.fingerprint,
6146
- ...connection.runtimeArtifactRequest ? {
6147
- runtimeArtifactMode: "capture",
6148
- ...connection.runtimeArtifactRequest.expected ? { expectedRuntimeArtifact: connection.runtimeArtifactRequest.expected } : {}
6149
- } : {},
6150
- agentId: sessionAgentId,
6151
- agentDir,
6152
- config: params.config,
6153
- abandonSignal: runAbortController.signal,
6154
- timeoutMs: appServer.requestTimeoutMs
6298
+ agentId: sessionAgentId
6155
6299
  });
6156
6300
  try {
6157
6301
  connection.assertCurrent();
@@ -6210,6 +6354,7 @@ async function prepareCodexAttemptRuntime(connection) {
6210
6354
  preDynamicStartupStages.mark("context-engine-support");
6211
6355
  return {
6212
6356
  connection,
6357
+ clientOptions,
6213
6358
  preparedAuthBinding,
6214
6359
  runtimeParams,
6215
6360
  effectiveContextWindowInfo,
@@ -6269,27 +6414,18 @@ function toTranscriptToolResultContentItem(item) {
6269
6414
  type: "text",
6270
6415
  text: typeof record.text === "string" ? record.text : ""
6271
6416
  };
6272
- if (record.type === "inputImage") return typeof record.imageUrl === "string" ? {
6417
+ if (record.type === "inputImage" && typeof record.imageUrl === "string") return {
6273
6418
  type: "image",
6274
6419
  url: record.imageUrl
6275
- } : {
6276
- type: "text",
6277
- text: formatUnsupportedCodexDynamicToolOutput(record.type)
6278
6420
  };
6421
+ const rawType = typeof record.type === "string" ? record.type.replace(/\s+/g, " ").trim() : "";
6279
6422
  return {
6280
6423
  type: "text",
6281
- text: formatUnsupportedCodexDynamicToolOutput(record.type)
6424
+ text: `[Unsupported Codex dynamic tool output: ${rawType ? truncateUtf16Safe(rawType, 80) : "unknown"}${rawType.length > 80 ? "..." : ""}]`
6282
6425
  };
6283
6426
  }
6284
- function formatUnsupportedCodexDynamicToolOutput(type) {
6285
- const rawType = typeof type === "string" ? type.replace(/\s+/g, " ").trim() : "";
6286
- return `[Unsupported Codex dynamic tool output: ${rawType ? truncateUtf16Safe(rawType, 80) : "unknown"}${rawType.length > 80 ? "..." : ""}]`;
6287
- }
6288
6427
  function resolveCodexDynamicToolDirectNames(params, registeredTools, hostSystemAgentActive = false) {
6289
- const names = [];
6290
- if (hostSystemAgentActive && isSystemAgentOnlyCodexDynamicToolAllowlist(params.toolsAllow)) names.push("openclaw");
6291
- if (registeredTools.some((tool) => tool.name === "message")) names.push("message");
6292
- return names;
6428
+ return [...hostSystemAgentActive && isSystemAgentOnlyCodexDynamicToolAllowlist(params.toolsAllow) ? ["openclaw"] : [], ...registeredTools.some((tool) => tool.name === "message") ? ["message"] : []];
6293
6429
  }
6294
6430
  //#endregion
6295
6431
  //#region extensions/codex/src/app-server/run-attempt-server-requests.ts
@@ -6307,7 +6443,7 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
6307
6443
  const autoApprove = shouldAutoApproveCodexAppServerApprovals(appServer);
6308
6444
  const { compactionPlanState, toolBridge, toolOutcomeOrdinals, suppressedDynamicToolOutcomeOrdinals, allocateCodexToolOutcomeOrdinal } = attemptTools;
6309
6445
  const { state, turnIdRef, userInputBridgeRef, openClawDynamicToolExecutions, pendingOpenClawDynamicToolCompletionIds, noteProgress } = turnRuntime;
6310
- const { emitExecutionPhaseOnce, scheduleTurnReleaseAfterTerminalDynamicTool, scheduleTerminalDynamicToolReleaseCheck } = lifecycle;
6446
+ const { emitExecutionPhaseOnce, recordDynamicToolResult, scheduleTerminalDynamicToolReleaseCheck } = lifecycle;
6311
6447
  let refreshDrain;
6312
6448
  let refreshStopping = false;
6313
6449
  const settlePluginRuntimeRefresh = async (turnId) => {
@@ -6441,24 +6577,21 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
6441
6577
  });
6442
6578
  setExecutionTimeoutMs?.(dynamicToolTimeoutMs);
6443
6579
  const toolStartedAt = Date.now();
6444
- const diagnosticContext = {
6580
+ const diagnostics = createCodexDynamicToolDiagnostics({
6445
6581
  call,
6446
6582
  agentId: sessionAgentId,
6447
6583
  runId: params.runId,
6448
6584
  sessionId: params.sessionId,
6449
6585
  sessionKey: params.sessionKey
6450
- };
6586
+ });
6451
6587
  let terminalDiagnosticObserved = false;
6452
6588
  const unsubscribeToolDiagnosticObserver = onInternalDiagnosticEvent((event) => {
6453
- if (isDynamicToolTerminalDiagnosticEvent(event) && isMatchingDynamicToolTerminalDiagnostic({
6454
- ...diagnosticContext,
6455
- event
6456
- })) terminalDiagnosticObserved = true;
6589
+ if (diagnostics.matchesTerminal(event)) terminalDiagnosticObserved = true;
6457
6590
  }, { include: DYNAMIC_TOOL_TERMINAL_DIAGNOSTIC_TYPES });
6458
6591
  try {
6459
6592
  const { execution } = openClawDynamicToolExecutions.claim(call, async () => {
6460
6593
  await projector?.transcriptCheckpoint.flush();
6461
- emitDynamicToolStartedDiagnostic(diagnosticContext);
6594
+ diagnostics.started();
6462
6595
  const response = await handleDynamicToolCallWithTimeout({
6463
6596
  call,
6464
6597
  toolBridge,
@@ -6540,30 +6673,18 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
6540
6673
  data: activity
6541
6674
  });
6542
6675
  }
6543
- if (!terminalDiagnosticObserved && !hasPendingDynamicToolTerminalDiagnostic(diagnosticContext)) emitDynamicToolTerminalDiagnostic({
6544
- ...diagnosticContext,
6545
- response,
6546
- durationMs: toolDurationMs
6547
- });
6676
+ if (!terminalDiagnosticObserved && !diagnostics.hasPendingTerminal()) diagnostics.terminal(response, toolDurationMs);
6548
6677
  pendingOpenClawDynamicToolCompletionIds.delete(call.callId);
6549
6678
  if (params.pluginRuntimeRefreshPending?.()) await settlePluginRuntimeRefresh(turnId);
6550
- else if (response.terminate === true && response.success) scheduleTurnReleaseAfterTerminalDynamicTool({
6679
+ else recordDynamicToolResult({
6551
6680
  call,
6552
6681
  response,
6553
6682
  durationMs: toolDurationMs
6554
6683
  });
6555
- else if (response.asyncStarted === true) scheduleTerminalDynamicToolReleaseCheck();
6556
- else {
6557
- state.currentTurnHadNonTerminalDynamicToolResult = true;
6558
- state.pendingTerminalDynamicToolRelease = void 0;
6559
- }
6560
6684
  return protocolResponse;
6561
6685
  } catch (error) {
6562
6686
  pendingOpenClawDynamicToolCompletionIds.delete(call.callId);
6563
- if (!terminalDiagnosticObserved && !hasPendingDynamicToolTerminalDiagnostic(diagnosticContext)) emitDynamicToolErrorDiagnostic({
6564
- ...diagnosticContext,
6565
- durationMs: Math.max(0, Date.now() - toolStartedAt)
6566
- });
6687
+ if (!terminalDiagnosticObserved && !diagnostics.hasPendingTerminal()) diagnostics.error(Math.max(0, Date.now() - toolStartedAt));
6567
6688
  await settlePluginRuntimeRefresh(turnId);
6568
6689
  throw error;
6569
6690
  } finally {
@@ -6584,7 +6705,7 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
6584
6705
  //#region extensions/codex/src/app-server/attempt-runtime-artifact.ts
6585
6706
  async function verifyStartupArtifact(params) {
6586
6707
  if (!params.request) return;
6587
- const { readCodexAppServerClientRuntimeArtifact, validateCodexAppServerRuntimeArtifact } = await import("./runtime-artifact-CUTOOnKw.mjs");
6708
+ const { readCodexAppServerClientRuntimeArtifact, validateCodexAppServerRuntimeArtifact } = await import("./runtime-artifact-C13pR7tD.mjs");
6588
6709
  const runtimeArtifact = readCodexAppServerClientRuntimeArtifact(params.client);
6589
6710
  const expected = params.request.expected;
6590
6711
  const matchesExpected = !expected || runtimeArtifact?.id === expected.id && runtimeArtifact.fingerprint === expected.fingerprint;
@@ -6601,7 +6722,7 @@ function startCodexComputerUseHealthMonitor(params) {
6601
6722
  const state = getComputerUseHealthMonitorState();
6602
6723
  const existing = state.monitors.get(params.client);
6603
6724
  if (!params.config.enabled || !params.config.healthCheckEnabled) {
6604
- if (existing) clearComputerUseHealthMonitor(params.client, existing);
6725
+ clearComputerUseHealthMonitor(params.client, existing);
6605
6726
  return {
6606
6727
  started: false,
6607
6728
  reason: params.config.enabled ? "health_disabled" : "disabled"
@@ -6621,7 +6742,7 @@ function startCodexComputerUseHealthMonitor(params) {
6621
6742
  intervalMs,
6622
6743
  reason: "already_started"
6623
6744
  };
6624
- if (existing) clearComputerUseHealthMonitor(params.client, existing);
6745
+ clearComputerUseHealthMonitor(params.client, existing);
6625
6746
  const monitor = {
6626
6747
  fingerprint,
6627
6748
  timer: setInterval(() => {
@@ -6632,8 +6753,7 @@ function startCodexComputerUseHealthMonitor(params) {
6632
6753
  };
6633
6754
  monitor.timer.unref?.();
6634
6755
  monitor.disposeCloseHandler = params.client.addCloseHandler((client) => {
6635
- const active = state.monitors.get(client);
6636
- if (active) clearComputerUseHealthMonitor(client, active);
6756
+ clearComputerUseHealthMonitor(client, state.monitors.get(client));
6637
6757
  });
6638
6758
  state.monitors.set(params.client, monitor);
6639
6759
  return {
@@ -6666,7 +6786,7 @@ async function runCodexComputerUseHealthProbe(client, config, monitor, tools) {
6666
6786
  }
6667
6787
  if (repair?.attempted && repair.warnings.length === 0) embeddedAgentLog.info("codex computer-use periodic health reloaded MCP servers", { mcpServerName: config.mcpServerName });
6668
6788
  } catch (error) {
6669
- embeddedAgentLog.warn("codex computer-use periodic health probe crashed", {
6789
+ embeddedAgentLog.warn("codex computer-use periodic health check crashed", {
6670
6790
  mcpServerName: config.mcpServerName,
6671
6791
  error: error instanceof Error ? error.message : String(error)
6672
6792
  });
@@ -6675,6 +6795,7 @@ async function runCodexComputerUseHealthProbe(client, config, monitor, tools) {
6675
6795
  }
6676
6796
  }
6677
6797
  function clearComputerUseHealthMonitor(client, monitor) {
6798
+ if (!monitor) return;
6678
6799
  clearInterval(monitor.timer);
6679
6800
  monitor.disposeCloseHandler();
6680
6801
  getComputerUseHealthMonitorState().monitors.delete(client);
@@ -6688,8 +6809,8 @@ const CODEX_APP_SERVER_STARTUP_MAX_ATTEMPTS = 3;
6688
6809
  */
6689
6810
  async function startCodexAttemptThread(params) {
6690
6811
  let pluginAppServer = params.appServer;
6691
- const startupRuntimeAuthProfileId = params.startupPreparedAuth?.kind === "profile" ? params.startupPreparedAuth.profileId : params.startupAuthProfileId ?? void 0;
6692
- 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;
6693
6814
  let releaseSharedClientLease;
6694
6815
  let startupClientForAbandonedRequestCleanup;
6695
6816
  let releaseStartupResourcesOnTimeout;
@@ -6711,12 +6832,13 @@ async function startCodexAttemptThread(params) {
6711
6832
  },
6712
6833
  operation: async () => {
6713
6834
  const threadConfig = mergeCodexThreadConfigs(params.configuredMcpDynamicSurface ? void 0 : params.bundleMcpThreadConfig?.configPatch);
6714
- const { pluginThreadConfigRequired, pluginThreadConfigPluginConfig, resolvedPluginPolicy, enabledPluginConfigKeys } = resolveCodexPluginThreadConfigStartupPolicy({
6835
+ const pluginStartupPolicy = resolveCodexPluginThreadConfigStartupPolicy({
6715
6836
  pluginConfig: params.pluginConfig,
6716
6837
  nativeToolSurfaceEnabled: params.nativeToolSurfaceEnabled,
6717
- hostedAppsSupported: !isCodexResponsesOAuth(params.startupPreparedAuth),
6838
+ hostedAppsSupported: !isCodexResponsesOAuth(params.clientOptions.preparedAuth),
6718
6839
  scheduledRuntimeAuthority: params.buildAttemptParams().scheduledRuntimeAuthority
6719
6840
  });
6841
+ const { pluginThreadConfigRequired, resolvedPluginPolicy, enabledPluginConfigKeys } = pluginStartupPolicy;
6720
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) ? {
6721
6843
  ...params.appServer,
6722
6844
  approvalPolicy: withMcpElicitationsApprovalPolicy(params.appServer.approvalPolicy)
@@ -6732,20 +6854,14 @@ async function startCodexAttemptThread(params) {
6732
6854
  params.assertCurrent?.();
6733
6855
  if (startupAbandonController.signal.aborted) throw new CodexAppServerStartupError("aborted");
6734
6856
  startupClient = await params.attemptClientFactory({
6857
+ ...params.clientOptions,
6735
6858
  assertCurrent: () => {
6736
6859
  params.assertCurrent?.();
6737
6860
  params.authority?.assertLegacyCurrent();
6738
6861
  },
6739
6862
  startOptions: params.appServer.start,
6740
6863
  pluginConfig: params.pluginConfig,
6741
- ...params.startupPreparedAuth ? { preparedAuth: params.startupPreparedAuth } : { authProfileId: params.startupAuthProfileId },
6742
- authRequirement: params.startupAuthRequirement,
6743
6864
  authProfileStore: attemptParams.authProfileStore,
6744
- authBindingFingerprint: params.startupAuthBindingFingerprint,
6745
- ...params.runtimeArtifactRequest ? {
6746
- runtimeArtifactMode: "capture",
6747
- ...params.runtimeArtifactRequest.expected ? { expectedRuntimeArtifact: params.runtimeArtifactRequest.expected } : {}
6748
- } : {},
6749
6865
  agentId: params.sessionAgentId,
6750
6866
  agentDir: params.agentDir,
6751
6867
  config: params.config,
@@ -6778,7 +6894,7 @@ async function startCodexAttemptThread(params) {
6778
6894
  ensureCodexAppServerClientRuntime(activeStartupClient, {
6779
6895
  agentDir: params.agentDir,
6780
6896
  authProfileId: startupRuntimeAuthProfileId,
6781
- 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",
6782
6898
  authProfileStore: startupRuntimeAuthProfileStore ?? attemptParams.authProfileStore,
6783
6899
  config: params.config
6784
6900
  });
@@ -6823,11 +6939,11 @@ async function startCodexAttemptThread(params) {
6823
6939
  appServerVersion: activeStartupClient.getServerVersion(),
6824
6940
  runtimeIdentity: startupRuntimeIdentity
6825
6941
  });
6826
- const basePluginThreadConfigInputFingerprint = pluginThreadConfigRequired ? buildCodexPluginThreadConfigInputFingerprint({
6827
- pluginConfig: pluginThreadConfigPluginConfig,
6828
- appCacheKey: pluginAppCacheKey
6829
- }) : void 0;
6830
- const pluginThreadConfigInputFingerprint = basePluginThreadConfigInputFingerprint ? buildScheduledCodexAppAuthorityInputFingerprint(basePluginThreadConfigInputFingerprint, attemptParams.scheduledRuntimeAuthority) : void 0;
6942
+ const createPluginThreadConfig = prepareCodexPluginThreadConfigStartupProvider({
6943
+ startupPolicy: pluginStartupPolicy,
6944
+ appCacheKey: pluginAppCacheKey,
6945
+ scheduledRuntimeAuthority: attemptParams.scheduledRuntimeAuthority
6946
+ });
6831
6947
  embeddedAgentLog.debug("codex plugin thread config eligibility", buildCodexPluginThreadConfigEligibilityLogData({
6832
6948
  sessionId: attemptParams.sessionId,
6833
6949
  sessionKey: attemptParams.sessionKey ?? "",
@@ -6919,10 +7035,9 @@ async function startCodexAttemptThread(params) {
6919
7035
  config: threadConfig,
6920
7036
  shellEnvironment: params.shellEnvironment,
6921
7037
  shellPathPrepend: params.shellPathPrepend,
7038
+ shellGitConfigParameters: params.shellGitConfigParameters,
6922
7039
  disableLoginShell: params.disableLoginShell,
6923
- finalConfigPatch: params.finalConfigPatch,
6924
7040
  buildFinalConfigPatch: params.buildFinalConfigPatch,
6925
- nativeHookRelayGeneration: params.nativeHookRelayGeneration,
6926
7041
  nativeHookRelayRequired: params.nativeHookRelayRequired,
6927
7042
  nativeModelAdmission: params.nativeModelAdmission,
6928
7043
  nativeCodeModeEnabled: params.nativeToolSurfaceEnabled,
@@ -6936,18 +7051,13 @@ async function startCodexAttemptThread(params) {
6936
7051
  appServerRuntimeFingerprint,
6937
7052
  contextEngineProjection: params.contextEngineProjection,
6938
7053
  signal,
6939
- pluginThreadConfig: pluginThreadConfigRequired ? createCodexPluginThreadConfigStartupProvider({
6940
- inputFingerprint: pluginThreadConfigInputFingerprint,
6941
- enabledPluginConfigKeys,
6942
- policy: resolvedPluginPolicy,
7054
+ pluginThreadConfig: createPluginThreadConfig?.({
6943
7055
  requestTimeoutMs: params.appServer.requestTimeoutMs,
6944
7056
  signal,
6945
- pluginConfig: pluginThreadConfigPluginConfig,
6946
7057
  client: activeStartupClient,
6947
7058
  configCwd: startupExecutionCwd,
6948
- appCacheKey: pluginAppCacheKey,
6949
7059
  scheduledRuntimeAuthority: attemptParams.scheduledRuntimeAuthority
6950
- }) : void 0
7060
+ })
6951
7061
  });
6952
7062
  try {
6953
7063
  const startupThread = await startOrResumeThread(buildThreadLifecycleParams(startupAbandonController.signal, reserveStartupThread));
@@ -7077,10 +7187,10 @@ async function startCodexAttemptRuntime(resources) {
7077
7187
  const { prompt, state, trajectoryRecorder, startupTimeoutMs, buildNativeHookRelayFinalConfigPatch } = resources;
7078
7188
  const { context, turnState, rebuildCodexTurnPromptTextFromCurrentProjection, applyNoContextEngineContinuityProjection } = prompt;
7079
7189
  const { runtime, attemptTools, promptState } = context;
7080
- 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;
7081
7191
  const { toolBridge, toolState } = attemptTools;
7082
7192
  const developerInstructions = joinPresentSections(turnState.promptBuild.developerInstructions, attemptTools.configuredMcp?.diagnosticNotice);
7083
- 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;
7084
7194
  let pluginAppServer = withCodexAppServerFastModeServiceTier(appServer, runtimeParams);
7085
7195
  const loopDetectionEnabled = (sessionAgentId && params.config ? resolveAgentConfig(params.config, sessionAgentId)?.tools?.loopDetection?.enabled : void 0) ?? params.config?.tools?.loopDetection?.enabled ?? false;
7086
7196
  try {
@@ -7097,17 +7207,15 @@ async function startCodexAttemptRuntime(resources) {
7097
7207
  appServer: pluginAppServer,
7098
7208
  pluginConfig,
7099
7209
  computerUseConfig,
7100
- startupAuthProfileId: startupClientAuthProfileId,
7101
- startupAuthRequirement,
7102
- startupAuthBindingFingerprint: preparedAuthBinding?.fingerprint,
7210
+ clientOptions,
7103
7211
  ...runtimeArtifactRequest ? { runtimeArtifactRequest } : {},
7104
- startupPreparedAuth,
7105
7212
  startupAuthAccountCacheKey,
7106
7213
  startupEnvApiKeyCacheKey,
7107
7214
  agentDir,
7108
7215
  config: params.config,
7109
7216
  shellEnvironment: connection.shellEnvironment,
7110
7217
  shellPathPrepend: connection.shellPathPrepend,
7218
+ shellGitConfigParameters: connection.shellGitConfigParameters,
7111
7219
  disableLoginShell: connection.disableLoginShell,
7112
7220
  buildAttemptParams: () => ({ ...runtimeParams }),
7113
7221
  ...effectiveRuntimeModelId !== runtimeParams.modelId ? { runtimeModelId: effectiveRuntimeModelId } : {},
@@ -7155,10 +7263,7 @@ async function startCodexAttemptRuntime(resources) {
7155
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");
7156
7264
  if (state.thread.lifecycle.action === "started" || state.thread.lifecycle.action === "forked") {
7157
7265
  const activePolicy = resolveReviewerPolicyContext(state.thread);
7158
- const activeConfig = await resolveRuntimeOptionsForCurrentBinding({
7159
- modelProvider: activePolicy.modelProvider,
7160
- model: activePolicy.model
7161
- });
7266
+ const activeConfig = await resolveRuntimeOptionsForCurrentBinding(activePolicy);
7162
7267
  connection.assertCurrent();
7163
7268
  const activeAppServer = resolveCodexAppServerForModelProvider({
7164
7269
  appServer: activeConfig,
@@ -7215,10 +7320,11 @@ function resolveInactiveCodexHeartbeatResponseDescriptor(params) {
7215
7320
  description: descriptor.description
7216
7321
  } : void 0;
7217
7322
  }
7218
- /** Keeps the thread-stable heartbeat endpoint executable on ordinary Codex turns. */
7219
- function createInactiveCodexHeartbeatResponseTool(descriptor) {
7323
+ function selectInactiveCodexHeartbeatResponseTool(params) {
7324
+ if (params.disableTools) return;
7325
+ const descriptor = params.descriptor;
7220
7326
  if (descriptor.name !== HEARTBEAT_RESPONSE_TOOL_NAME) throw new Error(`Expected ${HEARTBEAT_RESPONSE_TOOL_NAME}, received ${descriptor.name}`);
7221
- return {
7327
+ const tool = {
7222
7328
  name: descriptor.name,
7223
7329
  label: descriptor.name,
7224
7330
  description: descriptor.description,
@@ -7239,10 +7345,7 @@ function createInactiveCodexHeartbeatResponseTool(descriptor) {
7239
7345
  };
7240
7346
  }
7241
7347
  };
7242
- }
7243
- function selectInactiveCodexHeartbeatResponseTool(params) {
7244
- if (params.disableTools) return;
7245
- const allowed = applyEmbeddedAttemptToolsAllow([createInactiveCodexHeartbeatResponseTool(params.descriptor)], params.toolsAllow);
7348
+ const allowed = applyEmbeddedAttemptToolsAllow([tool], params.toolsAllow);
7246
7349
  return filterCodexDynamicTools(allowed, params.pluginConfig)[0];
7247
7350
  }
7248
7351
  //#endregion
@@ -7394,23 +7497,11 @@ async function prepareCodexAttemptTools(runtime) {
7394
7497
  let scopedMcpTools;
7395
7498
  let toolDisposal;
7396
7499
  const disposeTools = (reason) => toolDisposal ??= (async () => {
7397
- await runAgentCleanupStep({
7398
- runId: params.runId,
7399
- sessionId: params.sessionId,
7400
- step: "codex-dynamic-tool-cleanup",
7401
- log: embeddedAgentLog,
7402
- cleanup: async () => {
7403
- const errors = (await Promise.allSettled(runCleanups.splice(0).map(async (cleanup) => await cleanup(reason)))).flatMap((result) => result.status === "rejected" ? [result.reason] : []);
7404
- if (params.oneShotCliRun && errors.length) throw new AggregateError(errors, "Codex tool cleanup failed");
7405
- }
7406
- });
7407
- for (const [step, materialized] of [["codex-scoped-mcp-dispose", scopedMcpTools], ["codex-configured-mcp-dispose", configuredMcp]]) await runAgentCleanupStep({
7408
- runId: params.runId,
7409
- sessionId: params.sessionId,
7410
- step,
7411
- log: embeddedAgentLog,
7412
- 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");
7413
7503
  });
7504
+ for (const [step, materialized] of [["codex-scoped-mcp-dispose", scopedMcpTools], ["codex-configured-mcp-dispose", configuredMcp]]) await runCodexCleanupStep(params, step, async () => materialized?.dispose());
7414
7505
  })();
7415
7506
  try {
7416
7507
  const tools = await buildDynamicTools({
@@ -7441,7 +7532,7 @@ async function prepareCodexAttemptTools(runtime) {
7441
7532
  sessionId: params.sessionId,
7442
7533
  runId: params.runId,
7443
7534
  agentId: policyAgentId,
7444
- agentDir: agentDir ?? resolveAgentDir$1(params.config ?? {}, sessionAgentId),
7535
+ agentDir: agentDir ?? resolveAgentDir$2(params.config ?? {}, sessionAgentId),
7445
7536
  agentAccountId: params.agentAccountId,
7446
7537
  messageProvider: params.messageProvider ?? params.messageChannel,
7447
7538
  messageChannel: params.messageChannel,
@@ -7695,14 +7786,12 @@ async function resolveCodexExplicitSkillInputs(params) {
7695
7786
  async function prepareCodexProviderReviewContinuation(params) {
7696
7787
  const acknowledgment = params.acknowledgment;
7697
7788
  if (!acknowledgment) return;
7698
- let nativeChanged = false;
7699
- let dispatched = false;
7700
- let dispose = () => {};
7789
+ let state = "prepared";
7701
7790
  const assertCurrent = () => {
7702
7791
  params.signal.throwIfAborted();
7703
7792
  params.assertCurrent();
7704
7793
  acknowledgment.read();
7705
- 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");
7706
7795
  };
7707
7796
  assertCurrent();
7708
7797
  const snapshot = acknowledgment.read();
@@ -7718,16 +7807,16 @@ async function prepareCodexProviderReviewContinuation(params) {
7718
7807
  assertCurrent();
7719
7808
  const { review } = snapshot;
7720
7809
  if (review.nativeThreadId !== params.turnStartParams.threadId || !review.review?.continuation) throw new Error("Provider review no longer matches the native thread");
7721
- dispose = params.client.addNotificationHandler((notification) => {
7810
+ const dispose = params.client.addNotificationHandler((notification) => {
7722
7811
  const event = notification.params;
7723
7812
  if (!isJsonObject(event) || event.threadId !== review.nativeThreadId) return;
7724
- if (notification.method === "turn/started") nativeChanged = true;
7813
+ if (notification.method === "turn/started") state = "changed";
7725
7814
  else if (notification.method === "turn/completed" || notification.method === "error" && event.willRetry !== true) {
7726
7815
  const turn = isJsonObject(event.turn) ? event.turn : void 0;
7727
7816
  const turnId = turn?.id ?? event.turnId;
7728
7817
  const error = isJsonObject(turn?.error) ? turn.error : isJsonObject(event.error) ? event.error : void 0;
7729
7818
  const failure = readCodexProviderRefusal(typeof error?.message === "string" ? error.message : void 0, error?.codexErrorInfo, { misalignment: error?.misalignment });
7730
- 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";
7731
7820
  }
7732
7821
  });
7733
7822
  try {
@@ -7761,13 +7850,13 @@ async function prepareCodexProviderReviewContinuation(params) {
7761
7850
  dispose,
7762
7851
  dispatch: () => {
7763
7852
  assertCurrent();
7764
- if (dispatched) throw new Error("Provider review continuation already dispatched");
7765
- dispatched = true;
7853
+ if (state === "dispatched") throw new Error("Provider review continuation already dispatched");
7854
+ state = "dispatched";
7766
7855
  dispose();
7767
7856
  },
7768
7857
  accept: async (turnId) => {
7769
7858
  assertCurrent();
7770
- if (!dispatched) throw new Error("Provider review continuation has not dispatched");
7859
+ if (state !== "dispatched") throw new Error("Provider review continuation has not dispatched");
7771
7860
  await acknowledgment.acceptNativeTurn({
7772
7861
  nativeThreadId: params.turnStartParams.threadId,
7773
7862
  nativeTurnId: turnId,
@@ -7861,14 +7950,6 @@ async function prepareCodexAttemptTurnRequest(resources, turnRuntime, ensureCurr
7861
7950
  embeddedAgentLog.debug("codex app-server model call diagnostic ended with error", { error: formatErrorMessage(error) });
7862
7951
  }
7863
7952
  });
7864
- const throwIfTurnStartAcceptedAfterAbort = () => {
7865
- if (!runAbortController.signal.aborted) return;
7866
- const reason = runAbortController.signal.reason;
7867
- if (reason instanceof Error) throw reason;
7868
- const error = new Error(typeof reason === "string" && reason.length > 0 ? reason : "codex app-server turn start aborted before acceptance");
7869
- error.name = "AbortError";
7870
- throw error;
7871
- };
7872
7953
  const prepareWorkspaceReferences = () => {
7873
7954
  const references = prepareCodexWorkspaceReferences(resourceState.client, resourceState.thread.threadId, workspaceBootstrapContext.promptContext);
7874
7955
  prompt.refreshWorkspaceReferences(references.include);
@@ -8021,7 +8102,13 @@ async function prepareCodexAttemptTurnRequest(resources, turnRuntime, ensureCurr
8021
8102
  assertTurnCurrent();
8022
8103
  resourceState.nativeSubagentMonitor?.bindTurn(acceptedTurnId, modelMapping);
8023
8104
  if (upstreamUserText.includes(workspaceBootstrapContext.promptContext ?? "")) references.accepted();
8024
- 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
+ }
8025
8112
  await continuation?.accept(acceptedTurnId);
8026
8113
  return {
8027
8114
  turn: startedTurn,
@@ -8081,7 +8168,7 @@ async function prepareCodexAttemptTurnRequest(resources, turnRuntime, ensureCurr
8081
8168
  //#endregion
8082
8169
  //#region extensions/codex/src/app-server/run-attempt-turn-start.ts
8083
8170
  async function startCodexAttemptTurn(resources, turnRuntime, notifications, requestRuntime) {
8084
- const { prompt, state: resourceState, trajectoryRecorder, markTrajectoryEndRecorded } = resources;
8171
+ const { prompt, state: resourceState, trajectoryRecorder } = resources;
8085
8172
  const { context, turnState, systemPromptReport } = prompt;
8086
8173
  const { runtime, historyState, hookContext, hookRunner } = context;
8087
8174
  const { connection, runtimeParams } = runtime;
@@ -8141,11 +8228,7 @@ async function startCodexAttemptTurn(resources, turnRuntime, notifications, requ
8141
8228
  threadId: resourceState.thread.threadId
8142
8229
  }
8143
8230
  });
8144
- try {
8145
- started = await startCodexTurn();
8146
- } catch (retryError) {
8147
- turnStartError = retryError;
8148
- }
8231
+ started = await startCodexTurn();
8149
8232
  }
8150
8233
  } catch (retrySetupError) {
8151
8234
  turnStartError = retrySetupError;
@@ -8180,7 +8263,7 @@ async function startCodexAttemptTurn(resources, turnRuntime, notifications, requ
8180
8263
  aborted: runAbortController.signal.aborted,
8181
8264
  promptError: message
8182
8265
  });
8183
- markTrajectoryEndRecorded();
8266
+ resourceState.trajectoryEndRecorded = true;
8184
8267
  runAgentHarnessLlmOutputHook({
8185
8268
  event: {
8186
8269
  ...buildLlmOutputEvent(),
@@ -8212,35 +8295,26 @@ async function startCodexAttemptTurn(resources, turnRuntime, notifications, requ
8212
8295
  ctx: hookContext,
8213
8296
  hookRunner
8214
8297
  });
8215
- if (usageLimitError) {
8216
- await markCodexAuthProfileBlockedFromRateLimits({
8217
- params,
8218
- authProfileId: startupAuthProfileId,
8219
- rateLimits: usageLimitError.rateLimitsForProfile
8220
- });
8221
- return { result: buildCodexTurnStartFailureResult({
8222
- params,
8223
- message: usageLimitError.message,
8224
- promptError: new CodexUsageLimitPromptError(usageLimitError.message),
8225
- messagesSnapshot,
8226
- systemPromptReport
8227
- }) };
8228
- }
8229
- if (isCodexContextRestartSelectionChangedError(turnStartError)) return { result: {
8230
- ...buildCodexTurnStartFailureResult({
8231
- params,
8232
- message,
8233
- messagesSnapshot,
8234
- systemPromptReport
8235
- }),
8236
- codexAppServerFailure: {
8237
- kind: "client_closed_before_turn_completed",
8238
- transport: appServer.start.transport,
8239
- threadId: resourceState.thread.threadId,
8240
- replaySafe: true
8241
- }
8242
- } };
8243
- 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 };
8244
8318
  }
8245
8319
  }
8246
8320
  if (!started) throw new Error("codex app-server turn/start failed without an error");
@@ -8274,6 +8348,7 @@ var CodexAttemptState = class {
8274
8348
  this.projectionClosed = false;
8275
8349
  this.terminalDynamicToolReleaseCheckScheduled = false;
8276
8350
  this.currentTurnHadNonTerminalDynamicToolResult = false;
8351
+ this.currentTurnHadToolAuthoredFinalReply = false;
8277
8352
  }
8278
8353
  };
8279
8354
  function createCodexAttemptTurnState(resources) {
@@ -8409,10 +8484,13 @@ function createCodexAttemptTurnState(resources) {
8409
8484
  //#endregion
8410
8485
  //#region extensions/codex/src/app-server/run-attempt.ts
8411
8486
  async function runCodexAppServerAttempt(params, options) {
8412
- 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");
8413
8488
  const preparation = createCodexAttemptPreparationTiming(params);
8414
8489
  const connection = await preparation.measure("connection", () => prepareCodexAttemptConnection({
8415
- params,
8490
+ params: params.continuation ? {
8491
+ ...params,
8492
+ prompt: `${params.continuation.prompt}\n\n${params.prompt}`
8493
+ } : params,
8416
8494
  options
8417
8495
  }));
8418
8496
  try {