@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.
Files changed (174) hide show
  1. package/README.md +2 -0
  2. package/assets/icon.png +0 -0
  3. package/dist/.setup/{account-usage-runtime-C2MOIvfq.mjs → account-usage-runtime-DFhbh1zz.mjs} +6 -6
  4. package/dist/.setup/{apply-CJ0ZfmBG.mjs → apply-D3GcSoSa.mjs} +35 -55
  5. package/dist/.setup/{attempt-client-cleanup-BpYKdTA0.mjs → attempt-client-cleanup-DOP-cW5j.mjs} +179 -73
  6. package/dist/.setup/attempt-workspace-context-C5HigshI.mjs +164 -0
  7. package/dist/.setup/{auth-binding-DhLWa_7K.mjs → auth-binding-BLWz7stm.mjs} +14 -1
  8. package/dist/.setup/{auth-cache-key-QirmgiCo.mjs → auth-cache-key-Dbvq-QgB.mjs} +41 -111
  9. package/dist/.setup/{auth-profile-WqZtZfXN.mjs → auth-profile-B0okYl2D.mjs} +1 -2
  10. package/dist/.setup/auth-profile-health-oHizqgye.mjs +53 -0
  11. package/dist/.setup/auth-profile-recovery-BREezV0L.mjs +14 -0
  12. package/dist/.setup/auth-start-options-BPIPeEX8.mjs +44 -0
  13. package/dist/.setup/{binding-connection-Bm38niE8.mjs → binding-connection-DTtN1KrX.mjs} +2 -2
  14. package/dist/.setup/{binding-connection.runtime-CnRMC0ta.mjs → binding-connection.runtime-6TpgD1M6.mjs} +5 -5
  15. package/dist/.setup/{bounded-turn-BtlZcivC.mjs → bounded-turn-CbjoN2OW.mjs} +140 -37
  16. package/dist/.setup/bounded-turn-isolation-B8K_ylqk.mjs +14 -0
  17. package/dist/.setup/{build-state-Xx9ybZqa.mjs → build-state-Da1_z0kd.mjs} +1 -1
  18. package/dist/.setup/{capabilities-_vXcZGSx.mjs → capabilities-B3WEZl4e.mjs} +2 -10
  19. package/dist/.setup/{client-vXs2929Q.mjs → client-N0JpgSzF.mjs} +635 -872
  20. package/dist/.setup/client-catalog-response-5HHLdcde.mjs +285 -0
  21. package/dist/.setup/{command-dispatch-naHIZwwF.mjs → command-dispatch-BeAoaovI.mjs} +9 -8
  22. package/dist/.setup/{command-formatters-CGEkdawF.mjs → command-formatters-R3ckE3Co.mjs} +36 -64
  23. package/dist/.setup/{command-handlers-BtAJEW1X.mjs → command-handlers-ylTMS00z.mjs} +301 -488
  24. package/dist/.setup/{command-rpc-DHFpn4le.mjs → command-rpc-CGJGUQ6Y.mjs} +40 -28
  25. package/dist/.setup/compact-C2WamavS.mjs +776 -0
  26. package/dist/.setup/{config-CedDWjM-.mjs → config-DKhXquav.mjs} +26 -28
  27. package/dist/.setup/{config-options-BsanJ8QG.mjs → config-options-CzyWLTJt.mjs} +68 -65
  28. package/dist/.setup/{config-parsing-CcB9iPoq.mjs → config-parsing-b088LyhT.mjs} +57 -60
  29. package/dist/.setup/{config-runtime-CeAhl_h4.mjs → config-runtime-C0NbLms1.mjs} +2 -2
  30. package/dist/.setup/{config-security-BRQ2mgW9.mjs → config-security-CE-FcGw9.mjs} +51 -215
  31. package/dist/.setup/{config-utils-DujwEnhg.mjs → config-utils-D0CXecki.mjs} +3 -13
  32. package/dist/.setup/context-engine-projection-PezSESth.mjs +387 -0
  33. package/dist/.setup/{conversation-binding-DhzrpTM6.mjs → conversation-binding-3Min8qvP.mjs} +71 -105
  34. package/dist/.setup/{conversation-binding-data-CrcyZk6O.mjs → conversation-binding-data-C746z5Pn.mjs} +8 -12
  35. package/dist/.setup/{conversation-control-DN53ns41.mjs → conversation-control-CEP8X5JC.mjs} +30 -69
  36. package/dist/.setup/{cyber-failover-DYwbmf1o.mjs → cyber-failover-XV0nNRZu.mjs} +1 -1
  37. package/dist/.setup/{cyber-failover-notice-e9G3J9-e.mjs → cyber-failover-notice-RNpGpTyP.mjs} +1 -1
  38. package/dist/.setup/{dynamic-tools-D16lOp67.mjs → dynamic-tools-DzlsLUuS.mjs} +3136 -3167
  39. package/dist/.setup/{effective-mcp-catalog-K6kLCN8X.mjs → effective-mcp-catalog-CxUtC-xG.mjs} +8 -17
  40. package/dist/.setup/{ephemeral-turn-R1gA8Sn6.mjs → ephemeral-turn-CDsPJOa2.mjs} +9 -6
  41. package/dist/.setup/event-projector-assistant-message-CigreO4K.mjs +69 -0
  42. package/dist/.setup/{event-projector-usage-C7Ntzs-f.mjs → event-projector-usage-03R0I2dM.mjs} +4 -26
  43. package/dist/.setup/event-projector-values-DJSz8BTk.mjs +106 -0
  44. package/dist/.setup/incognito-session-DWYapfwf.mjs +2 -0
  45. package/dist/.setup/{inference-context-fulhZuz8.mjs → inference-context-D-9gWlTR.mjs} +16 -18
  46. package/dist/.setup/inference-dispatch-CMZtjQyz.mjs +359 -0
  47. package/dist/.setup/inference-metadata-CgIf7sOx.mjs +81 -0
  48. package/dist/.setup/inference-proxy-DhcXOgUE.mjs +561 -0
  49. package/dist/.setup/{isolated-completion-B6srt48J.mjs → isolated-completion-Dm3PzxJk.mjs} +15 -11
  50. package/dist/.setup/launch-args-DbFCehO7.mjs +196 -0
  51. package/dist/.setup/{managed-binary-DP6Rib3P.mjs → managed-binary-kiWRhNRE.mjs} +16 -9
  52. package/dist/.setup/{model-catalog-DkvUuBey.mjs → model-catalog-PAuZgJC6.mjs} +14 -14
  53. package/dist/.setup/model-runtime-BdqzOMkU.mjs +11 -0
  54. package/dist/.setup/{models-BDFgm_G-.mjs → models-DHXZtVVk.mjs} +9 -18
  55. package/dist/.setup/{native-auth-BLZGqFjw.mjs → native-auth-CuG53tu4.mjs} +5 -5
  56. package/dist/.setup/{native-execution-policy-YBMHSzC4.mjs → native-execution-policy-BxZJy5mP.mjs} +6 -31
  57. package/dist/.setup/{native-subagent-monitor-B1hxzIOy.mjs → native-subagent-monitor-Dpsmf2wz.mjs} +4422 -3808
  58. package/dist/.setup/native-subagent-pending-assignments-DwkCzLvD.mjs +203 -0
  59. package/dist/.setup/native-task-assignments-DMQ0g3hu.mjs +194 -0
  60. package/dist/.setup/{node-cli-sessions-Cl8b2ZF3.mjs → node-cli-sessions-HC4W6FLI.mjs} +99 -111
  61. package/dist/.setup/node-exec-server.runtime-BgBfWQqo.mjs +244 -0
  62. package/dist/.setup/{plan-xD7WKYTM.mjs → plan-Y-QIvrKB.mjs} +118 -163
  63. package/dist/.setup/{plugin-activation-r8nq5Jzp.mjs → plugin-activation-cNHRfaxU.mjs} +10 -47
  64. package/dist/.setup/{plugin-app-cache-key-BOxKP7db.mjs → plugin-app-cache-key-BL9B5H0L.mjs} +9 -42
  65. package/dist/.setup/{plugin-inventory-DUle8DLz.mjs → plugin-inventory-Cky2XJUw.mjs} +32 -23
  66. package/dist/.setup/{plugin-marketplace-discovery-P-Vndfqq.mjs → plugin-marketplace-discovery-D_dV9FXa.mjs} +22 -25
  67. package/dist/.setup/{plugin-metadata-cache-DsS5buNa.mjs → plugin-metadata-cache-DsjsL1dr.mjs} +328 -318
  68. package/dist/.setup/protocol-CANUwXJ3.mjs +17 -0
  69. package/dist/.setup/provider-DH8NSzGt.mjs +51 -0
  70. package/dist/.setup/{provider-capabilities-B8J4Dy-O.mjs → provider-capabilities-CAxoF-X1.mjs} +35 -12
  71. package/dist/.setup/{rate-limits-DOEGYRNs.mjs → rate-limits-B7-X2TgG.mjs} +123 -166
  72. package/dist/.setup/{request-BioXJLYa.mjs → request-BHZ1nz8d.mjs} +25 -16
  73. package/dist/.setup/responses-oauth-twnuTaAa.mjs +93 -0
  74. package/dist/.setup/rpc-error-BlD2vuzn.mjs +31 -0
  75. package/dist/.setup/{run-attempt-rlA07pUv.mjs → run-attempt-D8RZUOzY.mjs} +2046 -1454
  76. package/dist/.setup/{run-attempt-lifecycle-B7JbY4-F.mjs → run-attempt-lifecycle-C-6O3Exn.mjs} +10 -24
  77. package/dist/.setup/{runtime-artifact-Dy38Z5iU.mjs → runtime-artifact-DDQ-HGXf.mjs} +43 -47
  78. package/dist/.setup/runtime-artifact-connection-D68qQn1m.mjs +78 -0
  79. package/dist/.setup/sandbox-guard-DjCz2eOw.mjs +126 -0
  80. package/dist/.setup/scope-DOC1Xjc8.mjs +6 -0
  81. package/dist/.setup/session-binding-DGCYAfvD.mjs +443 -0
  82. package/dist/.setup/{session-binding-record-TH3xA0zj.mjs → session-binding-record-Oe9L-CNY.mjs} +73 -132
  83. package/dist/.setup/{session-binding-sidecars-CKYEcfNn.mjs → session-binding-sidecars-jo6H8dFr.mjs} +242 -60
  84. package/dist/.setup/{session-catalog-fUdWDx-U.mjs → session-catalog-4sCdv5qx.mjs} +598 -452
  85. package/dist/.setup/{session-catalog-adoption-CR_whkEW.mjs → session-catalog-adoption-BU_pHWG7.mjs} +59 -26
  86. package/dist/.setup/{session-catalog-archive-CwZaPacf.mjs → session-catalog-archive-spHfihri.mjs} +7 -7
  87. package/dist/.setup/session-catalog-events-DePDzzjc.mjs +139 -0
  88. package/dist/.setup/session-catalog-home-id-vlih0B_g.mjs +22 -0
  89. package/dist/.setup/{session-catalog-index-B141u15s.mjs → session-catalog-index-CZvDzC6z.mjs} +286 -182
  90. package/dist/.setup/{session-catalog-index-order-Cc5BzlQr.mjs → session-catalog-index-order-BcQpHks3.mjs} +2 -2
  91. package/dist/.setup/{session-catalog-index-state-BAuDztHN.mjs → session-catalog-index-state-TeO7EyO-.mjs} +6 -2
  92. package/dist/.setup/session-catalog-limits-DDxOsQeC.mjs +14 -0
  93. package/dist/.setup/session-catalog-list-request-CvtxrYSe.mjs +170 -0
  94. package/dist/.setup/session-catalog-native-projection-DjhwGL6x.mjs +178 -0
  95. package/dist/.setup/{session-catalog-node-adoption-BVRsYOSh.mjs → session-catalog-node-adoption-DgXvSGu0.mjs} +30 -35
  96. package/dist/.setup/{session-catalog-node-continue-Dowv8osw.mjs → session-catalog-node-continue-DjKXHBbi.mjs} +25 -18
  97. package/dist/.setup/session-catalog-node-lookup-CtAXI5W5.mjs +56 -0
  98. package/dist/.setup/{session-catalog-native-projection-ChV3cCtm.mjs → session-catalog-parsing-CPGaPYr-.mjs} +14 -180
  99. package/dist/.setup/{session-catalog-projection-C1Bj9Jl-.mjs → session-catalog-projection-Cr5qP5Dj.mjs} +15 -5
  100. package/dist/.setup/session-catalog-provenance-DoAvktcj.mjs +95 -0
  101. package/dist/.setup/{session-cli-DIj-IE-E.mjs → session-cli-Cn_nCqfq.mjs} +11 -24
  102. package/dist/.setup/{session-history-C--SrLI8.mjs → session-history-D83lJWHG.mjs} +16 -23
  103. package/dist/.setup/{session-history-import-JHXT5Xfi.mjs → session-history-import-WhX-X33a.mjs} +7 -10
  104. package/dist/.setup/session-history-read-Ov3StuL4.mjs +133 -0
  105. package/dist/.setup/{session-history.worker-CpNj7H_P.mjs → session-history.worker-MnPKncqP.mjs} +14 -23
  106. package/dist/.setup/session-initialization-6aveB9qb.mjs +22 -0
  107. package/dist/.setup/{session-permission-policy-DhurXY0l.mjs → session-permission-policy-Ci_fVX6y.mjs} +4 -8
  108. package/dist/.setup/{session-retirement-CU87AOg9.mjs → session-retirement-qMTxkNx2.mjs} +31 -12
  109. package/dist/.setup/{settled-turn-context-fmwouT5I.mjs → settled-turn-context-D4yj4rxf.mjs} +1 -1
  110. package/dist/.setup/{settled-turn-finalizer-CiY2bLFK.mjs → settled-turn-finalizer-BsvEabkw.mjs} +17 -13
  111. package/dist/.setup/{shared-client-BpTtuLQ5.mjs → shared-client-DqyTMYug.mjs} +826 -485
  112. package/dist/.setup/shared-client-lifecycle-DJIgqgMw.mjs +153 -0
  113. package/dist/.setup/{side-question-DSCZyoBD.mjs → side-question-C4kCmQy1.mjs} +206 -334
  114. package/dist/.setup/{source-Bjp4UQij.mjs → source-CS_7GFJZ.mjs} +82 -139
  115. package/dist/.setup/spawn-error-CL3n6MAa.mjs +57 -0
  116. package/dist/.setup/{thread-archive-guard-jmecf6OJ.mjs → thread-archive-guard-C9frICzX.mjs} +10 -3
  117. package/dist/.setup/thread-lifecycle-DPflntEJ.mjs +2362 -0
  118. package/dist/.setup/{incognito-session-uhrBF6wJ.mjs → thread-ownership-queue-Dp24d7-F.mjs} +1 -2
  119. package/dist/.setup/{thread-ownership-skomxnIt.mjs → thread-ownership-roNP0l1c.mjs} +47 -10
  120. package/dist/.setup/thread-policy-DTd-DtkX.mjs +109 -0
  121. package/dist/.setup/thread-requests-B_bRnMGN.mjs +2102 -0
  122. package/dist/.setup/{thread-resume-BkNpj9Pz.mjs → thread-resume-CdDaoc7T.mjs} +6 -6
  123. package/dist/.setup/timeout-CXOfNoaX.mjs +46 -0
  124. package/dist/.setup/transcript-history-projection-DRSifI-1.mjs +201 -0
  125. package/dist/.setup/{transcript-mirror-attestation-CzM-94NC.mjs → transcript-mirror-attestation-YSegaktH.mjs} +3 -4
  126. package/dist/.setup/{transcript-mirror-D4qp_leP.mjs → transcript-mirror-kxmCYsuF.mjs} +224 -206
  127. package/dist/.setup/{transport-stdio-Cmx94Oiy.mjs → transport-stdio-Bdegpn2V.mjs} +138 -75
  128. package/dist/.setup/transport-websocket-BTBE-LD9.mjs +211 -0
  129. package/dist/.setup/{upstream-prompt-provenance-LphB8slG.mjs → upstream-prompt-provenance-fXkKbPVC.mjs} +3 -9
  130. package/dist/.setup/{upstream-session-fork-D3UKxgVD.mjs → upstream-session-fork-CBeVjBpT.mjs} +48 -40
  131. package/dist/.setup/{usage-BOgBEKso.mjs → usage-BMzNxeR_.mjs} +5 -4
  132. package/dist/.setup/{usage-limit-error-C0ow7DOc.mjs → usage-limit-error-QXerDo3i.mjs} +5 -20
  133. package/dist/.setup/{web-search-provider.runtime-CTGuJt6i.mjs → web-search-provider.runtime-P77OUeoo.mjs} +10 -20
  134. package/dist/api.js +25 -16
  135. package/dist/catalog-page-worker-entrypoint.js +12 -0
  136. package/dist/catalog-page.worker.js +9 -0
  137. package/dist/cli-metadata.js +1 -1
  138. package/dist/doctor-contract-api.js +50 -8
  139. package/dist/harness.js +344 -1
  140. package/dist/index.js +345 -346
  141. package/dist/media-understanding-provider.js +9 -22
  142. package/dist/migration-provider-api.js +1 -1
  143. package/dist/provider-discovery.js +1 -1
  144. package/dist/session-history-worker-runtime.js +16 -33
  145. package/dist/session-history.worker.js +1 -1
  146. package/openclaw.plugin.json +14 -2
  147. package/package.json +11 -7
  148. package/dist/.setup/attempt-context-VXVwTCfS.mjs +0 -636
  149. package/dist/.setup/compact-C3i3qlzj.mjs +0 -687
  150. package/dist/.setup/event-projector-assistant-message-DNUR1s0A.mjs +0 -105
  151. package/dist/.setup/event-projector-items-DyTQ_XqL.mjs +0 -200
  152. package/dist/.setup/harness-rxaaoN-o.mjs +0 -349
  153. package/dist/.setup/history-rejection-B4nOXNXF.mjs +0 -13
  154. package/dist/.setup/image-payload-sanitizer-tupAr-2o.mjs +0 -79
  155. package/dist/.setup/inference-proxy-CC15HuSi.mjs +0 -311
  156. package/dist/.setup/launch-args-DnMak49W.mjs +0 -111
  157. package/dist/.setup/local-runtime-attribution-B_2mnqhb.mjs +0 -19
  158. package/dist/.setup/native-subagent-history-YXaL6dMd.mjs +0 -135
  159. package/dist/.setup/native-subagent-task-ids-DsuOonKv.mjs +0 -411
  160. package/dist/.setup/node-exec-server.runtime-BaViBKNz.mjs +0 -226
  161. package/dist/.setup/plugin-approval-roundtrip-CjfzafAZ.mjs +0 -122
  162. package/dist/.setup/provider-fFh_-VR3.mjs +0 -50
  163. package/dist/.setup/rolldown-runtime-8H4AJuhK.mjs +0 -14
  164. package/dist/.setup/sandbox-guard-BBP-RbTf.mjs +0 -166
  165. package/dist/.setup/session-binding-_0W_fHRr.mjs +0 -721
  166. package/dist/.setup/session-catalog-events-jMcYfQyd.mjs +0 -250
  167. package/dist/.setup/session-history-read-B3ZfSUbF.mjs +0 -50
  168. package/dist/.setup/session-initialization-DH1z6fXn.mjs +0 -75
  169. package/dist/.setup/thread-history-page-BTx-4xsg.mjs +0 -83
  170. package/dist/.setup/thread-lifecycle-Cik28qWn.mjs +0 -4904
  171. package/dist/.setup/thread-policy-Cjs4B8xf.mjs +0 -54
  172. package/dist/.setup/timeout-DZF05XrR.mjs +0 -63
  173. package/dist/.setup/transcript-history-projection-DHNBDhCU.mjs +0 -243
  174. package/dist/.setup/version-CoqzXPgK.mjs +0 -12
@@ -1,38 +1,43 @@
1
- import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.mjs";
2
- import { n as defineCodexBuildState, t as codexBuildSymbol } from "./build-state-Xx9ybZqa.mjs";
1
+ import { i as isJsonObject } from "./protocol-CANUwXJ3.mjs";
2
+ import { n as defineCodexBuildState, t as codexBuildSymbol } from "./build-state-Da1_z0kd.mjs";
3
3
  import { t as CODEX_APP_SERVER_AUTH_PROVIDER } from "./auth-profile-selection-DFu9e167.mjs";
