@openclaw/codex 2026.9.5 → 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.
- package/README.md +2 -0
- package/assets/icon.png +0 -0
- package/dist/.setup/{account-usage-runtime-C2MOIvfq.mjs → account-usage-runtime-DFhbh1zz.mjs} +6 -6
- package/dist/.setup/{apply-CJ0ZfmBG.mjs → apply-D3GcSoSa.mjs} +35 -55
- package/dist/.setup/{attempt-client-cleanup-BpYKdTA0.mjs → attempt-client-cleanup-DOP-cW5j.mjs} +179 -73
- package/dist/.setup/attempt-workspace-context-C5HigshI.mjs +164 -0
- package/dist/.setup/{auth-binding-DhLWa_7K.mjs → auth-binding-BLWz7stm.mjs} +14 -1
- package/dist/.setup/{auth-cache-key-QirmgiCo.mjs → auth-cache-key-Dbvq-QgB.mjs} +41 -111
- package/dist/.setup/{auth-profile-WqZtZfXN.mjs → auth-profile-B0okYl2D.mjs} +1 -2
- package/dist/.setup/auth-profile-health-oHizqgye.mjs +53 -0
- package/dist/.setup/auth-profile-recovery-BREezV0L.mjs +14 -0
- package/dist/.setup/auth-start-options-BPIPeEX8.mjs +44 -0
- package/dist/.setup/{binding-connection-Bm38niE8.mjs → binding-connection-DTtN1KrX.mjs} +2 -2
- package/dist/.setup/{binding-connection.runtime-CnRMC0ta.mjs → binding-connection.runtime-6TpgD1M6.mjs} +5 -5
- package/dist/.setup/{bounded-turn-BtlZcivC.mjs → bounded-turn-CbjoN2OW.mjs} +140 -37
- package/dist/.setup/bounded-turn-isolation-B8K_ylqk.mjs +14 -0
- package/dist/.setup/{build-state-Xx9ybZqa.mjs → build-state-Da1_z0kd.mjs} +1 -1
- package/dist/.setup/{capabilities-_vXcZGSx.mjs → capabilities-B3WEZl4e.mjs} +2 -10
- package/dist/.setup/{client-vXs2929Q.mjs → client-N0JpgSzF.mjs} +635 -872
- package/dist/.setup/client-catalog-response-5HHLdcde.mjs +285 -0
- package/dist/.setup/{command-dispatch-naHIZwwF.mjs → command-dispatch-BeAoaovI.mjs} +9 -8
- package/dist/.setup/{command-formatters-CGEkdawF.mjs → command-formatters-R3ckE3Co.mjs} +36 -64
- package/dist/.setup/{command-handlers-BtAJEW1X.mjs → command-handlers-ylTMS00z.mjs} +301 -488
- package/dist/.setup/{command-rpc-DHFpn4le.mjs → command-rpc-CGJGUQ6Y.mjs} +40 -28
- package/dist/.setup/compact-C2WamavS.mjs +776 -0
- package/dist/.setup/{config-CedDWjM-.mjs → config-DKhXquav.mjs} +26 -28
- package/dist/.setup/{config-options-BsanJ8QG.mjs → config-options-CzyWLTJt.mjs} +68 -65
- package/dist/.setup/{config-parsing-CcB9iPoq.mjs → config-parsing-b088LyhT.mjs} +57 -60
- package/dist/.setup/{config-runtime-CeAhl_h4.mjs → config-runtime-C0NbLms1.mjs} +2 -2
- package/dist/.setup/{config-security-BRQ2mgW9.mjs → config-security-CE-FcGw9.mjs} +51 -215
- package/dist/.setup/{config-utils-DujwEnhg.mjs → config-utils-D0CXecki.mjs} +3 -13
- package/dist/.setup/context-engine-projection-PezSESth.mjs +387 -0
- package/dist/.setup/{conversation-binding-DhzrpTM6.mjs → conversation-binding-3Min8qvP.mjs} +71 -105
- package/dist/.setup/{conversation-binding-data-CrcyZk6O.mjs → conversation-binding-data-C746z5Pn.mjs} +8 -12
- package/dist/.setup/{conversation-control-DN53ns41.mjs → conversation-control-CEP8X5JC.mjs} +30 -69
- package/dist/.setup/{cyber-failover-DYwbmf1o.mjs → cyber-failover-XV0nNRZu.mjs} +1 -1
- package/dist/.setup/{cyber-failover-notice-e9G3J9-e.mjs → cyber-failover-notice-RNpGpTyP.mjs} +1 -1
- package/dist/.setup/{dynamic-tools-D16lOp67.mjs → dynamic-tools-DzlsLUuS.mjs} +3136 -3167
- package/dist/.setup/{effective-mcp-catalog-K6kLCN8X.mjs → effective-mcp-catalog-CxUtC-xG.mjs} +8 -17
- package/dist/.setup/{ephemeral-turn-R1gA8Sn6.mjs → ephemeral-turn-CDsPJOa2.mjs} +9 -6
- package/dist/.setup/event-projector-assistant-message-CigreO4K.mjs +69 -0
- package/dist/.setup/{event-projector-usage-C7Ntzs-f.mjs → event-projector-usage-03R0I2dM.mjs} +4 -26
- package/dist/.setup/event-projector-values-DJSz8BTk.mjs +106 -0
- package/dist/.setup/incognito-session-DWYapfwf.mjs +2 -0
- package/dist/.setup/{inference-context-fulhZuz8.mjs → inference-context-D-9gWlTR.mjs} +16 -18
- package/dist/.setup/inference-dispatch-CMZtjQyz.mjs +359 -0
- package/dist/.setup/inference-metadata-CgIf7sOx.mjs +81 -0
- package/dist/.setup/inference-proxy-DhcXOgUE.mjs +561 -0
- package/dist/.setup/{isolated-completion-B6srt48J.mjs → isolated-completion-Dm3PzxJk.mjs} +15 -11
- package/dist/.setup/launch-args-DbFCehO7.mjs +196 -0
- package/dist/.setup/{managed-binary-DP6Rib3P.mjs → managed-binary-kiWRhNRE.mjs} +16 -9
- package/dist/.setup/{model-catalog-DkvUuBey.mjs → model-catalog-PAuZgJC6.mjs} +14 -14
- package/dist/.setup/model-runtime-BdqzOMkU.mjs +11 -0
- package/dist/.setup/{models-BDFgm_G-.mjs → models-DHXZtVVk.mjs} +9 -18
- package/dist/.setup/{native-auth-BLZGqFjw.mjs → native-auth-CuG53tu4.mjs} +5 -5
- package/dist/.setup/{native-execution-policy-YBMHSzC4.mjs → native-execution-policy-BxZJy5mP.mjs} +6 -31
- package/dist/.setup/{native-subagent-monitor-B1hxzIOy.mjs → native-subagent-monitor-Dpsmf2wz.mjs} +4422 -3808
- package/dist/.setup/native-subagent-pending-assignments-DwkCzLvD.mjs +203 -0
- package/dist/.setup/native-task-assignments-DMQ0g3hu.mjs +194 -0
- package/dist/.setup/{node-cli-sessions-Cl8b2ZF3.mjs → node-cli-sessions-HC4W6FLI.mjs} +99 -111
- package/dist/.setup/node-exec-server.runtime-BgBfWQqo.mjs +244 -0
- package/dist/.setup/{plan-xD7WKYTM.mjs → plan-Y-QIvrKB.mjs} +118 -163
- package/dist/.setup/{plugin-activation-r8nq5Jzp.mjs → plugin-activation-cNHRfaxU.mjs} +10 -47
- package/dist/.setup/{plugin-app-cache-key-BOxKP7db.mjs → plugin-app-cache-key-BL9B5H0L.mjs} +9 -42
- package/dist/.setup/{plugin-inventory-DUle8DLz.mjs → plugin-inventory-Cky2XJUw.mjs} +32 -23
- package/dist/.setup/{plugin-marketplace-discovery-P-Vndfqq.mjs → plugin-marketplace-discovery-D_dV9FXa.mjs} +22 -25
- package/dist/.setup/{plugin-metadata-cache-DsS5buNa.mjs → plugin-metadata-cache-DsjsL1dr.mjs} +328 -318
- package/dist/.setup/protocol-CANUwXJ3.mjs +17 -0
- package/dist/.setup/provider-DH8NSzGt.mjs +51 -0
- package/dist/.setup/{provider-capabilities-B8J4Dy-O.mjs → provider-capabilities-CAxoF-X1.mjs} +35 -12
- package/dist/.setup/{rate-limits-DOEGYRNs.mjs → rate-limits-B7-X2TgG.mjs} +123 -166
- package/dist/.setup/{request-BioXJLYa.mjs → request-BHZ1nz8d.mjs} +25 -16
- package/dist/.setup/responses-oauth-twnuTaAa.mjs +93 -0
- package/dist/.setup/rpc-error-BlD2vuzn.mjs +31 -0
- package/dist/.setup/{run-attempt-rlA07pUv.mjs → run-attempt-D8RZUOzY.mjs} +2046 -1454
- package/dist/.setup/{run-attempt-lifecycle-B7JbY4-F.mjs → run-attempt-lifecycle-C-6O3Exn.mjs} +10 -24
- package/dist/.setup/{runtime-artifact-Dy38Z5iU.mjs → runtime-artifact-DDQ-HGXf.mjs} +43 -47
- package/dist/.setup/runtime-artifact-connection-D68qQn1m.mjs +78 -0
- package/dist/.setup/sandbox-guard-DjCz2eOw.mjs +126 -0
- package/dist/.setup/scope-DOC1Xjc8.mjs +6 -0
- package/dist/.setup/session-binding-DGCYAfvD.mjs +443 -0
- package/dist/.setup/{session-binding-record-TH3xA0zj.mjs → session-binding-record-Oe9L-CNY.mjs} +73 -132
- package/dist/.setup/{session-binding-sidecars-CKYEcfNn.mjs → session-binding-sidecars-jo6H8dFr.mjs} +242 -60
- package/dist/.setup/{session-catalog-fUdWDx-U.mjs → session-catalog-4sCdv5qx.mjs} +598 -452
- package/dist/.setup/{session-catalog-adoption-CR_whkEW.mjs → session-catalog-adoption-BU_pHWG7.mjs} +59 -26
- package/dist/.setup/{session-catalog-archive-CwZaPacf.mjs → session-catalog-archive-spHfihri.mjs} +7 -7
- package/dist/.setup/session-catalog-events-DePDzzjc.mjs +139 -0
- package/dist/.setup/session-catalog-home-id-vlih0B_g.mjs +22 -0
- package/dist/.setup/{session-catalog-index-B141u15s.mjs → session-catalog-index-CZvDzC6z.mjs} +286 -182
- package/dist/.setup/{session-catalog-index-order-Cc5BzlQr.mjs → session-catalog-index-order-BcQpHks3.mjs} +2 -2
- package/dist/.setup/{session-catalog-index-state-BAuDztHN.mjs → session-catalog-index-state-TeO7EyO-.mjs} +6 -2
- package/dist/.setup/session-catalog-limits-DDxOsQeC.mjs +14 -0
- package/dist/.setup/session-catalog-list-request-CvtxrYSe.mjs +170 -0
- package/dist/.setup/session-catalog-native-projection-DjhwGL6x.mjs +178 -0
- package/dist/.setup/{session-catalog-node-adoption-BVRsYOSh.mjs → session-catalog-node-adoption-DgXvSGu0.mjs} +30 -35
- package/dist/.setup/{session-catalog-node-continue-Dowv8osw.mjs → session-catalog-node-continue-DjKXHBbi.mjs} +25 -18
- package/dist/.setup/session-catalog-node-lookup-CtAXI5W5.mjs +56 -0
- package/dist/.setup/{session-catalog-native-projection-ChV3cCtm.mjs → session-catalog-parsing-CPGaPYr-.mjs} +14 -180
- package/dist/.setup/{session-catalog-projection-C1Bj9Jl-.mjs → session-catalog-projection-Cr5qP5Dj.mjs} +15 -5
- package/dist/.setup/session-catalog-provenance-DoAvktcj.mjs +95 -0
- package/dist/.setup/{session-cli-DIj-IE-E.mjs → session-cli-Cn_nCqfq.mjs} +11 -24
- package/dist/.setup/{session-history-C--SrLI8.mjs → session-history-D83lJWHG.mjs} +16 -23
- package/dist/.setup/{session-history-import-JHXT5Xfi.mjs → session-history-import-WhX-X33a.mjs} +7 -10
- package/dist/.setup/session-history-read-Ov3StuL4.mjs +133 -0
- package/dist/.setup/{session-history.worker-CpNj7H_P.mjs → session-history.worker-MnPKncqP.mjs} +14 -23
- package/dist/.setup/session-initialization-6aveB9qb.mjs +22 -0
- package/dist/.setup/{session-permission-policy-DhurXY0l.mjs → session-permission-policy-Ci_fVX6y.mjs} +4 -8
- package/dist/.setup/{session-retirement-CU87AOg9.mjs → session-retirement-qMTxkNx2.mjs} +31 -12
- package/dist/.setup/{settled-turn-context-fmwouT5I.mjs → settled-turn-context-D4yj4rxf.mjs} +1 -1
- package/dist/.setup/{settled-turn-finalizer-CiY2bLFK.mjs → settled-turn-finalizer-BsvEabkw.mjs} +17 -13
- package/dist/.setup/{shared-client-BpTtuLQ5.mjs → shared-client-DqyTMYug.mjs} +826 -485
- package/dist/.setup/shared-client-lifecycle-DJIgqgMw.mjs +153 -0
- package/dist/.setup/{side-question-DSCZyoBD.mjs → side-question-C4kCmQy1.mjs} +206 -334
- package/dist/.setup/{source-Bjp4UQij.mjs → source-CS_7GFJZ.mjs} +82 -139
- package/dist/.setup/spawn-error-CL3n6MAa.mjs +57 -0
- package/dist/.setup/{thread-archive-guard-jmecf6OJ.mjs → thread-archive-guard-C9frICzX.mjs} +10 -3
- package/dist/.setup/thread-lifecycle-DPflntEJ.mjs +2362 -0
- package/dist/.setup/{incognito-session-uhrBF6wJ.mjs → thread-ownership-queue-Dp24d7-F.mjs} +1 -2
- package/dist/.setup/{thread-ownership-skomxnIt.mjs → thread-ownership-roNP0l1c.mjs} +47 -10
- package/dist/.setup/thread-policy-DTd-DtkX.mjs +109 -0
- package/dist/.setup/thread-requests-B_bRnMGN.mjs +2102 -0
- package/dist/.setup/{thread-resume-BkNpj9Pz.mjs → thread-resume-CdDaoc7T.mjs} +6 -6
- package/dist/.setup/timeout-CXOfNoaX.mjs +46 -0
- package/dist/.setup/transcript-history-projection-DRSifI-1.mjs +201 -0
- package/dist/.setup/{transcript-mirror-attestation-CzM-94NC.mjs → transcript-mirror-attestation-YSegaktH.mjs} +3 -4
- package/dist/.setup/{transcript-mirror-D4qp_leP.mjs → transcript-mirror-kxmCYsuF.mjs} +224 -206
- package/dist/.setup/{transport-stdio-Cmx94Oiy.mjs → transport-stdio-Bdegpn2V.mjs} +138 -75
- package/dist/.setup/transport-websocket-BTBE-LD9.mjs +211 -0
- package/dist/.setup/{upstream-prompt-provenance-LphB8slG.mjs → upstream-prompt-provenance-fXkKbPVC.mjs} +3 -9
- package/dist/.setup/{upstream-session-fork-D3UKxgVD.mjs → upstream-session-fork-CBeVjBpT.mjs} +48 -40
- package/dist/.setup/{usage-BOgBEKso.mjs → usage-BMzNxeR_.mjs} +5 -4
- package/dist/.setup/{usage-limit-error-C0ow7DOc.mjs → usage-limit-error-QXerDo3i.mjs} +5 -20
- package/dist/.setup/{web-search-provider.runtime-CTGuJt6i.mjs → web-search-provider.runtime-P77OUeoo.mjs} +10 -20
- package/dist/api.js +25 -16
- package/dist/catalog-page-worker-entrypoint.js +12 -0
- package/dist/catalog-page.worker.js +9 -0
- package/dist/cli-metadata.js +1 -1
- package/dist/doctor-contract-api.js +50 -8
- package/dist/harness.js +344 -1
- package/dist/index.js +345 -346
- package/dist/media-understanding-provider.js +9 -22
- package/dist/migration-provider-api.js +1 -1
- package/dist/provider-discovery.js +1 -1
- package/dist/session-history-worker-runtime.js +16 -33
- package/dist/session-history.worker.js +1 -1
- package/openclaw.plugin.json +14 -2
- package/package.json +11 -7
- package/dist/.setup/attempt-context-VXVwTCfS.mjs +0 -636
- package/dist/.setup/compact-C3i3qlzj.mjs +0 -687
- package/dist/.setup/event-projector-assistant-message-DNUR1s0A.mjs +0 -105
- package/dist/.setup/event-projector-items-DyTQ_XqL.mjs +0 -200
- package/dist/.setup/harness-rxaaoN-o.mjs +0 -349
- package/dist/.setup/history-rejection-B4nOXNXF.mjs +0 -13
- package/dist/.setup/image-payload-sanitizer-tupAr-2o.mjs +0 -79
- package/dist/.setup/inference-proxy-CC15HuSi.mjs +0 -311
- package/dist/.setup/launch-args-DnMak49W.mjs +0 -111
- package/dist/.setup/local-runtime-attribution-B_2mnqhb.mjs +0 -19
- package/dist/.setup/native-subagent-history-YXaL6dMd.mjs +0 -135
- package/dist/.setup/native-subagent-task-ids-DsuOonKv.mjs +0 -411
- package/dist/.setup/node-exec-server.runtime-BaViBKNz.mjs +0 -226
- package/dist/.setup/plugin-approval-roundtrip-CjfzafAZ.mjs +0 -122
- package/dist/.setup/provider-fFh_-VR3.mjs +0 -50
- package/dist/.setup/rolldown-runtime-8H4AJuhK.mjs +0 -14
- package/dist/.setup/sandbox-guard-BBP-RbTf.mjs +0 -166
- package/dist/.setup/session-binding-_0W_fHRr.mjs +0 -721
- package/dist/.setup/session-catalog-events-jMcYfQyd.mjs +0 -250
- package/dist/.setup/session-history-read-B3ZfSUbF.mjs +0 -50
- package/dist/.setup/session-initialization-DH1z6fXn.mjs +0 -75
- package/dist/.setup/thread-history-page-BTx-4xsg.mjs +0 -83
- package/dist/.setup/thread-lifecycle-Cik28qWn.mjs +0 -4904
- package/dist/.setup/thread-policy-Cjs4B8xf.mjs +0 -54
- package/dist/.setup/timeout-DZF05XrR.mjs +0 -63
- package/dist/.setup/transcript-history-projection-DHNBDhCU.mjs +0 -243
- package/dist/.setup/version-CoqzXPgK.mjs +0 -12
|
@@ -1,102 +1,93 @@
|
|
|
1
|
-
import { n as isCodexFastServiceTier } from "./config-utils-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { r as
|
|
8
|
-
import {
|
|
9
|
-
import { s as
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import { t as CODEX_CONTROL_METHODS } from "./capabilities-
|
|
14
|
-
import {
|
|
15
|
-
import { a as defaultCodexAppInventoryCache, r as buildCodexPluginAppCacheKey } from "./plugin-app-cache-key-
|
|
16
|
-
import { i as resolveCodexBindingAppServerConnection } from "./binding-connection-
|
|
17
|
-
import { o as withCodexAppServerJsonClient } from "./request-
|
|
18
|
-
import "./config-
|
|
19
|
-
import { n as resolveCodexAppServerRuntimeOptions } from "./config-runtime-
|
|
20
|
-
import { a as resolveCodexAppServerAuthProfileStore, i as resolveCodexAppServerAuthProfileIdForAgent, n as normalizeCodexAppServerBindingModelProvider } from "./auth-profile-
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import { n as
|
|
26
|
-
import { n as
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import { n as
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
32
|
-
import { a as
|
|
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";
|
|
3
|
+
import { i as isJsonObject } from "./protocol-CANUwXJ3.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";
|
|
41
|
+
import { parseAgentSessionKey } from "openclaw/plugin-sdk/routing";
|
|
39
42
|
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
40
43
|
import { ensureAuthProfileStore, resolveAgentDir as resolveAgentDir$1, resolveAgentWorkspaceDir, resolveAuthProfileEligibility, resolveProfileUnusableUntilForDisplay } from "openclaw/plugin-sdk/agent-runtime";
|
|
41
44
|
import { getSessionEntry, resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
|
|
42
45
|
import { findNormalizedProviderValue, resolveAuthProfileOrder } from "openclaw/plugin-sdk/provider-auth";
|
|
43
|
-
import { parseAgentSessionKey } from "openclaw/plugin-sdk/routing";
|
|
44
46
|
import { renderMessagePresentationFallbackText } from "openclaw/plugin-sdk/interactive-runtime";
|
|
45
47
|
import { MODEL_SELECTION_LOCKED_MESSAGE, isModelSelectionLocked, resolvePersistedSessionRuntimeId } from "openclaw/plugin-sdk/model-session-runtime";
|
|
46
48
|
//#region extensions/codex/src/command-account.ts
|
|
47
49
|
const OPENAI_PROVIDER_ID = "openai";
|
|
48
|
-
const OPENAI_CODEX_PROVIDER_ID = OPENAI_PROVIDER_ID;
|
|
49
50
|
async function readCodexAccountAuthOverview(params) {
|
|
51
|
+
if (!params.account.ok && !params.limits.ok) return;
|
|
50
52
|
const config = params.ctx.config;
|
|
51
53
|
const agentDir = params.agentDir;
|
|
52
54
|
const store = ensureAuthProfileStore(agentDir, {
|
|
53
55
|
allowKeychainPrompt: false,
|
|
54
56
|
config
|
|
55
57
|
});
|
|
56
|
-
const
|
|
58
|
+
const order = resolveDisplayAuthOrder({
|
|
57
59
|
config,
|
|
58
60
|
store
|
|
59
61
|
});
|
|
62
|
+
const activeProfileId = params.authProfileId ?? void 0;
|
|
63
|
+
if (activeProfileId && !order.includes(activeProfileId)) order.unshift(activeProfileId);
|
|
60
64
|
if (order.length === 0) return;
|
|
61
65
|
const now = Date.now();
|
|
62
|
-
const activeProfileId = resolveActiveProfileId({
|
|
63
|
-
store,
|
|
64
|
-
order,
|
|
65
|
-
explicitOrder,
|
|
66
|
-
config,
|
|
67
|
-
account: params.account,
|
|
68
|
-
limits: params.limits,
|
|
69
|
-
now
|
|
70
|
-
});
|
|
71
66
|
const activeIsSubscription = activeProfileId !== void 0 && isChatGptSubscriptionProfile(store.profiles[activeProfileId]);
|
|
72
|
-
const subscriptionProfileId = activeIsSubscription ? activeProfileId : order.find((profileId) => isChatGptSubscriptionProfile(store.profiles[profileId]));
|
|
67
|
+
const subscriptionProfileId = activeIsSubscription ? activeProfileId : activeProfileId ? order.find((profileId) => isChatGptSubscriptionProfile(store.profiles[profileId])) : void 0;
|
|
73
68
|
const activeUsage = activeIsSubscription && params.limits.ok ? summarizeCodexAccountUsage(params.limits.value, now) : void 0;
|
|
74
|
-
const subscriptionUsage = subscriptionProfileId &&
|
|
69
|
+
const subscriptionUsage = subscriptionProfileId && !activeIsSubscription ? await readSubscriptionUsage({
|
|
75
70
|
...params,
|
|
76
71
|
agentDir,
|
|
77
72
|
config,
|
|
78
73
|
subscriptionProfileId,
|
|
79
74
|
now
|
|
80
75
|
}) : activeUsage;
|
|
81
|
-
|
|
82
|
-
const rows = order.map((profileId, index) => buildProfileRow({
|
|
76
|
+
const rows = order.map((profileId) => buildProfileRow({
|
|
83
77
|
store,
|
|
84
78
|
config,
|
|
85
79
|
profileId,
|
|
86
80
|
activeProfileId,
|
|
87
|
-
activeIndex: activeProfileId ? order.indexOf(activeProfileId) : -1,
|
|
88
|
-
index,
|
|
89
81
|
now,
|
|
90
82
|
usage: profileId === subscriptionProfileId ? subscriptionUsage : void 0
|
|
91
83
|
}));
|
|
92
84
|
const activeRow = rows.find((row) => row.active);
|
|
93
85
|
if (!activeRow) return {
|
|
94
|
-
currentLine: "OpenAI credentials: no working credential",
|
|
95
86
|
orderTitle: "Auth order",
|
|
96
87
|
rows
|
|
97
88
|
};
|
|
98
89
|
const activeIsApiKey = store.profiles[activeRow.profileId]?.type === "api_key";
|
|
99
|
-
const subscriptionLabel = subscriptionProfileId ? formatProfileLabel(subscriptionProfileId, store.profiles[subscriptionProfileId]) :
|
|
90
|
+
const subscriptionLabel = subscriptionProfileId ? formatProfileLabel(subscriptionProfileId, store.profiles[subscriptionProfileId]) : void 0;
|
|
100
91
|
const subscriptionUsageLine = formatSubscriptionUsageLine(subscriptionUsage);
|
|
101
92
|
return {
|
|
102
93
|
...activeIsApiKey ? { currentLine: buildApiKeyActiveLine(activeRow, subscriptionUsage) } : {},
|
|
@@ -107,92 +98,13 @@ async function readCodexAccountAuthOverview(params) {
|
|
|
107
98
|
};
|
|
108
99
|
}
|
|
109
100
|
function resolveDisplayAuthOrder(params) {
|
|
110
|
-
const
|
|
111
|
-
if (
|
|
112
|
-
order: normalizeUniqueStringEntries(codexOrder),
|
|
113
|
-
explicit: true
|
|
114
|
-
};
|
|
115
|
-
return {
|
|
116
|
-
order: resolveAuthProfileOrder({
|
|
117
|
-
cfg: params.config,
|
|
118
|
-
store: params.store,
|
|
119
|
-
provider: OPENAI_CODEX_PROVIDER_ID
|
|
120
|
-
}),
|
|
121
|
-
explicit: hasExplicitOpenAiAuthOrder(params)
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
function hasExplicitOpenAiAuthOrder(params) {
|
|
125
|
-
const sources = [params.store.order, params.config?.auth?.order];
|
|
126
|
-
for (const source of sources) {
|
|
127
|
-
const codex = resolveOrder(source, OPENAI_CODEX_PROVIDER_ID);
|
|
128
|
-
if (codex && codex.length > 0) return true;
|
|
129
|
-
const openai = resolveOrder(source, OPENAI_PROVIDER_ID);
|
|
130
|
-
if (openai && openai.length > 0) return true;
|
|
131
|
-
}
|
|
132
|
-
return false;
|
|
133
|
-
}
|
|
134
|
-
function resolveOrder(order, provider) {
|
|
135
|
-
return findNormalizedProviderValue(order, provider);
|
|
136
|
-
}
|
|
137
|
-
function resolveActiveProfileId(params) {
|
|
138
|
-
const liveProfileId = resolveLiveAccountProfileId({
|
|
139
|
-
account: params.account,
|
|
140
|
-
store: params.store,
|
|
141
|
-
order: params.order
|
|
142
|
-
});
|
|
143
|
-
if (liveProfileId) return liveProfileId;
|
|
144
|
-
if (params.explicitOrder) return params.order.find((profileId) => isActiveProfileCandidate(params, profileId) && resolveAuthProfileEligibility({
|
|
145
|
-
cfg: params.config,
|
|
146
|
-
store: params.store,
|
|
147
|
-
provider: OPENAI_CODEX_PROVIDER_ID,
|
|
148
|
-
profileId,
|
|
149
|
-
now: params.now
|
|
150
|
-
}).eligible);
|
|
151
|
-
const lastGood = [params.store.lastGood?.[OPENAI_PROVIDER_ID], params.store.lastGood?.[OPENAI_CODEX_PROVIDER_ID]].find((profileId) => typeof profileId === "string" && params.order.includes(profileId) && isActiveProfileCandidate(params, profileId));
|
|
152
|
-
if (lastGood) return lastGood;
|
|
153
|
-
const mostRecent = params.order.map((profileId) => ({
|
|
154
|
-
profileId,
|
|
155
|
-
lastUsed: params.store.usageStats?.[profileId]?.lastUsed ?? 0
|
|
156
|
-
})).filter((entry) => entry.lastUsed > 0 && isActiveProfileCandidate(params, entry.profileId)).toSorted((left, right) => right.lastUsed - left.lastUsed)[0]?.profileId;
|
|
157
|
-
if (mostRecent) return mostRecent;
|
|
158
|
-
if (shouldInferApiKeyActiveFromRateLimitProbe(params.limits)) {
|
|
159
|
-
const apiKeyProfile = params.order.find((profileId) => params.store.profiles[profileId]?.type === "api_key");
|
|
160
|
-
if (apiKeyProfile) return apiKeyProfile;
|
|
161
|
-
}
|
|
101
|
+
const explicitOrder = findNormalizedProviderValue(params.store.order, OPENAI_PROVIDER_ID) ?? findNormalizedProviderValue(params.config?.auth?.order, OPENAI_PROVIDER_ID);
|
|
102
|
+
if (explicitOrder && explicitOrder.length > 0) return normalizeUniqueStringEntries(explicitOrder);
|
|
162
103
|
return resolveAuthProfileOrder({
|
|
163
104
|
cfg: params.config,
|
|
164
105
|
store: params.store,
|
|
165
|
-
provider:
|
|
166
|
-
})
|
|
167
|
-
}
|
|
168
|
-
function isActiveProfileCandidate(params, profileId) {
|
|
169
|
-
return !isActiveUntil(resolveProfileUnusableUntilForDisplay(params.store, profileId) ?? void 0, params.now);
|
|
170
|
-
}
|
|
171
|
-
function resolveLiveAccountProfileId(params) {
|
|
172
|
-
if (!params.account.ok || !isJsonObject(params.account.value)) return;
|
|
173
|
-
const account = isJsonObject(params.account.value.account) ? params.account.value.account : params.account.value;
|
|
174
|
-
const type = normalizeOptionalString(account.type)?.toLowerCase();
|
|
175
|
-
if (type === "chatgpt") {
|
|
176
|
-
const email = normalizeOptionalString(account.email)?.toLowerCase();
|
|
177
|
-
const accountId = normalizeOptionalString(account.accountId ?? account.chatgptAccountId);
|
|
178
|
-
const subscriptionProfiles = params.order.filter((profileId) => isChatGptSubscriptionProfile(params.store.profiles[profileId]));
|
|
179
|
-
if (accountId) {
|
|
180
|
-
const exactWorkspace = subscriptionProfiles.find((profileId) => {
|
|
181
|
-
const credential = params.store.profiles[profileId];
|
|
182
|
-
return credential && "accountId" in credential && credential.accountId === accountId;
|
|
183
|
-
});
|
|
184
|
-
if (exactWorkspace) return exactWorkspace;
|
|
185
|
-
}
|
|
186
|
-
const matchingProfiles = email ? subscriptionProfiles.filter((profileId) => {
|
|
187
|
-
return (params.store.profiles[profileId]?.email?.trim().toLowerCase() ?? extractEmailFromProfileId(profileId))?.toLowerCase() === email;
|
|
188
|
-
}) : subscriptionProfiles;
|
|
189
|
-
const lastGood = params.store.lastGood?.[OPENAI_PROVIDER_ID];
|
|
190
|
-
return (lastGood && matchingProfiles.includes(lastGood) ? lastGood : void 0) ?? matchingProfiles[0] ?? subscriptionProfiles[0];
|
|
191
|
-
}
|
|
192
|
-
if (type === "apikey" || type === "api_key") return params.order.find((profileId) => params.store.profiles[profileId]?.type === "api_key");
|
|
193
|
-
}
|
|
194
|
-
function shouldInferApiKeyActiveFromRateLimitProbe(limits) {
|
|
195
|
-
return !limits.ok && limits.error.toLowerCase().includes("chatgpt authentication required");
|
|
106
|
+
provider: OPENAI_PROVIDER_ID
|
|
107
|
+
});
|
|
196
108
|
}
|
|
197
109
|
async function readSubscriptionUsage(params) {
|
|
198
110
|
const limits = await params.safeCodexControlRequest(params.pluginConfig, CODEX_CONTROL_METHODS.rateLimits, void 0, {
|
|
@@ -209,13 +121,12 @@ function buildProfileRow(params) {
|
|
|
209
121
|
const label = formatProfileLabel(params.profileId, credential);
|
|
210
122
|
const kind = formatProfileKind(credential);
|
|
211
123
|
const active = params.profileId === params.activeProfileId;
|
|
212
|
-
const status = active ? "active now" : params.usage?.blocked ?
|
|
124
|
+
const status = active ? "active now" : params.usage?.blocked ? "rate-limited" : describeInactiveProfileStatus({
|
|
213
125
|
store: params.store,
|
|
214
126
|
config: params.config,
|
|
215
127
|
profileId: params.profileId,
|
|
216
128
|
credential,
|
|
217
|
-
now: params.now
|
|
218
|
-
afterActive: params.activeIndex >= 0 && params.index > params.activeIndex
|
|
129
|
+
now: params.now
|
|
219
130
|
});
|
|
220
131
|
return {
|
|
221
132
|
profileId: params.profileId,
|
|
@@ -223,22 +134,18 @@ function buildProfileRow(params) {
|
|
|
223
134
|
kind,
|
|
224
135
|
status,
|
|
225
136
|
active,
|
|
226
|
-
...credential?.type === "api_key" && active ? { billingNote: "billed per token" } : {}
|
|
227
|
-
...params.usage?.usageLine ? { usage: params.usage.usageLine } : {}
|
|
137
|
+
...credential?.type === "api_key" && active ? { billingNote: "billed per token" } : {}
|
|
228
138
|
};
|
|
229
139
|
}
|
|
230
|
-
function formatUsageBlockedStatus(usage) {
|
|
231
|
-
return usage.blocked ? "rate-limited" : "available if needed";
|
|
232
|
-
}
|
|
233
140
|
function describeInactiveProfileStatus(params) {
|
|
234
141
|
const stats = params.store.usageStats?.[params.profileId];
|
|
235
142
|
const blockedUntil = stats?.blockedUntil;
|
|
236
|
-
if (isActiveUntil(blockedUntil, params.now)) return `rate-limited - resets ${
|
|
143
|
+
if (isActiveUntil(blockedUntil, params.now)) return `rate-limited - resets in ${formatRelativeDuration(Math.max(6e4, blockedUntil - params.now))}`;
|
|
237
144
|
if (isActiveUntil(resolveProfileUnusableUntilForDisplay(params.store, params.profileId) ?? void 0, params.now)) return describeFailureStatus(stats?.disabledReason ?? stats?.cooldownReason, params.credential);
|
|
238
145
|
const eligibility = resolveAuthProfileEligibility({
|
|
239
146
|
cfg: params.config,
|
|
240
147
|
store: params.store,
|
|
241
|
-
provider:
|
|
148
|
+
provider: OPENAI_PROVIDER_ID,
|
|
242
149
|
profileId: params.profileId,
|
|
243
150
|
now: params.now
|
|
244
151
|
});
|
|
@@ -324,22 +231,6 @@ function describeEligibilityStatus(reason, credential) {
|
|
|
324
231
|
function isActiveUntil(value, now) {
|
|
325
232
|
return typeof value === "number" && Number.isFinite(value) && value > now;
|
|
326
233
|
}
|
|
327
|
-
function formatRelativeReset(untilMs, nowMs) {
|
|
328
|
-
const durationMs = Math.max(1e3, untilMs - nowMs);
|
|
329
|
-
const minuteMs = 6e4;
|
|
330
|
-
const hourMs = 60 * minuteMs;
|
|
331
|
-
const dayMs = 24 * hourMs;
|
|
332
|
-
if (durationMs < hourMs) {
|
|
333
|
-
const minutes = Math.ceil(durationMs / minuteMs);
|
|
334
|
-
return `in ${minutes} ${minutes === 1 ? "minute" : "minutes"}`;
|
|
335
|
-
}
|
|
336
|
-
if (durationMs < dayMs) {
|
|
337
|
-
const hours = Math.ceil(durationMs / hourMs);
|
|
338
|
-
return `in ${hours} ${hours === 1 ? "hour" : "hours"}`;
|
|
339
|
-
}
|
|
340
|
-
const days = Math.ceil(durationMs / dayMs);
|
|
341
|
-
return `in ${days} ${days === 1 ? "day" : "days"}`;
|
|
342
|
-
}
|
|
343
234
|
function buildCodexPluginAppLinks(apps, options = {}) {
|
|
344
235
|
const blocks = apps.slice(0, 5).map((app) => {
|
|
345
236
|
const name = formatCodexDisplayText((app.name.trim() || app.id).slice(0, 80));
|
|
@@ -379,6 +270,24 @@ function buildCodexPluginAppLinks(apps, options = {}) {
|
|
|
379
270
|
});
|
|
380
271
|
return blocks;
|
|
381
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
|
+
}
|
|
382
291
|
function safeCodexAppLink(value) {
|
|
383
292
|
if (!value || value.length > 2048 || /[\s\p{Cc}\p{Cf}<>]/u.test(value)) return;
|
|
384
293
|
try {
|
|
@@ -686,22 +595,7 @@ function formatCodexPluginReadiness(readiness, page = 1) {
|
|
|
686
595
|
type: "text",
|
|
687
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."
|
|
688
597
|
});
|
|
689
|
-
blocks.push(
|
|
690
|
-
type: "buttons",
|
|
691
|
-
buttons: [...canRefreshHostedApps ? [{
|
|
692
|
-
label: "Refresh hosted apps",
|
|
693
|
-
action: {
|
|
694
|
-
type: "command",
|
|
695
|
-
command: "/codex plugins refresh"
|
|
696
|
-
}
|
|
697
|
-
}] : [], {
|
|
698
|
-
label: "Check status",
|
|
699
|
-
action: {
|
|
700
|
-
type: "command",
|
|
701
|
-
command: `/codex plugins status ${readiness.commandId}`
|
|
702
|
-
}
|
|
703
|
-
}]
|
|
704
|
-
});
|
|
598
|
+
blocks.push(buildCodexPluginStatusButtons(readiness.commandId, canRefreshHostedApps));
|
|
705
599
|
}
|
|
706
600
|
}
|
|
707
601
|
const presentation = {
|
|
@@ -872,73 +766,59 @@ function buildCodexSubcommandPickerReply() {
|
|
|
872
766
|
};
|
|
873
767
|
}
|
|
874
768
|
function buildCodexFastMenuReply() {
|
|
875
|
-
|
|
876
|
-
"
|
|
877
|
-
"
|
|
878
|
-
"
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
}];
|
|
887
|
-
return {
|
|
888
|
-
text: [
|
|
889
|
-
"Codex fast mode. Pick one or type /codex fast <mode>:",
|
|
890
|
-
"",
|
|
891
|
-
...modes.map((m, i) => ` ${i + 1}. /codex fast ${m}`),
|
|
892
|
-
"",
|
|
893
|
-
"Type '/codex' to go back to the main menu."
|
|
894
|
-
].join("\n"),
|
|
895
|
-
presentation: buildCodexCommandPickerPresentation("Codex fast mode", "Pick a Codex fast mode:", buttons)
|
|
896
|
-
};
|
|
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
|
+
});
|
|
897
780
|
}
|
|
898
781
|
function buildCodexPermissionsMenuReply() {
|
|
899
|
-
|
|
900
|
-
"
|
|
901
|
-
"
|
|
902
|
-
"
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
}];
|
|
911
|
-
return {
|
|
912
|
-
text: [
|
|
913
|
-
"Codex permissions. Pick one or type /codex permissions <mode>:",
|
|
914
|
-
"",
|
|
915
|
-
...modes.map((m, i) => ` ${i + 1}. /codex permissions ${m}`),
|
|
916
|
-
"",
|
|
917
|
-
"Type '/codex' to go back to the main menu."
|
|
918
|
-
].join("\n"),
|
|
919
|
-
presentation: buildCodexCommandPickerPresentation("Codex permissions", "Pick a Codex permissions mode:", buttons)
|
|
920
|
-
};
|
|
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
|
+
});
|
|
921
793
|
}
|
|
922
794
|
function buildCodexComputerUseMenuReply() {
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
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}`
|
|
927
808
|
})), {
|
|
928
809
|
label: "back",
|
|
929
810
|
command: "/codex"
|
|
930
811
|
}];
|
|
931
812
|
return {
|
|
932
813
|
text: [
|
|
933
|
-
|
|
934
|
-
"",
|
|
935
|
-
...actions.map((a, i) => ` ${i + 1}. /codex computer-use ${a}`),
|
|
814
|
+
params.introduction,
|
|
936
815
|
"",
|
|
937
|
-
|
|
816
|
+
...params.choices.map((choice, index) => ` ${index + 1}. ${params.command} ${choice}`),
|
|
938
817
|
"",
|
|
818
|
+
...params.hint ? [params.hint, ""] : [],
|
|
939
819
|
"Type '/codex' to go back to the main menu."
|
|
940
820
|
].join("\n"),
|
|
941
|
-
presentation: buildCodexCommandPickerPresentation(
|
|
821
|
+
presentation: buildCodexCommandPickerPresentation(params.title, params.prompt, buttons)
|
|
942
822
|
};
|
|
943
823
|
}
|
|
944
824
|
function isMenuVerb(rest) {
|
|
@@ -990,54 +870,18 @@ function splitArgs(value) {
|
|
|
990
870
|
return args;
|
|
991
871
|
}
|
|
992
872
|
function parseBindArgs(args) {
|
|
993
|
-
const parsed =
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
}
|
|
1006
|
-
parsed.cwd = value;
|
|
1007
|
-
index += 1;
|
|
1008
|
-
continue;
|
|
1009
|
-
}
|
|
1010
|
-
if (arg === "--model") {
|
|
1011
|
-
const value = readRequiredOptionValue(args, index);
|
|
1012
|
-
if (!value || parsed.model !== void 0) {
|
|
1013
|
-
parsed.help = true;
|
|
1014
|
-
continue;
|
|
1015
|
-
}
|
|
1016
|
-
parsed.model = value;
|
|
1017
|
-
index += 1;
|
|
1018
|
-
continue;
|
|
1019
|
-
}
|
|
1020
|
-
if (arg === "--provider" || arg === "--model-provider") {
|
|
1021
|
-
const value = readRequiredOptionValue(args, index);
|
|
1022
|
-
if (!value || parsed.provider !== void 0) {
|
|
1023
|
-
parsed.help = true;
|
|
1024
|
-
continue;
|
|
1025
|
-
}
|
|
1026
|
-
parsed.provider = value;
|
|
1027
|
-
index += 1;
|
|
1028
|
-
continue;
|
|
1029
|
-
}
|
|
1030
|
-
if (!arg.startsWith("-") && !parsed.threadId) {
|
|
1031
|
-
parsed.threadId = arg;
|
|
1032
|
-
continue;
|
|
1033
|
-
}
|
|
1034
|
-
parsed.help = true;
|
|
1035
|
-
}
|
|
1036
|
-
parsed.threadId = normalizeOptionalString(parsed.threadId);
|
|
1037
|
-
parsed.cwd = normalizeOptionalString(parsed.cwd);
|
|
1038
|
-
parsed.model = normalizeOptionalString(parsed.model);
|
|
1039
|
-
parsed.provider = normalizeOptionalString(parsed.provider);
|
|
1040
|
-
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
|
+
};
|
|
1041
885
|
}
|
|
1042
886
|
function parseCodexCliSessionsArgs(args) {
|
|
1043
887
|
const parsed = { filter: "" };
|
|
@@ -1080,29 +924,34 @@ function parseCodexCliSessionsArgs(args) {
|
|
|
1080
924
|
return parsed;
|
|
1081
925
|
}
|
|
1082
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) {
|
|
1083
939
|
const parsed = {};
|
|
940
|
+
const values = /* @__PURE__ */ new Map();
|
|
1084
941
|
for (let index = 0; index < args.length; index += 1) {
|
|
1085
|
-
const arg = expectDefined(args[index], "current Codex
|
|
942
|
+
const arg = expectDefined(args[index], "current Codex thread argument");
|
|
1086
943
|
if (arg === "--help" || arg === "-h") {
|
|
1087
944
|
parsed.help = true;
|
|
1088
945
|
continue;
|
|
1089
946
|
}
|
|
1090
|
-
|
|
947
|
+
const option = options.get(arg);
|
|
948
|
+
if (option) {
|
|
1091
949
|
const value = readRequiredOptionValue(args, index);
|
|
1092
|
-
if (!value ||
|
|
1093
|
-
parsed.help = true;
|
|
1094
|
-
continue;
|
|
1095
|
-
}
|
|
1096
|
-
parsed.host = value;
|
|
1097
|
-
index += 1;
|
|
1098
|
-
continue;
|
|
1099
|
-
}
|
|
1100
|
-
if (arg === "--bind") {
|
|
1101
|
-
if (readRequiredOptionValue(args, index) !== "here" || parsed.bindHere !== void 0) {
|
|
950
|
+
if (!value || values.has(option) || option === "bind" && value !== "here") {
|
|
1102
951
|
parsed.help = true;
|
|
1103
952
|
continue;
|
|
1104
953
|
}
|
|
1105
|
-
|
|
954
|
+
values.set(option, value);
|
|
1106
955
|
index += 1;
|
|
1107
956
|
continue;
|
|
1108
957
|
}
|
|
@@ -1113,8 +962,10 @@ function parseResumeArgs(args) {
|
|
|
1113
962
|
parsed.help = true;
|
|
1114
963
|
}
|
|
1115
964
|
parsed.threadId = normalizeOptionalString(parsed.threadId);
|
|
1116
|
-
|
|
1117
|
-
|
|
965
|
+
return {
|
|
966
|
+
parsed,
|
|
967
|
+
values
|
|
968
|
+
};
|
|
1118
969
|
}
|
|
1119
970
|
function parseComputerUseArgs(args) {
|
|
1120
971
|
const parsed = {
|
|
@@ -1139,33 +990,14 @@ function parseComputerUseArgs(args) {
|
|
|
1139
990
|
parsed.action = arg;
|
|
1140
991
|
continue;
|
|
1141
992
|
}
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
if (!value || parsed.overrides.marketplaceSource !== void 0) {
|
|
1145
|
-
parsed.help = true;
|
|
1146
|
-
continue;
|
|
1147
|
-
}
|
|
1148
|
-
parsed.overrides.marketplaceSource = value;
|
|
1149
|
-
index += 1;
|
|
1150
|
-
continue;
|
|
1151
|
-
}
|
|
1152
|
-
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) {
|
|
1153
995
|
const value = readRequiredOptionValue(args, index);
|
|
1154
|
-
if (!value || parsed.overrides
|
|
996
|
+
if (!value || parsed.overrides[option] !== void 0) {
|
|
1155
997
|
parsed.help = true;
|
|
1156
998
|
continue;
|
|
1157
999
|
}
|
|
1158
|
-
parsed.overrides
|
|
1159
|
-
index += 1;
|
|
1160
|
-
continue;
|
|
1161
|
-
}
|
|
1162
|
-
if (arg === "--marketplace") {
|
|
1163
|
-
const value = readRequiredOptionValue(args, index);
|
|
1164
|
-
if (!value || parsed.overrides.marketplaceName !== void 0) {
|
|
1165
|
-
parsed.help = true;
|
|
1166
|
-
continue;
|
|
1167
|
-
}
|
|
1168
|
-
parsed.overrides.marketplaceName = value;
|
|
1000
|
+
parsed.overrides[option] = value;
|
|
1169
1001
|
index += 1;
|
|
1170
1002
|
continue;
|
|
1171
1003
|
}
|
|
@@ -1182,8 +1014,19 @@ function parseComputerUseArgs(args) {
|
|
|
1182
1014
|
}
|
|
1183
1015
|
parsed.help = true;
|
|
1184
1016
|
}
|
|
1185
|
-
|
|
1186
|
-
parsed.
|
|
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
|
+
}
|
|
1187
1030
|
return parsed;
|
|
1188
1031
|
}
|
|
1189
1032
|
function formatComputerUsePersistentIdentityMigration(parsed) {
|
|
@@ -1203,16 +1046,6 @@ function readRequiredOptionValue(args, index) {
|
|
|
1203
1046
|
if (!normalized || normalized.startsWith("-")) return;
|
|
1204
1047
|
return value;
|
|
1205
1048
|
}
|
|
1206
|
-
function normalizeComputerUseStringOverrides(overrides) {
|
|
1207
|
-
const normalized = {};
|
|
1208
|
-
const marketplaceSource = normalizeOptionalString(overrides.marketplaceSource);
|
|
1209
|
-
if (marketplaceSource) normalized.marketplaceSource = marketplaceSource;
|
|
1210
|
-
const marketplacePath = normalizeOptionalString(overrides.marketplacePath);
|
|
1211
|
-
if (marketplacePath) normalized.marketplacePath = marketplacePath;
|
|
1212
|
-
const marketplaceName = normalizeOptionalString(overrides.marketplaceName);
|
|
1213
|
-
if (marketplaceName) normalized.marketplaceName = marketplaceName;
|
|
1214
|
-
return normalized;
|
|
1215
|
-
}
|
|
1216
1049
|
//#endregion
|
|
1217
1050
|
//#region extensions/codex/src/command-diagnostics-support.ts
|
|
1218
1051
|
const CODEX_DIAGNOSTICS_SOURCE = "openclaw-diagnostics";
|
|
@@ -1232,16 +1065,11 @@ function normalizeDiagnosticsReason(note) {
|
|
|
1232
1065
|
}
|
|
1233
1066
|
function parseDiagnosticsArgs(args) {
|
|
1234
1067
|
const [action, token, ...extra] = splitArgs(args);
|
|
1235
|
-
const normalizedAction = action?.toLowerCase();
|
|
1236
|
-
if (
|
|
1237
|
-
action:
|
|
1068
|
+
const normalizedAction = action?.toLowerCase().replace(/^--/, "");
|
|
1069
|
+
if (normalizedAction === "confirm" || normalizedAction === "cancel") return token && extra.length === 0 ? {
|
|
1070
|
+
action: normalizedAction,
|
|
1238
1071
|
token
|
|
1239
|
-
};
|
|
1240
|
-
if ((normalizedAction === "cancel" || normalizedAction === "--cancel") && token && extra.length === 0) return {
|
|
1241
|
-
action: "cancel",
|
|
1242
|
-
token
|
|
1243
|
-
};
|
|
1244
|
-
if (normalizedAction === "confirm" || normalizedAction === "--confirm" || normalizedAction === "cancel" || normalizedAction === "--cancel") return { action: "usage" };
|
|
1072
|
+
} : { action: "usage" };
|
|
1245
1073
|
return {
|
|
1246
1074
|
action: "request",
|
|
1247
1075
|
note: args
|
|
@@ -1297,27 +1125,14 @@ function readCodexDiagnosticsConfirmationScope(ctx) {
|
|
|
1297
1125
|
}
|
|
1298
1126
|
function readCodexDiagnosticsScopeMismatch(pending, ctx) {
|
|
1299
1127
|
const current = readCodexDiagnosticsConfirmationScope(ctx);
|
|
1300
|
-
if (pending.accountId !== current.accountId) return
|
|
1301
|
-
confirmMessage: "This Codex diagnostics confirmation belongs to a different account.",
|
|
1302
|
-
cancelMessage: "This Codex diagnostics confirmation belongs to a different account."
|
|
1303
|
-
};
|
|
1128
|
+
if (pending.accountId !== current.accountId) return "This Codex diagnostics confirmation belongs to a different account.";
|
|
1304
1129
|
if (pending.privateRouted) return;
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
cancelMessage: "This Codex diagnostics confirmation belongs to a different thread."
|
|
1312
|
-
};
|
|
1313
|
-
if (pending.threadParentId !== current.threadParentId) return {
|
|
1314
|
-
confirmMessage: "This Codex diagnostics confirmation belongs to a different parent thread.",
|
|
1315
|
-
cancelMessage: "This Codex diagnostics confirmation belongs to a different parent thread."
|
|
1316
|
-
};
|
|
1317
|
-
if (pending.sessionKey !== current.sessionKey) return {
|
|
1318
|
-
confirmMessage: "This Codex diagnostics confirmation belongs to a different session.",
|
|
1319
|
-
cancelMessage: "This Codex diagnostics confirmation belongs to a different session."
|
|
1320
|
-
};
|
|
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}.`;
|
|
1321
1136
|
}
|
|
1322
1137
|
function readPendingCodexDiagnosticsConfirmation(token, now) {
|
|
1323
1138
|
prunePendingCodexDiagnosticsConfirmations(now);
|
|
@@ -1394,13 +1209,13 @@ function formatCodexDiagnosticsTargetLine(target) {
|
|
|
1394
1209
|
}
|
|
1395
1210
|
function readCodexDiagnosticsTargetsCooldownMessage(targets, ctx, now, options = {}) {
|
|
1396
1211
|
for (const target of targets) {
|
|
1397
|
-
const cooldownMs = readCodexDiagnosticsCooldownMs(target.threadId, now);
|
|
1212
|
+
const cooldownMs = readCodexDiagnosticsCooldownMs(lastCodexDiagnosticsUploadByThread, target.threadId, now);
|
|
1398
1213
|
if (cooldownMs > 0) {
|
|
1399
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.`;
|
|
1400
1215
|
return `Codex diagnostics were already sent for thread ${formatCodexDisplayText(target.threadId)} recently. Try again in ${Math.ceil(cooldownMs / 1e3)}s.`;
|
|
1401
1216
|
}
|
|
1402
1217
|
}
|
|
1403
|
-
const scopeCooldownMs =
|
|
1218
|
+
const scopeCooldownMs = readCodexDiagnosticsCooldownMs(lastCodexDiagnosticsUploadByScope, options.cooldownScope ?? readCodexDiagnosticsCooldownScope(ctx), now);
|
|
1404
1219
|
if (scopeCooldownMs > 0) return `Codex diagnostics were already sent for this account or channel recently. Try again in ${Math.ceil(scopeCooldownMs / 1e3)}s.`;
|
|
1405
1220
|
}
|
|
1406
1221
|
function recordCodexDiagnosticsUpload(threadId, ctx, now, cooldownScope) {
|
|
@@ -1422,30 +1237,22 @@ function readCodexDiagnosticsCooldownScope(ctx) {
|
|
|
1422
1237
|
return crypto.createHash("sha256").update(payload).digest("hex");
|
|
1423
1238
|
}
|
|
1424
1239
|
function buildDiagnosticsTags(ctx) {
|
|
1425
|
-
const
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
}
|
|
1429
|
-
|
|
1430
|
-
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
|
+
};
|
|
1431
1245
|
}
|
|
1432
1246
|
function formatCodexCopyableValueForDisplay(value) {
|
|
1433
1247
|
const safe = formatCodexTextForDisplay(value);
|
|
1434
1248
|
if (CODEX_RESUME_SAFE_THREAD_ID_PATTERN.test(safe)) return `\`${safe}\``;
|
|
1435
1249
|
return escapeCodexChatText(safe);
|
|
1436
1250
|
}
|
|
1437
|
-
function readCodexDiagnosticsCooldownMs(
|
|
1438
|
-
const lastSentAt =
|
|
1251
|
+
function readCodexDiagnosticsCooldownMs(map, key, now) {
|
|
1252
|
+
const lastSentAt = map.get(key);
|
|
1439
1253
|
if (!lastSentAt) return 0;
|
|
1440
1254
|
const remainingMs = Math.max(0, CODEX_DIAGNOSTICS_COOLDOWN_MS - (now - lastSentAt));
|
|
1441
|
-
if (remainingMs === 0)
|
|
1442
|
-
return remainingMs;
|
|
1443
|
-
}
|
|
1444
|
-
function readCodexDiagnosticsScopeCooldownMs(scope, now) {
|
|
1445
|
-
const lastSentAt = lastCodexDiagnosticsUploadByScope.get(scope);
|
|
1446
|
-
if (!lastSentAt) return 0;
|
|
1447
|
-
const remainingMs = Math.max(0, CODEX_DIAGNOSTICS_COOLDOWN_MS - (now - lastSentAt));
|
|
1448
|
-
if (remainingMs === 0) lastCodexDiagnosticsUploadByScope.delete(scope);
|
|
1255
|
+
if (remainingMs === 0) map.delete(key);
|
|
1449
1256
|
return remainingMs;
|
|
1450
1257
|
}
|
|
1451
1258
|
function recordBoundedCodexDiagnosticsCooldown(map, key, maxSize, now) {
|
|
@@ -1573,7 +1380,15 @@ async function resolvePreparedCodexCommandAuthority(deps, ctx) {
|
|
|
1573
1380
|
sessionKey,
|
|
1574
1381
|
storePath,
|
|
1575
1382
|
assertHostCurrent,
|
|
1576
|
-
assertCurrent
|
|
1383
|
+
assertCurrent,
|
|
1384
|
+
assertMutationCurrent: () => {
|
|
1385
|
+
assertCodexHostOwnerCurrent(ctx);
|
|
1386
|
+
assertCurrent();
|
|
1387
|
+
},
|
|
1388
|
+
assertHostMutationCurrent: () => {
|
|
1389
|
+
assertCodexHostOwnerCurrent(ctx);
|
|
1390
|
+
assertHostCurrent();
|
|
1391
|
+
}
|
|
1577
1392
|
};
|
|
1578
1393
|
}
|
|
1579
1394
|
async function resolveCommandAppServerContext(deps, ctx, pluginConfig) {
|
|
@@ -1631,7 +1446,9 @@ function resolveCodexConversationControlScope(ctx) {
|
|
|
1631
1446
|
}
|
|
1632
1447
|
//#endregion
|
|
1633
1448
|
//#region extensions/codex/src/command-diagnostics.ts
|
|
1634
|
-
|
|
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");
|
|
1450
|
+
async function handleCodexDiagnosticsFeedback(deps, context, pluginConfig, args, commandPrefix) {
|
|
1451
|
+
const ctx = { ...context };
|
|
1635
1452
|
if (ctx.senderIsOwner !== true) return { text: "Only an owner can send Codex diagnostics." };
|
|
1636
1453
|
const parsed = parseDiagnosticsArgs(args);
|
|
1637
1454
|
if (parsed.action === "usage") return { text: formatDiagnosticsUsage(commandPrefix) };
|
|
@@ -1642,9 +1459,8 @@ async function handleCodexDiagnosticsFeedback(deps, ctx, pluginConfig, args, com
|
|
|
1642
1459
|
return await requestCodexDiagnosticsFeedbackApproval(deps, ctx, parsed.note, commandPrefix);
|
|
1643
1460
|
}
|
|
1644
1461
|
async function requestCodexDiagnosticsFeedbackApproval(deps, ctx, note, commandPrefix) {
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
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 };
|
|
1648
1464
|
const now = Date.now();
|
|
1649
1465
|
const cooldownMessage = readCodexDiagnosticsTargetsCooldownMessage(targets, ctx, now);
|
|
1650
1466
|
if (cooldownMessage) return { text: cooldownMessage };
|
|
@@ -1698,9 +1514,8 @@ async function requestCodexDiagnosticsFeedbackApproval(deps, ctx, note, commandP
|
|
|
1698
1514
|
};
|
|
1699
1515
|
}
|
|
1700
1516
|
async function previewCodexDiagnosticsFeedbackApproval(deps, ctx, note) {
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
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;
|
|
1704
1519
|
const cooldownMessage = readCodexDiagnosticsTargetsCooldownMessage(targets, ctx, Date.now(), { includeThreadId: false });
|
|
1705
1520
|
if (cooldownMessage) return cooldownMessage;
|
|
1706
1521
|
const reason = normalizeDiagnosticsReason(note);
|
|
@@ -1714,28 +1529,16 @@ async function previewCodexDiagnosticsFeedbackApproval(deps, ctx, note) {
|
|
|
1714
1529
|
].join("\n");
|
|
1715
1530
|
}
|
|
1716
1531
|
async function confirmCodexDiagnosticsFeedback(deps, ctx, pluginConfig, token) {
|
|
1717
|
-
const pending =
|
|
1718
|
-
if (
|
|
1719
|
-
if (!pending.senderId || !ctx.senderId) return "Cannot confirm Codex diagnostics because this command did not include the original sender identity.";
|
|
1720
|
-
if (pending.senderId !== ctx.senderId) return "Only the user who requested these Codex diagnostics can confirm the upload.";
|
|
1721
|
-
if (pending.channel !== ctx.channel) return "This Codex diagnostics confirmation belongs to a different channel.";
|
|
1722
|
-
const scopeMismatch = readCodexDiagnosticsScopeMismatch(pending, ctx);
|
|
1723
|
-
if (scopeMismatch) return scopeMismatch.confirmMessage;
|
|
1724
|
-
deletePendingCodexDiagnosticsConfirmation(token);
|
|
1532
|
+
const pending = consumeCodexDiagnosticsConfirmation(ctx, token, "confirm");
|
|
1533
|
+
if (typeof pending === "string") return pending;
|
|
1725
1534
|
if (!pending.privateRouted && !await hasAnyCodexDiagnosticsIdentity(ctx)) return "Cannot send Codex diagnostics because this command did not include a stable session identity.";
|
|
1726
1535
|
const currentTargets = pending.privateRouted ? resolvePendingCodexDiagnosticsTargets(deps, pending.targets, ctx.config) : await resolveCodexDiagnosticsTargets(deps, ctx);
|
|
1727
1536
|
if (!codexDiagnosticsTargetsMatch(pending.targets, currentTargets)) return "The Codex diagnostics sessions changed before confirmation. Run /diagnostics again for the current threads.";
|
|
1728
1537
|
return await sendCodexDiagnosticsFeedbackForTargets(deps, ctx, pluginConfig, pending.note ?? "", currentTargets, { cooldownScope: pending.scopeKey });
|
|
1729
1538
|
}
|
|
1730
1539
|
function cancelCodexDiagnosticsFeedback(ctx, token) {
|
|
1731
|
-
const pending =
|
|
1732
|
-
if (
|
|
1733
|
-
if (!pending.senderId || !ctx.senderId) return "Cannot cancel Codex diagnostics because this command did not include the original sender identity.";
|
|
1734
|
-
if (pending.senderId !== ctx.senderId) return "Only the user who requested these Codex diagnostics can cancel the upload.";
|
|
1735
|
-
if (pending.channel !== ctx.channel) return "This Codex diagnostics confirmation belongs to a different channel.";
|
|
1736
|
-
const scopeMismatch = readCodexDiagnosticsScopeMismatch(pending, ctx);
|
|
1737
|
-
if (scopeMismatch) return scopeMismatch.cancelMessage;
|
|
1738
|
-
deletePendingCodexDiagnosticsConfirmation(token);
|
|
1540
|
+
const pending = consumeCodexDiagnosticsConfirmation(ctx, token, "cancel");
|
|
1541
|
+
if (typeof pending === "string") return pending;
|
|
1739
1542
|
return [
|
|
1740
1543
|
"Codex diagnostics upload canceled.",
|
|
1741
1544
|
"Codex sessions:",
|
|
@@ -1743,13 +1546,12 @@ function cancelCodexDiagnosticsFeedback(ctx, token) {
|
|
|
1743
1546
|
].join("\n");
|
|
1744
1547
|
}
|
|
1745
1548
|
async function sendCodexDiagnosticsFeedbackForContext(deps, ctx, pluginConfig, note) {
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
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;
|
|
1749
1551
|
return await sendCodexDiagnosticsFeedbackForTargets(deps, ctx, pluginConfig, note, targets);
|
|
1750
1552
|
}
|
|
1751
1553
|
async function sendCodexDiagnosticsFeedbackForTargets(deps, ctx, pluginConfig, note, targets, options = {}) {
|
|
1752
|
-
if (targets.length === 0) return
|
|
1554
|
+
if (targets.length === 0) return NO_DIAGNOSTICS_THREAD;
|
|
1753
1555
|
const now = Date.now();
|
|
1754
1556
|
const cooldownMessage = readCodexDiagnosticsTargetsCooldownMessage(targets, ctx, now, { cooldownScope: options.cooldownScope });
|
|
1755
1557
|
if (cooldownMessage) return cooldownMessage;
|
|
@@ -1758,6 +1560,7 @@ async function sendCodexDiagnosticsFeedbackForTargets(deps, ctx, pluginConfig, n
|
|
|
1758
1560
|
const failed = [];
|
|
1759
1561
|
for (const target of targets) {
|
|
1760
1562
|
const assertCurrent = () => {
|
|
1563
|
+
ctx.assertOwnerCurrent?.();
|
|
1761
1564
|
const current = resolvePendingCodexDiagnosticsTargets(deps, [target], ctx.config);
|
|
1762
1565
|
if (!codexDiagnosticsTargetsMatch([target], current)) throw new Error("The Codex diagnostics session changed before upload; request it again.");
|
|
1763
1566
|
};
|
|
@@ -1809,6 +1612,22 @@ async function sendCodexDiagnosticsFeedbackForTargets(deps, ctx, pluginConfig, n
|
|
|
1809
1612
|
}
|
|
1810
1613
|
return formatCodexDiagnosticsUploadResult(sent, failed);
|
|
1811
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
|
+
}
|
|
1812
1631
|
async function hasAnyCodexDiagnosticsIdentity(ctx) {
|
|
1813
1632
|
if (await resolveControlTarget(ctx)) return true;
|
|
1814
1633
|
return (ctx.diagnosticsSessions ?? []).some((session) => Boolean(session.sessionId));
|
|
@@ -1955,6 +1774,7 @@ async function bindConversation(deps, ctx, pluginConfig, args) {
|
|
|
1955
1774
|
}
|
|
1956
1775
|
});
|
|
1957
1776
|
const threadLabel = parsed.threadId ?? "a new thread";
|
|
1777
|
+
assertCodexHostOwnerCurrent(ctx);
|
|
1958
1778
|
const request = await ctx.requestConversationBinding({
|
|
1959
1779
|
summary: `Codex app-server thread ${formatCodexDisplayText(threadLabel)} in ${formatCodexDisplayText(workspaceDir)}`,
|
|
1960
1780
|
detachHint: "/codex detach",
|
|
@@ -1988,6 +1808,7 @@ async function detachConversation(deps, ctx) {
|
|
|
1988
1808
|
bindingStore: deps.bindingStore,
|
|
1989
1809
|
identity,
|
|
1990
1810
|
expectedThreadId,
|
|
1811
|
+
assertCurrent: () => assertCodexHostOwnerCurrent(ctx),
|
|
1991
1812
|
...expectedStartId ? { expectedStartId } : {},
|
|
1992
1813
|
...isIncognitoSessionKey(sourceSessionKey) ? { allowUntracked: true } : {},
|
|
1993
1814
|
afterClear: async () => {
|
|
@@ -1996,6 +1817,7 @@ async function detachConversation(deps, ctx) {
|
|
|
1996
1817
|
})) return "This Codex conversation binding changed while detaching; try again.";
|
|
1997
1818
|
return detachedPublicConversation;
|
|
1998
1819
|
});
|
|
1820
|
+
assertCodexHostOwnerCurrent(ctx);
|
|
1999
1821
|
return await detachPublicConversation();
|
|
2000
1822
|
}
|
|
2001
1823
|
async function describeConversationBinding(deps, ctx) {
|
|
@@ -2119,7 +1941,10 @@ async function resumeThread(deps, ctx, pluginConfig, args) {
|
|
|
2119
1941
|
retained = await retainCodexAppServerBindingSubscription(client, effectiveThreadId, knownOwnership);
|
|
2120
1942
|
assertCurrent();
|
|
2121
1943
|
if (!retained) throw new Error("Codex resumed thread lost its native subscription owner.");
|
|
2122
|
-
if (bindingBeforeCommit && !sameOwner) await releaseCodexAppServerBindingSubscription(bindingBeforeCommit, {
|
|
1944
|
+
if (bindingBeforeCommit && !sameOwner) await releaseCodexAppServerBindingSubscription(bindingBeforeCommit, {
|
|
1945
|
+
assertCurrent,
|
|
1946
|
+
retainedClientId: clientId
|
|
1947
|
+
});
|
|
2123
1948
|
assertCurrent();
|
|
2124
1949
|
if (!await deps.bindingStore.mutate(identity, {
|
|
2125
1950
|
kind: "set",
|
|
@@ -2155,6 +1980,7 @@ async function resumeThread(deps, ctx, pluginConfig, args) {
|
|
|
2155
1980
|
sessionId: ctx.sessionId,
|
|
2156
1981
|
storePath: ctx.sessionTarget?.storePath,
|
|
2157
1982
|
assertCurrent: assertHostGeneration,
|
|
1983
|
+
assertOwnerCurrent: () => assertCodexHostOwnerCurrent(ctx),
|
|
2158
1984
|
beforeRequest: async (request) => {
|
|
2159
1985
|
const { thread } = await request({
|
|
2160
1986
|
method: "thread/read",
|
|
@@ -2199,6 +2025,7 @@ async function bindCodexCliNodeSession(deps, ctx, parsed) {
|
|
|
2199
2025
|
cwd: resolved.session?.cwd
|
|
2200
2026
|
});
|
|
2201
2027
|
const summary = `Codex CLI session ${formatCodexDisplayText(parsed.threadId)} on ${formatCodexDisplayText(nodeId)}`;
|
|
2028
|
+
assertCodexHostOwnerCurrent(ctx);
|
|
2202
2029
|
const request = await ctx.requestConversationBinding({
|
|
2203
2030
|
summary,
|
|
2204
2031
|
detachHint: "/codex detach",
|
|
@@ -2291,7 +2118,10 @@ async function handleComputerUseCommand(deps, ctx, pluginConfig, args) {
|
|
|
2291
2118
|
forceEnable: parsed.action === "install" || parsed.hasOverrides,
|
|
2292
2119
|
...Object.keys(parsed.overrides).length > 0 ? { overrides: parsed.overrides } : {}
|
|
2293
2120
|
};
|
|
2294
|
-
if (parsed.action === "install") return formatComputerUseStatus(await deps.installCodexComputerUse(
|
|
2121
|
+
if (parsed.action === "install") return formatComputerUseStatus(await deps.installCodexComputerUse({
|
|
2122
|
+
...params,
|
|
2123
|
+
assertCurrent: () => assertCodexHostOwnerCurrent(ctx)
|
|
2124
|
+
}));
|
|
2295
2125
|
return formatComputerUseStatus(await deps.readCodexComputerUseStatus(params));
|
|
2296
2126
|
}
|
|
2297
2127
|
async function handleNativeGoal(deps, ctx, pluginConfig, args) {
|
|
@@ -2325,7 +2155,10 @@ async function handleNativeGoal(deps, ctx, pluginConfig, args) {
|
|
|
2325
2155
|
}
|
|
2326
2156
|
if (action === "clear") {
|
|
2327
2157
|
if (args.length > 1) return "Usage: /codex goal clear";
|
|
2328
|
-
const response = await deps.codexControlRequest(pluginConfig, CODEX_CONTROL_METHODS.clearThreadGoal, { threadId: binding.threadId },
|
|
2158
|
+
const response = await deps.codexControlRequest(pluginConfig, CODEX_CONTROL_METHODS.clearThreadGoal, { threadId: binding.threadId }, {
|
|
2159
|
+
...goalRequestOptions,
|
|
2160
|
+
assertOwnerCurrent: () => assertCodexHostOwnerCurrent(ctx)
|
|
2161
|
+
});
|
|
2329
2162
|
return isJsonObject(response) && response.cleared === true ? "Cleared the Codex goal." : "No Codex goal was active.";
|
|
2330
2163
|
}
|
|
2331
2164
|
const requestedStatus = action === "pause" ? "paused" : action === "resume" ? "active" : action === "block" ? "blocked" : action === "complete" ? "complete" : void 0;
|
|
@@ -2338,6 +2171,7 @@ async function handleNativeGoal(deps, ctx, pluginConfig, args) {
|
|
|
2338
2171
|
...requestedStatus ? { status: requestedStatus } : {}
|
|
2339
2172
|
}, {
|
|
2340
2173
|
...goalRequestOptions,
|
|
2174
|
+
assertOwnerCurrent: () => assertCodexHostOwnerCurrent(ctx),
|
|
2341
2175
|
...(isObjectiveUpdate || requestedStatus === "active") && connection.usesSupervisionConnection ? { beforeRequest: supervisedCommandGuard(deps, target.identity, binding) } : {}
|
|
2342
2176
|
})));
|
|
2343
2177
|
}
|
|
@@ -2354,20 +2188,17 @@ function formatNativeGoal(response) {
|
|
|
2354
2188
|
`- Tokens: ${tokensUsed}${tokenBudget === void 0 ? "" : ` / ${tokenBudget}`}`
|
|
2355
2189
|
].join("\n");
|
|
2356
2190
|
}
|
|
2357
|
-
async function stopConversationTurn(deps, ctx
|
|
2191
|
+
async function stopConversationTurn(deps, ctx) {
|
|
2358
2192
|
const authority = await resolvePreparedCodexCommandAuthority(deps, ctx);
|
|
2359
2193
|
const { target, binding } = authority;
|
|
2360
2194
|
if (!target) return "Cannot stop Codex because this command did not include a stable binding identity.";
|
|
2361
2195
|
return (await deps.stopCodexConversationTurn({
|
|
2362
2196
|
identity: target.identity,
|
|
2363
2197
|
binding,
|
|
2364
|
-
|
|
2365
|
-
agentDir: target.agentDir,
|
|
2366
|
-
config: ctx.config,
|
|
2367
|
-
assertCurrent: authority.assertCurrent
|
|
2198
|
+
assertCurrent: authority.assertMutationCurrent
|
|
2368
2199
|
})).message;
|
|
2369
2200
|
}
|
|
2370
|
-
async function steerConversationTurn(deps, ctx,
|
|
2201
|
+
async function steerConversationTurn(deps, ctx, message) {
|
|
2371
2202
|
const authority = await resolvePreparedCodexCommandAuthority(deps, ctx);
|
|
2372
2203
|
const { target, binding } = authority;
|
|
2373
2204
|
if (!target) return "Cannot steer Codex because this command did not include a stable binding identity.";
|
|
@@ -2375,10 +2206,7 @@ async function steerConversationTurn(deps, ctx, pluginConfig, message) {
|
|
|
2375
2206
|
identity: target.identity,
|
|
2376
2207
|
binding,
|
|
2377
2208
|
message,
|
|
2378
|
-
|
|
2379
|
-
agentDir: target.agentDir,
|
|
2380
|
-
config: ctx.config,
|
|
2381
|
-
assertCurrent: authority.assertCurrent
|
|
2209
|
+
assertCurrent: authority.assertMutationCurrent
|
|
2382
2210
|
})).message;
|
|
2383
2211
|
}
|
|
2384
2212
|
async function setConversationModel(deps, ctx, pluginConfig, args) {
|
|
@@ -2410,7 +2238,8 @@ async function setConversationModel(deps, ctx, pluginConfig, args) {
|
|
|
2410
2238
|
config: ctx.config,
|
|
2411
2239
|
binding,
|
|
2412
2240
|
storePath: authority.storePath,
|
|
2413
|
-
assertCurrent: authority.assertCurrent
|
|
2241
|
+
assertCurrent: authority.assertCurrent,
|
|
2242
|
+
assertCommitAllowed: authority.assertMutationCurrent
|
|
2414
2243
|
});
|
|
2415
2244
|
}
|
|
2416
2245
|
async function setConversationFastMode(deps, ctx, args) {
|
|
@@ -2426,7 +2255,7 @@ async function setConversationFastMode(deps, ctx, args) {
|
|
|
2426
2255
|
bindingStore: deps.bindingStore,
|
|
2427
2256
|
binding,
|
|
2428
2257
|
enabled: parsed,
|
|
2429
|
-
assertCurrent: authority.assertCurrent
|
|
2258
|
+
assertCurrent: parsed === void 0 ? authority.assertCurrent : authority.assertMutationCurrent
|
|
2430
2259
|
});
|
|
2431
2260
|
}
|
|
2432
2261
|
async function setConversationPermissions(deps, ctx, args) {
|
|
@@ -2442,7 +2271,7 @@ async function setConversationPermissions(deps, ctx, args) {
|
|
|
2442
2271
|
mode: parsed,
|
|
2443
2272
|
config: ctx.config,
|
|
2444
2273
|
storePath: authority.storePath,
|
|
2445
|
-
assertCurrent: authority.assertHostCurrent,
|
|
2274
|
+
assertCurrent: parsed ? authority.assertHostMutationCurrent : authority.assertHostCurrent,
|
|
2446
2275
|
session: {
|
|
2447
2276
|
agentId: target.agentId,
|
|
2448
2277
|
sessionId: ctx.sessionId,
|
|
@@ -2471,7 +2300,7 @@ async function startThreadAction(deps, ctx, pluginConfig, kind, args) {
|
|
|
2471
2300
|
}
|
|
2472
2301
|
const compactCurrent = ctx.runtimeContext?.compactCurrent;
|
|
2473
2302
|
if (!compactCurrent) return "Codex compaction is unavailable because this command is not bound to a session.";
|
|
2474
|
-
authority.
|
|
2303
|
+
authority.assertMutationCurrent();
|
|
2475
2304
|
const result = await compactCurrent();
|
|
2476
2305
|
return result.compacted ? `Compacted Codex session (${result.tokensAfter ?? "unknown"} tokens after).` : `Codex compaction did not complete: ${formatCodexDisplayText(result.reason ?? "no reason returned")}.`;
|
|
2477
2306
|
}
|
|
@@ -2494,6 +2323,7 @@ async function startThreadAction(deps, ctx, pluginConfig, kind, args) {
|
|
|
2494
2323
|
sessionKey: authority.sessionKey,
|
|
2495
2324
|
storePath: authority.storePath,
|
|
2496
2325
|
assertCurrent: authority.assertCurrent,
|
|
2326
|
+
assertOwnerCurrent: () => assertCodexHostOwnerCurrent(ctx),
|
|
2497
2327
|
...connection.usesSupervisionConnection ? {
|
|
2498
2328
|
startOptions: connection.appServer.start,
|
|
2499
2329
|
beforeRequest: supervisedCommandGuard(deps, target.identity, binding)
|
|
@@ -2569,7 +2399,11 @@ function formatCodexAvailablePlugins(plugins, warnings, query, page) {
|
|
|
2569
2399
|
//#region extensions/codex/src/command-plugins-management.ts
|
|
2570
2400
|
const POLICY_REFRESH_HINT = "Takes effect on your next message.";
|
|
2571
2401
|
const AVAILABLE_USAGE = "Usage: /codex plugins available [query] [--page <positive integer>]. Search text must be at most 100 characters; use -- before literal query text that contains options.";
|
|
2572
|
-
async function handleCodexPluginsSubcommand(
|
|
2402
|
+
async function handleCodexPluginsSubcommand(input, rest, io, runtime) {
|
|
2403
|
+
const ctx = {
|
|
2404
|
+
...input,
|
|
2405
|
+
gatewayClientScopes: input.gatewayClientScopes?.slice()
|
|
2406
|
+
};
|
|
2573
2407
|
const [verb = "list", ...args] = rest;
|
|
2574
2408
|
const normalized = verb.toLowerCase();
|
|
2575
2409
|
if (normalized === "menu") {
|
|
@@ -2611,7 +2445,7 @@ async function handleCodexPluginsSubcommand(ctx, rest, io, runtime) {
|
|
|
2611
2445
|
});
|
|
2612
2446
|
return formatCodexAvailablePlugins(discovered.plugins, discovered.warnings, query, page);
|
|
2613
2447
|
} catch (error) {
|
|
2614
|
-
return { text: `Could not list Codex plugins: ${formatCodexDisplayText(
|
|
2448
|
+
return { text: `Could not list Codex plugins: ${formatCodexDisplayText(coerceErrorMessage(error))}` };
|
|
2615
2449
|
}
|
|
2616
2450
|
}
|
|
2617
2451
|
if (normalized === "status") {
|
|
@@ -2635,7 +2469,7 @@ async function handleCodexPluginsSubcommand(ctx, rest, io, runtime) {
|
|
|
2635
2469
|
if (args.length !== 1 || !args[0]) return { text: "Usage: /codex plugins install <plugin>@<marketplace>" };
|
|
2636
2470
|
if (!canMutateCodexHost(ctx)) return { text: "Only an owner or operator.admin gateway client can run /codex plugins install." };
|
|
2637
2471
|
if (!runtime) return { text: "Codex plugin installation is unavailable for this command." };
|
|
2638
|
-
return await installCodexPlugin(args[0], io, runtime);
|
|
2472
|
+
return await installCodexPlugin(args[0], io, runtime, ctx);
|
|
2639
2473
|
}
|
|
2640
2474
|
const target = args[0];
|
|
2641
2475
|
if (normalized === "enable" || normalized === "disable") {
|
|
@@ -2653,6 +2487,7 @@ async function handleCodexPluginsSubcommand(ctx, rest, io, runtime) {
|
|
|
2653
2487
|
if (configured.status === "ambiguous" || configured.status === "mismatched") return { text: describeConfiguredPluginIdentityConflict(target, configured.status) };
|
|
2654
2488
|
if (configured.status === "missing") return { text: `Codex sub-plugin '${formatCodexDisplayText(target)}' is not configured. Run '/codex plugins list' to see configured plugins.` };
|
|
2655
2489
|
const configKey = configured.configKey;
|
|
2490
|
+
assertCodexHostOwnerCurrent(ctx);
|
|
2656
2491
|
await io.mutate((block) => {
|
|
2657
2492
|
if (wantEnabled) block.enabled = true;
|
|
2658
2493
|
block.plugins ??= {};
|
|
@@ -2660,7 +2495,7 @@ async function handleCodexPluginsSubcommand(ctx, rest, io, runtime) {
|
|
|
2660
2495
|
...block.plugins[configKey],
|
|
2661
2496
|
enabled: wantEnabled
|
|
2662
2497
|
};
|
|
2663
|
-
});
|
|
2498
|
+
}, () => assertCodexHostOwnerCurrent(ctx));
|
|
2664
2499
|
return { text: `${formatCodexDisplayText(configKey)}: ${wantEnabled ? "enabled" : "disabled"} in openclaw.json. ${POLICY_REFRESH_HINT}` };
|
|
2665
2500
|
}
|
|
2666
2501
|
return { text: `Unknown /codex plugins subcommand: ${formatCodexDisplayText(verb)}\n\n${buildPluginsHelp()}` };
|
|
@@ -2766,7 +2601,7 @@ function buildPluginsHelp() {
|
|
|
2766
2601
|
"Only an owner or operator.admin can discover, inspect, refresh hosted apps, install, enable, or disable plugins."
|
|
2767
2602
|
].join("\n");
|
|
2768
2603
|
}
|
|
2769
|
-
async function installCodexPlugin(requestedId, io, runtime) {
|
|
2604
|
+
async function installCodexPlugin(requestedId, io, runtime, ctx) {
|
|
2770
2605
|
const requested = parseCodexPluginMarketplaceId(requestedId);
|
|
2771
2606
|
if (!requested) return { text: "Invalid plugin identifier. Use /codex plugins install <plugin>@<marketplace>. Both names allow ASCII letters, digits, underscores, and hyphens. Plugin names may also contain dots between nonempty segments." };
|
|
2772
2607
|
let plugin;
|
|
@@ -2782,7 +2617,7 @@ async function installCodexPlugin(requestedId, io, runtime) {
|
|
|
2782
2617
|
if (!plugin) return { text: `Multiple available Codex plugins match '${formatCodexDisplayText(requestedId)}'; the marketplace identity must be unique.` };
|
|
2783
2618
|
} else plugin = matching[0];
|
|
2784
2619
|
} catch (error) {
|
|
2785
|
-
return { text: `Could not verify the requested Codex plugin: ${formatCodexDisplayText(
|
|
2620
|
+
return { text: `Could not verify the requested Codex plugin: ${formatCodexDisplayText(coerceErrorMessage(error))}` };
|
|
2786
2621
|
}
|
|
2787
2622
|
if (!plugin) return { text: `${formatCodexDisplayText(requestedId)} was not found. Run /codex plugins available to inspect the current marketplaces.` };
|
|
2788
2623
|
if (!plugin.available) return { text: `${formatCodexDisplayText(requestedId)} is unavailable or disabled by its marketplace administrator.` };
|
|
@@ -2795,7 +2630,7 @@ async function installCodexPlugin(requestedId, io, runtime) {
|
|
|
2795
2630
|
const configured = resolveInstalledPluginKey((await io.readConfig()).plugins ?? {}, plugin);
|
|
2796
2631
|
if (configured.status === "ambiguous" || configured.status === "mismatched") return { text: describeConfiguredPluginIdentityConflict(requestedId, configured.status) };
|
|
2797
2632
|
} catch (error) {
|
|
2798
|
-
return { text: `Could not verify existing Codex plugin authorization: ${formatCodexDisplayText(
|
|
2633
|
+
return { text: `Could not verify existing Codex plugin authorization: ${formatCodexDisplayText(coerceErrorMessage(error))}` };
|
|
2799
2634
|
}
|
|
2800
2635
|
let result;
|
|
2801
2636
|
if (!alreadyInstalled) {
|
|
@@ -2808,13 +2643,15 @@ async function installCodexPlugin(requestedId, io, runtime) {
|
|
|
2808
2643
|
} : void 0;
|
|
2809
2644
|
if (!requestParams) return { text: `${formatCodexDisplayText(requestedId)} cannot be installed because its marketplace did not provide a trusted local path or remote plugin identifier.` };
|
|
2810
2645
|
try {
|
|
2646
|
+
assertCodexHostOwnerCurrent(ctx);
|
|
2811
2647
|
result = await runtime.install(requestParams);
|
|
2812
2648
|
} catch (error) {
|
|
2813
|
-
return { text: `Could not install ${formatCodexDisplayText(requestedId)}: ${formatCodexDisplayText(
|
|
2649
|
+
return { text: `Could not install ${formatCodexDisplayText(requestedId)}: ${formatCodexDisplayText(coerceErrorMessage(error))}` };
|
|
2814
2650
|
}
|
|
2815
2651
|
}
|
|
2816
2652
|
const selectedPlugin = plugin;
|
|
2817
2653
|
try {
|
|
2654
|
+
assertCodexHostOwnerCurrent(ctx);
|
|
2818
2655
|
await io.mutate((block) => {
|
|
2819
2656
|
block.plugins ??= {};
|
|
2820
2657
|
const configured = resolveInstalledPluginKey(block.plugins, selectedPlugin);
|
|
@@ -2831,15 +2668,15 @@ async function installCodexPlugin(requestedId, io, runtime) {
|
|
|
2831
2668
|
pluginName: existing?.pluginName ?? (curated ? selectedPlugin.pluginName : persistedPluginName(selectedPlugin))
|
|
2832
2669
|
};
|
|
2833
2670
|
block.plugins[configKey] = updated;
|
|
2834
|
-
});
|
|
2671
|
+
}, () => assertCodexHostOwnerCurrent(ctx));
|
|
2835
2672
|
} catch (error) {
|
|
2836
|
-
return { text: `${formatCodexDisplayText(requestedId)} was installed in Codex but could not be authorized in OpenClaw and will not be exposed: ${formatCodexDisplayText(
|
|
2673
|
+
return { text: `${formatCodexDisplayText(requestedId)} was installed in Codex but could not be authorized in OpenClaw and will not be exposed: ${formatCodexDisplayText(coerceErrorMessage(error))}` };
|
|
2837
2674
|
}
|
|
2838
2675
|
let refreshWarning = "";
|
|
2839
2676
|
if (runtime.refresh) try {
|
|
2840
2677
|
refreshWarning = (await runtime.refresh(workspaceDir)).diagnostics.map((diagnostic) => ` ${formatCodexDisplayText(diagnostic.message)}`).join("");
|
|
2841
2678
|
} catch (error) {
|
|
2842
|
-
refreshWarning = ` Runtime refresh requires a new conversation: ${formatCodexDisplayText(
|
|
2679
|
+
refreshWarning = ` Runtime refresh requires a new conversation: ${formatCodexDisplayText(coerceErrorMessage(error))}`;
|
|
2843
2680
|
}
|
|
2844
2681
|
const appsNeedingAuth = result?.appsNeedingAuth ?? [];
|
|
2845
2682
|
if (appsNeedingAuth.length > 0) {
|
|
@@ -2871,22 +2708,7 @@ async function installCodexPlugin(requestedId, io, runtime) {
|
|
|
2871
2708
|
type: "text",
|
|
2872
2709
|
text: `Some app setup permissions could not be confirmed. Run /codex plugins status ${requestedId} to check the current account and restrictions.`
|
|
2873
2710
|
}] : [],
|
|
2874
|
-
|
|
2875
|
-
type: "buttons",
|
|
2876
|
-
buttons: [...appLinks.length > 0 ? [{
|
|
2877
|
-
label: "Refresh hosted apps",
|
|
2878
|
-
action: {
|
|
2879
|
-
type: "command",
|
|
2880
|
-
command: "/codex plugins refresh"
|
|
2881
|
-
}
|
|
2882
|
-
}] : [], {
|
|
2883
|
-
label: "Check status",
|
|
2884
|
-
action: {
|
|
2885
|
-
type: "command",
|
|
2886
|
-
command: `/codex plugins status ${requestedId}`
|
|
2887
|
-
}
|
|
2888
|
-
}]
|
|
2889
|
-
},
|
|
2711
|
+
buildCodexPluginStatusButtons(requestedId, appLinks.length > 0),
|
|
2890
2712
|
{
|
|
2891
2713
|
type: "context",
|
|
2892
2714
|
text: `${refreshWarning.trim()} ${POLICY_REFRESH_HINT}`.trim()
|
|
@@ -2902,9 +2724,6 @@ async function installCodexPlugin(requestedId, io, runtime) {
|
|
|
2902
2724
|
const status = alreadyInstalled ? "bundle was already installed in Codex" : "bundle was installed in Codex";
|
|
2903
2725
|
return { text: `${formatCodexDisplayText(requestedId)} ${status}. OpenClaw app access is configured.${refreshWarning} ${POLICY_REFRESH_HINT}` };
|
|
2904
2726
|
}
|
|
2905
|
-
function errorMessage(error) {
|
|
2906
|
-
return error instanceof Error ? error.message : String(error);
|
|
2907
|
-
}
|
|
2908
2727
|
function formatPluginList(plugins, options = {}) {
|
|
2909
2728
|
const globalEnabled = options.globalEnabled === true;
|
|
2910
2729
|
const keys = Object.keys(plugins).toSorted();
|
|
@@ -2935,7 +2754,11 @@ function formatPluginList(plugins, options = {}) {
|
|
|
2935
2754
|
//#region extensions/codex/src/command-plugins-runtime.ts
|
|
2936
2755
|
const SCOPE_CHANGED_MESSAGE = "Codex account, conversation, or plugin policy changed. Run the command again.";
|
|
2937
2756
|
async function withCodexPluginCommandContext(params, run) {
|
|
2938
|
-
const { deps,
|
|
2757
|
+
const { deps, pluginConfig } = params;
|
|
2758
|
+
const ctx = {
|
|
2759
|
+
...params.ctx,
|
|
2760
|
+
gatewayClientScopes: params.ctx.gatewayClientScopes?.slice()
|
|
2761
|
+
};
|
|
2939
2762
|
const current = await deps.codexPluginsManagementIo?.readConfig() ?? {};
|
|
2940
2763
|
const initialPolicy = JSON.stringify(current);
|
|
2941
2764
|
const { scope, target, binding } = await resolveCommandAppServerContext(deps, ctx, pluginConfig);
|
|
@@ -3016,7 +2839,10 @@ async function withCodexPluginCommandContext(params, run) {
|
|
|
3016
2839
|
const response = await request({
|
|
3017
2840
|
method,
|
|
3018
2841
|
requestParams,
|
|
3019
|
-
assertCurrent
|
|
2842
|
+
assertCurrent: () => {
|
|
2843
|
+
assertCurrent();
|
|
2844
|
+
assertCodexHostOwnerCurrent(ctx);
|
|
2845
|
+
}
|
|
3020
2846
|
});
|
|
3021
2847
|
await validateCurrent();
|
|
3022
2848
|
return response;
|
|
@@ -3065,6 +2891,17 @@ async function handleCodexSubcommand(ctx, options) {
|
|
|
3065
2891
|
if (CODEX_NATIVE_CONTROL_SUBCOMMANDS.has(normalized) && !returnsBeforeNativeCodexExecution(normalized, rest) && !isReadOnlyCodexGoalCommand(normalized, rest) && !canMutateCodexHost(ctx)) return { text: CODEX_NATIVE_EXECUTION_AUTH_ERROR };
|
|
3066
2892
|
const sandboxBlock = resolveCodexNativeCommandSandboxBlock(ctx, normalized, rest);
|
|
3067
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}` };
|
|
3068
2905
|
if (normalized === "plugins") {
|
|
3069
2906
|
if (rest[0]?.toLowerCase() === "refresh") {
|
|
3070
2907
|
if (rest.length !== 1) return { text: "Usage: /codex plugins refresh — refresh hosted app inventory for the current Codex account/runtime." };
|
|
@@ -3099,7 +2936,8 @@ async function handleCodexSubcommand(ctx, options) {
|
|
|
3099
2936
|
const scope = await getAppServerScope();
|
|
3100
2937
|
return await deps.codexControlRequest(options.pluginConfig, CODEX_CONTROL_METHODS.installPlugin, requestParams, {
|
|
3101
2938
|
...scope,
|
|
3102
|
-
config: ctx.config
|
|
2939
|
+
config: ctx.config,
|
|
2940
|
+
assertOwnerCurrent: () => assertCodexHostOwnerCurrent(ctx)
|
|
3103
2941
|
});
|
|
3104
2942
|
},
|
|
3105
2943
|
refresh: async (workspaceDir) => {
|
|
@@ -3132,7 +2970,6 @@ async function handleCodexSubcommand(ctx, options) {
|
|
|
3132
2970
|
appServerVersion: client.getServerVersion(),
|
|
3133
2971
|
runtimeIdentity: client.getRuntimeIdentity()
|
|
3134
2972
|
});
|
|
3135
|
-
defaultCodexPluginMetadataCache.invalidate(appCacheKey);
|
|
3136
2973
|
return await refreshCodexPluginRuntimeState({
|
|
3137
2974
|
configCwd: workspaceDir,
|
|
3138
2975
|
appCache: defaultCodexAppInventoryCache,
|
|
@@ -3153,12 +2990,10 @@ async function handleCodexSubcommand(ctx, options) {
|
|
|
3153
2990
|
});
|
|
3154
2991
|
}
|
|
3155
2992
|
if (normalized === "status") {
|
|
3156
|
-
if (rest.length > 0) return { text: "Usage: /codex status" };
|
|
3157
2993
|
const { agentDir } = resolveCodexConversationControlScope(ctx);
|
|
3158
2994
|
return { text: formatCodexStatus(await deps.readCodexStatusProbes(options.pluginConfig, ctx.config, agentDir)) };
|
|
3159
2995
|
}
|
|
3160
2996
|
if (normalized === "models") {
|
|
3161
|
-
if (rest.length > 0) return { text: "Usage: /codex models" };
|
|
3162
2997
|
const { agentDir } = resolveCodexConversationControlScope(ctx);
|
|
3163
2998
|
return { text: formatModels(await deps.listCodexAppServerModels(deps.requestOptions(options.pluginConfig, 100, ctx.config, agentDir))) };
|
|
3164
2999
|
}
|
|
@@ -3167,19 +3002,10 @@ async function handleCodexSubcommand(ctx, options) {
|
|
|
3167
3002
|
if (normalized === "sessions") return { text: await buildCodexCliSessions(deps, rest) };
|
|
3168
3003
|
if (normalized === "resume") return { text: await resumeThread(deps, ctx, options.pluginConfig, rest) };
|
|
3169
3004
|
if (normalized === "bind") return await bindConversation(deps, ctx, options.pluginConfig, rest);
|
|
3170
|
-
if (normalized === "detach" || normalized === "unbind") {
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
}
|
|
3174
|
-
if (normalized === "binding") {
|
|
3175
|
-
if (rest.length > 0) return { text: "Usage: /codex binding" };
|
|
3176
|
-
return { text: await describeConversationBinding(deps, ctx) };
|
|
3177
|
-
}
|
|
3178
|
-
if (normalized === "stop") {
|
|
3179
|
-
if (rest.length > 0) return { text: "Usage: /codex stop" };
|
|
3180
|
-
return { text: await stopConversationTurn(deps, ctx, options.pluginConfig) };
|
|
3181
|
-
}
|
|
3182
|
-
if (normalized === "steer") return { text: await steerConversationTurn(deps, ctx, options.pluginConfig, rest.join(" ")) };
|
|
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) };
|
|
3008
|
+
if (normalized === "steer") return { text: await steerConversationTurn(deps, ctx, rest.join(" ")) };
|
|
3183
3009
|
if (normalized === "model") return { text: await setConversationModel(deps, ctx, options.pluginConfig, rest) };
|
|
3184
3010
|
if (normalized === "fast") {
|
|
3185
3011
|
if (isMenuVerb(rest)) return buildCodexFastMenuReply();
|
|
@@ -3189,31 +3015,21 @@ async function handleCodexSubcommand(ctx, options) {
|
|
|
3189
3015
|
if (isMenuVerb(rest)) return buildCodexPermissionsMenuReply();
|
|
3190
3016
|
return { text: await setConversationPermissions(deps, ctx, rest) };
|
|
3191
3017
|
}
|
|
3192
|
-
if (normalized === "compact") return { text: await startThreadAction(deps, ctx, options.pluginConfig,
|
|
3193
|
-
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) };
|
|
3194
3019
|
if (normalized === "diagnostics") return await handleCodexDiagnosticsFeedback(deps, ctx, options.pluginConfig, rest.join(" "), "/codex diagnostics");
|
|
3195
3020
|
if (normalized === "computer-use" || normalized === "computeruse") {
|
|
3196
3021
|
if (isMenuVerb(rest)) return buildCodexComputerUseMenuReply();
|
|
3197
3022
|
return { text: await handleComputerUseCommand(deps, ctx, options.pluginConfig, rest) };
|
|
3198
3023
|
}
|
|
3199
|
-
if (normalized === "mcp") {
|
|
3200
|
-
if (rest.length > 0) return { text: "Usage: /codex mcp" };
|
|
3024
|
+
if (normalized === "mcp" || normalized === "skills") {
|
|
3201
3025
|
const scope = await resolveCommandAppServerScope(deps, ctx, options.pluginConfig);
|
|
3202
|
-
|
|
3026
|
+
const response = await deps.codexControlRequest(options.pluginConfig, normalized === "mcp" ? CODEX_CONTROL_METHODS.listMcpServers : CODEX_CONTROL_METHODS.listSkills, normalized === "mcp" ? { limit: 100 } : {}, {
|
|
3203
3027
|
config: ctx.config,
|
|
3204
3028
|
...scope
|
|
3205
|
-
})
|
|
3206
|
-
|
|
3207
|
-
if (normalized === "skills") {
|
|
3208
|
-
if (rest.length > 0) return { text: "Usage: /codex skills" };
|
|
3209
|
-
const scope = await resolveCommandAppServerScope(deps, ctx, options.pluginConfig);
|
|
3210
|
-
return { text: formatSkills(await deps.codexControlRequest(options.pluginConfig, CODEX_CONTROL_METHODS.listSkills, {}, {
|
|
3211
|
-
config: ctx.config,
|
|
3212
|
-
...scope
|
|
3213
|
-
})) };
|
|
3029
|
+
});
|
|
3030
|
+
return { text: normalized === "mcp" ? formatList(response, "MCP servers") : formatSkills(response) };
|
|
3214
3031
|
}
|
|
3215
3032
|
if (normalized === "account") {
|
|
3216
|
-
if (rest.length > 0) return { text: "Usage: /codex account" };
|
|
3217
3033
|
const scope = await resolveCommandAppServerScope(deps, ctx, options.pluginConfig);
|
|
3218
3034
|
const requestScope = {
|
|
3219
3035
|
config: ctx.config,
|
|
@@ -3223,6 +3039,7 @@ async function handleCodexSubcommand(ctx, options) {
|
|
|
3223
3039
|
return { text: formatAccount(account, limits, await readCodexAccountAuthOverview({
|
|
3224
3040
|
ctx,
|
|
3225
3041
|
agentDir: scope.agentDir,
|
|
3042
|
+
authProfileId: scope.authProfileId,
|
|
3226
3043
|
pluginConfig: options.pluginConfig,
|
|
3227
3044
|
safeCodexControlRequest: deps.safeCodexControlRequest,
|
|
3228
3045
|
account,
|
|
@@ -3234,11 +3051,7 @@ async function handleCodexSubcommand(ctx, options) {
|
|
|
3234
3051
|
function resolvePluginRuntimeRefreshMethod(method) {
|
|
3235
3052
|
const recognized = [
|
|
3236
3053
|
CODEX_CONTROL_METHODS.listPlugins,
|
|
3237
|
-
CODEX_CONTROL_METHODS.listSkills,
|
|
3238
|
-
CODEX_CONTROL_METHODS.listHooks,
|
|
3239
|
-
CODEX_CONTROL_METHODS.reloadMcpServers,
|
|
3240
3054
|
CODEX_CONTROL_METHODS.installedApps,
|
|
3241
|
-
CODEX_CONTROL_METHODS.listApps,
|
|
3242
3055
|
CODEX_CONTROL_METHODS.readApps
|
|
3243
3056
|
].find((candidate) => candidate === method);
|
|
3244
3057
|
if (!recognized) throw new Error(`Unexpected Codex plugin refresh method: ${method}`);
|