@openclaw/codex 2026.9.6 → 2026.9.7

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 (158) hide show
  1. package/README.md +2 -0
  2. package/assets/icon.png +0 -0
  3. package/dist/.setup/{account-usage-runtime-Eem_WGqY.mjs → account-usage-runtime-DFhbh1zz.mjs} +5 -5
  4. package/dist/.setup/{apply-DDOi8uNx.mjs → apply-D3GcSoSa.mjs} +22 -36
  5. package/dist/.setup/{attempt-client-cleanup-CEv1cKwF.mjs → attempt-client-cleanup-DOP-cW5j.mjs} +128 -37
  6. package/dist/.setup/attempt-workspace-context-C5HigshI.mjs +164 -0
  7. package/dist/.setup/{auth-binding-DhLWa_7K.mjs → auth-binding-BLWz7stm.mjs} +14 -1
  8. package/dist/.setup/{auth-cache-key-B2mpaI9D.mjs → auth-cache-key-Dbvq-QgB.mjs} +36 -34
  9. package/dist/.setup/{auth-profile-WqZtZfXN.mjs → auth-profile-B0okYl2D.mjs} +1 -2
  10. package/dist/.setup/auth-start-options-BPIPeEX8.mjs +44 -0
  11. package/dist/.setup/{binding-connection-ThoatDcb.mjs → binding-connection-DTtN1KrX.mjs} +2 -2
  12. package/dist/.setup/{binding-connection.runtime-yoHrABt-.mjs → binding-connection.runtime-6TpgD1M6.mjs} +4 -4
  13. package/dist/.setup/{bounded-turn-B2HScEgT.mjs → bounded-turn-CbjoN2OW.mjs} +15 -18
  14. package/dist/.setup/bounded-turn-isolation-B8K_ylqk.mjs +14 -0
  15. package/dist/.setup/{build-state-C7EnDVgr.mjs → build-state-Da1_z0kd.mjs} +1 -1
  16. package/dist/.setup/{capabilities-CDXOOFdZ.mjs → capabilities-B3WEZl4e.mjs} +2 -10
  17. package/dist/.setup/{client-Cs08OXVQ.mjs → client-N0JpgSzF.mjs} +138 -399
  18. package/dist/.setup/{client-catalog-response-BMgt_4q4.mjs → client-catalog-response-5HHLdcde.mjs} +1 -1
  19. package/dist/.setup/{command-dispatch-B4JuOsOk.mjs → command-dispatch-BeAoaovI.mjs} +5 -8
  20. package/dist/.setup/{command-formatters-Bmqvr9tO.mjs → command-formatters-R3ckE3Co.mjs} +29 -61
  21. package/dist/.setup/{command-handlers-DW7Lx9oH.mjs → command-handlers-ylTMS00z.mjs} +222 -343
  22. package/dist/.setup/{command-rpc-DixIj3HW.mjs → command-rpc-CGJGUQ6Y.mjs} +15 -18
  23. package/dist/.setup/compact-C2WamavS.mjs +776 -0
  24. package/dist/.setup/{config-BoTP_mrL.mjs → config-DKhXquav.mjs} +26 -28
  25. package/dist/.setup/{config-options-BvaRs51b.mjs → config-options-CzyWLTJt.mjs} +24 -37
  26. package/dist/.setup/{config-parsing-CcB9iPoq.mjs → config-parsing-b088LyhT.mjs} +57 -60
  27. package/dist/.setup/{config-runtime-C8Rw1m1m.mjs → config-runtime-C0NbLms1.mjs} +2 -2
  28. package/dist/.setup/{config-security-BEReZ6go.mjs → config-security-CE-FcGw9.mjs} +32 -111
  29. package/dist/.setup/{config-utils-DujwEnhg.mjs → config-utils-D0CXecki.mjs} +3 -13
  30. package/dist/.setup/context-engine-projection-PezSESth.mjs +387 -0
  31. package/dist/.setup/{conversation-binding-DP-gMrBP.mjs → conversation-binding-3Min8qvP.mjs} +67 -90
  32. package/dist/.setup/{conversation-binding-data-CrcyZk6O.mjs → conversation-binding-data-C746z5Pn.mjs} +8 -12
  33. package/dist/.setup/{conversation-control-uK9Jomlc.mjs → conversation-control-CEP8X5JC.mjs} +8 -8
  34. package/dist/.setup/{cyber-failover-DYwbmf1o.mjs → cyber-failover-XV0nNRZu.mjs} +1 -1
  35. package/dist/.setup/{cyber-failover-notice-e9G3J9-e.mjs → cyber-failover-notice-RNpGpTyP.mjs} +1 -1
  36. package/dist/.setup/{dynamic-tools-BDXl-8Cw.mjs → dynamic-tools-DzlsLUuS.mjs} +2305 -2606
  37. package/dist/.setup/{effective-mcp-catalog-CvnvnGIe.mjs → effective-mcp-catalog-CxUtC-xG.mjs} +8 -17
  38. package/dist/.setup/{ephemeral-turn-poidXgek.mjs → ephemeral-turn-CDsPJOa2.mjs} +3 -3
  39. package/dist/.setup/event-projector-assistant-message-CigreO4K.mjs +69 -0
  40. package/dist/.setup/{event-projector-usage-CnBS8Wa3.mjs → event-projector-usage-03R0I2dM.mjs} +3 -25
  41. package/dist/.setup/event-projector-values-DJSz8BTk.mjs +106 -0
  42. package/dist/.setup/incognito-session-DWYapfwf.mjs +2 -0
  43. package/dist/.setup/{inference-context-D96l9-ew.mjs → inference-context-D-9gWlTR.mjs} +16 -18
  44. package/dist/.setup/inference-dispatch-CMZtjQyz.mjs +359 -0
  45. package/dist/.setup/inference-metadata-CgIf7sOx.mjs +81 -0
  46. package/dist/.setup/{inference-proxy-b-aJMSxm.mjs → inference-proxy-DhcXOgUE.mjs} +174 -214
  47. package/dist/.setup/{isolated-completion-BIZFhTNG.mjs → isolated-completion-Dm3PzxJk.mjs} +9 -12
  48. package/dist/.setup/{managed-binary-BnshlFag.mjs → managed-binary-kiWRhNRE.mjs} +8 -12
  49. package/dist/.setup/{model-catalog-CfXJf9Ay.mjs → model-catalog-PAuZgJC6.mjs} +11 -10
  50. package/dist/.setup/model-runtime-BdqzOMkU.mjs +11 -0
  51. package/dist/.setup/{models-KnqBv0hE.mjs → models-DHXZtVVk.mjs} +9 -18
  52. package/dist/.setup/{native-auth-rWbGbMn3.mjs → native-auth-CuG53tu4.mjs} +4 -4
  53. package/dist/.setup/{native-execution-policy-umd0tgh4.mjs → native-execution-policy-BxZJy5mP.mjs} +5 -30
  54. package/dist/.setup/{native-subagent-monitor-D3filLY2.mjs → native-subagent-monitor-Dpsmf2wz.mjs} +4395 -3609
  55. package/dist/.setup/native-subagent-pending-assignments-DwkCzLvD.mjs +203 -0
  56. package/dist/.setup/native-task-assignments-DMQ0g3hu.mjs +194 -0
  57. package/dist/.setup/{node-cli-sessions-r3avj02l.mjs → node-cli-sessions-HC4W6FLI.mjs} +19 -49
  58. package/dist/.setup/{node-exec-server.runtime-BDwWXVpK.mjs → node-exec-server.runtime-BgBfWQqo.mjs} +3 -6
  59. package/dist/.setup/{plan-CN3VwfNU.mjs → plan-Y-QIvrKB.mjs} +49 -92
  60. package/dist/.setup/{plugin-activation-DT3MNtqj.mjs → plugin-activation-cNHRfaxU.mjs} +8 -36
  61. package/dist/.setup/{plugin-app-cache-key-B2CsSdnV.mjs → plugin-app-cache-key-BL9B5H0L.mjs} +6 -23
  62. package/dist/.setup/{plugin-inventory-BoRei8Z4.mjs → plugin-inventory-Cky2XJUw.mjs} +21 -21
  63. package/dist/.setup/{plugin-marketplace-discovery-CDOi8IFs.mjs → plugin-marketplace-discovery-D_dV9FXa.mjs} +18 -24
  64. package/dist/.setup/{plugin-metadata-cache-Ctmo83k_.mjs → plugin-metadata-cache-DsjsL1dr.mjs} +115 -175
  65. package/dist/.setup/{provider-BOsxQHOM.mjs → provider-DH8NSzGt.mjs} +11 -14
  66. package/dist/.setup/{provider-capabilities-BfE88FZ5.mjs → provider-capabilities-CAxoF-X1.mjs} +13 -18
  67. package/dist/.setup/{rate-limits-CMU3DUD0.mjs → rate-limits-B7-X2TgG.mjs} +9 -31
  68. package/dist/.setup/{request-D2L0zMrq.mjs → request-BHZ1nz8d.mjs} +7 -6
  69. package/dist/.setup/responses-oauth-twnuTaAa.mjs +93 -0
  70. package/dist/.setup/rpc-error-BlD2vuzn.mjs +31 -0
  71. package/dist/.setup/{run-attempt-BHu11r7h.mjs → run-attempt-D8RZUOzY.mjs} +1035 -1023
  72. package/dist/.setup/{run-attempt-lifecycle-B7JbY4-F.mjs → run-attempt-lifecycle-C-6O3Exn.mjs} +10 -24
  73. package/dist/.setup/{runtime-artifact-CLZ8udh-.mjs → runtime-artifact-DDQ-HGXf.mjs} +16 -4
  74. package/dist/.setup/runtime-artifact-connection-D68qQn1m.mjs +78 -0
  75. package/dist/.setup/sandbox-guard-DjCz2eOw.mjs +126 -0
  76. package/dist/.setup/scope-DOC1Xjc8.mjs +6 -0
  77. package/dist/.setup/session-binding-DGCYAfvD.mjs +443 -0
  78. package/dist/.setup/{session-binding-record-BGoz8wOK.mjs → session-binding-record-Oe9L-CNY.mjs} +52 -130
  79. package/dist/.setup/{session-binding-sidecars-BlB5EvIS.mjs → session-binding-sidecars-jo6H8dFr.mjs} +196 -17
  80. package/dist/.setup/{session-catalog-Pno1xGcl.mjs → session-catalog-4sCdv5qx.mjs} +170 -324
  81. package/dist/.setup/{session-catalog-adoption-BI6UTDZT.mjs → session-catalog-adoption-BU_pHWG7.mjs} +7 -6
  82. package/dist/.setup/{session-catalog-archive-lHBqzhaO.mjs → session-catalog-archive-spHfihri.mjs} +6 -6
  83. package/dist/.setup/session-catalog-events-DePDzzjc.mjs +139 -0
  84. package/dist/.setup/session-catalog-home-id-vlih0B_g.mjs +22 -0
  85. package/dist/.setup/{session-catalog-index-B9_VQIUz.mjs → session-catalog-index-CZvDzC6z.mjs} +126 -122
  86. package/dist/.setup/{session-catalog-index-order-hcdz07yN.mjs → session-catalog-index-order-BcQpHks3.mjs} +1 -1
  87. package/dist/.setup/{session-catalog-index-state-Dgh8ORJm.mjs → session-catalog-index-state-TeO7EyO-.mjs} +3 -2
  88. package/dist/.setup/session-catalog-limits-DDxOsQeC.mjs +14 -0
  89. package/dist/.setup/session-catalog-list-request-CvtxrYSe.mjs +170 -0
  90. package/dist/.setup/session-catalog-native-projection-DjhwGL6x.mjs +178 -0
  91. package/dist/.setup/{session-catalog-node-adoption-ITddWx_X.mjs → session-catalog-node-adoption-DgXvSGu0.mjs} +10 -27
  92. package/dist/.setup/{session-catalog-node-continue-6g6qi4A9.mjs → session-catalog-node-continue-DjKXHBbi.mjs} +8 -10
  93. package/dist/.setup/session-catalog-node-lookup-CtAXI5W5.mjs +56 -0
  94. package/dist/.setup/{session-catalog-native-projection-DowriLid.mjs → session-catalog-parsing-CPGaPYr-.mjs} +11 -194
  95. package/dist/.setup/{session-catalog-projection-zK_PUsiE.mjs → session-catalog-projection-Cr5qP5Dj.mjs} +6 -4
  96. package/dist/.setup/session-catalog-provenance-DoAvktcj.mjs +95 -0
  97. package/dist/.setup/{session-cli-irrD-uo7.mjs → session-cli-Cn_nCqfq.mjs} +9 -22
  98. package/dist/.setup/{session-history-BrqhSCf9.mjs → session-history-D83lJWHG.mjs} +4 -6
  99. package/dist/.setup/{session-history-import-D-3wAgOP.mjs → session-history-import-WhX-X33a.mjs} +7 -10
  100. package/dist/.setup/session-history-read-Ov3StuL4.mjs +133 -0
  101. package/dist/.setup/{session-history.worker-CaCh0xF_.mjs → session-history.worker-MnPKncqP.mjs} +9 -5
  102. package/dist/.setup/session-initialization-6aveB9qb.mjs +22 -0
  103. package/dist/.setup/{session-permission-policy-BI1QK_98.mjs → session-permission-policy-Ci_fVX6y.mjs} +4 -8
  104. package/dist/.setup/{session-retirement-BH-S6qkJ.mjs → session-retirement-qMTxkNx2.mjs} +17 -17
  105. package/dist/.setup/{settled-turn-context-fmwouT5I.mjs → settled-turn-context-D4yj4rxf.mjs} +1 -1
  106. package/dist/.setup/{settled-turn-finalizer-DiAi6Kx6.mjs → settled-turn-finalizer-BsvEabkw.mjs} +14 -10
  107. package/dist/.setup/{shared-client-DA4VR4Eb.mjs → shared-client-DqyTMYug.mjs} +783 -412
  108. package/dist/.setup/shared-client-lifecycle-DJIgqgMw.mjs +153 -0
  109. package/dist/.setup/{side-question-BJ1wSDcB.mjs → side-question-C4kCmQy1.mjs} +79 -143
  110. package/dist/.setup/{source-CUzJq5WN.mjs → source-CS_7GFJZ.mjs} +80 -137
  111. package/dist/.setup/{thread-lifecycle-B3mfz1TG.mjs → thread-lifecycle-DPflntEJ.mjs} +294 -737
  112. package/dist/.setup/{incognito-session-uhrBF6wJ.mjs → thread-ownership-queue-Dp24d7-F.mjs} +1 -2
  113. package/dist/.setup/{thread-ownership-DcTtAcXj.mjs → thread-ownership-roNP0l1c.mjs} +45 -10
  114. package/dist/.setup/{thread-policy-DGuQsuFC.mjs → thread-policy-DTd-DtkX.mjs} +46 -7
  115. package/dist/.setup/{thread-requests-BLvGkP2R.mjs → thread-requests-B_bRnMGN.mjs} +199 -302
  116. package/dist/.setup/{thread-resume-DIBXwOpE.mjs → thread-resume-CdDaoc7T.mjs} +6 -6
  117. package/dist/.setup/{timeout-C910MdAB.mjs → timeout-CXOfNoaX.mjs} +1 -35
  118. package/dist/.setup/{transcript-history-projection-ZZpkFkJ_.mjs → transcript-history-projection-DRSifI-1.mjs} +17 -89
  119. package/dist/.setup/{transcript-mirror-attestation-CzM-94NC.mjs → transcript-mirror-attestation-YSegaktH.mjs} +3 -4
  120. package/dist/.setup/{transcript-mirror-BtHDBp1G.mjs → transcript-mirror-kxmCYsuF.mjs} +7 -9
  121. package/dist/.setup/{transport-stdio-h2VHOskC.mjs → transport-stdio-Bdegpn2V.mjs} +5 -22
  122. package/dist/.setup/transport-websocket-BTBE-LD9.mjs +211 -0
  123. package/dist/.setup/{upstream-prompt-provenance-LphB8slG.mjs → upstream-prompt-provenance-fXkKbPVC.mjs} +3 -9
  124. package/dist/.setup/{upstream-session-fork-BUr4OUbC.mjs → upstream-session-fork-CBeVjBpT.mjs} +23 -23
  125. package/dist/.setup/{usage-BML0r-ua.mjs → usage-BMzNxeR_.mjs} +4 -4
  126. package/dist/.setup/{usage-limit-error-DUMbefVY.mjs → usage-limit-error-QXerDo3i.mjs} +4 -19
  127. package/dist/.setup/{web-search-provider.runtime-CDKlN-Rv.mjs → web-search-provider.runtime-P77OUeoo.mjs} +8 -19
  128. package/dist/api.js +9 -11
  129. package/dist/catalog-page.worker.js +1 -1
  130. package/dist/cli-metadata.js +1 -1
  131. package/dist/doctor-contract-api.js +50 -8
  132. package/dist/harness.js +344 -1
  133. package/dist/index.js +193 -245
  134. package/dist/media-understanding-provider.js +9 -22
  135. package/dist/migration-provider-api.js +1 -1
  136. package/dist/provider-discovery.js +1 -1
  137. package/dist/session-history-worker-runtime.js +3 -3
  138. package/dist/session-history.worker.js +1 -1
  139. package/openclaw.plugin.json +14 -2
  140. package/package.json +7 -6
  141. package/dist/.setup/attempt-workspace-context-DUVEn_CS.mjs +0 -331
  142. package/dist/.setup/compact-Du5UvtxA.mjs +0 -680
  143. package/dist/.setup/event-projector-assistant-message-BsruvNrH.mjs +0 -103
  144. package/dist/.setup/event-projector-items-C6L_5ZiT.mjs +0 -234
  145. package/dist/.setup/harness-a_MsE4-_.mjs +0 -355
  146. package/dist/.setup/history-rejection-B4nOXNXF.mjs +0 -13
  147. package/dist/.setup/image-payload-sanitizer-tupAr-2o.mjs +0 -79
  148. package/dist/.setup/local-runtime-attribution-B_2mnqhb.mjs +0 -19
  149. package/dist/.setup/native-subagent-history-0nYYgo0k.mjs +0 -148
  150. package/dist/.setup/native-subagent-task-ids-wb8CKZGN.mjs +0 -441
  151. package/dist/.setup/plugin-approval-roundtrip-C0MZzCuP.mjs +0 -122
  152. package/dist/.setup/rolldown-runtime-8H4AJuhK.mjs +0 -14
  153. package/dist/.setup/sandbox-guard-C2sRMOEY.mjs +0 -166
  154. package/dist/.setup/session-binding-Cm0apEbd.mjs +0 -692
  155. package/dist/.setup/session-catalog-events-Bj6j94E_.mjs +0 -347
  156. package/dist/.setup/session-history-read-B3ZfSUbF.mjs +0 -50
  157. package/dist/.setup/session-initialization-rcgbZiid.mjs +0 -75
  158. package/dist/.setup/thread-history-page-DoVpnHim.mjs +0 -83