4
- import { _ as resolveCodexAppServerUserHomeDir, g as resolveCodexAppServerLocalHomeDir, h as resolveCodexAppServerHomeDir, m as isJsonObject, v as withEphemeralCodexAuthStore } from "./config-security-BRQ2mgW9.mjs";
5
- import { n as isCodexAppServerProxyLaunch } from "./launch-args-DnMak49W.mjs";
6
- import { f as isUnsupportedCodexAppServerVersionError, t as CodexAppServerClient } from "./client-vXs2929Q.mjs";
7
- import { a as resolveCodexAppServerStartOptionsForAgent, d as readCodexEffectiveConfig, o as resolveCodexComputerUseConfig, t as codexAppServerStartOptionsKey, u as CODEX_SESSION_OVERRIDABLE_LAYER_TYPES } from "./config-options-BsanJ8QG.mjs";
8
- import { c as resolveMacOSDesktopCodexAppPathCandidates, i as resolveManagedCodexNativeCommand, l as resolveMacOSDesktopCodexBundledMarketplaceCandidates, r as resolveManagedCodexAppServerStartOptions, s as resolveFirstExistingMacOSDesktopCodexBundledMarketplacePath, t as isManagedCodexDesktopCommand, u as resolveMacOSDesktopCodexComputerUseServiceAppCandidates } from "./managed-binary-DP6Rib3P.mjs";
9
- import { _ as isCodexDesktopGenerationCurrent, a as readCodexCliAuthFileApiKey, c as resolveCodexAppServerPreparedApiKeyCacheKey, d as createCodexAppServerStartupLifetime, f as getCurrentSharedClientEntry, i as fingerprintTokenAuthProfileCacheKey, l as closeRetiredSharedClientEntry, m as retireSharedCodexAppServerClientIfCurrent, n as CODEX_AUTH_JSON_FILENAME, o as readFirstNonEmptyEnv, p as getSharedCodexAppServerClientState, r as fingerprintApiKeyAuthProfileCacheKey, s as resolveCodexAppServerFallbackApiKeyCacheKey, t as CODEX_APP_SERVER_API_KEY_ENV_VARS, u as closeRetiredSharedClientEntryIfIdle, v as waitForCodexDesktopGeneration } from "./auth-cache-key-QirmgiCo.mjs";
10
- import { n as resolveCodexAppServerSpawnEnv } from "./transport-stdio-Cmx94Oiy.mjs";
11
- import { n as withTimeout } from "./timeout-DZF05XrR.mjs";
12
- import { c as readCodexSessionMeta, n as observeCodexCatalogClient } from "./session-catalog-events-jMcYfQyd.mjs";
13
- import { n as resolveCodexAppServerRuntimeOptions } from "./config-runtime-CeAhl_h4.mjs";
14
- import { a as resolveCodexAppServerAuthProfileStore, i as resolveCodexAppServerAuthProfileIdForAgent, r as resolveCodexAppServerAuthProfileId, t as isCodexAppServerNativeAuthProfile } from "./auth-profile-WqZtZfXN.mjs";
4
+ import { n as isCodexAppServerProxyLaunch } from "./launch-args-DbFCehO7.mjs";
5
+ import { a as withEphemeralCodexAuthStore, i as withClearedEnvironmentVariables, n as resolveCodexAppServerLocalHomeDir, r as resolveCodexAppServerUserHomeDir, t as resolveCodexAppServerHomeDir } from "./auth-start-options-BPIPeEX8.mjs";
6
+ import { a as resolveCodexAppServerStartOptionsForAgent, d as readCodexEffectiveConfig, o as resolveCodexComputerUseConfig, t as codexAppServerStartOptionsKey, u as CODEX_SESSION_OVERRIDABLE_LAYER_TYPES } from "./config-options-CzyWLTJt.mjs";
7
+ import { d as resolveMacOSDesktopCodexBundledMarketplaceCandidates, f as resolveMacOSDesktopCodexComputerUseServiceAppCandidates, i as resolveManagedCodexNativeCommand, l as resolveFirstExistingMacOSDesktopCodexBundledMarketplacePath, r as resolveManagedCodexAppServerStartOptions, t as isManagedCodexDesktopCommand, u as resolveMacOSDesktopCodexAppPathCandidates } from "./managed-binary-kiWRhNRE.mjs";
8
+ import { a as readCodexCliAuthFileApiKey, c as resolveCodexAppServerPreparedApiKeyCacheKey, d as waitForCodexDesktopGeneration, f as readCodexDesktopArtifactTreeFingerprint, i as fingerprintTokenAuthProfileCacheKey, n as CODEX_AUTH_JSON_FILENAME, o as readFirstNonEmptyEnv, r as fingerprintApiKeyAuthProfileCacheKey, s as resolveCodexAppServerFallbackApiKeyCacheKey, t as CODEX_APP_SERVER_API_KEY_ENV_VARS, u as isCodexDesktopGenerationCurrent } from "./auth-cache-key-Dbvq-QgB.mjs";
9
+ import { a as notifyDesktopGenerationDrainChecks, c as retainSharedClientEntry, d as retireSharedCodexAppServerClientIfCurrent, m as waitForUnclaimedSharedClientStartup, n as getCurrentSharedClientEntry, o as ownCodexStartup, r as getSharedCodexAppServerClientState, s as releaseSharedClientEntry, t as createCodexAppServerStartupLifetime, u as retirePendingSharedClientEntryIfUnclaimed } from "./shared-client-lifecycle-DJIgqgMw.mjs";
10
+ import { n as resolveCodexAppServerSpawnEnv } from "./transport-stdio-Bdegpn2V.mjs";
11
+ import { n as CodexAppServerAuthProfileUnavailableError, r as formatCodexAuthProfileUnavailableMessage } from "./auth-profile-recovery-BREezV0L.mjs";
12
+ import { i as withTimeout } from "./timeout-CXOfNoaX.mjs";
13
+ import { n as readCodexSessionMeta } from "./session-catalog-provenance-DoAvktcj.mjs";
14
+ import { n as observeCodexCatalogClient } from "./session-catalog-events-DePDzzjc.mjs";
15
+ import { n as resolveCodexAppServerRuntimeOptions } from "./config-runtime-C0NbLms1.mjs";
16
+ import { a as resolveCodexAppServerAuthProfileStore, i as resolveCodexAppServerAuthProfileIdForAgent, r as resolveCodexAppServerAuthProfileId, t as isCodexAppServerNativeAuthProfile } from "./auth-profile-B0okYl2D.mjs";
17
+ import { i as isCodexResponsesOAuthCredential, n as createCodexResponsesOAuth, o as resolveCodexResponsesOAuthProfileFingerprint, r as isCodexResponsesOAuth, t as CODEX_RESPONSES_OAUTH_PROVIDER } from "./responses-oauth-twnuTaAa.mjs";
18
+ import { f as isUnsupportedCodexAppServerVersionError, t as CodexAppServerClient } from "./client-N0JpgSzF.mjs";
19
+ import { n as isCodexWebSocketOpenFailure } from "./transport-websocket-BTBE-LD9.mjs";
20
+ import { t as __exportAll } from "./session-binding-sidecars-jo6H8dFr.mjs";
15
21
  import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
16
- import { createHash } from "node:crypto";
22
+ import { createHash, randomUUID } from "node:crypto";
17
23
  import { isDeepStrictEqual } from "node:util";
18
24
  import { AgentHarnessPreflightError, resolveDefaultAgentDir } from "openclaw/plugin-sdk/agent-harness-registration";
