@openclaw/codex 2026.10.5-beta.3 → 2026.10.10-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 (156) hide show
  1. package/README.md +10 -3
  2. package/dist/.setup/{account-usage-runtime-CBR8imwK.mjs → account-usage-runtime-DDCDkvtl.mjs} +15 -9
  3. package/dist/.setup/{app-server-policy-D_zv8J7V.mjs → app-server-policy-Cog6mm2i.mjs} +1 -1
  4. package/dist/.setup/{apply-CfWD3Bk6.mjs → apply-BVSXYkTV.mjs} +11 -11
  5. package/dist/.setup/{attempt-client-cleanup-D3YvP0N7.mjs → attempt-client-cleanup-6OcbMH46.mjs} +14 -8
  6. package/dist/.setup/attempt-terminal-sZutF0WY.mjs +1 -0
  7. package/dist/.setup/{attempt-workspace-context-CcwP3DA3.mjs → attempt-workspace-context-GYPLawX6.mjs} +2 -2
  8. package/dist/.setup/{auth-binding-BaxlhaNx.mjs → auth-binding-830RLAJW.mjs} +2 -2
  9. package/dist/.setup/{auth-cache-key-BzYrcgwJ.mjs → auth-cache-key-CVcYw8HD.mjs} +92 -80
  10. package/dist/.setup/{auth-profile-CgHQ8Vot.mjs → auth-profile-auwzSwwy.mjs} +14 -8
  11. package/dist/.setup/{auth-profile-health-oHizqgye.mjs → auth-profile-health-BVPZU9I8.mjs} +15 -8
  12. package/dist/.setup/{auth-profile-selection-hr8ocLtz.mjs → auth-profile-selection-Bp5PDk3W.mjs} +24 -7
  13. package/dist/.setup/{binding-connection-B7HAAZSI.mjs → binding-connection-GTgUj9pi.mjs} +2 -2
  14. package/dist/.setup/{binding-connection.runtime-DAXn7iFl.mjs → binding-connection.runtime-RcWR3vQu.mjs} +4 -3
  15. package/dist/.setup/{bounded-turn-isolation-BfDAo-qZ.mjs → bounded-turn-isolation-D8CDrAVX.mjs} +3 -3
  16. package/dist/.setup/{bounded-turn-BmChqNaK.mjs → bounded-turn-mN_ekXYW.mjs} +18 -22
  17. package/dist/.setup/{build-state-sjOWPg_o.mjs → build-state-VcujMRqP.mjs} +1 -1
  18. package/dist/.setup/{capabilities-DbOzOglY.mjs → capabilities-DAS-JX1z.mjs} +1 -1
  19. package/dist/.setup/{client-aPKNc4Ii.mjs → client-BS8X7HmG.mjs} +47 -317
  20. package/dist/.setup/{client-catalog-response-Du2GmrOV.mjs → client-catalog-response-jM38o5w1.mjs} +2 -2
  21. package/dist/.setup/client-initialize-CjgZcX61.mjs +165 -0
  22. package/dist/.setup/{command-dispatch-CF6mgl3u.mjs → command-dispatch-DzXbHqCn.mjs} +3 -3
  23. package/dist/.setup/{command-formatters-xW9KpoSZ.mjs → command-formatters-B_7-QZ1c.mjs} +2 -2
  24. package/dist/.setup/{command-handlers-DlycReQg.mjs → command-handlers-tfb5Uq-O.mjs} +539 -406
  25. package/dist/.setup/command-rpc-SXqLQukR.mjs +296 -0
  26. package/dist/.setup/compact-M-JxLcbZ.mjs +823 -0
  27. package/dist/.setup/{computer-use-C6yYfm6-.mjs → computer-use-FqQ-Flbl.mjs} +21 -68
  28. package/dist/.setup/{config-C1YVVLEA.mjs → config-BfrAlTMT.mjs} +3 -3
  29. package/dist/.setup/{config-options-DDzeNQ8m.mjs → config-options-DMFZkd3X.mjs} +1 -1
  30. package/dist/.setup/{config-runtime-DWzK-k0n.mjs → config-runtime-BZRizyuG.mjs} +2 -2
  31. package/dist/.setup/{context-engine-projection-ps-yn_ci.mjs → context-engine-projection-PIeLSnR-.mjs} +16 -30
  32. package/dist/.setup/{conversation-binding-CP_mK17t.mjs → conversation-binding-C7MZy-Cx.mjs} +228 -116
  33. package/dist/.setup/{conversation-binding-data-UgLuTSQT.mjs → conversation-binding-data-khgW0n-o.mjs} +4 -2
  34. package/dist/.setup/{conversation-control-GXM3unE4.mjs → conversation-control-B2EpVZEb.mjs} +53 -23
  35. package/dist/.setup/{cyber-failover-D4dgNfFf.mjs → cyber-failover-CqEZoQsj.mjs} +1 -1
  36. package/dist/.setup/{cyber-failover-notice-ljgGGL0s.mjs → cyber-failover-notice-poL3Advd.mjs} +1 -1
  37. package/dist/.setup/{doctor-start-options-JjTAl-q_.mjs → doctor-start-options-8uIBXIzR.mjs} +8 -5
  38. package/dist/.setup/{dynamic-tool-build-DKko0Jjw.mjs → dynamic-tool-build-BjFAIG-f.mjs} +208 -218
  39. package/dist/.setup/{dynamic-tools-8hqa1jVc.mjs → dynamic-tools-XqWsVjcC.mjs} +344 -118
  40. package/dist/.setup/{effective-mcp-catalog-uIZ4w7Nh.mjs → effective-mcp-catalog-C3ta5hHc.mjs} +11 -9
  41. package/dist/.setup/{ephemeral-turn-DAlEbytF.mjs → ephemeral-turn-1ZF17fUR.mjs} +5 -4
  42. package/dist/.setup/{event-projector-assistant-message-CLMKN4x-.mjs → event-projector-assistant-message-ChOAY7rW.mjs} +16 -11
  43. package/dist/.setup/{event-projector-usage-BpKfdoTm.mjs → event-projector-usage-CBY0Hkga.mjs} +2 -2
  44. package/dist/.setup/{event-projector-values-CLvG1Hil.mjs → event-projector-values-yf4us9Pf.mjs} +1 -1
  45. package/dist/.setup/experimental-features-uGnVDtp-.mjs +19 -0
  46. package/dist/.setup/inference-context-mv_dBpAL.mjs +209 -0
  47. package/dist/.setup/{inference-dispatch-CO6tTs4q.mjs → inference-dispatch-C2zVSnrr.mjs} +2 -2
  48. package/dist/.setup/{inference-metadata-DCvcG_N_.mjs → inference-metadata-CYFWLHVk.mjs} +3 -1
  49. package/dist/.setup/{inference-proxy-BDWV0djM.mjs → inference-proxy-yd3hr2dr.mjs} +8 -8
  50. package/dist/.setup/installed-probe-lVC1X5ve.mjs +185 -0
  51. package/dist/.setup/{isolated-completion-BWEjVHBf.mjs → isolated-completion-P-r8NRE4.mjs} +7 -7
  52. package/dist/.setup/managed-binary-DbKvGXKl.mjs +395 -0
  53. package/dist/.setup/{mcp-app-session-preparation-CJR8ib5s.mjs → mcp-app-session-preparation-fnsnCovu.mjs} +18 -14
  54. package/dist/.setup/{model-catalog-Ben3FsFp.mjs → model-catalog-Y_esgRPY.mjs} +28 -17
  55. package/dist/.setup/{models-BB0l-gUb.mjs → models-BWLEUo2E.mjs} +3 -3
  56. package/dist/.setup/{native-auth-esN5MdIv.mjs → native-auth-DpZIaY8N.mjs} +7 -4
  57. package/dist/.setup/native-execution-policy-D09tLP-u.mjs +152 -0
  58. package/dist/.setup/{native-hook-relay-DQzvuJ-W.mjs → native-hook-relay-C7aaLJaP.mjs} +45 -10
  59. package/dist/.setup/{native-mcp-app-UkwXOBfS.mjs → native-mcp-app-CsWj-v_x.mjs} +5 -5
  60. package/dist/.setup/{native-skill-isolation-DoRxgQPX.mjs → native-skill-isolation-CMimsKYy.mjs} +7 -7
  61. package/dist/.setup/{native-subagent-monitor-DC4clzAD.mjs → native-subagent-monitor-CFE7b4oC.mjs} +485 -239
  62. package/dist/.setup/{native-subagent-pending-assignments-DmVhedNs.mjs → native-subagent-pending-assignments-CTinVtjo.mjs} +1 -1
  63. package/dist/.setup/{native-task-assignments-DimsQ9Qa.mjs → native-task-assignments-YJopbaVO.mjs} +9 -5
  64. package/dist/.setup/{node-cli-sessions-CzKg2nGq.mjs → node-cli-sessions-BuJnBnEq.mjs} +7 -4
  65. package/dist/.setup/{node-exec-server.runtime-BWkULhBM.mjs → node-exec-server.runtime-CP7RC1Nd.mjs} +3 -3
  66. package/dist/.setup/{plan-DFVngccH.mjs → plan-B4cHgqNv.mjs} +7 -20
  67. package/dist/.setup/{plugin-activation-D7WkJMvU.mjs → plugin-activation-CXPWe-hl.mjs} +4 -4
  68. package/dist/.setup/{plugin-app-cache-key-Bg9DbDI6.mjs → plugin-app-cache-key-DRb-niJc.mjs} +17 -55
  69. package/dist/.setup/{plugin-approval-roundtrip-68FoMlaZ.mjs → plugin-approval-roundtrip-DIZHLbAM.mjs} +1 -1
  70. package/dist/.setup/{plugin-inventory-CYgdo14P.mjs → plugin-inventory-DE9wcaeH.mjs} +2 -2
  71. package/dist/.setup/{plugin-metadata-cache-Bi8TAPwX.mjs → plugin-metadata-cache-BqC-a6Fb.mjs} +2 -15
  72. package/dist/.setup/{project-doc-thread-config-BVcvnps8.mjs → project-doc-thread-config-B0UI3f1D.mjs} +6 -6
  73. package/dist/.setup/protocol-CaPAVwe9.mjs +12 -0
  74. package/dist/.setup/{provider-capabilities-DWH29sy3.mjs → provider-capabilities-DjcKunHS.mjs} +1 -1
  75. package/dist/.setup/{provider-BCXRBKEb.mjs → provider-wj_LFJH3.mjs} +4 -4
  76. package/dist/.setup/{rate-limits-CI8pTPqL.mjs → rate-limits-BpfURnuy.mjs} +1 -1
  77. package/dist/.setup/{request-DInueZ2q.mjs → request-ePeNJrOd.mjs} +132 -136
  78. package/dist/.setup/{responses-oauth-twnuTaAa.mjs → responses-oauth-CCV7aVYF.mjs} +6 -6
  79. package/dist/.setup/{rpc-error-C98SHchT.mjs → rpc-error-DemqqaxE.mjs} +7 -3
  80. package/dist/.setup/{run-attempt-BN-0TO0P.mjs → run-attempt-BcWArowv.mjs} +595 -426
  81. package/dist/.setup/{run-attempt-lifecycle-KN4oh-7O.mjs → run-attempt-lifecycle-DN-ATDp9.mjs} +1 -1
  82. package/dist/.setup/{runtime-artifact-C13pR7tD.mjs → runtime-artifact-CmLWeyJB.mjs} +3 -3
  83. package/dist/.setup/{runtime-artifact-connection-jS5DeCok.mjs → runtime-artifact-connection-DpWlZ02e.mjs} +3 -3
  84. package/dist/.setup/{sandbox-guard-DIImwCy1.mjs → sandbox-guard-DneAfNye.mjs} +70 -30
  85. package/dist/.setup/{session-binding-JEHNMPsr.mjs → session-binding-BgsWcbdY.mjs} +25 -23
  86. package/dist/.setup/{session-binding-record-DU_0biMD.mjs → session-binding-record-C_THntMe.mjs} +27 -12
  87. package/dist/.setup/{session-binding-record-codec-BpH8u_G9.mjs → session-binding-record-codec-DvmOI7g_.mjs} +1 -0
  88. package/dist/.setup/{session-binding-sidecars-DD-enC8w.mjs → session-binding-sidecars-BNSS6WL4.mjs} +55 -63
  89. package/dist/.setup/session-cancellation-DLBSJO5n.mjs +43 -0
  90. package/dist/.setup/{session-catalog-adoption-Ca3OYGYM.mjs → session-catalog-adoption-ppsLlVLB.mjs} +24 -38
  91. package/dist/.setup/{session-catalog-archive-Bv6gV7x9.mjs → session-catalog-archive-CqLRHJ6z.mjs} +11 -13
  92. package/dist/.setup/{session-catalog-events-DujfzcAY.mjs → session-catalog-events-DK0opVp3.mjs} +5 -5
  93. package/dist/.setup/{session-catalog-index-DQ9_sj42.mjs → session-catalog-index-BfzfdtH7.mjs} +96 -271
  94. package/dist/.setup/{session-catalog-index-order-CTfoefow.mjs → session-catalog-index-order-0Zqng2u8.mjs} +1 -1
  95. package/dist/.setup/{session-catalog-limits-BynIoOYm.mjs → session-catalog-limits-Dc6E0BZz.mjs} +1 -1
  96. package/dist/.setup/{session-catalog-list-request-D4MYNgDB.mjs → session-catalog-list-request-CAjoWjaH.mjs} +3 -4
  97. package/dist/.setup/{session-catalog-native-projection-BY2zMkMO.mjs → session-catalog-native-projection-G3lSDYYG.mjs} +5 -5
  98. package/dist/.setup/{session-catalog-node-adoption-BdP9Zjqo.mjs → session-catalog-node-adoption-e9v8mGgx.mjs} +5 -5
  99. package/dist/.setup/{session-catalog-node-continue-CNJibO4_.mjs → session-catalog-node-continue-H7nrzcUD.mjs} +5 -5
  100. package/dist/.setup/{session-catalog-node-lookup-BH_DBGa9.mjs → session-catalog-node-lookup-BrZfDkA8.mjs} +2 -2
  101. package/dist/.setup/{session-catalog-parsing-DkeoVn60.mjs → session-catalog-parsing-V6jyFg9g.mjs} +2 -2
  102. package/dist/.setup/{session-catalog-projection-BTXOyzl_.mjs → session-catalog-projection-BjWE414G.mjs} +8 -7
  103. package/dist/.setup/{session-catalog-provenance-CmsOE5mh.mjs → session-catalog-provenance-Dg9s12z-.mjs} +50 -30
  104. package/dist/.setup/{session-catalog-source-yQpy2Y6b.mjs → session-catalog-source-DqyuNxCe.mjs} +2 -6
  105. package/dist/.setup/{session-cli-GwU0izn-.mjs → session-cli-CBGKiqdv.mjs} +1 -1
  106. package/dist/.setup/{session-history-BO6i_pfk.mjs → session-history-7W0cgTXF.mjs} +11 -9
  107. package/dist/.setup/{session-history-import-CaO8s6ta.mjs → session-history-import-BwPKwcNi.mjs} +4 -4
  108. package/dist/.setup/{session-initialization-Bi_2DKhc.mjs → session-initialization-Dn3vveGv.mjs} +2 -2
  109. package/dist/.setup/{session-retirement-CIDqLMII.mjs → session-retirement-Ci_JvOfH.mjs} +8 -8
  110. package/dist/.setup/{session-history.worker-DJQfek5p.mjs → settled-turn-evidence--tRW6fSm.mjs} +2 -18
  111. package/dist/.setup/{settled-turn-finalizer-C6tjH8RJ.mjs → settled-turn-finalizer-D3-KXsbP.mjs} +8 -8
  112. package/dist/.setup/{shared-client-CCz9ldpr.mjs → shared-client-CE_uY0A1.mjs} +380 -557
  113. package/dist/.setup/side-question-OM18H9WJ.mjs +998 -0
  114. package/dist/.setup/{source-DsubBCYm.mjs → source-uGKgKWm8.mjs} +5 -5
  115. package/dist/.setup/{thread-archive-guard-LKdwQKyr.mjs → thread-archive-guard-BWjSsA92.mjs} +1 -1
  116. package/dist/.setup/{thread-lifecycle-run-CxVfnkG-.mjs → thread-lifecycle-run-mLueY6pH.mjs} +172 -75
  117. package/dist/.setup/{thread-model-selection-DcVebr8N.mjs → thread-model-selection-DxposL4X.mjs} +9 -9
  118. package/dist/.setup/{thread-ownership-_2e1sjfi.mjs → thread-ownership-t6Y9fLQS.mjs} +7 -7
  119. package/dist/.setup/{thread-policy-CLTwg3ZA.mjs → thread-policy-Cy301Or8.mjs} +6 -6
  120. package/dist/.setup/{thread-requests-BgzJwJtS.mjs → thread-requests-BjawdIVV.mjs} +14 -14
  121. package/dist/.setup/{thread-resume-C6qsk8_o.mjs → thread-resume-BUbsUfgF.mjs} +6 -6
  122. package/dist/.setup/{transcript-history-projection-DfKcoZCB.mjs → transcript-history-projection-i-FVpyha.mjs} +1 -1
  123. package/dist/.setup/{transcript-mirror-Bee2o6jj.mjs → transcript-mirror-CEQJZlF3.mjs} +6 -9
  124. package/dist/.setup/{transport-stdio-CRWTkKOn.mjs → transport-stdio-Bq160Dhv.mjs} +63 -64
  125. package/dist/.setup/{transport-websocket-DIyPfkHo.mjs → transport-websocket-0YqiI_MH.mjs} +1 -1
  126. package/dist/.setup/{turn-router-CSJl3yYQ.mjs → turn-router-Dbw17k3K.mjs} +2 -2
  127. package/dist/.setup/{upstream-session-fork-BC45E4Pe.mjs → upstream-session-fork-_LYkh0nZ.mjs} +46 -219
  128. package/dist/.setup/{usage-limit-error-CJoJ_F8V.mjs → usage-limit-error-DcOSH3J4.mjs} +4 -4
  129. package/dist/.setup/{usage-1eNaNDM2.mjs → usage-w_93wnnR.mjs} +4 -4
  130. package/dist/.setup/{web-search-item-CvokaZOo.mjs → web-search-item-DHVuNSqk.mjs} +1 -1
  131. package/dist/.setup/{web-search-provider.runtime-Qq_wUrvv.mjs → web-search-provider.runtime-DMHxve5v.mjs} +3 -3
  132. package/dist/.setup/{workspace-write-sandbox-probe-BDWO2Qkh.mjs → workspace-write-sandbox-probe-DJxOXcF3.mjs} +2 -2
  133. package/dist/api.js +7 -28
  134. package/dist/catalog-page.worker.js +1 -1
  135. package/dist/cli-metadata.js +1 -1
  136. package/dist/client-version-api.js +25 -0
  137. package/dist/doctor-contract-api.js +5 -5
  138. package/dist/harness.js +59 -36
  139. package/dist/index.js +259 -295
  140. package/dist/media-understanding-provider.js +2 -2
  141. package/dist/migration-provider-api.js +1 -2
  142. package/dist/native-session-binding-api.js +1 -2
  143. package/dist/provider-discovery.js +1 -1
  144. package/dist/session-history-worker-entrypoint.js +12 -0
  145. package/dist/session-history-worker-runtime.js +7 -18
  146. package/dist/session-history.worker.js +18 -2
  147. package/openclaw.plugin.json +1 -1
  148. package/package.json +6 -6
  149. package/dist/.setup/attempt-terminal-jO5IMj9K.mjs +0 -2
  150. package/dist/.setup/command-rpc-CUy4Bo-0.mjs +0 -247
  151. package/dist/.setup/compact-BCCjM_cb.mjs +0 -808
  152. package/dist/.setup/inference-context-DNlGwzwy.mjs +0 -91
  153. package/dist/.setup/managed-binary-BtIjV7yN.mjs +0 -175
  154. package/dist/.setup/native-execution-policy-MXEe7PB3.mjs +0 -75
  155. package/dist/.setup/protocol-CANUwXJ3.mjs +0 -17
  156. package/dist/.setup/side-question-COaYBoON.mjs +0 -826
