@openclaw/codex 2026.10.5-beta.4 → 2026.10.10-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/README.md +10 -3
  2. package/dist/.setup/{account-usage-runtime-CoVpNIlD.mjs → account-usage-runtime-DDCDkvtl.mjs} +15 -9
  3. package/dist/.setup/{app-server-policy-D_zv8J7V.mjs → app-server-policy-Cog6mm2i.mjs} +1 -1
  4. package/dist/.setup/{apply-BXDMd05l.mjs → apply-BVSXYkTV.mjs} +11 -11
  5. package/dist/.setup/{attempt-client-cleanup-zNuNTKVr.mjs → attempt-client-cleanup-6OcbMH46.mjs} +14 -8
  6. package/dist/.setup/attempt-terminal-sZutF0WY.mjs +1 -0
  7. package/dist/.setup/{attempt-workspace-context-CcwP3DA3.mjs → attempt-workspace-context-GYPLawX6.mjs} +2 -2
  8. package/dist/.setup/{auth-binding-BaxlhaNx.mjs → auth-binding-830RLAJW.mjs} +2 -2
  9. package/dist/.setup/{auth-cache-key-f8ODJ_OX.mjs → auth-cache-key-CVcYw8HD.mjs} +92 -80
  10. package/dist/.setup/{auth-profile-CgHQ8Vot.mjs → auth-profile-auwzSwwy.mjs} +14 -8
  11. package/dist/.setup/{auth-profile-health-oHizqgye.mjs → auth-profile-health-BVPZU9I8.mjs} +15 -8
  12. package/dist/.setup/{auth-profile-selection-hr8ocLtz.mjs → auth-profile-selection-Bp5PDk3W.mjs} +24 -7
  13. package/dist/.setup/{binding-connection-B7HAAZSI.mjs → binding-connection-GTgUj9pi.mjs} +2 -2
  14. package/dist/.setup/{binding-connection.runtime-DAXn7iFl.mjs → binding-connection.runtime-RcWR3vQu.mjs} +4 -3
  15. package/dist/.setup/{bounded-turn-isolation-BfDAo-qZ.mjs → bounded-turn-isolation-D8CDrAVX.mjs} +3 -3
  16. package/dist/.setup/{bounded-turn-DfIJtRlv.mjs → bounded-turn-mN_ekXYW.mjs} +18 -22
  17. package/dist/.setup/{build-state-Ds14X10-.mjs → build-state-VcujMRqP.mjs} +1 -1
  18. package/dist/.setup/{capabilities-DbOzOglY.mjs → capabilities-DAS-JX1z.mjs} +1 -1
  19. package/dist/.setup/{client-D93nbdB8.mjs → client-BS8X7HmG.mjs} +47 -317
  20. package/dist/.setup/{client-catalog-response-CuVLp4I0.mjs → client-catalog-response-jM38o5w1.mjs} +2 -2
  21. package/dist/.setup/client-initialize-CjgZcX61.mjs +165 -0
  22. package/dist/.setup/{command-dispatch-DxdH5a9-.mjs → command-dispatch-DzXbHqCn.mjs} +3 -3
  23. package/dist/.setup/{command-formatters-xW9KpoSZ.mjs → command-formatters-B_7-QZ1c.mjs} +2 -2
  24. package/dist/.setup/{command-handlers-fiYvYYq0.mjs → command-handlers-tfb5Uq-O.mjs} +539 -406
  25. package/dist/.setup/command-rpc-SXqLQukR.mjs +296 -0
  26. package/dist/.setup/compact-M-JxLcbZ.mjs +823 -0
  27. package/dist/.setup/{computer-use-DL2v3Kxq.mjs → computer-use-FqQ-Flbl.mjs} +21 -68
  28. package/dist/.setup/{config-C1YVVLEA.mjs → config-BfrAlTMT.mjs} +3 -3
  29. package/dist/.setup/{config-options-DDzeNQ8m.mjs → config-options-DMFZkd3X.mjs} +1 -1
  30. package/dist/.setup/{config-runtime-DWzK-k0n.mjs → config-runtime-BZRizyuG.mjs} +2 -2
  31. package/dist/.setup/{context-engine-projection-ps-yn_ci.mjs → context-engine-projection-PIeLSnR-.mjs} +16 -30
  32. package/dist/.setup/{conversation-binding-BieJZRRV.mjs → conversation-binding-C7MZy-Cx.mjs} +228 -116
  33. package/dist/.setup/{conversation-binding-data-UgLuTSQT.mjs → conversation-binding-data-khgW0n-o.mjs} +4 -2
  34. package/dist/.setup/{conversation-control-GXM3unE4.mjs → conversation-control-B2EpVZEb.mjs} +53 -23
  35. package/dist/.setup/{cyber-failover-D4dgNfFf.mjs → cyber-failover-CqEZoQsj.mjs} +1 -1
  36. package/dist/.setup/{cyber-failover-notice-ljgGGL0s.mjs → cyber-failover-notice-poL3Advd.mjs} +1 -1
  37. package/dist/.setup/{doctor-start-options-JjTAl-q_.mjs → doctor-start-options-8uIBXIzR.mjs} +8 -5
  38. package/dist/.setup/{dynamic-tool-build-DcaPmBlE.mjs → dynamic-tool-build-BjFAIG-f.mjs} +208 -218
  39. package/dist/.setup/{dynamic-tools-CnQFnNKH.mjs → dynamic-tools-XqWsVjcC.mjs} +344 -118
  40. package/dist/.setup/{effective-mcp-catalog-B5HKFZNK.mjs → effective-mcp-catalog-C3ta5hHc.mjs} +11 -9
  41. package/dist/.setup/{ephemeral-turn-De3qb8EQ.mjs → ephemeral-turn-1ZF17fUR.mjs} +5 -4
  42. package/dist/.setup/{event-projector-assistant-message-CLMKN4x-.mjs → event-projector-assistant-message-ChOAY7rW.mjs} +16 -11
  43. package/dist/.setup/{event-projector-usage-BpKfdoTm.mjs → event-projector-usage-CBY0Hkga.mjs} +2 -2
  44. package/dist/.setup/{event-projector-values-CLvG1Hil.mjs → event-projector-values-yf4us9Pf.mjs} +1 -1
  45. package/dist/.setup/experimental-features-uGnVDtp-.mjs +19 -0
  46. package/dist/.setup/inference-context-mv_dBpAL.mjs +209 -0
  47. package/dist/.setup/{inference-dispatch-CO6tTs4q.mjs → inference-dispatch-C2zVSnrr.mjs} +2 -2
  48. package/dist/.setup/{inference-metadata-DCvcG_N_.mjs → inference-metadata-CYFWLHVk.mjs} +3 -1
  49. package/dist/.setup/{inference-proxy-BDWV0djM.mjs → inference-proxy-yd3hr2dr.mjs} +8 -8
  50. package/dist/.setup/installed-probe-lVC1X5ve.mjs +185 -0
  51. package/dist/.setup/{isolated-completion-BPJdvk5F.mjs → isolated-completion-P-r8NRE4.mjs} +7 -7
  52. package/dist/.setup/managed-binary-DbKvGXKl.mjs +395 -0
  53. package/dist/.setup/{mcp-app-session-preparation-Dz2GOwyE.mjs → mcp-app-session-preparation-fnsnCovu.mjs} +18 -14
  54. package/dist/.setup/{model-catalog-ZNwltCKl.mjs → model-catalog-Y_esgRPY.mjs} +28 -17
  55. package/dist/.setup/{models-BHpbAuz8.mjs → models-BWLEUo2E.mjs} +3 -3
  56. package/dist/.setup/{native-auth-esN5MdIv.mjs → native-auth-DpZIaY8N.mjs} +7 -4
  57. package/dist/.setup/native-execution-policy-D09tLP-u.mjs +152 -0
  58. package/dist/.setup/{native-hook-relay-wq7jrNLk.mjs → native-hook-relay-C7aaLJaP.mjs} +45 -10
  59. package/dist/.setup/{native-mcp-app-DX3nyTtc.mjs → native-mcp-app-CsWj-v_x.mjs} +5 -5
  60. package/dist/.setup/{native-skill-isolation-DSBeF-Yy.mjs → native-skill-isolation-CMimsKYy.mjs} +7 -7
  61. package/dist/.setup/{native-subagent-monitor-DOLEIf9r.mjs → native-subagent-monitor-CFE7b4oC.mjs} +485 -239
  62. package/dist/.setup/{native-subagent-pending-assignments-DmVhedNs.mjs → native-subagent-pending-assignments-CTinVtjo.mjs} +1 -1
  63. package/dist/.setup/{native-task-assignments-DimsQ9Qa.mjs → native-task-assignments-YJopbaVO.mjs} +9 -5
  64. package/dist/.setup/{node-cli-sessions-CzKg2nGq.mjs → node-cli-sessions-BuJnBnEq.mjs} +7 -4
  65. package/dist/.setup/{node-exec-server.runtime-BWkULhBM.mjs → node-exec-server.runtime-CP7RC1Nd.mjs} +3 -3
  66. package/dist/.setup/{plan-41-YOBMq.mjs → plan-B4cHgqNv.mjs} +7 -20
  67. package/dist/.setup/{plugin-activation-D7WkJMvU.mjs → plugin-activation-CXPWe-hl.mjs} +4 -4
  68. package/dist/.setup/{plugin-app-cache-key-Bg9DbDI6.mjs → plugin-app-cache-key-DRb-niJc.mjs} +17 -55
  69. package/dist/.setup/{plugin-approval-roundtrip-CD88q3yx.mjs → plugin-approval-roundtrip-DIZHLbAM.mjs} +1 -1
  70. package/dist/.setup/{plugin-inventory-CYgdo14P.mjs → plugin-inventory-DE9wcaeH.mjs} +2 -2
  71. package/dist/.setup/{plugin-metadata-cache-Bi8TAPwX.mjs → plugin-metadata-cache-BqC-a6Fb.mjs} +2 -15
  72. package/dist/.setup/{project-doc-thread-config-BVcvnps8.mjs → project-doc-thread-config-B0UI3f1D.mjs} +6 -6
  73. package/dist/.setup/protocol-CaPAVwe9.mjs +12 -0
  74. package/dist/.setup/{provider-capabilities-Dn2WwH4P.mjs → provider-capabilities-DjcKunHS.mjs} +1 -1
  75. package/dist/.setup/{provider-LWKll6dV.mjs → provider-wj_LFJH3.mjs} +4 -4
  76. package/dist/.setup/{rate-limits-CI8pTPqL.mjs → rate-limits-BpfURnuy.mjs} +1 -1
  77. package/dist/.setup/{request-Bo0kKABI.mjs → request-ePeNJrOd.mjs} +132 -136
  78. package/dist/.setup/{responses-oauth-twnuTaAa.mjs → responses-oauth-CCV7aVYF.mjs} +6 -6
  79. package/dist/.setup/{rpc-error-C98SHchT.mjs → rpc-error-DemqqaxE.mjs} +7 -3
  80. package/dist/.setup/{run-attempt-ClU8MxhZ.mjs → run-attempt-BcWArowv.mjs} +595 -426
  81. package/dist/.setup/{run-attempt-lifecycle-KN4oh-7O.mjs → run-attempt-lifecycle-DN-ATDp9.mjs} +1 -1
  82. package/dist/.setup/{runtime-artifact-C13pR7tD.mjs → runtime-artifact-CmLWeyJB.mjs} +3 -3
  83. package/dist/.setup/{runtime-artifact-connection-jS5DeCok.mjs → runtime-artifact-connection-DpWlZ02e.mjs} +3 -3
  84. package/dist/.setup/{sandbox-guard-DIImwCy1.mjs → sandbox-guard-DneAfNye.mjs} +70 -30
  85. package/dist/.setup/{session-binding-JEHNMPsr.mjs → session-binding-BgsWcbdY.mjs} +25 -23
  86. package/dist/.setup/{session-binding-record-DU_0biMD.mjs → session-binding-record-C_THntMe.mjs} +27 -12
  87. package/dist/.setup/{session-binding-record-codec-BpH8u_G9.mjs → session-binding-record-codec-DvmOI7g_.mjs} +1 -0
  88. package/dist/.setup/{session-binding-sidecars-DD-enC8w.mjs → session-binding-sidecars-BNSS6WL4.mjs} +55 -63
  89. package/dist/.setup/session-cancellation-DLBSJO5n.mjs +43 -0
  90. package/dist/.setup/{session-catalog-adoption-Ca3OYGYM.mjs → session-catalog-adoption-ppsLlVLB.mjs} +24 -38
  91. package/dist/.setup/{session-catalog-archive-Bv6gV7x9.mjs → session-catalog-archive-CqLRHJ6z.mjs} +11 -13
  92. package/dist/.setup/{session-catalog-events-kR2Ot6nX.mjs → session-catalog-events-DK0opVp3.mjs} +5 -5
  93. package/dist/.setup/{session-catalog-index-CrnfVEnT.mjs → session-catalog-index-BfzfdtH7.mjs} +96 -271
  94. package/dist/.setup/{session-catalog-index-order-CTfoefow.mjs → session-catalog-index-order-0Zqng2u8.mjs} +1 -1
  95. package/dist/.setup/{session-catalog-limits-BynIoOYm.mjs → session-catalog-limits-Dc6E0BZz.mjs} +1 -1
  96. package/dist/.setup/{session-catalog-list-request-D4MYNgDB.mjs → session-catalog-list-request-CAjoWjaH.mjs} +3 -4
  97. package/dist/.setup/{session-catalog-native-projection-CWqCU1I_.mjs → session-catalog-native-projection-G3lSDYYG.mjs} +5 -5
  98. package/dist/.setup/{session-catalog-node-adoption-BdP9Zjqo.mjs → session-catalog-node-adoption-e9v8mGgx.mjs} +5 -5
  99. package/dist/.setup/{session-catalog-node-continue-CNJibO4_.mjs → session-catalog-node-continue-H7nrzcUD.mjs} +5 -5
  100. package/dist/.setup/{session-catalog-node-lookup-BH_DBGa9.mjs → session-catalog-node-lookup-BrZfDkA8.mjs} +2 -2
  101. package/dist/.setup/{session-catalog-parsing-DkeoVn60.mjs → session-catalog-parsing-V6jyFg9g.mjs} +2 -2
  102. package/dist/.setup/{session-catalog-projection-BzHiV818.mjs → session-catalog-projection-BjWE414G.mjs} +8 -7
  103. package/dist/.setup/{session-catalog-provenance-CmsOE5mh.mjs → session-catalog-provenance-Dg9s12z-.mjs} +50 -30
  104. package/dist/.setup/{session-catalog-source-DGuRdGvM.mjs → session-catalog-source-DqyuNxCe.mjs} +2 -6
  105. package/dist/.setup/{session-cli-GwU0izn-.mjs → session-cli-CBGKiqdv.mjs} +1 -1
  106. package/dist/.setup/{session-history-BO6i_pfk.mjs → session-history-7W0cgTXF.mjs} +11 -9
  107. package/dist/.setup/{session-history-import-CaO8s6ta.mjs → session-history-import-BwPKwcNi.mjs} +4 -4
  108. package/dist/.setup/{session-initialization-Bi_2DKhc.mjs → session-initialization-Dn3vveGv.mjs} +2 -2
  109. package/dist/.setup/{session-retirement-B3U5hpGJ.mjs → session-retirement-Ci_JvOfH.mjs} +8 -8
  110. package/dist/.setup/{session-history.worker-DJQfek5p.mjs → settled-turn-evidence--tRW6fSm.mjs} +2 -18
  111. package/dist/.setup/{settled-turn-finalizer-CYCVpTv2.mjs → settled-turn-finalizer-D3-KXsbP.mjs} +8 -8
  112. package/dist/.setup/{shared-client-BCx1wbyA.mjs → shared-client-CE_uY0A1.mjs} +380 -557
  113. package/dist/.setup/side-question-OM18H9WJ.mjs +998 -0
  114. package/dist/.setup/{source-DipMO9hL.mjs → source-uGKgKWm8.mjs} +5 -5
  115. package/dist/.setup/{thread-archive-guard-LKdwQKyr.mjs → thread-archive-guard-BWjSsA92.mjs} +1 -1
  116. package/dist/.setup/{thread-lifecycle-run-C_aYiYqk.mjs → thread-lifecycle-run-mLueY6pH.mjs} +172 -75
  117. package/dist/.setup/{thread-model-selection-DcVebr8N.mjs → thread-model-selection-DxposL4X.mjs} +9 -9
  118. package/dist/.setup/{thread-ownership-BoUd0i6L.mjs → thread-ownership-t6Y9fLQS.mjs} +7 -7
  119. package/dist/.setup/{thread-policy-B3wBRNph.mjs → thread-policy-Cy301Or8.mjs} +6 -6
  120. package/dist/.setup/{thread-requests-BgzJwJtS.mjs → thread-requests-BjawdIVV.mjs} +14 -14
  121. package/dist/.setup/{thread-resume-D-3bsr1j.mjs → thread-resume-BUbsUfgF.mjs} +6 -6
  122. package/dist/.setup/{transcript-history-projection-DfKcoZCB.mjs → transcript-history-projection-i-FVpyha.mjs} +1 -1
  123. package/dist/.setup/{transcript-mirror-Bee2o6jj.mjs → transcript-mirror-CEQJZlF3.mjs} +6 -9
  124. package/dist/.setup/{transport-stdio-CRWTkKOn.mjs → transport-stdio-Bq160Dhv.mjs} +63 -64
  125. package/dist/.setup/{transport-websocket-DIyPfkHo.mjs → transport-websocket-0YqiI_MH.mjs} +1 -1
  126. package/dist/.setup/{turn-router-DBVMToGo.mjs → turn-router-Dbw17k3K.mjs} +2 -2
  127. package/dist/.setup/{upstream-session-fork-p5fwKi7w.mjs → upstream-session-fork-_LYkh0nZ.mjs} +46 -219
  128. package/dist/.setup/{usage-limit-error-BQX8RHAd.mjs → usage-limit-error-DcOSH3J4.mjs} +4 -4
  129. package/dist/.setup/{usage-C2Kq7oej.mjs → usage-w_93wnnR.mjs} +4 -4
  130. package/dist/.setup/{web-search-item-CvokaZOo.mjs → web-search-item-DHVuNSqk.mjs} +1 -1
  131. package/dist/.setup/{web-search-provider.runtime-D89djc7e.mjs → web-search-provider.runtime-DMHxve5v.mjs} +3 -3
  132. package/dist/.setup/{workspace-write-sandbox-probe-BDWO2Qkh.mjs → workspace-write-sandbox-probe-DJxOXcF3.mjs} +2 -2
  133. package/dist/api.js +7 -28
  134. package/dist/catalog-page.worker.js +1 -1
  135. package/dist/cli-metadata.js +1 -1
  136. package/dist/client-version-api.js +25 -0
  137. package/dist/doctor-contract-api.js +5 -5
  138. package/dist/harness.js +59 -36
  139. package/dist/index.js +259 -295
  140. package/dist/media-understanding-provider.js +2 -2
  141. package/dist/migration-provider-api.js +1 -2
  142. package/dist/native-session-binding-api.js +1 -2
  143. package/dist/provider-discovery.js +1 -1
  144. package/dist/session-history-worker-entrypoint.js +12 -0
  145. package/dist/session-history-worker-runtime.js +7 -18
  146. package/dist/session-history.worker.js +18 -2
  147. package/openclaw.plugin.json +1 -1
  148. package/package.json +6 -6
  149. package/dist/.setup/attempt-terminal-jO5IMj9K.mjs +0 -2
  150. package/dist/.setup/command-rpc-HIvsy3wS.mjs +0 -247
  151. package/dist/.setup/compact-ClZ7Ar7L.mjs +0 -808
  152. package/dist/.setup/inference-context-DNlGwzwy.mjs +0 -91
  153. package/dist/.setup/managed-binary-BtIjV7yN.mjs +0 -175
  154. package/dist/.setup/native-execution-policy-MXEe7PB3.mjs +0 -75
  155. package/dist/.setup/protocol-CANUwXJ3.mjs +0 -17
  156. package/dist/.setup/side-question-Bz2UQW0l.mjs +0 -826