19
- import { addTimerTimeoutGraceMs, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
20
25
  import { runExec } from "openclaw/plugin-sdk/process-runtime";
21
- import fs, { constants } from "node:fs";
26
+ import { addTimerTimeoutGraceMs, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
27
+ import fs, { constants, existsSync } from "node:fs";
22
28
  import path from "node:path";
23
29
  import fs$1 from "node:fs/promises";
30
+ import { extractErrorCode } from "openclaw/plugin-sdk/error-runtime";
31
+ import { resolveGlobalMap } from "openclaw/plugin-sdk/global-singleton";
24
32
  import { createDeferred } from "openclaw/plugin-sdk/extension-shared";
25
33
  import { ensureAuthProfileStore, findPersistedAuthProfileCredential, refreshOAuthCredentialForRuntime, resolveApiKeyForProfile, resolvePersistedAuthProfileOwnerAgentDir } from "openclaw/plugin-sdk/agent-runtime";
26
- import { AgentHarnessPreflightError as AgentHarnessPreflightError$1, embeddedAgentLog as embeddedAgentLog$1, formatErrorMessage } from "openclaw/plugin-sdk/agent-harness-runtime";
34
+ import { AgentHarnessPreflightError as AgentHarnessPreflightError$1, embeddedAgentLog as embeddedAgentLog$1, formatErrorMessage as formatErrorMessage$1 } from "openclaw/plugin-sdk/agent-harness-runtime";
27
35
  import { hasUsableOAuthCredential, resolveOpenAICodexAuthIdentity } from "openclaw/plugin-sdk/provider-auth";
28
36
  import { pruneMapToMaxSize } from "openclaw/plugin-sdk/collection-runtime";
29
- import { assertNoSymlinkParents } from "openclaw/plugin-sdk/security-runtime";
37
+ import { assertDirectoryIdentitySync, readDirectoryIdentity } from "@openclaw/fs-safe/advanced";
38
+ import { assertNoSymlinkParents, pathScope } from "openclaw/plugin-sdk/security-runtime";
39
+ import { sleepWithAbort } from "openclaw/plugin-sdk/runtime-env";
30
40
  //#region extensions/codex/src/app-server/attempt-timeouts.ts
31
- /**
32
- * Timeout defaults and normalizers for Codex app-server startup and turn
33
- * liveness watches.
34
- */
35
- /** Minimum startup timeout accepted by the Codex app-server harness. */
36
41
  const CODEX_APP_SERVER_STARTUP_TIMEOUT_FLOOR_MS = 100;
37
42
  const TURN_TERMINAL_SETTLEMENT_TIMEOUT_MS = 12e4;
38
43
  const TURN_FINALIZE_DRAIN_ABORT_GRACE_MS = 5e3;
@@ -51,7 +56,6 @@ function resolvePositiveIntegerTimeoutMs(value, fallbackMs) {
51
56
  const fallback = resolveTimerTimeoutMs(fallbackMs, 1);
52
57
  return resolveTimerTimeoutMs(value, fallback);
53
58
  }
54
- /** Runs startup work with abort and timeout handling plus optional cleanup. */
55
59
  async function withCodexStartupTimeout(params) {
56
60
  if (params.signal.aborted) throw new CodexAppServerStartupError("aborted");
57
61
  let timeout;
@@ -89,13 +93,11 @@ async function withCodexStartupTimeout(params) {
89
93
  abortCleanup?.();
90
94
  }
91
95
  }
92
- /** Resolves startup timeout while honoring the configured floor. */
93
96
  function resolveCodexStartupTimeoutMs(params) {
94
97
  const timeoutFloorMs = resolvePositiveIntegerTimeoutMs(params.timeoutFloorMs, CODEX_APP_SERVER_STARTUP_TIMEOUT_FLOOR_MS);
95
98
  const timeoutMs = resolvePositiveIntegerTimeoutMs(params.timeoutMs, timeoutFloorMs);
96
99
  return Math.max(timeoutFloorMs, timeoutMs);
97
100
  }
98
- /** Adds gateway grace time to a caller timeout without overflowing invalid values. */
99
101
  function resolveCodexGatewayTimeoutWithGraceMs(timeoutMs, graceMs = 1e4) {
100
102
  const timeout = resolvePositiveIntegerTimeoutMs(timeoutMs, 1);
101
103
  const grace = resolveTimerTimeoutMs(graceMs, 0, 0);
@@ -166,17 +168,16 @@ async function assertOwnedCodexHomePath(params) {
166
168
  }
167
169
  async function readRealDirectoryIdentity(directoryPath, label) {
168
170
  const logicalPath = path.resolve(directoryPath);
169
- const before = await fs$1.lstat(logicalPath);
170
- if (before.isSymbolicLink() || !before.isDirectory()) throw new Error(`${label} must be a real directory: ${logicalPath}`);
171
- const realPath = await fs$1.realpath(logicalPath);
172
- const [after, resolved] = await Promise.all([fs$1.lstat(logicalPath), fs$1.lstat(realPath)]);
173
- if (after.isSymbolicLink() || !after.isDirectory() || !resolved.isDirectory() || before.dev !== after.dev || before.ino !== after.ino || after.dev !== resolved.dev || after.ino !== resolved.ino) throw new Error(`${label} changed while its ownership boundary was being established.`);
174
- return {
175
- logicalPath,
176
- realPath,
177
- dev: after.dev,
178
- ino: after.ino
179
- };
171
+ try {
172
+ const identity = await readDirectoryIdentity(logicalPath);
173
+ assertDirectoryIdentitySync(logicalPath, identity);
174
+ return {
175
+ logicalPath,
176
+ ...identity
177
+ };
178
+ } catch (cause) {
179
+ throw new Error(`${label} must remain a real directory: ${logicalPath}`, { cause });
180
+ }
180
181
  }
181
182
  async function assertOwnedServiceParentStable(parent) {
182
183
  await assertDirectoryIdentityStable(parent, "Computer Use service parent");
@@ -184,14 +185,10 @@ async function assertOwnedServiceParentStable(parent) {
184
185
  async function assertDirectoryIdentityStable(expected, label) {
185
186
  if (!await directoryIdentityIsStable(expected)) throw new Error(`${label} changed during refresh; refusing to mutate the replacement path.`);
186
187
  }
187
- async function ownedServiceParentIsStable(parent) {
188
- return await directoryIdentityIsStable(parent);
189
- }
190
188
  async function directoryIdentityIsStable(expected) {
191
189
  try {
192
- const current = await fs$1.lstat(expected.logicalPath);
193
- if (current.isSymbolicLink() || !current.isDirectory() || current.dev !== expected.dev || current.ino !== expected.ino) return false;
194
- return await fs$1.realpath(expected.logicalPath) === expected.realPath;
190
+ assertDirectoryIdentitySync(expected.logicalPath, expected);
191
+ return true;
195
192
  } catch {
196
193
  return false;
197
194
  }
@@ -200,7 +197,7 @@ async function assertNotSymlink(filePath, label) {
200
197
  try {
201
198
  if ((await fs$1.lstat(filePath)).isSymbolicLink()) throw new Error(`${label} must not be a symbolic link: ${filePath}`);
202
199
  } catch (error) {
203
- if (hasNodeErrorCode$1(error, "ENOENT")) return;
200
+ if (extractErrorCode(error) === "ENOENT") return;
204
201
  throw error;
205
202
  }
206
203
  }
@@ -208,84 +205,43 @@ async function ensureRealDirectoryTree(ownershipRoot, directoryPath, label) {
208
205
  const root = path.resolve(ownershipRoot);
209
206
  const target = path.resolve(directoryPath);
210
207
  assertPathAtOrInside(root, target, label);
211
- const relative = path.relative(root, target);
212
- let current = root;
213
- for (const segment of relative.split(path.sep).filter(Boolean)) {
214
- current = path.join(current, segment);
215
- const existing = await fs$1.lstat(current).catch((error) => {
216
- if (hasNodeErrorCode$1(error, "ENOENT")) return;
217
- throw error;
218
- });
219
- if (!existing) {
220
- try {
221
- await fs$1.mkdir(current, { mode: 448 });
222
- } catch (error) {
223
- if (!hasNodeErrorCode$1(error, "EEXIST")) throw error;
224
- }
225
- const created = await fs$1.lstat(current);
226
- if (created.isSymbolicLink() || !created.isDirectory()) throw new Error(`${label} changed while its directory tree was being created: ${current}`);
227
- } else if (existing.isSymbolicLink() || !existing.isDirectory()) throw new Error(`${label} must traverse real directories: ${current}`);
208
+ if (root !== target) {
209
+ const prepared = await pathScope(root, { label }).ensureDir(`${target}${path.sep}`, { mode: 448 });
210
+ if (!prepared.ok) throw new Error(`${label} must traverse real directories: ${prepared.error}`, { cause: prepared.diagnostic });
228
211
  }
229
- await assertNoSymlinkParents({
230
- rootDir: root,
231
- targetPath: target,
232
- allowMissing: false,
233
- requireDirectories: true,
234
- messagePrefix: "Computer Use service path"
235
- });
236
212
  await readRealDirectoryIdentity(target, label);
237
213
  }
238
214
  function assertPathAtOrInside(rootPath, candidatePath, label) {
239
215
  const relative = path.relative(path.resolve(rootPath), path.resolve(candidatePath));
240
216
  if (relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) throw new Error(`${label} must remain inside ${path.resolve(rootPath)}.`);
241
217
  }
242
- function hasNodeErrorCode$1(error, code) {
243
- return Boolean(error && typeof error === "object" && "code" in error && error.code === code);
244
- }
245
218
  //#endregion
246
219
  //#region extensions/codex/src/app-server/computer-use-cache.ts
247
220
  /** Shared Computer Use plugin cache reconciliation for isolated Codex homes. */
248
221
  const DEFAULT_CODEX_COMPUTER_USE_BUNDLED_MARKETPLACE_PATH = resolveMacOSDesktopCodexBundledMarketplaceCandidates("darwin")[0] ?? "";
249
222
  const DEFAULT_BUNDLED_MARKETPLACE_NAME = "openai-bundled";
250
223
  async function ensureCodexComputerUseSharedPluginCache(params) {
251
- if (!params.config.enabled) return skippedCacheResult("disabled", "Computer Use cache sharing skipped because it is disabled.");
252
- if (params.config.pluginCacheMode === "independent") return skippedCacheResult("independent", "Computer Use cache sharing skipped because pluginCacheMode is independent.");
253
- if (params.config.marketplaceName || params.config.marketplacePath) return skippedCacheResult("explicit_marketplace", "Computer Use cache sharing skipped because an explicit marketplace is configured.");
224
+ if (!params.config.enabled || params.config.pluginCacheMode === "independent" || params.config.marketplaceName || params.config.marketplacePath) return false;
254
225
  const bundledMarketplacePath = resolveComputerUseBundledMarketplacePath(params);
255
226
  const sourcePluginRoot = path.join(bundledMarketplacePath, "plugins", params.config.pluginName);
256
227
  const version = await readBundledPluginVersion(sourcePluginRoot);
257
- if (!version) return skippedCacheResult("source_missing", `Computer Use bundled plugin source was not found at ${sourcePluginRoot}.`);
258
- const marketplaceName = params.config.marketplaceName ?? DEFAULT_BUNDLED_MARKETPLACE_NAME;
259
- const cacheRoot = path.join(params.codexHome, "plugins", "cache", marketplaceName, params.config.pluginName);
260
- const cachePath = path.join(cacheRoot, version);
261
- return {
262
- status: "shared",
263
- changed: await ensureRealDirectoryCopy(cachePath, sourcePluginRoot, version, {
264
- codexHome: params.codexHome,
265
- ownershipRoot: params.ownershipRoot,
266
- assertCurrent: params.assertCurrent,
267
- forceRefresh: params.forceRefresh
268
- }),
269
- cachePath,
270
- targetPath: sourcePluginRoot,
271
- version,
272
- removedStaleVersions: [],
273
- warnings: [],
274
- message: `Computer Use plugin cache ${cachePath} contains bundled plugin ${sourcePluginRoot}.`
275
- };
228
+ if (!version) return false;
229
+ const cacheRoot = path.join(params.codexHome, "plugins", "cache", params.config.marketplaceName ?? DEFAULT_BUNDLED_MARKETPLACE_NAME, params.config.pluginName);
230
+ await ensureRealDirectoryCopy(path.join(cacheRoot, version), sourcePluginRoot, version, {
231
+ codexHome: params.codexHome,
232
+ ownershipRoot: params.ownershipRoot,
233
+ assertCurrent: params.assertCurrent,
234
+ forceRefresh: params.forceRefresh
235
+ });
236
+ return true;
276
237
  }
277
238
  function resolveComputerUseBundledMarketplacePath(params) {
278
239
  return params.bundledMarketplacePath ?? resolveFirstExistingMacOSDesktopCodexBundledMarketplacePath({ candidates: params.bundledMarketplacePathCandidates }) ?? params.bundledMarketplacePathCandidates?.[0] ?? DEFAULT_CODEX_COMPUTER_USE_BUNDLED_MARKETPLACE_PATH;
279
240
  }
280
241
  async function readBundledPluginVersion(sourcePluginRoot) {
281
242
  const pluginJsonPath = path.join(sourcePluginRoot, ".codex-plugin", "plugin.json");
282
- let raw;
283
- try {
284
- raw = await fs$1.readFile(pluginJsonPath, "utf8");
285
- } catch {
286
- return;
287
- }
288
243
  try {
244
+ const raw = await fs$1.readFile(pluginJsonPath, "utf8");
289
245
  const parsed = JSON.parse(raw);
290
246
  return typeof parsed.version === "string" && parsed.version.trim() ? parsed.version.trim() : void 0;
291
247
  } catch {
@@ -303,7 +259,13 @@ async function ensureRealDirectoryCopy(cachePath, sourcePluginRoot, version, bou
303
259
  const physicalCachePath = ownedParent ? path.join(ownedParent.realPath, path.basename(cachePath)) : cachePath;
304
260
  const stat = await fs$1.lstat(physicalCachePath).catch(() => void 0);
305
261
  if (stat?.isDirectory() && !stat.isSymbolicLink()) {
306
- if (await readBundledPluginVersion(physicalCachePath) === version && !boundary.forceRefresh) return false;
262
+ if (await readBundledPluginVersion(physicalCachePath) === version && !boundary.forceRefresh) {
263
+ const [cachedMcp, sourceMcp] = await Promise.all([physicalCachePath, sourcePluginRoot].map(async (root) => fs$1.readFile(path.join(root, ".mcp.json"), "utf8").catch((error) => {
264
+ if (extractErrorCode(error) === "ENOENT") return;
265
+ throw error;
266
+ })));
267
+ if (cachedMcp === sourceMcp) return;
268
+ }
307
269
  }
308
270
  const cacheName = path.basename(cachePath);
309
271
  const physicalCacheRoot = path.dirname(physicalCachePath);
@@ -312,7 +274,8 @@ async function ensureRealDirectoryCopy(cachePath, sourcePluginRoot, version, bou
312
274
  const backupPath = path.join(physicalCacheRoot, `.${cacheName}.backup-${process.pid}-${Date.now()}`);
313
275
  let backupCreated = false;
314
276
  try {
315
- await fs$1.cp(sourcePluginRoot, stagedPath, { recursive: true });
277
+ const physicalSourceRoot = await fs$1.realpath(sourcePluginRoot);
278
+ await fs$1.cp(physicalSourceRoot, stagedPath, { recursive: true });
316
279
  await waitForCodexDesktopGeneration();
317
280
  if (ownedParent) await assertDirectoryIdentityStable(ownedParent, "Computer Use plugin cache parent");
318
281
  if (stat) {
@@ -341,7 +304,6 @@ async function ensureRealDirectoryCopy(cachePath, sourcePluginRoot, version, bou
341
304
  force: true
342
305
  });
343
306
  }
344
- return true;
345
307
  } finally {
346
308
  if (!ownedParent || await directoryIdentityIsStable(ownedParent)) await fs$1.rm(stagingRoot, {
347
309
  recursive: true,
@@ -349,19 +311,148 @@ async function ensureRealDirectoryCopy(cachePath, sourcePluginRoot, version, bou
349
311
  });
350
312
  }
351
313
  }
352
- function skippedCacheResult(status, message) {
314
+ //#endregion
315
+ //#region extensions/codex/src/app-server/computer-use-unified.ts
316
+ /** Materializes the desktop-owned unified MCP template for an isolated Computer Use home. */
317
+ const UNIFIED_COMPUTER_USE_PLUGIN = "unified-computer-use";
318
+ const UNIFIED_SERVER = "cua_repl";
319
+ const CUA_REPL_ENTRY = "@oai/cua/tinyskyAlt";
320
+ /** The selected desktop distribution owns both the plugin and its executable dependencies. */
321
+ async function resolveCodexUnifiedComputerUseRuntime(candidate, codexHome, requestedPluginName, requestedServerName) {
322
+ const pluginName = requestedPluginName ?? "computer-use";
323
+ const serverName = requestedServerName ?? pluginName;
324
+ if (!(pluginName === "computer-use" && serverName === "computer-use") && !(pluginName === "unified-computer-use" && serverName === UNIFIED_SERVER)) return;
325
+ if ((await readObject(path.join(candidate.bundledMarketplacePath, "plugins", "computer-use", ".codex-plugin", "plugin.json")))?.mcpServers && requestedPluginName !== "unified-computer-use") return;
326
+ const pluginRoot = path.join(candidate.bundledMarketplacePath, "plugins", UNIFIED_COMPUTER_USE_PLUGIN);
327
+ const manifest = await readObject(path.join(pluginRoot, ".codex-plugin", "plugin.json"));
328
+ if (!manifest || manifest.name !== "unified-computer-use" || manifest.mcpServers !== "./.mcp.json") return;
329
+ const template = await readObject(path.join(pluginRoot, ".mcp.json"));
330
+ const servers = template?.mcpServers;
331
+ const server = isRecord(servers) ? servers[UNIFIED_SERVER] : void 0;
332
+ if (!template || !isRecord(servers) || !isRecord(server)) throw new Error("The selected desktop's unified Computer Use MCP template is invalid.");
333
+ const runtimeRoot = path.join(candidate.appBundlePath, "Contents", "Resources", "cua_node");
334
+ const modules = path.join(runtimeRoot, "lib", "node_modules");
335
+ const node = path.join(runtimeRoot, "bin", "node");
336
+ const nodeRepl = path.join(runtimeRoot, "bin", "node_repl");
337
+ const launcher = path.join(modules, "@oai", "cua-repl", "bin", "cua-repl.mjs");
338
+ const cuaRoot = path.join(modules, "@oai", "cua");
339
+ const cuaPackage = await readObject(path.join(cuaRoot, "package.json"));
340
+ const cuaEntry = isRecord(cuaPackage?.exports) ? cuaPackage.exports["./tinyskyAlt"] : void 0;
341
+ try {
342
+ if (typeof cuaEntry !== "string" || !cuaEntry.startsWith("./") || path.relative(cuaRoot, path.resolve(cuaRoot, cuaEntry)).startsWith("..")) throw new Error("The desktop CUA package does not expose its unified entry point.");
343
+ await Promise.all([
344
+ fs$1.access(node, constants.X_OK),
345
+ fs$1.access(nodeRepl, constants.X_OK),
346
+ fs$1.access(launcher, constants.R_OK),
347
+ fs$1.access(path.join(modules, "@oai", "sky", "package.json"), constants.R_OK),
348
+ fs$1.access(path.resolve(cuaRoot, cuaEntry), constants.R_OK)
349
+ ]);
350
+ } catch (cause) {
351
+ throw new Error("The selected desktop's unified Computer Use runtime is incomplete.", { cause });
352
+ }
353
353
  return {
354
- status,
355
- changed: false,
356
- message,
357
- removedStaleVersions: [],
358
- warnings: status === "source_missing" ? [message] : []
354
+ pluginRoot,
355
+ sourceFingerprint: await readCodexDesktopArtifactTreeFingerprint(pluginRoot),
356
+ manifest,
357
+ mcp: {
358
+ ...template,
359
+ mcpServers: {
360
+ ...servers,
361
+ [UNIFIED_SERVER]: {
362
+ ...server,
363
+ command: node,
364
+ args: [launcher],
365
+ enabled: true,
366
+ env_vars: [],
367
+ env: {
368
+ CODEX_HOME: codexHome,
369
+ CUA_REPL_NODE_REPL_PATH: nodeRepl,
370
+ CUA_REPL_ENABLED_SURFACES: "computer",
371
+ NODE_REPL_NODE_PATH: node,
372
+ NODE_REPL_NODE_MODULE_DIRS: modules,
373
+ NODE_REPL_TRUSTED_CODE_PATHS: [codexHome, modules].join(path.delimiter),
374
+ NODE_REPL_TRUSTED_SERVICES: JSON.stringify({ sky: "@oai/sky/service" }),
375
+ NODE_REPL_JS_BANNER: `await import(${JSON.stringify(CUA_REPL_ENTRY)});`,
376
+ SKY_CUA_SERVICE_PATH: path.join(codexHome, "computer-use", "Codex Computer Use.app")
377
+ }
378
+ }
379
+ }
380
+ }
381
+ };
382
+ }
383
+ async function publishCodexUnifiedComputerUsePlugin(target, runtime) {
384
+ const templatePath = path.join(runtime.pluginRoot, ".mcp.json");
385
+ await fs$1.cp(runtime.pluginRoot, target, {
386
+ recursive: true,
387
+ filter: (source) => source !== templatePath
388
+ });
389
+ await fs$1.writeFile(path.join(target, ".mcp.json"), `${JSON.stringify(runtime.mcp, null, 2)}\n`, { mode: 384 });
390
+ }
391
+ async function codexUnifiedComputerUsePluginMatches(target, runtime) {
392
+ return isDeepStrictEqual(await readObject(path.join(target, ".codex-plugin", "plugin.json")), runtime.manifest) && isDeepStrictEqual(await readObject(path.join(target, ".mcp.json")), runtime.mcp);
393
+ }
394
+ /** Preserve custom identities and legacy desktops; the legacy default follows its replacement. */
395
+ async function resolveManagedCodexComputerUseConfig(config, marketplacePath) {
396
+ if (!marketplacePath || config.marketplaceSource || config.marketplaceName || config.marketplacePath || config.pluginName !== "computer-use" || config.mcpServerName !== "computer-use") return config;
397
+ const plugins = path.join(marketplacePath, "plugins");
398
+ const legacy = await readObject(path.join(plugins, "computer-use", ".codex-plugin", "plugin.json"));
399
+ if (!legacy || legacy.mcpServers) return config;
400
+ const unified = await readObject(path.join(plugins, UNIFIED_COMPUTER_USE_PLUGIN, ".codex-plugin", "plugin.json"));
401
+ const mcp = await readObject(path.join(plugins, UNIFIED_COMPUTER_USE_PLUGIN, ".mcp.json"));
402
+ const server = isRecord(mcp?.mcpServers) ? mcp.mcpServers[UNIFIED_SERVER] : void 0;
403
+ if (unified?.name !== "unified-computer-use" || !isRecord(server) || server.enabled !== true) return config;
404
+ return {
405
+ ...config,
406
+ pluginName: UNIFIED_COMPUTER_USE_PLUGIN,
407
+ mcpServerName: UNIFIED_SERVER
359
408
  };
360
409
  }
410
+ /** A native plugin disable veto must survive an automatic identity replacement. */
411
+ function isLegacyCodexComputerUsePluginDisabled(config) {
412
+ const plugin = isRecord(config) && isRecord(config.plugins) ? config.plugins["computer-use@openai-bundled"] : void 0;
413
+ return isRecord(plugin) && plugin.enabled === false;
414
+ }
415
+ /** Renaming a server must not discard an operator's legacy server or tool restrictions. */
416
+ function hasLegacyCodexComputerUseMcpPolicy(config) {
417
+ if (!isRecord(config)) return false;
418
+ if (isRecord(config.mcp_servers) && Object.hasOwn(config.mcp_servers, "computer-use")) return true;
419
+ const plugin = isRecord(config.plugins) ? config.plugins["computer-use@openai-bundled"] : void 0;
420
+ return isRecord(plugin) && isRecord(plugin.mcp_servers) && Object.keys(plugin.mcp_servers).length > 0;
421
+ }
422
+ async function readObject(file) {
423
+ try {
424
+ const value = JSON.parse(await fs$1.readFile(file, "utf8"));
425
+ return isRecord(value) ? value : void 0;
426
+ } catch {
427
+ return;
428
+ }
429
+ }
430
+ /** Publish the cache from the same prepared source that native plugin/install consumes. */
431
+ async function reconcileManagedCodexComputerUseCache(params) {
432
+ const config = params.config;
433
+ params.assertCurrent();
434
+ const bundledMarketplacePath = params.managedMarketplacePath ?? params.bundledMarketplacePath;
435
+ const cacheBinding = [
436
+ params.epoch ?? "manual",
437
+ bundledMarketplacePath ?? "default",
438
+ config.pluginName
439
+ ].join("\0");
440
+ const shared = await ensureCodexComputerUseSharedPluginCache({
441
+ codexHome: params.codexHome,
442
+ config,
443
+ ...params.ownershipRoot ? { ownershipRoot: params.ownershipRoot } : {},
444
+ ...bundledMarketplacePath ? { bundledMarketplacePath } : {},
445
+ assertCurrent: params.assertCurrent,
446
+ forceRefresh: params.forceRefresh === true || params.previousCacheBinding !== cacheBinding
447
+ });
448
+ params.assertCurrent();
449
+ return shared ? cacheBinding : void 0;
450
+ }
361
451
  //#endregion
362
452
  //#region extensions/codex/src/app-server/computer-use-marketplace.ts
363
453
  /** Managed local wrapper for Codex's reserved bundled marketplace. */
364
454
  const MARKETPLACE_NAME = "openai-bundled";
455
+ const UNIFIED_SOURCE_FINGERPRINT = ".openclaw-unified-source-fingerprint";
365
456
  const activeInstalls$1 = /* @__PURE__ */ new Map();
366
457
  function resolveCodexManagedBundledMarketplacePath(codexHome) {
367
458
  return path.join(codexHome, ".tmp", "bundled-marketplaces", MARKETPLACE_NAME);
@@ -373,6 +464,7 @@ async function ensureCodexManagedBundledMarketplace(params) {
373
464
  candidates
374
465
  });
375
466
  if (!source) return;
467
+ const unifiedRuntime = await resolveCodexUnifiedComputerUseRuntime(source, params.codexHome, params.computerUsePluginName, params.computerUseMcpServerName);
376
468
  const parentPath = path.dirname(resolveCodexManagedBundledMarketplacePath(params.codexHome));
377
469
  const targetPath = path.join(parentPath, MARKETPLACE_NAME);
378
470
  const parent = await prepareOwnedServiceParent({
@@ -388,11 +480,12 @@ async function ensureCodexManagedBundledMarketplace(params) {
388
480
  await active.promise.catch(() => void 0);
389
481
  return await ensureCodexManagedBundledMarketplace(params);
390
482
  }
391
- const install = reconcileManagedWrapper({
483
+ const install = publishManagedWrapper({
392
484
  parent,
393
485
  physicalTargetPath,
394
486
  targetPath,
395
487
  source,
488
+ unifiedRuntime,
396
489
  ownershipCandidates: params.ownershipCandidates ?? candidates,
397
490
  assertCurrent: params.assertCurrent
398
491
  });
@@ -407,12 +500,9 @@ async function ensureCodexManagedBundledMarketplace(params) {
407
500
  install.then(clearActive, clearActive);
408
501
  return await install;
409
502
  }
410
- async function reconcileManagedWrapper(params) {
411
- if (await wrapperMatches(params.physicalTargetPath, params.source.bundledMarketplacePath)) return params.targetPath;
412
- return await publishManagedWrapper(params);
413
- }
414
503
  async function publishManagedWrapper(params) {
415
504
  const { parent, physicalTargetPath, targetPath, source, ownershipCandidates, assertCurrent } = params;
505
+ if (await wrapperMatches(physicalTargetPath, source.bundledMarketplacePath, params.unifiedRuntime)) return targetPath;
416
506
  const stagingPath = await fs$1.mkdtemp(path.join(parent.realPath, `.${MARKETPLACE_NAME}.staging-`));
417
507
  const backupPath = path.join(parent.realPath, `.${MARKETPLACE_NAME}.backup-${process.pid}-${Date.now()}`);
418
508
  let backupCreated = false;
@@ -422,10 +512,22 @@ async function publishManagedWrapper(params) {
422
512
  recursive: true,
423
513
  mode: 448
424
514
  });
425
- await Promise.all([fs$1.symlink(path.join(source.bundledMarketplacePath, ".agents", "plugins", "marketplace.json"), path.join(manifestParent, "marketplace.json")), fs$1.symlink(path.join(source.bundledMarketplacePath, "plugins"), path.join(stagingPath, "plugins"))]);
515
+ await fs$1.symlink(path.join(source.bundledMarketplacePath, ".agents", "plugins", "marketplace.json"), path.join(manifestParent, "marketplace.json"));
516
+ if (params.unifiedRuntime) {
517
+ const pluginsPath = path.join(stagingPath, "plugins");
518
+ await fs$1.mkdir(pluginsPath);
519
+ for (const entry of await fs$1.readdir(path.join(source.bundledMarketplacePath, "plugins"))) {
520
+ const target = path.join(pluginsPath, entry);
521
+ if (entry === "unified-computer-use") await publishCodexUnifiedComputerUsePlugin(target, params.unifiedRuntime);
522
+ else await fs$1.symlink(path.join(source.bundledMarketplacePath, "plugins", entry), target);
523
+ }
524
+ await fs$1.writeFile(path.join(stagingPath, UNIFIED_SOURCE_FINGERPRINT), params.unifiedRuntime.sourceFingerprint, { mode: 384 });
525
+ } else await fs$1.symlink(path.join(source.bundledMarketplacePath, "plugins"), path.join(stagingPath, "plugins"));
526
+ await waitForCodexDesktopGeneration();
527
+ assertCurrent?.();
426
528
  await assertDirectoryIdentityStable(parent, "managed bundled marketplace parent");
427
529
  const existing = await fs$1.lstat(physicalTargetPath).catch((error) => {
428
- if (hasNodeErrorCode(error, "ENOENT")) return;
530
+ if (extractErrorCode(error) === "ENOENT") return;
429
531
  throw error;
430
532
  });
431
533
  if (existing && !existing.isDirectory()) throw new Error(`Managed bundled marketplace must be a real directory: ${targetPath}`);
@@ -448,7 +550,7 @@ async function publishManagedWrapper(params) {
448
550
  if (backupCreated) try {
449
551
  await assertDirectoryIdentityStable(parent, "managed bundled marketplace parent");
450
552
  if (await fs$1.lstat(physicalTargetPath).catch(() => void 0)) {
451
- if (!await wrapperMatches(physicalTargetPath, source.bundledMarketplacePath)) throw new Error("managed bundled marketplace replacement is no longer owned", { cause: error });
553
+ if (!await wrapperOwnedBySource(physicalTargetPath, source.bundledMarketplacePath)) throw new Error("managed bundled marketplace replacement is no longer owned", { cause: error });
452
554
  await fs$1.rm(physicalTargetPath, { recursive: true });
453
555
  }
454
556
  await fs$1.rename(backupPath, physicalTargetPath);
@@ -479,22 +581,51 @@ async function isExpectedMarketplace(root) {
479
581
  return false;
480
582
  }
481
583
  }
482
- async function wrapperMatches(targetPath, sourcePath) {
584
+ async function wrapperMatches(targetPath, sourcePath, unifiedRuntime) {
585
+ if (!await wrapperOwnedBySource(targetPath, sourcePath)) return false;
586
+ const plugins = await fs$1.lstat(path.join(targetPath, "plugins"));
587
+ if (unifiedRuntime && plugins.isDirectory()) {
588
+ const [sourceEntries, targetEntries] = await Promise.all([fs$1.readdir(path.join(sourcePath, "plugins")), fs$1.readdir(path.join(targetPath, "plugins"))]);
589
+ const sourceNames = new Set(sourceEntries);
590
+ if (sourceNames.size !== targetEntries.length || targetEntries.some((name) => !sourceNames.has(name))) return false;
591
+ }
592
+ return unifiedRuntime ? plugins.isDirectory() && await fs$1.readFile(path.join(targetPath, UNIFIED_SOURCE_FINGERPRINT), "utf8").catch(() => void 0) === unifiedRuntime.sourceFingerprint && await codexUnifiedComputerUsePluginMatches(path.join(targetPath, "plugins", "unified-computer-use"), unifiedRuntime) : plugins.isSymbolicLink();
593
+ }
594
+ async function wrapperOwnedBySource(targetPath, sourcePath) {
483
595
  try {
484
596
  const target = await fs$1.lstat(targetPath);
485
597
  if (!target.isDirectory() || target.isSymbolicLink()) return false;
486
- const [manifest, plugins] = await Promise.all([fs$1.readlink(path.join(targetPath, ".agents", "plugins", "marketplace.json")), fs$1.readlink(path.join(targetPath, "plugins"))]);
487
- return manifest === path.join(sourcePath, ".agents", "plugins", "marketplace.json") && plugins === path.join(sourcePath, "plugins");
598
+ if (await fs$1.readlink(path.join(targetPath, ".agents", "plugins", "marketplace.json")) !== path.join(sourcePath, ".agents", "plugins", "marketplace.json")) return false;
599
+ const pluginsPath = path.join(targetPath, "plugins");
600
+ const plugins = await fs$1.lstat(pluginsPath);
601
+ if (plugins.isSymbolicLink()) return await fs$1.readlink(pluginsPath) === path.join(sourcePath, "plugins");
602
+ if (!plugins.isDirectory()) return false;
603
+ let hasUnifiedPlugin = false;
604
+ for (const entry of await fs$1.readdir(pluginsPath, { withFileTypes: true })) if (entry.name === "unified-computer-use" && entry.isDirectory()) {
605
+ const plugin = JSON.parse(await fs$1.readFile(path.join(pluginsPath, entry.name, ".codex-plugin", "plugin.json"), "utf8"));
606
+ if (!isRecord(plugin) || plugin.name !== "unified-computer-use") return false;
607
+ hasUnifiedPlugin = true;
608
+ } else if (!entry.isSymbolicLink() || await fs$1.readlink(path.join(pluginsPath, entry.name)) !== path.join(sourcePath, "plugins", entry.name)) return false;
609
+ return hasUnifiedPlugin;
488
610
  } catch {
489
611
  return false;
490
612
  }
491
613
  }
492
614
  async function wrapperMatchesAnySource(targetPath, candidates) {
493
- for (const candidate of candidates) if (await wrapperMatches(targetPath, candidate.bundledMarketplacePath)) return true;
615
+ for (const candidate of candidates) if (await wrapperOwnedBySource(targetPath, candidate.bundledMarketplacePath)) return true;
494
616
  return false;
495
617
  }
496
- function hasNodeErrorCode(error, code) {
497
- return Boolean(error && typeof error === "object" && "code" in error && error.code === code);
618
+ async function resolveClientManagedBundledMarketplacePath(codexHome, agentDir) {
619
+ if (!codexHome || !agentDir) return;
620
+ const [actualRealHome, expectedRealHome] = await Promise.all([fs$1.realpath(codexHome).catch(() => void 0), fs$1.realpath(resolveCodexAppServerHomeDir(agentDir)).catch(() => void 0)]);
621
+ if (!actualRealHome || actualRealHome !== expectedRealHome) return;
622
+ const managedPath = resolveCodexManagedBundledMarketplacePath(codexHome);
623
+ return existsSync(managedPath) ? managedPath : void 0;
624
+ }
625
+ function resolveBundledComputerUseMarketplacePath(params) {
626
+ if (params.defaultBundledMarketplacePath) return existsSync(params.defaultBundledMarketplacePath) ? params.defaultBundledMarketplacePath : void 0;
627
+ if (!params.defaultBundledMarketplacePathCandidates) return;
628
+ return resolveFirstExistingMacOSDesktopCodexBundledMarketplacePath({ candidates: params.defaultBundledMarketplacePathCandidates });
498
629
  }
499
630
  //#endregion
500
631
  //#region extensions/codex/src/app-server/computer-use-service.ts
@@ -546,7 +677,6 @@ async function ensureCodexComputerUseServiceApp(params) {
546
677
  ownershipRoot,
547
678
  targetParent,
548
679
  targetPath,
549
- platform,
550
680
  sourceAppCandidates: candidates
551
681
  });
552
682
  const activeEntry = {
@@ -562,13 +692,20 @@ async function ensureCodexComputerUseServiceApp(params) {
562
692
  }
563
693
  async function ensureCodexComputerUseServiceAppOnce(params) {
564
694
  const inspectServiceApp = params.inspectServiceApp ?? inspectTrustedServiceApp;
565
- const source = await findUsableServiceApp(params.sourceAppCandidates ?? [], inspectServiceApp);
695
+ const source = await findUsableServiceApp(params.sourceAppCandidates, inspectServiceApp);
566
696
  if (!source) return {
567
697
  status: "source_missing",
568
698
  changed: false,
569
699
  targetPath: params.targetPath
570
700
  };
571
701
  const { path: sourcePath, identity: sourceIdentity } = source;
702
+ const alreadyCurrent = {
703
+ status: "already_current",
704
+ changed: false,
705
+ targetPath: params.targetPath,
706
+ sourcePath,
707
+ sourceBuild: sourceIdentity.build
708
+ };
572
709
  const ownedParent = await prepareOwnedServiceParent({
573
710
  ownershipRoot: params.ownershipRoot,
574
711
  codexHome: params.codexHome,
@@ -577,19 +714,29 @@ async function ensureCodexComputerUseServiceAppOnce(params) {
577
714
  const operationTargetPath = path.join(ownedParent.realPath, SERVICE_APP_NAME);
578
715
  await assertNotSymlink(operationTargetPath, "Computer Use service target");
579
716
  const initialTarget = await readServiceAppSnapshot(operationTargetPath, inspectServiceApp);
580
- if (initialTarget.identity && identitiesMatch(initialTarget.identity, sourceIdentity)) return {
581
- status: "already_current",
582
- changed: false,
583
- targetPath: params.targetPath,
584
- sourcePath,
585
- sourceBuild: sourceIdentity.build
586
- };
717
+ if (initialTarget.identity && identitiesMatch(initialTarget.identity, sourceIdentity)) return alreadyCurrent;
587
718
  await assertOwnedServiceParentStable(ownedParent);
588
719
  const stagingRoot = await fs$1.mkdtemp(path.join(ownedParent.realPath, ".service-app.staging-"));
589
720
  const stagingRootIdentity = await readRealDirectoryIdentity(stagingRoot, "Computer Use service staging directory");
590
721
  const stagedPath = path.join(stagingRoot, SERVICE_APP_NAME);
591
722
  const backupPath = path.join(ownedParent.realPath, `.service-app.backup-${process.pid}-${Date.now()}`);
592
723
  let backupCreated = false;
724
+ const restoreBackup = async () => {
725
+ await assertOwnedServiceParentStable(ownedParent);
726
+ await fs$1.rename(backupPath, operationTargetPath);
727
+ await assertOwnedServiceParentStable(ownedParent);
728
+ backupCreated = false;
729
+ };
730
+ const removeBackup = async () => {
731
+ await assertOwnedServiceParentStable(ownedParent);
732
+ await assertNotSymlink(backupPath, "Computer Use service backup");
733
+ await fs$1.rm(backupPath, {
734
+ recursive: true,
735
+ force: true
736
+ });
737
+ await assertOwnedServiceParentStable(ownedParent);
738
+ backupCreated = false;
739
+ };
593
740
  try {
594
741
  await (params.copyServiceApp ?? copyServiceAppWithDitto)(sourcePath, stagedPath);
595
742
  await assertOwnedServiceParentStable(ownedParent);
@@ -612,23 +759,11 @@ async function ensureCodexComputerUseServiceAppOnce(params) {
612
759
  backupCreated = true;
613
760
  const movedTarget = await readServiceAppSnapshot(backupPath, inspectServiceApp);
614
761
  if (movedTarget.identity && identitiesMatch(movedTarget.identity, sourceIdentity)) {
615
- await assertOwnedServiceParentStable(ownedParent);
616
- await fs$1.rename(backupPath, operationTargetPath);
617
- await assertOwnedServiceParentStable(ownedParent);
618
- backupCreated = false;
619
- return {
620
- status: "already_current",
621
- changed: false,
622
- targetPath: params.targetPath,
623
- sourcePath,
624
- sourceBuild: sourceIdentity.build
625
- };
762
+ await restoreBackup();
763
+ return alreadyCurrent;
626
764
  }
627
765
  if (!snapshotsMatch(initialTarget, movedTarget)) {
628
- await assertOwnedServiceParentStable(ownedParent);
629
- await fs$1.rename(backupPath, operationTargetPath);
630
- await assertOwnedServiceParentStable(ownedParent);
631
- backupCreated = false;
766
+ await restoreBackup();
632
767
  throw new Error("Computer Use service target changed to an unexpected generation during refresh.");
633
768
  }
634
769
  }
@@ -642,33 +777,11 @@ async function ensureCodexComputerUseServiceAppOnce(params) {
642
777
  await assertNotSymlink(operationTargetPath, "Computer Use service target");
643
778
  const winnerIdentity = await inspectServiceApp(operationTargetPath);
644
779
  if (!winnerIdentity || !identitiesMatch(winnerIdentity, sourceIdentity)) {
645
- if (backupCreated) {
646
- if (!await pathExists$1(operationTargetPath)) {
647
- await assertOwnedServiceParentStable(ownedParent);
648
- await fs$1.rename(backupPath, operationTargetPath);
649
- await assertOwnedServiceParentStable(ownedParent);
650
- backupCreated = false;
651
- }
652
- }
780
+ if (backupCreated && !await pathExists$1(operationTargetPath)) await restoreBackup();
653
781
  throw error;
654
782
  }
655
- if (backupCreated) {
656
- await assertOwnedServiceParentStable(ownedParent);
657
- await assertNotSymlink(backupPath, "Computer Use service backup");
658
- await fs$1.rm(backupPath, {
659
- recursive: true,
660
- force: true
661
- });
662
- await assertOwnedServiceParentStable(ownedParent);
663
- backupCreated = false;
664
- }
665
- return {
666
- status: "already_current",
667
- changed: false,
668
- targetPath: params.targetPath,
669
- sourcePath,
670
- sourceBuild: sourceIdentity.build
671
- };
783
+ if (backupCreated) await removeBackup();
784
+ return alreadyCurrent;
672
785
  }
673
786
  await assertNotSymlink(operationTargetPath, "Installed Computer Use service app");
674
787
  const installedSnapshot = await readServiceAppSnapshot(operationTargetPath, inspectServiceApp);
@@ -688,16 +801,7 @@ async function ensureCodexComputerUseServiceAppOnce(params) {
688
801
  }
689
802
  throw new Error("Installed Computer Use service app failed post-install identity verification.");
690
803
  }
691
- if (backupCreated) {
692
- await assertOwnedServiceParentStable(ownedParent);
693
- await assertNotSymlink(backupPath, "Computer Use service backup");
694
- await fs$1.rm(backupPath, {
695
- recursive: true,
696
- force: true
697
- });
698
- await assertOwnedServiceParentStable(ownedParent);
699
- backupCreated = false;
700
- }
804
+ if (backupCreated) await removeBackup();
701
805
  return {
702
806
  status: initialTarget.exists ? "refreshed" : "installed",
703
807
  changed: true,
@@ -707,14 +811,14 @@ async function ensureCodexComputerUseServiceAppOnce(params) {
707
811
  ...initialTarget.identity ? { previousBuild: initialTarget.identity.build } : {}
708
812
  };
709
813
  } catch (error) {
710
- if (backupCreated && await ownedServiceParentIsStable(ownedParent) && !await pathExists$1(operationTargetPath)) {
814
+ if (backupCreated && await directoryIdentityIsStable(ownedParent) && !await pathExists$1(operationTargetPath)) {
711
815
  await assertOwnedServiceParentStable(ownedParent);
712
816
  await fs$1.rename(backupPath, operationTargetPath);
713
817
  backupCreated = false;
714
818
  }
715
819
  throw error;
716
820
  } finally {
717
- if (await ownedServiceParentIsStable(ownedParent) && await directoryIdentityIsStable(stagingRootIdentity)) await fs$1.rm(stagingRoot, {
821
+ if (await directoryIdentityIsStable(ownedParent) && await directoryIdentityIsStable(stagingRootIdentity)) await fs$1.rm(stagingRoot, {
718
822
  recursive: true,
719
823
  force: true
720
824
  });
@@ -761,18 +865,10 @@ function filesystemSnapshotsMatch(left, right) {
761
865
  function identitiesMatch(left, right) {
762
866
  return left.bundleId === right.bundleId && left.version === right.version && left.build === right.build && left.cdHash === right.cdHash && left.teamId === right.teamId && left.clientBundleId === right.clientBundleId && left.clientCdHash === right.clientCdHash && left.clientTeamId === right.clientTeamId;
763
867
  }
764
- async function hasExecutableClient(appPath) {
765
- try {
766
- await fs$1.access(path.join(appPath, CLIENT_RELATIVE_PATH), constants.X_OK);
767
- return true;
768
- } catch {
769
- return false;
770
- }
771
- }
772
868
  async function inspectTrustedServiceApp(appPath) {
773
- if (!await hasExecutableClient(appPath)) return;
774
869
  const clientAppPath = path.join(appPath, CLIENT_APP_RELATIVE_PATH);
775
870
  try {
871
+ await fs$1.access(path.join(appPath, CLIENT_RELATIVE_PATH), constants.X_OK);
776
872
  await verifyTrustedBundle(appPath, SERVICE_BUNDLE_ID, true);
777
873
  await verifyTrustedBundle(clientAppPath, CLIENT_BUNDLE_ID, false);
778
874
  const [info, serviceSignature, clientSignature] = await Promise.all([
@@ -880,7 +976,10 @@ const scopedOAuthRefreshQueues = /* @__PURE__ */ new WeakMap();
880
976
  async function bridgeCodexAppServerStartOptions(params) {
881
977
  if (params.startOptions.transport !== "stdio") return params.startOptions;
882
978
  const scopeStartOptions = () => withCodexHomeEnvironment(withEphemeralCodexAuthStore(params), params.agentDir);
883
- if (params.preparedAuth) return withClearedEnvironmentVariables(await scopeStartOptions(), CODEX_APP_SERVER_PREPARED_AUTH_ENV_VARS);
979
+ if (params.preparedAuth) {
980
+ const scopedStartOptions = await scopeStartOptions();
981
+ return withClearedEnvironmentVariables(scopedStartOptions, CODEX_APP_SERVER_PREPARED_AUTH_ENV_VARS);
982
+ }
884
983
  if (params.authProfileId === null) return scopeStartOptions();
885
984
  const store = resolveCodexAppServerAuthProfileStore({
886
985
  agentDir: params.agentDir,
@@ -913,8 +1012,7 @@ function resolveUnimportedAgentCodexAuthMessage(params) {
913
1012
  const targetAgentId = params.agentId?.trim() || "<agent-id>";
914
1013
  return `A Codex auth file exists at ${authPath}, but agent-scoped Codex runs use OpenClaw's auth store and do not read that file. Preview only that credential import with \`openclaw migrate plan codex --from <codex-home> --agent ${targetAgentId} --include-secrets --item auth:openai\`, then run \`openclaw migrate apply codex --from <codex-home> --agent ${targetAgentId} --include-secrets --item auth:openai --yes\`. If the plan finds no credentials, remove the stale auth file.`;
915
1014
  }
916
- /** Resolves prepared profile login material once so cache identity and RPC login cannot drift. */
917
- async function resolveCodexAppServerPreparedAuthProfileSnapshot(params) {
1015
+ function resolveCodexAppServerAuthProfile(params) {
918
1016
  const agentDir = params.agentDir?.trim() || resolveDefaultAgentDir(params.config ?? {});
919
1017
  const store = resolveCodexAppServerAuthProfileStore({
920
1018
  agentDir,
@@ -929,7 +1027,33 @@ async function resolveCodexAppServerPreparedAuthProfileSnapshot(params) {
929
1027
  });
930
1028
  if (!profileId) return;
931
1029
  const credential = store.profiles[profileId];
932
- if (!credential || !isCodexAppServerAuthProfileCredential(credential)) return;
1030
+ if (!credential || !isCodexAppServerAuthProvider(credential.provider)) return;
1031
+ return {
1032
+ agentDir,
1033
+ store,
1034
+ profileId,
1035
+ credential
1036
+ };
1037
+ }
1038
+ /** Resolves prepared profile login material once so cache identity and RPC login cannot drift. */
1039
+ async function resolveCodexAppServerPreparedAuthProfileSnapshot(params) {
1040
+ const profile = resolveCodexAppServerAuthProfile(params);
1041
+ if (!profile) return;
1042
+ const { agentDir, store, profileId, credential } = profile;
1043
+ if (isCodexResponsesOAuthCredential(credential)) return {
1044
+ inferenceAuth: "host-oauth",
1045
+ loginParams: {
1046
+ type: "apiKey",
1047
+ apiKey: `openclaw-local-${randomUUID()}`
1048
+ },
1049
+ secretFreeCacheKey: await resolveCodexResponsesOAuthProfileFingerprint({
1050
+ profileId,
1051
+ store,
1052
+ agentDir,
1053
+ config: params.config
1054
+ })
1055
+ };
1056
+ if (credential.type === "oauth" && credential.authFlow === "chatgpt-identity") throw new Error("ChatGPT subscription sharing was not granted; sign in again and enable sharing.");
933
1057
  const loginParams = await resolveCodexAppServerAuthProfileLoginParamsInternal({
934
1058
  agentDir,
935
1059
  authProfileId: profileId,
@@ -950,6 +1074,22 @@ async function resolveCodexAppServerPreparedAuthProfileSnapshot(params) {
950
1074
  /** Maps one prepared route to one mutually exclusive app-server auth handoff. */
951
1075
  async function resolveCodexAppServerPreparedAuthHandoff(params) {
952
1076
  const usesNativeHome = params.homeScope === "user";
1077
+ const selectedCredential = params.authProfileId ? params.authProfileStore.profiles[params.authProfileId] : void 0;
1078
+ if (isCodexResponsesOAuthCredential(selectedCredential)) {
1079
+ if (usesNativeHome || params.requirePreparedAuth || params.authRequirement !== "api-key") throw new Error("ChatGPT subscription sharing requires the managed local Codex API route and an isolated home.");
1080
+ const snapshot = await resolveCodexAppServerPreparedAuthProfileSnapshot(params);
1081
+ if (!snapshot || !params.authProfileId) throw new Error("ChatGPT subscription sharing could not prepare the selected profile.");
1082
+ return {
1083
+ authProfileId: params.authProfileId,
1084
+ nativeAuthProfile: false,
1085
+ preparedAuth: {
1086
+ kind: "profile",
1087
+ profileId: params.authProfileId,
1088
+ store: params.authProfileStore,
1089
+ snapshot
1090
+ }
1091
+ };
1092
+ }
953
1093
  if (params.requirePreparedAuth && usesNativeHome) throw createCodexAppServerAuthError("Codex remote-exec cloud placement requires prepared OpenAI auth. Configure an OpenAI API-key, OAuth, or token profile and use appServer.homeScope=\"agent\"; ambient credentials and native Codex auth are not allowed.");
954
1094
  if (usesNativeHome) return { nativeAuthProfile: true };
955
1095
  if (params.authRequirement === "api-key") {
@@ -964,6 +1104,7 @@ async function resolveCodexAppServerPreparedAuthHandoff(params) {
964
1104
  };
965
1105
  }
966
1106
  const authProfileId = params.authProfileId?.trim() || void 0;
1107
+ if (authProfileId && !params.authProfileStore.profiles[authProfileId]) throw new CodexAppServerAuthProfileUnavailableError(formatCodexAuthProfileUnavailableMessage(authProfileId));
967
1108
  const nativeAuthProfile = isCodexAppServerNativeAuthProfile({
968
1109
  authProfileId,
969
1110
  authProfileStore: params.authProfileStore,
@@ -994,38 +1135,19 @@ async function resolveCodexAppServerPreparedAuthHandoff(params) {
994
1135
  };
995
1136
  }
996
1137
  async function resolveCodexAppServerAuthAccountCacheKey(params) {
997
- const agentDir = params.agentDir?.trim() || resolveDefaultAgentDir(params.config ?? {});
998
- const store = resolveCodexAppServerAuthProfileStore({
999
- agentDir,
1000
- authProfileId: params.authProfileId,
1001
- authProfileStore: params.authProfileStore,
1002
- config: params.config
1003
- });
1004
- const profileId = resolveCodexAppServerAuthProfileId({
1005
- authProfileId: params.authProfileId,
1138
+ const profile = resolveCodexAppServerAuthProfile(params);
1139
+ if (!profile) return;
1140
+ const { agentDir, store, profileId, credential } = profile;
1141
+ const accountId = resolveChatgptAccountId(profileId, credential);
1142
+ if (credential.type === "oauth") return accountId;
1143
+ const value = (await resolveApiKeyForProfile({
1144
+ cfg: params.config,
1006
1145
  store,
1007
- config: params.config
1008
- });
1009
- if (!profileId) return;
1010
- const credential = store.profiles[profileId];
1011
- if (!credential || !isCodexAppServerAuthProfileCredential(credential)) return;
1012
- if (credential.type === "api_key") {
1013
- const apiKey = (await resolveApiKeyForProfile({
1014
- store,
1015
- profileId,
1016
- agentDir
1017
- }))?.apiKey?.trim();
1018
- return apiKey ? `${resolveChatgptAccountId(profileId, credential)}:${fingerprintApiKeyAuthProfileCacheKey(apiKey)}` : resolveChatgptAccountId(profileId, credential);
1019
- }
1020
- if (credential.type === "token") {
1021
- const accessToken = (await resolveApiKeyForProfile({
1022
- store,
1023
- profileId,
1024
- agentDir
1025
- }))?.apiKey?.trim();
1026
- return accessToken ? `${resolveChatgptAccountId(profileId, credential)}:${fingerprintTokenAuthProfileCacheKey(accessToken)}` : resolveChatgptAccountId(profileId, credential);
1027
- }
1028
- return resolveChatgptAccountId(profileId, credential);
1146
+ profileId,
1147
+ agentDir
1148
+ }))?.apiKey?.trim();
1149
+ if (!value) return accountId;
1150
+ return `${accountId}:${credential.type === "api_key" ? fingerprintApiKeyAuthProfileCacheKey(value) : fingerprintTokenAuthProfileCacheKey(value)}`;
1029
1151
  }
1030
1152
  async function withCodexHomeEnvironment(startOptions, agentDir) {
1031
1153
  const codexHome = resolveCodexAppServerLocalHomeDir(startOptions, agentDir);
@@ -1107,12 +1229,15 @@ async function reconcileCodexComputerUseStartArtifactsOnce(params) {
1107
1229
  needsBundledMarketplace
1108
1230
  }) : exactDesktopCandidate;
1109
1231
  params.assertCurrent();
1232
+ let marketplacePath;
1110
1233
  if (provisioningAgentDir) {
1111
1234
  if (desktopCandidates.length > 0 && !artifactCandidate) throw new CodexComputerUseCandidateArtifactsUnavailableError();
1112
1235
  try {
1113
- const marketplacePath = usesManagedBundledMarketplace ? await ensureCodexManagedBundledMarketplace({
1236
+ marketplacePath = usesManagedBundledMarketplace ? await ensureCodexManagedBundledMarketplace({
1114
1237
  codexHome,
1115
1238
  ownershipRoot: provisioningAgentDir,
1239
+ computerUsePluginName: computerUseConfig.pluginName,
1240
+ computerUseMcpServerName: computerUseConfig.mcpServerName,
1116
1241
  ...artifactCandidate ? {
1117
1242
  appServerCommand: artifactCandidate.appServerCommandPath,
1118
1243
  candidates: [artifactCandidate],
@@ -1143,21 +1268,17 @@ async function reconcileCodexComputerUseStartArtifactsOnce(params) {
1143
1268
  }
1144
1269
  }
1145
1270
  params.assertCurrent();
1146
- const cacheBinding = [
1147
- params.desktopGeneration?.epoch ?? "manual",
1148
- artifactCandidate?.bundledMarketplacePath ?? "default",
1149
- computerUseConfig.pluginName
1150
- ].join("\0");
1151
- const cache = await ensureCodexComputerUseSharedPluginCache({
1271
+ return await reconcileManagedCodexComputerUseCache({
1152
1272
  codexHome,
1153
1273
  config: computerUseConfig,
1154
- ...ownsIsolatedCodexHome ? { ownershipRoot: params.agentDir } : {},
1155
- ...artifactCandidate ? { bundledMarketplacePath: artifactCandidate.bundledMarketplacePath } : {},
1274
+ ownershipRoot: ownsIsolatedCodexHome ? params.agentDir : void 0,
1275
+ managedMarketplacePath: marketplacePath,
1276
+ bundledMarketplacePath: artifactCandidate?.bundledMarketplacePath,
1277
+ epoch: params.desktopGeneration?.epoch,
1156
1278
  assertCurrent: params.assertCurrent,
1157
- forceRefresh: params.forceCacheRefresh === true || params.previousCacheBinding !== cacheBinding
1279
+ forceRefresh: params.forceCacheRefresh,
1280
+ previousCacheBinding: params.previousCacheBinding
1158
1281
  });
1159
- params.assertCurrent();
1160
- return cache.status === "shared" ? cacheBinding : void 0;
1161
1282
  }
1162
1283
  async function resolveCompleteComputerUseArtifactCandidate(params) {
1163
1284
  for (const candidate of params.candidates) {
@@ -1195,10 +1316,14 @@ async function applyCodexAppServerAuthProfile(params) {
1195
1316
  let loginParams = params.preparedAuth?.kind === "profile" ? params.preparedAuth.snapshot.loginParams : params.preparedAuth?.kind === "api-key" ? {
1196
1317
  type: "apiKey",
1197
1318
  apiKey: params.preparedAuth.apiKey
1198
- } : await resolveCodexAppServerAuthProfileLoginParams({
1319
+ } : await resolveCodexAppServerAuthProfileLoginParamsInternal({
1199
1320
  agentDir,
1200
1321
  authProfileId: params.authProfileId ?? void 0,
1201
- authProfileStore: params.authProfileStore,
1322
+ authProfileStore: resolveCodexAppServerAuthProfileStore({
1323
+ ...params,
1324
+ agentDir,
1325
+ authProfileId: params.authProfileId ?? void 0
1326
+ }),
1202
1327
  config: params.config
1203
1328
  });
1204
1329
  if (params.authRequirement === "subscription" && loginParams?.type !== "chatgptAuthTokens") throw createCodexAppServerAuthError("Codex subscription auth profile could not produce login credentials. Sign in with `openclaw models auth login --provider openai`, select that profile, then retry.");
@@ -1231,8 +1356,7 @@ async function applyCodexAppServerAuthProfile(params) {
1231
1356
  */
1232
1357
  async function assertNativeCodexAccountMatchesRoute(client, authRequirement, assertCurrent) {
1233
1358
  if (!authRequirement) return;
1234
- const response = await client.request("account/read", { refreshToken: false }, { assertCurrent });
1235
- const accountType = isJsonObject(response.account) ? response.account.type : void 0;
1359
+ const accountType = (await client.request("account/read", { refreshToken: false }, { assertCurrent })).account?.type;
1236
1360
  if (authRequirement === "subscription") {
1237
1361
  if (accountType !== "chatgpt") throw createCodexAppServerAuthError("Codex subscription route requires ChatGPT auth in the native Codex home. Run `codex login` for that home, or use appServer.homeScope=\"agent\" with an OpenClaw OAuth profile, then retry.");
1238
1362
  return;
@@ -1243,28 +1367,6 @@ function createCodexAppServerAuthError(message, cause) {
1243
1367
  const error = cause === void 0 ? new Error(message) : new Error(message, { cause });
1244
1368
  return Object.assign(error, { status: 401 });
1245
1369
  }
1246
- var CodexAppServerAuthProfileUnavailableError = class extends Error {
1247
- constructor(..._args) {
1248
- super(..._args);
1249
- this.status = 401;
1250
- this.code = "selected_auth_profile_unavailable";
1251
- }
1252
- };
1253
- async function resolveCodexAppServerAuthProfileLoginParams(params) {
1254
- const store = resolveCodexAppServerAuthProfileStore(params);
1255
- const profileId = resolveCodexAppServerAuthProfileId({
1256
- authProfileId: params.authProfileId,
1257
- store,
1258
- config: params.config
1259
- });
1260
- const profile = profileId ? store.profiles[profileId] : void 0;
1261
- if (profileId && !profile) throw new CodexAppServerAuthProfileUnavailableError(`Codex app-server auth profile "${profileId}" was not found. Select an existing OpenAI profile or sign in again with OpenClaw, then retry.`);
1262
- if (profileId && profile && !isCodexAppServerAuthProfileCredential(profile)) throw new CodexAppServerAuthProfileUnavailableError(`Codex app-server auth profile "${profileId}" must use the canonical OpenAI auth provider; run "openclaw doctor --fix" to migrate legacy provider IDs.`);
1263
- return await resolveCodexAppServerAuthProfileLoginParamsInternal({
1264
- ...params,
1265
- authProfileStore: store
1266
- });
1267
- }
1268
1370
  async function refreshCodexAppServerAuthTokens(params) {
1269
1371
  const previousAccountId = params.previousAccountId?.trim();
1270
1372
  const handoffAccountId = params.authHandoff?.chatgptAccountId.trim();
@@ -1285,8 +1387,7 @@ async function refreshCodexAppServerAuthTokens(params) {
1285
1387
  forceOAuthRefresh: true
1286
1388
  });
1287
1389
  if (!loginParams || loginParams.type !== "chatgptAuthTokens") throw new Error("Codex app-server ChatGPT token refresh requires an OAuth auth profile. Sign in with `openclaw models auth login --provider openai`, select that profile, then retry.");
1288
- if (previousAccountId && loginParams.chatgptAccountId !== previousAccountId) throw new Error("ChatGPT workspace changed during Codex token refresh. Retry to start a client for the selected workspace.");
1289
- if (params.authHandoff && loginParams.chatgptAccountId !== params.authHandoff.chatgptAccountId) throw new Error("ChatGPT workspace changed during Codex token refresh. Retry to start a client for the selected workspace.");
1390
+ if (previousAccountId && loginParams.chatgptAccountId !== previousAccountId || params.authHandoff && loginParams.chatgptAccountId !== params.authHandoff.chatgptAccountId) throw new Error("ChatGPT workspace changed during Codex token refresh. Retry to start a client for the selected workspace.");
1290
1391
  return {
1291
1392
  accessToken: loginParams.accessToken,
1292
1393
  chatgptAccountId: loginParams.chatgptAccountId,
@@ -1307,8 +1408,8 @@ async function resolveCodexAppServerAuthProfileLoginParamsInternal(params) {
1307
1408
  });
1308
1409
  if (!profileId) return;
1309
1410
  const credential = store.profiles[profileId];
1310
- if (!credential) throw new CodexAppServerAuthProfileUnavailableError(`Codex app-server auth profile "${profileId}" was not found. Select an existing OpenAI profile or sign in again with OpenClaw, then retry.`);
1311
- if (!isCodexAppServerAuthProfileCredential(credential)) throw new CodexAppServerAuthProfileUnavailableError(`Codex app-server auth profile "${profileId}" must use the canonical OpenAI auth provider; run "openclaw doctor --fix" to migrate legacy provider IDs.`);
1411
+ if (!credential) throw new CodexAppServerAuthProfileUnavailableError(formatCodexAuthProfileUnavailableMessage(profileId));
1412
+ if (!isCodexAppServerAuthProvider(credential.provider)) throw new CodexAppServerAuthProfileUnavailableError(`Codex app-server auth profile "${profileId}" must use the canonical OpenAI auth provider; run "openclaw doctor --fix" to migrate legacy provider IDs.`);
1312
1413
  const loginParams = await resolveLoginParamsForCredential(profileId, credential, {
1313
1414
  agentDir: params.agentDir,
1314
1415
  store,
@@ -1331,30 +1432,22 @@ async function resolveCodexAppServerFallbackApiKeyLoginParams(params) {
1331
1432
  };
1332
1433
  }
1333
1434
  async function resolveLoginParamsForCredential(profileId, credential, params) {
1334
- if (credential.type === "api_key") {
1335
- const apiKey = (await resolveApiKeyForProfile({
1435
+ if (credential.type === "api_key" || credential.type === "token") {
1436
+ const value = (await resolveApiKeyForProfile({
1437
+ cfg: params.config,
1336
1438
  store: params.preferStoreCredential ? params.store : ensureAuthProfileStore(params.agentDir, {
1337
1439
  allowKeychainPrompt: false,
1338
- profileId
1440
+ profileId,
1441
+ config: params.config
1339
1442
  }),
1340
1443
  profileId,
1341
1444
  agentDir: params.agentDir
1342
1445
  }))?.apiKey?.trim();
1343
- return apiKey ? {
1446
+ if (!value) return;
1447
+ return credential.type === "api_key" ? {
1344
1448
  type: "apiKey",
1345
- apiKey
1346
- } : void 0;
1347
- }
1348
- if (credential.type === "token") {
1349
- const accessToken = (await resolveApiKeyForProfile({
1350
- store: params.preferStoreCredential ? params.store : ensureAuthProfileStore(params.agentDir, {
1351
- allowKeychainPrompt: false,
1352
- profileId
1353
- }),
1354
- profileId,
1355
- agentDir: params.agentDir
1356
- }))?.apiKey?.trim();
1357
- return accessToken ? buildChatgptAuthTokensParams(profileId, credential, accessToken) : void 0;
1449
+ apiKey: value
1450
+ } : buildChatgptAuthTokensParams(profileId, credential, value);
1358
1451
  }
1359
1452
  if (credential.type !== "oauth") return;
1360
1453
  const resolvedCredential = await resolveOAuthCredentialForCodexAppServer(profileId, credential, {
@@ -1384,7 +1477,7 @@ async function resolveOAuthCredentialForCodexAppServer(profileId, credential, pa
1384
1477
  persistedCredential,
1385
1478
  suppliedCredential: credential
1386
1479
  });
1387
- if (params.preferStoreCredential && params.store.runtimePersistedProfileIds?.includes(profileId) && (persistedCredential?.type !== "oauth" || !isCodexAppServerAuthProvider(persistedCredential.provider))) throw new CodexAppServerAuthProfileUnavailableError(`Codex app-server auth profile "${profileId}" is no longer available. Sign in again with OpenClaw, then retry.`);
1480
+ if (params.preferStoreCredential && params.store.runtimePersistedProfileIds?.includes(profileId) && (persistedCredential?.type !== "oauth" || !isCodexAppServerAuthProvider(persistedCredential.provider))) throw new CodexAppServerAuthProfileUnavailableError(`Codex app-server auth profile "${profileId}" is no longer an OpenAI OAuth credential in its persisted OpenClaw store. Run "openclaw doctor" to inspect credential ownership, or select an existing OpenAI profile.`);
1388
1481
  const store = useScopedCredential ? params.store : resolveCodexAppServerAuthProfileStore({
1389
1482
  agentDir: ownerAgentDir,
1390
1483
  authProfileId: profileId,
@@ -1408,17 +1501,22 @@ async function resolveOAuthCredentialForCodexAppServer(profileId, credential, pa
1408
1501
  profileId,
1409
1502
  credential: overlaidOAuthCredential,
1410
1503
  forceRefresh: params.forceRefresh && !reuseCompletedRotation,
1411
- expectedAccountId
1504
+ expectedAccountId,
1505
+ config: params.config
1412
1506
  });
1413
1507
  if (params.forceRefresh && !persistedOAuthCredential && overlaidOAuthCredential) {
1414
1508
  if (reuseCompletedRotation) return overlaidOAuthCredential;
1415
- const refreshedRuntimeCredential = await refreshOAuthCredentialForRuntime({ credential: overlaidOAuthCredential });
1509
+ const refreshedRuntimeCredential = await refreshOAuthCredentialForRuntime({
1510
+ credential: overlaidOAuthCredential,
1511
+ cfg: params.config
1512
+ });
1416
1513
  if (!refreshedRuntimeCredential?.access?.trim()) throw new Error(`Codex app-server auth profile "${profileId}" could not refresh. Sign in again with OpenClaw, then retry.`);
1417
1514
  assertCodexOAuthRefreshWorkspace(profileId, refreshedRuntimeCredential, expectedAccountId);
1418
1515
  store.profiles[profileId] = refreshedRuntimeCredential;
1419
1516
  return refreshedRuntimeCredential;
1420
1517
  }
1421
1518
  const resolved = await resolveApiKeyForProfile({
1519
+ cfg: params.config,
1422
1520
  store,
1423
1521
  profileId,
1424
1522
  agentDir: ownerAgentDir,
@@ -1426,7 +1524,7 @@ async function resolveOAuthCredentialForCodexAppServer(profileId, credential, pa
1426
1524
  allowProfileFallback: false,
1427
1525
  ...expectedAccountId ? { validateOAuthCredential: (candidate) => assertCodexOAuthRefreshWorkspace(profileId, candidate, expectedAccountId) } : {}
1428
1526
  });
1429
- if (!resolved || resolved.credential?.type !== "oauth" || !isCodexAppServerAuthProvider(resolved.credential.provider) || !resolved.apiKey.trim()) throw new CodexAppServerAuthProfileUnavailableError(`Codex app-server auth profile "${profileId}" is no longer available. Sign in again with OpenClaw, then retry.`);
1527
+ if (!resolved || resolved.credential?.type !== "oauth" || !isCodexAppServerAuthProvider(resolved.credential.provider) || !resolved.apiKey.trim()) throw new CodexAppServerAuthProfileUnavailableError(`Codex app-server auth profile "${profileId}" could not resolve usable OAuth credentials from its OpenClaw credential store. Run "openclaw doctor" to inspect credential ownership, or select an existing OpenAI profile.`);
1430
1528
  const candidate = {
1431
1529
  ...resolved.credential,
1432
1530
  access: resolved.apiKey
@@ -1470,7 +1568,10 @@ async function resolveScopedOAuthCredential(params) {
1470
1568
  const current = params.store.profiles[params.profileId];
1471
1569
  const credential = current?.type === "oauth" ? current : params.credential;
1472
1570
  if (!params.forceRefresh && hasUsableOAuthCredential(credential)) return credential;
1473
- const refreshed = await refreshOAuthCredentialForRuntime({ credential });
1571
+ const refreshed = await refreshOAuthCredentialForRuntime({
1572
+ credential,
1573
+ cfg: params.config
1574
+ });
1474
1575
  if (!refreshed?.access?.trim()) throw new Error(`Codex app-server auth profile "${params.profileId}" could not refresh. Sign in again with OpenClaw, then retry.`);
1475
1576
  assertCodexOAuthRefreshWorkspace(params.profileId, refreshed, params.expectedAccountId);
1476
1577
  if (!isDeepStrictEqual(params.store.profiles[params.profileId], credential)) throw new Error(`Codex app-server auth profile "${params.profileId}" changed while refreshing. Retry with the newly selected OpenAI profile.`);
@@ -1486,15 +1587,11 @@ async function resolveScopedOAuthCredential(params) {
1486
1587
  }
1487
1588
  function assertCodexOAuthRefreshWorkspace(profileId, credential, expectedAccountId) {
1488
1589
  if (!expectedAccountId) return;
1489
- const loginParams = buildChatgptAuthTokensParams(profileId, credential, credential.access.trim());
1490
- if (loginParams.type !== "chatgptAuthTokens" || loginParams.chatgptAccountId !== expectedAccountId) throw new Error("ChatGPT workspace changed during Codex token refresh. Retry to start a client for the selected workspace.");
1590
+ if (buildChatgptAuthTokensParams(profileId, credential, credential.access.trim()).chatgptAccountId !== expectedAccountId) throw new Error("ChatGPT workspace changed during Codex token refresh. Retry to start a client for the selected workspace.");
1491
1591
  }
1492
1592
  function isCodexAppServerAuthProvider(provider) {
1493
1593
  return provider.trim().toLowerCase() === CODEX_APP_SERVER_AUTH_PROVIDER;
1494
1594
  }
1495
- function isCodexAppServerAuthProfileCredential(credential) {
1496
- return isCodexAppServerAuthProvider(credential.provider);
1497
- }
1498
1595
  function shouldClearOpenAiApiKeyForCodexAuthProfile(params) {
1499
1596
  const profileId = params.authProfileId?.trim();
1500
1597
  return isCodexSubscriptionCredential(profileId ? params.store.profiles[profileId] : params.store.profiles[OPENAI_CODEX_DEFAULT_PROFILE_ID]);
@@ -1503,15 +1600,6 @@ function isCodexSubscriptionCredential(credential) {
1503
1600
  if (!credential || !isCodexAppServerAuthProvider(credential.provider)) return false;
1504
1601
  return credential.type === "oauth" || credential.type === "token";
1505
1602
  }
1506
- function withClearedEnvironmentVariables(startOptions, envVars) {
1507
- const clearEnv = startOptions.clearEnv ?? [];
1508
- const missingEnvVars = envVars.filter((envVar) => !clearEnv.includes(envVar));
1509
- if (missingEnvVars.length === 0) return startOptions;
1510
- return {
1511
- ...startOptions,
1512
- clearEnv: [...clearEnv, ...missingEnvVars]
1513
- };
1514
- }
1515
1603
  function buildChatgptAuthTokensParams(profileId, credential, accessToken) {
1516
1604
  const storedAccountId = resolveExplicitChatgptAccountId(credential);
1517
1605
  const tokenAccountId = resolveOpenAICodexAuthIdentity({ access: accessToken }).accountId;
@@ -1555,7 +1643,7 @@ function createThreadOwnerToken(threadId, onInvalidated) {
1555
1643
  } catch (error) {
1556
1644
  embeddedAgentLog$1.warn("codex thread ownership invalidation failed", {
1557
1645
  threadId,
1558
- reason: formatErrorMessage(error)
1646
+ reason: formatErrorMessage$1(error)
1559
1647
  });
1560
1648
  }
1561
1649
  }
@@ -1601,6 +1689,21 @@ function forgetThreadOwnership(runtime, threadId, owner) {
1601
1689
  if (forgotten) owner.invalidate();
1602
1690
  return forgotten;
1603
1691
  }
1692
+ /** Compaction discards client-authored catalog refreshes, not creation policy. */
1693
+ function revertRetainedThreadSkillsCatalog(runtime, threadId) {
1694
+ const retained = runtime.retainedThreads.get(threadId);
1695
+ if (retained?.ephemeralPolicy) retained.ephemeralPolicy = {
1696
+ ...retained.ephemeralPolicy,
1697
+ skillsInstructions: retained.ephemeralPolicy.nativeSkillsInstructions
1698
+ };
1699
+ }
1700
+ function createCodexEphemeralThreadPolicy({ developerInstructions, skillsInstructions }) {
1701
+ return {
1702
+ developerInstructions,
1703
+ skillsInstructions,
1704
+ nativeSkillsInstructions: skillsInstructions
1705
+ };
1706
+ }
1604
1707
  //#endregion
1605
1708
  //#region extensions/codex/src/app-server/rate-limit-cache.ts
1606
1709
  const DEFAULT_CODEX_RATE_LIMIT_CACHE_MAX_AGE_MS = 6e5;
@@ -1867,7 +1970,7 @@ function scheduleRetainedThreadEviction(client, runtime) {
1867
1970
  runtime.evictionTimer = setTimeout(() => {
1868
1971
  runtime.evictionTimer = void 0;
1869
1972
  evictExpiredRetainedThreads(client, runtime).catch((error) => {
1870
- embeddedAgentLog$1.warn("codex retained thread expiry failed", { reason: formatErrorMessage(error) });
1973
+ embeddedAgentLog$1.warn("codex retained thread expiry failed", { reason: formatErrorMessage$1(error) });
1871
1974
  });
1872
1975
  }, Math.max(0, expiresAt - Date.now()));
1873
1976
  runtime.evictionTimer.unref?.();
@@ -1961,7 +2064,7 @@ async function retainCodexAppServerLiveThread(client, threadId, releaseThread, c
1961
2064
  scheduleRetainedThreadEviction(client, runtime);
1962
2065
  embeddedAgentLog$1.warn("codex retained thread capacity eviction failed", {
1963
2066
  threadId,
1964
- reason: formatErrorMessage(error)
2067
+ reason: formatErrorMessage$1(error)
1965
2068
  });
1966
2069
  return false;
1967
2070
  }
@@ -2065,6 +2168,11 @@ function claimCodexAppServerThreadOwnership(client, runtime, threadId, retained,
2065
2168
  }
2066
2169
  };
2067
2170
  }
2171
+ /** Standalone incognito compaction retains its separately owned subscription. */
2172
+ function revertCodexAppServerLiveThreadSkillsCatalog(client, threadId) {
2173
+ const runtime = configuredClients.get(client);
2174
+ if (runtime && !runtime.closed) revertRetainedThreadSkillsCatalog(runtime, threadId);
2175
+ }
2068
2176
  /** Distinguish active claimed ownership from an already-evicted idle subscription. */
2069
2177
  function hasCodexAppServerLiveThread(client, threadId) {
2070
2178
  return hasThreadOwnership(configuredClients.get(client), threadId);
@@ -2154,25 +2262,156 @@ function protectCodexAppServerLiveThread(client, threadId) {
2154
2262
  evictExcessIdleThreads(client, runtime).catch((error) => {
2155
2263
  embeddedAgentLog$1.warn("codex retained thread unpin eviction failed", {
2156
2264
  threadId,
2157
- reason: formatErrorMessage(error)
2265
+ reason: formatErrorMessage$1(error)
2158
2266
  });
2159
2267
  });
2160
2268
  };
2161
2269
  }
2162
2270
  //#endregion
2271
+ //#region extensions/codex/src/app-server/client-startup-retry.ts
2272
+ /** Recovers physical startup, including acquisitions before thread preparation. */
2273
+ async function withCodexWebSocketOpenRetry(params) {
2274
+ const startedAt = performance.now();
2275
+ for (let attempt = 1;; attempt += 1) try {
2276
+ return await params.start(resolveRemainingAcquireTimeout(params.timeoutMs, startedAt));
2277
+ } catch (error) {
2278
+ if (params.signal.aborted || attempt >= 3 || !isCodexWebSocketOpenFailure(error)) throw error;
2279
+ const remaining = resolveRemainingAcquireTimeout(params.timeoutMs, startedAt);
2280
+ const delay = 1e3 * 2 ** (attempt - 1);
2281
+ await sleepWithAbort(remaining > 0 ? Math.min(delay, remaining) : delay, params.signal);
2282
+ }
2283
+ }
2284
+ function resolveRemainingAcquireTimeout(timeoutMs, startedAt) {
2285
+ if (!(timeoutMs > 0)) return timeoutMs;
2286
+ const remaining = timeoutMs - (performance.now() - startedAt);
2287
+ if (remaining <= 0) throw new CodexAppServerStartupError("timed_out", "codex app-server initialize timed out");
2288
+ return remaining;
2289
+ }
2290
+ async function withCodexAppServerAcquireDeadline(timeoutMs, promise, signal, timeoutMessage = "codex app-server initialize timed out", timeoutErrorFactory) {
2291
+ if (signal?.aborted) throw new CodexAppServerStartupError("aborted", "codex app-server initialize aborted");
2292
+ const timed = withTimeout(promise, timeoutMs, timeoutMessage, () => timeoutErrorFactory?.() ?? new CodexAppServerStartupError("timed_out", timeoutMessage));
2293
+ if (!signal) return await timed;
2294
+ return await new Promise((resolve, reject) => {
2295
+ const onAbort = () => reject(new CodexAppServerStartupError("aborted", "codex app-server initialize aborted"));
2296
+ signal.addEventListener("abort", onAbort, { once: true });
2297
+ timed.then(resolve, reject).finally(() => signal.removeEventListener("abort", onAbort));
2298
+ });
2299
+ }
2300
+ //#endregion
2301
+ //#region extensions/codex/src/app-server/inference-environment.ts
2302
+ function supportsInferenceEnvironment(native) {
2303
+ if (native.CODEX_CA_CERTIFICATE?.trim() || native.SSL_CERT_FILE?.trim()) return false;
2304
+ const names = [
2305
+ "HTTP_PROXY",
2306
+ "HTTPS_PROXY",
2307
+ "ALL_PROXY",
2308
+ "NO_PROXY"
2309
+ ];
2310
+ for (const upper of names) {
2311
+ const lower = upper.toLowerCase();
2312
+ if (native[upper] !== process.env[upper] || native[lower] !== process.env[lower] || native[upper] !== void 0 && native[lower] !== void 0 && native[upper] !== native[lower]) return false;
2313
+ }
2314
+ const value = (name) => (native[name] ?? native[name.toLowerCase()])?.trim() || void 0;
2315
+ const http = value("HTTP_PROXY");
2316
+ const https = value("HTTPS_PROXY");
2317
+ const all = value("ALL_PROXY");
2318
+ if (!http && !https && !all) return true;
2319
+ const noProxy = native.NO_PROXY ?? native.no_proxy ?? "";
2320
+ if (noProxy === "*") return true;
2321
+ if (native.REQUEST_METHOD !== void 0 || names.slice(0, 3).some((name) => {
2322
+ const raw = native[name] ?? native[name.toLowerCase()];
2323
+ return raw !== void 0 && raw !== raw.trim();
2324
+ })) return false;
2325
+ if ((https ?? all) !== (https ?? http ?? all)) return false;
2326
+ const bypasses = noProxy.split(",").map((entry) => entry.trim()).filter(Boolean);
2327
+ if (bypasses.some((entry) => ![
2328
+ "127.0.0.1",
2329
+ "localhost",
2330
+ "::1",
2331
+ "[::1]"
2332
+ ].includes(entry))) return false;
2333
+ if ((http || all) && !bypasses.includes("127.0.0.1")) return false;
2334
+ return /^https?:\/\//.test(https ?? all ?? "");
2335
+ }
2336
+ //#endregion
2337
+ //#region extensions/codex/src/app-server/inference-provider-config.ts
2338
+ function providerKind(name) {
2339
+ if (name === "Amazon Bedrock" || name === "Amazon Bedrock Runtime") return;
2340
+ return name === "OpenAI" ? "openai" : typeof name === "string" && name.toLowerCase() === "azure" ? "azure" : "other";
2341
+ }
2342
+ function hasProviderAws(config, provider) {
2343
+ return readProviderField(config, provider, "aws") != null || Object.keys(config ?? {}).some((key) => key.startsWith(`model_providers.${provider}.aws.`));
2344
+ }
2345
+ function configuredProviders(...configs) {
2346
+ const providers = /* @__PURE__ */ new Set(["openai"]);
2347
+ for (const config of configs) {
2348
+ for (const provider of Object.keys(isJsonObject(config?.model_providers) ? config.model_providers : {})) providers.add(provider);
2349
+ for (const key of Object.keys(config ?? {})) {
2350
+ const provider = /^model_providers\.([^.]+)(?:\.|$)/.exec(key)?.[1];
2351
+ if (provider) providers.add(provider);
2352
+ }
2353
+ }
2354
+ return providers;
2355
+ }
2356
+ function projectProviderRoutes(config, providers) {
2357
+ let projected = config ?? {};
2358
+ for (const [provider, route] of providers) projected = withProviderBaseUrl(projected, provider, route.baseUrl);
2359
+ return projected;
2360
+ }
2361
+ function readProviderBaseUrl(config, provider) {
2362
+ if (provider === "openai") return config?.openai_base_url;
2363
+ return readProviderField(config, provider, "base_url");
2364
+ }
2365
+ function readProviderField(config, provider, field) {
2366
+ const selected = (isJsonObject(config?.model_providers) ? config.model_providers : void 0)?.[provider];
2367
+ const flat = config?.[`model_providers.${provider}`];
2368
+ return config?.[`model_providers.${provider}.${field}`] ?? (isJsonObject(flat) ? flat[field] : void 0) ?? (isJsonObject(selected) ? selected[field] : void 0);
2369
+ }
2370
+ function withProviderBaseUrl(config, provider, baseUrl) {
2371
+ if (provider === "openai") return {
2372
+ ...config,
2373
+ openai_base_url: baseUrl
2374
+ };
2375
+ const providers = isJsonObject(config?.model_providers) ? config.model_providers : {};
2376
+ const selected = providers[provider];
2377
+ const providerKey = `model_providers.${provider}`;
2378
+ const baseUrlKey = `${providerKey}.base_url`;
2379
+ const flat = config?.[providerKey];
2380
+ return {
2381
+ ...config,
2382
+ model_providers: {
2383
+ ...providers,
2384
+ [provider]: {
2385
+ ...isJsonObject(selected) ? selected : {},
2386
+ base_url: baseUrl
2387
+ }
2388
+ },
2389
+ ...isJsonObject(flat) ? { [providerKey]: {
2390
+ ...flat,
2391
+ base_url: baseUrl
2392
+ } } : {},
2393
+ ...config?.[baseUrlKey] !== void 0 ? { [baseUrlKey]: baseUrl } : {}
2394
+ };
2395
+ }
2396
+ //#endregion
2163
2397
  //#region extensions/codex/src/app-server/inference-routing.ts
2164
2398
  const owners = defineCodexBuildState("openclaw.codexAppServerInferenceOwners", () => /* @__PURE__ */ new WeakMap())();
2165
2399
  const MAX_ROUTES = 8;
2166
2400
  const MAX_THREADS = 256;
2167
- const NATIVE_OPENAI_UPSTREAMS = /* @__PURE__ */ new Set(["https://api.openai.com/v1", "https://chatgpt.com/backend-api/codex"]);
2168
2401
  /** Only managed native stdio startup calls this; locality or metadata cannot opt a client in. */
2169
- function ownCodexInferenceClient(client) {
2402
+ function ownCodexInferenceClient(client, startOptions = {}, oauth) {
2170
2403
  if (owners.has(client)) return;
2404
+ if (!supportsInferenceEnvironment(resolveCodexAppServerSpawnEnv(startOptions))) {
2405
+ if (oauth) throw new Error("ChatGPT subscription sharing requires the managed public Responses inference route with a compatible proxy and trust configuration.");
2406
+ return;
2407
+ }
2171
2408
  const owner = {
2172
2409
  closed: false,
2410
+ memoryConfigured: false,
2173
2411
  routes: /* @__PURE__ */ new Map(),
2174
2412
  threads: /* @__PURE__ */ new Map(),
2175
- handles: /* @__PURE__ */ new Set()
2413
+ handles: /* @__PURE__ */ new Map(),
2414
+ oauth
2176
2415
  };
2177
2416
  owners.set(client, owner);
2178
2417
  const close = () => {
@@ -2191,10 +2430,11 @@ function ownCodexInferenceClient(client) {
2191
2430
  });
2192
2431
  }
2193
2432
  async function prepareCodexInferenceRoute(params) {
2194
- const owner = owners.get(params.client);
2433
+ const client = params.client;
2434
+ const owner = owners.get(client);
2195
2435
  if (!owner) return;
2196
2436
  const assertClient = () => {
2197
- if (owner.closed || owners.get(params.client) !== owner) throw new Error("Codex inference route ownership changed; reconnect before retrying");
2437
+ if (owner.closed || owners.get(client) !== owner) throw new Error("Codex inference route ownership changed; reconnect before retrying");
2198
2438
  };
2199
2439
  const assertCurrent = () => {
2200
2440
  assertClient();
@@ -2204,40 +2444,102 @@ async function prepareCodexInferenceRoute(params) {
2204
2444
  assertCurrent();
2205
2445
  const snapshot = params.effectiveConfig ?? await readCodexEffectiveConfig(params.client, params.cwd, { signal: params.signal });
2206
2446
  assertCurrent();
2207
- if (snapshot.config.model_provider != null && snapshot.config.model_provider !== "openai") return;
2208
- if (isJsonObject(snapshot.config.features) && snapshot.config.features.respect_system_proxy === true) return;
2209
- const configured = snapshot.config.openai_base_url;
2447
+ const unsupported = () => {
2448
+ if (owner.oauth) throw new Error("ChatGPT subscription sharing requires the managed public Responses inference route.");
2449
+ };
2450
+ const selectedProvider = params.modelProvider ?? params.config?.model_provider ?? snapshot.config.model_provider ?? "openai";
2451
+ if (owner.oauth && (snapshot.config.model_provider != null && snapshot.config.model_provider !== "openai" || selectedProvider !== "openai" && selectedProvider !== "openclaw_token_sharing")) return unsupported();
2452
+ const provider = owner.oauth ? CODEX_RESPONSES_OAUTH_PROVIDER : selectedProvider;
2453
+ if (typeof provider !== "string" || !provider.trim()) return unsupported();
2454
+ const customProvider = !owner.oauth && provider !== "openai";
2455
+ const providerField = (field) => readProviderField(params.config, provider, field) ?? readProviderField(snapshot.config, provider, field);
2456
+ const nativeProviderName = owner.oauth ? "OpenClaw subscription sharing" : customProvider ? providerField("name") : "OpenAI";
2457
+ const kind = providerKind(nativeProviderName);
2458
+ const wireApi = customProvider ? providerField("wire_api") : "responses";
2459
+ if (!kind || customProvider && ([
2460
+ "amazon-bedrock",
2461
+ "amazon-bedrock-runtime",
2462
+ "ollama",
2463
+ "lmstudio"
2464
+ ].includes(provider) || hasProviderAws(params.config, provider) || hasProviderAws(snapshot.config, provider) || wireApi != null && wireApi !== "responses")) return unsupported();
2465
+ if ((params.config?.["features.respect_system_proxy"] ?? (isJsonObject(params.config?.features) ? params.config.features.respect_system_proxy : void 0) ?? (isJsonObject(snapshot.config.features) ? snapshot.config.features.respect_system_proxy : void 0)) === true) return unsupported();
2466
+ const configured = customProvider ? providerField("base_url") : params.config?.openai_base_url ?? snapshot.config.openai_base_url;
2210
2467
  if (configured != null && typeof configured !== "string") throw new Error("Codex inference upstream configuration is invalid");
2468
+ if (typeof configured === "string" && (!configured.trim() || configured.includes("?") || configured.includes("#"))) return unsupported();
2211
2469
  if (configured) {
2212
2470
  let target;
2213
2471
  try {
2214
2472
  target = new URL(configured);
2215
2473
  } catch {
2216
- return;
2474
+ return unsupported();
2217
2475
  }
2218
- if (!NATIVE_OPENAI_UPSTREAMS.has(target.href.replace(/\/$/, ""))) return;
2476
+ if (target.protocol !== "https:" || target.username || target.password || target.hash || target.search || owner.oauth && target.href.replace(/\/$/, "") !== "https://api.openai.com/v1") return unsupported();
2219
2477
  }
2220
- const origin = snapshot.origins?.openai_base_url;
2221
- if (origin && !CODEX_SESSION_OVERRIDABLE_LAYER_TYPES.has(origin.name.type)) return;
2222
- const account = await params.client.request("account/read", { refreshToken: false }, {
2478
+ if (customProvider && !configured) return unsupported();
2479
+ const configKey = customProvider ? `model_providers.${provider}.base_url` : "openai_base_url";
2480
+ if (Object.entries(snapshot.origins ?? {}).filter(([key]) => customProvider ? key === "model_providers" || key === `model_providers.${provider}` || key === configKey : key === configKey).some(([, origin]) => !origin || !CODEX_SESSION_OVERRIDABLE_LAYER_TYPES.has(origin.name.type))) return unsupported();
2481
+ const account = customProvider ? void 0 : await params.client.request("account/read", { refreshToken: false }, {
2223
2482
  signal: params.signal,
2224
2483
  assertCurrent
2225
2484
  });
2226
2485
  assertCurrent();
2227
- const type = isJsonObject(account.account) ? account.account.type : void 0;
2228
- if (type !== "apiKey" && type !== "chatgpt") return;
2229
- if (owner.authRoute && owner.authRoute !== type) throw new Error("Codex native account route changed; reconnect before retrying");
2230
- owner.authRoute = type;
2486
+ const type = account?.account?.type;
2487
+ if (owner.oauth && type !== "apiKey") return unsupported();
2488
+ if (!customProvider && type !== "apiKey" && type !== "chatgpt") return unsupported();
2489
+ if (!customProvider && owner.authRoute && owner.authRoute !== type) throw new Error("Codex native account route changed; reconnect before retrying");
2490
+ if (type === "apiKey" || type === "chatgpt") owner.authRoute = type;
2231
2491
  const target = new URL(configured || (type === "apiKey" ? "https://api.openai.com/v1" : "https://chatgpt.com/backend-api/codex"));
2232
- const key = target.toString();
2492
+ const { isBlockedHostnameOrIp } = await import("openclaw/plugin-sdk/ssrf-runtime");
2493
+ assertCurrent();
2494
+ if (isBlockedHostnameOrIp(target.hostname)) return unsupported();
2495
+ const nativeBaseUrl = typeof configured === "string" ? configured.toLowerCase() : target.href;
2496
+ const preserveAzureUrlFeatures = typeof nativeProviderName === "string" && nativeProviderName.toLowerCase() === "azure" || [
2497
+ "openai.azure.",
2498
+ "cognitiveservices.azure.",
2499
+ "aoai.azure.",
2500
+ "azure-api.",
2501
+ "azurefd.",
2502
+ "windows.net/openai"
2503
+ ].some((marker) => nativeBaseUrl.includes(marker));
2504
+ const preserveCodexBackendRoutes = nativeProviderName === "OpenAI" && (configured == null || configured.replace(/\/+$/, "").endsWith("/backend-api/codex"));
2505
+ const memoryFeature = params.config?.["features.memories"] ?? (isJsonObject(params.config?.features) ? params.config.features.memories : void 0) ?? (isJsonObject(snapshot.config.features) ? snapshot.config.features.memories : void 0);
2506
+ owner.memoryConfigured ||= memoryFeature === true;
2507
+ const modelPolicyEnforced = params.modelPolicyEnforced !== false;
2508
+ const key = JSON.stringify([
2509
+ provider,
2510
+ target.toString(),
2511
+ kind,
2512
+ preserveAzureUrlFeatures,
2513
+ preserveCodexBackendRoutes,
2514
+ modelPolicyEnforced
2515
+ ]);
2233
2516
  let pending = owner.routes.get(key);
2234
2517
  if (!pending) {
2235
- if (owner.routes.size >= MAX_ROUTES) throw new Error("Codex inference route limit reached");
2236
- pending = import("./inference-proxy-CC15HuSi.mjs").then(({ createCodexInferenceProxy }) => {
2518
+ if (owner.routes.size >= MAX_ROUTES) {
2519
+ if (params.optionalProjection) return unsupported();
2520
+ throw new Error("Codex inference route limit reached; start a fresh managed native connection before retrying.");
2521
+ }
2522
+ pending = Promise.all([
2523
+ import("./inference-proxy-DhcXOgUE.mjs"),
2524
+ import("./native-subagent-monitor-Dpsmf2wz.mjs").then((n) => n.n),
2525
+ import("./inference-dispatch-CMZtjQyz.mjs")
2526
+ ]).then(([{ createCodexInferenceProxy }, native, { createCodexInferenceModelBinding }]) => {
2237
2527
  assertClient();
2238
2528
  return createCodexInferenceProxy({
2239
2529
  upstream: target,
2240
- assertCurrent: assertClient
2530
+ assertCurrent: assertClient,
2531
+ oauth: owner.oauth,
2532
+ preserveAzureUrlFeatures,
2533
+ preserveCodexBackendRoutes,
2534
+ bindModelExecution: createCodexInferenceModelBinding({
2535
+ client,
2536
+ provider,
2537
+ modelPolicyEnforced,
2538
+ assertCurrent: assertClient,
2539
+ memoryConfigured: () => owner.memoryConfigured,
2540
+ captureModelSource: native.codexNativeSubagentMonitorRuntime.captureModelSource,
2541
+ resolveModelThreadId: native.codexNativeSubagentMonitorRuntime.resolveModelThreadId
2542
+ })
2241
2543
  });
2242
2544
  });
2243
2545
  owner.routes.set(key, pending);
@@ -2246,14 +2548,41 @@ async function prepareCodexInferenceRoute(params) {
2246
2548
  assertCurrent();
2247
2549
  route.assertCurrent();
2248
2550
  params.client.protectPrivateTransportSecret(new URL(route.baseUrl).pathname.split("/")[1] ?? "");
2249
- owner.handles.add(route);
2551
+ owner.handles.set(route, {
2552
+ provider,
2553
+ kind,
2554
+ modelPolicyEnforced
2555
+ });
2250
2556
  return route;
2251
2557
  }
2252
2558
  /** Prepare a managed thread without changing an attached or unsupported native profile. */
2253
2559
  async function prepareCodexInferenceThreadConfig(params) {
2254
2560
  const { binding } = params;
2255
- if (binding?.connectionScope === "supervision" || binding?.preserveNativeModel === true) return;
2256
- const route = await prepareCodexInferenceRoute(params);
2561
+ const owner = owners.get(params.client);
2562
+ if (!owner) return;
2563
+ if (owner.closed) throw new Error("Codex inference route ownership changed; reconnect before retrying");
2564
+ const preserved = binding?.connectionScope === "supervision" || binding?.preserveNativeModel === true;
2565
+ let retained = preserved && binding?.clientId === params.clientId ? owner.threads.get(binding.threadId) : void 0;
2566
+ if (preserved) {
2567
+ if (owner.oauth) throw new Error("ChatGPT subscription sharing cannot attach to a native Codex thread.");
2568
+ if (!retained) return;
2569
+ retained.route.assertCurrent();
2570
+ if (owner.handles.get(retained.route)?.modelPolicyEnforced !== (params.modelPolicyEnforced !== false)) retained = void 0;
2571
+ else if (!params.operatorBacked) return {
2572
+ route: retained.route,
2573
+ providers: retained.providers,
2574
+ config: projectProviderRoutes(params.config, retained.providers)
2575
+ };
2576
+ }
2577
+ params.signal?.throwIfAborted();
2578
+ params.assertCurrent();
2579
+ const effectiveConfig = params.effectiveConfig ?? await readCodexEffectiveConfig(params.client, params.cwd, { signal: params.signal });
2580
+ params.signal?.throwIfAborted();
2581
+ params.assertCurrent();
2582
+ const route = retained?.route ?? await prepareCodexInferenceRoute({
2583
+ ...params,
2584
+ effectiveConfig
2585
+ });
2257
2586
  if (!route) return;
2258
2587
  if (binding?.clientId === params.clientId && !getCodexInferenceThread(params.client, binding.threadId)) {
2259
2588
  const { thread } = await params.client.request("thread/read", {
@@ -2266,23 +2595,65 @@ async function prepareCodexInferenceThreadConfig(params) {
2266
2595
  params.assertCurrent();
2267
2596
  if (thread.id !== binding.threadId || thread.status?.type !== "notLoaded") throw new Error("Codex loaded thread has no owned inference route; reconnect before retrying");
2268
2597
  }
2269
- if (params.config?.openai_base_url !== void 0 && params.config.openai_base_url !== route.upstream) throw new Error("Codex thread configuration conflicts with its trusted inference upstream");
2270
- return {
2598
+ const provider = owner.handles.get(route)?.provider;
2599
+ if (!provider) throw new Error("Codex inference provider ownership changed");
2600
+ if (owner.oauth) return {
2271
2601
  route,
2272
2602
  config: {
2273
2603
  ...params.config,
2274
- openai_base_url: route.baseUrl
2604
+ model_provider: CODEX_RESPONSES_OAUTH_PROVIDER,
2605
+ model_providers: { [CODEX_RESPONSES_OAUTH_PROVIDER]: responsesOAuthProvider(route) }
2275
2606
  }
2276
2607
  };
2608
+ if (!params.operatorBacked) return {
2609
+ route,
2610
+ config: withProviderBaseUrl(params.config, provider, route.baseUrl)
2611
+ };
2612
+ const providers = new Map(retained?.providers ?? [[provider, route]]);
2613
+ for (const candidate of configuredProviders(effectiveConfig.config, params.config)) {
2614
+ if (providers.has(candidate)) continue;
2615
+ const sibling = await prepareCodexInferenceRoute({
2616
+ ...params,
2617
+ effectiveConfig,
2618
+ modelProvider: candidate,
2619
+ optionalProjection: true
2620
+ });
2621
+ if (sibling) providers.set(candidate, sibling);
2622
+ }
2623
+ return {
2624
+ route,
2625
+ config: projectProviderRoutes(params.config, providers),
2626
+ providers
2627
+ };
2628
+ }
2629
+ function responsesOAuthProvider(route) {
2630
+ return {
2631
+ name: "OpenClaw subscription sharing",
2632
+ base_url: route.baseUrl,
2633
+ wire_api: "responses",
2634
+ requires_openai_auth: true,
2635
+ supports_websockets: false
2636
+ };
2277
2637
  }
2278
2638
  /** Validate the exact private handle and unchanged upstream, not a localhost string exception. */
2279
- function assertCodexInferenceRouteConfig(client, route, config) {
2639
+ function assertCodexInferenceRouteConfig(client, route, config, modelProvider, providers) {
2280
2640
  if (!route) return;
2281
2641
  const owner = owners.get(client);
2282
- if (!owner || owner.closed || !owner.handles.has(route) || config?.openai_base_url !== route.baseUrl) throw new Error("Codex parent-local inference route was overridden; no turn was sent");
2642
+ const provider = (owner?.handles.get(route))?.provider;
2643
+ const selectedProvider = modelProvider ?? config?.model_provider ?? provider;
2644
+ const systemProxy = config?.["features.respect_system_proxy"] ?? (isJsonObject(config?.features) ? config.features.respect_system_proxy : void 0);
2645
+ if (!owner || owner.closed || !provider || selectedProvider !== provider || systemProxy === true || readProviderBaseUrl(config, provider) !== route.baseUrl) throw new Error("Codex parent-local inference route was overridden; no turn was sent");
2646
+ if (owner.oauth && (config?.model_provider !== "openclaw_token_sharing" || !isJsonObject(config?.model_providers) || !isDeepStrictEqual(config.model_providers["openclaw_token_sharing"], responsesOAuthProvider(route)) || Object.keys(config).some((key) => key.startsWith(`model_providers.openclaw_token_sharing`)))) throw new Error("Codex parent-local inference route was overridden; no turn was sent");
2283
2647
  route.assertCurrent();
2648
+ for (const [candidate, sibling] of providers ?? [[provider, route]]) {
2649
+ const siblingDefinition = owner.handles.get(sibling);
2650
+ const name = readProviderField(config, candidate, "name");
2651
+ const wireApi = readProviderField(config, candidate, "wire_api");
2652
+ if (siblingDefinition?.provider !== candidate || readProviderBaseUrl(config, candidate) !== sibling.baseUrl || candidate !== "openai" && (name !== void 0 && providerKind(name) !== siblingDefinition.kind || wireApi !== void 0 && wireApi !== "responses" || hasProviderAws(config, candidate))) throw new Error("Codex native provider inference route was overridden; no turn was sent");
2653
+ sibling.assertCurrent();
2654
+ }
2284
2655
  }
2285
- function bindCodexInferenceThread(client, threadId, route) {
2656
+ function bindCodexInferenceThread(client, threadId, route, providers) {
2286
2657
  const owner = owners.get(client);
2287
2658
  if (!owner && !route) return;
2288
2659
  if (!owner || owner.closed) throw new Error("Codex inference client is closed");
@@ -2291,30 +2662,53 @@ function bindCodexInferenceThread(client, threadId, route) {
2291
2662
  return;
2292
2663
  }
2293
2664
  route.assertCurrent();
2665
+ const provider = owner.handles.get(route)?.provider;
2666
+ if (!provider) throw new Error("Codex inference provider ownership changed");
2294
2667
  if (!owner.threads.has(threadId) && owner.threads.size >= MAX_THREADS) throw new Error("Codex inference thread limit reached; reconnect before retrying");
2295
- owner.threads.set(threadId, route);
2668
+ const projected = new Map(providers ?? [[provider, route]]);
2669
+ if (projected.get(provider) !== route) throw new Error("Codex inference provider ownership changed");
2670
+ const assertCurrent = () => {
2671
+ if (owner.closed || owners.get(client) !== owner) throw new Error("Codex inference client is closed");
2672
+ for (const [candidate, routed] of projected) {
2673
+ if (owner.handles.get(routed)?.provider !== candidate) throw new Error("Codex inference provider ownership changed");
2674
+ routed.assertCurrent();
2675
+ }
2676
+ };
2677
+ assertCurrent();
2678
+ const qualification = owner.handles.get(route)?.modelPolicyEnforced ? Object.freeze({
2679
+ assertCurrent,
2680
+ hasProvider: (candidate) => {
2681
+ assertCurrent();
2682
+ const projectedRoute = projected.get(candidate);
2683
+ return projectedRoute !== void 0 && owner.handles.get(projectedRoute)?.modelPolicyEnforced === true;
2684
+ }
2685
+ }) : void 0;
2686
+ owner.threads.set(threadId, {
2687
+ route,
2688
+ providers: projected,
2689
+ qualification
2690
+ });
2296
2691
  }
2297
2692
  function getCodexInferenceThread(client, threadId) {
2298
2693
  const owner = owners.get(client);
2299
2694
  if (owner?.closed) throw new Error("Codex inference client is closed");
2300
- return owner?.threads.get(threadId);
2695
+ return owner?.threads.get(threadId)?.route;
2696
+ }
2697
+ /** Configuration provenance for native restore admission, independent of the input's source. */
2698
+ function getCodexInferenceThreadQualification(client, threadId) {
2699
+ const owner = owners.get(client);
2700
+ if (owner?.closed) throw new Error("Codex inference client is closed");
2701
+ return owner?.threads.get(threadId)?.qualification;
2301
2702
  }
2302
2703
  //#endregion
2303
2704
  //#region extensions/codex/src/app-server/native-config-fence.ts
2705
+ /** Serializes this Gateway's native config writes with its config-loading requests. */
2304
2706
  const CODEX_NATIVE_CONFIG_FENCE_STATE = Symbol.for("openclaw.codexNativeConfigFenceState");
2305
- function getFenceState() {
2306
- const globalState = globalThis;
2307
- globalState[CODEX_NATIVE_CONFIG_FENCE_STATE] ??= /* @__PURE__ */ new Map();
2308
- return globalState[CODEX_NATIVE_CONFIG_FENCE_STATE];
2309
- }
2310
2707
  /** Acquires the per-CODEX_HOME fence and returns an idempotent release. */
2311
2708
  async function acquireCodexNativeConfigFence(key, options = {}) {
2312
- const state = getFenceState();
2709
+ const state = resolveGlobalMap(CODEX_NATIVE_CONFIG_FENCE_STATE);
2313
2710
  const previous = state.get(key) ?? Promise.resolve();
2314
- let resolveCurrent = () => void 0;
2315
- const current = new Promise((resolve) => {
2316
- resolveCurrent = resolve;
2317
- });
2711
+ const { promise: current, resolve: resolveCurrent } = createDeferred();
2318
2712
  state.set(key, current);
2319
2713
  try {
2320
2714
  await waitForPreviousFence(previous, options);
@@ -2407,9 +2801,14 @@ function resolveCodexAppServerSpawnIdentity(startOptions, resolvedNativeCommand)
2407
2801
  }
2408
2802
  //#endregion
2409
2803
  //#region extensions/codex/src/app-server/thread-lifecycle-errors.ts
2804
+ const CODEX_APP_SERVER_CONTEXT_RESTART_SELECTION_CHANGED = "CODEX_APP_SERVER_CONTEXT_RESTART_SELECTION_CHANGED";
2805
+ /** True when a pre-write context restart must replay on the newly selected owner. */
2806
+ function isCodexContextRestartSelectionChangedError(error) {
2807
+ return error instanceof Error && "code" in error && error.code === "CODEX_APP_SERVER_CONTEXT_RESTART_SELECTION_CHANGED";
2808
+ }
2410
2809
  var CodexThreadStartRequestError = class extends Error {
2411
2810
  constructor(cause) {
2412
- super(`thread/start: ${formatErrorMessage(cause)}`, { cause });
2811
+ super(`thread/start: ${formatErrorMessage$1(cause)}`, { cause });
2413
2812
  this.name = "CodexThreadStartRequestError";
2414
2813
  }
2415
2814
  };
@@ -2433,10 +2832,6 @@ var CodexAdoptedThreadActiveError = class extends AgentHarnessPreflightError$1 {
2433
2832
  };
2434
2833
  //#endregion
2435
2834
  //#region extensions/codex/src/app-server/shared-client.ts
2436
- /**
2437
- * Owns shared and isolated Codex app-server client startup, auth application,
2438
- * lease tracking, and teardown.
2439
- */
2440
2835
  var shared_client_exports = /* @__PURE__ */ __exportAll({
2441
2836
  assertCodexAppServerClientStartSelectionCurrent: () => assertCodexAppServerClientStartSelectionCurrent,
2442
2837
  captureCodexAppServerClientLifetime: () => captureCodexAppServerClientLifetime,
@@ -2455,7 +2850,6 @@ var shared_client_exports = /* @__PURE__ */ __exportAll({
2455
2850
  releaseCodexAppServerClientLease: () => releaseCodexAppServerClientLease,
2456
2851
  releaseLeasedSharedCodexAppServerClient: () => releaseLeasedSharedCodexAppServerClient,
2457
2852
  resolveCodexNativeConfigFenceKey: () => resolveCodexNativeConfigFenceKey,
2458
- retainSharedCodexAppServerClientByInstanceId: () => retainSharedCodexAppServerClientByInstanceId,
2459
2853
  retainSharedCodexAppServerClientIfCurrent: () => retainSharedCodexAppServerClientIfCurrent,
2460
2854
  retireSharedCodexAppServerClientIfCurrent: () => retireSharedCodexAppServerClientIfCurrent,
2461
2855
  waitForCodexAppServerClientDesktopGenerationDrain: () => waitForCodexAppServerClientDesktopGenerationDrain,
@@ -2463,12 +2857,6 @@ var shared_client_exports = /* @__PURE__ */ __exportAll({
2463
2857
  });
2464
2858
  const SHARED_CODEX_APP_SERVER_CLIENT_DISPOSER = codexBuildSymbol("openclaw.codexAppServerClientDisposer");
2465
2859
  const CODEX_APP_SERVER_INITIALIZE_TIMEOUT_MESSAGE = "codex app-server initialize timed out";
2466
- function ownCodexStartup(lifetime, operation) {
2467
- lifetime.pending.add(operation);
2468
- const release = () => lifetime.pending.delete(operation);
2469
- operation.then(release, release);
2470
- return operation;
2471
- }
2472
2860
  async function prepareCodexAppServerClient(options) {
2473
2861
  const lifetime = getSharedCodexAppServerClientState().startup;
2474
2862
  const abandonSignal = options?.abandonSignal ? AbortSignal.any([lifetime.controller.signal, options.abandonSignal]) : lifetime.controller.signal;
@@ -2497,11 +2885,9 @@ function readCodexAppServerClientProcessIdentity(client) {
2497
2885
  ...runtimeIdentity?.userAgent ? { userAgent: runtimeIdentity.userAgent } : {}
2498
2886
  };
2499
2887
  }
2500
- /** Returns the lifecycle fingerprint that owns a managed desktop client. */
2501
2888
  function readCodexAppServerClientDesktopGenerationFingerprint(client) {
2502
2889
  return readCodexAppServerClientDesktopGeneration(client)?.fingerprint;
2503
2890
  }
2504
- /** Returns the lifecycle generation that owns a managed desktop client. */
2505
2891
  function readCodexAppServerClientDesktopGeneration(client) {
2506
2892
  return getSharedCodexAppServerClientState().startMetadata.get(client)?.desktopGeneration;
2507
2893
  }
@@ -2548,19 +2934,14 @@ function assertCodexAppServerClientStartSelectionCurrent(params) {
2548
2934
  });
2549
2935
  if ((metadata.startOptions.managedCommandOrder ?? "package-first") !== (current.managedCommandOrder ?? "package-first")) throw new CodexAppServerStartSelectionChangedError();
2550
2936
  }
2551
- /** Resolves the per-CODEX_HOME key used to serialize native config loading. */
2552
2937
  function resolveCodexNativeConfigFenceKey(params) {
2553
2938
  const metadata = params.client ? getSharedCodexAppServerClientState().startMetadata.get(params.client) : void 0;
2554
2939
  const startOptions = metadata?.startOptions ?? params.startOptions;
2555
2940
  if (!startOptions || startOptions.transport !== "stdio") return;
2556
- const configuredHome = startOptions.env?.CODEX_HOME?.trim();
2941
+ const configuredHome = startOptions.codexHome ?? startOptions.env?.CODEX_HOME?.trim();
2557
2942
  const codexHome = configuredHome ? configuredHome : startOptions.homeScope === "user" ? resolveCodexAppServerUserHomeDir() : resolveCodexAppServerHomeDir(params.agentDir ?? metadata?.agentDir ?? resolveDefaultAgentDir(params.config ?? {}));
2558
2943
  return codexHome ? `codex-home:${path.resolve(codexHome)}` : void 0;
2559
2944
  }
2560
- function inferAuthRequirement(preparedAuth) {
2561
- if (preparedAuth?.kind === "api-key") return "api-key";
2562
- return preparedAuth?.kind === "profile" ? "subscription" : void 0;
2563
- }
2564
2945
  async function resolveCodexAppServerClientStartContext(options) {
2565
2946
  const requestedStartOptions = options?.startOptions ?? resolveCodexAppServerRuntimeOptions({ pluginConfig: options?.pluginConfig }).start;
2566
2947
  const agentDir = options?.agentDir ?? (requestedStartOptions.homeScope === "user" ? void 0 : resolveDefaultAgentDir(options?.config ?? {}));
@@ -2568,12 +2949,12 @@ async function resolveCodexAppServerClientStartContext(options) {
2568
2949
  const preparedAuth = options?.preparedAuth;
2569
2950
  const preparedApiKey = preparedAuth?.kind === "api-key" ? preparedAuth.apiKey.trim() : void 0;
2570
2951
  if (preparedAuth && options?.authProfileId !== void 0) throw new Error("Prepared Codex auth cannot also select a legacy auth profile.");
2571
- if (preparedAuth?.kind === "profile" && !preparedAuth.store.profiles[preparedAuth.profileId]) throw new Error(`Prepared Codex auth profile "${preparedAuth.profileId}" was not found. Select an existing OpenAI profile or sign in again with OpenClaw, then retry.`);
2952
+ if (preparedAuth?.kind === "profile" && !preparedAuth.store.profiles[preparedAuth.profileId]) throw new CodexAppServerAuthProfileUnavailableError(formatCodexAuthProfileUnavailableMessage(preparedAuth.profileId));
2572
2953
  if (preparedAuth?.kind === "api-key" && !preparedApiKey) throw new Error("Prepared Codex API-key auth is missing its resolved key.");
2573
2954
  if (preparedAuth && requestedStartOptions.homeScope === "user") throw new Error("Prepared Codex auth requires an isolated app-server home.");
2574
- const preparedAuthRequirement = inferAuthRequirement(preparedAuth);
2955
+ const preparedAuthRequirement = preparedAuth && (preparedAuth.kind === "api-key" || isCodexResponsesOAuth(preparedAuth) ? "api-key" : "subscription");
2575
2956
  if (options?.authRequirement && preparedAuthRequirement && options.authRequirement !== preparedAuthRequirement) throw new Error("Prepared Codex auth does not satisfy the requested auth requirement.");
2576
- const authRequirement = options?.authRequirement ?? preparedAuthRequirement;
2957
+ let authRequirement = options?.authRequirement ?? preparedAuthRequirement;
2577
2958
  const usesNativeAuth = !preparedAuth && (options?.authProfileId === null || requestedStartOptions.homeScope === "user");
2578
2959
  const requestedAuthProfileId = preparedAuth?.kind === "profile" ? preparedAuth.profileId : options?.authProfileId ?? void 0;
2579
2960
  const authProfileStore = preparedAuth?.kind === "profile" ? preparedAuth.store : !usesNativeAuth && preparedAuth?.kind !== "api-key" ? resolveCodexAppServerAuthProfileStore({
@@ -2594,7 +2975,7 @@ async function resolveCodexAppServerClientStartContext(options) {
2594
2975
  agentDir,
2595
2976
  config: options?.config
2596
2977
  }) : void 0;
2597
- if (preparedAuth?.kind === "profile" && !preparedAuthProfileSnapshot) throw new Error(`Prepared Codex auth profile "${preparedAuth.profileId}" is unusable. Repair or replace the selected OpenAI profile, then retry.`);
2978
+ if (preparedAuth?.kind === "profile" && !preparedAuthProfileSnapshot) throw new CodexAppServerAuthProfileUnavailableError(`Prepared Codex auth profile "${preparedAuth.profileId}" is unusable. Repair or replace the selected OpenAI profile, then retry.`);
2598
2979
  const resolvedPreparedAuth = preparedAuth?.kind === "api-key" ? {
2599
2980
  kind: "api-key",
2600
2981
  apiKey: preparedApiKey
@@ -2604,10 +2985,25 @@ async function resolveCodexAppServerClientStartContext(options) {
2604
2985
  store: authProfileStore,
2605
2986
  snapshot: preparedAuthProfileSnapshot
2606
2987
  } : void 0;
2988
+ if (isCodexResponsesOAuth(resolvedPreparedAuth)) {
2989
+ if (authRequirement && authRequirement !== "api-key") throw new Error("ChatGPT subscription sharing requires the public OpenAI API route.");
2990
+ authRequirement = "api-key";
2991
+ }
2607
2992
  const agentStartOptions = resolveCodexAppServerStartOptionsForAgent({
2608
2993
  startOptions: requestedStartOptions,
2609
2994
  agentDir
2610
2995
  });
2996
+ const startOptions = await bridgeCodexAppServerStartOptions({
2997
+ startOptions: await resolveManagedCodexAppServerStartOptions(agentStartOptions),
2998
+ agentId: options?.agentId,
2999
+ agentDir,
3000
+ authProfileId: usesNativeAuth || preparedAuth?.kind === "api-key" ? null : authProfileId,
3001
+ ...(preparedAuth || isCodexResponsesOAuth(resolvedPreparedAuth)) && resolvedPreparedAuth ? { preparedAuth: resolvedPreparedAuth } : {},
3002
+ authRequirement,
3003
+ config: options?.config,
3004
+ pluginConfig: options?.pluginConfig,
3005
+ ...authProfileStore ? { authProfileStore } : {}
3006
+ });
2611
3007
  return {
2612
3008
  agentDir,
2613
3009
  usesNativeAuth,
@@ -2616,17 +3012,7 @@ async function resolveCodexAppServerClientStartContext(options) {
2616
3012
  requestedStartOptions,
2617
3013
  preparedAuth: resolvedPreparedAuth,
2618
3014
  authRequirement,
2619
- startOptions: await bridgeCodexAppServerStartOptions({
2620
- startOptions: await resolveManagedCodexAppServerStartOptions(agentStartOptions),
2621
- agentId: options?.agentId,
2622
- agentDir,
2623
- authProfileId: usesNativeAuth || preparedAuth?.kind === "api-key" ? null : authProfileId,
2624
- ...preparedAuth && resolvedPreparedAuth ? { preparedAuth: resolvedPreparedAuth } : {},
2625
- authRequirement,
2626
- config: options?.config,
2627
- pluginConfig: options?.pluginConfig,
2628
- ...authProfileStore ? { authProfileStore } : {}
2629
- }),
3015
+ startOptions,
2630
3016
  ...options?.pluginConfig !== void 0 ? { pluginConfig: options.pluginConfig } : {},
2631
3017
  ...desktopGeneration ? { desktopGeneration } : {}
2632
3018
  };
@@ -2644,7 +3030,6 @@ function getSharedCodexAppServerClient(options) {
2644
3030
  function getLeasedSharedCodexAppServerClient(options) {
2645
3031
  return acquireSharedCodexAppServerClient(options, true);
2646
3032
  }
2647
- /** Releases one outstanding lease for a shared Codex app-server client. */
2648
3033
  function releaseLeasedSharedCodexAppServerClient(client) {
2649
3034
  const entry = getSharedCodexAppServerClientState().entriesByClient.get(client);
2650
3035
  if (!entry || entry.anonymousLeases === 0) return false;
@@ -2716,7 +3101,8 @@ async function acquireSharedCodexAppServerClient(options, leased = false) {
2716
3101
  const state = getSharedCodexAppServerClientState();
2717
3102
  const { context, lifetime, abandonSignal, startedAt, assertCurrent } = await prepareCodexAppServerClient(options);
2718
3103
  assertCurrent();
2719
- const { agentDir, usesNativeAuth, authProfileId, authProfileStore, preparedAuth, authRequirement, requestedStartOptions, startOptions, desktopGeneration, pluginConfig } = context;
3104
+ const { usesNativeAuth, ...startContext } = context;
3105
+ const { agentDir, authProfileId, authProfileStore, preparedAuth, authRequirement, startOptions, desktopGeneration } = startContext;
2720
3106
  const remainingTimeoutMs = resolveRemainingAcquireTimeout(timeoutMs, startedAt);
2721
3107
  const authIdentityCacheKey = preparedAuth?.kind === "api-key" ? resolveCodexAppServerPreparedApiKeyCacheKey(preparedAuth.apiKey) : preparedAuth?.snapshot.secretFreeCacheKey ?? (authRequirement === "api-key" && !authProfileId ? resolveCodexAppServerFallbackApiKeyCacheKey({ startOptions }) : void 0);
2722
3108
  const baseKey = `${codexAppServerStartOptionsKey(startOptions, {
@@ -2758,17 +3144,10 @@ async function acquireSharedCodexAppServerClient(options, leased = false) {
2758
3144
  if (options.abandonSignal.aborted) abandon();
2759
3145
  }
2760
3146
  const startup = entry.startup ?? (entry.startup = createSharedCodexAppServerClientStartup({
3147
+ ...startContext,
2761
3148
  lifetime,
2762
3149
  entry,
2763
- requestedStartOptions,
2764
- startOptions,
2765
- desktopGeneration,
2766
- ...pluginConfig !== void 0 ? { pluginConfig } : {},
2767
- agentDir,
2768
3150
  authProfileId: usesNativeAuth || preparedAuth?.kind === "api-key" ? null : authProfileId,
2769
- authProfileStore,
2770
- preparedAuth,
2771
- authRequirement,
2772
3151
  runtimeArtifactMode,
2773
3152
  ...options?.expectedRuntimeArtifact ? { expectedRuntimeArtifact: options.expectedRuntimeArtifact } : {},
2774
3153
  abandonSignal: entry.startupAbort.signal,
@@ -2782,7 +3161,7 @@ async function acquireSharedCodexAppServerClient(options, leased = false) {
2782
3161
  agentDir,
2783
3162
  authProfileId: usesNativeAuth ? void 0 : authProfileId,
2784
3163
  ...authProfileStore ? { authProfileStore } : {},
2785
- authMode: preparedAuth?.kind === "api-key" ? "prepared-api-key" : "profile",
3164
+ authMode: preparedAuth?.kind === "api-key" || isCodexResponsesOAuth(preparedAuth) ? "prepared-api-key" : "profile",
2786
3165
  config: options?.config
2787
3166
  });
2788
3167
  if (leased) {
@@ -2793,6 +3172,7 @@ async function acquireSharedCodexAppServerClient(options, leased = false) {
2793
3172
  } catch (error) {
2794
3173
  releasePendingAcquire();
2795
3174
  retirePendingSharedClientEntryIfUnclaimed(entry);
3175
+ await waitForUnclaimedSharedClientStartup(entry);
2796
3176
  throw error;
2797
3177
  } finally {
2798
3178
  cleanupAbandonSignal?.();
@@ -2800,30 +3180,17 @@ async function acquireSharedCodexAppServerClient(options, leased = false) {
2800
3180
  releasePendingAcquire();
2801
3181
  }
2802
3182
  }
2803
- async function withCodexAppServerAcquireDeadline(timeoutMs, promise, signal, timeoutMessage = CODEX_APP_SERVER_INITIALIZE_TIMEOUT_MESSAGE, timeoutErrorFactory) {
2804
- if (signal?.aborted) throw new CodexAppServerStartupError("aborted", "codex app-server initialize aborted");
2805
- const timed = withTimeout(promise, timeoutMs, timeoutMessage, () => timeoutErrorFactory?.() ?? new CodexAppServerStartupError("timed_out", timeoutMessage));
2806
- if (!signal) return await timed;
2807
- return await new Promise((resolve, reject) => {
2808
- const onAbort = () => reject(new CodexAppServerStartupError("aborted", "codex app-server initialize aborted"));
2809
- signal.addEventListener("abort", onAbort, { once: true });
2810
- timed.then(resolve, reject).finally(() => signal.removeEventListener("abort", onAbort));
2811
- });
2812
- }
2813
3183
  function buildCodexAppServerInitializeTimeoutError(client) {
2814
3184
  const stderr = client?.getStderrDiagnostic();
2815
3185
  return new CodexAppServerStartupError("timed_out", stderr ? `${CODEX_APP_SERVER_INITIALIZE_TIMEOUT_MESSAGE}; stderr=${JSON.stringify(stderr)}` : CODEX_APP_SERVER_INITIALIZE_TIMEOUT_MESSAGE);
2816
3186
  }
2817
- function resolveRemainingAcquireTimeout(timeoutMs, startedAt) {
2818
- if (!(timeoutMs > 0)) return timeoutMs;
2819
- const remaining = timeoutMs - (performance.now() - startedAt);
2820
- if (remaining <= 0) throw new CodexAppServerStartupError("timed_out", "codex app-server initialize timed out");
2821
- return remaining;
2822
- }
2823
3187
  function createSharedCodexAppServerClientStartup(params) {
2824
3188
  const initialized = createDeferred();
2825
3189
  const ready = ownCodexStartup(params.lifetime, startInitializedCodexAppServerClient({
2826
3190
  ...params,
3191
+ onStartingClient: (starting) => {
3192
+ params.entry.startupTransport = starting;
3193
+ },
2827
3194
  onStartedClient: (startedClient) => {
2828
3195
  const state = getSharedCodexAppServerClientState();
2829
3196
  if (params.entry.client) state.entriesByClient.delete(params.entry.client);
@@ -2863,18 +3230,11 @@ async function createIsolatedCodexAppServerClient(options) {
2863
3230
  const { context, lifetime, abandonSignal, startedAt, assertCurrent } = await prepareCodexAppServerClient(options);
2864
3231
  assertCurrent();
2865
3232
  const timeoutMs = options?.timeoutMs ?? 0;
2866
- const { agentDir, usesNativeAuth, authProfileId, authProfileStore, preparedAuth, authRequirement, requestedStartOptions, startOptions, desktopGeneration, pluginConfig } = context;
3233
+ const { usesNativeAuth, ...startContext } = context;
2867
3234
  return await ownCodexStartup(lifetime, startInitializedCodexAppServerClient({
3235
+ ...startContext,
2868
3236
  lifetime,
2869
- requestedStartOptions,
2870
- startOptions,
2871
- ...desktopGeneration ? { desktopGeneration } : {},
2872
- ...pluginConfig !== void 0 ? { pluginConfig } : {},
2873
- agentDir,
2874
- authProfileId: usesNativeAuth || preparedAuth?.kind === "api-key" ? null : authProfileId,
2875
- authProfileStore,
2876
- preparedAuth,
2877
- authRequirement,
3237
+ authProfileId: usesNativeAuth || context.preparedAuth?.kind === "api-key" ? null : context.authProfileId,
2878
3238
  runtimeArtifactMode: options?.runtimeArtifactMode ?? (options?.expectedRuntimeArtifact ? "capture" : void 0),
2879
3239
  ...options?.expectedRuntimeArtifact ? { expectedRuntimeArtifact: options.expectedRuntimeArtifact } : {},
2880
3240
  config: options?.config,
@@ -2895,7 +3255,17 @@ function trackIsolatedCodexAppServerClient(client) {
2895
3255
  notifyDesktopGenerationDrainChecks(state);
2896
3256
  });
2897
3257
  }
2898
- async function startInitializedCodexAppServerClient(params) {
3258
+ function startInitializedCodexAppServerClient(params) {
3259
+ return withCodexWebSocketOpenRetry({
3260
+ timeoutMs: params.timeoutMs ?? 0,
3261
+ signal: params.abandonSignal ? AbortSignal.any([params.lifetime.controller.signal, params.abandonSignal]) : params.lifetime.controller.signal,
3262
+ start: (timeoutMs) => startInitializedCodexAppServerClientOnce({
3263
+ ...params,
3264
+ timeoutMs
3265
+ })
3266
+ });
3267
+ }
3268
+ async function startInitializedCodexAppServerClientOnce(params) {
2899
3269
  const acquireStartedAt = performance.now();
2900
3270
  const timeoutMs = params.timeoutMs ?? 0;
2901
3271
  const abandonSignal = params.abandonSignal ? AbortSignal.any([params.lifetime.controller.signal, params.abandonSignal]) : params.lifetime.controller.signal;
@@ -2906,7 +3276,8 @@ async function startInitializedCodexAppServerClient(params) {
2906
3276
  const startOptionsCandidates = resolveManagedFallbackStartOptions(params.startOptions);
2907
3277
  for (const [index, startOptions] of startOptionsCandidates.entries()) {
2908
3278
  params.assertCurrent?.();
2909
- const desktopGeneration = params.desktopGeneration ?? (isManagedCodexDesktopCommand(startOptions.command) ? await waitForStartup(waitForCodexDesktopGeneration) : void 0);
3279
+ const desktopCommand = isManagedCodexDesktopCommand(startOptions.command);
3280
+ const desktopGeneration = params.desktopGeneration ?? (desktopCommand ? await waitForStartup(waitForCodexDesktopGeneration) : void 0);
2910
3281
  const assertStartupCurrent = () => {
2911
3282
  params.assertCurrent?.();
2912
3283
  if (abandonSignal.aborted) throw new CodexAppServerStartupError("aborted", "codex app-server initialize aborted");
@@ -2941,7 +3312,7 @@ async function startInitializedCodexAppServerClient(params) {
2941
3312
  } finally {
2942
3313
  artifactDrain?.cancel();
2943
3314
  }
2944
- const runtimeArtifactModule = params.runtimeArtifactMode ? await import("./runtime-artifact-Dy38Z5iU.mjs") : void 0;
3315
+ const runtimeArtifactModule = params.runtimeArtifactMode ? await import("./runtime-artifact-DDQ-HGXf.mjs") : void 0;
2945
3316
  const runtimeArtifactBeforeStart = runtimeArtifactModule ? await runtimeArtifactModule.captureCodexAppServerRuntimeArtifactBeforeStart({
2946
3317
  startOptions,
2947
3318
  spawnIdentity: resolveCodexAppServerSpawnIdentity(startOptions),
@@ -2955,14 +3326,21 @@ async function startInitializedCodexAppServerClient(params) {
2955
3326
  let starting;
2956
3327
  let client;
2957
3328
  try {
2958
- client = await waitForStartup(() => starting = CodexAppServerClient.start(startOptions, () => {
2959
- assertStartupCurrent();
2960
- resolveRemainingAcquireTimeout(timeoutMs, acquireStartedAt);
2961
- }));
3329
+ client = await waitForStartup(() => {
3330
+ starting = CodexAppServerClient.start(startOptions, () => {
3331
+ assertStartupCurrent();
3332
+ resolveRemainingAcquireTimeout(timeoutMs, acquireStartedAt);
3333
+ });
3334
+ params.onStartingClient?.(starting);
3335
+ return starting;
3336
+ });
2962
3337
  } catch (error) {
2963
- if (starting) ownCodexStartup(params.lifetime, starting.then((lateClient) => lateClient.closeAndWait(), () => {}));
3338
+ if (starting) await ownCodexStartup(params.lifetime, starting.then((lateClient) => lateClient.closeAndWait(), () => {}));
2964
3339
  throw error;
2965
3340
  }
3341
+ client.addCloseHandler((closedClient) => {
3342
+ ownCodexStartup(params.lifetime, closedClient.waitForCloseWork());
3343
+ });
2966
3344
  let ready = false;
2967
3345
  try {
2968
3346
  const nativeCommandAtStart = startOptions.commandSource === "resolved-managed" ? resolveManagedCodexNativeCommand(startOptions.command) : void 0;
@@ -3001,7 +3379,7 @@ async function startInitializedCodexAppServerClient(params) {
3001
3379
  ensureCodexAppServerClientRuntime(client, {
3002
3380
  agentDir: params.agentDir,
3003
3381
  authProfileId: params.authProfileId ?? void 0,
3004
- authMode: params.preparedAuth?.kind === "api-key" ? "prepared-api-key" : "profile",
3382
+ authMode: params.preparedAuth?.kind === "api-key" || isCodexResponsesOAuth(params.preparedAuth) ? "prepared-api-key" : "profile",
3005
3383
  ...params.authProfileStore ? { authProfileStore: params.authProfileStore } : {},
3006
3384
  config: params.config,
3007
3385
  onAuthRefreshFailure: () => retireSharedCodexAppServerClientIfCurrent(client)
@@ -3018,7 +3396,18 @@ async function startInitializedCodexAppServerClient(params) {
3018
3396
  assertCurrent: assertStartupCurrent,
3019
3397
  ...params.authProfileStore ? { authProfileStore: params.authProfileStore } : {}
3020
3398
  }));
3021
- if (startOptions.transport === "stdio" && nativeCommandAtStart && !desktopGeneration && !isManagedCodexDesktopCommand(startOptions.command) && !isCodexAppServerProxyLaunch(startOptions.args)) ownCodexInferenceClient(client);
3399
+ const ownsInference = startOptions.transport === "stdio" && nativeCommandAtStart && !isCodexAppServerProxyLaunch(startOptions.args);
3400
+ if (isCodexResponsesOAuth(params.preparedAuth) && (!ownsInference || desktopGeneration || desktopCommand)) throw new Error("ChatGPT subscription sharing requires a managed local Codex process.");
3401
+ if (ownsInference) {
3402
+ const prepared = params.preparedAuth;
3403
+ ownCodexInferenceClient(client, startOptions, isCodexResponsesOAuth(prepared) && prepared?.kind === "profile" ? createCodexResponsesOAuth({
3404
+ profileId: prepared.profileId,
3405
+ store: prepared.store,
3406
+ fingerprint: prepared.snapshot.secretFreeCacheKey,
3407
+ agentDir: params.agentDir,
3408
+ config: params.config
3409
+ }) : void 0);
3410
+ }
3022
3411
  recordCodexAppServerAuthHandoff(client, authHandoff);
3023
3412
  if (runtimeArtifactModule && runtimeArtifact) runtimeArtifactModule.bindCodexAppServerRuntimeArtifact(client, runtimeArtifact);
3024
3413
  assertStartupCurrent();
@@ -3036,7 +3425,7 @@ async function startInitializedCodexAppServerClient(params) {
3036
3425
  ready = true;
3037
3426
  return client;
3038
3427
  } finally {
3039
- if (!ready) ownCodexStartup(params.lifetime, client.closeAndWait());
3428
+ if (!ready) await ownCodexStartup(params.lifetime, client.closeAndWait());
3040
3429
  }
3041
3430
  }
3042
3431
  throw new Error("Managed Codex app-server fallback candidates were exhausted.");
@@ -3062,7 +3451,6 @@ function resolveManagedFallbackStartOptions(startOptions) {
3062
3451
  function shouldTryManagedFallbackStartOption(error, startOptions, index, startOptionsCandidates) {
3063
3452
  return startOptions.commandSource === "resolved-managed" && index < startOptionsCandidates.length - 1 && isUnsupportedCodexAppServerVersionError(error);
3064
3453
  }
3065
- /** Clears and closes the shared entry only if it still owns the supplied client. */
3066
3454
  function clearSharedCodexAppServerClientIfCurrent(client) {
3067
3455
  if (!client) return false;
3068
3456
  const state = getSharedCodexAppServerClientState();
@@ -3085,24 +3473,10 @@ function captureSharedClientRegistration(client) {
3085
3473
  const generation = readCodexAppServerClientDesktopGeneration(client);
3086
3474
  return () => entry !== void 0 && state.clients.get(entry.key) === entry && entry.client === client && !entry.closeWhenIdle && !entry.closeError && !client.getCloseError() && (!generation || isCodexDesktopGenerationCurrent(generation));
3087
3475
  }
3088
- /** Retains the matching shared client and returns a release callback. */
3089
3476
  function retainSharedCodexAppServerClientIfCurrent(client) {
3090
3477
  const entry = getCurrentSharedClientEntry(client);
3091
3478
  return entry ? retainSharedClientEntry(entry) : void 0;
3092
3479
  }
3093
- /** Retains the live shared client whose initialized instance id matches a thread binding. */
3094
- function retainSharedCodexAppServerClientByInstanceId(clientId) {
3095
- const normalizedClientId = clientId?.trim();
3096
- if (!normalizedClientId) return;
3097
- for (const entry of getSharedCodexAppServerClientState().clients.values()) {
3098
- const client = entry.client;
3099
- if (client?.getInstanceId() !== normalizedClientId || entry.closeWhenIdle || entry.closeError) continue;
3100
- return {
3101
- client,
3102
- release: retainSharedClientEntry(entry)
3103
- };
3104
- }
3105
- }
3106
3480
  /** Captures physical ownership, independently of unrelated thread and reader leases. */
3107
3481
  function captureCodexAppServerClientLifetime(client, requiredOwnership) {
3108
3482
  const state = getSharedCodexAppServerClientState();
@@ -3127,10 +3501,7 @@ function createOlderDesktopGenerationDrainWait(params) {
3127
3501
  };
3128
3502
  const state = getSharedCodexAppServerClientState();
3129
3503
  let settled = false;
3130
- let resolveWait;
3131
- const promise = new Promise((resolve) => {
3132
- resolveWait = resolve;
3133
- });
3504
+ const { promise, resolve: resolveWait } = createDeferred();
3134
3505
  const cancel = () => {
3135
3506
  if (settled) return;
3136
3507
  settled = true;
@@ -3152,18 +3523,13 @@ function createOlderDesktopGenerationDrainWait(params) {
3152
3523
  };
3153
3524
  }
3154
3525
  function hasLiveOlderDesktopGenerationClient(params) {
3155
- for (const client of params.state.liveClients) if (isOlderDesktopGenerationClientForHome(client, params.generation, params.targetHome)) return true;
3156
- for (const client of params.state.isolatedClients) if (isOlderDesktopGenerationClientForHome(client, params.generation, params.targetHome)) return true;
3526
+ for (const clients of [params.state.liveClients, params.state.isolatedClients]) for (const client of clients) if (isOlderDesktopGenerationClientForHome(client, params.generation, params.targetHome)) return true;
3157
3527
  return false;
3158
3528
  }
3159
3529
  function isOlderDesktopGenerationClientForHome(client, generation, targetHome) {
3160
3530
  const metadata = getSharedCodexAppServerClientState().startMetadata.get(client);
3161
3531
  return Boolean(metadata?.desktopGeneration && metadata.desktopGeneration.epoch < generation.epoch && resolveCodexNativeConfigFenceKey({ client }) === targetHome);
3162
3532
  }
3163
- function notifyDesktopGenerationDrainChecks(state) {
3164
- for (const check of state.desktopGenerationDrainChecks) check();
3165
- }
3166
- /** Clears a matching shared client and waits for its process to exit. */
3167
3533
  async function clearSharedCodexAppServerClientIfCurrentAndWait(client, options) {
3168
3534
  if (!client) return false;
3169
3535
  const state = getSharedCodexAppServerClientState();
@@ -3173,7 +3539,6 @@ async function clearSharedCodexAppServerClientIfCurrentAndWait(client, options)
3173
3539
  await client.closeAndWait(options);
3174
3540
  return true;
3175
3541
  }
3176
- /** Clears all shared clients and waits for their processes to exit. */
3177
3542
  async function clearSharedCodexAppServerClientAndWait(options) {
3178
3543
  const state = getSharedCodexAppServerClientState();
3179
3544
  const lifetime = state.startup;
@@ -3205,7 +3570,6 @@ function getOrCreateSharedClientEntry(state, key) {
3205
3570
  }
3206
3571
  return entry;
3207
3572
  }
3208
- /** Clears a matching shared client only when no lease or acquire currently claims it. */
3209
3573
  function clearSharedCodexAppServerClientIfCurrentAndUnclaimed(client) {
3210
3574
  const entry = getCurrentSharedClientEntry(client);
3211
3575
  return {
@@ -3215,20 +3579,6 @@ function clearSharedCodexAppServerClientIfCurrentAndUnclaimed(client) {
3215
3579
  pendingAcquires: entry?.pendingAcquires ?? 0
3216
3580
  };
3217
3581
  }
3218
- function retainSharedClientEntry(entry, counter = "activeLeases") {
3219
- let released = false;
3220
- entry[counter] += 1;
3221
- return () => {
3222
- if (released) return;
3223
- released = true;
3224
- releaseSharedClientEntry(entry, counter);
3225
- };
3226
- }
3227
- function releaseSharedClientEntry(entry, counter) {
3228
- entry[counter] -= 1;
3229
- closeRetiredSharedClientEntryIfIdle(entry);
3230
- notifyDesktopGenerationDrainChecks(getSharedCodexAppServerClientState());
3231
- }
3232
3582
  function closeSharedClientEntryIfUnclaimed(entry) {
3233
3583
  if (entry.activeLeases > 0 || entry.pendingAcquires > 0) return false;
3234
3584
  const state = getSharedCodexAppServerClientState();
@@ -3237,14 +3587,5 @@ function closeSharedClientEntryIfUnclaimed(entry) {
3237
3587
  entry.client?.close();
3238
3588
  return Boolean(entry.client);
3239
3589
  }
3240
- function retirePendingSharedClientEntryIfUnclaimed(entry) {
3241
- if (entry.activeLeases > 0 || entry.pendingAcquires > 0) return;
3242
- entry.startupAbort?.abort(/* @__PURE__ */ new Error("Codex app-server startup was abandoned"));
3243
- entry.closeWhenIdle = true;
3244
- const state = getSharedCodexAppServerClientState();
3245
- if (state.clients.get(entry.key) === entry) state.clients.delete(entry.key);
3246
- if (!entry.client) return;
3247
- closeRetiredSharedClientEntry(entry);
3248
- }
3249
3590
  //#endregion
3250
- export { assertNotSymlink as $, getCodexInferenceThread as A, prepareCodexWorkspaceReferences as B, CodexThreadBindingConflictError as C, acquireCodexNativeConfigFence as D, nativeHookRelayUnregisterQueue as E, forgetCodexWorkspaceReferences as F, unsubscribeCodexAppServerLiveThread as G, readCodexClientSessionMeta as H, hasCodexAppServerLiveThread as I, rememberCodexRateLimitsRead as J, readCodexRateLimitsRevision as K, hasCodexAppServerSiblingThreadWork as L, claimCodexAppServerLiveThread as M, consumeCodexAppServerLiveThread as N, assertCodexInferenceRouteConfig as O, ensureCodexAppServerClientRuntime as P, resolveCodexManagedBundledMarketplacePath as Q, isCodexAppServerClientRuntimeLive as R, CodexAdoptedThreadActiveError as S, CodexThreadStartRequestError as T, releaseCodexAppServerLiveThread as U, protectCodexAppServerLiveThread as V, retainCodexAppServerLiveThread as W, resolveCodexAppServerAuthAccountCacheKey as X, reconcileCodexComputerUseStartArtifacts as Y, resolveCodexAppServerPreparedAuthHandoff as Z, retainSharedCodexAppServerClientByInstanceId as _, clearSharedCodexAppServerClientIfCurrentAndUnclaimed as a, resolveCodexStartupTimeoutMs as at, waitForCodexAppServerClientDesktopGenerationDrain as b, getLeasedSharedCodexAppServerClient as c, readCodexAppServerClientDesktopGeneration as d, CodexAppServerStartupError as et, readCodexAppServerClientDesktopGenerationFingerprint as f, resolveCodexNativeConfigFenceKey as g, releaseLeasedSharedCodexAppServerClient as h, clearSharedCodexAppServerClientIfCurrent as i, resolveCodexGatewayTimeoutWithGraceMs as it, prepareCodexInferenceThreadConfig as j, bindCodexInferenceThread as k, getSharedCodexAppServerClient as l, releaseCodexAppServerClientLease as m, captureCodexAppServerClientLifetime as n, TURN_TERMINAL_SETTLEMENT_TIMEOUT_MS as nt, clearSharedCodexAppServerClientIfCurrentAndWait as o, withCodexStartupTimeout as ot, readCodexAppServerClientProcessIdentity as p, readRecentCodexRateLimits as q, captureSharedCodexAppServerCatalogLifetime as r, isCodexAppServerStartupError as rt, createIsolatedCodexAppServerClient as s, assertCodexAppServerClientStartSelectionCurrent as t, TURN_FINALIZE_DRAIN_ABORT_GRACE_MS as tt, isCodexAppServerStartSelectionChangedError as u, retainSharedCodexAppServerClientIfCurrent as v, CodexThreadClientReplacementError as w, withLeasedCodexAppServerClientStartSelectionRetry as x, shared_client_exports as y, isCodexAppServerLiveThreadClaimed as z };
3591
+ export { reconcileCodexComputerUseStartArtifacts as $, bindCodexInferenceThread as A, isCodexAppServerClientRuntimeLive as B, CodexThreadBindingConflictError as C, nativeHookRelayUnregisterQueue as D, isCodexContextRestartSelectionChangedError as E, consumeCodexAppServerLiveThread as F, releaseCodexAppServerLiveThread as G, prepareCodexWorkspaceReferences as H, ensureCodexAppServerClientRuntime as I, unsubscribeCodexAppServerLiveThread as J, retainCodexAppServerLiveThread as K, forgetCodexWorkspaceReferences as L, getCodexInferenceThreadQualification as M, prepareCodexInferenceThreadConfig as N, acquireCodexNativeConfigFence as O, claimCodexAppServerLiveThread as P, createCodexEphemeralThreadPolicy as Q, hasCodexAppServerLiveThread as R, CodexAdoptedThreadActiveError as S, CodexThreadStartRequestError as T, protectCodexAppServerLiveThread as U, isCodexAppServerLiveThreadClaimed as V, readCodexClientSessionMeta as W, readRecentCodexRateLimits as X, readCodexRateLimitsRevision as Y, rememberCodexRateLimitsRead as Z, retainSharedCodexAppServerClientIfCurrent as _, clearSharedCodexAppServerClientIfCurrentAndUnclaimed as a, isLegacyCodexComputerUsePluginDisabled as at, withLeasedCodexAppServerClientStartSelectionRetry as b, getLeasedSharedCodexAppServerClient as c, assertNotSymlink as ct, readCodexAppServerClientDesktopGeneration as d, TURN_TERMINAL_SETTLEMENT_TIMEOUT_MS as dt, resolveCodexAppServerAuthAccountCacheKey as et, readCodexAppServerClientDesktopGenerationFingerprint as f, isCodexAppServerStartupError as ft, resolveCodexNativeConfigFenceKey as g, releaseLeasedSharedCodexAppServerClient as h, withCodexStartupTimeout as ht, clearSharedCodexAppServerClientIfCurrent as i, hasLegacyCodexComputerUseMcpPolicy as it, getCodexInferenceThread as j, assertCodexInferenceRouteConfig as k, getSharedCodexAppServerClient as l, CodexAppServerStartupError as lt, releaseCodexAppServerClientLease as m, resolveCodexStartupTimeoutMs as mt, captureCodexAppServerClientLifetime as n, resolveBundledComputerUseMarketplacePath as nt, clearSharedCodexAppServerClientIfCurrentAndWait as o, resolveManagedCodexComputerUseConfig as ot, readCodexAppServerClientProcessIdentity as p, resolveCodexGatewayTimeoutWithGraceMs as pt, revertCodexAppServerLiveThreadSkillsCatalog as q, captureSharedCodexAppServerCatalogLifetime as r, resolveClientManagedBundledMarketplacePath as rt, createIsolatedCodexAppServerClient as s, ensureCodexComputerUseSharedPluginCache as st, assertCodexAppServerClientStartSelectionCurrent as t, resolveCodexAppServerPreparedAuthHandoff as tt, isCodexAppServerStartSelectionChangedError as u, TURN_FINALIZE_DRAIN_ABORT_GRACE_MS as ut, shared_client_exports as v, CodexThreadClientReplacementError as w, CODEX_APP_SERVER_CONTEXT_RESTART_SELECTION_CHANGED as x, waitForCodexAppServerClientDesktopGenerationDrain as y, hasCodexAppServerSiblingThreadWork as z };