@@ -1,37 +1,38 @@
1
- import { i as isJsonObject } from "./protocol-CANUwXJ3.mjs";
2
- import { m as sessionBindingIdentity, n as assertCodexBindingMayBeReplaced, r as bindingStoreKey } from "./session-binding-record-DU_0biMD.mjs";
1
+ import { r as isJsonObject } from "./protocol-CaPAVwe9.mjs";
2
+ import { g as sessionBindingIdentity, n as assertCodexBindingMayBeReplaced, r as bindingStoreKey } from "./session-binding-record-C_THntMe.mjs";
3
3
  import { r as isCodexFastServiceTier } from "./config-utils-DN_YT7dE.mjs";
4
- import { c as resolveCodexAppServerPreparedApiKeyCacheKey, s as resolveCodexAppServerFallbackApiKeyCacheKey } from "./auth-cache-key-BzYrcgwJ.mjs";
4
+ import { c as resolveCodexAppServerPreparedApiKeyCacheKey, s as resolveCodexAppServerFallbackApiKeyCacheKey } from "./auth-cache-key-CVcYw8HD.mjs";
5
5
  import { n as withCodexConversationThreadActivity } from "./thread-ownership-queue-CeyYScUC.mjs";
6
6
  import { a as canMutateCodexHost, i as assertCodexHostOwnerCurrent, n as CODEX_HOST_INSPECTION_AUTH_ERROR, o as hasCodexAdminScope, r as CODEX_NATIVE_EXECUTION_AUTH_ERROR, t as CODEX_FULL_PERMISSIONS_AUTH_ERROR } from "./command-authorization-AikPDtcc.mjs";
7
- import { l as formatRelativeDuration, s as summarizeCodexAccountUsage } from "./rate-limits-CI8pTPqL.mjs";
8
- import { a as formatCodexAccountLine, c as formatCodexTextForDisplay, d as formatModels, f as formatSkills, i as formatAccount, l as formatComputerUseStatus, m as isLikelyEmailAddress, n as buildHelp, o as formatCodexDisplayText, p as formatThreads, r as escapeCodexChatText, s as formatCodexStatus, t as CODEX_RESUME_SAFE_THREAD_ID_PATTERN, u as formatList } from "./command-formatters-xW9KpoSZ.mjs";
9
- import { i as readCodexConversationBindingData, n as createCodexCliNodeConversationBindingData, o as resolveCodexDefaultWorkspaceDir, r as createCodexConversationBindingData } from "./conversation-binding-data-UgLuTSQT.mjs";
10
- import { r as CodexAppServerRpcError } from "./rpc-error-C98SHchT.mjs";
11
- import { t as CODEX_CONTROL_METHODS } from "./capabilities-DbOzOglY.mjs";
7
+ import { l as formatRelativeDuration, s as summarizeCodexAccountUsage } from "./rate-limits-BpfURnuy.mjs";
8
+ import { a as formatCodexAccountLine, c as formatCodexTextForDisplay, d as formatModels, f as formatSkills, i as formatAccount, l as formatComputerUseStatus, m as isLikelyEmailAddress, n as buildHelp, o as formatCodexDisplayText, p as formatThreads, r as escapeCodexChatText, s as formatCodexStatus, t as CODEX_RESUME_SAFE_THREAD_ID_PATTERN, u as formatList } from "./command-formatters-B_7-QZ1c.mjs";
9
+ import { i as readCodexConversationBindingData, n as createCodexCliNodeConversationBindingData, o as resolveCodexDefaultWorkspaceDir, r as createCodexConversationBindingData } from "./conversation-binding-data-khgW0n-o.mjs";
10
+ import { r as CodexAppServerRpcError } from "./rpc-error-DemqqaxE.mjs";
11
+ import { t as CODEX_CONTROL_METHODS } from "./capabilities-DAS-JX1z.mjs";
12
12
  import { n as filterCodexMarketplacePlugins, r as parseCodexPluginMarketplaceId, t as discoverCodexMarketplacePlugins } from "./plugin-marketplace-discovery-BblHM3DU.mjs";