@@ -1,36 +1,36 @@
1
- import { i as isJsonObject } from "./protocol-CANUwXJ3.mjs";
2
- import { n as defineCodexBuildState, t as codexBuildSymbol } from "./build-state-Ds14X10-.mjs";
3
- import { t as CODEX_APP_SERVER_AUTH_PROVIDER } from "./auth-profile-selection-hr8ocLtz.mjs";
1
+ import { r as isJsonObject } from "./protocol-CaPAVwe9.mjs";
2
+ import { n as defineCodexBuildState, t as codexBuildSymbol } from "./build-state-VcujMRqP.mjs";
3
+ import { t as CODEX_APP_SERVER_AUTH_PROVIDER } from "./auth-profile-selection-Bp5PDk3W.mjs";
4
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-DDzeNQ8m.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-BtIjV7yN.mjs";
8
- import { A as waitForCodexDesktopGeneration, C as retirePendingSharedClientEntryIfUnclaimed, D as waitForUnclaimedSharedClientStartup, _ as observeSharedClientAcquire, a as readCodexCliAuthFileApiKey, b as releaseSharedClientEntry, c as resolveCodexAppServerPreparedApiKeyCacheKey, d as getCurrentSharedClientEntry, f as getOrCreateSharedClientEntry, g as observeAcquire, h as notifyDesktopGenerationDrainChecks, i as fingerprintTokenAuthProfileCacheKey, j as readCodexDesktopArtifactTreeFingerprint, k as isCodexDesktopGenerationCurrent, l as closeSharedClientEntryIfUnclaimed, 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 createCodexAppServerStartupLifetime, v as ownCodexStartup, w as retireSharedCodexAppServerClientIfCurrent, x as retainSharedClientEntry, y as recordSharedClientAcquireBoundary } from "./auth-cache-key-f8ODJ_OX.mjs";
9
- import { n as resolveCodexAppServerSpawnEnv } from "./transport-stdio-CRWTkKOn.mjs";
5
+ import { a as withEphemeralCodexAuthStore, i as withClearedEnvironmentVariables, n as resolveCodexAppServerLocalHomeDir, 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-DMFZkd3X.mjs";
7
+ import { a as isManagedCodexDesktopCommand, b as resolveMacOSDesktopCodexBundledMarketplaceCandidates, c as readInstalledCodexAppServerStatus, f as resolveManagedCodexNativeCommand, i as assertInstalledCodexAppServerVersion, l as rejectInstalledCodexAppServer, r as INSTALLED_CODEX_START_TIMEOUT_MS, u as resolveManagedCodexAppServerStartOptions, v as resolveFirstExistingMacOSDesktopCodexBundledMarketplacePath, x as resolveMacOSDesktopCodexComputerUseServiceAppCandidates, y as resolveMacOSDesktopCodexAppPathCandidates } from "./managed-binary-DbKvGXKl.mjs";
8
+ import { A as waitForUnclaimedSharedClientStartup, C as releaseSharedClientEntry, D as retireSharedCodexAppServerClientIfCurrent, E as retirePendingSharedClientEntryIfUnclaimed, M as waitForCodexDesktopGeneration, N as readCodexDesktopArtifactTreeFingerprint, S as rekeySharedClientEntry, _ as observeAcquire, a as readCodexCliAuthFileApiKey, b as recordSharedClientAcquireBoundary, c as resolveCodexAppServerPreparedApiKeyCacheKey, d as createCodexAppServerStartupLifetime, f as getCurrentSharedClientEntry, g as isSharedCodexFallbackJoinError, i as fingerprintTokenAuthProfileCacheKey, l as SharedCodexFallbackJoinError, m as getSharedCodexAppServerClientState, n as CODEX_AUTH_JSON_FILENAME, o as readFirstNonEmptyEnv, p as getOrCreateSharedClientEntry, r as fingerprintApiKeyAuthProfileCacheKey, s as resolveCodexAppServerFallbackApiKeyCacheKey, t as CODEX_APP_SERVER_API_KEY_ENV_VARS, u as closeSharedClientEntryIfUnclaimed, v as observeSharedClientAcquire, w as retainSharedClientEntry, x as refreshSharedClientIdleRetirement, y as ownCodexStartup } from "./auth-cache-key-CVcYw8HD.mjs";
9
+ import { n as resolveCodexAppServerSpawnEnv } from "./transport-stdio-Bq160Dhv.mjs";
10
10
  import { n as CodexAppServerAuthProfileUnavailableError, r as formatCodexAuthProfileUnavailableMessage } from "./auth-profile-recovery-BREezV0L.mjs";
11
- import { a as codexPrewriteRejectionCause } from "./rpc-error-C98SHchT.mjs";
11
+ import { a as codexPrewriteRejectionCause } from "./rpc-error-DemqqaxE.mjs";
12
12
  import { i as withTimeout } from "./timeout-D0mEWSGG.mjs";
13
- import { n as readCodexSessionMeta } from "./session-catalog-provenance-CmsOE5mh.mjs";
14
- import { n as observeCodexCatalogClient } from "./session-catalog-events-kR2Ot6nX.mjs";
15
- import { n as resolveCodexAppServerRuntimeOptions } from "./config-runtime-DWzK-k0n.mjs";
16
- import { a as resolveCodexAppServerAuthProfileStore, i as resolveCodexAppServerAuthProfileIdForAgent, r as resolveCodexAppServerAuthProfileId, t as isCodexAppServerNativeAuthProfile } from "./auth-profile-CgHQ8Vot.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 { N as isUnsupportedCodexAppServerVersionError, t as CodexAppServerClient } from "./client-D93nbdB8.mjs";
19
- import { n as isCodexWebSocketOpenFailure } from "./transport-websocket-DIyPfkHo.mjs";
20
- import { t as __exportAll } from "./session-binding-sidecars-DD-enC8w.mjs";
13
+ import { n as readCodexSessionMeta } from "./session-catalog-provenance-Dg9s12z-.mjs";
14
+ import { n as observeCodexCatalogClient } from "./session-catalog-events-DK0opVp3.mjs";
15
+ import { n as resolveCodexAppServerRuntimeOptions } from "./config-runtime-BZRizyuG.mjs";
16
+ import { a as resolveCodexAppServerAuthProfileStore, i as resolveCodexAppServerAuthProfileIdForAgent, r as resolveCodexAppServerAuthProfileId, t as isCodexAppServerNativeAuthProfile } from "./auth-profile-auwzSwwy.mjs";
17
+ import { i as isCodexResponsesOAuthCredential, n as createCodexResponsesOAuth, o as resolveCodexResponsesOAuthProfileFingerprint, r as isCodexResponsesOAuth, t as CODEX_RESPONSES_OAUTH_PROVIDER } from "./responses-oauth-CCV7aVYF.mjs";
18
+ import { t as CodexAppServerClient } from "./client-BS8X7HmG.mjs";
19
+ import { a as isUnsupportedCodexAppServerVersionError } from "./client-initialize-CjgZcX61.mjs";
20
+ import { n as isCodexWebSocketOpenFailure } from "./transport-websocket-0YqiI_MH.mjs";
21
+ import { t as __exportAll } from "./session-binding-sidecars-BNSS6WL4.mjs";
21
22
  import { asOptionalRecord, isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
22
23
  import { createHash, randomUUID } from "node:crypto";
23
24
  import { isDeepStrictEqual } from "node:util";
24
25
  import { AgentHarnessPreflightError, resolveDefaultAgentDir } from "openclaw/plugin-sdk/agent-harness-registration";
25
26
  import { addTimerTimeoutGraceMs, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
26
- import { resolveGlobalMap } from "openclaw/plugin-sdk/global-singleton";
27
27
  import { runExec } from "openclaw/plugin-sdk/process-runtime";
28
28
  import fs, { constants, existsSync } from "node:fs";
29
29
  import path from "node:path";
30
30
  import fs$1 from "node:fs/promises";
31
31
  import { extractErrorCode } from "openclaw/plugin-sdk/error-runtime";
32
32
  import { createDeferred } from "openclaw/plugin-sdk/extension-shared";
33
- import { ensureAuthProfileStore, findPersistedAuthProfileCredential, refreshOAuthCredentialForRuntime, resolveApiKeyForProfile, resolvePersistedAuthProfileOwnerAgentDir } from "openclaw/plugin-sdk/agent-runtime";
33
+ import { ensureAuthProfileStoreAsync, findPersistedAuthProfileCredentialAsync, refreshOAuthCredentialForRuntime, resolveApiKeyForProfile, resolvePersistedAuthProfileOwnerAgentDirAsync } from "openclaw/plugin-sdk/agent-runtime";
34
34
  import { AgentHarnessPreflightError as AgentHarnessPreflightError$1, embeddedAgentLog as embeddedAgentLog$1, formatErrorMessage as formatErrorMessage$1 } from "openclaw/plugin-sdk/agent-harness-runtime";
35
35
  import { hasUsableOAuthCredential, resolveOpenAICodexAuthIdentity } from "openclaw/plugin-sdk/provider-auth";
36
36
  import { assertDirectoryIdentitySync, readDirectoryIdentity } from "@openclaw/fs-safe/advanced";
@@ -42,6 +42,7 @@ const CODEX_APP_SERVER_STARTUP_TIMEOUT_FLOOR_MS = 100;
42
42
  const CODEX_APP_SERVER_STARTUP_REQUEST_TIMEOUT_MULTIPLE = 10;
43
43
  const TURN_TERMINAL_SETTLEMENT_TIMEOUT_MS = 12e4;
44
44
  const TURN_FINALIZE_DRAIN_ABORT_GRACE_MS = 5e3;
45
+ const CODEX_APP_SERVER_INITIALIZE_TIMEOUT_MESSAGE = "codex app-server initialize timed out";
45
46
  var CodexAppServerStartupError = class extends Error {
46
47
  constructor(reason, message = reason === "timed_out" ? "codex app-server startup timed out" : "codex app-server startup aborted") {
47
48
  super(message);
@@ -50,6 +51,10 @@ var CodexAppServerStartupError = class extends Error {
50
51
  this.name = "CodexAppServerStartupError";
51
52
  }
52
53
  };
54
+ function buildCodexAppServerInitializeTimeoutError(client) {
55
+ const stderr = client?.getStderrDiagnostic();
56
+ return new CodexAppServerStartupError("timed_out", stderr ? `${CODEX_APP_SERVER_INITIALIZE_TIMEOUT_MESSAGE}; stderr=${JSON.stringify(stderr)}` : CODEX_APP_SERVER_INITIALIZE_TIMEOUT_MESSAGE);
57
+ }
53
58
  function isCodexAppServerStartupError(error, reason) {
54
59
  const cause = codexPrewriteRejectionCause(error);
55
60
  return cause instanceof Error && "code" in cause && cause.code === "CODEX_APP_SERVER_STARTUP_CANCELLED" && "reason" in cause && (cause.reason === "aborted" || cause.reason === "timed_out") && (reason === void 0 || cause.reason === reason);
@@ -141,7 +146,7 @@ async function prepareOwnedServiceParent(params) {
141
146
  await ensureRealDirectoryTree(params.ownershipRoot, params.targetParent, "Computer Use service parent");
142
147
  await assertServicePathParents(params.ownershipRoot, params.targetParent, false);
143
148
  const [rootIdentity, parentIdentity] = await Promise.all([readRealDirectoryIdentity(params.ownershipRoot, "Computer Use ownership root"), readRealDirectoryIdentity(params.targetParent, "Computer Use service parent")]);
144
- assertPathAtOrInside(rootIdentity.realPath, parentIdentity.realPath, "canonical Computer Use service parent");
149
+ assertPathAtOrInside(rootIdentity.realPath, parentIdentity.realPath, "resolved Computer Use service parent");
145
150
  return parentIdentity;
146
151
  }
147
152
  async function assertOwnedCodexHomePath(params) {
@@ -238,39 +243,20 @@ async function ensureCodexComputerUseSharedPluginCache(params) {
238
243
  const physicalCacheRoot = path.dirname(physicalCachePath);
239
244
  const stagingRoot = await fs$1.mkdtemp(path.join(physicalCacheRoot, `.${cacheName}.staging-`));
240
245
  const stagedPath = path.join(stagingRoot, cacheName);
241
- const backupPath = path.join(physicalCacheRoot, `.${cacheName}.backup-${process.pid}-${Date.now()}`);
242
- let backupCreated = false;
243
246
  try {
244
247
  const physicalSourceRoot = await fs$1.realpath(sourcePluginRoot);
245
248
  await fs$1.cp(physicalSourceRoot, stagedPath, { recursive: true });
246
- await waitForCodexDesktopGeneration();
247
249
  if (ownedParent) await assertDirectoryIdentityStable(ownedParent, "Computer Use plugin cache parent");
248
250
  if (stat) {
249
251
  params.assertCurrent?.();
250
- await fs$1.rename(physicalCachePath, backupPath);
251
- backupCreated = true;
252
- }
253
- try {
254
- if (ownedParent) await assertDirectoryIdentityStable(ownedParent, "Computer Use plugin cache parent");
255
- params.assertCurrent?.();
256
- await fs$1.rename(stagedPath, physicalCachePath);
257
- } catch (error) {
258
- if (backupCreated) try {
259
- if (ownedParent) await assertDirectoryIdentityStable(ownedParent, "Computer Use plugin cache parent");
260
- await fs$1.rename(backupPath, physicalCachePath);
261
- backupCreated = false;
262
- } catch (restoreError) {
263
- throw new Error(`Failed to install Computer Use cache ${cachePath} and restore its prior copy: ${String(error)}`, { cause: restoreError });
264
- }
265
- throw error;
266
- }
267
- if (backupCreated) {
268
- if (ownedParent) await assertDirectoryIdentityStable(ownedParent, "Computer Use plugin cache parent");
269
- await fs$1.rm(backupPath, {
252
+ await fs$1.rm(physicalCachePath, {
270
253
  recursive: true,
271
254
  force: true
272
255
  });
256
+ if (ownedParent) await assertDirectoryIdentityStable(ownedParent, "Computer Use plugin cache parent");
273
257
  }
258
+ params.assertCurrent?.();
259
+ await fs$1.rename(stagedPath, physicalCachePath);
274
260
  } finally {
275
261
  if (!ownedParent || await directoryIdentityIsStable(ownedParent)) await fs$1.rm(stagingRoot, {
276
262
  recursive: true,
@@ -456,11 +442,7 @@ async function ensureCodexManagedBundledMarketplace(params) {
456
442
  const physicalTargetPath = path.join(parent.realPath, MARKETPLACE_NAME);
457
443
  await assertNotSymlink(physicalTargetPath, "managed bundled marketplace");
458
444
  const active = activeInstalls$1.get(physicalTargetPath);
459
- if (active) {
460
- if (active.sourcePath === source.bundledMarketplacePath) return await active.promise;
461
- await active.promise.catch(() => void 0);
462
- return await ensureCodexManagedBundledMarketplace(params);
463
- }
445
+ if (active) return await active;
464
446
  const install = publishManagedWrapper({
465
447
  parent,
466
448
  physicalTargetPath,
@@ -470,23 +452,17 @@ async function ensureCodexManagedBundledMarketplace(params) {
470
452
  ownershipCandidates: params.ownershipCandidates ?? candidates,
471
453
  assertCurrent: params.assertCurrent
472
454
  });
473
- const activeEntry = {
474
- sourcePath: source.bundledMarketplacePath,
475
- promise: install
476
- };
477
- activeInstalls$1.set(physicalTargetPath, activeEntry);
478
- const clearActive = () => {
479
- if (activeInstalls$1.get(physicalTargetPath) === activeEntry) activeInstalls$1.delete(physicalTargetPath);
480
- };
481
- install.then(clearActive, clearActive);
482
- return await install;
455
+ activeInstalls$1.set(physicalTargetPath, install);
456
+ try {
457
+ return await install;
458
+ } finally {
459
+ activeInstalls$1.delete(physicalTargetPath);
460
+ }
483
461
  }
484
462
  async function publishManagedWrapper(params) {
485
463
  const { parent, physicalTargetPath, targetPath, source, ownershipCandidates, assertCurrent } = params;
486
464
  if (await wrapperMatches(physicalTargetPath, source.bundledMarketplacePath, params.unifiedRuntime)) return targetPath;
487
465
  const stagingPath = await fs$1.mkdtemp(path.join(parent.realPath, `.${MARKETPLACE_NAME}.staging-`));
488
- const backupPath = path.join(parent.realPath, `.${MARKETPLACE_NAME}.backup-${process.pid}-${Date.now()}`);
489
- let backupCreated = false;
490
466
  try {
491
467
  const manifestParent = path.join(stagingPath, ".agents", "plugins");
492
468
  await fs$1.mkdir(manifestParent, {
@@ -504,9 +480,6 @@ async function publishManagedWrapper(params) {
504
480
  }
505
481
  await fs$1.writeFile(path.join(stagingPath, UNIFIED_SOURCE_FINGERPRINT), params.unifiedRuntime.sourceFingerprint, { mode: 384 });
506
482
  } else await fs$1.symlink(path.join(source.bundledMarketplacePath, "plugins"), path.join(stagingPath, "plugins"));
507
- await waitForCodexDesktopGeneration();
508
- assertCurrent?.();
509
- await assertDirectoryIdentityStable(parent, "managed bundled marketplace parent");
510
483
  const existing = await fs$1.lstat(physicalTargetPath).catch((error) => {
511
484
  if (extractErrorCode(error) === "ENOENT") return;
512
485
  throw error;
@@ -514,32 +487,14 @@ async function publishManagedWrapper(params) {
514
487
  if (existing && !existing.isDirectory()) throw new Error(`Managed bundled marketplace must be a real directory: ${targetPath}`);
515
488
  if (existing && !await wrapperMatchesAnySource(physicalTargetPath, ownershipCandidates)) throw new Error(`Refusing to replace an unowned bundled marketplace directory: ${targetPath}`);
516
489
  if (existing) {
517
- assertCurrent?.();
518
- await fs$1.rename(physicalTargetPath, backupPath);
519
- backupCreated = true;
520
490
  await assertDirectoryIdentityStable(parent, "managed bundled marketplace parent");
491
+ assertCurrent?.();
492
+ await fs$1.rm(physicalTargetPath, { recursive: true });
521
493
  }
494
+ await assertDirectoryIdentityStable(parent, "managed bundled marketplace parent");
522
495
  assertCurrent?.();
523
496
  await fs$1.rename(stagingPath, physicalTargetPath);
524
- await assertDirectoryIdentityStable(parent, "managed bundled marketplace parent");
525
- if (backupCreated) {
526
- await fs$1.rm(backupPath, { recursive: true });
527
- backupCreated = false;
528
- }
529
497
  return targetPath;
530
- } catch (error) {
531
- if (backupCreated) try {
532
- await assertDirectoryIdentityStable(parent, "managed bundled marketplace parent");
533
- if (await fs$1.lstat(physicalTargetPath).catch(() => void 0)) {
534
- if (!await wrapperOwnedBySource(physicalTargetPath, source.bundledMarketplacePath)) throw new Error("managed bundled marketplace replacement is no longer owned", { cause: error });
535
- await fs$1.rm(physicalTargetPath, { recursive: true });
536
- }
537
- await fs$1.rename(backupPath, physicalTargetPath);
538
- backupCreated = false;
539
- } catch (restoreError) {
540
- throw new Error(`Failed to restore the prior managed bundled marketplace: ${String(error)}`, { cause: restoreError });
541
- }
542
- throw error;
543
498
  } finally {
544
499
  if (await directoryIdentityIsStable(parent)) await fs$1.rm(stagingPath, {
545
500
  recursive: true,
@@ -646,13 +601,8 @@ async function ensureCodexComputerUseServiceApp(params) {
646
601
  targetPath
647
602
  });
648
603
  const candidates = params.sourceAppCandidates ?? resolveMacOSDesktopCodexComputerUseServiceAppCandidates(platform, params.appServerCommand);
649
- const syncKey = [targetPath, ...candidates].join("\0");
650
604
  const active = activeInstalls.get(targetPath);
651
- if (active) {
652
- if (active.syncKey === syncKey) return await active.promise;
653
- await active.promise.catch(() => void 0);
654
- return await ensureCodexComputerUseServiceApp(params);
655
- }
605
+ if (active) return await active;
656
606
  const install = ensureCodexComputerUseServiceAppOnce({
657
607
  ...params,
658
608
  codexHome,
@@ -661,16 +611,12 @@ async function ensureCodexComputerUseServiceApp(params) {
661
611
  targetPath,
662
612
  sourceAppCandidates: candidates
663
613
  });
664
- const activeEntry = {
665
- syncKey,
666
- promise: install
667
- };
668
- activeInstalls.set(targetPath, activeEntry);
669
- const clearActive = () => {
670
- if (activeInstalls.get(targetPath) === activeEntry) activeInstalls.delete(targetPath);
671
- };
672
- install.then(clearActive, clearActive);
673
- return await install;
614
+ activeInstalls.set(targetPath, install);
615
+ try {
616
+ return await install;
617
+ } finally {
618
+ activeInstalls.delete(targetPath);
619
+ }
674
620
  }
675
621
  async function ensureCodexComputerUseServiceAppOnce(params) {
676
622
  const inspectServiceApp = params.inspectServiceApp ?? inspectTrustedServiceApp;
@@ -695,30 +641,15 @@ async function ensureCodexComputerUseServiceAppOnce(params) {
695
641
  });
696
642
  const operationTargetPath = path.join(ownedParent.realPath, SERVICE_APP_NAME);
697
643
  await assertNotSymlink(operationTargetPath, "Computer Use service target");
698
- const initialTarget = await readServiceAppSnapshot(operationTargetPath, inspectServiceApp);
699
- if (initialTarget.identity && identitiesMatch(initialTarget.identity, sourceIdentity)) return alreadyCurrent;
644
+ const targetExisted = await pathExists$1(operationTargetPath);
645
+ const initialIdentity = await inspectServiceApp(operationTargetPath);
646
+ if (initialIdentity && identitiesMatch(initialIdentity, sourceIdentity)) return alreadyCurrent;
700
647
  await assertDirectoryIdentityStable(ownedParent, SERVICE_PARENT_LABEL);
701
648
  const stagingRoot = await fs$1.mkdtemp(path.join(ownedParent.realPath, ".service-app.staging-"));
702
649
  const stagingRootIdentity = await readRealDirectoryIdentity(stagingRoot, "Computer Use service staging directory");
703
650
  const stagedPath = path.join(stagingRoot, SERVICE_APP_NAME);
704
651
  const backupPath = path.join(ownedParent.realPath, `.service-app.backup-${process.pid}-${Date.now()}`);
705
652
  let backupCreated = false;
706
- const restoreBackup = async () => {
707
- await assertDirectoryIdentityStable(ownedParent, SERVICE_PARENT_LABEL);
708
- await fs$1.rename(backupPath, operationTargetPath);
709
- await assertDirectoryIdentityStable(ownedParent, SERVICE_PARENT_LABEL);
710
- backupCreated = false;
711
- };
712
- const removeBackup = async () => {
713
- await assertDirectoryIdentityStable(ownedParent, SERVICE_PARENT_LABEL);
714
- await assertNotSymlink(backupPath, "Computer Use service backup");
715
- await fs$1.rm(backupPath, {
716
- recursive: true,
717
- force: true
718
- });
719
- await assertDirectoryIdentityStable(ownedParent, SERVICE_PARENT_LABEL);
720
- backupCreated = false;
721
- };
722
653
  try {
723
654
  await (params.copyServiceApp ?? copyServiceAppWithDitto)(sourcePath, stagedPath);
724
655
  await assertDirectoryIdentityStable(ownedParent, SERVICE_PARENT_LABEL);
@@ -726,69 +657,42 @@ async function ensureCodexComputerUseServiceAppOnce(params) {
726
657
  await assertNotSymlink(stagedPath, "Copied Computer Use service app");
727
658
  const stagedIdentity = await inspectServiceApp(stagedPath);
728
659
  if (!stagedIdentity || !identitiesMatch(stagedIdentity, sourceIdentity)) throw new Error(`Copied Computer Use service app at ${stagedPath} does not match its selected signed source.`);
729
- const stagedSnapshot = await readServiceAppSnapshot(stagedPath, inspectServiceApp);
730
- const currentSourceIdentity = await inspectServiceApp(sourcePath);
731
- await waitForCodexDesktopGeneration();
732
660
  await assertDirectoryIdentityStable(ownedParent, SERVICE_PARENT_LABEL);
733
661
  await assertDirectoryIdentityStable(stagingRootIdentity, "Computer Use service staging directory");
734
- if (!currentSourceIdentity || !identitiesMatch(currentSourceIdentity, sourceIdentity)) throw new Error("Selected Computer Use service source changed during refresh.");
735
662
  await assertNotSymlink(operationTargetPath, "Computer Use service target");
736
663
  if (await pathExists$1(operationTargetPath)) {
737
664
  await assertDirectoryIdentityStable(ownedParent, SERVICE_PARENT_LABEL);
738
665
  params.assertCurrent?.();
739
666
  await fs$1.rename(operationTargetPath, backupPath);
740
- await assertDirectoryIdentityStable(ownedParent, SERVICE_PARENT_LABEL);
741
667
  backupCreated = true;
742
- const movedTarget = await readServiceAppSnapshot(backupPath, inspectServiceApp);
743
- if (movedTarget.identity && identitiesMatch(movedTarget.identity, sourceIdentity)) {
744
- await restoreBackup();
745
- return alreadyCurrent;
746
- }
747
- if (!snapshotsMatch(initialTarget, movedTarget)) {
748
- await restoreBackup();
749
- throw new Error("Computer Use service target changed to an unexpected generation during refresh.");
750
- }
751
- }
752
- try {
753
- await assertDirectoryIdentityStable(ownedParent, SERVICE_PARENT_LABEL);
754
- params.assertCurrent?.();
755
- await fs$1.rename(stagedPath, operationTargetPath);
756
- await assertDirectoryIdentityStable(ownedParent, SERVICE_PARENT_LABEL);
757
- } catch (error) {
758
- await assertDirectoryIdentityStable(ownedParent, SERVICE_PARENT_LABEL);
759
- await assertNotSymlink(operationTargetPath, "Computer Use service target");
760
- const winnerIdentity = await inspectServiceApp(operationTargetPath);
761
- if (!winnerIdentity || !identitiesMatch(winnerIdentity, sourceIdentity)) {
762
- if (backupCreated && !await pathExists$1(operationTargetPath)) await restoreBackup();
763
- throw error;
764
- }
765
- if (backupCreated) await removeBackup();
766
- return alreadyCurrent;
767
668
  }
669
+ await assertDirectoryIdentityStable(ownedParent, SERVICE_PARENT_LABEL);
670
+ params.assertCurrent?.();
671
+ await fs$1.rename(stagedPath, operationTargetPath);
768
672
  await assertNotSymlink(operationTargetPath, "Installed Computer Use service app");
769
- const installedSnapshot = await readServiceAppSnapshot(operationTargetPath, inspectServiceApp);
770
- if (!installedSnapshot.identity || !identitiesMatch(installedSnapshot.identity, sourceIdentity)) {
771
- if (filesystemSnapshotsMatch(installedSnapshot, stagedSnapshot)) {
772
- await assertDirectoryIdentityStable(ownedParent, SERVICE_PARENT_LABEL);
773
- await fs$1.rm(operationTargetPath, {
774
- recursive: true,
775
- force: true
776
- });
777
- await assertDirectoryIdentityStable(ownedParent, SERVICE_PARENT_LABEL);
778
- if (backupCreated) {
779
- await fs$1.rename(backupPath, operationTargetPath);
780
- await assertDirectoryIdentityStable(ownedParent, SERVICE_PARENT_LABEL);
781
- backupCreated = false;
782
- }
783
- }
673
+ const installedIdentity = await inspectServiceApp(operationTargetPath);
674
+ if (!installedIdentity || !identitiesMatch(installedIdentity, sourceIdentity)) {
675
+ await assertDirectoryIdentityStable(ownedParent, SERVICE_PARENT_LABEL);
676
+ await fs$1.rm(operationTargetPath, {
677
+ recursive: true,
678
+ force: true
679
+ });
784
680
  throw new Error("Installed Computer Use service app failed post-install identity verification.");
785
681
  }
786
- if (backupCreated) await removeBackup();
682
+ if (backupCreated) {
683
+ await assertDirectoryIdentityStable(ownedParent, SERVICE_PARENT_LABEL);
684
+ await assertNotSymlink(backupPath, "Computer Use service backup");
685
+ await fs$1.rm(backupPath, {
686
+ recursive: true,
687
+ force: true
688
+ });
689
+ backupCreated = false;
690
+ }
787
691
  return {
788
692
  ...alreadyCurrent,
789
- status: initialTarget.exists ? "refreshed" : "installed",
693
+ status: targetExisted ? "refreshed" : "installed",
790
694
  changed: true,
791
- ...initialTarget.identity ? { previousBuild: initialTarget.identity.build } : {}
695
+ ...initialIdentity ? { previousBuild: initialIdentity.build } : {}
792
696
  };
793
697
  } catch (error) {
794
698
  if (backupCreated && await directoryIdentityIsStable(ownedParent) && !await pathExists$1(operationTargetPath)) {
@@ -816,32 +720,6 @@ async function findUsableServiceApp(candidates, inspectServiceApp) {
816
720
  };
817
721
  }
818
722
  }
819
- async function readServiceAppSnapshot(appPath, inspectServiceApp) {
820
- if (!await pathExists$1(appPath)) return { exists: false };
821
- return {
822
- exists: true,
823
- identity: await inspectServiceApp(appPath),
824
- filesystemKey: await readServiceAppFilesystemKey(appPath)
825
- };
826
- }
827
- async function readServiceAppFilesystemKey(appPath) {
828
- const paths = [
829
- appPath,
830
- path.join(appPath, "Contents", "Info.plist"),
831
- path.join(appPath, CLIENT_RELATIVE_PATH)
832
- ];
833
- return (await Promise.all(paths.map((entryPath) => fs$1.stat(entryPath).then((stat) => `${stat.dev}:${stat.ino}:${stat.size}:${stat.mtimeMs}`, () => "missing")))).join("|");
834
- }
835
- function snapshotsMatch(left, right) {
836
- if (left.exists !== right.exists) return false;
837
- if (!left.exists) return true;
838
- if (left.filesystemKey && right.filesystemKey && left.filesystemKey !== right.filesystemKey) return false;
839
- if (left.identity || right.identity) return Boolean(left.identity && right.identity && identitiesMatch(left.identity, right.identity));
840
- return left.filesystemKey !== void 0 && left.filesystemKey === right.filesystemKey;
841
- }
842
- function filesystemSnapshotsMatch(left, right) {
843
- return Boolean(left.exists && right.exists && left.filesystemKey && left.filesystemKey === right.filesystemKey);
844
- }
845
723
  function identitiesMatch(left, right) {
846
724
  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;
847
725
  }
@@ -957,7 +835,7 @@ async function bridgeCodexAppServerStartOptions(params) {
957
835
  return withClearedEnvironmentVariables(scopedStartOptions, CODEX_APP_SERVER_PREPARED_AUTH_ENV_VARS);
958
836
  }
959
837
  if (params.authProfileId === null) return scopeStartOptions();
960
- const store = resolveCodexAppServerAuthProfileStore({
838
+ const store = await resolveCodexAppServerAuthProfileStore({
961
839
  agentDir: params.agentDir,
962
840
  authProfileId: params.authProfileId,
963
841
  authProfileStore: params.authProfileStore,
@@ -976,7 +854,10 @@ async function bridgeCodexAppServerStartOptions(params) {
976
854
  }) ? withClearedEnvironmentVariables(scopedStartOptions, CODEX_APP_SERVER_API_KEY_ENV_VARS) : scopedStartOptions;
977
855
  }
978
856
  function assertNoUnimportedAgentCodexAuthFile(params) {
979
- if (params.authRequirement === "api-key" && resolveCodexAppServerFallbackApiKeyCacheKey({ startOptions: params.startOptions })) return;
857
+ if ((params.authRequirement === "api-key" || params.authRequirement === "environment-api-key") && resolveCodexAppServerFallbackApiKeyCacheKey({
858
+ startOptions: params.startOptions,
859
+ allowNativeAuthFile: params.authRequirement === "api-key"
860
+ })) return;
980
861
  if (params.startOptions.transport !== "stdio" || params.startOptions.homeScope === "user") return;
981
862
  const codexHome = resolveCodexAppServerHomeDir(params.agentDir);
982
863
  const authPath = path.join(codexHome, CODEX_AUTH_JSON_FILENAME);
@@ -984,9 +865,9 @@ function assertNoUnimportedAgentCodexAuthFile(params) {
984
865
  const targetAgentId = params.agentId?.trim() || "<agent-id>";
985
866
  throw new AgentHarnessPreflightError(`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.`);
986
867
  }
987
- function resolveCodexAppServerAuthProfile(params) {
868
+ async function resolveCodexAppServerAuthProfile(params) {
988
869
  const agentDir = params.agentDir?.trim() || resolveDefaultAgentDir(params.config ?? {});
989
- const store = resolveCodexAppServerAuthProfileStore({
870
+ const store = await resolveCodexAppServerAuthProfileStore({
990
871
  ...params,
991
872
  agentDir
992
873
  });
@@ -1006,7 +887,7 @@ function resolveCodexAppServerAuthProfile(params) {
1006
887
  }
1007
888
  /** Resolves prepared profile login material once so cache identity and RPC login cannot drift. */
1008
889
  async function resolveCodexAppServerPreparedAuthProfileSnapshot(params) {
1009
- const profile = resolveCodexAppServerAuthProfile(params);
890
+ const profile = await resolveCodexAppServerAuthProfile(params);
1010
891
  if (!profile) return;
1011
892
  const { agentDir, store, profileId, credential } = profile;
1012
893
  if (isCodexResponsesOAuthCredential(credential)) return {
@@ -1074,7 +955,7 @@ async function resolveCodexAppServerPreparedAuthHandoff(params) {
1074
955
  }
1075
956
  const authProfileId = params.authProfileId?.trim() || void 0;
1076
957
  if (authProfileId && !params.authProfileStore.profiles[authProfileId]) throw new CodexAppServerAuthProfileUnavailableError(formatCodexAuthProfileUnavailableMessage(authProfileId));
1077
- const nativeAuthProfile = isCodexAppServerNativeAuthProfile({
958
+ const nativeAuthProfile = await isCodexAppServerNativeAuthProfile({
1078
959
  authProfileId,
1079
960
  authProfileStore: params.authProfileStore,
1080
961
  agentDir: params.agentDir,
@@ -1102,7 +983,7 @@ async function resolveCodexAppServerPreparedAuthHandoff(params) {
1102
983
  };
1103
984
  }
1104
985
  async function resolveCodexAppServerAuthAccountCacheKey(params) {
1105
- const profile = resolveCodexAppServerAuthProfile(params);
986
+ const profile = await resolveCodexAppServerAuthProfile(params);
1106
987
  if (!profile) return;
1107
988
  const { agentDir, store, profileId, credential } = profile;
1108
989
  const accountId = resolveChatgptAccountId(profileId, credential);
@@ -1148,12 +1029,7 @@ async function reconcileCodexComputerUseStartArtifacts(params) {
1148
1029
  else activeComputerUseArtifactReconciliations.delete(key);
1149
1030
  activeComputerUseArtifactReconciliations.set(key, owner);
1150
1031
  owner.active += 1;
1151
- const epoch = params.desktopGeneration?.epoch;
1152
- if (epoch !== void 0 && (owner.latestEpoch === void 0 || epoch > owner.latestEpoch)) owner.latestEpoch = epoch;
1153
- const assertCurrent = () => {
1154
- params.assertCurrent?.();
1155
- if (epoch !== void 0 && owner.latestEpoch !== epoch) throw new Error("Codex Computer Use artifact reconciliation was superseded.");
1156
- };
1032
+ const assertCurrent = () => params.assertCurrent?.();
1157
1033
  const operation = owner.tail.then(async () => {
1158
1034
  assertCurrent();
1159
1035
  const appliedCacheBinding = await reconcileCodexComputerUseStartArtifactsOnce({
@@ -1165,13 +1041,11 @@ async function reconcileCodexComputerUseStartArtifacts(params) {
1165
1041
  assertCurrent();
1166
1042
  owner.appliedCacheBinding = appliedCacheBinding;
1167
1043
  });
1168
- const settled = operation.catch(() => void 0);
1169
- owner.tail = settled;
1044
+ owner.tail = operation.catch(() => void 0);
1170
1045
  try {
1171
1046
  await operation;
1172
1047
  } finally {
1173
- owner.active = Math.max(0, owner.active - 1);
1174
- if (owner.active === 0 && owner.latestEpoch === void 0 && activeComputerUseArtifactReconciliations.get(key) === owner && owner.tail === settled) activeComputerUseArtifactReconciliations.delete(key);
1048
+ owner.active -= 1;
1175
1049
  pruneComputerUseArtifactOwners();
1176
1050
  }
1177
1051
  }
@@ -1265,9 +1139,14 @@ var CodexComputerUseCandidateArtifactsUnavailableError = class extends Error {
1265
1139
  }
1266
1140
  };
1267
1141
  async function applyCodexAppServerAuthProfile(params) {
1142
+ const withCurrent = async (write) => {
1143
+ await params.assertCurrentAsync?.();
1144
+ params.assertCurrent?.();
1145
+ write();
1146
+ };
1268
1147
  params.assertCurrent?.();
1269
1148
  if (!params.preparedAuth && params.authProfileId === null) {
1270
- await assertNativeCodexAccountMatchesRoute(params.client, params.authRequirement, params.assertCurrent);
1149
+ await assertNativeCodexAccountMatchesRoute(params.client, params.authRequirement, params.assertCurrent, withCurrent);
1271
1150
  return;
1272
1151
  }
1273
1152
  const agentDir = params.agentDir ?? resolveDefaultAgentDir(params.config ?? {});
@@ -1277,7 +1156,7 @@ async function applyCodexAppServerAuthProfile(params) {
1277
1156
  } : await resolveCodexAppServerAuthProfileLoginParamsInternal({
1278
1157
  agentDir,
1279
1158
  authProfileId: params.authProfileId ?? void 0,
1280
- authProfileStore: resolveCodexAppServerAuthProfileStore({
1159
+ authProfileStore: await resolveCodexAppServerAuthProfileStore({
1281
1160
  ...params,
1282
1161
  agentDir,
1283
1162
  authProfileId: params.authProfileId ?? void 0
@@ -1285,18 +1164,22 @@ async function applyCodexAppServerAuthProfile(params) {
1285
1164
  config: params.config
1286
1165
  });
1287
1166
  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.");
1288
- if (!loginParams && params.authRequirement === "api-key" && params.startOptions?.transport === "stdio") {
1167
+ if (!loginParams && (params.authRequirement === "api-key" || params.authRequirement === "environment-api-key") && params.startOptions?.transport === "stdio") {
1289
1168
  const env = resolveCodexAppServerSpawnEnv(params.startOptions, process.env);
1290
1169
  loginParams = await resolveCodexAppServerFallbackApiKeyLoginParams({
1291
1170
  client: params.client,
1292
1171
  env,
1293
- codexCliAuthEnv: process.env,
1294
- assertCurrent: params.assertCurrent
1172
+ ...params.authRequirement === "api-key" ? { codexCliAuthEnv: process.env } : {},
1173
+ assertCurrent: params.assertCurrent,
1174
+ withCurrent
1295
1175
  });
1296
1176
  }
1297
1177
  if (loginParams) {
1298
1178
  try {
1299
- await params.client.request("account/login/start", loginParams, { assertCurrent: params.assertCurrent });
1179
+ await params.client.request("account/login/start", loginParams, {
1180
+ assertCurrent: params.assertCurrent,
1181
+ withCurrent
1182
+ });
1300
1183
  } catch (error) {
1301
1184
  throw codexPrewriteRejectionCause(error);
1302
1185
  }
@@ -1316,9 +1199,12 @@ async function applyCodexAppServerAuthProfile(params) {
1316
1199
  * ChatGPT plan. An absent account is left alone because the native home may serve a
1317
1200
  * custom model provider that reports no OpenAI account at all.
1318
1201
  */
1319
- async function assertNativeCodexAccountMatchesRoute(client, authRequirement, assertCurrent) {
1202
+ async function assertNativeCodexAccountMatchesRoute(client, authRequirement, assertCurrent, withCurrent) {
1320
1203
  if (!authRequirement) return;
1321
- const accountType = (await client.request("account/read", { refreshToken: false }, { assertCurrent })).account?.type;
1204
+ const accountType = (await client.request("account/read", { refreshToken: false }, {
1205
+ assertCurrent,
1206
+ withCurrent
1207
+ })).account?.type;
1322
1208
  if (authRequirement === "subscription") {
1323
1209
  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.");
1324
1210
  return;
@@ -1333,7 +1219,7 @@ async function refreshCodexAppServerAuthTokens(params) {
1333
1219
  const handoffAccountId = params.authHandoff?.chatgptAccountId.trim();
1334
1220
  if (previousAccountId && handoffAccountId && previousAccountId !== handoffAccountId) throw codexWorkspaceChangedError("before");
1335
1221
  if (previousAccountId) {
1336
- const store = resolveCodexAppServerAuthProfileStore(params);
1222
+ const store = await resolveCodexAppServerAuthProfileStore(params);
1337
1223
  const profileId = resolveCodexAppServerAuthProfileId({
1338
1224
  ...params,
1339
1225
  store
@@ -1355,7 +1241,7 @@ async function refreshCodexAppServerAuthTokens(params) {
1355
1241
  };
1356
1242
  }
1357
1243
  async function resolveCodexAppServerAuthProfileLoginParamsInternal(params) {
1358
- const store = resolveCodexAppServerAuthProfileStore(params);
1244
+ const store = await resolveCodexAppServerAuthProfileStore(params);
1359
1245
  const profileId = resolveCodexAppServerAuthProfileId({
1360
1246
  ...params,
1361
1247
  store
@@ -1363,7 +1249,7 @@ async function resolveCodexAppServerAuthProfileLoginParamsInternal(params) {
1363
1249
  if (!profileId) return;
1364
1250
  const credential = store.profiles[profileId];
1365
1251
  if (!credential) throw new CodexAppServerAuthProfileUnavailableError(formatCodexAuthProfileUnavailableMessage(profileId));
1366
- 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.`);
1252
+ if (!isCodexAppServerAuthProvider(credential.provider)) throw new CodexAppServerAuthProfileUnavailableError(`Codex app-server auth profile "${profileId}" must use the OpenAI auth provider; run "openclaw doctor --fix" to migrate legacy provider IDs.`);
1367
1253
  const preferStoreCredential = Boolean(params.authProfileStore?.profiles[profileId]);
1368
1254
  let loginCredential = credential;
1369
1255
  let value;
@@ -1371,7 +1257,7 @@ async function resolveCodexAppServerAuthProfileLoginParamsInternal(params) {
1371
1257
  if (credential.type === "api_key" || credential.type === "token") {
1372
1258
  value = (await resolveApiKeyForProfile({
1373
1259
  cfg: params.config,
1374
- store: preferStoreCredential ? store : ensureAuthProfileStore(params.agentDir, {
1260
+ store: preferStoreCredential ? store : await ensureAuthProfileStoreAsync(params.agentDir, {
1375
1261
  allowKeychainPrompt: false,
1376
1262
  profileId,
1377
1263
  config: params.config
@@ -1396,27 +1282,30 @@ async function resolveCodexAppServerAuthProfileLoginParamsInternal(params) {
1396
1282
  } : buildChatgptAuthTokensParams(profileId, loginCredential, value);
1397
1283
  }
1398
1284
  async function resolveCodexAppServerFallbackApiKeyLoginParams(params) {
1399
- const apiKey = readFirstNonEmptyEnv(params.env, CODEX_APP_SERVER_API_KEY_ENV_VARS) ?? await readCodexCliAuthFileApiKey(params.codexCliAuthEnv);
1285
+ const apiKey = readFirstNonEmptyEnv(params.env, CODEX_APP_SERVER_API_KEY_ENV_VARS) ?? (params.codexCliAuthEnv ? await readCodexCliAuthFileApiKey(params.codexCliAuthEnv) : void 0);
1400
1286
  if (!apiKey) return;
1401
- if ((await params.client.request("account/read", { refreshToken: false }, { assertCurrent: params.assertCurrent })).account) return;
1287
+ if ((await params.client.request("account/read", { refreshToken: false }, {
1288
+ assertCurrent: params.assertCurrent,
1289
+ withCurrent: params.withCurrent
1290
+ })).account) return;
1402
1291
  return {
1403
1292
  type: "apiKey",
1404
1293
  apiKey
1405
1294
  };
1406
1295
  }
1407
1296
  async function resolveOAuthCredentialForCodexAppServer(profileId, credential, params) {
1408
- const ownerAgentDir = resolvePersistedAuthProfileOwnerAgentDir({
1297
+ const ownerAgentDir = await resolvePersistedAuthProfileOwnerAgentDirAsync({
1409
1298
  agentDir: params.agentDir,
1410
1299
  profileId
1411
1300
  });
1412
- const persistedCredential = findPersistedAuthProfileCredential({
1301
+ const persistedCredential = await findPersistedAuthProfileCredentialAsync({
1413
1302
  agentDir: ownerAgentDir,
1414
1303
  profileId
1415
1304
  });
1416
1305
  const persistedProfile = params.store.runtimePersistedProfileIds?.includes(profileId);
1417
1306
  const useScopedCredential = params.preferStoreCredential && (!persistedProfile || persistedCredential?.type === "oauth" && isCodexAppServerAuthProvider(persistedCredential.provider) && !isDeepStrictEqual(persistedCredential, credential) && !hasMatchingOAuthIdentity(persistedCredential, credential));
1418
1307
  if (params.preferStoreCredential && persistedProfile && (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.`);
1419
- const store = useScopedCredential ? params.store : resolveCodexAppServerAuthProfileStore({
1308
+ const store = useScopedCredential ? params.store : await resolveCodexAppServerAuthProfileStore({
1420
1309
  agentDir: ownerAgentDir,
1421
1310
  authProfileId: profileId,
1422
1311
  config: params.config
@@ -1504,14 +1393,16 @@ async function resolveScopedOAuthCredential(params) {
1504
1393
  cfg: params.config
1505
1394
  });
1506
1395
  if (!refreshed?.access?.trim()) throw new Error(`Codex app-server auth profile "${params.profileId}" could not refresh. Sign in again with OpenClaw, then retry.`);
1507
- assertCodexOAuthRefreshWorkspace(params.profileId, refreshed, params.expectedAccountId);
1396
+ assertCodexOAuthRefreshWorkspace(params.profileId, refreshed, resolveOpenAICodexAuthIdentity(credential).accountId?.trim());
1508
1397
  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.`);
1509
1398
  params.store.profiles[params.profileId] = refreshed;
1510
1399
  return refreshed;
1511
1400
  })();
1512
1401
  storeRefreshes.set(params.profileId, refresh);
1513
1402
  try {
1514
- return await refresh;
1403
+ const refreshed = await refresh;
1404
+ assertCodexOAuthRefreshWorkspace(params.profileId, refreshed, params.expectedAccountId);
1405
+ return refreshed;
1515
1406
  } finally {
1516
1407
  if (storeRefreshes.get(params.profileId) === refresh) storeRefreshes.delete(params.profileId);
1517
1408
  }
@@ -1560,6 +1451,62 @@ function resolveExplicitChatgptAccountId(credential) {
1560
1451
  return "accountId" in credential && typeof credential.accountId === "string" ? credential.accountId.trim() || void 0 : void 0;
1561
1452
  }
1562
1453
  //#endregion
1454
+ //#region extensions/codex/src/app-server/client-fork-settings.ts
1455
+ const clients = defineCodexBuildState("openclaw.codexClientForkSettings", () => /* @__PURE__ */ new WeakMap())();
1456
+ /** The physical client owner initializes and disposes these nonpersistent snapshots. */
1457
+ function initializeCodexClientForkSettings(client) {
1458
+ clients.set(client, /* @__PURE__ */ new Map());
1459
+ }
1460
+ function forgetCodexClientForkSettings(client, threadId) {
1461
+ if (threadId === void 0) clients.delete(client);
1462
+ else clients.get(client)?.delete(threadId);
1463
+ }
1464
+ function recordCodexThreadForkSettings(client, threadId, params) {
1465
+ const settings = clients.get(client);
1466
+ if (!settings || settings.has(threadId)) return;
1467
+ const permissions = typeof params.permissions === "string" ? params.permissions : void 0;
1468
+ const thread = {
1469
+ threadId,
1470
+ ...params.model !== void 0 ? { model: params.model } : {},
1471
+ ...params.modelProvider !== void 0 ? { modelProvider: params.modelProvider } : {},
1472
+ ...params.cwd !== void 0 ? { cwd: params.cwd } : {},
1473
+ ...params.runtimeWorkspaceRoots !== void 0 ? { runtimeWorkspaceRoots: params.runtimeWorkspaceRoots } : {},
1474
+ ...params.approvalPolicy !== void 0 ? { approvalPolicy: params.approvalPolicy } : {},
1475
+ ...params.approvalsReviewer !== void 0 ? { approvalsReviewer: params.approvalsReviewer } : {},
1476
+ ...params.sandbox !== void 0 ? { sandbox: params.sandbox } : {},
1477
+ ...permissions !== void 0 ? { permissions } : {},
1478
+ ...params.serviceTier !== void 0 ? { serviceTier: params.serviceTier } : {},
1479
+ ...params.config !== void 0 ? { config: params.config } : {},
1480
+ ...params.developerInstructions !== void 0 ? { developerInstructions: params.developerInstructions } : {}
1481
+ };
1482
+ settings.set(threadId, { thread });
1483
+ }
1484
+ function recordCodexTurnForkSettings(client, params) {
1485
+ const settings = clients.get(client)?.get(params.threadId);
1486
+ if (settings) settings.turn = {
1487
+ additionalContext: params.additionalContext,
1488
+ cwd: params.cwd,
1489
+ runtimeWorkspaceRoots: params.runtimeWorkspaceRoots,
1490
+ model: params.model,
1491
+ approvalPolicy: params.approvalPolicy,
1492
+ approvalsReviewer: params.approvalsReviewer,
1493
+ sandboxPolicy: params.sandboxPolicy,
1494
+ serviceTier: params.serviceTier,
1495
+ effort: params.effort,
1496
+ personality: params.personality,
1497
+ environments: params.environments,
1498
+ collaborationMode: params.collaborationMode
1499
+ };
1500
+ }
1501
+ function requireCodexThreadForkSettings(client, threadId) {
1502
+ const settings = clients.get(client)?.get(threadId);
1503
+ if (!settings?.turn) throw new Error("Cache-parity session fork requires a parent turn prepared by this OpenClaw runtime. Send a normal message first.");
1504
+ return {
1505
+ ...settings,
1506
+ turn: settings.turn
1507
+ };
1508
+ }
1509
+ //#endregion
1563
1510
  //#region extensions/codex/src/app-server/client-thread-owner.ts
1564
1511
  function createThreadOwnerToken(threadId, onInvalidated) {
1565
1512
  const owner = {
@@ -1627,8 +1574,12 @@ function revertRetainedThreadInstructions(runtime, threadId) {
1627
1574
  refreshableInstructions: retained.ephemeralPolicy.nativeRefreshableInstructions
1628
1575
  };
1629
1576
  }
1630
- function createCodexEphemeralThreadPolicy({ developerInstructions, refreshableInstructions }) {
1577
+ function createCodexEphemeralThreadPolicy({ developerInstructions, refreshableInstructions, config }, nativeConfig) {
1578
+ const limit = config?.model_auto_compact_token_limit ?? nativeConfig?.model_auto_compact_token_limit;
1579
+ const scope = config?.model_auto_compact_token_limit_scope ?? nativeConfig?.model_auto_compact_token_limit_scope ?? "total";
1631
1580
  return {
1581
+ ...typeof limit === "number" ? { autoCompactTokenLimit: limit } : {},
1582
+ ...typeof scope === "string" ? { autoCompactTokenLimitScope: scope } : {},
1632
1583
  developerInstructions,
1633
1584
  refreshableInstructions,
1634
1585
  nativeRefreshableInstructions: refreshableInstructions
@@ -1707,12 +1658,11 @@ const rateLimitsByClient = defineCodexBuildState("openclaw.codexAppServerRateLim
1707
1658
  /** Replaces one physical client's cache with an authoritative rate-limit read response. */
1708
1659
  function rememberCodexRateLimitsRead(client, value, nowMs = Date.now()) {
1709
1660
  if (value !== void 0) {
1710
- const revisionsByLimitId = { ...rateLimitsByClient.get(client)?.revisionsByLimitId };
1711
- for (const limitId of readRateLimitIds(value)) revisionsByLimitId[limitId] = (revisionsByLimitId[limitId] ?? 0) + 1;
1661
+ const currentState = rateLimitsByClient.get(client);
1712
1662
  rateLimitsByClient.set(client, {
1713
1663
  value,
1714
1664
  updatedAtMs: nowMs,
1715
- revisionsByLimitId
1665
+ revision: (currentState?.revision ?? 0) + Number(hasCodexRateLimit(value))
1716
1666
  });
1717
1667
  }
1718
1668
  }
@@ -1726,15 +1676,12 @@ function mergeCodexRateLimitsUpdate(client, value, nowMs = Date.now()) {
1726
1676
  rateLimitsByClient.set(client, {
1727
1677
  value: mergeRateLimitUpdate(current, update),
1728
1678
  updatedAtMs: nowMs,
1729
- revisionsByLimitId: {
1730
- ...currentState?.revisionsByLimitId,
1731
- [limitId]: (currentState?.revisionsByLimitId[limitId] ?? 0) + 1
1732
- }
1679
+ revision: (currentState?.revision ?? 0) + Number(limitId === "codex")
1733
1680
  });
1734
1681
  }
1735
- /** Per-limit marker used to trust only primary Codex updates from one turn startup. */
1736
- function readCodexRateLimitsRevision(client, limitId = "codex") {
1737
- return rateLimitsByClient.get(client)?.revisionsByLimitId[limitId] ?? 0;
1682
+ /** Marker used to trust only primary Codex updates from one turn startup. */
1683
+ function readCodexRateLimitsRevision(client) {
1684
+ return rateLimitsByClient.get(client)?.revision ?? 0;
1738
1685
  }
1739
1686
  /** Reads one physical client's cached rate-limit payload within the max-age window. */
1740
1687
  function readRecentCodexRateLimits(client, options) {
@@ -1775,15 +1722,13 @@ function mergeRateLimitUpdate(current, update) {
1775
1722
  ...nextByLimitId ? { rateLimitsByLimitId: nextByLimitId } : {}
1776
1723
  };
1777
1724
  }
1778
- function readRateLimitIds(value) {
1779
- if (!isJsonObject(value)) return [];
1780
- const ids = /* @__PURE__ */ new Set();
1781
- if (isJsonObject(value.rateLimits)) ids.add(readLimitId(value.rateLimits));
1782
- if (isJsonObject(value.rateLimitsByLimitId)) for (const [key, snapshot] of Object.entries(value.rateLimitsByLimitId)) {
1783
- const snapshotLimitId = isJsonObject(snapshot) && typeof snapshot.limitId === "string" ? snapshot.limitId.trim() : "";
1784
- ids.add(snapshotLimitId || key);
1785
- }
1786
- return [...ids];
1725
+ function hasCodexRateLimit(value) {
1726
+ if (!isJsonObject(value)) return false;
1727
+ if (isJsonObject(value.rateLimits) && readLimitId(value.rateLimits) === "codex") return true;
1728
+ if (!isJsonObject(value.rateLimitsByLimitId)) return false;
1729
+ return Object.entries(value.rateLimitsByLimitId).some(([key, snapshot]) => {
1730
+ return ((isJsonObject(snapshot) && typeof snapshot.limitId === "string" ? snapshot.limitId.trim() : "") || key) === "codex";
1731
+ });
1787
1732
  }
1788
1733
  function readLimitId(snapshot) {
1789
1734
  const value = snapshot.limitId;
@@ -1832,7 +1777,7 @@ async function readCodexClientSessionMeta(client, sessionsRoot, boundRolloutPath
1832
1777
  return readCodexWorkspaceSessionMeta(client, configuredClients.get(client), sessionsRoot, boundRolloutPath, threadId, CODEX_APP_SERVER_LIVE_THREAD_MAX_IDLE);
1833
1778
  }
1834
1779
  /** Installs one auth-refresh handler and one rate-limit observer per physical client. */
1835
- function ensureCodexAppServerClientRuntime(client, context) {
1780
+ function ensureCodexAppServerClientRuntime(client, context, onThreadOwnershipChange) {
1836
1781
  const existing = configuredClients.get(client);
1837
1782
  if (existing) {
1838
1783
  if (existing.closed) return;
@@ -1844,6 +1789,7 @@ function ensureCodexAppServerClientRuntime(client, context) {
1844
1789
  }
1845
1790
  const runtime = {
1846
1791
  context,
1792
+ onThreadOwnershipChange,
1847
1793
  closed: false,
1848
1794
  retainedThreads: /* @__PURE__ */ new Map(),
1849
1795
  claimedThreads: /* @__PURE__ */ new Map(),
@@ -1853,6 +1799,7 @@ function ensureCodexAppServerClientRuntime(client, context) {
1853
1799
  workspaceReferences: /* @__PURE__ */ new Map()
1854
1800
  };
1855
1801
  configuredClients.set(client, runtime);
1802
+ initializeCodexClientForkSettings(client);
1856
1803
  client.addCloseHandler(() => {
1857
1804
  runtime.closed = true;
1858
1805
  clearTimeout(runtime.evictionTimer);
@@ -1865,6 +1812,7 @@ function ensureCodexAppServerClientRuntime(client, context) {
1865
1812
  runtime.protectedThreads.clear();
1866
1813
  runtime.sessionMetadata.clear();
1867
1814
  runtime.workspaceReferences.clear();
1815
+ forgetCodexClientForkSettings(client);
1868
1816
  });
1869
1817
  client.addRequestHandler(async (request) => {
1870
1818
  if (request.method !== "account/chatgptAuthTokens/refresh") return;
@@ -1910,16 +1858,18 @@ function ensureCodexAppServerClientRuntime(client, context) {
1910
1858
  if (typeof threadId === "string") {
1911
1859
  invalidateThreadOwnership(runtime, threadId);
1912
1860
  runtime.sessionMetadata.delete(threadId);
1861
+ forgetCodexClientForkSettings(client, threadId);
1913
1862
  runtime.workspaceReferences.delete(threadId);
1914
- scheduleRetainedThreadEviction(client, runtime);
1863
+ updateThreadOwnership(client, runtime);
1915
1864
  }
1916
1865
  }
1917
1866
  });
1918
1867
  }
1919
- function scheduleRetainedThreadEviction(client, runtime) {
1868
+ function updateThreadOwnership(client, runtime) {
1920
1869
  clearTimeout(runtime.evictionTimer);
1921
1870
  runtime.evictionTimer = void 0;
1922
1871
  if (runtime.closed) return;
1872
+ runtime.onThreadOwnershipChange?.();
1923
1873
  let expiresAt = Number.POSITIVE_INFINITY;
1924
1874
  for (const [threadId, thread] of runtime.retainedThreads) if (!runtime.protectedThreads.has(threadId)) expiresAt = Math.min(expiresAt, thread.expiresAt);
1925
1875
  if (!Number.isFinite(expiresAt)) return;
@@ -1928,7 +1878,7 @@ function scheduleRetainedThreadEviction(client, runtime) {
1928
1878
  evictExpiredRetainedThreads(client, runtime).catch((error) => {
1929
1879
  embeddedAgentLog$1.warn("codex retained thread expiry failed", { reason: formatErrorMessage$1(error) });
1930
1880
  });
1931
- }, Math.max(0, expiresAt - Date.now()));
1881
+ }, Math.max(0, Math.floor(expiresAt - performance.now())));
1932
1882
  runtime.evictionTimer.unref?.();
1933
1883
  }
1934
1884
  async function releaseRetainedThread(client, runtime, threadId, assertCurrent, withCurrent) {
@@ -1940,13 +1890,7 @@ async function releaseRetainedThread(client, runtime, threadId, assertCurrent, w
1940
1890
  }
1941
1891
  const retained = runtime.retainedThreads.get(threadId);
1942
1892
  if (!retained) return false;
1943
- const olderThreadIds = /* @__PURE__ */ new Set();
1944
- for (const candidateThreadId of runtime.retainedThreads.keys()) {
1945
- if (candidateThreadId === threadId) break;
1946
- olderThreadIds.add(candidateThreadId);
1947
- }
1948
1893
  runtime.retainedThreads.delete(threadId);
1949
- scheduleRetainedThreadEviction(client, runtime);
1950
1894
  const transition = {
1951
1895
  retainedOwnerToken: retained.ownerToken,
1952
1896
  completion: Promise.resolve().then(() => {
@@ -1955,29 +1899,28 @@ async function releaseRetainedThread(client, runtime, threadId, assertCurrent, w
1955
1899
  })
1956
1900
  };
1957
1901
  runtime.releasingThreads.set(threadId, transition);
1902
+ updateThreadOwnership(client, runtime);
1958
1903
  try {
1959
1904
  await transition.completion;
1960
1905
  runtime.workspaceReferences.delete(threadId);
1906
+ forgetCodexClientForkSettings(client, threadId);
1961
1907
  retained.ownerToken?.invalidate();
1962
1908
  return true;
1963
1909
  } catch (error) {
1964
1910
  if (!runtime.closed && !transition.invalidated && runtime.releasingThreads.get(threadId) === transition && !runtime.retainedThreads.has(threadId) && !runtime.claimedThreads.has(threadId)) {
1965
- if (retained.ephemeralPolicy === void 0) retained.expiresAt = Date.now() + CODEX_APP_SERVER_LIVE_THREAD_IDLE_TIMEOUT_MS;
1966
- const newerThreads = [...runtime.retainedThreads.entries()].filter(([candidateThreadId]) => !olderThreadIds.has(candidateThreadId));
1967
- for (const [candidateThreadId] of newerThreads) runtime.retainedThreads.delete(candidateThreadId);
1911
+ if (retained.ephemeralPolicy === void 0) retained.expiresAt = performance.now() + CODEX_APP_SERVER_LIVE_THREAD_IDLE_TIMEOUT_MS;
1968
1912
  runtime.retainedThreads.set(threadId, retained);
1969
- for (const [candidateThreadId, newerThread] of newerThreads) runtime.retainedThreads.set(candidateThreadId, newerThread);
1970
1913
  }
1971
1914
  throw error;
1972
1915
  } finally {
1973
1916
  if (runtime.releasingThreads.get(threadId) === transition) runtime.releasingThreads.delete(threadId);
1974
- scheduleRetainedThreadEviction(client, runtime);
1917
+ updateThreadOwnership(client, runtime);
1975
1918
  }
1976
1919
  }
1977
1920
  async function evictExpiredRetainedThreads(client, runtime) {
1978
- const now = Date.now();
1921
+ const now = performance.now();
1979
1922
  for (const [threadId, thread] of runtime.retainedThreads) if (thread.expiresAt <= now && !runtime.protectedThreads.has(threadId)) await releaseRetainedThread(client, runtime, threadId);
1980
- scheduleRetainedThreadEviction(client, runtime);
1923
+ updateThreadOwnership(client, runtime);
1981
1924
  }
1982
1925
  async function evictExcessIdleThreads(client, runtime) {
1983
1926
  const idleThreads = () => [...runtime.retainedThreads].filter(([threadId, thread]) => thread.ephemeralPolicy === void 0 && !runtime.protectedThreads.has(threadId));
@@ -2006,7 +1949,7 @@ async function retainCodexAppServerLiveThread(client, threadId, releaseThread, c
2006
1949
  configFingerprint,
2007
1950
  ephemeralPolicy,
2008
1951
  serviceTier,
2009
- expiresAt: ephemeralPolicy === void 0 ? Date.now() + CODEX_APP_SERVER_LIVE_THREAD_IDLE_TIMEOUT_MS : Number.POSITIVE_INFINITY,
1952
+ expiresAt: ephemeralPolicy === void 0 ? performance.now() + CODEX_APP_SERVER_LIVE_THREAD_IDLE_TIMEOUT_MS : Number.POSITIVE_INFINITY,
2010
1953
  release: (releaseThread ? physicalThreadReleases.get(releaseThread) ?? releaseThread : void 0) ?? defaultThreadRelease(client)
2011
1954
  };
2012
1955
  runtime.retainedThreads.set(threadId, retained);
@@ -2015,7 +1958,7 @@ async function retainCodexAppServerLiveThread(client, threadId, releaseThread, c
2015
1958
  await evictExcessIdleThreads(client, runtime);
2016
1959
  } catch (error) {
2017
1960
  if (runtime.retainedThreads.get(threadId) === retained) runtime.retainedThreads.delete(threadId);
2018
- scheduleRetainedThreadEviction(client, runtime);
1961
+ updateThreadOwnership(client, runtime);
2019
1962
  embeddedAgentLog$1.warn("codex retained thread capacity eviction failed", {
2020
1963
  threadId,
2021
1964
  reason: formatErrorMessage$1(error)
@@ -2024,9 +1967,12 @@ async function retainCodexAppServerLiveThread(client, threadId, releaseThread, c
2024
1967
  }
2025
1968
  if (runtime.closed) return false;
2026
1969
  if (claimed !== void 0 && runtime.claimedThreads.get(threadId) === claimed) runtime.claimedThreads.delete(threadId);
2027
- scheduleRetainedThreadEviction(client, runtime);
1970
+ updateThreadOwnership(client, runtime);
2028
1971
  return true;
2029
1972
  }
1973
+ function readCodexLiveThreadEphemeralPolicy(client, threadId) {
1974
+ return configuredClients.get(client)?.retainedThreads.get(threadId)?.ephemeralPolicy;
1975
+ }
2030
1976
  /** Transfer one idle subscription to its next turn or compaction without touching sibling threads. */
2031
1977
  async function consumeCodexAppServerLiveThread(client, threadId, configFingerprint) {
2032
1978
  const runtime = configuredClients.get(client);
@@ -2050,7 +1996,7 @@ async function claimCodexAppServerLiveThread(client, threadId, onInvalidated) {
2050
1996
  return;
2051
1997
  }
2052
1998
  return claimCodexAppServerThreadOwnership(client, runtime, threadId, runtime.retainedThreads.get(threadId) ?? {
2053
- expiresAt: Date.now() + CODEX_APP_SERVER_LIVE_THREAD_IDLE_TIMEOUT_MS,
1999
+ expiresAt: performance.now() + CODEX_APP_SERVER_LIVE_THREAD_IDLE_TIMEOUT_MS,
2054
2000
  release: defaultThreadRelease(client)
2055
2001
  }, onInvalidated);
2056
2002
  }
@@ -2061,7 +2007,7 @@ function claimCodexAppServerThreadOwnership(client, runtime, threadId, retained,
2061
2007
  runtime.claimedThreads.set(threadId, claimed);
2062
2008
  previousClaim?.invalidate();
2063
2009
  retained.ownerToken?.invalidate();
2064
- scheduleRetainedThreadEviction(client, runtime);
2010
+ updateThreadOwnership(client, runtime);
2065
2011
  const assertCurrent = () => {
2066
2012
  if (claimed.invalidated || runtime.closed || runtime.claimedThreads.get(threadId) !== claimed) throw new Error(`Codex thread subscription ownership changed: ${threadId}`);
2067
2013
  };
@@ -2102,10 +2048,12 @@ function claimCodexAppServerThreadOwnership(client, runtime, threadId, retained,
2102
2048
  if (runtime.claimedThreads.get(threadId) === claimed) {
2103
2049
  runtime.claimedThreads.delete(threadId);
2104
2050
  runtime.workspaceReferences.delete(threadId);
2051
+ forgetCodexClientForkSettings(client, threadId);
2105
2052
  claimed.invalidate();
2106
2053
  }
2107
2054
  } finally {
2108
2055
  if (runtime.releasingThreads.get(threadId) === transition) runtime.releasingThreads.delete(threadId);
2056
+ updateThreadOwnership(client, runtime);
2109
2057
  }
2110
2058
  };
2111
2059
  physicalThreadReleases.set(release, retained.release);
@@ -2119,7 +2067,8 @@ function claimCodexAppServerThreadOwnership(client, runtime, threadId, retained,
2119
2067
  forget: () => {
2120
2068
  if (forgetThreadOwnership(runtime, threadId, claimed)) {
2121
2069
  runtime.workspaceReferences.delete(threadId);
2122
- scheduleRetainedThreadEviction(client, runtime);
2070
+ forgetCodexClientForkSettings(client, threadId);
2071
+ updateThreadOwnership(client, runtime);
2123
2072
  }
2124
2073
  }
2125
2074
  };
@@ -2129,6 +2078,11 @@ function revertCodexAppServerLiveThreadInstructions(client, threadId) {
2129
2078
  const runtime = configuredClients.get(client);
2130
2079
  if (runtime && !runtime.closed) revertRetainedThreadInstructions(runtime, threadId);
2131
2080
  }
2081
+ /** Native subscriptions, including ephemeral history and releases, pin their physical client. */
2082
+ function hasCodexAppServerThreadOwnership(client) {
2083
+ const runtime = configuredClients.get(client);
2084
+ return Boolean(runtime && !runtime.closed && (runtime.retainedThreads.size > 0 || runtime.claimedThreads.size > 0 || runtime.releasingThreads.size > 0 || runtime.protectedThreads.size > 0));
2085
+ }
2132
2086
  /** Distinguish active claimed ownership from an already-evicted idle subscription. */
2133
2087
  function hasCodexAppServerLiveThread(client, threadId) {
2134
2088
  return hasThreadOwnership(configuredClients.get(client), threadId);
@@ -2169,6 +2123,7 @@ async function unsubscribeCodexAppServerLiveThread(client, threadId, timeoutMs,
2169
2123
  });
2170
2124
  assertCurrent?.();
2171
2125
  runtime?.workspaceReferences.delete(threadId);
2126
+ forgetCodexClientForkSettings(client, threadId);
2172
2127
  });
2173
2128
  const ownsTransition = runtime !== void 0 && transition === void 0;
2174
2129
  if (transition) transition.physicalRelease = physicalRelease;
@@ -2178,20 +2133,24 @@ async function unsubscribeCodexAppServerLiveThread(client, threadId, timeoutMs,
2178
2133
  physicalRelease
2179
2134
  };
2180
2135
  runtime.releasingThreads.set(threadId, transition);
2136
+ updateThreadOwnership(client, runtime);
2181
2137
  }
2182
2138
  try {
2183
2139
  await physicalRelease;
2184
2140
  if (retained !== void 0 && runtime?.retainedThreads.get(threadId) === retained) {
2185
2141
  runtime.retainedThreads.delete(threadId);
2186
2142
  retained.ownerToken?.invalidate();
2187
- scheduleRetainedThreadEviction(client, runtime);
2143
+ updateThreadOwnership(client, runtime);
2188
2144
  }
2189
2145
  if (claimed !== void 0 && runtime?.claimedThreads.get(threadId) === claimed) {
2190
2146
  runtime.claimedThreads.delete(threadId);
2191
2147
  claimed.invalidate();
2192
2148
  }
2193
2149
  } finally {
2194
- if (ownsTransition && runtime.releasingThreads.get(threadId) === transition) runtime.releasingThreads.delete(threadId);
2150
+ if (ownsTransition && runtime.releasingThreads.get(threadId) === transition) {
2151
+ runtime.releasingThreads.delete(threadId);
2152
+ updateThreadOwnership(client, runtime);
2153
+ }
2195
2154
  }
2196
2155
  }
2197
2156
  /** Reset/end owns the exact thread; failed generation retirement must never release its successor. */
@@ -2204,7 +2163,7 @@ function protectCodexAppServerLiveThread(client, threadId) {
2204
2163
  const runtime = configuredClients.get(client);
2205
2164
  if (!runtime || runtime.closed) return () => void 0;
2206
2165
  runtime.protectedThreads.set(threadId, (runtime.protectedThreads.get(threadId) ?? 0) + 1);
2207
- scheduleRetainedThreadEviction(client, runtime);
2166
+ updateThreadOwnership(client, runtime);
2208
2167
  let protectedThread = true;
2209
2168
  return () => {
2210
2169
  if (!protectedThread) return;
@@ -2213,12 +2172,12 @@ function protectCodexAppServerLiveThread(client, threadId) {
2213
2172
  if (releaseThreadProtection(runtime, threadId)) {
2214
2173
  const retained = runtime.retainedThreads.get(threadId);
2215
2174
  if (retained) {
2216
- if (retained.ephemeralPolicy === void 0) retained.expiresAt = Date.now() + CODEX_APP_SERVER_LIVE_THREAD_IDLE_TIMEOUT_MS;
2175
+ if (retained.ephemeralPolicy === void 0) retained.expiresAt = performance.now() + CODEX_APP_SERVER_LIVE_THREAD_IDLE_TIMEOUT_MS;
2217
2176
  runtime.retainedThreads.delete(threadId);
2218
2177
  runtime.retainedThreads.set(threadId, retained);
2219
2178
  }
2220
2179
  }
2221
- scheduleRetainedThreadEviction(client, runtime);
2180
+ updateThreadOwnership(client, runtime);
2222
2181
  evictExcessIdleThreads(client, runtime).catch((error) => {
2223
2182
  embeddedAgentLog$1.warn("codex retained thread unpin eviction failed", {
2224
2183
  threadId,
@@ -2380,7 +2339,7 @@ function ownCodexInferenceClient(client, startOptions = {}, oauth) {
2380
2339
  };
2381
2340
  client.addCloseHandler(close);
2382
2341
  client.addNotificationHandler((notification) => {
2383
- if (notification.method === "thread/closed" && isJsonObject(notification.params) && typeof notification.params.threadId === "string") owner.threads.delete(notification.params.threadId);
2342
+ if ((notification.method === "thread/closed" || notification.method === "thread/archived" || notification.method === "thread/deleted") && isJsonObject(notification.params) && typeof notification.params.threadId === "string") forgetCodexInferenceThread(client, notification.params.threadId);
2384
2343
  if (notification.method !== "account/updated" || !owner.authRoute) return;
2385
2344
  const mode = isJsonObject(notification.params) ? notification.params.authMode : void 0;
2386
2345
  if ((mode === "apiKey" ? "apiKey" : mode === "chatgpt" || mode === "chatgptAuthTokens" ? "chatgpt" : void 0) !== owner.authRoute) close();
@@ -2485,9 +2444,9 @@ async function prepareCodexInferenceRoute(params) {
2485
2444
  throw new Error("Codex inference route limit reached; start a fresh managed native connection before retrying.");
2486
2445
  }
2487
2446
  pending = Promise.all([
2488
- import("./inference-proxy-BDWV0djM.mjs"),
2489
- import("./native-subagent-monitor-DOLEIf9r.mjs").then((n) => n.n),
2490
- import("./inference-dispatch-CO6tTs4q.mjs")
2447
+ import("./inference-proxy-yd3hr2dr.mjs"),
2448
+ import("./native-subagent-monitor-CFE7b4oC.mjs").then((n) => n.n),
2449
+ import("./inference-dispatch-C2zVSnrr.mjs")
2491
2450
  ]).then(([{ createCodexInferenceProxy }, native, { createCodexInferenceModelBinding }]) => {
2492
2451
  assertClient();
2493
2452
  return createCodexInferenceProxy({
@@ -2636,7 +2595,7 @@ function bindCodexInferenceThread(client, threadId, route, providers) {
2636
2595
  if (!owner && !route) return;
2637
2596
  if (!owner || owner.closed) throw new Error("Codex inference client is closed");
2638
2597
  if (!route) {
2639
- owner.threads.delete(threadId);
2598
+ forgetCodexInferenceThread(client, threadId);
2640
2599
  return;
2641
2600
  }
2642
2601
  route.assertCurrent();
@@ -2661,12 +2620,19 @@ function bindCodexInferenceThread(client, threadId, route, providers) {
2661
2620
  return projectedRoute !== void 0 && owner.handles.get(projectedRoute)?.modelPolicyEnforced === true;
2662
2621
  }
2663
2622
  }) : void 0;
2623
+ const previous = owner.threads.get(threadId)?.route;
2624
+ if (previous && previous !== route) previous.context.forget(threadId);
2664
2625
  owner.threads.set(threadId, {
2665
2626
  route,
2666
2627
  providers: projected,
2667
2628
  qualification
2668
2629
  });
2669
2630
  }
2631
+ function forgetCodexInferenceThread(client, threadId) {
2632
+ const owner = owners.get(client);
2633
+ owner?.threads.get(threadId)?.route.context.forget(threadId);
2634
+ owner?.threads.delete(threadId);
2635
+ }
2670
2636
  function getCodexInferenceThread(client, threadId) {
2671
2637
  const owner = owners.get(client);
2672
2638
  if (owner?.closed) throw new Error("Codex inference client is closed");
@@ -2679,52 +2645,24 @@ function getCodexInferenceThreadQualification(client, threadId) {
2679
2645
  return owner?.threads.get(threadId)?.qualification;
2680
2646
  }
2681
2647
  //#endregion
2682
- //#region extensions/codex/src/app-server/native-config-fence.ts
2683
- /** Serializes this Gateway's native config writes with its config-loading requests. */
2684
- const CODEX_NATIVE_CONFIG_FENCE_STATE = Symbol.for("openclaw.codexNativeConfigFenceState");
2685
- /** Acquires the per-CODEX_HOME fence and returns an idempotent release. */
2686
- async function acquireCodexNativeConfigFence(key, options = {}) {
2687
- const state = resolveGlobalMap(CODEX_NATIVE_CONFIG_FENCE_STATE);
2688
- const previous = state.get(key) ?? Promise.resolve();
2689
- const { promise: current, resolve: resolveCurrent } = createDeferred();
2690
- state.set(key, current);
2691
- let released = false;
2692
- const release = () => {
2693
- if (released) return;
2694
- released = true;
2695
- resolveCurrent();
2696
- if (state.get(key) === current) state.delete(key);
2697
- };
2698
- try {
2699
- await waitForPreviousFence(previous, options);
2700
- } catch (error) {
2701
- previous.then(release);
2702
- throw error;
2703
- }
2704
- return release;
2648
+ //#region extensions/codex/src/app-server/managed-fallback.ts
2649
+ function isCodexComputerUseCandidateArtifactsUnavailableError(error) {
2650
+ return error !== null && typeof error === "object" && "code" in error && error.code === "CODEX_COMPUTER_USE_CANDIDATE_ARTIFACTS_UNAVAILABLE";
2705
2651
  }
2706
- async function waitForPreviousFence(previous, options) {
2707
- if (options.signal?.aborted) throw new Error(options.abortMessage ?? "Codex native config fence aborted");
2708
- if (options.timeoutMs === void 0 && !options.signal) {
2709
- await previous;
2710
- return;
2711
- }
2712
- await new Promise((resolve, reject) => {
2713
- let timeout;
2714
- const settle = (error) => {
2715
- clearTimeout(timeout);
2716
- timeout = void 0;
2717
- options.signal?.removeEventListener("abort", onAbort);
2718
- return error ? reject(error) : resolve();
2652
+ function resolveManagedFallbackStartOptions(startOptions) {
2653
+ const commands = [startOptions.command, ...startOptions.managedFallbackCommandPaths ?? []];
2654
+ const candidates = [];
2655
+ for (const [index, command] of commands.entries()) {
2656
+ const managedFallbackCommandPaths = commands.slice(index + 1);
2657
+ const candidate = {
2658
+ ...startOptions,
2659
+ command
2719
2660
  };
2720
- const onAbort = () => settle(new Error(options.abortMessage ?? "Codex native config fence aborted"));
2721
- previous.then(() => settle());
2722
- options.signal?.addEventListener("abort", onAbort, { once: true });
2723
- if (options.timeoutMs !== void 0) {
2724
- timeout = setTimeout(() => settle(new Error(options.timeoutMessage ?? "Codex native config fence timed out")), Math.max(1, options.timeoutMs));
2725
- timeout.unref?.();
2726
- }
2727
- });
2661
+ if (managedFallbackCommandPaths.length === 0) delete candidate.managedFallbackCommandPaths;
2662
+ else candidate.managedFallbackCommandPaths = managedFallbackCommandPaths;
2663
+ candidates.push(candidate);
2664
+ }
2665
+ return candidates;
2728
2666
  }
2729
2667
  //#endregion
2730
2668
  //#region extensions/codex/src/app-server/native-hook-relay-state.ts
@@ -2763,6 +2701,38 @@ const nativeHookRelayUnregisterQueue = {
2763
2701
  }
2764
2702
  };
2765
2703
  //#endregion
2704
+ //#region extensions/codex/src/app-server/shared-client-key.ts
2705
+ /** Cache keys that decide which acquisitions share one physical Codex app-server client. */
2706
+ /**
2707
+ * Returns the shared-client key for start options under one acquisition's
2708
+ * auth identity, desktop generation, and runtime-artifact mode. Callers key
2709
+ * their resolved start options, and rekey after a managed fallback.
2710
+ */
2711
+ function createSharedCodexAppServerClientKeyResolver(params) {
2712
+ const { preparedAuth, authRequirement, authProfileId, desktopGeneration } = params;
2713
+ const authIdentityCacheKey = preparedAuth?.kind === "api-key" ? resolveCodexAppServerPreparedApiKeyCacheKey(preparedAuth.apiKey) : preparedAuth?.snapshot.secretFreeCacheKey ?? ((authRequirement === "api-key" || authRequirement === "environment-api-key") && !authProfileId ? resolveCodexAppServerFallbackApiKeyCacheKey({
2714
+ startOptions: params.startOptions,
2715
+ allowNativeAuthFile: authRequirement === "api-key"
2716
+ }) : void 0);
2717
+ const expectedRuntimeArtifactKey = params.expectedRuntimeArtifact ? createHash("sha256").update(params.expectedRuntimeArtifact.id).update("\0").update(params.expectedRuntimeArtifact.fingerprint).digest("hex") : "mint";
2718
+ return (startOptions) => {
2719
+ const baseKey = `${codexAppServerStartOptionsKey(startOptions, {
2720
+ authProfileId,
2721
+ authBindingFingerprint: params.authBindingFingerprint,
2722
+ agentDir: params.usesNativeAuth ? void 0 : params.agentDir,
2723
+ fallbackApiKeyCacheKey: authIdentityCacheKey
2724
+ })}\0auth-requirement:${authRequirement ?? "native"}${desktopGeneration ? `\0desktop-generation:${desktopGeneration.epoch}` : ""}`;
2725
+ return params.runtimeArtifactMode ? `${baseKey}\0runtime-artifact:capture-v1:${expectedRuntimeArtifactKey}` : baseKey;
2726
+ };
2727
+ }
2728
+ //#endregion
2729
+ //#region extensions/codex/src/app-server/shared-client-start-policy.ts
2730
+ function shouldTrackDesktopGeneration(startOptions, pluginConfig) {
2731
+ if (startOptions.transport !== "stdio") return false;
2732
+ if (resolveCodexComputerUseConfig({ pluginConfig }).enabled && (startOptions.commandSource === "managed" || startOptions.commandSource === "resolved-managed")) return true;
2733
+ return startOptions.commandSource === "managed" && (startOptions.managedCommandOrder ?? "package-first") === "desktop-first";
2734
+ }
2735
+ //#endregion
2766
2736
  //#region extensions/codex/src/app-server/spawn-identity.ts
2767
2737
  /** Resolves non-secret spawn identity before startup; argv is represented only by its hash. */
2768
2738
  function resolveCodexAppServerSpawnIdentity(startOptions, resolvedNativeCommand) {
@@ -2777,12 +2747,6 @@ function resolveCodexAppServerSpawnIdentity(startOptions, resolvedNativeCommand)
2777
2747
  }
2778
2748
  //#endregion
2779
2749
  //#region extensions/codex/src/app-server/thread-lifecycle-errors.ts
2780
- const CODEX_APP_SERVER_CONTEXT_RESTART_SELECTION_CHANGED = "CODEX_APP_SERVER_CONTEXT_RESTART_SELECTION_CHANGED";
2781
- /** True when a pre-write context restart must replay on the newly selected owner. */
2782
- function isCodexContextRestartSelectionChangedError(error) {
2783
- const cause = codexPrewriteRejectionCause(error);
2784
- return cause instanceof Error && "code" in cause && cause.code === "CODEX_APP_SERVER_CONTEXT_RESTART_SELECTION_CHANGED";
2785
- }
2786
2750
  var CodexThreadStartRequestError = class extends Error {
2787
2751
  constructor(cause) {
2788
2752
  super(`thread/start: ${formatErrorMessage$1(cause)}`, { cause });
@@ -2810,30 +2774,24 @@ var CodexAdoptedThreadActiveError = class extends AgentHarnessPreflightError$1 {
2810
2774
  //#endregion
2811
2775
  //#region extensions/codex/src/app-server/shared-client.ts
2812
2776
  var shared_client_exports = /* @__PURE__ */ __exportAll({
2813
- assertCodexAppServerClientStartSelectionCurrent: () => assertCodexAppServerClientStartSelectionCurrent,
2814
2777
  captureCodexAppServerClientLifetime: () => captureCodexAppServerClientLifetime,
2815
2778
  captureSharedCodexAppServerCatalogLifetime: () => captureSharedCodexAppServerCatalogLifetime,
2816
2779
  clearSharedCodexAppServerClientAndWait: () => clearSharedCodexAppServerClientAndWait,
2817
- clearSharedCodexAppServerClientIfCurrent: () => clearSharedCodexAppServerClientIfCurrent,
2818
2780
  clearSharedCodexAppServerClientIfCurrentAndUnclaimed: () => clearSharedCodexAppServerClientIfCurrentAndUnclaimed,
2819
2781
  clearSharedCodexAppServerClientIfCurrentAndWait: () => clearSharedCodexAppServerClientIfCurrentAndWait,
2820
2782
  createIsolatedCodexAppServerClient: () => createIsolatedCodexAppServerClient,
2821
2783
  getLeasedSharedCodexAppServerClient: () => getLeasedSharedCodexAppServerClient,
2822
2784
  getSharedCodexAppServerClient: () => getSharedCodexAppServerClient,
2823
- isCodexAppServerStartSelectionChangedError: () => isCodexAppServerStartSelectionChangedError,
2824
2785
  readCodexAppServerClientDesktopGeneration: () => readCodexAppServerClientDesktopGeneration,
2825
2786
  readCodexAppServerClientDesktopGenerationFingerprint: () => readCodexAppServerClientDesktopGenerationFingerprint,
2826
2787
  readCodexAppServerClientProcessIdentity: () => readCodexAppServerClientProcessIdentity,
2827
2788
  releaseCodexAppServerClientLease: () => releaseCodexAppServerClientLease,
2828
2789
  releaseLeasedSharedCodexAppServerClient: () => releaseLeasedSharedCodexAppServerClient,
2829
- resolveCodexNativeConfigFenceKey: () => resolveCodexNativeConfigFenceKey,
2830
2790
  retainSharedCodexAppServerClientIfCurrent: () => retainSharedCodexAppServerClientIfCurrent,
2831
2791
  retireSharedCodexAppServerClientIfCurrent: () => retireSharedCodexAppServerClientIfCurrent,
2832
- waitForCodexAppServerClientDesktopGenerationDrain: () => waitForCodexAppServerClientDesktopGenerationDrain,
2833
- withLeasedCodexAppServerClientStartSelectionRetry: () => withLeasedCodexAppServerClientStartSelectionRetry
2792
+ withCodexAppServerClientRequestScope: () => withCodexAppServerClientRequestScope
2834
2793
  });
2835
2794
  const SHARED_CODEX_APP_SERVER_CLIENT_DISPOSER = codexBuildSymbol("openclaw.codexAppServerClientDisposer");
2836
- const CODEX_APP_SERVER_INITIALIZE_TIMEOUT_MESSAGE = "codex app-server initialize timed out";
2837
2795
  async function prepareCodexAppServerClient(options) {
2838
2796
  const lifetime = getSharedCodexAppServerClientState().startup;
2839
2797
  const abandonSignal = options?.abandonSignal ? AbortSignal.any([lifetime.controller.signal, options.abandonSignal]) : lifetime.controller.signal;
@@ -2844,7 +2802,7 @@ async function prepareCodexAppServerClient(options) {
2844
2802
  const startedAt = performance.now();
2845
2803
  observeAcquire(options, { boundary: "context" });
2846
2804
  return {
2847
- context: await withCodexAppServerAcquireDeadline(options?.timeoutMs ?? 0, ownCodexStartup(lifetime, resolveCodexAppServerClientStartContext(options)), abandonSignal),
2805
+ context: await withCodexAppServerAcquireDeadline(options?.timeoutMs ?? 0, ownCodexStartup(lifetime, resolveCodexAppServerClientStartContext(options, startedAt)), abandonSignal),
2848
2806
  lifetime,
2849
2807
  abandonSignal,
2850
2808
  startedAt,
@@ -2869,59 +2827,7 @@ function readCodexAppServerClientDesktopGenerationFingerprint(client) {
2869
2827
  function readCodexAppServerClientDesktopGeneration(client) {
2870
2828
  return getSharedCodexAppServerClientState().startMetadata.get(client)?.desktopGeneration;
2871
2829
  }
2872
- /** Waits until older physical desktop clients for this client's Codex home exit. */
2873
- async function waitForCodexAppServerClientDesktopGenerationDrain(params) {
2874
- const metadata = getSharedCodexAppServerClientState().startMetadata.get(params.client);
2875
- if (!metadata?.desktopGeneration) return;
2876
- const drain = createOlderDesktopGenerationDrainWait({
2877
- generation: metadata.desktopGeneration,
2878
- startOptions: metadata.startOptions,
2879
- agentDir: metadata.agentDir
2880
- });
2881
- try {
2882
- await withCodexAppServerAcquireDeadline(params.timeoutMs ?? 0, drain.promise, params.signal, "Codex Computer Use install timed out waiting for older desktop clients");
2883
- } finally {
2884
- drain.cancel();
2885
- }
2886
- }
2887
- var CodexAppServerStartSelectionChangedError = class extends Error {
2888
- constructor() {
2889
- super("Codex app-server managed executable selection changed during startup");
2890
- this.code = "CODEX_APP_SERVER_START_SELECTION_CHANGED";
2891
- this.name = "CodexAppServerStartSelectionChangedError";
2892
- }
2893
- };
2894
- /** Cross-bundle-safe check for a managed executable selection retry. */
2895
- function isCodexAppServerStartSelectionChangedError(error) {
2896
- const cause = codexPrewriteRejectionCause(error);
2897
- return cause instanceof Error && "code" in cause && cause.code === "CODEX_APP_SERVER_START_SELECTION_CHANGED";
2898
- }
2899
- /**
2900
- * Rechecks mutable Codex-owned plugin state immediately before thread start/resume.
2901
- * The synchronous check prevents another gateway task from installing Computer
2902
- * Use between the check and the JSON-RPC write on the same event loop turn.
2903
- */
2904
- function assertCodexAppServerClientStartSelectionCurrent(params) {
2905
- const metadata = getSharedCodexAppServerClientState().startMetadata.get(params.client);
2906
- if (!metadata) return;
2907
- if (metadata.desktopGeneration && !isCodexDesktopGenerationCurrent(metadata.desktopGeneration)) throw new CodexAppServerStartSelectionChangedError();
2908
- const requestedStartOptions = params.startOptions ?? metadata.requestedStartOptions;
2909
- if (requestedStartOptions.commandSource !== "managed") return;
2910
- const current = resolveCodexAppServerStartOptionsForAgent({
2911
- startOptions: requestedStartOptions,
2912
- agentDir: params.agentDir ?? metadata.agentDir
2913
- });
2914
- if ((metadata.startOptions.managedCommandOrder ?? "package-first") !== (current.managedCommandOrder ?? "package-first")) throw new CodexAppServerStartSelectionChangedError();
2915
- }
2916
- function resolveCodexNativeConfigFenceKey(params) {
2917
- const metadata = params.client ? getSharedCodexAppServerClientState().startMetadata.get(params.client) : void 0;
2918
- const startOptions = metadata?.startOptions ?? params.startOptions;
2919
- if (!startOptions || startOptions.transport !== "stdio") return;
2920
- const configuredHome = startOptions.codexHome ?? startOptions.env?.CODEX_HOME?.trim();
2921
- const codexHome = configuredHome ? configuredHome : startOptions.homeScope === "user" ? resolveCodexAppServerUserHomeDir() : resolveCodexAppServerHomeDir(params.agentDir ?? metadata?.agentDir ?? resolveDefaultAgentDir(params.config ?? {}));
2922
- return codexHome ? `codex-home:${path.resolve(codexHome)}` : void 0;
2923
- }
2924
- async function resolveCodexAppServerClientStartContext(options) {
2830
+ async function resolveCodexAppServerClientStartContext(options, startedAt) {
2925
2831
  const requestedStartOptions = options?.startOptions ?? resolveCodexAppServerRuntimeOptions({ pluginConfig: options?.pluginConfig }).start;
2926
2832
  const agentDir = options?.agentDir ?? (requestedStartOptions.homeScope === "user" ? void 0 : resolveDefaultAgentDir(options?.config ?? {}));
2927
2833
  const desktopGeneration = shouldTrackDesktopGeneration(requestedStartOptions, options?.pluginConfig) ? await waitForCodexDesktopGeneration() : void 0;
@@ -2936,13 +2842,13 @@ async function resolveCodexAppServerClientStartContext(options) {
2936
2842
  let authRequirement = options?.authRequirement ?? preparedAuthRequirement;
2937
2843
  const usesNativeAuth = !preparedAuth && (options?.authProfileId === null || requestedStartOptions.homeScope === "user");
2938
2844
  const requestedAuthProfileId = preparedAuth?.kind === "profile" ? preparedAuth.profileId : options?.authProfileId ?? void 0;
2939
- const authProfileStore = preparedAuth?.kind === "profile" ? preparedAuth.store : !usesNativeAuth && preparedAuth?.kind !== "api-key" ? resolveCodexAppServerAuthProfileStore({
2845
+ const authProfileStore = preparedAuth?.kind === "profile" ? preparedAuth.store : !usesNativeAuth && preparedAuth?.kind !== "api-key" ? await resolveCodexAppServerAuthProfileStore({
2940
2846
  agentDir,
2941
2847
  authProfileId: requestedAuthProfileId,
2942
2848
  authProfileStore: options?.authProfileStore,
2943
2849
  config: options?.config
2944
2850
  }) : options?.authProfileStore;
2945
- const authProfileId = preparedAuth?.kind === "profile" ? preparedAuth.profileId : usesNativeAuth || preparedAuth?.kind === "api-key" ? void 0 : resolveCodexAppServerAuthProfileIdForAgent({
2851
+ const authProfileId = preparedAuth?.kind === "profile" ? preparedAuth.profileId : usesNativeAuth || preparedAuth?.kind === "api-key" ? void 0 : await resolveCodexAppServerAuthProfileIdForAgent({
2946
2852
  authProfileId: requestedAuthProfileId,
2947
2853
  agentDir,
2948
2854
  config: options?.config,
@@ -2972,8 +2878,9 @@ async function resolveCodexAppServerClientStartContext(options) {
2972
2878
  startOptions: requestedStartOptions,
2973
2879
  agentDir
2974
2880
  });
2881
+ const remainingMs = resolveRemainingAcquireTimeout(options?.timeoutMs ?? 0, startedAt);
2975
2882
  const startOptions = await bridgeCodexAppServerStartOptions({
2976
- startOptions: await resolveManagedCodexAppServerStartOptions(agentStartOptions),
2883
+ startOptions: await resolveManagedCodexAppServerStartOptions(agentStartOptions, { selectionTimeoutMs: remainingMs > 0 ? remainingMs / 2 : void 0 }),
2977
2884
  agentId: options?.agentId,
2978
2885
  agentDir,
2979
2886
  authProfileId: usesNativeAuth || preparedAuth?.kind === "api-key" ? null : authProfileId,
@@ -2996,11 +2903,6 @@ async function resolveCodexAppServerClientStartContext(options) {
2996
2903
  ...desktopGeneration ? { desktopGeneration } : {}
2997
2904
  };
2998
2905
  }
2999
- function shouldTrackDesktopGeneration(startOptions, pluginConfig) {
3000
- if (startOptions.transport !== "stdio") return false;
3001
- if (resolveCodexComputerUseConfig({ pluginConfig }).enabled && (startOptions.commandSource === "managed" || startOptions.commandSource === "resolved-managed")) return true;
3002
- return startOptions.commandSource === "managed" && (startOptions.managedCommandOrder ?? "package-first") === "desktop-first";
3003
- }
3004
2906
  /** Gets or starts a shared Codex app-server client without retaining a lease. */
3005
2907
  function getSharedCodexAppServerClient(options) {
3006
2908
  return acquireSharedCodexAppServerClient(options);
@@ -3022,58 +2924,43 @@ function releaseCodexAppServerClientLease(lease) {
3022
2924
  lease.client = void 0;
3023
2925
  return client ? releaseLeasedSharedCodexAppServerClient(client) : false;
3024
2926
  }
3025
- /** Retries one config-loading operation with a shared deadline and current client lease. */
3026
- async function withLeasedCodexAppServerClientStartSelectionRetry(params) {
3027
- let client = params.lease.client;
3028
- if (!client) throw new Error("Codex app-server selection retry requires an active client lease");
2927
+ /** Shares a deadline and live lease check across one operation's requests. */
2928
+ async function withCodexAppServerClientRequestScope(params) {
2929
+ const client = params.lease.client;
2930
+ if (!client) throw new Error("Codex app-server request scope requires an active client lease");
3029
2931
  const timeoutMs = params.options?.timeoutMs ?? 6e4;
3030
2932
  const deadline = performance.now() + timeoutMs;
3031
2933
  const signal = params.signal ?? params.options?.abandonSignal;
3032
2934
  const requestOptions = () => {
3033
- if (signal?.aborted) throw new CodexAppServerStartupError("aborted", "Codex app-server selection retry aborted");
2935
+ if (signal?.aborted) throw new CodexAppServerStartupError("aborted", "Codex app-server request aborted");
3034
2936
  const remainingTimeoutMs = deadline - performance.now();
3035
- if (remainingTimeoutMs <= 0) throw new CodexAppServerStartupError("timed_out", "Codex app-server selection retry timed out");
2937
+ if (remainingTimeoutMs <= 0) throw new CodexAppServerStartupError("timed_out", "Codex app-server request timed out");
3036
2938
  return {
3037
2939
  timeoutMs: remainingTimeoutMs,
3038
2940
  ...signal ? { signal } : {}
3039
2941
  };
3040
2942
  };
3041
- for (let attempt = 0; attempt < 2; attempt += 1) {
3042
- const attemptClient = client;
3043
- let scopeActive = true;
3044
- const assertCurrent = () => {
3045
- if (!scopeActive || params.lease.client !== attemptClient) throw new CodexAppServerStartupError("aborted", "Codex app-server request scope is closed");
3046
- };
3047
- try {
3048
- requestOptions();
3049
- return await params.run(client, () => {
3050
- assertCurrent();
3051
- return {
3052
- ...requestOptions(),
3053
- assertCurrent
3054
- };
3055
- });
3056
- } catch (error) {
3057
- if (!isCodexAppServerStartSelectionChangedError(error) || attempt > 0) throw error;
3058
- retireSharedCodexAppServerClientIfCurrent(client);
3059
- params.lease.client = void 0;
3060
- if (!releaseLeasedSharedCodexAppServerClient(client)) {
3061
- client.close();
3062
- throw new Error("Codex app-server selection retry requires a leased shared client", { cause: error });
3063
- }
3064
- const replacementOptions = requestOptions();
3065
- client = await getLeasedSharedCodexAppServerClient({
3066
- ...params.options,
3067
- timeoutMs: replacementOptions.timeoutMs,
3068
- ...signal ? { abandonSignal: signal } : {}
3069
- });
3070
- params.lease.client = client;
3071
- params.onClientChange?.(client);
3072
- } finally {
3073
- scopeActive = false;
3074
- }
2943
+ let scopeActive = true;
2944
+ const assertCurrent = () => {
2945
+ if (!scopeActive || params.lease.client !== client) throw new CodexAppServerStartupError("aborted", "Codex app-server request scope is closed");
2946
+ };
2947
+ try {
2948
+ requestOptions();
2949
+ return await params.run(client, () => {
2950
+ assertCurrent();
2951
+ return {
2952
+ ...requestOptions(),
2953
+ assertCurrent,
2954
+ ...params.options?.assertCurrentAsync ? { withCurrent: async (write) => {
2955
+ await params.options?.assertCurrentAsync?.();
2956
+ assertCurrent();
2957
+ write();
2958
+ } } : {}
2959
+ };
2960
+ });
2961
+ } finally {
2962
+ scopeActive = false;
3075
2963
  }
3076
- throw new Error("Codex app-server selection retry loop exited unexpectedly");
3077
2964
  }
3078
2965
  async function acquireSharedCodexAppServerClient(options, leased = false) {
3079
2966
  const timeoutMs = options?.timeoutMs ?? 0;
@@ -3084,23 +2971,21 @@ async function acquireSharedCodexAppServerClient(options, leased = false) {
3084
2971
  const { usesNativeAuth, ...startContext } = context;
3085
2972
  const { agentDir, authProfileId, authProfileStore, preparedAuth, authRequirement, startOptions, desktopGeneration } = startContext;
3086
2973
  const remainingTimeoutMs = resolveRemainingAcquireTimeout(timeoutMs, startedAt);
3087
- const authIdentityCacheKey = preparedAuth?.kind === "api-key" ? resolveCodexAppServerPreparedApiKeyCacheKey(preparedAuth.apiKey) : preparedAuth?.snapshot.secretFreeCacheKey ?? (authRequirement === "api-key" && !authProfileId ? resolveCodexAppServerFallbackApiKeyCacheKey({ startOptions }) : void 0);
3088
- const baseKey = `${codexAppServerStartOptionsKey(startOptions, {
2974
+ const runtimeArtifactMode = options?.runtimeArtifactMode ?? (options?.expectedRuntimeArtifact ? "capture" : void 0);
2975
+ const keyFor = createSharedCodexAppServerClientKeyResolver({
2976
+ startOptions,
2977
+ agentDir,
3089
2978
  authProfileId,
3090
2979
  authBindingFingerprint: options?.authBindingFingerprint,
3091
- agentDir: usesNativeAuth ? void 0 : agentDir,
3092
- fallbackApiKeyCacheKey: authIdentityCacheKey
3093
- })}\0auth-requirement:${authRequirement ?? "native"}${desktopGeneration ? `\0desktop-generation:${desktopGeneration.epoch}` : ""}`;
3094
- const runtimeArtifactMode = options?.runtimeArtifactMode ?? (options?.expectedRuntimeArtifact ? "capture" : void 0);
3095
- const expectedRuntimeArtifactKey = options?.expectedRuntimeArtifact ? createHash("sha256").update(options.expectedRuntimeArtifact.id).update("\0").update(options.expectedRuntimeArtifact.fingerprint).digest("hex") : "mint";
3096
- const key = runtimeArtifactMode ? `${baseKey}\0runtime-artifact:capture-v1:${expectedRuntimeArtifactKey}` : baseKey;
3097
- let entry = getOrCreateSharedClientEntry(state, key);
3098
- const existingClient = entry.client;
3099
- const existingGeneration = existingClient ? state.startMetadata.get(existingClient)?.desktopGeneration : void 0;
3100
- if (existingClient && existingGeneration && !isCodexDesktopGenerationCurrent(existingGeneration)) {
3101
- retireSharedCodexAppServerClientIfCurrent(existingClient);
3102
- entry = getOrCreateSharedClientEntry(state, key);
3103
- }
2980
+ preparedAuth,
2981
+ authRequirement,
2982
+ usesNativeAuth,
2983
+ desktopGeneration,
2984
+ runtimeArtifactMode,
2985
+ expectedRuntimeArtifact: options?.expectedRuntimeArtifact
2986
+ });
2987
+ const key = keyFor(startOptions);
2988
+ const entry = getOrCreateSharedClientEntry(state, key);
3104
2989
  entry.startupAbort ??= new AbortController();
3105
2990
  entry.closeWhenIdle = false;
3106
2991
  const releasePendingAcquire = retainSharedClientEntry(entry, "pendingAcquires");
@@ -3129,6 +3014,7 @@ async function acquireSharedCodexAppServerClient(options, leased = false) {
3129
3014
  ...startContext,
3130
3015
  lifetime,
3131
3016
  entry,
3017
+ onManagedFallback: (fallback) => rekeySharedClientEntry(entry, keyFor(fallback)),
3132
3018
  authProfileId: usesNativeAuth || preparedAuth?.kind === "api-key" ? null : authProfileId,
3133
3019
  runtimeArtifactMode,
3134
3020
  expectedRuntimeArtifact: options?.expectedRuntimeArtifact,
@@ -3156,6 +3042,10 @@ async function acquireSharedCodexAppServerClient(options, leased = false) {
3156
3042
  retirePendingSharedClientEntryIfUnclaimed(entry);
3157
3043
  observeAcquire(options, { boundary: "cleanup" });
3158
3044
  await waitForUnclaimedSharedClientStartup(entry);
3045
+ if (isSharedCodexFallbackJoinError(error)) return acquireSharedCodexAppServerClient({
3046
+ ...options,
3047
+ timeoutMs: resolveRemainingAcquireTimeout(timeoutMs, startedAt)
3048
+ }, leased);
3159
3049
  throw error;
3160
3050
  } finally {
3161
3051
  cleanupAbandonSignal?.();
@@ -3163,10 +3053,6 @@ async function acquireSharedCodexAppServerClient(options, leased = false) {
3163
3053
  releasePendingAcquire();
3164
3054
  }
3165
3055
  }
3166
- function buildCodexAppServerInitializeTimeoutError(client) {
3167
- const stderr = client?.getStderrDiagnostic();
3168
- return new CodexAppServerStartupError("timed_out", stderr ? `${CODEX_APP_SERVER_INITIALIZE_TIMEOUT_MESSAGE}; stderr=${JSON.stringify(stderr)}` : CODEX_APP_SERVER_INITIALIZE_TIMEOUT_MESSAGE);
3169
- }
3170
3056
  function createSharedCodexAppServerClientStartup(params) {
3171
3057
  const initialized = createDeferred();
3172
3058
  const ready = ownCodexStartup(params.lifetime, startInitializedCodexAppServerClient({
@@ -3185,7 +3071,6 @@ function createSharedCodexAppServerClientStartup(params) {
3185
3071
  state.liveClients.add(startedClient);
3186
3072
  startedClient.addTransportExitHandler((exitedClient) => {
3187
3073
  state.liveClients.delete(exitedClient);
3188
- notifyDesktopGenerationDrainChecks(state);
3189
3074
  });
3190
3075
  for (const callback of params.entry.onStartedClientCallbacks) callback(startedClient);
3191
3076
  retirePendingSharedClientEntryIfUnclaimed(params.entry);
@@ -3194,7 +3079,10 @@ function createSharedCodexAppServerClientStartup(params) {
3194
3079
  }).then((client) => {
3195
3080
  const state = getSharedCodexAppServerClientState();
3196
3081
  params.entry.client = client;
3082
+ params.entry.hasOwnedThreads = () => hasCodexAppServerThreadOwnership(client);
3197
3083
  client.addCloseHandler((closedClient) => {
3084
+ clearTimeout(params.entry.idleTimer);
3085
+ params.entry.idleTimer = void 0;
3198
3086
  const entry = getCurrentSharedClientEntry(closedClient);
3199
3087
  if (entry) state.clients.delete(entry.key);
3200
3088
  });
@@ -3212,6 +3100,7 @@ function createSharedCodexAppServerClientStartup(params) {
3212
3100
  }
3213
3101
  /** Starts a caller-owned client; its assertion never binds ordinary shared-client leases. */
3214
3102
  async function createIsolatedCodexAppServerClient(options) {
3103
+ await options?.assertCurrentAsync?.();
3215
3104
  options?.assertCurrent?.();
3216
3105
  const { context, lifetime, abandonSignal, startedAt, assertCurrent } = await prepareCodexAppServerClient(options);
3217
3106
  assertCurrent();
@@ -3231,13 +3120,13 @@ async function createIsolatedCodexAppServerClient(options) {
3231
3120
  timeoutMs: resolveRemainingAcquireTimeout(timeoutMs, startedAt),
3232
3121
  abandonSignal,
3233
3122
  assertCurrent: options?.assertCurrent,
3123
+ assertCurrentAsync: options?.assertCurrentAsync,
3234
3124
  onAcquireObservation: options?.onAcquireObservation,
3235
3125
  onStartedClient: (client) => {
3236
3126
  const state = getSharedCodexAppServerClientState();
3237
3127
  state.isolatedClients.add(client);
3238
3128
  client.addTransportExitHandler((exitedClient) => {
3239
3129
  state.isolatedClients.delete(exitedClient);
3240
- notifyDesktopGenerationDrainChecks(state);
3241
3130
  });
3242
3131
  options?.onStartedClient?.(client);
3243
3132
  }
@@ -3257,30 +3146,34 @@ async function startInitializedCodexAppServerClientOnce(params) {
3257
3146
  const acquireStartedAt = performance.now();
3258
3147
  const timeoutMs = params.timeoutMs ?? 0;
3259
3148
  const abandonSignal = params.abandonSignal ? AbortSignal.any([params.lifetime.controller.signal, params.abandonSignal]) : params.lifetime.controller.signal;
3260
- const waitForStartup = (operation, timeoutErrorFactory) => {
3149
+ const waitForStartup = (operation, timeoutErrorFactory, candidateLimitMs) => {
3261
3150
  if (abandonSignal.aborted) throw new CodexAppServerStartupError("aborted", "codex app-server initialize aborted");
3262
- return withCodexAppServerAcquireDeadline(resolveRemainingAcquireTimeout(timeoutMs, acquireStartedAt), ownCodexStartup(params.lifetime, operation()), abandonSignal, CODEX_APP_SERVER_INITIALIZE_TIMEOUT_MESSAGE, timeoutErrorFactory);
3151
+ const remainingMs = resolveRemainingAcquireTimeout(timeoutMs, acquireStartedAt);
3152
+ return withCodexAppServerAcquireDeadline(candidateLimitMs === void 0 ? remainingMs : remainingMs > 0 ? Math.min(remainingMs / 2, candidateLimitMs) : candidateLimitMs, ownCodexStartup(params.lifetime, operation()), abandonSignal, CODEX_APP_SERVER_INITIALIZE_TIMEOUT_MESSAGE, timeoutErrorFactory);
3263
3153
  };
3264
3154
  const startOptionsCandidates = resolveManagedFallbackStartOptions(params.startOptions);
3155
+ const yieldInstalledCodex = (index, command, error) => {
3156
+ if (params.startOptions.commandSource !== "resolved-managed" || index + 1 >= startOptionsCandidates.length || readInstalledCodexAppServerStatus(command) === void 0 || abandonSignal.aborted) return false;
3157
+ try {
3158
+ params.assertCurrent?.();
3159
+ } catch {
3160
+ return false;
3161
+ }
3162
+ const ownsFallback = params.onManagedFallback?.(startOptionsCandidates[index + 1]) ?? true;
3163
+ rejectInstalledCodexAppServer(command, error);
3164
+ if (!ownsFallback) throw new SharedCodexFallbackJoinError();
3165
+ return true;
3166
+ };
3265
3167
  for (const [index, startOptions] of startOptionsCandidates.entries()) {
3266
3168
  params.assertCurrent?.();
3267
- observeAcquire(params, { boundary: "prestart-artifact-drain" });
3268
3169
  const desktopCommand = isManagedCodexDesktopCommand(startOptions.command);
3269
3170
  const desktopGeneration = params.desktopGeneration ?? (desktopCommand ? await waitForStartup(waitForCodexDesktopGeneration) : void 0);
3270
3171
  const assertStartupCurrent = () => {
3271
3172
  params.assertCurrent?.();
3272
3173
  if (abandonSignal.aborted) throw new CodexAppServerStartupError("aborted", "codex app-server initialize aborted");
3273
- if (desktopGeneration && !isCodexDesktopGenerationCurrent(desktopGeneration)) throw new CodexAppServerStartSelectionChangedError();
3274
3174
  };
3275
- const computerUseConfig = resolveCodexComputerUseConfig({ pluginConfig: params.pluginConfig });
3276
3175
  const ownsIsolatedCodexHome = params.requestedStartOptions.homeScope !== "user" && !params.requestedStartOptions.env?.CODEX_HOME?.trim();
3277
- const artifactDrain = desktopGeneration && ownsIsolatedCodexHome && computerUseConfig.enabled && (computerUseConfig.autoInstall || computerUseConfig.pluginCacheMode === "shared") ? createOlderDesktopGenerationDrainWait({
3278
- generation: desktopGeneration,
3279
- startOptions,
3280
- agentDir: params.agentDir
3281
- }) : void 0;
3282
3176
  try {
3283
- if (artifactDrain) await waitForStartup(() => artifactDrain.promise);
3284
3177
  await reconcileCodexComputerUseStartArtifacts({
3285
3178
  startOptions,
3286
3179
  agentDir: params.agentDir,
@@ -3298,10 +3191,8 @@ async function startInitializedCodexAppServerClientOnce(params) {
3298
3191
  });
3299
3192
  }
3300
3193
  throw error;
3301
- } finally {
3302
- artifactDrain?.cancel();
3303
3194
  }
3304
- const runtimeArtifactModule = params.runtimeArtifactMode ? await import("./runtime-artifact-C13pR7tD.mjs") : void 0;
3195
+ const runtimeArtifactModule = params.runtimeArtifactMode ? await import("./runtime-artifact-CmLWeyJB.mjs") : void 0;
3305
3196
  const runtimeArtifactBeforeStart = runtimeArtifactModule ? await runtimeArtifactModule.captureCodexAppServerRuntimeArtifactBeforeStart({
3306
3197
  startOptions,
3307
3198
  spawnIdentity: resolveCodexAppServerSpawnIdentity(startOptions),
@@ -3317,7 +3208,8 @@ async function startInitializedCodexAppServerClientOnce(params) {
3317
3208
  try {
3318
3209
  observeAcquire(params, { boundary: "transport-registration" });
3319
3210
  client = await waitForStartup(() => {
3320
- starting = CodexAppServerClient.start(startOptions, () => {
3211
+ starting = CodexAppServerClient.start(startOptions, async () => {
3212
+ await params.assertCurrentAsync?.();
3321
3213
  assertStartupCurrent();
3322
3214
  resolveRemainingAcquireTimeout(timeoutMs, acquireStartedAt);
3323
3215
  });
@@ -3329,6 +3221,7 @@ async function startInitializedCodexAppServerClientOnce(params) {
3329
3221
  observeAcquire(params, { boundary: "cleanup" });
3330
3222
  await ownCodexStartup(params.lifetime, starting.then((lateClient) => lateClient.closeAndWait(), () => {}));
3331
3223
  }
3224
+ if (yieldInstalledCodex(index, startOptions.command, error)) continue;
3332
3225
  throw error;
3333
3226
  }
3334
3227
  client.addCloseHandler((closedClient) => {
@@ -3348,9 +3241,10 @@ async function startInitializedCodexAppServerClientOnce(params) {
3348
3241
  params.onStartedClient?.(client);
3349
3242
  observeAcquire(params, { boundary: "initialize" });
3350
3243
  try {
3351
- await waitForStartup(() => client.initialize(), () => buildCodexAppServerInitializeTimeoutError(client));
3244
+ await waitForStartup(() => client.initialize(), () => buildCodexAppServerInitializeTimeoutError(client), startOptions.commandSource === "resolved-managed" && index + 1 < startOptionsCandidates.length && readInstalledCodexAppServerStatus(startOptions.command) !== void 0 ? INSTALLED_CODEX_START_TIMEOUT_MS : void 0);
3245
+ if (startOptions.commandSource === "resolved-managed") assertInstalledCodexAppServerVersion(startOptions.command, client.getServerVersion());
3352
3246
  } catch (error) {
3353
- if (startOptions.commandSource === "resolved-managed" && index < startOptionsCandidates.length - 1 && isUnsupportedCodexAppServerVersionError(error)) continue;
3247
+ if (yieldInstalledCodex(index, startOptions.command, error) || startOptions.commandSource === "resolved-managed" && index < startOptionsCandidates.length - 1 && isUnsupportedCodexAppServerVersionError(error)) continue;
3354
3248
  throw error;
3355
3249
  }
3356
3250
  assertStartupCurrent();
@@ -3379,7 +3273,7 @@ async function startInitializedCodexAppServerClientOnce(params) {
3379
3273
  ...params.authProfileStore ? { authProfileStore: params.authProfileStore } : {},
3380
3274
  config: params.config,
3381
3275
  onAuthRefreshFailure: () => retireSharedCodexAppServerClientIfCurrent(client)
3382
- });
3276
+ }, () => refreshSharedClientIdleRetirement(client));
3383
3277
  assertStartupCurrent();
3384
3278
  observeAcquire(params, { boundary: "auth-handoff" });
3385
3279
  const authHandoff = await waitForStartup(() => applyCodexAppServerAuthProfile({
@@ -3391,34 +3285,24 @@ async function startInitializedCodexAppServerClientOnce(params) {
3391
3285
  startOptions,
3392
3286
  config: params.config,
3393
3287
  assertCurrent: assertStartupCurrent,
3288
+ assertCurrentAsync: params.assertCurrentAsync,
3394
3289
  ...params.authProfileStore ? { authProfileStore: params.authProfileStore } : {}
3395
3290
  }));
3396
3291
  const ownsInference = startOptions.transport === "stdio" && nativeCommandAtStart && !isCodexAppServerProxyLaunch(startOptions.args);
3397
3292
  if (isCodexResponsesOAuth(params.preparedAuth) && (!ownsInference || desktopGeneration || desktopCommand)) throw new Error("ChatGPT subscription sharing requires a managed local Codex process.");
3398
3293
  if (ownsInference) {
3399
3294
  const prepared = params.preparedAuth;
3400
- ownCodexInferenceClient(client, startOptions, isCodexResponsesOAuth(prepared) && prepared?.kind === "profile" ? createCodexResponsesOAuth({
3295
+ ownCodexInferenceClient(client, startOptions, isCodexResponsesOAuth(prepared) && prepared?.kind === "profile" ? await waitForStartup(() => createCodexResponsesOAuth({
3401
3296
  profileId: prepared.profileId,
3402
3297
  store: prepared.store,
3403
3298
  fingerprint: prepared.snapshot.secretFreeCacheKey,
3404
3299
  agentDir: params.agentDir,
3405
3300
  config: params.config
3406
- }) : void 0);
3301
+ })) : void 0);
3407
3302
  }
3408
3303
  recordCodexAppServerAuthHandoff(client, authHandoff);
3409
3304
  if (runtimeArtifactModule && runtimeArtifact) runtimeArtifactModule.bindCodexAppServerRuntimeArtifact(client, runtimeArtifact);
3410
3305
  assertStartupCurrent();
3411
- const fenceKey = resolveCodexNativeConfigFenceKey({ client });
3412
- if (fenceKey) client.setThreadSessionRequestGuard(async (options) => {
3413
- const release = await acquireCodexNativeConfigFence(fenceKey, options);
3414
- try {
3415
- assertCodexAppServerClientStartSelectionCurrent({ client });
3416
- return release;
3417
- } catch (error) {
3418
- release();
3419
- throw error;
3420
- }
3421
- }, () => Boolean(retireSharedCodexAppServerClientIfCurrent(client)));
3422
3306
  ready = true;
3423
3307
  observeAcquire(params, { boundary: "ready" });
3424
3308
  return client;
@@ -3431,34 +3315,11 @@ async function startInitializedCodexAppServerClientOnce(params) {
3431
3315
  }
3432
3316
  throw new Error("Managed Codex app-server fallback candidates were exhausted.");
3433
3317
  }
3434
- function isCodexComputerUseCandidateArtifactsUnavailableError(error) {
3435
- return error !== null && typeof error === "object" && "code" in error && error.code === "CODEX_COMPUTER_USE_CANDIDATE_ARTIFACTS_UNAVAILABLE";
3436
- }
3437
- function resolveManagedFallbackStartOptions(startOptions) {
3438
- const commands = [startOptions.command, ...startOptions.managedFallbackCommandPaths ?? []];
3439
- const candidates = [];
3440
- for (const [index, command] of commands.entries()) {
3441
- const managedFallbackCommandPaths = commands.slice(index + 1);
3442
- const candidate = {
3443
- ...startOptions,
3444
- command
3445
- };
3446
- if (managedFallbackCommandPaths.length === 0) delete candidate.managedFallbackCommandPaths;
3447
- else candidate.managedFallbackCommandPaths = managedFallbackCommandPaths;
3448
- candidates.push(candidate);
3449
- }
3450
- return candidates;
3451
- }
3452
3318
  function detachCurrentSharedClient(client) {
3453
3319
  const entry = client && getCurrentSharedClientEntry(client);
3454
3320
  return Boolean(entry && getSharedCodexAppServerClientState().clients.delete(entry.key));
3455
3321
  }
3456
- function clearSharedCodexAppServerClientIfCurrent(client) {
3457
- if (!detachCurrentSharedClient(client)) return false;
3458
- client.close();
3459
- return true;
3460
- }
3461
- /** Captures a revocable observation of the exact shared client and native account/config. */
3322
+ /** Captures the physical client lifetime for passive catalog reads. */
3462
3323
  function captureSharedCodexAppServerCatalogLifetime(client) {
3463
3324
  const isCurrent = captureSharedClientRegistration(client);
3464
3325
  const revision = client.getModelCatalogRevision();
@@ -3468,8 +3329,7 @@ function captureSharedCodexAppServerCatalogLifetime(client) {
3468
3329
  function captureSharedClientRegistration(client) {
3469
3330
  const state = getSharedCodexAppServerClientState();
3470
3331
  const entry = getCurrentSharedClientEntry(client);
3471
- const generation = readCodexAppServerClientDesktopGeneration(client);
3472
- return () => entry !== void 0 && state.clients.get(entry.key) === entry && entry.client === client && !entry.closeWhenIdle && !entry.closeError && !client.getCloseError() && (!generation || isCodexDesktopGenerationCurrent(generation));
3332
+ return () => entry !== void 0 && state.clients.get(entry.key) === entry && entry.client === client && !entry.closeWhenIdle && !entry.closeError && !client.getCloseError();
3473
3333
  }
3474
3334
  function retainSharedCodexAppServerClientIfCurrent(client) {
3475
3335
  const entry = getCurrentSharedClientEntry(client);
@@ -3483,47 +3343,10 @@ function captureCodexAppServerClientLifetime(client, requiredOwnership) {
3483
3343
  const isCurrent = requiredOwnership !== "connection" && state.isolatedClients.has(client) ? () => state.isolatedClients.has(client) && !client.getCloseError() : captureSharedClientRegistration(client);
3484
3344
  const assertCurrent = () => {
3485
3345
  if (!isCurrent()) throw new CodexAdoptedThreadActiveError("Codex app-server connection changed during thread preparation; reconnect before continuing");
3486
- assertCodexAppServerClientStartSelectionCurrent({ client });
3487
3346
  };
3488
3347
  assertCurrent();
3489
3348
  return assertCurrent;
3490
3349
  }
3491
- function createOlderDesktopGenerationDrainWait(params) {
3492
- const targetHome = resolveCodexNativeConfigFenceKey({
3493
- startOptions: params.startOptions,
3494
- agentDir: params.agentDir
3495
- });
3496
- if (!targetHome) return {
3497
- promise: Promise.resolve(),
3498
- cancel: () => void 0
3499
- };
3500
- const state = getSharedCodexAppServerClientState();
3501
- const { promise, resolve: resolveWait } = createDeferred();
3502
- const cancel = () => {
3503
- state.desktopGenerationDrainChecks.delete(check);
3504
- resolveWait();
3505
- };
3506
- const check = () => {
3507
- if (!hasLiveOlderDesktopGenerationClient({
3508
- state,
3509
- generation: params.generation,
3510
- targetHome
3511
- })) cancel();
3512
- };
3513
- state.desktopGenerationDrainChecks.add(check);
3514
- check();
3515
- return {
3516
- promise,
3517
- cancel
3518
- };
3519
- }
3520
- function hasLiveOlderDesktopGenerationClient(params) {
3521
- for (const clients of [params.state.liveClients, params.state.isolatedClients]) for (const client of clients) {
3522
- const metadata = params.state.startMetadata.get(client);
3523
- if (metadata?.desktopGeneration && metadata.desktopGeneration.epoch < params.generation.epoch && resolveCodexNativeConfigFenceKey({ client }) === params.targetHome) return true;
3524
- }
3525
- return false;
3526
- }
3527
3350
  async function clearSharedCodexAppServerClientIfCurrentAndWait(client, options) {
3528
3351
  if (!detachCurrentSharedClient(client)) return false;
3529
3352
  await client.closeAndWait(options);
@@ -3555,4 +3378,4 @@ function clearSharedCodexAppServerClientIfCurrentAndUnclaimed(client) {
3555
3378
  };
3556
3379
  }
3557
3380
  //#endregion
3558
- export { createCodexEphemeralThreadPolicy as $, bindCodexInferenceThread as A, isCodexAppServerClientRuntimeLive as B, CodexThreadBindingConflictError as C, nativeHookRelayUnregisterQueue as D, isCodexContextRestartSelectionChangedError as E, consumeCodexAppServerLiveThread as F, readCodexClientSessionMeta as G, isCodexAppServerLiveThreadProtected as H, ensureCodexAppServerClientRuntime as I, revertCodexAppServerLiveThreadInstructions as J, releaseCodexAppServerLiveThread as K, forgetCodexWorkspaceReferences as L, getCodexInferenceThreadQualification as M, prepareCodexInferenceThreadConfig as N, acquireCodexNativeConfigFence as O, claimCodexAppServerLiveThread as P, rememberCodexRateLimitsRead as Q, hasCodexAppServerLiveThread as R, CodexAdoptedThreadActiveError as S, CodexThreadStartRequestError as T, prepareCodexWorkspaceReferences as U, isCodexAppServerLiveThreadClaimed as V, protectCodexAppServerLiveThread as W, readCodexRateLimitsRevision as X, unsubscribeCodexAppServerLiveThread as Y, readRecentCodexRateLimits as Z, retainSharedCodexAppServerClientIfCurrent as _, clearSharedCodexAppServerClientIfCurrentAndUnclaimed as a, hasLegacyCodexComputerUseMcpPolicy as at, withLeasedCodexAppServerClientStartSelectionRetry as b, getLeasedSharedCodexAppServerClient as c, ensureCodexComputerUseSharedPluginCache as ct, readCodexAppServerClientDesktopGeneration as d, TURN_FINALIZE_DRAIN_ABORT_GRACE_MS as dt, reconcileCodexComputerUseStartArtifacts as et, readCodexAppServerClientDesktopGenerationFingerprint as f, TURN_TERMINAL_SETTLEMENT_TIMEOUT_MS as ft, resolveCodexNativeConfigFenceKey as g, withCodexStartupTimeout as gt, releaseLeasedSharedCodexAppServerClient as h, resolveCodexStartupTimeoutMs as ht, clearSharedCodexAppServerClientIfCurrent as i, resolveClientManagedBundledMarketplacePath as it, getCodexInferenceThread as j, assertCodexInferenceRouteConfig as k, getSharedCodexAppServerClient as l, assertNotSymlink as lt, releaseCodexAppServerClientLease as m, resolveCodexGatewayTimeoutWithGraceMs as mt, captureCodexAppServerClientLifetime as n, resolveCodexAppServerPreparedAuthHandoff as nt, clearSharedCodexAppServerClientIfCurrentAndWait as o, isLegacyCodexComputerUsePluginDisabled as ot, readCodexAppServerClientProcessIdentity as p, isCodexAppServerStartupError as pt, retainCodexAppServerLiveThread as q, captureSharedCodexAppServerCatalogLifetime as r, resolveBundledComputerUseMarketplacePath as rt, createIsolatedCodexAppServerClient as s, resolveManagedCodexComputerUseConfig as st, assertCodexAppServerClientStartSelectionCurrent as t, resolveCodexAppServerAuthAccountCacheKey as tt, isCodexAppServerStartSelectionChangedError as u, CodexAppServerStartupError 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 };
3381
+ export { resolveBundledComputerUseMarketplacePath as $, hasCodexAppServerLiveThread as A, retainCodexAppServerLiveThread as B, getCodexInferenceThread as C, consumeCodexAppServerLiveThread as D, claimCodexAppServerLiveThread as E, prepareCodexWorkspaceReferences as F, rememberCodexRateLimitsRead as G, unsubscribeCodexAppServerLiveThread as H, protectCodexAppServerLiveThread as I, recordCodexTurnForkSettings as J, createCodexEphemeralThreadPolicy as K, readCodexClientSessionMeta as L, isCodexAppServerClientRuntimeLive as M, isCodexAppServerLiveThreadClaimed as N, ensureCodexAppServerClientRuntime as O, isCodexAppServerLiveThreadProtected as P, resolveCodexAppServerPreparedAuthHandoff as Q, readCodexLiveThreadEphemeralPolicy as R, bindCodexInferenceThread as S, prepareCodexInferenceThreadConfig as T, readCodexRateLimitsRevision as U, revertCodexAppServerLiveThreadInstructions as V, readRecentCodexRateLimits as W, reconcileCodexComputerUseStartArtifacts as X, requireCodexThreadForkSettings as Y, resolveCodexAppServerAuthAccountCacheKey as Z, CodexThreadBindingConflictError as _, createIsolatedCodexAppServerClient as a, assertNotSymlink as at, nativeHookRelayUnregisterQueue as b, readCodexAppServerClientDesktopGeneration as c, TURN_TERMINAL_SETTLEMENT_TIMEOUT_MS as ct, releaseCodexAppServerClientLease as d, resolveCodexStartupTimeoutMs as dt, resolveClientManagedBundledMarketplacePath as et, releaseLeasedSharedCodexAppServerClient as f, withCodexStartupTimeout as ft, CodexAdoptedThreadActiveError as g, withCodexAppServerClientRequestScope as h, clearSharedCodexAppServerClientIfCurrentAndWait as i, ensureCodexComputerUseSharedPluginCache as it, hasCodexAppServerSiblingThreadWork as j, forgetCodexWorkspaceReferences as k, readCodexAppServerClientDesktopGenerationFingerprint as l, isCodexAppServerStartupError as lt, shared_client_exports as m, captureSharedCodexAppServerCatalogLifetime as n, isLegacyCodexComputerUsePluginDisabled as nt, getLeasedSharedCodexAppServerClient as o, CodexAppServerStartupError as ot, retainSharedCodexAppServerClientIfCurrent as p, recordCodexThreadForkSettings as q, clearSharedCodexAppServerClientIfCurrentAndUnclaimed as r, resolveManagedCodexComputerUseConfig as rt, getSharedCodexAppServerClient as s, TURN_FINALIZE_DRAIN_ABORT_GRACE_MS as st, captureCodexAppServerClientLifetime as t, hasLegacyCodexComputerUseMcpPolicy as tt, readCodexAppServerClientProcessIdentity as u, resolveCodexGatewayTimeoutWithGraceMs as ut, CodexThreadClientReplacementError as v, getCodexInferenceThreadQualification as w, assertCodexInferenceRouteConfig as x, CodexThreadStartRequestError as y, releaseCodexAppServerLiveThread as z };