@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
package/README.md CHANGED
@@ -26,7 +26,7 @@ Local discovery reads native provenance from plain or compressed rollouts. A fai
26
26
 
27
27
  With `appServer.remoteWorkspaceRoot`, OpenClaw maps workspace-relative paths to the remote root. Local filesystem-root workspaces, including `/` and Windows drive roots, follow the same mapping.
28
28
 
29
- A supervised OpenClaw Chat cannot be deleted while its model-selection lock protects the native binding. Before native archive, OpenClaw checks the exact target and every non-archived spawned descendant reported by Codex; any active OpenClaw binding blocks the operation. Descendant pagination errors, cycles, and safety-limit exhaustion also fail closed. Codex still does not expose a conditional archive operation or cross-process runner lease, so the confirmation covers unknown native clients and the race between the status read and archive request.
29
+ A supervised OpenClaw Chat cannot be deleted while its model-selection lock protects the native binding. Before native archive, OpenClaw checks the exact target and every non-archived spawned descendant reported by Codex; any active OpenClaw binding blocks the operation. Descendant pagination errors, cycles, and safety-limit exhaustion also block archive. Codex still does not expose a conditional archive operation or cross-process runner lease, so the confirmation covers unknown native clients and the race between the status read and archive request.
30
30
 
31
31
  Disabling or uninstalling the plugin leaves supervised Chats locked and unavailable rather than rerouting them. Reinstall or re-enable the same plugin and restart the Gateway to resume those Chats.
32
32
 
@@ -34,9 +34,9 @@ These shell commands differ from the in-chat `/codex` runtime commands. In parti
34
34
 
35
35
  Native Codex plugin catalogs are discoverable with `/codex plugins available`, including repository marketplaces declared in `.agents/plugins/marketplace.json` in the bound workspace. An owner or `operator.admin` can install and authorize an exact plugin with `/codex plugins install <plugin>@<marketplace>`. The owner-scoped `codex_plugins` agent tool only reads marketplace metadata; installation and policy changes stay on authenticated `/codex` management commands. Explicitly installing a plugin trusts its skills, apps, MCP servers, and hooks.
36
36
 
37
- Cached app inventory diagnostics reflect the current refresh or invalidation. Failures from superseded requests remain logged without replacing that newer status.
37
+ Catalog and app-inventory refreshes are best effort while settings, installed plugins, or desktop artifacts change. An in-flight read can publish its captured metadata; a later refresh, cache expiry, or restart picks up the change. Normal parallel refreshes retain unrelated apps, while authorization is checked separately when work executes. An app-server or desktop replacement during an operation may return an error instead of automatically replaying the operation.
38
38
 
39
- For a supervised branch, Codex App Server selects the snapshot fork's model and provider from its current native configuration. OpenClaw starts the canonical harness thread with exactly that returned pair. Codex persists the canonical thread's native selection, and later resumes preserve it because OpenClaw omits model and provider overrides. OpenClaw cannot substitute its outer runtime, model, or fallback. The returned initial pair can differ from the source's last recorded model.
39
+ For a supervised branch, Codex App Server selects the snapshot fork's model and provider from its current native configuration. OpenClaw starts the OpenClaw harness thread with exactly that returned pair. Codex persists the harness thread's native selection, and later resumes preserve it because OpenClaw omits model and provider overrides. OpenClaw cannot substitute its outer runtime, model, or fallback. The returned initial pair can differ from the source's last recorded model.
40
40
 
41
41
  The visible-history mirror keeps at most 200 user or assistant messages, 512 KiB total, and 64 KiB per message. Image inputs become `[Image attachment]`; image data and local paths are not copied.
42
42
 
@@ -46,4 +46,11 @@ Settled-turn finalization uses the same configured Codex App Server transport as
46
46
 
47
47
  When settled-turn recovery rejects history, the `codex settled-turn finalization context capture failed` warning includes a stable `reason`, such as `item_limit`, `byte_limit`, `field_limit`, `unsupported_user_image`, or `snapshot_invalidated`. Unknown failures use `history_read_failed`. The warning excludes transcript content and exception text. Rejected history remains unavailable for finalization, and completed actions are never replayed.
48
48
 