@@ -1,40 +1,42 @@
1
- import { n as isCodexFastServiceTier } from "./config-utils-DujwEnhg.mjs";
2
- import { c as CODEX_PLUGINS_MARKETPLACE_NAME, i as pluginReadParams, r as isOpenAiCuratedMarketplaceName, t as findCodexMarketplacePluginSummary } from "./plugin-inventory-BoRei8Z4.mjs";
3
- import { m as sessionBindingIdentity, n as assertCodexBindingMayBeReplaced, r as bindingStoreKey } from "./session-binding-record-BGoz8wOK.mjs";
1
+ import { n as isCodexFastServiceTier } from "./config-utils-D0CXecki.mjs";
2
+ import { o as pluginReadParams, r as isOpenAiCuratedMarketplaceName, t as findCodexMarketplacePluginSummary, u as CODEX_PLUGINS_MARKETPLACE_NAME } from "./plugin-inventory-Cky2XJUw.mjs";
4
3
  import { i as isJsonObject } from "./protocol-CANUwXJ3.mjs";
5
- import { c as resolveCodexAppServerPreparedApiKeyCacheKey, s as resolveCodexAppServerFallbackApiKeyCacheKey } from "./auth-cache-key-B2mpaI9D.mjs";
6
- import { r as withCodexConversationThreadActivity, t as isIncognitoSessionKey } from "./incognito-session-uhrBF6wJ.mjs";
7
- import { a as CODEX_HOST_INSPECTION_AUTH_ERROR, c as canMutateCodexHost, i as CODEX_FULL_PERMISSIONS_AUTH_ERROR, l as hasCodexAdminScope, n as filterCodexMarketplacePlugins, o as CODEX_NATIVE_EXECUTION_AUTH_ERROR, r as parseCodexPluginMarketplaceId, s as assertCodexHostOwnerCurrent, t as discoverCodexMarketplacePlugins } from "./plugin-marketplace-discovery-CDOi8IFs.mjs";
8
- import { s as summarizeCodexAccountUsage } from "./rate-limits-CMU3DUD0.mjs";
9
- import { a as formatCodexAccountLine, c as formatCodexTextForDisplay, d as formatModels, f as formatSkills, i as formatAccount, l as formatComputerUseStatus, 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-Bmqvr9tO.mjs";
10
- import { i as readCodexConversationBindingData, n as createCodexCliNodeConversationBindingData, o as resolveCodexDefaultWorkspaceDir, r as createCodexConversationBindingData } from "./conversation-binding-data-CrcyZk6O.mjs";
11
- import { o as CodexAppServerRpcError } from "./timeout-C910MdAB.mjs";
12
- import { t as CODEX_CONTROL_METHODS } from "./capabilities-CDXOOFdZ.mjs";
13
- import { o as formatCodexCliSessions } from "./node-cli-sessions-r3avj02l.mjs";
14
- import { a as defaultCodexAppInventoryCache, r as buildCodexPluginAppCacheKey } from "./plugin-app-cache-key-B2CsSdnV.mjs";
15
- import { i as resolveCodexBindingAppServerConnection } from "./binding-connection-ThoatDcb.mjs";
16
- import { o as withCodexAppServerJsonClient } from "./request-D2L0zMrq.mjs";
17
- import "./config-BoTP_mrL.mjs";
18
- import { n as resolveCodexAppServerRuntimeOptions } from "./config-runtime-C8Rw1m1m.mjs";
19
- import { a as resolveCodexAppServerAuthProfileStore, i as resolveCodexAppServerAuthProfileIdForAgent, n as normalizeCodexAppServerBindingModelProvider } from "./auth-profile-WqZtZfXN.mjs";
20
- import { I as hasCodexAppServerLiveThread, N as consumeCodexAppServerLiveThread, X as resolveCodexAppServerAuthAccountCacheKey, c as getLeasedSharedCodexAppServerClient, h as releaseLeasedSharedCodexAppServerClient } from "./shared-client-DA4VR4Eb.mjs";
21
- import { b as assertCodexThreadResumeResponse, s as isCodexAppServerIndeterminateRequestCancellationError, u as isCodexAppServerPrewriteRequestCancellationError, v as assertCodexThreadAcceptsDirectInput } from "./client-Cs08OXVQ.mjs";
22
- import { o as closeCodexStartupClientBestEffort } from "./attempt-client-cleanup-CEv1cKwF.mjs";
23
- import { n as fingerprintCodexAppServerAuthBinding } from "./auth-binding-DhLWa_7K.mjs";
24
- import { t as listAllCodexAppServerModels } from "./models-KnqBv0hE.mjs";
25
- import { n as refreshCodexAppRuntimeState, r as refreshCodexPluginRuntimeState } from "./plugin-activation-DT3MNtqj.mjs";
26
- import { n as createCodexSessionGenerationSupersededError, o as resolveCodexSessionBinding } from "./session-binding-Cm0apEbd.mjs";
27
- import { i as assertCodexSupervisionThreadLineage } from "./thread-policy-DGuQsuFC.mjs";
28
- import { a as rollbackCodexAppServerBindingSubscription, i as retireCodexConversationThreadBinding, n as releaseCodexAppServerBindingSubscription, r as retainCodexAppServerBindingSubscription, s as withExclusiveCodexAppServerThread, t as isSameCodexAppServerThreadOwner } from "./thread-ownership-DcTtAcXj.mjs";
29
- import { n as resolveCodexNativeSandboxBlock, t as resolveCodexNativeExecutionBlock } from "./sandbox-guard-C2sRMOEY.mjs";
30
- import { i as readCodexComputerUseStatus, r as installCodexComputerUse, t as defaultCodexPluginMetadataCache } from "./plugin-metadata-cache-Ctmo83k_.mjs";
31
- import { a as requestOptions, i as readCodexStatusProbes, o as safeCodexControlRequest, r as prepareCodexControlSessionAuth, t as codexControlRequest } from "./command-rpc-DixIj3HW.mjs";
32
- import { a as setCodexConversationFastMode, c as steerCodexConversationTurn, i as readCodexConversationActiveTurn, l as stopCodexConversationTurn, n as parseCodexFastModeArg, o as setCodexConversationModel, r as parseCodexPermissionsModeArg, s as setCodexConversationPermissions, t as formatPermissionsMode } from "./conversation-control-uK9Jomlc.mjs";
4
+ import { n as assertCodexBindingMayBeReplaced, r as bindingStoreKey, v as sessionBindingIdentity } from "./session-binding-record-Oe9L-CNY.mjs";
5
+ import { c as resolveCodexAppServerPreparedApiKeyCacheKey, s as resolveCodexAppServerFallbackApiKeyCacheKey } from "./auth-cache-key-Dbvq-QgB.mjs";
6
+ import { n as withCodexConversationThreadActivity } from "./thread-ownership-queue-Dp24d7-F.mjs";
7
+ import { a as CODEX_HOST_INSPECTION_AUTH_ERROR, c as canMutateCodexHost, i as CODEX_FULL_PERMISSIONS_AUTH_ERROR, l as hasCodexAdminScope, n as filterCodexMarketplacePlugins, o as CODEX_NATIVE_EXECUTION_AUTH_ERROR, r as parseCodexPluginMarketplaceId, s as assertCodexHostOwnerCurrent, t as discoverCodexMarketplacePlugins } from "./plugin-marketplace-discovery-D_dV9FXa.mjs";
8
+ import { l as formatRelativeDuration, s as summarizeCodexAccountUsage } from "./rate-limits-B7-X2TgG.mjs";
9
+ import { a as formatCodexAccountLine, c as formatCodexTextForDisplay, d as formatModels, f as formatSkills, i as formatAccount, l as formatComputerUseStatus, 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-R3ckE3Co.mjs";
10
+ import { i as readCodexConversationBindingData, n as createCodexCliNodeConversationBindingData, o as resolveCodexDefaultWorkspaceDir, r as createCodexConversationBindingData } from "./conversation-binding-data-C746z5Pn.mjs";
11
+ import { t as isIncognitoSessionKey } from "./incognito-session-DWYapfwf.mjs";
12
+ import { n as CodexAppServerRpcError } from "./rpc-error-BlD2vuzn.mjs";
13
+ import { t as CODEX_CONTROL_METHODS } from "./capabilities-B3WEZl4e.mjs";
14
+ import { o as formatCodexCliSessions } from "./node-cli-sessions-HC4W6FLI.mjs";
15
+ import { a as defaultCodexAppInventoryCache, r as buildCodexPluginAppCacheKey } from "./plugin-app-cache-key-BL9B5H0L.mjs";
16
+ import { i as resolveCodexBindingAppServerConnection } from "./binding-connection-DTtN1KrX.mjs";
17
+ import { o as withCodexAppServerJsonClient } from "./request-BHZ1nz8d.mjs";
18
+ import "./config-DKhXquav.mjs";
19
+ import { n as resolveCodexAppServerRuntimeOptions } from "./config-runtime-C0NbLms1.mjs";
20
+ import { a as resolveCodexAppServerAuthProfileStore, i as resolveCodexAppServerAuthProfileIdForAgent, n as normalizeCodexAppServerBindingModelProvider } from "./auth-profile-B0okYl2D.mjs";
21
+ import { F as consumeCodexAppServerLiveThread, R as hasCodexAppServerLiveThread, c as getLeasedSharedCodexAppServerClient, et as resolveCodexAppServerAuthAccountCacheKey, h as releaseLeasedSharedCodexAppServerClient } from "./shared-client-DqyTMYug.mjs";
22
+ import { b as assertCodexThreadResumeResponse, s as isCodexAppServerIndeterminateRequestCancellationError, u as isCodexAppServerPrewriteRequestCancellationError, v as assertCodexThreadAcceptsDirectInput } from "./client-N0JpgSzF.mjs";
23
+ import { o as closeCodexStartupClientBestEffort } from "./attempt-client-cleanup-DOP-cW5j.mjs";
24
+ import { n as fingerprintCodexAppServerAuthBinding } from "./auth-binding-BLWz7stm.mjs";
25
+ import { n as listAllCodexAppServerModels } from "./models-DHXZtVVk.mjs";
26
+ import { n as refreshCodexAppRuntimeState, r as refreshCodexPluginRuntimeState } from "./plugin-activation-cNHRfaxU.mjs";
27
+ import { n as createCodexSessionGenerationSupersededError, o as resolveCodexSessionBinding } from "./session-binding-DGCYAfvD.mjs";
28
+ import { i as assertCodexSupervisionThreadLineage } from "./thread-policy-DTd-DtkX.mjs";
29
+ import { a as rollbackCodexAppServerBindingSubscription, c as withExclusiveCodexAppServerThread, i as retireCodexConversationThreadBinding, n as releaseCodexAppServerBindingSubscription, r as retainCodexAppServerBindingSubscription, t as isSameCodexAppServerThreadOwner } from "./thread-ownership-roNP0l1c.mjs";
30
+ import { n as resolveCodexNativeSandboxBlock, t as resolveCodexNativeExecutionBlock } from "./sandbox-guard-DjCz2eOw.mjs";
31
+ import { i as readCodexComputerUseStatus, r as installCodexComputerUse, t as defaultCodexPluginMetadataCache } from "./plugin-metadata-cache-DsjsL1dr.mjs";
32
+ import { a as requestOptions, i as readCodexStatusProbes, o as safeCodexControlRequest, r as prepareCodexControlSessionAuth, t as codexControlRequest } from "./command-rpc-CGJGUQ6Y.mjs";
33
+ import { a as setCodexConversationFastMode, c as steerCodexConversationTurn, i as readCodexConversationActiveTurn, l as stopCodexConversationTurn, n as parseCodexFastModeArg, o as setCodexConversationModel, r as parseCodexPermissionsModeArg, s as setCodexConversationPermissions, t as formatPermissionsMode } from "./conversation-control-CEP8X5JC.mjs";
33
34
  import { normalizeOptionalString, normalizeUniqueStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
34
35
  import crypto from "node:crypto";
35
36
  import { isDeepStrictEqual } from "node:util";
36
37
  import { resolveSessionAgentIdsStrict } from "openclaw/plugin-sdk/agent-scope-runtime";
37
38
  import { parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
39
+ import { coerceErrorMessage } from "openclaw/plugin-sdk/error-runtime";
38
40
  import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
39
41
  import { parseAgentSessionKey } from "openclaw/plugin-sdk/routing";
40
42
  import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
@@ -138,7 +140,7 @@ function buildProfileRow(params) {
138
140
  function describeInactiveProfileStatus(params) {
139
141
  const stats = params.store.usageStats?.[params.profileId];
140
142
  const blockedUntil = stats?.blockedUntil;
141
- if (isActiveUntil(blockedUntil, params.now)) return `rate-limited - resets ${formatRelativeReset(blockedUntil, params.now)}`;
143
+ if (isActiveUntil(blockedUntil, params.now)) return `rate-limited - resets in ${formatRelativeDuration(Math.max(6e4, blockedUntil - params.now))}`;
142
144
  if (isActiveUntil(resolveProfileUnusableUntilForDisplay(params.store, params.profileId) ?? void 0, params.now)) return describeFailureStatus(stats?.disabledReason ?? stats?.cooldownReason, params.credential);
143
145
  const eligibility = resolveAuthProfileEligibility({
144
146
  cfg: params.config,
@@ -229,22 +231,6 @@ function describeEligibilityStatus(reason, credential) {
229
231
  function isActiveUntil(value, now) {
230
232
  return typeof value === "number" && Number.isFinite(value) && value > now;
231
233
  }
232
- function formatRelativeReset(untilMs, nowMs) {
233
- const durationMs = Math.max(1e3, untilMs - nowMs);
234
- const minuteMs = 6e4;
235
- const hourMs = 60 * minuteMs;
236
- const dayMs = 24 * hourMs;
237
- if (durationMs < hourMs) {
238
- const minutes = Math.ceil(durationMs / minuteMs);
239
- return `in ${minutes} ${minutes === 1 ? "minute" : "minutes"}`;
240
- }
241
- if (durationMs < dayMs) {
242
- const hours = Math.ceil(durationMs / hourMs);
243
- return `in ${hours} ${hours === 1 ? "hour" : "hours"}`;
244
- }
245
- const days = Math.ceil(durationMs / dayMs);
246
- return `in ${days} ${days === 1 ? "day" : "days"}`;
247
- }
248
234
  function buildCodexPluginAppLinks(apps, options = {}) {
249
235
  const blocks = apps.slice(0, 5).map((app) => {
250
236
  const name = formatCodexDisplayText((app.name.trim() || app.id).slice(0, 80));
@@ -284,6 +270,24 @@ function buildCodexPluginAppLinks(apps, options = {}) {
284
270
  });
285
271
  return blocks;
286
272
  }
273
+ function buildCodexPluginStatusButtons(pluginId, canRefreshHostedApps) {
274
+ return {
275
+ type: "buttons",
276
+ buttons: [...canRefreshHostedApps ? [{
277
+ label: "Refresh hosted apps",
278
+ action: {
279
+ type: "command",
280
+ command: "/codex plugins refresh"
281
+ }
282
+ }] : [], {
283
+ label: "Check status",
284
+ action: {
285
+ type: "command",
286
+ command: `/codex plugins status ${pluginId}`
287
+ }
288
+ }]
289
+ };
290
+ }
287
291
  function safeCodexAppLink(value) {
288
292
  if (!value || value.length > 2048 || /[\s\p{Cc}\p{Cf}<>]/u.test(value)) return;
289
293
  try {
@@ -591,22 +595,7 @@ function formatCodexPluginReadiness(readiness, page = 1) {
591
595
  type: "text",
592
596
  text: "Flags reflect Codex's runtime snapshot; status does not refresh hosted tools. After connecting, /codex plugins refresh refreshes hosted inventory for the current Codex account/runtime, across all apps. Use Check status separately to inspect this plugin without refreshing. OpenClaw app-access changes take effect on your next message; use /new or /reset after connecting."
593
597
  });
594
- blocks.push({
595
- type: "buttons",
596
- buttons: [...canRefreshHostedApps ? [{
597
- label: "Refresh hosted apps",
598
- action: {
599
- type: "command",
600
- command: "/codex plugins refresh"
601
- }
602
- }] : [], {
603
- label: "Check status",
604
- action: {
605
- type: "command",
606
- command: `/codex plugins status ${readiness.commandId}`
607
- }
608
- }]
609
- });
598
+ blocks.push(buildCodexPluginStatusButtons(readiness.commandId, canRefreshHostedApps));
610
599
  }
611
600
  }
612
601
  const presentation = {
@@ -777,73 +766,59 @@ function buildCodexSubcommandPickerReply() {
777
766
  };
778
767
  }
779
768
  function buildCodexFastMenuReply() {
780
- const modes = [
781
- "on",
782
- "off",
783
- "status"
784
- ];
785
- const buttons = [...modes.map((mode) => ({
786
- label: mode,
787
- command: `/codex fast ${mode}`
788
- })), {
789
- label: "back",
790
- command: "/codex"
791
- }];
792
- return {
793
- text: [
794
- "Codex fast mode. Pick one or type /codex fast <mode>:",
795
- "",
796
- ...modes.map((m, i) => ` ${i + 1}. /codex fast ${m}`),
797
- "",
798
- "Type '/codex' to go back to the main menu."
799
- ].join("\n"),
800
- presentation: buildCodexCommandPickerPresentation("Codex fast mode", "Pick a Codex fast mode:", buttons)
801
- };
769
+ return buildCodexChoiceMenuReply({
770
+ title: "Codex fast mode",
771
+ prompt: "Pick a Codex fast mode:",
772
+ introduction: "Codex fast mode. Pick one or type /codex fast <mode>:",
773
+ command: "/codex fast",
774
+ choices: [
775
+ "on",
776
+ "off",
777
+ "status"
778
+ ]
779
+ });
802
780
  }
803
781
  function buildCodexPermissionsMenuReply() {
804
- const modes = [
805
- "default",
806
- "yolo",
807
- "status"
808
- ];
809
- const buttons = [...modes.map((mode) => ({
810
- label: mode,
811
- command: `/codex permissions ${mode}`
812
- })), {
813
- label: "back",
814
- command: "/codex"
815
- }];
816
- return {
817
- text: [
818
- "Codex permissions. Pick one or type /codex permissions <mode>:",
819
- "",
820
- ...modes.map((m, i) => ` ${i + 1}. /codex permissions ${m}`),
821
- "",
822
- "Type '/codex' to go back to the main menu."
823
- ].join("\n"),
824
- presentation: buildCodexCommandPickerPresentation("Codex permissions", "Pick a Codex permissions mode:", buttons)
825
- };
782
+ return buildCodexChoiceMenuReply({
783
+ title: "Codex permissions",
784
+ prompt: "Pick a Codex permissions mode:",
785
+ introduction: "Codex permissions. Pick one or type /codex permissions <mode>:",
786
+ command: "/codex permissions",
787
+ choices: [
788
+ "default",
789
+ "yolo",
790
+ "status"
791
+ ]
792
+ });
826
793
  }
827
794
  function buildCodexComputerUseMenuReply() {
828
- const actions = ["status", "install"];
829
- const buttons = [...actions.map((action) => ({
830
- label: action,
831
- command: `/codex computer-use ${action}`
795
+ return buildCodexChoiceMenuReply({
796
+ title: "Codex computer-use",
797
+ prompt: "Pick a Codex computer-use action:",
798
+ introduction: "Codex computer-use. Pick one or type /codex computer-use <action>:",
799
+ command: "/codex computer-use",
800
+ choices: ["status", "install"],
801
+ hint: "Flag-driven invocations (--source, --marketplace-path, --marketplace) are not in the picker. Type '/codex computer-use' or read '/codex help' for the full surface."
802
+ });
803
+ }
804
+ function buildCodexChoiceMenuReply(params) {
805
+ const buttons = [...params.choices.map((choice) => ({
806
+ label: choice,
807
+ command: `${params.command} ${choice}`
832
808
  })), {
833
809
  label: "back",
834
810
  command: "/codex"
835
811
  }];
836
812
  return {
837
813
  text: [
838
- "Codex computer-use. Pick one or type /codex computer-use <action>:",
814
+ params.introduction,
839
815
  "",
840
- ...actions.map((a, i) => ` ${i + 1}. /codex computer-use ${a}`),
841
- "",
842
- "Flag-driven invocations (--source, --marketplace-path, --marketplace) are not in the picker. Type '/codex computer-use' or read '/codex help' for the full surface.",
816
+ ...params.choices.map((choice, index) => ` ${index + 1}. ${params.command} ${choice}`),
843
817
  "",
818
+ ...params.hint ? [params.hint, ""] : [],
844
819
  "Type '/codex' to go back to the main menu."
845
820
  ].join("\n"),
846
- presentation: buildCodexCommandPickerPresentation("Codex computer-use", "Pick a Codex computer-use action:", buttons)
821
+ presentation: buildCodexCommandPickerPresentation(params.title, params.prompt, buttons)
847
822
  };
848
823
  }
849
824
  function isMenuVerb(rest) {
@@ -895,54 +870,18 @@ function splitArgs(value) {
895
870
  return args;
896
871
  }
897
872
  function parseBindArgs(args) {
898
- const parsed = {};
899
- for (let index = 0; index < args.length; index += 1) {
900
- const arg = expectDefined(args[index], "current Codex bind argument");
901
- if (arg === "--help" || arg === "-h") {
902
- parsed.help = true;
903
- continue;
904
- }
905
- if (arg === "--cwd") {
906
- const value = readRequiredOptionValue(args, index);
907
- if (!value || parsed.cwd !== void 0) {
908
- parsed.help = true;
909
- continue;
910
- }
911
- parsed.cwd = value;
912
- index += 1;
913
- continue;
914
- }
915
- if (arg === "--model") {
916
- const value = readRequiredOptionValue(args, index);
917
- if (!value || parsed.model !== void 0) {
918
- parsed.help = true;
919
- continue;
920
- }
921
- parsed.model = value;
922
- index += 1;
923
- continue;
924
- }
925
- if (arg === "--provider" || arg === "--model-provider") {
926
- const value = readRequiredOptionValue(args, index);
927
- if (!value || parsed.provider !== void 0) {
928
- parsed.help = true;
929
- continue;
930
- }
931
- parsed.provider = value;
932
- index += 1;
933
- continue;
934
- }
935
- if (!arg.startsWith("-") && !parsed.threadId) {
936
- parsed.threadId = arg;
937
- continue;
938
- }
939
- parsed.help = true;
940
- }
941
- parsed.threadId = normalizeOptionalString(parsed.threadId);
942
- parsed.cwd = normalizeOptionalString(parsed.cwd);
943
- parsed.model = normalizeOptionalString(parsed.model);
944
- parsed.provider = normalizeOptionalString(parsed.provider);
945
- return parsed;
873
+ const { parsed, values } = parseThreadArgs(args, /* @__PURE__ */ new Map([
874
+ ["--cwd", "cwd"],
875
+ ["--model", "model"],
876
+ ["--provider", "provider"],
877
+ ["--model-provider", "provider"]
878
+ ]));
879
+ return {
880
+ ...parsed,
881
+ cwd: normalizeOptionalString(values.get("cwd")),
882
+ model: normalizeOptionalString(values.get("model")),
883
+ provider: normalizeOptionalString(values.get("provider"))
884
+ };
946
885
  }
947
886
  function parseCodexCliSessionsArgs(args) {
948
887
  const parsed = { filter: "" };
@@ -985,29 +924,34 @@ function parseCodexCliSessionsArgs(args) {
985
924
  return parsed;
986
925
  }
987
926
  function parseResumeArgs(args) {
927
+ const { parsed, values } = parseThreadArgs(args, /* @__PURE__ */ new Map([
928
+ ["--host", "host"],
929
+ ["--node", "host"],
930
+ ["--bind", "bind"]
931
+ ]));
932
+ return {
933
+ ...parsed,
934
+ ...values.has("bind") ? { bindHere: true } : {},
935
+ host: normalizeOptionalString(values.get("host"))
936
+ };
937
+ }
938
+ function parseThreadArgs(args, options) {
988
939
  const parsed = {};
940
+ const values = /* @__PURE__ */ new Map();
989
941
  for (let index = 0; index < args.length; index += 1) {
990
- const arg = expectDefined(args[index], "current Codex resume argument");
942
+ const arg = expectDefined(args[index], "current Codex thread argument");
991
943
  if (arg === "--help" || arg === "-h") {
992
944
  parsed.help = true;
993
945
  continue;
994
946
  }
995
- if (arg === "--host" || arg === "--node") {
947
+ const option = options.get(arg);
948
+ if (option) {
996
949
  const value = readRequiredOptionValue(args, index);
997
- if (!value || parsed.host !== void 0) {
998
- parsed.help = true;
999
- continue;
1000
- }
1001
- parsed.host = value;
1002
- index += 1;
1003
- continue;
1004
- }
1005
- if (arg === "--bind") {
1006
- if (readRequiredOptionValue(args, index) !== "here" || parsed.bindHere !== void 0) {
950
+ if (!value || values.has(option) || option === "bind" && value !== "here") {
1007
951
  parsed.help = true;
1008
952
  continue;
1009
953
  }
1010
- parsed.bindHere = true;
954
+ values.set(option, value);
1011
955
  index += 1;
1012
956
  continue;
1013
957
  }
@@ -1018,8 +962,10 @@ function parseResumeArgs(args) {
1018
962
  parsed.help = true;
1019
963
  }
1020
964
  parsed.threadId = normalizeOptionalString(parsed.threadId);
1021
- parsed.host = normalizeOptionalString(parsed.host);
1022
- return parsed;
965
+ return {
966
+ parsed,
967
+ values
968
+ };
1023
969
  }
1024
970
  function parseComputerUseArgs(args) {
1025
971
  const parsed = {
@@ -1044,33 +990,14 @@ function parseComputerUseArgs(args) {
1044
990
  parsed.action = arg;
1045
991
  continue;
1046
992
  }
1047
- if (arg === "--source" || arg === "--marketplace-source") {
1048
- const value = readRequiredOptionValue(args, index);
1049
- if (!value || parsed.overrides.marketplaceSource !== void 0) {
1050
- parsed.help = true;
1051
- continue;
1052
- }
1053
- parsed.overrides.marketplaceSource = value;
1054
- index += 1;
1055
- continue;
1056
- }
1057
- if (arg === "--marketplace-path" || arg === "--path") {
993
+ const option = arg === "--source" || arg === "--marketplace-source" ? "marketplaceSource" : arg === "--marketplace-path" || arg === "--path" ? "marketplacePath" : arg === "--marketplace" ? "marketplaceName" : void 0;
994
+ if (option) {
1058
995
  const value = readRequiredOptionValue(args, index);
1059
- if (!value || parsed.overrides.marketplacePath !== void 0) {
996
+ if (!value || parsed.overrides[option] !== void 0) {
1060
997
  parsed.help = true;
1061
998
  continue;
1062
999
  }
1063
- parsed.overrides.marketplacePath = value;
1064
- index += 1;
1065
- continue;
1066
- }
1067
- if (arg === "--marketplace") {
1068
- const value = readRequiredOptionValue(args, index);
1069
- if (!value || parsed.overrides.marketplaceName !== void 0) {
1070
- parsed.help = true;
1071
- continue;
1072
- }
1073
- parsed.overrides.marketplaceName = value;
1000
+ parsed.overrides[option] = value;
1074
1001
  index += 1;
1075
1002
  continue;
1076
1003
  }
@@ -1087,8 +1014,19 @@ function parseComputerUseArgs(args) {
1087
1014
  }
1088
1015
  parsed.help = true;
1089
1016
  }
1090
- parsed.overrides = normalizeComputerUseStringOverrides(parsed.overrides);
1091
- parsed.hasOverrides = Object.values(parsed.overrides).some(Boolean);
1017
+ const overrides = parsed.overrides;
1018
+ parsed.overrides = {};
1019
+ for (const key of [
1020
+ "marketplaceSource",
1021
+ "marketplacePath",
1022
+ "marketplaceName"
1023
+ ]) {
1024
+ const value = normalizeOptionalString(overrides[key]);
1025
+ if (value) {
1026
+ parsed.overrides[key] = value;
1027
+ parsed.hasOverrides = true;
1028
+ }
1029
+ }
1092
1030
  return parsed;
1093
1031
  }
1094
1032
  function formatComputerUsePersistentIdentityMigration(parsed) {
@@ -1108,16 +1046,6 @@ function readRequiredOptionValue(args, index) {
1108
1046
  if (!normalized || normalized.startsWith("-")) return;
1109
1047
  return value;
1110
1048
  }
1111
- function normalizeComputerUseStringOverrides(overrides) {
1112
- const normalized = {};
1113
- const marketplaceSource = normalizeOptionalString(overrides.marketplaceSource);
1114
- if (marketplaceSource) normalized.marketplaceSource = marketplaceSource;
1115
- const marketplacePath = normalizeOptionalString(overrides.marketplacePath);
1116
- if (marketplacePath) normalized.marketplacePath = marketplacePath;
1117
- const marketplaceName = normalizeOptionalString(overrides.marketplaceName);
1118
- if (marketplaceName) normalized.marketplaceName = marketplaceName;
1119
- return normalized;
1120
- }
1121
1049
  //#endregion
1122
1050
  //#region extensions/codex/src/command-diagnostics-support.ts
1123
1051
  const CODEX_DIAGNOSTICS_SOURCE = "openclaw-diagnostics";
@@ -1137,16 +1065,11 @@ function normalizeDiagnosticsReason(note) {
1137
1065
  }
1138
1066
  function parseDiagnosticsArgs(args) {
1139
1067
  const [action, token, ...extra] = splitArgs(args);
1140
- const normalizedAction = action?.toLowerCase();
1141
- if ((normalizedAction === "confirm" || normalizedAction === "--confirm") && token && extra.length === 0) return {
1142
- action: "confirm",
1068
+ const normalizedAction = action?.toLowerCase().replace(/^--/, "");
1069
+ if (normalizedAction === "confirm" || normalizedAction === "cancel") return token && extra.length === 0 ? {
1070
+ action: normalizedAction,
1143
1071
  token
1144
- };
1145
- if ((normalizedAction === "cancel" || normalizedAction === "--cancel") && token && extra.length === 0) return {
1146
- action: "cancel",
1147
- token
1148
- };
1149
- if (normalizedAction === "confirm" || normalizedAction === "--confirm" || normalizedAction === "cancel" || normalizedAction === "--cancel") return { action: "usage" };
1072
+ } : { action: "usage" };
1150
1073
  return {
1151
1074
  action: "request",
1152
1075
  note: args
@@ -1202,27 +1125,14 @@ function readCodexDiagnosticsConfirmationScope(ctx) {
1202
1125
  }
1203
1126
  function readCodexDiagnosticsScopeMismatch(pending, ctx) {
1204
1127
  const current = readCodexDiagnosticsConfirmationScope(ctx);
1205
- if (pending.accountId !== current.accountId) return {
1206
- confirmMessage: "This Codex diagnostics confirmation belongs to a different account.",
1207
- cancelMessage: "This Codex diagnostics confirmation belongs to a different account."
1208
- };
1128
+ if (pending.accountId !== current.accountId) return "This Codex diagnostics confirmation belongs to a different account.";
1209
1129
  if (pending.privateRouted) return;
1210
- if (pending.channelId !== current.channelId) return {
1211
- confirmMessage: "This Codex diagnostics confirmation belongs to a different channel instance.",
1212
- cancelMessage: "This Codex diagnostics confirmation belongs to a different channel instance."
1213
- };
1214
- if (pending.messageThreadId !== current.messageThreadId) return {
1215
- confirmMessage: "This Codex diagnostics confirmation belongs to a different thread.",
1216
- cancelMessage: "This Codex diagnostics confirmation belongs to a different thread."
1217
- };
1218
- if (pending.threadParentId !== current.threadParentId) return {
1219
- confirmMessage: "This Codex diagnostics confirmation belongs to a different parent thread.",
1220
- cancelMessage: "This Codex diagnostics confirmation belongs to a different parent thread."
1221
- };
1222
- if (pending.sessionKey !== current.sessionKey) return {
1223
- confirmMessage: "This Codex diagnostics confirmation belongs to a different session.",
1224
- cancelMessage: "This Codex diagnostics confirmation belongs to a different session."
1225
- };
1130
+ for (const [field, label] of [
1131
+ ["channelId", "channel instance"],
1132
+ ["messageThreadId", "thread"],
1133
+ ["threadParentId", "parent thread"],
1134
+ ["sessionKey", "session"]
1135
+ ]) if (pending[field] !== current[field]) return `This Codex diagnostics confirmation belongs to a different ${label}.`;
1226
1136
  }
1227
1137
  function readPendingCodexDiagnosticsConfirmation(token, now) {
1228
1138
  prunePendingCodexDiagnosticsConfirmations(now);
@@ -1299,13 +1209,13 @@ function formatCodexDiagnosticsTargetLine(target) {
1299
1209
  }
1300
1210
  function readCodexDiagnosticsTargetsCooldownMessage(targets, ctx, now, options = {}) {
1301
1211
  for (const target of targets) {
1302
- const cooldownMs = readCodexDiagnosticsCooldownMs(target.threadId, now);
1212
+ const cooldownMs = readCodexDiagnosticsCooldownMs(lastCodexDiagnosticsUploadByThread, target.threadId, now);
1303
1213
  if (cooldownMs > 0) {
1304
1214
  if (options.includeThreadId === false) return `Codex diagnostics were already sent for one of these Codex threads recently. Try again in ${Math.ceil(cooldownMs / 1e3)}s.`;
1305
1215
  return `Codex diagnostics were already sent for thread ${formatCodexDisplayText(target.threadId)} recently. Try again in ${Math.ceil(cooldownMs / 1e3)}s.`;
1306
1216
  }
1307
1217
  }
1308
- const scopeCooldownMs = readCodexDiagnosticsScopeCooldownMs(options.cooldownScope ?? readCodexDiagnosticsCooldownScope(ctx), now);
1218
+ const scopeCooldownMs = readCodexDiagnosticsCooldownMs(lastCodexDiagnosticsUploadByScope, options.cooldownScope ?? readCodexDiagnosticsCooldownScope(ctx), now);
1309
1219
  if (scopeCooldownMs > 0) return `Codex diagnostics were already sent for this account or channel recently. Try again in ${Math.ceil(scopeCooldownMs / 1e3)}s.`;
1310
1220
  }
1311
1221
  function recordCodexDiagnosticsUpload(threadId, ctx, now, cooldownScope) {
@@ -1327,30 +1237,22 @@ function readCodexDiagnosticsCooldownScope(ctx) {
1327
1237
  return crypto.createHash("sha256").update(payload).digest("hex");
1328
1238
  }
1329
1239
  function buildDiagnosticsTags(ctx) {
1330
- const tags = { source: CODEX_DIAGNOSTICS_SOURCE };
1331
- addTag(tags, "channel", ctx.channel);
1332
- return tags;
1333
- }
1334
- function addTag(tags, key, value) {
1335
- if (typeof value === "string" && value.trim()) tags[key] = value.trim();
1240
+ const channel = normalizeOptionalString(ctx.channel);
1241
+ return {
1242
+ source: CODEX_DIAGNOSTICS_SOURCE,
1243
+ ...channel ? { channel } : {}
1244
+ };
1336
1245
  }
1337
1246
  function formatCodexCopyableValueForDisplay(value) {
1338
1247
  const safe = formatCodexTextForDisplay(value);
1339
1248
  if (CODEX_RESUME_SAFE_THREAD_ID_PATTERN.test(safe)) return `\`${safe}\``;
1340
1249
  return escapeCodexChatText(safe);
1341
1250
  }
1342
- function readCodexDiagnosticsCooldownMs(threadId, now) {
1343
- const lastSentAt = lastCodexDiagnosticsUploadByThread.get(threadId);
1344
- if (!lastSentAt) return 0;
1345
- const remainingMs = Math.max(0, CODEX_DIAGNOSTICS_COOLDOWN_MS - (now - lastSentAt));
1346
- if (remainingMs === 0) lastCodexDiagnosticsUploadByThread.delete(threadId);
1347
- return remainingMs;
1348
- }
1349
- function readCodexDiagnosticsScopeCooldownMs(scope, now) {
1350
- const lastSentAt = lastCodexDiagnosticsUploadByScope.get(scope);
1251
+ function readCodexDiagnosticsCooldownMs(map, key, now) {
1252
+ const lastSentAt = map.get(key);
1351
1253
  if (!lastSentAt) return 0;
1352
1254
  const remainingMs = Math.max(0, CODEX_DIAGNOSTICS_COOLDOWN_MS - (now - lastSentAt));
1353
- if (remainingMs === 0) lastCodexDiagnosticsUploadByScope.delete(scope);
1255
+ if (remainingMs === 0) map.delete(key);
1354
1256
  return remainingMs;
1355
1257
  }
1356
1258
  function recordBoundedCodexDiagnosticsCooldown(map, key, maxSize, now) {
@@ -1544,6 +1446,7 @@ function resolveCodexConversationControlScope(ctx) {
1544
1446
  }
1545
1447
  //#endregion
1546
1448
  //#region extensions/codex/src/command-diagnostics.ts
1449
+ const NO_DIAGNOSTICS_THREAD = ["No Codex thread is attached to this OpenClaw session yet.", "Use /codex threads to find a thread, then /codex resume <thread-id> before sending diagnostics."].join("\n");
1547
1450
  async function handleCodexDiagnosticsFeedback(deps, context, pluginConfig, args, commandPrefix) {
1548
1451
  const ctx = { ...context };
1549
1452
  if (ctx.senderIsOwner !== true) return { text: "Only an owner can send Codex diagnostics." };
@@ -1556,9 +1459,8 @@ async function handleCodexDiagnosticsFeedback(deps, context, pluginConfig, args,
1556
1459
  return await requestCodexDiagnosticsFeedbackApproval(deps, ctx, parsed.note, commandPrefix);
1557
1460
  }
1558
1461
  async function requestCodexDiagnosticsFeedbackApproval(deps, ctx, note, commandPrefix) {
1559
- if (!await hasAnyCodexDiagnosticsIdentity(ctx)) return { text: "Cannot send Codex diagnostics because this command did not include a stable session identity." };
1560
- const targets = await resolveCodexDiagnosticsTargets(deps, ctx);
1561
- if (targets.length === 0) return { text: ["No Codex thread is attached to this OpenClaw session yet.", "Use /codex threads to find a thread, then /codex resume <thread-id> before sending diagnostics."].join("\n") };
1462
+ const targets = await requireCodexDiagnosticsTargets(deps, ctx);
1463
+ if (typeof targets === "string") return { text: targets };
1562
1464
  const now = Date.now();
1563
1465
  const cooldownMessage = readCodexDiagnosticsTargetsCooldownMessage(targets, ctx, now);
1564
1466
  if (cooldownMessage) return { text: cooldownMessage };
@@ -1612,9 +1514,8 @@ async function requestCodexDiagnosticsFeedbackApproval(deps, ctx, note, commandP
1612
1514
  };
1613
1515
  }
1614
1516
  async function previewCodexDiagnosticsFeedbackApproval(deps, ctx, note) {
1615
- if (!await hasAnyCodexDiagnosticsIdentity(ctx)) return "Cannot send Codex diagnostics because this command did not include a stable session identity.";
1616
- const targets = await resolveCodexDiagnosticsTargets(deps, ctx);
1617
- if (targets.length === 0) return ["No Codex thread is attached to this OpenClaw session yet.", "Use /codex threads to find a thread, then /codex resume <thread-id> before sending diagnostics."].join("\n");
1517
+ const targets = await requireCodexDiagnosticsTargets(deps, ctx);
1518
+ if (typeof targets === "string") return targets;
1618
1519
  const cooldownMessage = readCodexDiagnosticsTargetsCooldownMessage(targets, ctx, Date.now(), { includeThreadId: false });
1619
1520
  if (cooldownMessage) return cooldownMessage;
1620
1521
  const reason = normalizeDiagnosticsReason(note);
@@ -1628,28 +1529,16 @@ async function previewCodexDiagnosticsFeedbackApproval(deps, ctx, note) {
1628
1529
  ].join("\n");
1629
1530
  }
1630
1531
  async function confirmCodexDiagnosticsFeedback(deps, ctx, pluginConfig, token) {
1631
- const pending = readPendingCodexDiagnosticsConfirmation(token, Date.now());
1632
- if (!pending) return "No pending Codex diagnostics confirmation was found. Run /diagnostics again to create a fresh request.";
1633
- if (!pending.senderId || !ctx.senderId) return "Cannot confirm Codex diagnostics because this command did not include the original sender identity.";
1634
- if (pending.senderId !== ctx.senderId) return "Only the user who requested these Codex diagnostics can confirm the upload.";
1635
- if (pending.channel !== ctx.channel) return "This Codex diagnostics confirmation belongs to a different channel.";
1636
- const scopeMismatch = readCodexDiagnosticsScopeMismatch(pending, ctx);
1637
- if (scopeMismatch) return scopeMismatch.confirmMessage;
1638
- deletePendingCodexDiagnosticsConfirmation(token);
1532
+ const pending = consumeCodexDiagnosticsConfirmation(ctx, token, "confirm");
1533
+ if (typeof pending === "string") return pending;
1639
1534
  if (!pending.privateRouted && !await hasAnyCodexDiagnosticsIdentity(ctx)) return "Cannot send Codex diagnostics because this command did not include a stable session identity.";
1640
1535
  const currentTargets = pending.privateRouted ? resolvePendingCodexDiagnosticsTargets(deps, pending.targets, ctx.config) : await resolveCodexDiagnosticsTargets(deps, ctx);
1641
1536
  if (!codexDiagnosticsTargetsMatch(pending.targets, currentTargets)) return "The Codex diagnostics sessions changed before confirmation. Run /diagnostics again for the current threads.";
1642
1537
  return await sendCodexDiagnosticsFeedbackForTargets(deps, ctx, pluginConfig, pending.note ?? "", currentTargets, { cooldownScope: pending.scopeKey });
1643
1538
  }
1644
1539
  function cancelCodexDiagnosticsFeedback(ctx, token) {
1645
- const pending = readPendingCodexDiagnosticsConfirmation(token, Date.now());
1646
- if (!pending) return "No pending Codex diagnostics confirmation was found.";
1647
- if (!pending.senderId || !ctx.senderId) return "Cannot cancel Codex diagnostics because this command did not include the original sender identity.";
1648
- if (pending.senderId !== ctx.senderId) return "Only the user who requested these Codex diagnostics can cancel the upload.";
1649
- if (pending.channel !== ctx.channel) return "This Codex diagnostics confirmation belongs to a different channel.";
1650
- const scopeMismatch = readCodexDiagnosticsScopeMismatch(pending, ctx);
1651
- if (scopeMismatch) return scopeMismatch.cancelMessage;
1652
- deletePendingCodexDiagnosticsConfirmation(token);
1540
+ const pending = consumeCodexDiagnosticsConfirmation(ctx, token, "cancel");
1541
+ if (typeof pending === "string") return pending;
1653
1542
  return [
1654
1543
  "Codex diagnostics upload canceled.",
1655
1544
  "Codex sessions:",
@@ -1657,13 +1546,12 @@ function cancelCodexDiagnosticsFeedback(ctx, token) {
1657
1546
  ].join("\n");
1658
1547
  }
1659
1548
  async function sendCodexDiagnosticsFeedbackForContext(deps, ctx, pluginConfig, note) {
1660
- if (!await hasAnyCodexDiagnosticsIdentity(ctx)) return "Cannot send Codex diagnostics because this command did not include a stable session identity.";
1661
- const targets = await resolveCodexDiagnosticsTargets(deps, ctx);
1662
- if (targets.length === 0) return ["No Codex thread is attached to this OpenClaw session yet.", "Use /codex threads to find a thread, then /codex resume <thread-id> before sending diagnostics."].join("\n");
1549
+ const targets = await requireCodexDiagnosticsTargets(deps, ctx);
1550
+ if (typeof targets === "string") return targets;
1663
1551
  return await sendCodexDiagnosticsFeedbackForTargets(deps, ctx, pluginConfig, note, targets);
1664
1552
  }
1665
1553
  async function sendCodexDiagnosticsFeedbackForTargets(deps, ctx, pluginConfig, note, targets, options = {}) {
1666
- if (targets.length === 0) return ["No Codex thread is attached to this OpenClaw session yet.", "Use /codex threads to find a thread, then /codex resume <thread-id> before sending diagnostics."].join("\n");
1554
+ if (targets.length === 0) return NO_DIAGNOSTICS_THREAD;
1667
1555
  const now = Date.now();
1668
1556
  const cooldownMessage = readCodexDiagnosticsTargetsCooldownMessage(targets, ctx, now, { cooldownScope: options.cooldownScope });
1669
1557
  if (cooldownMessage) return cooldownMessage;
@@ -1724,6 +1612,22 @@ async function sendCodexDiagnosticsFeedbackForTargets(deps, ctx, pluginConfig, n
1724
1612
  }
1725
1613
  return formatCodexDiagnosticsUploadResult(sent, failed);
1726
1614
  }
1615
+ function consumeCodexDiagnosticsConfirmation(ctx, token, action) {
1616
+ const pending = readPendingCodexDiagnosticsConfirmation(token, Date.now());
1617
+ if (!pending) return action === "confirm" ? "No pending Codex diagnostics confirmation was found. Run /diagnostics again to create a fresh request." : "No pending Codex diagnostics confirmation was found.";
1618
+ if (!pending.senderId || !ctx.senderId) return `Cannot ${action} Codex diagnostics because this command did not include the original sender identity.`;
1619
+ if (pending.senderId !== ctx.senderId) return `Only the user who requested these Codex diagnostics can ${action} the upload.`;
1620
+ if (pending.channel !== ctx.channel) return "This Codex diagnostics confirmation belongs to a different channel.";
1621
+ const scopeMismatch = readCodexDiagnosticsScopeMismatch(pending, ctx);
1622
+ if (scopeMismatch) return scopeMismatch;
1623
+ deletePendingCodexDiagnosticsConfirmation(token);
1624
+ return pending;
1625
+ }
1626
+ async function requireCodexDiagnosticsTargets(deps, ctx) {
1627
+ if (!await hasAnyCodexDiagnosticsIdentity(ctx)) return "Cannot send Codex diagnostics because this command did not include a stable session identity.";
1628
+ const targets = await resolveCodexDiagnosticsTargets(deps, ctx);
1629
+ return targets.length > 0 ? targets : NO_DIAGNOSTICS_THREAD;
1630
+ }
1727
1631
  async function hasAnyCodexDiagnosticsIdentity(ctx) {
1728
1632
  if (await resolveControlTarget(ctx)) return true;
1729
1633
  return (ctx.diagnosticsSessions ?? []).some((session) => Boolean(session.sessionId));
@@ -2037,7 +1941,10 @@ async function resumeThread(deps, ctx, pluginConfig, args) {
2037
1941
  retained = await retainCodexAppServerBindingSubscription(client, effectiveThreadId, knownOwnership);
2038
1942
  assertCurrent();
2039
1943
  if (!retained) throw new Error("Codex resumed thread lost its native subscription owner.");
2040
- if (bindingBeforeCommit && !sameOwner) await releaseCodexAppServerBindingSubscription(bindingBeforeCommit, { assertCurrent });
1944
+ if (bindingBeforeCommit && !sameOwner) await releaseCodexAppServerBindingSubscription(bindingBeforeCommit, {
1945
+ assertCurrent,
1946
+ retainedClientId: clientId
1947
+ });
2041
1948
  assertCurrent();
2042
1949
  if (!await deps.bindingStore.mutate(identity, {
2043
1950
  kind: "set",
@@ -2538,7 +2445,7 @@ async function handleCodexPluginsSubcommand(input, rest, io, runtime) {
2538
2445
  });
2539
2446
  return formatCodexAvailablePlugins(discovered.plugins, discovered.warnings, query, page);
2540
2447
  } catch (error) {
2541
- return { text: `Could not list Codex plugins: ${formatCodexDisplayText(errorMessage(error))}` };
2448
+ return { text: `Could not list Codex plugins: ${formatCodexDisplayText(coerceErrorMessage(error))}` };
2542
2449
  }
2543
2450
  }
2544
2451
  if (normalized === "status") {
@@ -2710,7 +2617,7 @@ async function installCodexPlugin(requestedId, io, runtime, ctx) {
2710
2617
  if (!plugin) return { text: `Multiple available Codex plugins match '${formatCodexDisplayText(requestedId)}'; the marketplace identity must be unique.` };
2711
2618
  } else plugin = matching[0];
2712
2619
  } catch (error) {
2713
- return { text: `Could not verify the requested Codex plugin: ${formatCodexDisplayText(errorMessage(error))}` };
2620
+ return { text: `Could not verify the requested Codex plugin: ${formatCodexDisplayText(coerceErrorMessage(error))}` };
2714
2621
  }
2715
2622
  if (!plugin) return { text: `${formatCodexDisplayText(requestedId)} was not found. Run /codex plugins available to inspect the current marketplaces.` };
2716
2623
  if (!plugin.available) return { text: `${formatCodexDisplayText(requestedId)} is unavailable or disabled by its marketplace administrator.` };
@@ -2723,7 +2630,7 @@ async function installCodexPlugin(requestedId, io, runtime, ctx) {
2723
2630
  const configured = resolveInstalledPluginKey((await io.readConfig()).plugins ?? {}, plugin);
2724
2631
  if (configured.status === "ambiguous" || configured.status === "mismatched") return { text: describeConfiguredPluginIdentityConflict(requestedId, configured.status) };
2725
2632
  } catch (error) {
2726
- return { text: `Could not verify existing Codex plugin authorization: ${formatCodexDisplayText(errorMessage(error))}` };
2633
+ return { text: `Could not verify existing Codex plugin authorization: ${formatCodexDisplayText(coerceErrorMessage(error))}` };
2727
2634
  }
2728
2635
  let result;
2729
2636
  if (!alreadyInstalled) {
@@ -2739,7 +2646,7 @@ async function installCodexPlugin(requestedId, io, runtime, ctx) {
2739
2646
  assertCodexHostOwnerCurrent(ctx);
2740
2647
  result = await runtime.install(requestParams);
2741
2648
  } catch (error) {
2742
- return { text: `Could not install ${formatCodexDisplayText(requestedId)}: ${formatCodexDisplayText(errorMessage(error))}` };
2649
+ return { text: `Could not install ${formatCodexDisplayText(requestedId)}: ${formatCodexDisplayText(coerceErrorMessage(error))}` };
2743
2650
  }
2744
2651
  }
2745
2652
  const selectedPlugin = plugin;
@@ -2763,13 +2670,13 @@ async function installCodexPlugin(requestedId, io, runtime, ctx) {
2763
2670
  block.plugins[configKey] = updated;
2764
2671
  }, () => assertCodexHostOwnerCurrent(ctx));
2765
2672
  } catch (error) {
2766
- return { text: `${formatCodexDisplayText(requestedId)} was installed in Codex but could not be authorized in OpenClaw and will not be exposed: ${formatCodexDisplayText(errorMessage(error))}` };
2673
+ return { text: `${formatCodexDisplayText(requestedId)} was installed in Codex but could not be authorized in OpenClaw and will not be exposed: ${formatCodexDisplayText(coerceErrorMessage(error))}` };
2767
2674
  }
2768
2675
  let refreshWarning = "";
2769
2676
  if (runtime.refresh) try {
2770
2677
  refreshWarning = (await runtime.refresh(workspaceDir)).diagnostics.map((diagnostic) => ` ${formatCodexDisplayText(diagnostic.message)}`).join("");
2771
2678
  } catch (error) {
2772
- refreshWarning = ` Runtime refresh requires a new conversation: ${formatCodexDisplayText(errorMessage(error))}`;
2679
+ refreshWarning = ` Runtime refresh requires a new conversation: ${formatCodexDisplayText(coerceErrorMessage(error))}`;
2773
2680
  }
2774
2681
  const appsNeedingAuth = result?.appsNeedingAuth ?? [];
2775
2682
  if (appsNeedingAuth.length > 0) {
@@ -2801,22 +2708,7 @@ async function installCodexPlugin(requestedId, io, runtime, ctx) {
2801
2708
  type: "text",
2802
2709
  text: `Some app setup permissions could not be confirmed. Run /codex plugins status ${requestedId} to check the current account and restrictions.`
2803
2710
  }] : [],
2804
- {
2805
- type: "buttons",
2806
- buttons: [...appLinks.length > 0 ? [{
2807
- label: "Refresh hosted apps",
2808
- action: {
2809
- type: "command",
2810
- command: "/codex plugins refresh"
2811
- }
2812
- }] : [], {
2813
- label: "Check status",
2814
- action: {
2815
- type: "command",
2816
- command: `/codex plugins status ${requestedId}`
2817
- }
2818
- }]
2819
- },
2711
+ buildCodexPluginStatusButtons(requestedId, appLinks.length > 0),
2820
2712
  {
2821
2713
  type: "context",
2822
2714
  text: `${refreshWarning.trim()} ${POLICY_REFRESH_HINT}`.trim()
@@ -2832,9 +2724,6 @@ async function installCodexPlugin(requestedId, io, runtime, ctx) {
2832
2724
  const status = alreadyInstalled ? "bundle was already installed in Codex" : "bundle was installed in Codex";
2833
2725
  return { text: `${formatCodexDisplayText(requestedId)} ${status}. OpenClaw app access is configured.${refreshWarning} ${POLICY_REFRESH_HINT}` };
2834
2726
  }
2835
- function errorMessage(error) {
2836
- return error instanceof Error ? error.message : String(error);
2837
- }
2838
2727
  function formatPluginList(plugins, options = {}) {
2839
2728
  const globalEnabled = options.globalEnabled === true;
2840
2729
  const keys = Object.keys(plugins).toSorted();
@@ -3002,6 +2891,17 @@ async function handleCodexSubcommand(ctx, options) {
3002
2891
  if (CODEX_NATIVE_CONTROL_SUBCOMMANDS.has(normalized) && !returnsBeforeNativeCodexExecution(normalized, rest) && !isReadOnlyCodexGoalCommand(normalized, rest) && !canMutateCodexHost(ctx)) return { text: CODEX_NATIVE_EXECUTION_AUTH_ERROR };
3003
2892
  const sandboxBlock = resolveCodexNativeCommandSandboxBlock(ctx, normalized, rest);
3004
2893
  if (sandboxBlock) return { text: sandboxBlock };
2894
+ const usageCommand = normalized === "unbind" ? "detach" : normalized;
2895
+ if (rest.length > 0 && [
2896
+ "status",
2897
+ "models",
2898
+ "detach",
2899
+ "binding",
2900
+ "stop",
2901
+ "mcp",
2902
+ "skills",
2903
+ "account"
2904
+ ].includes(usageCommand)) return { text: `Usage: /codex ${usageCommand}` };
3005
2905
  if (normalized === "plugins") {
3006
2906
  if (rest[0]?.toLowerCase() === "refresh") {
3007
2907
  if (rest.length !== 1) return { text: "Usage: /codex plugins refresh — refresh hosted app inventory for the current Codex account/runtime." };
@@ -3090,12 +2990,10 @@ async function handleCodexSubcommand(ctx, options) {
3090
2990
  });
3091
2991
  }
3092
2992
  if (normalized === "status") {
3093
- if (rest.length > 0) return { text: "Usage: /codex status" };
3094
2993
  const { agentDir } = resolveCodexConversationControlScope(ctx);
3095
2994
  return { text: formatCodexStatus(await deps.readCodexStatusProbes(options.pluginConfig, ctx.config, agentDir)) };
3096
2995
  }
3097
2996
  if (normalized === "models") {
3098
- if (rest.length > 0) return { text: "Usage: /codex models" };
3099
2997
  const { agentDir } = resolveCodexConversationControlScope(ctx);
3100
2998
  return { text: formatModels(await deps.listCodexAppServerModels(deps.requestOptions(options.pluginConfig, 100, ctx.config, agentDir))) };
3101
2999
  }
@@ -3104,18 +3002,9 @@ async function handleCodexSubcommand(ctx, options) {
3104
3002
  if (normalized === "sessions") return { text: await buildCodexCliSessions(deps, rest) };
3105
3003
  if (normalized === "resume") return { text: await resumeThread(deps, ctx, options.pluginConfig, rest) };
3106
3004
  if (normalized === "bind") return await bindConversation(deps, ctx, options.pluginConfig, rest);
3107
- if (normalized === "detach" || normalized === "unbind") {
3108
- if (rest.length > 0) return { text: "Usage: /codex detach" };
3109
- return { text: await detachConversation(deps, ctx) };
3110
- }
3111
- if (normalized === "binding") {
3112
- if (rest.length > 0) return { text: "Usage: /codex binding" };
3113
- return { text: await describeConversationBinding(deps, ctx) };
3114
- }
3115
- if (normalized === "stop") {
3116
- if (rest.length > 0) return { text: "Usage: /codex stop" };
3117
- return { text: await stopConversationTurn(deps, ctx) };
3118
- }
3005
+ if (normalized === "detach" || normalized === "unbind") return { text: await detachConversation(deps, ctx) };
3006
+ if (normalized === "binding") return { text: await describeConversationBinding(deps, ctx) };
3007
+ if (normalized === "stop") return { text: await stopConversationTurn(deps, ctx) };
3119
3008
  if (normalized === "steer") return { text: await steerConversationTurn(deps, ctx, rest.join(" ")) };
3120
3009
  if (normalized === "model") return { text: await setConversationModel(deps, ctx, options.pluginConfig, rest) };
3121
3010
  if (normalized === "fast") {
@@ -3126,31 +3015,21 @@ async function handleCodexSubcommand(ctx, options) {
3126
3015
  if (isMenuVerb(rest)) return buildCodexPermissionsMenuReply();
3127
3016
  return { text: await setConversationPermissions(deps, ctx, rest) };
3128
3017
  }
3129
- if (normalized === "compact") return { text: await startThreadAction(deps, ctx, options.pluginConfig, "compact", rest) };
3130
- if (normalized === "review") return { text: await startThreadAction(deps, ctx, options.pluginConfig, "review", rest) };
3018
+ if (normalized === "compact" || normalized === "review") return { text: await startThreadAction(deps, ctx, options.pluginConfig, normalized, rest) };
3131
3019
  if (normalized === "diagnostics") return await handleCodexDiagnosticsFeedback(deps, ctx, options.pluginConfig, rest.join(" "), "/codex diagnostics");
3132
3020
  if (normalized === "computer-use" || normalized === "computeruse") {
3133
3021
  if (isMenuVerb(rest)) return buildCodexComputerUseMenuReply();
3134
3022
  return { text: await handleComputerUseCommand(deps, ctx, options.pluginConfig, rest) };
3135
3023
  }
3136
- if (normalized === "mcp") {
3137
- if (rest.length > 0) return { text: "Usage: /codex mcp" };
3138
- const scope = await resolveCommandAppServerScope(deps, ctx, options.pluginConfig);
3139
- return { text: formatList(await deps.codexControlRequest(options.pluginConfig, CODEX_CONTROL_METHODS.listMcpServers, { limit: 100 }, {
3140
- config: ctx.config,
3141
- ...scope
3142
- }), "MCP servers") };
3143
- }
3144
- if (normalized === "skills") {
3145
- if (rest.length > 0) return { text: "Usage: /codex skills" };
3024
+ if (normalized === "mcp" || normalized === "skills") {
3146
3025
  const scope = await resolveCommandAppServerScope(deps, ctx, options.pluginConfig);
3147
- return { text: formatSkills(await deps.codexControlRequest(options.pluginConfig, CODEX_CONTROL_METHODS.listSkills, {}, {
3026
+ const response = await deps.codexControlRequest(options.pluginConfig, normalized === "mcp" ? CODEX_CONTROL_METHODS.listMcpServers : CODEX_CONTROL_METHODS.listSkills, normalized === "mcp" ? { limit: 100 } : {}, {
3148
3027
  config: ctx.config,
3149
3028
  ...scope
3150
- })) };
3029
+ });
3030
+ return { text: normalized === "mcp" ? formatList(response, "MCP servers") : formatSkills(response) };
3151
3031
  }
3152
3032
  if (normalized === "account") {
3153
- if (rest.length > 0) return { text: "Usage: /codex account" };
3154
3033
  const scope = await resolveCommandAppServerScope(deps, ctx, options.pluginConfig);
3155
3034
  const requestScope = {
3156
3035
  config: ctx.config,