13
- import { o as formatCodexCliSessions } from "./node-cli-sessions-CzKg2nGq.mjs";
14
- import { a as defaultCodexAppInventoryCache, r as buildCodexPluginAppCacheKey } from "./plugin-app-cache-key-Bg9DbDI6.mjs";
15
- import { i as resolveCodexBindingAppServerConnection } from "./binding-connection-B7HAAZSI.mjs";
16
- import { a as withCodexAppServerJsonClient } from "./request-DInueZ2q.mjs";
17
- import { n as findCodexMarketplacePluginSummary, o as pluginReadParams, r as isOpenAiCuratedMarketplaceName, u as CODEX_PLUGINS_MARKETPLACE_NAME } from "./plugin-inventory-CYgdo14P.mjs";
18
- import "./config-C1YVVLEA.mjs";
19
- import { n as resolveCodexAppServerRuntimeOptions } from "./config-runtime-DWzK-k0n.mjs";
20
- import { a as resolveCodexAppServerAuthProfileStore, i as resolveCodexAppServerAuthProfileIdForAgent, n as normalizeCodexAppServerBindingModelProvider } from "./auth-profile-CgHQ8Vot.mjs";
21
- import { F as consumeCodexAppServerLiveThread, R as hasCodexAppServerLiveThread, c as getLeasedSharedCodexAppServerClient, h as releaseLeasedSharedCodexAppServerClient, tt as resolveCodexAppServerAuthAccountCacheKey } from "./shared-client-CCz9ldpr.mjs";
22
- import { a as isCodexAppServerIndeterminateRequestCancellationError, h as assertCodexThreadResumeResponse, p as assertCodexThreadAcceptsDirectInput, s as isCodexAppServerPrewriteRequestCancellationError } from "./client-aPKNc4Ii.mjs";
23
- import { o as closeCodexStartupClientBestEffort } from "./attempt-client-cleanup-D3YvP0N7.mjs";
24
- import { n as fingerprintCodexAppServerAuthBinding } from "./auth-binding-BaxlhaNx.mjs";
25
- import { n as listAllCodexAppServerModels } from "./models-BB0l-gUb.mjs";
26
- import { n as refreshCodexAppRuntimeState, r as refreshCodexPluginRuntimeState } from "./plugin-activation-D7WkJMvU.mjs";
27
- import { i as resolveCodexSessionBinding, n as createCodexSessionGenerationSupersededError } from "./session-binding-JEHNMPsr.mjs";
28
- import { a as rollbackCodexAppServerBindingSubscription, c as withExclusiveCodexAppServerThread, i as retireCodexConversationThreadBinding, n as releaseCodexAppServerBindingSubscription, r as retainCodexAppServerBindingSubscription, t as isSameCodexAppServerThreadOwner } from "./thread-ownership-_2e1sjfi.mjs";
29
- import { n as resolveCodexNativeSandboxBlock, t as resolveCodexNativeExecutionBlock } from "./sandbox-guard-DIImwCy1.mjs";
30
- import { i as assertCodexSupervisionThreadLineage } from "./thread-policy-CLTwg3ZA.mjs";
31
- import { t as defaultCodexPluginMetadataCache } from "./plugin-metadata-cache-Bi8TAPwX.mjs";
32
- import { n as installCodexComputerUse, r as readCodexComputerUseStatus } from "./computer-use-C6yYfm6-.mjs";
33
- import { a as requestOptions, i as readCodexStatusProbes, o as safeCodexControlRequest, r as prepareCodexControlSessionAuth, t as codexControlRequest } from "./command-rpc-CUy4Bo-0.mjs";
34
- import { a as readCodexConversationActiveTurn, c as setCodexConversationModel, d as stopCodexConversationTurn, i as parseCodexPermissionsModeArg, l as setCodexConversationPermissions, n as formatPermissionsMode, r as parseCodexFastModeArg, s as setCodexConversationFastMode, u as steerCodexConversationTurn } from "./conversation-control-GXM3unE4.mjs";
13
+ import { o as formatCodexCliSessions } from "./node-cli-sessions-BuJnBnEq.mjs";
14
+ import { a as defaultCodexAppInventoryCache, r as buildCodexPluginAppCacheKey } from "./plugin-app-cache-key-DRb-niJc.mjs";
15
+ import { i as resolveCodexBindingAppServerConnection } from "./binding-connection-GTgUj9pi.mjs";
16
+ import { a as withCodexAppServerJsonClient } from "./request-ePeNJrOd.mjs";
17
+ import { n as findCodexMarketplacePluginSummary, o as pluginReadParams, r as isOpenAiCuratedMarketplaceName, u as CODEX_PLUGINS_MARKETPLACE_NAME } from "./plugin-inventory-DE9wcaeH.mjs";
18
+ import "./config-BfrAlTMT.mjs";
19
+ import { n as resolveCodexAppServerRuntimeOptions } from "./config-runtime-BZRizyuG.mjs";
20
+ import { a as resolveCodexAppServerAuthProfileStore, i as resolveCodexAppServerAuthProfileIdForAgent, n as normalizeCodexAppServerBindingModelProvider, r as resolveCodexAppServerAuthProfileId } from "./auth-profile-auwzSwwy.mjs";
21
+ import { A as hasCodexAppServerLiveThread, D as consumeCodexAppServerLiveThread, Z as resolveCodexAppServerAuthAccountCacheKey, f as releaseLeasedSharedCodexAppServerClient, o as getLeasedSharedCodexAppServerClient } from "./shared-client-CE_uY0A1.mjs";
22
+ import { f as assertCodexThreadAcceptsDirectInput, i as isCodexAppServerIndeterminateRequestCancellationError, m as assertCodexThreadResumeResponse, o as isCodexAppServerPrewriteRequestCancellationError } from "./client-BS8X7HmG.mjs";
23
+ import { o as closeCodexStartupClientBestEffort } from "./attempt-client-cleanup-6OcbMH46.mjs";
24
+ import { n as fingerprintCodexAppServerAuthBinding } from "./auth-binding-830RLAJW.mjs";
25
+ import { n as listAllCodexAppServerModels } from "./models-BWLEUo2E.mjs";
26
+ import { n as refreshCodexAppRuntimeState, r as refreshCodexPluginRuntimeState } from "./plugin-activation-CXPWe-hl.mjs";
27
+ import { i as resolveCodexSessionBinding, n as createCodexSessionGenerationSupersededError } from "./session-binding-BgsWcbdY.mjs";
28
+ import { a as rollbackCodexAppServerBindingSubscription, c as withExclusiveCodexAppServerThread, i as retireCodexConversationThreadBinding, n as releaseCodexAppServerBindingSubscription, r as retainCodexAppServerBindingSubscription, t as isSameCodexAppServerThreadOwner } from "./thread-ownership-t6Y9fLQS.mjs";
29
+ import { n as prepareCodexNativeExecutionBlock, r as prepareCodexNativeSandboxBlock } from "./sandbox-guard-DneAfNye.mjs";
30
+ import { i as assertCodexSupervisionThreadLineage } from "./thread-policy-Cy301Or8.mjs";
31
+ import { t as defaultCodexPluginMetadataCache } from "./plugin-metadata-cache-BqC-a6Fb.mjs";
32
+ import { n as installCodexComputerUse, r as readCodexComputerUseStatus } from "./computer-use-FqQ-Flbl.mjs";
33
+ import { t as readCodexExperimentalFeature } from "./experimental-features-uGnVDtp-.mjs";
34
+ import { a as requestOptions, i as readCodexStatusProbes, o as safeCodexControlRequest, r as prepareCodexControlSessionAuth, t as codexControlRequest } from "./command-rpc-SXqLQukR.mjs";
35
+ import { a as readCodexConversationActiveTurn, c as setCodexConversationModel, d as stopCodexConversationTurn, i as parseCodexPermissionsModeArg, l as setCodexConversationPermissions, n as formatPermissionsMode, r as parseCodexFastModeArg, s as setCodexConversationFastMode, u as steerCodexConversationTurn } from "./conversation-control-B2EpVZEb.mjs";
35
36
  import { normalizeOptionalString, normalizeUniqueStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
36
37
  import crypto from "node:crypto";
37
38
  import { isDeepStrictEqual } from "node:util";
@@ -42,20 +43,20 @@ import { coerceErrorMessage } from "openclaw/plugin-sdk/error-runtime";
42
43
  import { isIncognitoSessionKey } from "openclaw/plugin-sdk/session-key-runtime";
43
44
  import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
44
45
  import { parseAgentSessionKey } from "openclaw/plugin-sdk/routing";
45
- import { ensureAuthProfileStore, resolveAgentDir as resolveAgentDir$1, resolveAgentWorkspaceDir, resolveAuthProfileEligibility, resolveProfileUnusableUntilForDisplay } from "openclaw/plugin-sdk/agent-runtime";
46
- import { getSessionEntry, resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
47
- import { findNormalizedProviderValue, resolveAuthProfileOrder } from "openclaw/plugin-sdk/provider-auth";
46
+ import { ensureAuthProfileStoreAsync, resolveAgentDir as resolveAgentDir$1, resolveAgentWorkspaceDir, resolveAuthProfileEligibility, resolveProfileUnusableUntilForDisplay } from "openclaw/plugin-sdk/agent-runtime";
47
+ import { getSessionEntryAsync, resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
48
+ import { ensureAuthProfileStore, findNormalizedProviderValue, resolveAuthProfileOrder } from "openclaw/plugin-sdk/provider-auth";
48
49
  import { pruneMapToMaxSize } from "openclaw/plugin-sdk/collection-runtime";
50
+ import { captureSessionEntryCurrentCheckAsync, composeSessionEntryCommitGuards } from "openclaw/plugin-sdk/session-binding-runtime";
49
51
  import { renderMessagePresentationFallbackText } from "openclaw/plugin-sdk/interactive-runtime";
50
52
  import { MODEL_SELECTION_LOCKED_MESSAGE, isModelSelectionLocked, resolvePersistedSessionRuntimeId } from "openclaw/plugin-sdk/model-session-runtime";
51
- import { composeSessionEntryCommitGuards } from "openclaw/plugin-sdk/session-binding-runtime";
52
53
  //#region extensions/codex/src/command-account.ts
53
54
  const OPENAI_PROVIDER_ID = "openai";
54
55
  async function readCodexAccountAuthOverview(params) {
55
56
  if (!params.account.ok && !params.limits.ok) return;
56
57
  const config = params.ctx.config;
57
58
  const agentDir = params.agentDir;
58
- const store = ensureAuthProfileStore(agentDir, {
59
+ const store = await ensureAuthProfileStoreAsync(agentDir, {
59
60
  allowKeychainPrompt: false,
60
61
  config
61
62
  });
@@ -394,22 +395,7 @@ function buildCodexCommandPickerPresentation(title, prompt, buttons) {
394
395
  async function readCodexHostedAppsSupport(context, account) {
395
396
  if (account.status !== "known") return "unknown";
396
397
  if (!isJsonObject(account.value.account) || account.value.account.type !== "chatgpt") return "sign_in_required";
397
- const features = await readEvidence(async () => {
398
- let cursor;
399
- const visited = /* @__PURE__ */ new Set();
400
- do {
401
- const response = await context.request("experimentalFeature/list", {
402
- ...context.threadId ? { threadId: context.threadId } : {},
403
- ...cursor ? { cursor } : {},
404
- limit: 100
405
- });
406
- const apps = response.data.find((feature) => feature.name === "apps");
407
- if (apps) return apps.enabled;
408
- cursor = response.nextCursor ?? void 0;
409
- if (cursor && visited.has(cursor)) return;
410
- if (cursor) visited.add(cursor);
411
- } while (cursor);
412
- });
398
+ const features = await readEvidence(() => readCodexExperimentalFeature((params) => context.request("experimentalFeature/list", params), "apps", context.threadId));
413
399
  if (features.status !== "known") return features.reason === "unsupported" ? "unsupported" : "unknown";
414
400
  return features.value === void 0 ? "unknown" : features.value ? "supported" : "disabled";
415
401
  }
@@ -1230,12 +1216,12 @@ async function resolveControlTarget(ctx) {
1230
1216
  } : void 0;
1231
1217
  }
1232
1218
  async function resolvePreparedCodexCommandAuthority(deps, ctx) {
1233
- const target = await resolveControlTarget(ctx);
1234
1219
  const fallback = resolveCodexConversationControlScope(ctx);
1235
1220
  const sessionId = ctx.sessionId;
1236
1221
  const sessionKey = ctx.sessionKey;
1237
1222
  const sessionAgentId = ctx.sessionTarget?.agentId ?? fallback.agentId;
1238
1223
  const storePath = ctx.sessionTarget?.storePath ?? (sessionKey ? resolveStorePath(ctx.config.session?.store, { agentId: sessionAgentId }) : void 0);
1224
+ const target = await resolveControlTarget(ctx);
1239
1225
  const sessionIdentity = sessionId ? sessionBindingIdentity({
1240
1226
  sessionId,
1241
1227
  sessionKey,
@@ -1249,71 +1235,98 @@ async function resolvePreparedCodexCommandAuthority(deps, ctx) {
1249
1235
  config: ctx.config,
1250
1236
  storePath
1251
1237
  }) : void 0;
1252
- const assertHostCurrent = currentSession?.authority.assertLegacyCurrent ?? composeSessionEntryCommitGuards([]);
1253
- const binding = (target && (!sessionIdentity || !isDeepStrictEqual(target.identity, sessionIdentity)) ? await resolveCodexSessionBinding({
1254
- bindingStore: deps.bindingStore,
1255
- identity: target.identity,
1256
- config: ctx.config,
1257
- storePath,
1258
- assertCurrent: assertHostCurrent
1259
- }) : currentSession)?.binding;
1260
- const assertCurrent = composeSessionEntryCommitGuards([assertHostCurrent], (assertSource) => {
1261
- assertSource();
1262
- if (target && !isDeepStrictEqual(deps.bindingStore.read(target.identity), binding)) throw new Error("Codex command binding changed before dispatch");
1263
- assertSource();
1264
- });
1265
- assertCurrent();
1266
- return {
1267
- target,
1268
- binding,
1269
- currentSessionBinding: currentSession?.binding,
1270
- sessionId,
1271
- sessionKey,
1272
- storePath,
1273
- assertHostCurrent,
1274
- assertCurrent,
1275
- assertMutationCurrent: composeSessionEntryCommitGuards([assertCurrent], (assertSource) => {
1276
- assertCodexHostOwnerCurrent(ctx);
1238
+ let resolvedTarget = currentSession;
1239
+ const release = () => {
1240
+ if (resolvedTarget !== currentSession) resolvedTarget?.release();
1241
+ currentSession?.release();
1242
+ };
1243
+ try {
1244
+ const assertHostCurrent = currentSession?.authority.assertLegacyCurrent ?? composeSessionEntryCommitGuards([]);
1245
+ resolvedTarget = target && (!sessionIdentity || !isDeepStrictEqual(target.identity, sessionIdentity)) ? await resolveCodexSessionBinding({
1246
+ bindingStore: deps.bindingStore,
1247
+ identity: target.identity,
1248
+ config: ctx.config,
1249
+ storePath,
1250
+ assertCurrent: assertHostCurrent
1251
+ }) : currentSession;
1252
+ const binding = resolvedTarget?.binding;
1253
+ const assertCurrent = composeSessionEntryCommitGuards([assertHostCurrent], (assertSource) => {
1277
1254
  assertSource();
1278
- }),
1279
- assertHostMutationCurrent: composeSessionEntryCommitGuards([assertHostCurrent], (assertSource) => {
1280
- assertCodexHostOwnerCurrent(ctx);
1255
+ if (target && !isDeepStrictEqual(deps.bindingStore.read(target.identity), binding)) throw new Error("Codex command binding changed before dispatch");
1281
1256
  assertSource();
1282
- })
1283
- };
1257
+ });
1258
+ assertCurrent();
1259
+ const assertCurrentAsync = async () => {
1260
+ await ctx.assertNativePolicyCurrent?.();
1261
+ await resolvedTarget?.authority.withCurrent(assertCurrent);
1262
+ if (!resolvedTarget) assertCurrent();
1263
+ };
1264
+ return {
1265
+ release,
1266
+ target,
1267
+ binding,
1268
+ currentSessionBinding: currentSession?.binding,
1269
+ sessionId,
1270
+ sessionKey,
1271
+ storePath,
1272
+ assertHostCurrent,
1273
+ assertCurrent,
1274
+ assertCurrentAsync,
1275
+ mutationSource: composeSessionEntryCommitGuards([assertCurrent, ctx.nativePolicySource]),
1276
+ assertMutationCurrent: composeSessionEntryCommitGuards([assertCurrent], (assertSource) => {
1277
+ assertCodexHostOwnerCurrent(ctx);
1278
+ assertSource();
1279
+ }),
1280
+ assertHostMutationCurrent: composeSessionEntryCommitGuards([assertHostCurrent], (assertSource) => {
1281
+ assertCodexHostOwnerCurrent(ctx);
1282
+ assertSource();
1283
+ })
1284
+ };
1285
+ } catch (error) {
1286
+ release();
1287
+ throw error;
1288
+ }
1284
1289
  }
1285
1290
  async function resolveCommandAppServerContext(deps, ctx, pluginConfig) {
1286
1291
  const authority = await resolvePreparedCodexCommandAuthority(deps, ctx);
1287
- const { target, binding } = authority;
1288
- const fallback = resolveCodexConversationControlScope(ctx);
1289
- const agentDir = target?.agentDir ?? fallback.agentDir;
1290
- const authProfileId = binding?.connectionScope === "supervision" ? void 0 : resolveCodexAppServerAuthProfileIdForAgent({
1291
- authProfileId: binding?.authProfileId ?? target?.requestedAuthProfileId,
1292
- agentDir,
1293
- config: ctx.config
1294
- });
1295
- const connection = await resolveCodexBindingAppServerConnection({
1296
- binding,
1297
- authProfileId,
1298
- pluginConfig,
1299
- agentDir,
1300
- config: ctx.config,
1301
- assertCurrent: authority.assertCurrent
1302
- });
1303
- return {
1304
- scope: {
1305
- agentId: target?.agentId ?? fallback.agentId,
1292
+ try {
1293
+ const { target, binding } = authority;
1294
+ const fallback = resolveCodexConversationControlScope(ctx);
1295
+ const agentDir = target?.agentDir ?? fallback.agentDir;
1296
+ const authProfileId = binding?.connectionScope === "supervision" ? void 0 : await resolveCodexAppServerAuthProfileIdForAgent({
1297
+ authProfileId: binding?.authProfileId ?? target?.requestedAuthProfileId,
1306
1298
  agentDir,
1307
- ...connection.clientAuthProfileId !== void 0 ? { authProfileId: connection.clientAuthProfileId } : {},
1308
- ...connection.usesSupervisionConnection ? { startOptions: connection.appServer.start } : {},
1309
- ...authority.sessionKey ? { sessionKey: authority.sessionKey } : {},
1310
- ...authority.sessionId ? { sessionId: authority.sessionId } : {},
1311
- ...authority.storePath ? { storePath: authority.storePath } : {},
1312
- assertCurrent: authority.assertCurrent
1313
- },
1314
- target,
1315
- binding
1316
- };
1299
+ config: ctx.config
1300
+ });
1301
+ const connection = await resolveCodexBindingAppServerConnection({
1302
+ binding,
1303
+ authProfileId,
1304
+ pluginConfig,
1305
+ agentDir,
1306
+ config: ctx.config,
1307
+ assertCurrent: authority.assertCurrent,
1308
+ assertCurrentAsync: authority.assertCurrentAsync
1309
+ });
1310
+ return {
1311
+ scope: {
1312
+ agentId: target?.agentId ?? fallback.agentId,
1313
+ agentDir,
1314
+ ...connection.clientAuthProfileId !== void 0 ? { authProfileId: connection.clientAuthProfileId } : {},
1315
+ ...connection.usesSupervisionConnection ? { startOptions: connection.appServer.start } : {},
1316
+ ...authority.sessionKey ? { sessionKey: authority.sessionKey } : {},
1317
+ ...authority.sessionId ? { sessionId: authority.sessionId } : {},
1318
+ ...authority.storePath ? { storePath: authority.storePath } : {},
1319
+ assertCurrent: authority.assertCurrent,
1320
+ assertCurrentAsync: authority.assertCurrentAsync,
1321
+ release: authority.release
1322
+ },
1323
+ target,
1324
+ binding
1325
+ };
1326
+ } catch (error) {
1327
+ authority.release();
1328
+ throw error;
1329
+ }
1317
1330
  }
1318
1331
  async function resolveCommandAppServerScope(deps, ctx, pluginConfig) {
1319
1332
  return (await resolveCommandAppServerContext(deps, ctx, pluginConfig)).scope;
@@ -1426,7 +1439,10 @@ async function confirmCodexDiagnosticsFeedback(deps, ctx, pluginConfig, token) {
1426
1439
  const pending = consumeCodexDiagnosticsConfirmation(ctx, token, "confirm");
1427
1440
  if (typeof pending === "string") return pending;
1428
1441
  if (!pending.privateRouted && !await hasAnyCodexDiagnosticsIdentity(ctx)) return "Cannot send Codex diagnostics because this command did not include a stable session identity.";
1429
- const currentTargets = pending.privateRouted ? resolvePendingCodexDiagnosticsTargets(deps, pending.targets, ctx.config) : await resolveCodexDiagnosticsTargets(deps, ctx);
1442
+ const currentTargets = pending.privateRouted ? (await Promise.all(pending.targets.map(async (target) => {
1443
+ const binding = await deps.bindingStore.readAsync(target.identity);
1444
+ return binding?.threadId ? [await resolveCodexDiagnosticsTarget(target, binding, ctx.config)] : [];
1445
+ }))).flat() : await resolveCodexDiagnosticsTargets(deps, ctx);
1430
1446
  if (!codexDiagnosticsTargetsMatch(pending.targets, currentTargets)) return "The Codex diagnostics sessions changed before confirmation. Run /diagnostics again for the current threads.";
1431
1447
  return await sendCodexDiagnosticsFeedbackForTargets(deps, ctx, pluginConfig, pending.note ?? "", currentTargets, pending.scopeKey);
1432
1448
  }
@@ -1558,20 +1574,38 @@ async function resolveCodexDiagnosticsTargets(deps, ctx) {
1558
1574
  const key = bindingStoreKey(candidate.identity);
1559
1575
  if (seenBindingKeys.has(key)) continue;
1560
1576
  seenBindingKeys.add(key);
1561
- const binding = deps.bindingStore.read(candidate.identity);
1577
+ const binding = await deps.bindingStore.readAsync(candidate.identity);
1562
1578
  if (!binding?.threadId || seenThreadIds.has(binding.threadId)) continue;
1563
1579
  seenThreadIds.add(binding.threadId);
1564
- targets.push(resolveCodexDiagnosticsTarget(candidate, binding, ctx.config));
1580
+ targets.push(await resolveCodexDiagnosticsTarget(candidate, binding, ctx.config));
1565
1581
  }
1566
1582
  return targets;
1567
1583
  }
1568
1584
  function resolvePendingCodexDiagnosticsTargets(deps, targets, config) {
1569
1585
  return targets.flatMap((target) => {
1570
1586
  const binding = deps.bindingStore.read(target.identity);
1571
- return binding?.threadId ? [resolveCodexDiagnosticsTarget(target, binding, config)] : [];
1587
+ if (!binding?.threadId) return [];
1588
+ return [createCodexDiagnosticsTarget(target, binding, binding.connectionScope === "supervision" ? void 0 : binding.authProfileId?.trim() || resolveCodexAppServerAuthProfileId({
1589
+ authProfileId: binding.authProfileId,
1590
+ config,
1591
+ store: ensureAuthProfileStore(target.agentDir, {
1592
+ profileId: binding.authProfileId,
1593
+ allowKeychainPrompt: false,
1594
+ config,
1595
+ externalCliProviderIds: ["openai"],
1596
+ ...binding.authProfileId ? { externalCliProfileIds: [binding.authProfileId] } : {}
1597
+ })
1598
+ }))];
1572
1599
  });
1573
1600
  }
1574
- function resolveCodexDiagnosticsTarget(target, binding, config) {
1601
+ async function resolveCodexDiagnosticsTarget(target, binding, config) {
1602
+ return createCodexDiagnosticsTarget(target, binding, binding.connectionScope === "supervision" ? void 0 : await resolveCodexAppServerAuthProfileIdForAgent({
1603
+ authProfileId: binding.authProfileId,
1604
+ agentDir: target.agentDir,
1605
+ config
1606
+ }));
1607
+ }
1608
+ function createCodexDiagnosticsTarget(target, binding, authProfileId) {
1575
1609
  const candidate = {
1576
1610
  identity: target.identity,
1577
1611
  agentDir: target.agentDir,
@@ -1590,11 +1624,6 @@ function resolveCodexDiagnosticsTarget(target, binding, config) {
1590
1624
  appServerRuntimeFingerprint: binding.appServerRuntimeFingerprint,
1591
1625
  pendingSupervisionBranch: binding.pendingSupervisionBranch
1592
1626
  };
1593
- const authProfileId = resolveCodexAppServerAuthProfileIdForAgent({
1594
- authProfileId: binding.authProfileId,
1595
- agentDir: target.agentDir,
1596
- config
1597
- });
1598
1627
  return {
1599
1628
  ...candidate,
1600
1629
  threadId: binding.threadId,
@@ -1603,12 +1632,12 @@ function resolveCodexDiagnosticsTarget(target, binding, config) {
1603
1632
  }
1604
1633
  //#endregion
1605
1634
  //#region extensions/codex/src/command-handler-bindings.ts
1606
- function isCurrentSessionModelSelectionLocked(ctx) {
1635
+ async function isCurrentSessionModelSelectionLocked(ctx) {
1607
1636
  const sessionKey = ctx.sessionKey?.trim();
1608
1637
  if (!sessionKey) return false;
1609
1638
  const { agentId } = resolveCodexConversationControlScope(ctx);
1610
1639
  const storePath = ctx.sessionTarget?.storePath ?? resolveStorePath(ctx.config.session?.store, { agentId });
1611
- return isModelSelectionLocked(getSessionEntry({
1640
+ return isModelSelectionLocked(await getSessionEntryAsync({
1612
1641
  storePath,
1613
1642
  sessionKey,
1614
1643
  hydrateSkillPromptRefs: false,
@@ -1618,7 +1647,7 @@ function isCurrentSessionModelSelectionLocked(ctx) {
1618
1647
  async function bindConversation(deps, ctx, pluginConfig, args) {
1619
1648
  const parsed = parseBindArgs(args);
1620
1649
  if (parsed.help) return { text: "Usage: /codex bind [thread-id] [--cwd <path>] [--model <model>] [--provider <provider>]" };
1621
- if (isCurrentSessionModelSelectionLocked(ctx)) return { text: MODEL_SELECTION_LOCKED_MESSAGE };
1650
+ if (await isCurrentSessionModelSelectionLocked(ctx)) return { text: MODEL_SELECTION_LOCKED_MESSAGE };
1622
1651
  const scope = resolveCodexConversationControlScope(ctx);
1623
1652
  const workspaceDir = parsed.cwd ?? deps.resolveCodexDefaultWorkspaceDir(pluginConfig);
1624
1653
  const currentConversation = await ctx.getCurrentConversationBinding();
@@ -1631,12 +1660,13 @@ async function bindConversation(deps, ctx, pluginConfig, args) {
1631
1660
  config: ctx.config
1632
1661
  }) : void 0;
1633
1662
  const currentOwner = currentConversationData?.kind === "codex-app-server-session" ? conversationBindingIdentity(currentConversationData.bindingId) : sessionOwner;
1634
- const existingBinding = currentOwner ? deps.bindingStore.read(currentOwner) : void 0;
1663
+ const existingBinding = currentOwner ? await deps.bindingStore.readAsync(currentOwner) : void 0;
1635
1664
  assertCodexBindingMayBeReplaced(existingBinding, "binding this conversation to another thread");
1636
1665
  const sessionSource = sessionOwner && existingBinding ? {
1637
1666
  agentId: sessionOwner.agentId,
1638
1667
  sessionId: sessionOwner.sessionId,
1639
1668
  threadId: existingBinding.threadId,
1669
+ storePath: ctx.sessionTarget?.storePath ?? resolveStorePath(ctx.config.session?.store, { agentId: sessionOwner.agentId }),
1640
1670
  ...sessionOwner.sessionKey ? { sessionKey: sessionOwner.sessionKey } : {}
1641
1671
  } : void 0;
1642
1672
  const authProfileId = existingBinding?.authProfileId;
@@ -1655,6 +1685,7 @@ async function bindConversation(deps, ctx, pluginConfig, args) {
1655
1685
  }
1656
1686
  });
1657
1687
  const threadLabel = parsed.threadId ?? "a new thread";
1688
+ await ctx.assertNativePolicyCurrent?.();
1658
1689
  assertCodexHostOwnerCurrent(ctx);
1659
1690
  const request = await ctx.requestConversationBinding({
1660
1691
  summary: `Codex app-server thread ${formatCodexDisplayText(threadLabel)} in ${formatCodexDisplayText(workspaceDir)}`,
@@ -1666,7 +1697,7 @@ async function bindConversation(deps, ctx, pluginConfig, args) {
1666
1697
  return { text: `Bound this conversation to ${formatCodexDisplayText(threadLabel)} in ${formatCodexDisplayText(workspaceDir)}. The next message will initialize it.` };
1667
1698
  }
1668
1699
  async function detachConversation(deps, ctx) {
1669
- if (isCurrentSessionModelSelectionLocked(ctx)) return MODEL_SELECTION_LOCKED_MESSAGE;
1700
+ if (await isCurrentSessionModelSelectionLocked(ctx)) return MODEL_SELECTION_LOCKED_MESSAGE;
1670
1701
  const current = await ctx.getCurrentConversationBinding();
1671
1702
  const data = readCodexConversationBindingData(current);
1672
1703
  const identity = data?.kind === "codex-app-server-session" ? conversationBindingIdentity(data.bindingId) : void 0;
@@ -1674,7 +1705,7 @@ async function detachConversation(deps, ctx) {
1674
1705
  let expectedThreadId;
1675
1706
  let expectedStartId;
1676
1707
  if (data?.kind === "codex-app-server-session") {
1677
- const binding = deps.bindingStore.read(identity);
1708
+ const binding = await deps.bindingStore.readAsync(identity);
1678
1709
  assertCodexBindingMayBeReplaced(binding, "detaching its conversation binding");
1679
1710
  if (deps.readCodexConversationActiveTurn(identity)) return "This Codex conversation has an active run; use /codex stop before detaching it.";
1680
1711
  expectedThreadId = binding?.threadId;
@@ -1698,6 +1729,7 @@ async function detachConversation(deps, ctx) {
1698
1729
  })) return "This Codex conversation binding changed while detaching; try again.";
1699
1730
  return detachedPublicConversation;
1700
1731
  });
1732
+ await ctx.assertNativePolicyCurrent?.();
1701
1733
  assertCodexHostOwnerCurrent(ctx);
1702
1734
  return await detachPublicConversation();
1703
1735
  }
@@ -1714,11 +1746,11 @@ async function describeConversationBinding(deps, ctx) {
1714
1746
  "- Active run: not tracked"
1715
1747
  ].join("\n");
1716
1748
  const identity = conversationBindingIdentity(data.bindingId);
1717
- const threadBinding = deps.bindingStore.read(identity);
1749
+ const threadBinding = await deps.bindingStore.readAsync(identity);
1718
1750
  const active = deps.readCodexConversationActiveTurn(identity);
1719
1751
  const sessionKey = ctx.sessionKey?.trim();
1720
1752
  const { agentId } = resolveCodexConversationControlScope(ctx);
1721
- const sessionEntry = sessionKey ? getSessionEntry({
1753
+ const sessionEntry = sessionKey ? await getSessionEntryAsync({
1722
1754
  agentId,
1723
1755
  storePath: ctx.sessionTarget?.storePath ?? resolveStorePath(ctx.config.session?.store, { agentId }),
1724
1756
  sessionKey,
@@ -1739,6 +1771,7 @@ async function describeConversationBinding(deps, ctx) {
1739
1771
  }
1740
1772
  async function buildThreads(deps, ctx, pluginConfig, filter) {
1741
1773
  const scope = await resolveCommandAppServerScope(deps, ctx, pluginConfig);
1774
+ using _ = { [Symbol.dispose]: scope.release };
1742
1775
  const response = await deps.codexControlRequest(pluginConfig, CODEX_CONTROL_METHODS.listThreads, {
1743
1776
  limit: 10,
1744
1777
  ...filter.trim() ? { searchTerm: filter.trim() } : {}
@@ -1763,7 +1796,7 @@ async function resumeThread(deps, ctx, pluginConfig, args) {
1763
1796
  if (parsed.help) return args.includes("--help") || args.includes("-h") || parsed.host ? "Usage: /codex resume <thread-id>\nUsage: /codex resume <session-id> --host <node> --bind here" : "Usage: /codex resume <thread-id>";
1764
1797
  if (parsed.host) return await bindCodexCliNodeSession(deps, ctx, parsed);
1765
1798
  if (!normalizedThreadId || args.length !== 1) return "Usage: /codex resume <thread-id>";
1766
- if (isCurrentSessionModelSelectionLocked(ctx)) return MODEL_SELECTION_LOCKED_MESSAGE;
1799
+ if (await isCurrentSessionModelSelectionLocked(ctx)) return MODEL_SELECTION_LOCKED_MESSAGE;
1767
1800
  if (!ctx.sessionId) return "Cannot attach a Codex thread because this command did not include an OpenClaw session id.";
1768
1801
  const scope = resolveCodexConversationControlScope(ctx);
1769
1802
  const identity = sessionBindingIdentity({
@@ -1772,13 +1805,14 @@ async function resumeThread(deps, ctx, pluginConfig, args) {
1772
1805
  agentId: scope.agentId,
1773
1806
  config: ctx.config
1774
1807
  });
1775
- const { authority } = await resolveCodexSessionBinding({
1808
+ const { authority, release } = await resolveCodexSessionBinding({
1776
1809
  reclaimStale: true,
1777
1810
  bindingStore: deps.bindingStore,
1778
1811
  identity,
1779
1812
  config: ctx.config,
1780
1813
  storePath: ctx.sessionTarget?.storePath
1781
1814
  });
1815
+ using _ = { [Symbol.dispose]: release };
1782
1816
  const assertHostGeneration = authority.assertLegacyCurrent;
1783
1817
  return await withExclusiveCodexAppServerThread({
1784
1818
  bindingStore: deps.bindingStore,
@@ -1788,16 +1822,16 @@ async function resumeThread(deps, ctx, pluginConfig, args) {
1788
1822
  const generation = await deps.bindingStore.prepareSessionGenerationReclaim(identity);
1789
1823
  assertHostGeneration();
1790
1824
  if (generation.kind !== "resolved" || !generation.result) throw createCodexSessionGenerationSupersededError(identity.sessionId);
1791
- const currentBinding = deps.bindingStore.read(identity);
1825
+ const currentBinding = await deps.bindingStore.readAsync(identity);
1792
1826
  assertCodexBindingMayBeReplaced(currentBinding, "attaching a different resumed thread");
1793
1827
  let pendingResumeConfiguration = false;
1794
- const commitResumedThread = async (value, client, { authProfileId, assertCurrent }) => {
1828
+ const commitResumedThread = async (value, client, { authProfileId, assertCurrent, assertCurrentAsync, source }) => {
1795
1829
  const response = assertCodexThreadResumeResponse(value);
1796
1830
  const effectiveThreadId = response.thread.id;
1797
1831
  if (effectiveThreadId !== normalizedThreadId) throw new Error(`Codex thread/resume returned ${effectiveThreadId} for ${normalizedThreadId}`);
1798
1832
  const resumedCwd = response.thread.cwd;
1799
1833
  if (typeof resumedCwd !== "string") throw new Error(`Codex thread/resume returned no cwd for ${normalizedThreadId}`);
1800
- const modelProvider = normalizeCodexAppServerBindingModelProvider({
1834
+ const modelProvider = await normalizeCodexAppServerBindingModelProvider({
1801
1835
  authProfileId,
1802
1836
  modelProvider: response.modelProvider ?? void 0,
1803
1837
  agentDir: scope.agentDir,
@@ -1808,7 +1842,7 @@ async function resumeThread(deps, ctx, pluginConfig, args) {
1808
1842
  let sameOwner = false;
1809
1843
  let knownOwnership;
1810
1844
  try {
1811
- const bindingBeforeCommit = deps.bindingStore.read(identity);
1845
+ const bindingBeforeCommit = await deps.bindingStore.readAsync(identity);
1812
1846
  assertCodexBindingMayBeReplaced(bindingBeforeCommit, "committing a different resumed thread");
1813
1847
  sameOwner = isSameCodexAppServerThreadOwner(bindingBeforeCommit, {
1814
1848
  threadId: effectiveThreadId,
@@ -1816,6 +1850,7 @@ async function resumeThread(deps, ctx, pluginConfig, args) {
1816
1850
  });
1817
1851
  const sameThreadBinding = bindingBeforeCommit?.threadId === effectiveThreadId ? bindingBeforeCommit : void 0;
1818
1852
  pendingResumeConfiguration = sameThreadBinding?.preserveNativeModel !== true && (!sameThreadBinding?.dynamicToolsFingerprint || !sameThreadBinding.webSearchThreadConfigFingerprint || sameThreadBinding.pendingResumeConfiguration === true);
1853
+ await assertCurrentAsync?.();
1819
1854
  assertCurrent();
1820
1855
  assertCodexThreadAcceptsDirectInput(response.thread);
1821
1856
  knownOwnership = sameOwner ? await consumeCodexAppServerLiveThread(client, effectiveThreadId) : void 0;
@@ -1825,6 +1860,11 @@ async function resumeThread(deps, ctx, pluginConfig, args) {
1825
1860
  if (!retained) throw new Error("Codex resumed thread lost its native subscription owner.");
1826
1861
  if (bindingBeforeCommit && !sameOwner) await releaseCodexAppServerBindingSubscription(bindingBeforeCommit, {
1827
1862
  assertCurrent,
1863
+ withCurrent: async (write) => {
1864
+ await assertCurrentAsync?.();
1865
+ assertCurrent();
1866
+ write();
1867
+ },
1828
1868
  retainedClientId: clientId
1829
1869
  });
1830
1870
  assertCurrent();
@@ -1842,7 +1882,11 @@ async function resumeThread(deps, ctx, pluginConfig, args) {
1842
1882
  modelProvider,
1843
1883
  historyCoveredThrough: (/* @__PURE__ */ new Date()).toISOString()
1844
1884
  }
1845
- }, assertCurrent)) throw new Error("Codex thread binding changed while attaching the resumed thread.");
1885
+ }, composeSessionEntryCommitGuards([
1886
+ assertCurrent,
1887
+ source,
1888
+ ctx.nativePolicySource
1889
+ ]))) throw new Error("Codex thread binding changed while attaching the resumed thread.");
1846
1890
  } catch (error) {
1847
1891
  if (sameOwner && knownOwnership && !retained) {
1848
1892
  if (!await retainCodexAppServerBindingSubscription(client, effectiveThreadId, knownOwnership)) await closeCodexStartupClientBestEffort(client);
@@ -1862,6 +1906,7 @@ async function resumeThread(deps, ctx, pluginConfig, args) {
1862
1906
  sessionId: ctx.sessionId,
1863
1907
  storePath: ctx.sessionTarget?.storePath,
1864
1908
  assertCurrent: assertHostGeneration,
1909
+ assertCurrentAsync: ctx.assertNativePolicyCurrent,
1865
1910
  assertOwnerCurrent: () => assertCodexHostOwnerCurrent(ctx),
1866
1911
  beforeRequest: async (request) => {
1867
1912
  const { thread } = await request({
@@ -1881,10 +1926,10 @@ async function resumeThread(deps, ctx, pluginConfig, args) {
1881
1926
  }
1882
1927
  async function bindCodexCliNodeSession(deps, ctx, parsed) {
1883
1928
  if (!parsed.threadId || !parsed.host || parsed.bindHere !== true) return "Usage: /codex resume <session-id> --host <node> --bind here";
1884
- if (isCurrentSessionModelSelectionLocked(ctx)) return MODEL_SELECTION_LOCKED_MESSAGE;
1929
+ if (await isCurrentSessionModelSelectionLocked(ctx)) return MODEL_SELECTION_LOCKED_MESSAGE;
1885
1930
  if (ctx.sessionId) {
1886
1931
  const scope = resolveCodexConversationControlScope(ctx);
1887
- const binding = deps.bindingStore.read(sessionBindingIdentity({
1932
+ const binding = await deps.bindingStore.readAsync(sessionBindingIdentity({
1888
1933
  sessionId: ctx.sessionId,
1889
1934
  sessionKey: ctx.sessionKey,
1890
1935
  agentId: scope.agentId,
@@ -1907,6 +1952,7 @@ async function bindCodexCliNodeSession(deps, ctx, parsed) {
1907
1952
  cwd: resolved.session?.cwd
1908
1953
  });
1909
1954
  const summary = `Codex CLI session ${formatCodexDisplayText(parsed.threadId)} on ${formatCodexDisplayText(nodeId)}`;
1955
+ await ctx.assertNativePolicyCurrent?.();
1910
1956
  assertCodexHostOwnerCurrent(ctx);
1911
1957
  const request = await ctx.requestConversationBinding({
1912
1958
  summary,
@@ -1936,21 +1982,71 @@ const CODEX_NATIVE_CONTROL_SUBCOMMANDS = /* @__PURE__ */ new Set([
1936
1982
  "unbind",
1937
1983
  "stop"
1938
1984
  ]);
1939
- function resolveCodexNativeCommandSandboxBlock(ctx, subcommand, args) {
1940
- if (isReadOnlyCodexGoalCommand(subcommand, args) || !CODEX_NATIVE_EXECUTION_SUBCOMMANDS.has(subcommand) || returnsBeforeNativeCodexExecution(subcommand, args)) return;
1941
- if (isCodexCliNodeResumeBind(subcommand, args)) return resolveCodexNativeSandboxBlock({
1942
- config: ctx.config,
1943
- sessionKey: ctx.sessionKey,
1944
- sessionId: ctx.sessionId,
1945
- surface: `/${["codex", subcommand].join(" ")}`
1946
- });
1947
- return resolveCodexNativeExecutionBlock({
1948
- config: ctx.config,
1949
- agentId: ctx.agentId,
1950
- sessionKey: ctx.sessionKey,
1951
- sessionId: ctx.sessionId,
1952
- surface: `/${["codex", subcommand].join(" ")}`
1953
- });
1985
+ async function resolveCodexNativeCommandSandboxBlock(ctx, subcommand, args) {
1986
+ if (isReadOnlyCodexGoalCommand(subcommand, args) || returnsBeforeNativeCodexExecution(subcommand, args)) return {
1987
+ block: void 0,
1988
+ async assertCurrent() {},
1989
+ release() {}
1990
+ };
1991
+ const sessionKey = ctx.sessionTarget?.sessionKey ?? ctx.sessionKey;
1992
+ const checksModelLock = [
1993
+ "bind",
1994
+ "resume",
1995
+ "detach",
1996
+ "unbind",
1997
+ "model"
1998
+ ].includes(subcommand);
1999
+ if (!checksModelLock && !CODEX_NATIVE_EXECUTION_SUBCOMMANDS.has(subcommand)) return {
2000
+ block: void 0,
2001
+ async assertCurrent() {},
2002
+ release() {}
2003
+ };
2004
+ const agentId = ctx.sessionTarget?.agentId ?? resolveCodexConversationControlScope(ctx).agentId;
2005
+ const storePath = ctx.sessionTarget?.storePath ?? resolveStorePath(ctx.config.session?.store, { agentId });
2006
+ const modelCurrent = checksModelLock && sessionKey ? await captureSessionEntryCurrentCheckAsync({
2007
+ agentId,
2008
+ storePath,
2009
+ sessionKey,
2010
+ fields: ["modelSelectionLocked"]
2011
+ }) : void 0;
2012
+ if (!CODEX_NATIVE_EXECUTION_SUBCOMMANDS.has(subcommand)) return {
2013
+ block: void 0,
2014
+ assertCurrent: modelCurrent?.assertCurrent ?? (async () => {}),
2015
+ source: modelCurrent?.source,
2016
+ release: modelCurrent?.release ?? (() => {})
2017
+ };
2018
+ let execution;
2019
+ try {
2020
+ const surface = `/${["codex", subcommand].join(" ")}`;
2021
+ execution = isCodexCliNodeResumeBind(subcommand, args) ? await prepareCodexNativeSandboxBlock({
2022
+ config: ctx.config,
2023
+ sessionKey: ctx.sessionKey,
2024
+ sessionId: ctx.sessionId,
2025
+ surface
2026
+ }) : await prepareCodexNativeExecutionBlock({
2027
+ config: ctx.config,
2028
+ agentId: ctx.agentId,
2029
+ sessionKey,
2030
+ sessionId: ctx.sessionId,
2031
+ storePath,
2032
+ surface
2033
+ });
2034
+ } catch (error) {
2035
+ modelCurrent?.release();
2036
+ throw error;
2037
+ }
2038
+ return {
2039
+ block: execution.block,
2040
+ source: composeSessionEntryCommitGuards([modelCurrent?.source, execution.source]),
2041
+ assertCurrent: async () => {
2042
+ await modelCurrent?.assertCurrent();
2043
+ await execution.assertCurrent();
2044
+ },
2045
+ release: () => {
2046
+ modelCurrent?.release();
2047
+ execution.release();
2048
+ }
2049
+ };
1954
2050
  }
1955
2051
  function isReadOnlyCodexGoalCommand(subcommand, args) {
1956
2052
  if (subcommand !== "goal" || args.length > 1) return false;
@@ -2006,6 +2102,7 @@ async function handleNativeGoal(deps, ctx, pluginConfig, args) {
2006
2102
  const action = (args[0] ?? "status").toLowerCase();
2007
2103
  const objective = args.slice(1).join(" ").trim();
2008
2104
  const authority = await resolvePreparedCodexCommandAuthority(deps, ctx);
2105
+ using _ = { [Symbol.dispose]: authority.release };
2009
2106
  const { target, binding } = authority;
2010
2107
  if (!target) return "Cannot manage the Codex goal because this command has no stable binding identity.";
2011
2108
  if (!binding?.threadId) return "No Codex thread is attached to this OpenClaw session yet.";
@@ -2015,7 +2112,8 @@ async function handleNativeGoal(deps, ctx, pluginConfig, args) {
2015
2112
  pluginConfig,
2016
2113
  agentDir: target.agentDir,
2017
2114
  config: ctx.config,
2018
- assertCurrent: authority.assertCurrent
2115
+ assertCurrent: authority.assertCurrent,
2116
+ assertCurrentAsync: authority.assertCurrentAsync
2019
2117
  });
2020
2118
  const goalRequestOptions = {
2021
2119
  agentDir: target.agentDir,
@@ -2025,6 +2123,7 @@ async function handleNativeGoal(deps, ctx, pluginConfig, args) {
2025
2123
  sessionKey: authority.sessionKey,
2026
2124
  storePath: authority.storePath,
2027
2125
  assertCurrent: authority.assertCurrent,
2126
+ assertCurrentAsync: authority.assertCurrentAsync,
2028
2127
  ...connection.usesSupervisionConnection ? { startOptions: connection.appServer.start } : {}
2029
2128
  };
2030
2129
  if (action === "status" || action === "get" || action === "clear") {
@@ -2066,12 +2165,14 @@ function formatNativeGoal(response) {
2066
2165
  }
2067
2166
  async function controlConversationTurn(deps, ctx, command, message) {
2068
2167
  const authority = await resolvePreparedCodexCommandAuthority(deps, ctx);
2168
+ using _ = { [Symbol.dispose]: authority.release };
2069
2169
  const { target, binding } = authority;
2070
2170
  if (!target) return `Cannot ${command} Codex because this command did not include a stable binding identity.`;
2071
2171
  const params = {
2072
2172
  identity: target.identity,
2073
2173
  binding,
2074
- assertCurrent: authority.assertMutationCurrent
2174
+ assertCurrent: authority.assertMutationCurrent,
2175
+ assertCurrentAsync: authority.assertCurrentAsync
2075
2176
  };
2076
2177
  return (command === "stop" ? await deps.stopCodexConversationTurn(params) : await deps.steerCodexConversationTurn({
2077
2178
  ...params,
@@ -2082,12 +2183,13 @@ async function setConversationModel(deps, ctx, args) {
2082
2183
  if (args.length > 1) return "Usage: /codex model <model>";
2083
2184
  const [model = ""] = args;
2084
2185
  const normalized = model.trim();
2085
- if (normalized && isCurrentSessionModelSelectionLocked(ctx)) return MODEL_SELECTION_LOCKED_MESSAGE;
2186
+ if (normalized && await isCurrentSessionModelSelectionLocked(ctx)) return MODEL_SELECTION_LOCKED_MESSAGE;
2086
2187
  const authority = await resolvePreparedCodexCommandAuthority(deps, ctx);
2188
+ using _ = { [Symbol.dispose]: authority.release };
2087
2189
  const { target, binding } = authority;
2088
2190
  if (!target) return "Cannot set Codex model because this command did not include a stable binding identity.";
2089
2191
  if (!normalized) {
2090
- const currentSession = authority.sessionId && authority.sessionKey && authority.storePath ? getSessionEntry({
2192
+ const currentSession = authority.sessionId && authority.sessionKey && authority.storePath ? await getSessionEntryAsync({
2091
2193
  storePath: authority.storePath,
2092
2194
  sessionKey: authority.sessionKey,
2093
2195
  hydrateSkillPromptRefs: false,
@@ -2107,13 +2209,15 @@ async function setConversationModel(deps, ctx, args) {
2107
2209
  binding,
2108
2210
  storePath: authority.storePath,
2109
2211
  assertCurrent: authority.assertCurrent,
2110
- assertCommitAllowed: authority.assertMutationCurrent
2212
+ assertCurrentAsync: authority.assertCurrentAsync,
2213
+ assertCommitAllowed: composeSessionEntryCommitGuards([authority.mutationSource, authority.assertMutationCurrent])
2111
2214
  });
2112
2215
  }
2113
2216
  async function setConversationPreference(deps, ctx, args, kind) {
2114
2217
  const usage = `Usage: /codex ${kind} ${kind === "fast" ? "[on|off|status]" : "[default|yolo|status]"}`;
2115
2218
  if (args.length > 1) return usage;
2116
2219
  const authority = await resolvePreparedCodexCommandAuthority(deps, ctx);
2220
+ using _ = { [Symbol.dispose]: authority.release };
2117
2221
  const { target, binding } = authority;
2118
2222
  if (kind === "fast") {
2119
2223
  if (!target) return "Cannot set Codex fast mode because this command did not include a stable binding identity.";
@@ -2125,7 +2229,7 @@ async function setConversationPreference(deps, ctx, args, kind) {
2125
2229
  bindingStore: deps.bindingStore,
2126
2230
  binding,
2127
2231
  enabled: parsed,
2128
- assertCurrent: parsed === void 0 ? authority.assertCurrent : authority.assertMutationCurrent
2232
+ assertCurrent: parsed === void 0 ? authority.assertCurrent : composeSessionEntryCommitGuards([authority.mutationSource, authority.assertMutationCurrent])
2129
2233
  });
2130
2234
  }
2131
2235
  if (!target || !ctx.sessionId || !ctx.sessionKey) return "Cannot set Codex permissions because this command did not include a complete session identity.";
@@ -2138,6 +2242,7 @@ async function setConversationPreference(deps, ctx, args, kind) {
2138
2242
  config: ctx.config,
2139
2243
  storePath: authority.storePath,
2140
2244
  assertCurrent: parsed ? authority.assertHostMutationCurrent : authority.assertHostCurrent,
2245
+ sourceAuthority: parsed ? composeSessionEntryCommitGuards([authority.mutationSource, authority.assertHostMutationCurrent]) : void 0,
2141
2246
  session: {
2142
2247
  agentId: target.agentId,
2143
2248
  sessionId: ctx.sessionId,
@@ -2148,13 +2253,14 @@ async function setConversationPreference(deps, ctx, args, kind) {
2148
2253
  async function startThreadAction(deps, ctx, pluginConfig, kind, args) {
2149
2254
  if (args.length > 0) return `Usage: /codex ${kind}`;
2150
2255
  const authority = await resolvePreparedCodexCommandAuthority(deps, ctx);
2256
+ using _ = { [Symbol.dispose]: authority.release };
2151
2257
  const { target, binding } = authority;
2152
2258
  if (!target) return `Cannot start Codex ${kind === "compact" ? "compaction" : "review"} because this command did not include a stable binding identity.`;
2153
2259
  if (!binding?.threadId) return `No Codex thread is attached to this OpenClaw session yet.`;
2154
2260
  if (kind === "compact") {
2155
2261
  const sessionTarget = ctx.sessionTarget;
2156
2262
  if (!ctx.sessionId || !ctx.sessionKey || !sessionTarget || sessionTarget.sessionId !== ctx.sessionId || sessionTarget.sessionKey !== ctx.sessionKey) return "Codex compaction is unavailable because this command is not bound to a complete session identity.";
2157
- const currentSession = getSessionEntry({
2263
+ const currentSession = await getSessionEntryAsync({
2158
2264
  storePath: authority.storePath ?? sessionTarget.storePath,
2159
2265
  sessionKey: ctx.sessionKey,
2160
2266
  hydrateSkillPromptRefs: false,
@@ -2166,6 +2272,7 @@ async function startThreadAction(deps, ctx, pluginConfig, kind, args) {
2166
2272
  }
2167
2273
  const compactCurrent = ctx.runtimeContext?.compactCurrent;
2168
2274
  if (!compactCurrent) return "Codex compaction is unavailable because this command is not bound to a session.";
2275
+ await authority.assertCurrentAsync();
2169
2276
  authority.assertMutationCurrent();
2170
2277
  const result = await compactCurrent();
2171
2278
  return result.compacted ? `Compacted Codex session (${result.tokensAfter ?? "unknown"} tokens after).` : `Codex compaction did not complete: ${formatCodexDisplayText(result.reason ?? "no reason returned")}.`;
@@ -2176,7 +2283,8 @@ async function startThreadAction(deps, ctx, pluginConfig, kind, args) {
2176
2283
  pluginConfig,
2177
2284
  agentDir: target.agentDir,
2178
2285
  config: ctx.config,
2179
- assertCurrent: authority.assertCurrent
2286
+ assertCurrent: authority.assertCurrent,
2287
+ assertCurrentAsync: authority.assertCurrentAsync
2180
2288
  });
2181
2289
  await deps.bindingStore.withLease(target.identity, () => deps.codexControlRequest(pluginConfig, CODEX_CONTROL_METHODS.review, {
2182
2290
  threadId: binding.threadId,
@@ -2189,6 +2297,7 @@ async function startThreadAction(deps, ctx, pluginConfig, kind, args) {
2189
2297
  sessionKey: authority.sessionKey,
2190
2298
  storePath: authority.storePath,
2191
2299
  assertCurrent: authority.assertCurrent,
2300
+ assertCurrentAsync: authority.assertCurrentAsync,
2192
2301
  assertOwnerCurrent: () => assertCodexHostOwnerCurrent(ctx),
2193
2302
  ...connection.usesSupervisionConnection ? {
2194
2303
  startOptions: connection.appServer.start,
@@ -2613,8 +2722,8 @@ async function withCodexPluginCommandContext(params, run) {
2613
2722
  gatewayClientScopes: params.ctx.gatewayClientScopes?.slice()
2614
2723
  };
2615
2724
  const current = await deps.codexPluginsManagementIo?.readConfig() ?? {};
2616
- const initialPolicy = JSON.stringify(current);
2617
- const { scope, target, binding } = await resolveCommandAppServerContext(deps, ctx, pluginConfig);
2725
+ const { scope, binding } = await resolveCommandAppServerContext(deps, ctx, pluginConfig);
2726
+ using _ = { [Symbol.dispose]: scope.release };
2618
2727
  const conversation = readCodexConversationBindingData(await ctx.getCurrentConversationBinding());
2619
2728
  const workspaceDir = binding?.cwd || (conversation?.kind === "codex-app-server-session" ? conversation.workspaceDir : void 0) || resolveAgentWorkspaceDir(ctx.config, scope.agentId);
2620
2729
  const configuredRuntime = resolveCodexAppServerRuntimeOptions({ pluginConfig });
@@ -2626,102 +2735,108 @@ async function withCodexPluginCommandContext(params, run) {
2626
2735
  ...scope,
2627
2736
  config: ctx.config
2628
2737
  }, appServer.start);
2629
- const preparedAuth = "preparedAuth" in auth.clientOptions ? auth.clientOptions.preparedAuth : void 0;
2630
- const usesNativeAuth = scope.authProfileId === null || appServer.start.homeScope === "user";
2631
- const profileId = usesNativeAuth ? void 0 : auth.authProfileId;
2632
- const readAuthBinding = () => profileId ? fingerprintCodexAppServerAuthBinding({
2633
- authProfileId: profileId,
2634
- authProfileStore: resolveCodexAppServerAuthProfileStore({
2738
+ try {
2739
+ const { assertCurrentAsync } = {
2740
+ assertCurrentAsync: scope.assertCurrentAsync,
2741
+ ...auth.clientOptions
2742
+ };
2743
+ const preparedAuth = "preparedAuth" in auth.clientOptions ? auth.clientOptions.preparedAuth : void 0;
2744
+ const usesNativeAuth = scope.authProfileId === null || appServer.start.homeScope === "user";
2745
+ const profileId = usesNativeAuth ? void 0 : auth.authProfileId;
2746
+ const readAuthBinding = async () => profileId ? fingerprintCodexAppServerAuthBinding({
2747
+ authProfileId: profileId,
2748
+ authProfileStore: await resolveCodexAppServerAuthProfileStore({
2749
+ authProfileId: profileId,
2750
+ agentDir: scope.agentDir,
2751
+ config: ctx.config
2752
+ }),
2753
+ agentDir: scope.agentDir,
2754
+ config: ctx.config
2755
+ }) : Promise.resolve(void 0);
2756
+ const authBinding = "authBindingFingerprint" in auth.clientOptions ? auth.clientOptions.authBindingFingerprint : await readAuthBinding();
2757
+ const accountId = usesNativeAuth ? void 0 : preparedAuth?.kind === "api-key" ? resolveCodexAppServerPreparedApiKeyCacheKey(preparedAuth.apiKey) : preparedAuth?.kind === "profile" ? preparedAuth.snapshot.secretFreeCacheKey : await resolveCodexAppServerAuthAccountCacheKey({
2635
2758
  authProfileId: profileId,
2636
2759
  agentDir: scope.agentDir,
2637
2760
  config: ctx.config
2638
- }),
2639
- agentDir: scope.agentDir,
2640
- config: ctx.config
2641
- }) : Promise.resolve(void 0);
2642
- const authBinding = "authBindingFingerprint" in auth.clientOptions ? auth.clientOptions.authBindingFingerprint : await readAuthBinding();
2643
- const accountId = usesNativeAuth ? void 0 : preparedAuth?.kind === "api-key" ? resolveCodexAppServerPreparedApiKeyCacheKey(preparedAuth.apiKey) : preparedAuth?.kind === "profile" ? preparedAuth.snapshot.secretFreeCacheKey : await resolveCodexAppServerAuthAccountCacheKey({
2644
- authProfileId: profileId,
2645
- agentDir: scope.agentDir,
2646
- config: ctx.config
2647
- });
2648
- if (await readAuthBinding() !== authBinding) throw new Error(SCOPE_CHANGED_MESSAGE);
2649
- return await withCodexAppServerJsonClient({
2650
- startOptions: appServer.start,
2651
- pluginConfig,
2652
- agentDir: scope.agentDir,
2653
- config: ctx.config,
2654
- sessionId: ctx.sessionId,
2655
- sessionKey: ctx.sessionKey,
2656
- timeoutMs: appServer.requestTimeoutMs,
2657
- timeoutMessage: "Codex plugin request timed out. Check the Codex connection and retry.",
2658
- assertCurrent: scope.assertCurrent,
2659
- ...auth.clientOptions
2660
- }, async (request, client, requestScope) => {
2661
- const assertCurrent = () => {
2662
- requestScope.assertCurrent();
2663
- if (client.getCloseError()) throw new Error(SCOPE_CHANGED_MESSAGE);
2664
- };
2665
- const validateCurrent = async () => {
2666
- assertCurrent();
2667
- const currentTarget = await resolveControlTarget(ctx);
2668
- const currentConversation = readCodexConversationBindingData(await ctx.getCurrentConversationBinding());
2669
- const currentPolicy = JSON.stringify(await deps.codexPluginsManagementIo?.readConfig() ?? {});
2670
- const currentAuthBinding = await readAuthBinding();
2671
- assertCurrent();
2672
- if (!isDeepStrictEqual(currentTarget, target) || !isDeepStrictEqual(currentConversation, conversation) || currentPolicy !== initialPolicy || currentAuthBinding !== authBinding) throw new Error(SCOPE_CHANGED_MESSAGE);
2673
- };
2674
- try {
2675
- await request({
2676
- method: "account/read",
2677
- requestParams: { refreshToken: false },
2678
- assertCurrent
2679
- });
2680
- } catch {
2681
- requestScope.assertCurrent();
2682
- throw new Error("Codex account startup could not be confirmed. Check /codex account and retry.");
2683
- }
2684
- const unsubscribe = client.addNotificationHandler((notification) => {
2685
- if (notification.method === "account/updated") requestScope.abort(/* @__PURE__ */ new Error(SCOPE_CHANGED_MESSAGE));
2686
2761
  });
2687
- try {
2688
- await validateCurrent();
2689
- const result = await run({
2690
- request: async (method, requestParams) => {
2691
- await validateCurrent();
2692
- const response = await request({
2693
- method,
2694
- requestParams,
2695
- assertCurrent: () => {
2696
- assertCurrent();
2697
- assertCodexHostOwnerCurrent(ctx);
2698
- }
2699
- });
2700
- await validateCurrent();
2701
- return response;
2702
- },
2703
- workspaceDir,
2704
- agentId: scope.agentId,
2705
- current,
2706
- ...profileId ? { profileId } : {},
2707
- ...binding?.clientId === client.getInstanceId() ? { threadId: binding.threadId } : {},
2708
- appCacheKey: buildCodexPluginAppCacheKey({
2709
- appServer,
2710
- agentDir: scope.agentDir,
2711
- authProfileId: profileId,
2712
- accountId,
2713
- envApiKeyFingerprint: usesNativeAuth || preparedAuth || profileId ? void 0 : resolveCodexAppServerFallbackApiKeyCacheKey({ startOptions: appServer.start }),
2714
- appServerVersion: client.getServerVersion(),
2715
- runtimeIdentity: client.getRuntimeIdentity()
2716
- }),
2717
- validateCurrent
2762
+ if (await readAuthBinding() !== authBinding) throw new Error(SCOPE_CHANGED_MESSAGE);
2763
+ return await withCodexAppServerJsonClient({
2764
+ startOptions: appServer.start,
2765
+ pluginConfig,
2766
+ agentDir: scope.agentDir,
2767
+ config: ctx.config,
2768
+ sessionId: ctx.sessionId,
2769
+ sessionKey: ctx.sessionKey,
2770
+ timeoutMs: appServer.requestTimeoutMs,
2771
+ timeoutMessage: "Codex plugin request timed out. Check the Codex connection and retry.",
2772
+ assertCurrent: scope.assertCurrent,
2773
+ ...auth.clientOptions
2774
+ }, async (request, client, requestScope) => {
2775
+ const assertCurrent = () => {
2776
+ requestScope.assertCurrent();
2777
+ if (client.getCloseError()) throw new Error(SCOPE_CHANGED_MESSAGE);
2778
+ };
2779
+ const validateCurrent = async () => {
2780
+ assertCurrent();
2781
+ const currentAuthBinding = await readAuthBinding();
2782
+ await assertCurrentAsync?.();
2783
+ assertCurrent();
2784
+ if (currentAuthBinding !== authBinding) throw new Error(SCOPE_CHANGED_MESSAGE);
2785
+ };
2786
+ try {
2787
+ await request({
2788
+ method: "account/read",
2789
+ requestParams: { refreshToken: false },
2790
+ assertCurrent
2791
+ });
2792
+ } catch {
2793
+ requestScope.assertCurrent();
2794
+ throw new Error("Codex account startup could not be confirmed. Check /codex account and retry.");
2795
+ }
2796
+ const unsubscribe = client.addNotificationHandler((notification) => {
2797
+ if (notification.method === "account/updated") requestScope.abort(/* @__PURE__ */ new Error(SCOPE_CHANGED_MESSAGE));
2718
2798
  });
2719
- await validateCurrent();
2720
- return result;
2721
- } finally {
2722
- unsubscribe();
2723
- }
2724
- });
2799
+ try {
2800
+ await validateCurrent();
2801
+ const result = await run({
2802
+ request: async (method, requestParams) => {
2803
+ await validateCurrent();
2804
+ const response = await request({
2805
+ method,
2806
+ requestParams,
2807
+ assertCurrent: () => {
2808
+ assertCurrent();
2809
+ assertCodexHostOwnerCurrent(ctx);
2810
+ }
2811
+ });
2812
+ await validateCurrent();
2813
+ return response;
2814
+ },
2815
+ workspaceDir,
2816
+ agentId: scope.agentId,
2817
+ current,
2818
+ ...profileId ? { profileId } : {},
2819
+ ...binding?.clientId === client.getInstanceId() ? { threadId: binding.threadId } : {},
2820
+ appCacheKey: buildCodexPluginAppCacheKey({
2821
+ appServer,
2822
+ agentDir: scope.agentDir,
2823
+ authProfileId: profileId,
2824
+ accountId,
2825
+ envApiKeyFingerprint: usesNativeAuth || preparedAuth || profileId ? void 0 : resolveCodexAppServerFallbackApiKeyCacheKey({ startOptions: appServer.start }),
2826
+ appServerVersion: client.getServerVersion(),
2827
+ runtimeIdentity: client.getRuntimeIdentity()
2828
+ }),
2829
+ validateCurrent
2830
+ });
2831
+ await validateCurrent();
2832
+ return result;
2833
+ } finally {
2834
+ unsubscribe();
2835
+ }
2836
+ });
2837
+ } finally {
2838
+ auth.release();
2839
+ }
2725
2840
  }
2726
2841
  //#endregion
2727
2842
  //#region extensions/codex/src/command-handlers.ts
@@ -2733,168 +2848,186 @@ const CODEX_HOST_INSPECTION_SUBCOMMANDS = /* @__PURE__ */ new Set([
2733
2848
  "status",
2734
2849
  "threads"
2735
2850
  ]);
2736
- async function handleCodexSubcommand(ctx, options) {
2851
+ async function handleCodexSubcommand(inputCtx, options) {
2737
2852
  const deps = resolveCodexCommandDeps(options.deps);
2738
- const args = splitArgs(ctx.args);
2853
+ const args = splitArgs(inputCtx.args);
2739
2854
  if (args.length === 0) return buildCodexSubcommandPickerReply();
2740
2855
  const [subcommand = "status", ...rest] = args;
2741
2856
  const normalized = subcommand.toLowerCase();
2742
2857
  if (normalized === "help") return { text: buildHelp() };
2743
- if (CODEX_HOST_INSPECTION_SUBCOMMANDS.has(normalized) && !canMutateCodexHost(ctx)) return { text: CODEX_HOST_INSPECTION_AUTH_ERROR };
2744
- if (CODEX_NATIVE_CONTROL_SUBCOMMANDS.has(normalized) && !returnsBeforeNativeCodexExecution(normalized, rest) && !isReadOnlyCodexGoalCommand(normalized, rest) && !canMutateCodexHost(ctx)) return { text: CODEX_NATIVE_EXECUTION_AUTH_ERROR };
2745
- const sandboxBlock = resolveCodexNativeCommandSandboxBlock(ctx, normalized, rest);
2746
- if (sandboxBlock) return { text: sandboxBlock };
2747
- const usageCommand = normalized === "unbind" ? "detach" : normalized;
2748
- if (rest.length > 0 && [
2749
- "status",
2750
- "models",
2751
- "detach",
2752
- "binding",
2753
- "stop",
2754
- "mcp",
2755
- "skills",
2756
- "account"
2757
- ].includes(usageCommand)) return { text: `Usage: /codex ${usageCommand}` };
2758
- if (normalized === "plugins") {
2759
- if (rest[0]?.toLowerCase() === "refresh") {
2760
- if (rest.length !== 1) return { text: "Usage: /codex plugins refresh — refresh hosted app inventory for the current Codex account/runtime." };
2761
- if (!canMutateCodexHost(ctx)) return { text: "Only an owner or operator.admin gateway client can refresh hosted app inventory." };
2762
- return await withCodexPluginCommandContext({
2763
- deps,
2764
- ctx,
2765
- pluginConfig: options.pluginConfig
2766
- }, (context) => refreshCodexHostedApps(context));
2767
- }
2768
- if (!deps.codexPluginsManagementIo) return { text: "Codex sub-plugin management is not wired up (codexPluginsManagementIo dep is undefined). Edit ~/.openclaw/openclaw.json or use `openclaw config patch` until the runtime exposes the IO." };
2769
- let appServerScope;
2770
- const getAppServerScope = () => appServerScope ??= resolveCommandAppServerScope(deps, ctx, options.pluginConfig);
2771
- return await handleCodexPluginsSubcommand(ctx, rest, deps.codexPluginsManagementIo, {
2772
- withContext: (run) => withCodexPluginCommandContext({
2773
- deps,
2774
- ctx,
2775
- pluginConfig: options.pluginConfig
2776
- }, run),
2777
- workspaceDir: async () => {
2778
- const data = readCodexConversationBindingData(await ctx.getCurrentConversationBinding());
2779
- return (data?.kind === "codex-app-server-session" ? data.workspaceDir : void 0)?.trim() || deps.resolveCodexDefaultWorkspaceDir(options.pluginConfig);
2780
- },
2781
- list: async (requestParams) => {
2782
- const scope = await getAppServerScope();
2783
- return await deps.codexControlRequest(options.pluginConfig, CODEX_CONTROL_METHODS.listPlugins, requestParams, {
2784
- ...scope,
2785
- config: ctx.config
2786
- });
2787
- },
2788
- install: async (requestParams) => {
2789
- const scope = await getAppServerScope();
2790
- return await deps.codexControlRequest(options.pluginConfig, CODEX_CONTROL_METHODS.installPlugin, requestParams, {
2791
- ...scope,
2792
- config: ctx.config,
2793
- assertOwnerCurrent: () => assertCodexHostOwnerCurrent(ctx)
2794
- });
2795
- },
2796
- refresh: async (workspaceDir) => {
2797
- const scope = await getAppServerScope();
2798
- const configuredAppServer = resolveCodexAppServerRuntimeOptions({ pluginConfig: options.pluginConfig });
2799
- const appServer = scope.startOptions ? {
2800
- ...configuredAppServer,
2801
- start: scope.startOptions
2802
- } : configuredAppServer;
2803
- const authProfileId = scope.authProfileId ?? void 0;
2804
- const accountId = await resolveCodexAppServerAuthAccountCacheKey({
2805
- authProfileId,
2806
- agentDir: scope.agentDir,
2807
- config: ctx.config
2808
- });
2809
- const client = await getLeasedSharedCodexAppServerClient({
2810
- startOptions: appServer.start,
2811
- pluginConfig: options.pluginConfig,
2812
- authProfileId: scope.authProfileId,
2813
- agentDir: scope.agentDir,
2814
- config: ctx.config
2815
- });
2816
- try {
2817
- const appCacheKey = buildCodexPluginAppCacheKey({
2818
- appServer,
2819
- agentDir: scope.agentDir,
2858
+ if (CODEX_HOST_INSPECTION_SUBCOMMANDS.has(normalized) && !canMutateCodexHost(inputCtx)) return { text: CODEX_HOST_INSPECTION_AUTH_ERROR };
2859
+ if (CODEX_NATIVE_CONTROL_SUBCOMMANDS.has(normalized) && !returnsBeforeNativeCodexExecution(normalized, rest) && !isReadOnlyCodexGoalCommand(normalized, rest) && !canMutateCodexHost(inputCtx)) return { text: CODEX_NATIVE_EXECUTION_AUTH_ERROR };
2860
+ const nativePolicy = await resolveCodexNativeCommandSandboxBlock(inputCtx, normalized, rest);
2861
+ try {
2862
+ if (nativePolicy.block) return { text: nativePolicy.block };
2863
+ const previousPolicyCheck = inputCtx.assertNativePolicyCurrent;
2864
+ const ctx = {
2865
+ ...inputCtx,
2866
+ nativePolicySource: nativePolicy.source,
2867
+ assertNativePolicyCurrent: async () => {
2868
+ await previousPolicyCheck?.();
2869
+ await nativePolicy.assertCurrent();
2870
+ }
2871
+ };
2872
+ const usageCommand = normalized === "unbind" ? "detach" : normalized;
2873
+ if (rest.length > 0 && [
2874
+ "status",
2875
+ "models",
2876
+ "detach",
2877
+ "binding",
2878
+ "stop",
2879
+ "mcp",
2880
+ "skills",
2881
+ "account"
2882
+ ].includes(usageCommand)) return { text: `Usage: /codex ${usageCommand}` };
2883
+ if (normalized === "plugins") {
2884
+ if (rest[0]?.toLowerCase() === "refresh") {
2885
+ if (rest.length !== 1) return { text: "Usage: /codex plugins refresh — refresh hosted app inventory for the current Codex account/runtime." };
2886
+ if (!canMutateCodexHost(ctx)) return { text: "Only an owner or operator.admin gateway client can refresh hosted app inventory." };
2887
+ return await withCodexPluginCommandContext({
2888
+ deps,
2889
+ ctx,
2890
+ pluginConfig: options.pluginConfig
2891
+ }, (context) => refreshCodexHostedApps(context));
2892
+ }
2893
+ if (!deps.codexPluginsManagementIo) return { text: "Codex sub-plugin management is not wired up (codexPluginsManagementIo dep is undefined). Edit ~/.openclaw/openclaw.json or use `openclaw config patch` until the runtime exposes the IO." };
2894
+ let appServerScope;
2895
+ await using _ = { [Symbol.asyncDispose]: async () => {
2896
+ await appServerScope?.then((scope) => scope.release(), () => {});
2897
+ } };
2898
+ const getAppServerScope = () => appServerScope ??= resolveCommandAppServerScope(deps, ctx, options.pluginConfig);
2899
+ return await handleCodexPluginsSubcommand(ctx, rest, deps.codexPluginsManagementIo, {
2900
+ withContext: (run) => withCodexPluginCommandContext({
2901
+ deps,
2902
+ ctx,
2903
+ pluginConfig: options.pluginConfig
2904
+ }, run),
2905
+ workspaceDir: async () => {
2906
+ const data = readCodexConversationBindingData(await ctx.getCurrentConversationBinding());
2907
+ return (data?.kind === "codex-app-server-session" ? data.workspaceDir : void 0)?.trim() || deps.resolveCodexDefaultWorkspaceDir(options.pluginConfig);
2908
+ },
2909
+ list: async (requestParams) => {
2910
+ const scope = await getAppServerScope();
2911
+ return await deps.codexControlRequest(options.pluginConfig, CODEX_CONTROL_METHODS.listPlugins, requestParams, {
2912
+ ...scope,
2913
+ config: ctx.config
2914
+ });
2915
+ },
2916
+ install: async (requestParams) => {
2917
+ const scope = await getAppServerScope();
2918
+ return await deps.codexControlRequest(options.pluginConfig, CODEX_CONTROL_METHODS.installPlugin, requestParams, {
2919
+ ...scope,
2920
+ config: ctx.config,
2921
+ assertOwnerCurrent: () => assertCodexHostOwnerCurrent(ctx)
2922
+ });
2923
+ },
2924
+ refresh: async (workspaceDir) => {
2925
+ const scope = await getAppServerScope();
2926
+ const configuredAppServer = resolveCodexAppServerRuntimeOptions({ pluginConfig: options.pluginConfig });
2927
+ const appServer = scope.startOptions ? {
2928
+ ...configuredAppServer,
2929
+ start: scope.startOptions
2930
+ } : configuredAppServer;
2931
+ const authProfileId = scope.authProfileId ?? void 0;
2932
+ const accountId = await resolveCodexAppServerAuthAccountCacheKey({
2820
2933
  authProfileId,
2821
- accountId,
2822
- envApiKeyFingerprint: authProfileId ? void 0 : resolveCodexAppServerFallbackApiKeyCacheKey({ startOptions: appServer.start }),
2823
- appServerVersion: client.getServerVersion(),
2824
- runtimeIdentity: client.getRuntimeIdentity()
2934
+ agentDir: scope.agentDir,
2935
+ config: ctx.config
2825
2936
  });
2826
- return await refreshCodexPluginRuntimeState({
2827
- configCwd: workspaceDir,
2828
- appCache: defaultCodexAppInventoryCache,
2829
- appCacheKey,
2830
- metadataCache: defaultCodexPluginMetadataCache,
2831
- request: async (method, requestParams) => {
2832
- const requestMethod = resolvePluginRuntimeRefreshMethod(method);
2833
- return await deps.codexControlRequest(options.pluginConfig, requestMethod, requestParams, {
2834
- ...scope,
2835
- config: ctx.config
2836
- });
2837
- }
2937
+ const client = await getLeasedSharedCodexAppServerClient({
2938
+ startOptions: appServer.start,
2939
+ pluginConfig: options.pluginConfig,
2940
+ authProfileId: scope.authProfileId,
2941
+ agentDir: scope.agentDir,
2942
+ config: ctx.config
2838
2943
  });
2839
- } finally {
2840
- releaseLeasedSharedCodexAppServerClient(client);
2944
+ try {
2945
+ const appCacheKey = buildCodexPluginAppCacheKey({
2946
+ appServer,
2947
+ agentDir: scope.agentDir,
2948
+ authProfileId,
2949
+ accountId,
2950
+ envApiKeyFingerprint: authProfileId ? void 0 : resolveCodexAppServerFallbackApiKeyCacheKey({ startOptions: appServer.start }),
2951
+ appServerVersion: client.getServerVersion(),
2952
+ runtimeIdentity: client.getRuntimeIdentity()
2953
+ });
2954
+ return await refreshCodexPluginRuntimeState({
2955
+ configCwd: workspaceDir,
2956
+ appCache: defaultCodexAppInventoryCache,
2957
+ appCacheKey,
2958
+ metadataCache: defaultCodexPluginMetadataCache,
2959
+ request: async (method, requestParams) => {
2960
+ const requestMethod = resolvePluginRuntimeRefreshMethod(method);
2961
+ return await deps.codexControlRequest(options.pluginConfig, requestMethod, requestParams, {
2962
+ ...scope,
2963
+ config: ctx.config
2964
+ });
2965
+ }
2966
+ });
2967
+ } finally {
2968
+ releaseLeasedSharedCodexAppServerClient(client);
2969
+ }
2841
2970
  }
2842
- }
2843
- });
2844
- }
2845
- if (normalized === "status") {
2846
- const { agentDir } = resolveCodexConversationControlScope(ctx);
2847
- return { text: formatCodexStatus(await deps.readCodexStatusProbes(options.pluginConfig, ctx.config, agentDir)) };
2848
- }
2849
- if (normalized === "models") {
2850
- const { agentDir } = resolveCodexConversationControlScope(ctx);
2851
- return { text: formatModels(await deps.listCodexAppServerModels(deps.requestOptions(options.pluginConfig, 100, ctx.config, agentDir))) };
2852
- }
2853
- if (normalized === "threads") return { text: await buildThreads(deps, ctx, options.pluginConfig, rest.join(" ")) };
2854
- if (normalized === "goal") return { text: await handleNativeGoal(deps, ctx, options.pluginConfig, rest) };
2855
- if (normalized === "sessions") return { text: await buildCodexCliSessions(deps, rest) };
2856
- if (normalized === "resume") return { text: await resumeThread(deps, ctx, options.pluginConfig, rest) };
2857
- if (normalized === "bind") return await bindConversation(deps, ctx, options.pluginConfig, rest);
2858
- if (normalized === "detach" || normalized === "unbind") return { text: await detachConversation(deps, ctx) };
2859
- if (normalized === "binding") return { text: await describeConversationBinding(deps, ctx) };
2860
- if (normalized === "stop" || normalized === "steer") return { text: await controlConversationTurn(deps, ctx, normalized, rest.join(" ")) };
2861
- if (normalized === "model") return { text: await setConversationModel(deps, ctx, rest) };
2862
- if (normalized === "fast" || normalized === "permissions") {
2863
- if (isMenuVerb(rest)) return buildCodexChoiceMenuReply(normalized);
2864
- return { text: await setConversationPreference(deps, ctx, rest, normalized) };
2865
- }
2866
- if (normalized === "compact" || normalized === "review") return { text: await startThreadAction(deps, ctx, options.pluginConfig, normalized, rest) };
2867
- if (normalized === "diagnostics") return await handleCodexDiagnosticsFeedback(deps, ctx, options.pluginConfig, rest.join(" "));
2868
- if (normalized === "computer-use" || normalized === "computeruse") {
2869
- if (isMenuVerb(rest)) return buildCodexChoiceMenuReply("computer-use");
2870
- return { text: await handleComputerUseCommand(deps, ctx, options.pluginConfig, rest) };
2871
- }
2872
- if (normalized === "mcp" || normalized === "skills") {
2873
- const scope = await resolveCommandAppServerScope(deps, ctx, options.pluginConfig);
2874
- const response = await deps.codexControlRequest(options.pluginConfig, normalized === "mcp" ? CODEX_CONTROL_METHODS.listMcpServers : CODEX_CONTROL_METHODS.listSkills, normalized === "mcp" ? { limit: 100 } : {}, {
2875
- config: ctx.config,
2876
- ...scope
2877
- });
2878
- return { text: normalized === "mcp" ? formatList(response, "MCP servers") : formatSkills(response) };
2879
- }
2880
- if (normalized === "account") {
2881
- const scope = await resolveCommandAppServerScope(deps, ctx, options.pluginConfig);
2882
- const requestScope = {
2883
- config: ctx.config,
2884
- ...scope
2885
- };
2886
- const [account, limits] = await Promise.all([deps.safeCodexControlRequest(options.pluginConfig, CODEX_CONTROL_METHODS.account, { refreshToken: false }, requestScope), deps.safeCodexControlRequest(options.pluginConfig, CODEX_CONTROL_METHODS.rateLimits, void 0, requestScope)]);
2887
- return { text: formatAccount(account, limits, await readCodexAccountAuthOverview({
2888
- ctx,
2889
- agentDir: scope.agentDir,
2890
- authProfileId: scope.authProfileId,
2891
- pluginConfig: options.pluginConfig,
2892
- safeCodexControlRequest: deps.safeCodexControlRequest,
2893
- account,
2894
- limits
2895
- })) };
2971
+ });
2972
+ }
2973
+ if (normalized === "status") {
2974
+ const { agentDir } = resolveCodexConversationControlScope(ctx);
2975
+ return { text: formatCodexStatus(await deps.readCodexStatusProbes(options.pluginConfig, ctx.config, agentDir)) };
2976
+ }
2977
+ if (normalized === "models") {
2978
+ const { agentDir } = resolveCodexConversationControlScope(ctx);
2979
+ return { text: formatModels(await deps.listCodexAppServerModels(deps.requestOptions(options.pluginConfig, 100, ctx.config, agentDir))) };
2980
+ }
2981
+ if (normalized === "threads") return { text: await buildThreads(deps, ctx, options.pluginConfig, rest.join(" ")) };
2982
+ if (normalized === "goal") return { text: await handleNativeGoal(deps, ctx, options.pluginConfig, rest) };
2983
+ if (normalized === "sessions") return { text: await buildCodexCliSessions(deps, rest) };
2984
+ if (normalized === "resume") return { text: await resumeThread(deps, ctx, options.pluginConfig, rest) };
2985
+ if (normalized === "bind") return await bindConversation(deps, ctx, options.pluginConfig, rest);
2986
+ if (normalized === "detach" || normalized === "unbind") return { text: await detachConversation(deps, ctx) };
2987
+ if (normalized === "binding") return { text: await describeConversationBinding(deps, ctx) };
2988
+ if (normalized === "stop" || normalized === "steer") return { text: await controlConversationTurn(deps, ctx, normalized, rest.join(" ")) };
2989
+ if (normalized === "model") return { text: await setConversationModel(deps, ctx, rest) };
2990
+ if (normalized === "fast" || normalized === "permissions") {
2991
+ if (isMenuVerb(rest)) return buildCodexChoiceMenuReply(normalized);
2992
+ return { text: await setConversationPreference(deps, ctx, rest, normalized) };
2993
+ }
2994
+ if (normalized === "compact" || normalized === "review") return { text: await startThreadAction(deps, ctx, options.pluginConfig, normalized, rest) };
2995
+ if (normalized === "diagnostics") return await handleCodexDiagnosticsFeedback(deps, ctx, options.pluginConfig, rest.join(" "));
2996
+ if (normalized === "computer-use" || normalized === "computeruse") {
2997
+ if (isMenuVerb(rest)) return buildCodexChoiceMenuReply("computer-use");
2998
+ return { text: await handleComputerUseCommand(deps, ctx, options.pluginConfig, rest) };
2999
+ }
3000
+ if (normalized === "mcp" || normalized === "skills") {
3001
+ const scope = await resolveCommandAppServerScope(deps, ctx, options.pluginConfig);
3002
+ using _ = { [Symbol.dispose]: scope.release };
3003
+ const response = await deps.codexControlRequest(options.pluginConfig, normalized === "mcp" ? CODEX_CONTROL_METHODS.listMcpServers : CODEX_CONTROL_METHODS.listSkills, normalized === "mcp" ? { limit: 100 } : {}, {
3004
+ config: ctx.config,
3005
+ ...scope
3006
+ });
3007
+ return { text: normalized === "mcp" ? formatList(response, "MCP servers") : formatSkills(response) };
3008
+ }
3009
+ if (normalized === "account") {
3010
+ const scope = await resolveCommandAppServerScope(deps, ctx, options.pluginConfig);
3011
+ using _ = { [Symbol.dispose]: scope.release };
3012
+ const requestScope = {
3013
+ config: ctx.config,
3014
+ ...scope
3015
+ };
3016
+ const [account, limits] = await Promise.all([deps.safeCodexControlRequest(options.pluginConfig, CODEX_CONTROL_METHODS.account, { refreshToken: false }, requestScope), deps.safeCodexControlRequest(options.pluginConfig, CODEX_CONTROL_METHODS.rateLimits, void 0, requestScope)]);
3017
+ return { text: formatAccount(account, limits, await readCodexAccountAuthOverview({
3018
+ ctx,
3019
+ agentDir: scope.agentDir,
3020
+ authProfileId: scope.authProfileId,
3021
+ pluginConfig: options.pluginConfig,
3022
+ safeCodexControlRequest: deps.safeCodexControlRequest,
3023
+ account,
3024
+ limits
3025
+ })) };
3026
+ }
3027
+ return { text: `Unknown Codex command: ${formatCodexDisplayText(subcommand)}\n\n${buildHelp()}` };
3028
+ } finally {
3029
+ nativePolicy.release();
2896
3030
  }
2897
- return { text: `Unknown Codex command: ${formatCodexDisplayText(subcommand)}\n\n${buildHelp()}` };
2898
3031
  }
2899
3032
  function resolvePluginRuntimeRefreshMethod(method) {
2900
3033
  const recognized = [