49
+ The `codex_app_server.item` agent-event stream includes native item lifecycle events
50
+ and raw function, custom/code-mode, local-shell, and tool-search call receipts.
51
+ Calls publish `phase: "started"` and recorded outputs publish `phase: "completed"`,
52
+ correlated by `itemId` (the native `call_id`). Raw receipt events carry only phase,
53
+ item ID, and type, not arguments or results. An outer code-mode call remains open
54
+ even when its child command items have completed.
55
+
49
56
  See the [Codex harness](https://docs.openclaw.ai/plugins/codex-harness) and [Codex supervision](https://docs.openclaw.ai/plugins/codex-supervision) guides.
@@ -1,13 +1,14 @@
1
1
  import { n as isCodexAppServerProxyLaunch } from "./launch-args-DbFCehO7.mjs";
2
- import { t as buildCodexAppServerUsageSnapshot } from "./rate-limits-CI8pTPqL.mjs";
3
- import { t as readCodexAppServerUsage } from "./request-Bo0kKABI.mjs";
4
- import "./config-C1YVVLEA.mjs";
5
- import { n as resolveCodexAppServerRuntimeOptions } from "./config-runtime-DWzK-k0n.mjs";
6
- import { a as resolveCodexAppServerAuthProfileStore } from "./auth-profile-CgHQ8Vot.mjs";
2
+ import { t as buildCodexAppServerUsageSnapshot } from "./rate-limits-BpfURnuy.mjs";
3
+ import { t as readCodexAppServerUsage } from "./request-ePeNJrOd.mjs";
4
+ import "./config-BfrAlTMT.mjs";
5
+ import { n as resolveCodexAppServerRuntimeOptions } from "./config-runtime-BZRizyuG.mjs";
6
+ import { a as resolveCodexAppServerAuthProfileStore } from "./auth-profile-auwzSwwy.mjs";
7
7
  import { isDeepStrictEqual } from "node:util";
8
8
  import { listAgentIds, resolveAgentDir } from "openclaw/plugin-sdk/agent-scope-runtime";
9
9
  import { z } from "zod";
10
10
  import { ErrorCodes, errorShape } from "openclaw/plugin-sdk/gateway-runtime";
11
+ import { ensureAuthProfileStore } from "openclaw/plugin-sdk/provider-auth";
11
12
  //#region extensions/codex/src/account-usage-runtime.ts
12
13
  const paramsSchema = z.object({
13
14
  agentId: z.string().min(1),
@@ -28,19 +29,24 @@ async function handleCodexAccountUsage({ params, respond, context, signal, hasCu
28
29
  }
29
30
  try {
30
31
  const agentDir = resolveAgentDir(config, agentId);
31
- const readStore = () => resolveCodexAppServerAuthProfileStore({
32
+ const store = structuredClone(await resolveCodexAppServerAuthProfileStore({
32
33
  agentDir,
33
34
  authProfileId: profileId,
34
35
  config
35
- });
36
- const store = structuredClone(readStore());
36
+ }));
37
37
  const credential = store.profiles[profileId];
38
38
  if (!credential || credential.provider !== "openai" || credential.type === "api_key") {
39
39
  invalid("Select a saved Codex subscription login.");
40
40
  return;
41
41
  }
42
42
  const assertCurrent = () => {
43
- if (signal?.aborted || hasCurrentClientAuthority?.() === false || context.getRuntimeConfig() !== config || !isDeepStrictEqual(readStore().profiles[profileId], store.profiles[profileId])) throw new Error("Account credentials changed. Refresh Models and try again.");
43
+ if (signal?.aborted || hasCurrentClientAuthority?.() === false || context.getRuntimeConfig() !== config || !isDeepStrictEqual(ensureAuthProfileStore(agentDir, {
44
+ profileId,
45
+ allowKeychainPrompt: false,
46
+ config,
47
+ externalCliProviderIds: ["openai"],
48
+ externalCliProfileIds: [profileId]
49
+ }).profiles[profileId], store.profiles[profileId])) throw new Error("Account credentials changed. Refresh Models and try again.");
44
50
  };
45
51
  assertCurrent();
46
52
  const { start } = resolveCodexAppServerRuntimeOptions({ pluginConfig: config.plugins?.entries?.codex?.config });
@@ -1,4 +1,4 @@
1
- import { n as canUseCodexModelBackedApprovalsReviewerForModel } from "./config-C1YVVLEA.mjs";
1
+ import { n as canUseCodexModelBackedApprovalsReviewerForModel } from "./config-BfrAlTMT.mjs";
2
2
  //#region extensions/codex/src/app-server/app-server-policy.ts
3
3
  function resolveCodexAppServerForModelProvider(params) {
4
4
  return params.appServer.approvalsReviewer === "user" || canUseCodexModelBackedApprovalsReviewerForModel({
@@ -1,13 +1,13 @@
1
- import { s as resolveCodexAppServerFallbackApiKeyCacheKey } from "./auth-cache-key-f8ODJ_OX.mjs";
2
- import { a as defaultCodexAppInventoryCache, r as buildCodexPluginAppCacheKey } from "./plugin-app-cache-key-Bg9DbDI6.mjs";
3
- import { r as requestCodexAppServerJson } from "./request-Bo0kKABI.mjs";
4
- import { r as isOpenAiCuratedMarketplaceName, u as CODEX_PLUGINS_MARKETPLACE_NAME } from "./plugin-inventory-CYgdo14P.mjs";
5
- import "./config-C1YVVLEA.mjs";
6
- import { n as resolveCodexAppServerRuntimeOptions } from "./config-runtime-DWzK-k0n.mjs";
7
- import { i as resolveCodexAppServerAuthProfileIdForAgent } from "./auth-profile-CgHQ8Vot.mjs";
8
- import { c as getLeasedSharedCodexAppServerClient, h as releaseLeasedSharedCodexAppServerClient, o as clearSharedCodexAppServerClientIfCurrentAndWait, tt as resolveCodexAppServerAuthAccountCacheKey } from "./shared-client-BCx1wbyA.mjs";
9
- import { t as ensureCodexPluginActivation } from "./plugin-activation-D7WkJMvU.mjs";
10
- import { CODEX_PLUGIN_CONFIG_PATH, buildCodexMigrationPlan, buildCodexPluginsConfigValue, hasCodexPluginConfigConflict, n as resolveCodexConfigPatchMode, readCodexPluginMigrationConfigEntry, t as createCodexAuthItemApplier } from "./plan-41-YOBMq.mjs";
1
+ import { s as resolveCodexAppServerFallbackApiKeyCacheKey } from "./auth-cache-key-CVcYw8HD.mjs";
2
+ import { a as defaultCodexAppInventoryCache, r as buildCodexPluginAppCacheKey } from "./plugin-app-cache-key-DRb-niJc.mjs";
3
+ import { r as requestCodexAppServerJson } from "./request-ePeNJrOd.mjs";
4
+ import { r as isOpenAiCuratedMarketplaceName, u as CODEX_PLUGINS_MARKETPLACE_NAME } from "./plugin-inventory-DE9wcaeH.mjs";
5
+ import "./config-BfrAlTMT.mjs";
6
+ import { n as resolveCodexAppServerRuntimeOptions } from "./config-runtime-BZRizyuG.mjs";
7
+ import { i as resolveCodexAppServerAuthProfileIdForAgent } from "./auth-profile-auwzSwwy.mjs";
8
+ import { Z as resolveCodexAppServerAuthAccountCacheKey, f as releaseLeasedSharedCodexAppServerClient, i as clearSharedCodexAppServerClientIfCurrentAndWait, o as getLeasedSharedCodexAppServerClient } from "./shared-client-CE_uY0A1.mjs";
9
+ import { t as ensureCodexPluginActivation } from "./plugin-activation-CXPWe-hl.mjs";
10
+ import { CODEX_PLUGIN_CONFIG_PATH, buildCodexMigrationPlan, buildCodexPluginsConfigValue, hasCodexPluginConfigConflict, n as resolveCodexConfigPatchMode, readCodexPluginMigrationConfigEntry, t as createCodexAuthItemApplier } from "./plan-B4cHgqNv.mjs";
11
11
  import { uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
12
12
  import { parseStrictNonNegativeInteger } from "openclaw/plugin-sdk/number-runtime";
13
13
  import path from "node:path";
@@ -250,7 +250,7 @@ function isCodexPluginLoadWarningItem(item) {
250
250
  async function buildTargetCodexPluginAppCacheKey(ctx) {
251
251
  const targets = resolvePlannedMigrationTargets(ctx);
252
252
  const appServer = resolveTargetCodexAppServer(ctx);
253
- const authProfileId = resolveCodexAppServerAuthProfileIdForAgent({
253
+ const authProfileId = await resolveCodexAppServerAuthProfileIdForAgent({
254
254
  agentDir: targets.agentDir,
255
255
  config: ctx.config
256
256
  });
@@ -1,9 +1,9 @@
1
- import { w as retireSharedCodexAppServerClientIfCurrent } from "./auth-cache-key-f8ODJ_OX.mjs";
2
- import { a as codexPrewriteRejectionCause, o as isCodexAppServerOverloadError, r as CodexAppServerRpcError } from "./rpc-error-C98SHchT.mjs";
3
- import { Y as unsubscribeCodexAppServerLiveThread, pt as isCodexAppServerStartupError, u as isCodexAppServerStartSelectionChangedError } from "./shared-client-BCx1wbyA.mjs";
4
- import { I as isCodexAppServerBrokenPipeError, c as isCodexAppServerRequestTimeoutError } from "./client-D93nbdB8.mjs";
5
- import { n as getCodexAppServerTurnRouter } from "./turn-router-DBVMToGo.mjs";
6
- import { t as __exportAll } from "./session-binding-sidecars-DD-enC8w.mjs";
1
+ import { D as retireSharedCodexAppServerClientIfCurrent } from "./auth-cache-key-CVcYw8HD.mjs";
2
+ import { a as codexPrewriteRejectionCause, o as isCodexAppServerOverloadError, r as CodexAppServerRpcError } from "./rpc-error-DemqqaxE.mjs";
3
+ import { H as unsubscribeCodexAppServerLiveThread, lt as isCodexAppServerStartupError } from "./shared-client-CE_uY0A1.mjs";
4
+ import { N as isCodexAppServerBrokenPipeError, s as isCodexAppServerRequestTimeoutError } from "./client-BS8X7HmG.mjs";
5
+ import { n as getCodexAppServerTurnRouter } from "./turn-router-Dbw17k3K.mjs";
6
+ import { t as __exportAll } from "./session-binding-sidecars-BNSS6WL4.mjs";
7
7
  import { createDeferred } from "openclaw/plugin-sdk/extension-shared";
8
8
  import { AgentHarnessPreflightError, embeddedAgentLog } from "openclaw/plugin-sdk/agent-harness-runtime";
9
9
  //#region extensions/codex/src/app-server/attempt-client-cleanup.ts
@@ -71,8 +71,12 @@ async function interruptCodexTurnAndWaitBestEffort(client, params) {
71
71
  };
72
72
  let cancelWatch;
73
73
  try {
74
+ params.assertCurrent?.();
74
75
  if (!params.turnId) {
75
- await client.request("turn/interrupt", requestParams, { timeoutMs });
76
+ await client.request("turn/interrupt", requestParams, {
77
+ timeoutMs,
78
+ assertCurrent: params.assertCurrent
79
+ });
76
80
  return true;
77
81
  }
78
82
  const deadline = performance.now() + timeoutMs;
@@ -87,7 +91,9 @@ async function interruptCodexTurnAndWaitBestEffort(client, params) {
87
91
  if (completion.state !== "pending") return await completion.completion;
88
92
  const requestInterrupt = async () => {
89
93
  try {
94
+ params.assertCurrent?.();
90
95
  await client.request("turn/interrupt", requestParams, {
96
+ assertCurrent: params.assertCurrent,
91
97
  timeoutMs: Math.max(1, deadline - performance.now()),
92
98
  signal: completion.settledSignal
93
99
  });
@@ -149,7 +155,7 @@ async function unsubscribeCodexThreadBestEffort(client, params) {
149
155
  function shouldRetireCodexStartupClient(error, spawnedBy, signal) {
150
156
  const cause = codexPrewriteRejectionCause(error);
151
157
  if (signal.aborted || isCodexAppServerStartupError(cause) || isCodexAppServerRequestTimeoutError(cause)) return true;
152
- return !isCodexAppServerStartSelectionChangedError(cause) && !isCodexAppServerOverloadError(cause) && !(cause instanceof AgentHarnessPreflightError && cause.scope === void 0) && (isCodexAppServerBrokenPipeError(cause) || !spawnedBy);
158
+ return !isCodexAppServerOverloadError(cause) && !(cause instanceof AgentHarnessPreflightError && cause.scope === void 0) && (isCodexAppServerBrokenPipeError(cause) || !spawnedBy);
153
159
  }
154
160
  //#endregion
155
161
  export { attempt_client_cleanup_exports as a, isCodexNoActiveTurnInterruptError as c, terminateCodexBackgroundTerminals as d, unsubscribeCodexThreadBestEffort as f, assertCodexThreadResumeSubscription as i, retireUnsafeCodexTurnClientBestEffort as l, CODEX_APP_SERVER_UNSUBSCRIBE_TIMEOUT_MS as n, closeCodexStartupClientBestEffort as o, CodexAppServerUnsafeSubscriptionError as r, interruptCodexTurnAndWaitBestEffort as s, CODEX_APP_SERVER_INTERRUPT_TIMEOUT_MS as t, shouldRetireCodexStartupClient as u };
@@ -0,0 +1 @@
1
+ export { agentHarnessAttemptTerminal as t } from "openclaw/plugin-sdk/agent-harness-runtime";
@@ -1,5 +1,5 @@
1
- import { r as flattenCodexDynamicToolFunctions } from "./protocol-CANUwXJ3.mjs";
2
- import { I as isMessageOnlyCodexSourceReply } from "./thread-requests-BgzJwJtS.mjs";
1
+ import { n as flattenCodexDynamicToolFunctions } from "./protocol-CaPAVwe9.mjs";
2
+ import { I as isMessageOnlyCodexSourceReply } from "./thread-requests-BjawdIVV.mjs";
3
3
  import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
4
4
  import path from "node:path";
5
5
  import { buildAgentWorkspaceInstructionSnapshot, buildBootstrapContextForFiles, embeddedAgentLog, prepareAgentWorkspaceContext } from "openclaw/plugin-sdk/agent-harness-runtime";
@@ -1,5 +1,5 @@
1
- import { i as isCodexResponsesOAuthCredential, o as resolveCodexResponsesOAuthProfileFingerprint } from "./responses-oauth-twnuTaAa.mjs";
2
- import { t as __exportAll } from "./session-binding-sidecars-DD-enC8w.mjs";
1
+ import { i as isCodexResponsesOAuthCredential, o as resolveCodexResponsesOAuthProfileFingerprint } from "./responses-oauth-CCV7aVYF.mjs";
2
+ import { t as __exportAll } from "./session-binding-sidecars-BNSS6WL4.mjs";
3
3
  import { resolveApiKeyForProfile } from "openclaw/plugin-sdk/agent-runtime";
4
4
  import { fingerprintResolvedAuthProfileCredential } from "openclaw/plugin-sdk/agent-harness-runtime";
5
5
  import { resolveOpenAICodexAuthIdentity } from "openclaw/plugin-sdk/provider-auth";
@@ -1,6 +1,6 @@
1
- import { n as defineCodexBuildState } from "./build-state-Ds14X10-.mjs";
2
- import { u as resolveMacOSDesktopCodexAppPathCandidates } from "./managed-binary-BtIjV7yN.mjs";
3
- import { n as resolveCodexAppServerSpawnEnv } from "./transport-stdio-CRWTkKOn.mjs";
1
+ import { n as defineCodexBuildState } from "./build-state-VcujMRqP.mjs";
2
+ import { y as resolveMacOSDesktopCodexAppPathCandidates } from "./managed-binary-DbKvGXKl.mjs";
3
+ import { n as resolveCodexAppServerSpawnEnv } from "./transport-stdio-Bq160Dhv.mjs";
4
4
  import { isRecord, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
5
5
  import { createHash } from "node:crypto";
6
6
  import fs, { constants, existsSync, watch } from "node:fs";
@@ -10,6 +10,7 @@ import fs$1 from "node:fs/promises";
10
10
  import { extractErrorCode } from "openclaw/plugin-sdk/error-runtime";
11
11
  import { sha256File } from "openclaw/plugin-sdk/file-access-runtime";
12
12
  import { sleepWithAbort } from "openclaw/plugin-sdk/retry-runtime";
13
+ import { racePromiseWithAbortSignal } from "openclaw/plugin-sdk/time-runtime";
13
14
  import { readSecretFile } from "openclaw/plugin-sdk/secret-file";
14
15
  //#region extensions/codex/src/app-server/desktop-generation-fingerprint.ts
15
16
  const MAX_COMPUTER_USE_PLUGIN_TREE_ENTRIES = 4096;
@@ -77,7 +78,6 @@ async function readCodexDesktopArtifactTreeFingerprint(root) {
77
78
  if (entryStat.isDirectory()) await visit(entryPath, relativePath, entryStat);
78
79
  else hash.update(`entry\0${relativePath}\0${await statFingerprint(entryPath)}\0`);
79
80
  }
80
- if (!sameStat(before, await fs$1.lstat(directory, { bigint: true }))) throw new Error(`Codex desktop artifact changed while fingerprinting: ${directory}`);
81
81
  };
82
82
  await visit(root, ".", rootStat);
83
83
  return hash.digest("hex");
@@ -87,35 +87,28 @@ async function statFingerprint(filePath) {
87
87
  const entry = await fs$1.lstat(filePath, { bigint: true });
88
88
  const type = entry.isSymbolicLink() ? "link" : entry.isDirectory() ? "directory" : entry.isFile() ? "file" : "other";
89
89
  const own = statTuple(entry);
90
- if (!entry.isSymbolicLink()) return `${type}:${own}:${entry.isFile() ? await readFileFingerprint(filePath, entry, false) : ""}`;
90
+ if (!entry.isSymbolicLink()) return `${type}:${own}:${entry.isFile() ? await readFileFingerprint(filePath, false) : ""}`;
91
91
  const [link, realPath, target] = await Promise.all([
92
92
  fs$1.readlink(filePath),
93
93
  fs$1.realpath(filePath),
94
94
  fs$1.stat(filePath, { bigint: true })
95
95
  ]);
96
- const content = target.isFile() ? await readFileFingerprint(filePath, target, true) : "";
96
+ const content = target.isFile() ? await readFileFingerprint(filePath, true) : "";
97
97
  return `${type}:${own}:${link}:${realPath}:${statTuple(target)}:${content}`;
98
98
  } catch (error) {
99
99
  return missingFingerprint(error);
100
100
  }
101
101
  }
102
- async function readFileFingerprint(filePath, expected, followsSymlink) {
102
+ async function readFileFingerprint(filePath, followsSymlink) {
103
103
  const noFollow = followsSymlink ? 0 : constants.O_NOFOLLOW ?? 0;
104
104
  const handle = await fs$1.open(filePath, constants.O_RDONLY | noFollow);
105
105
  try {
106
106
  const before = await handle.stat({ bigint: true });
107
- if (!sameStat(before, expected)) throw new Error(`Codex desktop artifact changed while fingerprinting: ${filePath}`);
108
- const hash = await sha256File(handle, { maxBytes: Number(before.size) });
109
- const after = await handle.stat({ bigint: true });
110
- if (BigInt(hash.bytes) !== before.size || !sameStat(before, after)) throw new Error(`Codex desktop artifact changed while fingerprinting: ${filePath}`);
111
- return hash.digest;
107
+ return (await sha256File(handle, { maxBytes: Number(before.size) })).digest;
112
108
  } finally {
113
109
  await handle.close();
114
110
  }
115
111
  }
116
- function sameStat(left, right) {
117
- return statTuple(left) === statTuple(right);
118
- }
119
112
  function statTuple(stat) {
120
113
  return [
121
114
  stat.dev,
@@ -137,34 +130,29 @@ const SETTLE_DELAY_MS = 1e3;
137
130
  /** Coalesces filesystem invalidations into one stable desktop generation. */
138
131
  function createCodexDesktopGenerationOwner(params) {
139
132
  let generation = params.initialGeneration;
140
- let invalidation = 0;
141
- let settledInvalidation = 0;
133
+ let dirty = false;
142
134
  let refresh;
143
135
  const markDirty = () => {
144
- invalidation += 1;
136
+ dirty = true;
145
137
  };
146
138
  const reconcile = () => {
147
139
  if (refresh) return refresh;
148
140
  refresh = (async () => {
149
- for (;;) {
150
- params.signal.throwIfAborted();
151
- const observedInvalidation = invalidation;
152
- const first = await params.readFingerprint();
153
- await sleepWithAbort(SETTLE_DELAY_MS, params.signal, { ref: false });
154
- params.signal.throwIfAborted();
155
- const second = await params.readFingerprint();
156
- params.signal.throwIfAborted();
157
- if (observedInvalidation !== invalidation || first !== second) continue;
158
- const previous = generation;
159
- generation = previous?.fingerprint === second ? previous : {
160
- epoch: (previous?.epoch ?? 0) + 1,
161
- fingerprint: second
162
- };
163
- settledInvalidation = invalidation;
164
- if (previous && generation !== previous) params.onGenerationChange?.(generation);
165
- return generation;
166
- }
167
- })().finally(() => {
141
+ await sleepWithAbort(SETTLE_DELAY_MS, params.signal, { ref: false });
142
+ dirty = false;
143
+ const fingerprint = await params.readFingerprint();
144
+ params.signal.throwIfAborted();
145
+ const previous = generation;
146
+ generation = previous?.fingerprint === fingerprint ? previous : {
147
+ epoch: (previous?.epoch ?? 0) + 1,
148
+ fingerprint
149
+ };
150
+ if (previous && generation !== previous) params.onGenerationChange?.(generation);
151
+ return generation;
152
+ })().catch((error) => {
153
+ dirty = true;
154
+ throw error;
155
+ }).finally(() => {
168
156
  refresh = void 0;
169
157
  });
170
158
  return refresh;
@@ -172,12 +160,11 @@ function createCodexDesktopGenerationOwner(params) {
172
160
  return {
173
161
  read: () => generation,
174
162
  markDirty,
175
- wait: () => settledInvalidation !== invalidation ? reconcile() : Promise.resolve(generation),
163
+ wait: () => dirty ? reconcile() : refresh ?? Promise.resolve(generation),
176
164
  refresh: () => {
177
165
  markDirty();
178
166
  return reconcile();
179
167
  },
180
- isCurrent: (candidate) => Boolean(candidate && !params.signal.aborted && settledInvalidation === invalidation && generation && candidate.epoch === generation.epoch && candidate.fingerprint === generation.fingerprint),
181
168
  waitForIdle: async () => {
182
169
  await refresh?.catch(() => {});
183
170
  }
@@ -188,13 +175,11 @@ function createCodexDesktopGenerationOwner(params) {
188
175
  /** Lifecycle-owned generation for managed macOS Codex desktop artifacts. */
189
176
  const APPLICATIONS_PATH = "/Applications";
190
177
  const REARM_INITIAL_DELAY_MS = 100;
191
- const REARM_MAX_DELAY_MS = 3e4;
192
178
  const state = defineCodexBuildState("openclaw.codexDesktopGenerationState", () => ({}));
193
179
  function waitForCodexDesktopGeneration() {
194
- return state().owner?.wait() ?? Promise.resolve(void 0);
195
- }
196
- function isCodexDesktopGenerationCurrent(generation) {
197
- return state().owner?.isCurrent(generation) ?? false;
180
+ const current = state();
181
+ const owner = current.owner;
182
+ return (current.watchHealthy === false ? owner?.refresh() : owner?.wait()) ?? Promise.resolve(void 0);
198
183
  }
199
184
  function createCodexDesktopGenerationService(params, runtime = {
200
185
  platform: process.platform,
@@ -218,7 +203,7 @@ function createCodexDesktopGenerationService(params, runtime = {
218
203
  initialGeneration: current.lastGeneration
219
204
  });
220
205
  armWatchers(current);
221
- refreshGeneration(current, current.owner, current.owner.refresh());
206
+ refreshGeneration(current, current.owner.refresh());
222
207
  },
223
208
  async stop() {
224
209
  const current = state();
@@ -230,14 +215,12 @@ function createCodexDesktopGenerationService(params, runtime = {
230
215
  current.context = void 0;
231
216
  current.runtime = void 0;
232
217
  current.watchHealthy = void 0;
233
- current.rearmDelayMs = void 0;
234
- current.rearmPending = false;
235
218
  closeWatchers(current);
236
219
  await Promise.all([scheduler?.stop(), owner?.waitForIdle()]);
237
220
  }
238
221
  };
239
222
  }
240
- function armWatchers(current) {
223
+ function armWatchers(current, retryOnFailure = true) {
241
224
  const owner = current.owner;
242
225
  const runtime = current.runtime;
243
226
  if (!owner || !runtime || current.watchers) return false;
@@ -249,25 +232,22 @@ function armWatchers(current) {
249
232
  if (!runtime.pathExists(watchedPath)) continue;
250
233
  try {
251
234
  const watcher = runtime.watchPath(watchedPath, { recursive: watchedPath !== APPLICATIONS_PATH }, (_eventType, filename) => {
252
- if (!isCurrentArm(current, owner, watchers)) return;
253
235
  if (watchedPath === APPLICATIONS_PATH && filename && !candidateNames.has(filename.toString().split(path.sep)[0] ?? "")) return;
254
236
  owner.markDirty();
255
237
  scheduleRearm(current, owner);
256
238
  });
257
239
  watchers.add(watcher);
258
240
  watcher.on("error", (error) => {
259
- if (!isCurrentArm(current, owner, watchers)) return;
260
241
  reportWatcherFailure(current, owner, error);
261
242
  scheduleRearm(current, owner);
262
243
  });
263
244
  } catch (error) {
264
245
  complete = false;
265
246
  reportWatcherFailure(current, owner, error);
266
- scheduleRearm(current, owner);
267
247
  }
268
248
  }
269
249
  current.watchHealthy = complete;
270
- if (complete) current.rearmDelayMs = REARM_INITIAL_DELAY_MS;
250
+ if (!complete && retryOnFailure) scheduleRearm(current, owner, false);
271
251
  return complete;
272
252
  }
273
253
  function reportWatcherFailure(current, owner, error) {
@@ -277,32 +257,24 @@ function reportWatcherFailure(current, owner, error) {
277
257
  current.context?.serviceHealth?.reportFailure(error);
278
258
  current.context?.logger.warn(`codex desktop generation watcher failed: ${String(error)}`);
279
259
  }
280
- function isCurrentArm(current, owner, watchers) {
281
- return isCurrentOwner(current, owner) && current.watchers === watchers;
282
- }
283
- function scheduleRearm(current, owner) {
284
- if (current.rearmPending && current.watchHealthy === false) return;
285
- const delayMs = current.watchHealthy === false ? current.rearmDelayMs ?? REARM_INITIAL_DELAY_MS : REARM_INITIAL_DELAY_MS;
286
- if (current.watchHealthy === false) current.rearmDelayMs = Math.min(delayMs * 2, REARM_MAX_DELAY_MS);
287
- current.rearmPending = true;
260
+ function scheduleRearm(current, owner, retryOnFailure = true) {
261
+ if (current.context?.scheduler.signal.aborted) return;
288
262
  current.context?.scheduler.schedule({
289
263
  id: "watcher-rearm",
290
- delayMs,
264
+ delayMs: REARM_INITIAL_DELAY_MS,
291
265
  run: async () => {
292
- current.rearmPending = false;
293
- if (!isCurrentOwner(current, owner)) return;
294
266
  const wasUnhealthy = current.watchHealthy === false;
295
267
  closeWatchers(current);
296
- if (!armWatchers(current) || wasUnhealthy) owner.markDirty();
297
- await refreshGeneration(current, owner, owner.wait());
268
+ if (!armWatchers(current, retryOnFailure) || wasUnhealthy) owner.markDirty();
269
+ await refreshGeneration(current, owner.wait());
298
270
  }
299
271
  });
300
272
  }
301
- function refreshGeneration(current, owner, refresh) {
273
+ function refreshGeneration(current, refresh) {
302
274
  return refresh.then(() => {
303
- if (isCurrentOwner(current, owner) && current.watchHealthy) current.context?.serviceHealth?.clearFailure();
275
+ if (!current.context?.scheduler.signal.aborted && current.watchHealthy) current.context?.serviceHealth?.clearFailure();
304
276
  }).catch((error) => {
305
- if (!isCurrentOwner(current, owner)) return;
277
+ if (!current.context || current.context.scheduler.signal.aborted) return;
306
278
  current.context?.serviceHealth?.reportFailure(error);
307
279
  current.context?.logger.warn(`codex desktop generation refresh failed: ${String(error)}`);
308
280
  });
@@ -312,9 +284,6 @@ function closeWatchers(current) {
312
284
  current.watchers = void 0;
313
285
  for (const watcher of watchers ?? []) watcher.close();
314
286
  }
315
- function isCurrentOwner(current, owner) {
316
- return current.owner === owner && !current.context?.scheduler.signal.aborted;
317
- }
318
287
  //#endregion
319
288
  //#region extensions/codex/src/app-server/shared-client-lifecycle.ts
320
289
  /** Client ownership and synchronous retirement, independent of startup/auth execution. */
@@ -351,11 +320,36 @@ function getOrCreateSharedClientEntry(state, key) {
351
320
  }
352
321
  return entry;
353
322
  }
323
+ var SharedCodexFallbackJoinError = class extends Error {
324
+ constructor() {
325
+ super("Shared Codex fallback already has a startup owner");
326
+ this.code = "CODEX_SHARED_FALLBACK_JOIN";
327
+ this.name = "SharedCodexFallbackJoinError";
328
+ }
329
+ };
330
+ function isSharedCodexFallbackJoinError(error) {
331
+ return error instanceof Error && "code" in error && error.code === "CODEX_SHARED_FALLBACK_JOIN";
332
+ }
333
+ /**
334
+ * Moves a current entry to the fallback key. False means the caller must
335
+ * re-acquire instead of starting a second client under an already-owned key.
336
+ */
337
+ function rekeySharedClientEntry(entry, key) {
338
+ const state = getSharedCodexAppServerClientState();
339
+ if (state.clients.get(entry.key) !== entry) return false;
340
+ const target = state.clients.get(key);
341
+ if (target) return target === entry;
342
+ state.clients.delete(entry.key);
343
+ entry.key = key;
344
+ state.clients.set(key, entry);
345
+ return true;
346
+ }
354
347
  function closeSharedClientEntryIfUnclaimed(entry) {
355
348
  if (entry.activeLeases > 0 || entry.pendingAcquires > 0) return false;
356
349
  const state = getSharedCodexAppServerClientState();
357
350
  if (state.clients.get(entry.key) !== entry) return false;
358
351
  state.clients.delete(entry.key);
352
+ cancelSharedClientIdleRetirement(entry);
359
353
  entry.client?.close();
360
354
  return Boolean(entry.client);
361
355
  }
@@ -374,7 +368,6 @@ const getSharedCodexAppServerClientState = defineCodexBuildState("openclaw.codex
374
368
  liveClients: /* @__PURE__ */ new Set(),
375
369
  isolatedClients: /* @__PURE__ */ new Set(),
376
370
  entriesByClient: /* @__PURE__ */ new WeakMap(),
377
- desktopGenerationDrainChecks: /* @__PURE__ */ new Set(),
378
371
  startup: createCodexAppServerStartupLifetime(),
379
372
  startMetadata: /* @__PURE__ */ new WeakMap()
380
373
  }));
@@ -408,6 +401,7 @@ function retireSharedCodexAppServerClientIfCurrent(client, opts) {
408
401
  const currentEntry = getCurrentSharedClientEntry(client);
409
402
  const entry = currentEntry ?? state.entriesByClient.get(client);
410
403
  if (!entry || entry.client !== client && !entry.closeError) return;
404
+ cancelSharedClientIdleRetirement(entry);
411
405
  if (currentEntry) {
412
406
  state.clients.delete(entry.key);
413
407
  entry.closeWhenIdle = true;
@@ -442,6 +436,7 @@ function closeRetiredSharedClientEntry(entry) {
442
436
  const client = entry.client;
443
437
  if (!client) return false;
444
438
  entry.client = void 0;
439
+ cancelSharedClientIdleRetirement(entry);
445
440
  client.close();
446
441
  return true;
447
442
  }
@@ -468,7 +463,7 @@ function waitForCodexAppServerClientExit(client) {
468
463
  return exited;
469
464
  }
470
465
  /** Acquire the recorded owner atomically, or join its exit before a replacement writes. */
471
- async function retainSharedCodexAppServerClientByInstanceId(clientId) {
466
+ async function retainSharedCodexAppServerClientByInstanceId(clientId, options) {
472
467
  const id = clientId?.trim();
473
468
  if (!id) return;
474
469
  const state = getSharedCodexAppServerClientState();
@@ -476,7 +471,8 @@ async function retainSharedCodexAppServerClientByInstanceId(clientId) {
476
471
  if (client.getInstanceId() !== id) continue;
477
472
  const entry = state.entriesByClient.get(client);
478
473
  if (entry?.client !== client || entry.closeError || client.getCloseError()) {
479
- await waitForCodexAppServerClientExit(client);
474
+ if (options?.waitForExit === false && client.getCloseError()) return;
475
+ await racePromiseWithAbortSignal(waitForCodexAppServerClientExit(client), options?.signal, options?.createAbortError);
480
476
  return;
481
477
  }
482
478
  const release = retainSharedClientEntry(entry);
@@ -484,16 +480,32 @@ async function retainSharedCodexAppServerClientByInstanceId(clientId) {
484
480
  client,
485
481
  release: (waitForRetirement = false) => {
486
482
  release();
487
- return client.getCloseError() || waitForRetirement && entry.closeWhenIdle ? waitForCodexAppServerClientExit(client) : void 0;
483
+ return options?.waitForExit !== false && (client.getCloseError() || waitForRetirement && entry.closeWhenIdle) ? waitForCodexAppServerClientExit(client) : void 0;
488
484
  }
489
485
  };
490
486
  }
491
487
  }
492
- function notifyDesktopGenerationDrainChecks(state) {
493
- for (const check of state.desktopGenerationDrainChecks) check();
488
+ const CODEX_APP_SERVER_CLIENT_IDLE_GRACE_MS = 3e4;
489
+ function cancelSharedClientIdleRetirement(entry) {
490
+ clearTimeout(entry.idleTimer);
491
+ entry.idleTimer = void 0;
492
+ }
493
+ function refreshSharedClientIdleRetirement(client) {
494
+ const entry = getCurrentSharedClientEntry(client);
495
+ if (entry) scheduleSharedClientIdleRetirement(entry);
496
+ }
497
+ function scheduleSharedClientIdleRetirement(entry) {
498
+ cancelSharedClientIdleRetirement(entry);
499
+ if (entry.activeLeases > 0 || entry.pendingAcquires > 0 || !entry.client || entry.hasOwnedThreads?.() || getCurrentSharedClientEntry(entry.client) !== entry) return;
500
+ entry.idleTimer = setTimeout(() => {
501
+ entry.idleTimer = void 0;
502
+ if (entry.activeLeases === 0 && entry.pendingAcquires === 0 && !entry.hasOwnedThreads?.()) retireSharedCodexAppServerClientIfCurrent(entry.client);
503
+ }, CODEX_APP_SERVER_CLIENT_IDLE_GRACE_MS);
504
+ entry.idleTimer.unref?.();
494
505
  }
495
506
  function retainSharedClientEntry(entry, counter = "activeLeases") {
496
507
  let released = false;
508
+ cancelSharedClientIdleRetirement(entry);
497
509
  entry[counter] += 1;
498
510
  return () => {
499
511
  if (released) return;
@@ -504,7 +516,7 @@ function retainSharedClientEntry(entry, counter = "activeLeases") {
504
516
  function releaseSharedClientEntry(entry, counter) {
505
517
  entry[counter] -= 1;
506
518
  closeRetiredSharedClientEntryIfIdle(entry);
507
- notifyDesktopGenerationDrainChecks(getSharedCodexAppServerClientState());
519
+ scheduleSharedClientIdleRetirement(entry);
508
520
  }
509
521
  //#endregion
510
522
  //#region extensions/codex/src/app-server/auth-cache-key.ts
@@ -514,7 +526,7 @@ const CODEX_APP_SERVER_API_KEY_ENV_VARS = ["CODEX_API_KEY", "OPENAI_API_KEY"];
514
526
  function resolveCodexAppServerFallbackApiKeyCacheKey(params) {
515
527
  if (params.startOptions.transport !== "stdio") return;
516
528
  const apiKey = readFirstNonEmptyEnvEntry(resolveCodexAppServerSpawnEnv(params.startOptions, params.baseEnv ?? process.env, params.platform ?? process.platform), CODEX_APP_SERVER_API_KEY_ENV_VARS);
517
- if (!apiKey) return resolveCodexCliAuthFileApiKeyCacheKey(params.baseEnv ?? process.env);
529
+ if (!apiKey) return params.allowNativeAuthFile === false ? void 0 : resolveCodexCliAuthFileApiKeyCacheKey(params.baseEnv ?? process.env);
518
530
  return fingerprintAuthCacheKey(apiKey.key, "env-api-key", apiKey.key, apiKey.value);
519
531
  }
520
532
  /** Secret-free cache identity for an API key already resolved by the runtime plan. */
@@ -576,4 +588,4 @@ function readFirstNonEmptyEnvEntry(env, keys) {
576
588
  }
577
589
  }
578
590
  //#endregion
579
- export { waitForCodexDesktopGeneration as A, retirePendingSharedClientEntryIfUnclaimed as C, waitForUnclaimedSharedClientStartup as D, waitForCodexAppServerClientExit as E, createCodexDesktopGenerationService as O, retainSharedCodexAppServerClientByInstanceId as S, retireSharedCodexAppServerClientsBeforeDesktopGeneration as T, observeSharedClientAcquire as _, readCodexCliAuthFileApiKey as a, releaseSharedClientEntry as b, resolveCodexAppServerPreparedApiKeyCacheKey as c, getCurrentSharedClientEntry as d, getOrCreateSharedClientEntry as f, observeAcquire as g, notifyDesktopGenerationDrainChecks as h, fingerprintTokenAuthProfileCacheKey as i, readCodexDesktopArtifactTreeFingerprint as j, isCodexDesktopGenerationCurrent as k, closeSharedClientEntryIfUnclaimed as l, hasActiveSharedCodexAppServerWork as m, CODEX_AUTH_JSON_FILENAME as n, readFirstNonEmptyEnv as o, getSharedCodexAppServerClientState as p, fingerprintApiKeyAuthProfileCacheKey as r, resolveCodexAppServerFallbackApiKeyCacheKey as s, CODEX_APP_SERVER_API_KEY_ENV_VARS as t, createCodexAppServerStartupLifetime as u, ownCodexStartup as v, retireSharedCodexAppServerClientIfCurrent as w, retainSharedClientEntry as x, recordSharedClientAcquireBoundary as y };
591
+ export { waitForUnclaimedSharedClientStartup as A, releaseSharedClientEntry as C, retireSharedCodexAppServerClientIfCurrent as D, retirePendingSharedClientEntryIfUnclaimed as E, waitForCodexDesktopGeneration as M, readCodexDesktopArtifactTreeFingerprint as N, retireSharedCodexAppServerClientsBeforeDesktopGeneration as O, rekeySharedClientEntry as S, retainSharedCodexAppServerClientByInstanceId as T, observeAcquire as _, readCodexCliAuthFileApiKey as a, recordSharedClientAcquireBoundary as b, resolveCodexAppServerPreparedApiKeyCacheKey as c, createCodexAppServerStartupLifetime as d, getCurrentSharedClientEntry as f, isSharedCodexFallbackJoinError as g, hasActiveSharedCodexAppServerWork as h, fingerprintTokenAuthProfileCacheKey as i, createCodexDesktopGenerationService as j, waitForCodexAppServerClientExit as k, SharedCodexFallbackJoinError as l, getSharedCodexAppServerClientState as m, CODEX_AUTH_JSON_FILENAME as n, readFirstNonEmptyEnv as o, getOrCreateSharedClientEntry as p, fingerprintApiKeyAuthProfileCacheKey as r, resolveCodexAppServerFallbackApiKeyCacheKey as s, CODEX_APP_SERVER_API_KEY_ENV_VARS as t, closeSharedClientEntryIfUnclaimed as u, observeSharedClientAcquire as v, retainSharedClientEntry as w, refreshSharedClientIdleRetirement as x, ownCodexStartup as y };