@openclaw/codex 2026.9.5 → 2026.9.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. package/README.md +2 -0
  2. package/assets/icon.png +0 -0
  3. package/dist/.setup/{account-usage-runtime-C2MOIvfq.mjs → account-usage-runtime-DFhbh1zz.mjs} +6 -6
  4. package/dist/.setup/{apply-CJ0ZfmBG.mjs → apply-D3GcSoSa.mjs} +35 -55
  5. package/dist/.setup/{attempt-client-cleanup-BpYKdTA0.mjs → attempt-client-cleanup-DOP-cW5j.mjs} +179 -73
  6. package/dist/.setup/attempt-workspace-context-C5HigshI.mjs +164 -0
  7. package/dist/.setup/{auth-binding-DhLWa_7K.mjs → auth-binding-BLWz7stm.mjs} +14 -1
  8. package/dist/.setup/{auth-cache-key-QirmgiCo.mjs → auth-cache-key-Dbvq-QgB.mjs} +41 -111
  9. package/dist/.setup/{auth-profile-WqZtZfXN.mjs → auth-profile-B0okYl2D.mjs} +1 -2
  10. package/dist/.setup/auth-profile-health-oHizqgye.mjs +53 -0
  11. package/dist/.setup/auth-profile-recovery-BREezV0L.mjs +14 -0
  12. package/dist/.setup/auth-start-options-BPIPeEX8.mjs +44 -0
  13. package/dist/.setup/{binding-connection-Bm38niE8.mjs → binding-connection-DTtN1KrX.mjs} +2 -2
  14. package/dist/.setup/{binding-connection.runtime-CnRMC0ta.mjs → binding-connection.runtime-6TpgD1M6.mjs} +5 -5
  15. package/dist/.setup/{bounded-turn-BtlZcivC.mjs → bounded-turn-CbjoN2OW.mjs} +140 -37
  16. package/dist/.setup/bounded-turn-isolation-B8K_ylqk.mjs +14 -0
  17. package/dist/.setup/{build-state-Xx9ybZqa.mjs → build-state-Da1_z0kd.mjs} +1 -1
  18. package/dist/.setup/{capabilities-_vXcZGSx.mjs → capabilities-B3WEZl4e.mjs} +2 -10
  19. package/dist/.setup/{client-vXs2929Q.mjs → client-N0JpgSzF.mjs} +635 -872
  20. package/dist/.setup/client-catalog-response-5HHLdcde.mjs +285 -0
  21. package/dist/.setup/{command-dispatch-naHIZwwF.mjs → command-dispatch-BeAoaovI.mjs} +9 -8
  22. package/dist/.setup/{command-formatters-CGEkdawF.mjs → command-formatters-R3ckE3Co.mjs} +36 -64
  23. package/dist/.setup/{command-handlers-BtAJEW1X.mjs → command-handlers-ylTMS00z.mjs} +301 -488
  24. package/dist/.setup/{command-rpc-DHFpn4le.mjs → command-rpc-CGJGUQ6Y.mjs} +40 -28
  25. package/dist/.setup/compact-C2WamavS.mjs +776 -0
  26. package/dist/.setup/{config-CedDWjM-.mjs → config-DKhXquav.mjs} +26 -28
  27. package/dist/.setup/{config-options-BsanJ8QG.mjs → config-options-CzyWLTJt.mjs} +68 -65
  28. package/dist/.setup/{config-parsing-CcB9iPoq.mjs → config-parsing-b088LyhT.mjs} +57 -60
  29. package/dist/.setup/{config-runtime-CeAhl_h4.mjs → config-runtime-C0NbLms1.mjs} +2 -2
  30. package/dist/.setup/{config-security-BRQ2mgW9.mjs → config-security-CE-FcGw9.mjs} +51 -215
  31. package/dist/.setup/{config-utils-DujwEnhg.mjs → config-utils-D0CXecki.mjs} +3 -13
  32. package/dist/.setup/context-engine-projection-PezSESth.mjs +387 -0
  33. package/dist/.setup/{conversation-binding-DhzrpTM6.mjs → conversation-binding-3Min8qvP.mjs} +71 -105
  34. package/dist/.setup/{conversation-binding-data-CrcyZk6O.mjs → conversation-binding-data-C746z5Pn.mjs} +8 -12
  35. package/dist/.setup/{conversation-control-DN53ns41.mjs → conversation-control-CEP8X5JC.mjs} +30 -69
  36. package/dist/.setup/{cyber-failover-DYwbmf1o.mjs → cyber-failover-XV0nNRZu.mjs} +1 -1
  37. package/dist/.setup/{cyber-failover-notice-e9G3J9-e.mjs → cyber-failover-notice-RNpGpTyP.mjs} +1 -1
  38. package/dist/.setup/{dynamic-tools-D16lOp67.mjs → dynamic-tools-DzlsLUuS.mjs} +3136 -3167
  39. package/dist/.setup/{effective-mcp-catalog-K6kLCN8X.mjs → effective-mcp-catalog-CxUtC-xG.mjs} +8 -17
  40. package/dist/.setup/{ephemeral-turn-R1gA8Sn6.mjs → ephemeral-turn-CDsPJOa2.mjs} +9 -6
  41. package/dist/.setup/event-projector-assistant-message-CigreO4K.mjs +69 -0
  42. package/dist/.setup/{event-projector-usage-C7Ntzs-f.mjs → event-projector-usage-03R0I2dM.mjs} +4 -26
  43. package/dist/.setup/event-projector-values-DJSz8BTk.mjs +106 -0
  44. package/dist/.setup/incognito-session-DWYapfwf.mjs +2 -0
  45. package/dist/.setup/{inference-context-fulhZuz8.mjs → inference-context-D-9gWlTR.mjs} +16 -18
  46. package/dist/.setup/inference-dispatch-CMZtjQyz.mjs +359 -0
  47. package/dist/.setup/inference-metadata-CgIf7sOx.mjs +81 -0
  48. package/dist/.setup/inference-proxy-DhcXOgUE.mjs +561 -0
  49. package/dist/.setup/{isolated-completion-B6srt48J.mjs → isolated-completion-Dm3PzxJk.mjs} +15 -11
  50. package/dist/.setup/launch-args-DbFCehO7.mjs +196 -0
  51. package/dist/.setup/{managed-binary-DP6Rib3P.mjs → managed-binary-kiWRhNRE.mjs} +16 -9
  52. package/dist/.setup/{model-catalog-DkvUuBey.mjs → model-catalog-PAuZgJC6.mjs} +14 -14
  53. package/dist/.setup/model-runtime-BdqzOMkU.mjs +11 -0
  54. package/dist/.setup/{models-BDFgm_G-.mjs → models-DHXZtVVk.mjs} +9 -18
  55. package/dist/.setup/{native-auth-BLZGqFjw.mjs → native-auth-CuG53tu4.mjs} +5 -5
  56. package/dist/.setup/{native-execution-policy-YBMHSzC4.mjs → native-execution-policy-BxZJy5mP.mjs} +6 -31
  57. package/dist/.setup/{native-subagent-monitor-B1hxzIOy.mjs → native-subagent-monitor-Dpsmf2wz.mjs} +4422 -3808
  58. package/dist/.setup/native-subagent-pending-assignments-DwkCzLvD.mjs +203 -0
  59. package/dist/.setup/native-task-assignments-DMQ0g3hu.mjs +194 -0
  60. package/dist/.setup/{node-cli-sessions-Cl8b2ZF3.mjs → node-cli-sessions-HC4W6FLI.mjs} +99 -111
  61. package/dist/.setup/node-exec-server.runtime-BgBfWQqo.mjs +244 -0
  62. package/dist/.setup/{plan-xD7WKYTM.mjs → plan-Y-QIvrKB.mjs} +118 -163
  63. package/dist/.setup/{plugin-activation-r8nq5Jzp.mjs → plugin-activation-cNHRfaxU.mjs} +10 -47
  64. package/dist/.setup/{plugin-app-cache-key-BOxKP7db.mjs → plugin-app-cache-key-BL9B5H0L.mjs} +9 -42
  65. package/dist/.setup/{plugin-inventory-DUle8DLz.mjs → plugin-inventory-Cky2XJUw.mjs} +32 -23
  66. package/dist/.setup/{plugin-marketplace-discovery-P-Vndfqq.mjs → plugin-marketplace-discovery-D_dV9FXa.mjs} +22 -25
  67. package/dist/.setup/{plugin-metadata-cache-DsS5buNa.mjs → plugin-metadata-cache-DsjsL1dr.mjs} +328 -318
  68. package/dist/.setup/protocol-CANUwXJ3.mjs +17 -0
  69. package/dist/.setup/provider-DH8NSzGt.mjs +51 -0
  70. package/dist/.setup/{provider-capabilities-B8J4Dy-O.mjs → provider-capabilities-CAxoF-X1.mjs} +35 -12
  71. package/dist/.setup/{rate-limits-DOEGYRNs.mjs → rate-limits-B7-X2TgG.mjs} +123 -166
  72. package/dist/.setup/{request-BioXJLYa.mjs → request-BHZ1nz8d.mjs} +25 -16
  73. package/dist/.setup/responses-oauth-twnuTaAa.mjs +93 -0
  74. package/dist/.setup/rpc-error-BlD2vuzn.mjs +31 -0
  75. package/dist/.setup/{run-attempt-rlA07pUv.mjs → run-attempt-D8RZUOzY.mjs} +2046 -1454
  76. package/dist/.setup/{run-attempt-lifecycle-B7JbY4-F.mjs → run-attempt-lifecycle-C-6O3Exn.mjs} +10 -24
  77. package/dist/.setup/{runtime-artifact-Dy38Z5iU.mjs → runtime-artifact-DDQ-HGXf.mjs} +43 -47
  78. package/dist/.setup/runtime-artifact-connection-D68qQn1m.mjs +78 -0
  79. package/dist/.setup/sandbox-guard-DjCz2eOw.mjs +126 -0
  80. package/dist/.setup/scope-DOC1Xjc8.mjs +6 -0
  81. package/dist/.setup/session-binding-DGCYAfvD.mjs +443 -0
  82. package/dist/.setup/{session-binding-record-TH3xA0zj.mjs → session-binding-record-Oe9L-CNY.mjs} +73 -132
  83. package/dist/.setup/{session-binding-sidecars-CKYEcfNn.mjs → session-binding-sidecars-jo6H8dFr.mjs} +242 -60
  84. package/dist/.setup/{session-catalog-fUdWDx-U.mjs → session-catalog-4sCdv5qx.mjs} +598 -452
  85. package/dist/.setup/{session-catalog-adoption-CR_whkEW.mjs → session-catalog-adoption-BU_pHWG7.mjs} +59 -26
  86. package/dist/.setup/{session-catalog-archive-CwZaPacf.mjs → session-catalog-archive-spHfihri.mjs} +7 -7
  87. package/dist/.setup/session-catalog-events-DePDzzjc.mjs +139 -0
  88. package/dist/.setup/session-catalog-home-id-vlih0B_g.mjs +22 -0
  89. package/dist/.setup/{session-catalog-index-B141u15s.mjs → session-catalog-index-CZvDzC6z.mjs} +286 -182
  90. package/dist/.setup/{session-catalog-index-order-Cc5BzlQr.mjs → session-catalog-index-order-BcQpHks3.mjs} +2 -2
  91. package/dist/.setup/{session-catalog-index-state-BAuDztHN.mjs → session-catalog-index-state-TeO7EyO-.mjs} +6 -2
  92. package/dist/.setup/session-catalog-limits-DDxOsQeC.mjs +14 -0
  93. package/dist/.setup/session-catalog-list-request-CvtxrYSe.mjs +170 -0
  94. package/dist/.setup/session-catalog-native-projection-DjhwGL6x.mjs +178 -0
  95. package/dist/.setup/{session-catalog-node-adoption-BVRsYOSh.mjs → session-catalog-node-adoption-DgXvSGu0.mjs} +30 -35
  96. package/dist/.setup/{session-catalog-node-continue-Dowv8osw.mjs → session-catalog-node-continue-DjKXHBbi.mjs} +25 -18
  97. package/dist/.setup/session-catalog-node-lookup-CtAXI5W5.mjs +56 -0
  98. package/dist/.setup/{session-catalog-native-projection-ChV3cCtm.mjs → session-catalog-parsing-CPGaPYr-.mjs} +14 -180
  99. package/dist/.setup/{session-catalog-projection-C1Bj9Jl-.mjs → session-catalog-projection-Cr5qP5Dj.mjs} +15 -5
  100. package/dist/.setup/session-catalog-provenance-DoAvktcj.mjs +95 -0
  101. package/dist/.setup/{session-cli-DIj-IE-E.mjs → session-cli-Cn_nCqfq.mjs} +11 -24
  102. package/dist/.setup/{session-history-C--SrLI8.mjs → session-history-D83lJWHG.mjs} +16 -23
  103. package/dist/.setup/{session-history-import-JHXT5Xfi.mjs → session-history-import-WhX-X33a.mjs} +7 -10
  104. package/dist/.setup/session-history-read-Ov3StuL4.mjs +133 -0
  105. package/dist/.setup/{session-history.worker-CpNj7H_P.mjs → session-history.worker-MnPKncqP.mjs} +14 -23
  106. package/dist/.setup/session-initialization-6aveB9qb.mjs +22 -0
  107. package/dist/.setup/{session-permission-policy-DhurXY0l.mjs → session-permission-policy-Ci_fVX6y.mjs} +4 -8
  108. package/dist/.setup/{session-retirement-CU87AOg9.mjs → session-retirement-qMTxkNx2.mjs} +31 -12
  109. package/dist/.setup/{settled-turn-context-fmwouT5I.mjs → settled-turn-context-D4yj4rxf.mjs} +1 -1
  110. package/dist/.setup/{settled-turn-finalizer-CiY2bLFK.mjs → settled-turn-finalizer-BsvEabkw.mjs} +17 -13
  111. package/dist/.setup/{shared-client-BpTtuLQ5.mjs → shared-client-DqyTMYug.mjs} +826 -485
  112. package/dist/.setup/shared-client-lifecycle-DJIgqgMw.mjs +153 -0
  113. package/dist/.setup/{side-question-DSCZyoBD.mjs → side-question-C4kCmQy1.mjs} +206 -334
  114. package/dist/.setup/{source-Bjp4UQij.mjs → source-CS_7GFJZ.mjs} +82 -139
  115. package/dist/.setup/spawn-error-CL3n6MAa.mjs +57 -0
  116. package/dist/.setup/{thread-archive-guard-jmecf6OJ.mjs → thread-archive-guard-C9frICzX.mjs} +10 -3
  117. package/dist/.setup/thread-lifecycle-DPflntEJ.mjs +2362 -0
  118. package/dist/.setup/{incognito-session-uhrBF6wJ.mjs → thread-ownership-queue-Dp24d7-F.mjs} +1 -2
  119. package/dist/.setup/{thread-ownership-skomxnIt.mjs → thread-ownership-roNP0l1c.mjs} +47 -10
  120. package/dist/.setup/thread-policy-DTd-DtkX.mjs +109 -0
  121. package/dist/.setup/thread-requests-B_bRnMGN.mjs +2102 -0
  122. package/dist/.setup/{thread-resume-BkNpj9Pz.mjs → thread-resume-CdDaoc7T.mjs} +6 -6
  123. package/dist/.setup/timeout-CXOfNoaX.mjs +46 -0
  124. package/dist/.setup/transcript-history-projection-DRSifI-1.mjs +201 -0
  125. package/dist/.setup/{transcript-mirror-attestation-CzM-94NC.mjs → transcript-mirror-attestation-YSegaktH.mjs} +3 -4
  126. package/dist/.setup/{transcript-mirror-D4qp_leP.mjs → transcript-mirror-kxmCYsuF.mjs} +224 -206
  127. package/dist/.setup/{transport-stdio-Cmx94Oiy.mjs → transport-stdio-Bdegpn2V.mjs} +138 -75
  128. package/dist/.setup/transport-websocket-BTBE-LD9.mjs +211 -0
  129. package/dist/.setup/{upstream-prompt-provenance-LphB8slG.mjs → upstream-prompt-provenance-fXkKbPVC.mjs} +3 -9
  130. package/dist/.setup/{upstream-session-fork-D3UKxgVD.mjs → upstream-session-fork-CBeVjBpT.mjs} +48 -40
  131. package/dist/.setup/{usage-BOgBEKso.mjs → usage-BMzNxeR_.mjs} +5 -4
  132. package/dist/.setup/{usage-limit-error-C0ow7DOc.mjs → usage-limit-error-QXerDo3i.mjs} +5 -20
  133. package/dist/.setup/{web-search-provider.runtime-CTGuJt6i.mjs → web-search-provider.runtime-P77OUeoo.mjs} +10 -20
  134. package/dist/api.js +25 -16
  135. package/dist/catalog-page-worker-entrypoint.js +12 -0
  136. package/dist/catalog-page.worker.js +9 -0
  137. package/dist/cli-metadata.js +1 -1
  138. package/dist/doctor-contract-api.js +50 -8
  139. package/dist/harness.js +344 -1
  140. package/dist/index.js +345 -346
  141. package/dist/media-understanding-provider.js +9 -22
  142. package/dist/migration-provider-api.js +1 -1
  143. package/dist/provider-discovery.js +1 -1
  144. package/dist/session-history-worker-runtime.js +16 -33
  145. package/dist/session-history.worker.js +1 -1
  146. package/openclaw.plugin.json +14 -2
  147. package/package.json +11 -7
  148. package/dist/.setup/attempt-context-VXVwTCfS.mjs +0 -636
  149. package/dist/.setup/compact-C3i3qlzj.mjs +0 -687
  150. package/dist/.setup/event-projector-assistant-message-DNUR1s0A.mjs +0 -105
  151. package/dist/.setup/event-projector-items-DyTQ_XqL.mjs +0 -200
  152. package/dist/.setup/harness-rxaaoN-o.mjs +0 -349
  153. package/dist/.setup/history-rejection-B4nOXNXF.mjs +0 -13
  154. package/dist/.setup/image-payload-sanitizer-tupAr-2o.mjs +0 -79
  155. package/dist/.setup/inference-proxy-CC15HuSi.mjs +0 -311
  156. package/dist/.setup/launch-args-DnMak49W.mjs +0 -111
  157. package/dist/.setup/local-runtime-attribution-B_2mnqhb.mjs +0 -19
  158. package/dist/.setup/native-subagent-history-YXaL6dMd.mjs +0 -135
  159. package/dist/.setup/native-subagent-task-ids-DsuOonKv.mjs +0 -411
  160. package/dist/.setup/node-exec-server.runtime-BaViBKNz.mjs +0 -226
  161. package/dist/.setup/plugin-approval-roundtrip-CjfzafAZ.mjs +0 -122
  162. package/dist/.setup/provider-fFh_-VR3.mjs +0 -50
  163. package/dist/.setup/rolldown-runtime-8H4AJuhK.mjs +0 -14
  164. package/dist/.setup/sandbox-guard-BBP-RbTf.mjs +0 -166
  165. package/dist/.setup/session-binding-_0W_fHRr.mjs +0 -721
  166. package/dist/.setup/session-catalog-events-jMcYfQyd.mjs +0 -250
  167. package/dist/.setup/session-history-read-B3ZfSUbF.mjs +0 -50
  168. package/dist/.setup/session-initialization-DH1z6fXn.mjs +0 -75
  169. package/dist/.setup/thread-history-page-BTx-4xsg.mjs +0 -83
  170. package/dist/.setup/thread-lifecycle-Cik28qWn.mjs +0 -4904
  171. package/dist/.setup/thread-policy-Cjs4B8xf.mjs +0 -54
  172. package/dist/.setup/timeout-DZF05XrR.mjs +0 -63
  173. package/dist/.setup/transcript-history-projection-DHNBDhCU.mjs +0 -243
  174. package/dist/.setup/version-CoqzXPgK.mjs +0 -12
@@ -1,16 +1,22 @@
1
- import { p as sessionBindingIdentity } from "./session-binding-record-TH3xA0zj.mjs";
2
- import { _ as resolveCodexAppServerUserHomeDir, f as assertCodexThreadForkParams, g as resolveCodexAppServerLocalHomeDir, h as resolveCodexAppServerHomeDir } from "./config-security-BRQ2mgW9.mjs";
3
- import { d as readCodexPluginConfig } from "./config-parsing-CcB9iPoq.mjs";
4
- import { A as parseTranscriptPage, B as unwrapNodeInvokePayload, E as isInteractiveThreadSource, I as requireOnlyKeys, M as readControlCursor, N as readGatewayParams, O as parseCatalogPage, P as readPageParams, S as catalogError, T as filterCatalogPageByTitle, _ as MAX_CURSOR_LENGTH, b as NODE_INVOKE_TIMEOUT_MS, d as CODEX_APP_SERVER_THREADS_CAPABILITY, f as CODEX_APP_SERVER_THREADS_LIST_COMMAND, g as CatalogParamsError, h as CODEX_LOCAL_SESSION_HOST_ID, j as readBoundedOptionalString, k as parseJsonParams, m as CODEX_CATALOG_TRANSCRIPT_READ_COMMAND, p as CODEX_APP_SERVER_THREAD_TURNS_LIST_COMMAND, y as MAX_TRANSCRIPT_PAGE_BYTES } from "./session-catalog-native-projection-ChV3cCtm.mjs";
5
- import { a as isCodexThreadReadMissingError, i as CodexAppServerRpcError, n as withTimeout } from "./timeout-DZF05XrR.mjs";
6
- import { t as CODEX_CONTROL_METHODS } from "./capabilities-_vXcZGSx.mjs";
7
- import { r as compareCodexCatalogRows } from "./session-catalog-index-order-Cc5BzlQr.mjs";
8
- import { n as readLegacyCodexHistoryPage, t as readCodexThreadHistoryPage } from "./thread-history-page-BTx-4xsg.mjs";
9
- import { i as projectCodexUserItemText } from "./transcript-history-projection-DHNBDhCU.mjs";
1
+ import { A as unwrapNodeInvokePayload, C as readGatewayParams, E as requireOnlyKeys, S as readControlCursor, _ as normalizeLimit, a as CODEX_LOCAL_SESSION_HOST_ID, b as parseTranscriptPage, f as catalogError, g as isInteractiveThreadSource, h as filterCatalogPageByTitle, i as CODEX_CATALOG_TRANSCRIPT_READ_COMMAND, l as MAX_TRANSCRIPT_PAGE_BYTES, n as CODEX_APP_SERVER_THREADS_LIST_COMMAND, o as CatalogParamsError, r as CODEX_APP_SERVER_THREAD_TURNS_LIST_COMMAND, s as MAX_CURSOR_LENGTH, t as CODEX_APP_SERVER_THREADS_CAPABILITY, u as NODE_INVOKE_TIMEOUT_MS, v as parseCatalogPage, w as readPageParams, x as readBoundedOptionalString, y as parseJsonParams } from "./session-catalog-parsing-CPGaPYr-.mjs";
2
+ import { n as assertCodexThreadForkParams } from "./protocol-CANUwXJ3.mjs";
3
+ import { v as sessionBindingIdentity } from "./session-binding-record-Oe9L-CNY.mjs";
4
+ import { d as readCodexPluginConfig } from "./config-parsing-b088LyhT.mjs";
5
+ import { n as resolveCodexAppServerLocalHomeDir, r as resolveCodexAppServerUserHomeDir, t as resolveCodexAppServerHomeDir } from "./auth-start-options-BPIPeEX8.mjs";
6
+ import { i as hasActiveSharedCodexAppServerWork, r as getSharedCodexAppServerClientState } from "./shared-client-lifecycle-DJIgqgMw.mjs";
7
+ import { n as CodexAppServerRpcError, r as isCodexThreadReadMissingError } from "./rpc-error-BlD2vuzn.mjs";
8
+ import { t as CODEX_CONTROL_METHODS } from "./capabilities-B3WEZl4e.mjs";
9
+ import { n as codexCatalogHomeIdFromCanonicalPath } from "./session-catalog-home-id-vlih0B_g.mjs";
10
+ import { i as withTimeout } from "./timeout-CXOfNoaX.mjs";
11
+ import { a as CodexCatalogLoadingError, n as currentCodexCatalogListRequest, r as withCodexCatalogListRequest, t as CodexCatalogListRequest } from "./session-catalog-list-request-CvtxrYSe.mjs";
12
+ import { t as lookupNodeCodexCatalogRecord } from "./session-catalog-node-lookup-CtAXI5W5.mjs";
13
+ import { r as projectCodexUserItemText } from "./transcript-history-projection-DRSifI-1.mjs";
10
14
  import { r as codexUpstreamContinueResult } from "./session-upstream-marker-D15C9NHp.mjs";
11
- import { t as buildCodexAppServerConnectionFingerprint } from "./plugin-app-cache-key-BOxKP7db.mjs";
12
- import { c as readCodexSessionMeta, o as codexCatalogHomeIdFromCanonicalPath, t as codexCatalogResidentHomeKey } from "./session-catalog-events-jMcYfQyd.mjs";
13
- import { a as setCodexCatalogConnectionHomeResolver } from "./binding-connection-Bm38niE8.mjs";
15
+ import { t as buildCodexAppServerConnectionFingerprint } from "./plugin-app-cache-key-BL9B5H0L.mjs";
16
+ import { n as findCodexAppServerSpawnError } from "./spawn-error-CL3n6MAa.mjs";
17
+ import { n as readCodexSessionMeta } from "./session-catalog-provenance-DoAvktcj.mjs";
18
+ import { t as codexCatalogResidentHomeKey } from "./session-catalog-events-DePDzzjc.mjs";
19
+ import { a as setCodexCatalogConnectionHomeResolver } from "./binding-connection-DTtN1KrX.mjs";
14
20
  import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
15
21
  import { randomUUID } from "node:crypto";
16
22
  import { embeddedAgentLog, resolveDefaultAgentDir } from "openclaw/plugin-sdk/agent-harness-registration";
@@ -18,6 +24,7 @@ import { listAgentIds, resolveAgentDir, resolveDefaultAgentId, resolveSessionAge
18
24
  import { z } from "zod";
19
25
  import path from "node:path";
20
26
  import fs from "node:fs/promises";
27
+ import { canonicalPathFromExistingAncestor } from "openclaw/plugin-sdk/file-access-runtime";
21
28
  import { scheduler } from "node:timers/promises";
22
29
  import { AsyncLocalStorage } from "node:async_hooks";
23
30
  import { isMainThread, threadId } from "node:worker_threads";
@@ -201,6 +208,14 @@ function currentCodexCatalogListDiagnostics() {
201
208
  const observation = listScope.getStore();
202
209
  return observation?.closed ? void 0 : observation;
203
210
  }
211
+ function startCodexCatalogListTiming(field, counter) {
212
+ const observation = currentCodexCatalogListDiagnostics();
213
+ const started = observation ? performance.now() : 0;
214
+ if (observation && counter) observation.fields[counter]++;
215
+ return () => {
216
+ if (observation && !observation.closed) observation.fields[field] = (observation.fields[field] ?? 0) + performance.now() - started;
217
+ };
218
+ }
204
219
  /** One logical list scope survives admission pauses; finishing drops its captured context. */
205
220
  function createCodexCatalogListScope() {
206
221
  const observation = start("list phases", {
@@ -287,98 +302,108 @@ function startCodexCatalogControlRequestDiagnostics(page) {
287
302
  return observation;
288
303
  }
289
304
  //#endregion
290
- //#region extensions/codex/src/session-catalog-availability.ts
291
- var CodexCatalogLoadingError = class extends Error {
305
+ //#region extensions/codex/src/session-catalog-node-snapshot.ts
306
+ /** One query-compatible native page per node, owned by the registered catalog provider. */
307
+ var CodexCatalogNodeSnapshots = class {
292
308
  constructor() {
293
- super("Codex session catalog is still loading. Retry shortly.");
294
- this.code = "APP_SERVER_UNAVAILABLE";
309
+ this.generation = 0;
310
+ this.inventoryGeneration = 0;
311
+ this.configGeneration = 0;
312
+ this.nodes = /* @__PURE__ */ new Map();
295
313
  }
296
- };
297
- /** One generation promise wakes cold callers; native pages remain owned by the index. */
298
- var CodexCatalogAvailability = class {
299
- constructor() {
300
- this.complete = false;
301
- this.changed = createDeferred();
314
+ start(config) {
315
+ if (this.config !== config) {
316
+ this.nodes.clear();
317
+ this.config = config;
318
+ this.configGeneration = this.generation + 1;
319
+ this.inventoryGeneration = this.configGeneration;
320
+ }
321
+ return ++this.generation;
302
322
  }
303
- begin() {
304
- this.failure = void 0;
323
+ observe(generation, nodes) {
324
+ if (generation < this.inventoryGeneration) return;
325
+ this.inventoryGeneration = generation;
326
+ const connected = new Map(nodes.filter((node) => node.connected).map((node) => [node.nodeId, node]));
327
+ for (const [nodeId, publication] of this.nodes) {
328
+ const node = connected.get(nodeId);
329
+ if (!node || node.connectedAtMs !== publication.connection) this.nodes.delete(nodeId);
330
+ }
331
+ for (const node of connected.values()) if (!this.nodes.has(node.nodeId)) this.nodes.set(node.nodeId, {
332
+ connection: node.connectedAtMs,
333
+ generation: 0
334
+ });
305
335
  }
306
- publish(frontier, complete = false) {
307
- if (this.complete) return;
308
- if (frontier && (!this.frontier || compareCodexCatalogRows(frontier, this.frontier) > 0)) {
309
- const { threadId, updatedAt, recencyAt, sourceOrder } = frontier;
310
- this.frontier = {
311
- threadId,
312
- updatedAt,
313
- recencyAt,
314
- sourceOrder
336
+ forNode(node, generation, key) {
337
+ let publication = this.nodes.get(node.nodeId);
338
+ if (!publication) {
339
+ publication = {
340
+ connection: node.connectedAtMs,
341
+ generation: 0
315
342
  };
343
+ if (generation >= this.inventoryGeneration) this.nodes.set(node.nodeId, publication);
316
344
  }
317
- this.complete = complete;
318
- this.notify();
319
- }
320
- fail(error) {
321
- this.failure = { error };
322
- this.notify();
323
- }
324
- notify() {
325
- const previous = this.changed;
326
- this.changed = createDeferred();
327
- previous.resolve();
328
- }
329
- async until(promise, deadline) {
330
- const remaining = deadline - performance.now();
331
- if (remaining <= 0) throw new CodexCatalogLoadingError();
332
- return await withTimeout(promise, remaining, "Codex session catalog is still loading", () => new CodexCatalogLoadingError());
333
- }
334
- async next(deadline) {
335
- if (this.failure) throw this.failure.error;
336
- await this.until(this.changed.promise, deadline);
345
+ const valid = () => generation >= this.configGeneration && this.nodes.get(node.nodeId) === publication && publication.connection === node.connectedAtMs;
346
+ return {
347
+ read: () => valid() && publication.snapshot?.key === key ? publication.snapshot : void 0,
348
+ publish: (host) => {
349
+ if (!valid() || generation < publication.generation) return false;
350
+ publication.generation = generation;
351
+ publication.snapshot = node.connected && host.connected ? {
352
+ key,
353
+ generation,
354
+ host
355
+ } : void 0;
356
+ return true;
357
+ },
358
+ isCurrent: (snapshot) => valid() && publication.snapshot === snapshot,
359
+ valid
360
+ };
337
361
  }
338
362
  };
339
- //#endregion
340
- //#region extensions/codex/src/session-catalog-node-lookup.ts
341
- async function lookupNodeCodexCatalogRecord(params) {
342
- const deadline = performance.now() + NODE_INVOKE_TIMEOUT_MS;
343
- const unverified = () => new CatalogParamsError("Codex session eligibility could not be verified");
344
- const remaining = () => {
345
- const timeoutMs = Math.ceil(deadline - performance.now());
346
- if (timeoutMs <= 0) throw unverified();
347
- return timeoutMs;
363
+ function createNodeHostPublication(publication, adopted, sourceKey, onHost, signal, partial, waitUntil) {
364
+ let publishedSnapshot;
365
+ let publishedHost;
366
+ const project = (host) => ({
367
+ ...host,
368
+ sessions: host.sessions.map((session) => {
369
+ const entry = session.sourceHomeId ? adopted.get(sourceKey(host.hostId, session.threadId, session.sourceHomeId)) : void 0;
370
+ return entry ? {
371
+ ...session,
372
+ sessionKey: entry.key
373
+ } : session;
374
+ })
375
+ });
376
+ const emit = (host) => {
377
+ publishedHost = project(host);
378
+ return onHost?.(publishedHost);
348
379
  };
349
- let cursor;
350
- const seenCursors = /* @__PURE__ */ new Set();
351
- for (;;) {
352
- const timeoutMs = remaining();
353
- const raw = await withTimeout(params.runtime.nodes.invoke({
354
- nodeId: params.nodeId,
355
- command: CODEX_APP_SERVER_THREADS_LIST_COMMAND,
356
- params: {
357
- agentId: params.agentId,
358
- limit: 100,
359
- ...cursor ? { cursor } : {}
360
- },
361
- timeoutMs,
362
- scopes: ["operator.write"]
363
- }), timeoutMs, "Codex session eligibility could not be verified", unverified);
364
- remaining();
365
- const page = parseCatalogPage(unwrapNodeInvokePayload(raw));
366
- const record = page.sessions.find((candidate) => candidate.threadId === params.threadId);
367
- if (record) return {
368
- kind: "found",
369
- record
370
- };
371
- const nextCursor = page.nextCursor?.trim();
372
- if (!nextCursor) break;
373
- if (seenCursors.has(nextCursor)) return { kind: "cursor-cycle" };
374
- seenCursors.add(nextCursor);
375
- if (seenCursors.size > 2e4) {
376
- const oldest = seenCursors.values().next().value;
377
- if (oldest !== void 0) seenCursors.delete(oldest);
380
+ return {
381
+ project,
382
+ readPublished: () => publishedHost,
383
+ publish: (host) => {
384
+ if (signal?.aborted) return partial ? void 0 : onHost?.(project(host));
385
+ if (!publication.valid()) return;
386
+ if (publication.publish(host)) {
387
+ publishedSnapshot = publication.read();
388
+ return emit(host);
389
+ }
390
+ const latest = publication.read();
391
+ return emit(latest?.host ?? host);
392
+ },
393
+ publishCached: (snapshot) => {
394
+ if (signal?.aborted || snapshot === publishedSnapshot || !publication.isCurrent(snapshot)) return;
395
+ const completion = createDeferred();
396
+ completion.promise.catch(() => void 0);
397
+ try {
398
+ waitUntil?.(completion.promise);
399
+ completion.resolve(emit(snapshot.host));
400
+ publishedSnapshot = snapshot;
401
+ } catch (error) {
402
+ completion.reject(error);
403
+ throw error;
404
+ }
378
405
  }
379
- cursor = nextCursor;
380
- }
381
- return { kind: "missing" };
406
+ };
382
407
  }
383
408
  //#endregion
384
409
  //#region extensions/codex/src/session-catalog-terminal.ts
@@ -390,6 +415,7 @@ function createCodexTerminalStartNodeHostCommand() {
390
415
  cap: CODEX_APP_SERVER_THREADS_CAPABILITY,
391
416
  dangerous: false,
392
417
  duplex: true,
418
+ hasActiveWork: () => false,
393
419
  isAvailable: ({ env }) => Boolean(resolveNodeHostExecutable("codex", {
394
420
  env,
395
421
  strategy: "direct"
@@ -416,6 +442,7 @@ function resolveCodexCatalogTerminalHome(sources) {
416
442
  if (!runtimeConfig) throw new Error("OpenClaw runtime config is unavailable");
417
443
  const agentDir = sources.source?.agentDir ?? (sources.agentId ? resolveAgentDir(runtimeConfig, sources.agentId) : resolveDefaultAgentDir(runtimeConfig));
418
444
  const startOptions = sources.source?.appServer.start ?? sources.resolveRuntimeOptions({ pluginConfig: sources.getPluginConfig() }).start;
445
+ if (startOptions.transport !== "stdio") throw new CatalogParamsError("Native terminal requires a local Codex source");
419
446
  return resolveCodexAppServerLocalHomeDir(startOptions, agentDir);
420
447
  }
421
448
  function resolveLocalCodexTerminalExecutable(env = process.env) {
@@ -441,7 +468,8 @@ function createCodexTerminalNodeHostCommand(bindRequest) {
441
468
  cap: CODEX_APP_SERVER_THREADS_CAPABILITY,
442
469
  dangerous: false,
443
470
  duplex: true,
444
- isAvailable: ({ env }) => Boolean(resolveNodeHostExecutable("codex", {
471
+ hasActiveWork: () => false,
472
+ isAvailable: ({ config, env }) => (readCodexPluginConfig(config.plugins?.entries?.codex?.config).appServer?.transport ?? "stdio") === "stdio" && Boolean(resolveNodeHostExecutable("codex", {
445
473
  env,
446
474
  pathEnv: env.PATH ?? env.Path ?? "",
447
475
  strategy: "direct"
@@ -449,6 +477,7 @@ function createCodexTerminalNodeHostCommand(bindRequest) {
449
477
  handle: async (paramsJSON, io) => {
450
478
  if (!io) throw new Error("Codex terminal command requires duplex transport");
451
479
  const request = await bindRequest(paramsJSON);
480
+ if (request.transport !== "stdio") throw new CatalogParamsError("Native terminal requires a local Codex source");
452
481
  const resume = decodeNodePtyResumeParams(request.paramsJSON, (value) => {
453
482
  if (typeof value !== "string" || !/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/iu.test(value)) throw new CatalogParamsError("threadId must be a UUID");
454
483
  return value;
@@ -460,9 +489,11 @@ function createCodexTerminalNodeHostCommand(bindRequest) {
460
489
  strategy: "direct"
461
490
  });
462
491
  if (!resolution) throw new Error("Codex CLI is unavailable");
492
+ request.assertCurrent();
463
493
  return JSON.stringify(await runNodePtyCommand({
464
494
  file: resolution.executable,
465
495
  args: ["resume", resume.threadId],
496
+ assertCurrent: () => request.assertCurrent(),
466
497
  ...record.cwd ? { cwd: record.cwd } : {},
467
498
  env: { CODEX_HOME: request.codexHome },
468
499
  cols: resume.cols,
@@ -500,7 +531,8 @@ async function openCodexCatalogTerminal(params) {
500
531
  agentId: params.agentId,
501
532
  runtime: params.api.runtime,
502
533
  nodeId,
503
- threadId: params.threadId
534
+ threadId: params.threadId,
535
+ sourceHomeId: params.sourceHomeId
504
536
  });
505
537
  if (lookup.kind !== "found" || !isInteractiveThreadSource(lookup.record.source)) throw new CatalogParamsError("Codex session is not a non-archived interactive Codex session");
506
538
  const record = lookup.record;
@@ -511,7 +543,8 @@ async function openCodexCatalogTerminal(params) {
511
543
  uploadPathStyle: "native",
512
544
  paramsJSON: JSON.stringify({
513
545
  agentId: params.agentId,
514
- threadId: params.threadId
546
+ threadId: params.threadId,
547
+ ...lookup.sourceHomeId ? { sourceHomeId: lookup.sourceHomeId } : {}
515
548
  }),
516
549
  ...record.cwd ? { cwd: record.cwd } : {},
517
550
  title
@@ -542,120 +575,6 @@ async function startCodexCatalogTerminal(params) {
542
575
  };
543
576
  }
544
577
  //#endregion
545
- //#region extensions/codex/src/session-catalog-list-request.ts
546
- const listRequest = new AsyncLocalStorage();
547
- function currentCodexCatalogListRequest() {
548
- return listRequest.getStore();
549
- }
550
- /** One foreground request owns its native read budget and source-health outcome. */
551
- var CodexCatalogListRequest = class {
552
- constructor() {
553
- this.pages = 0;
554
- this.closed = false;
555
- this.attempts = /* @__PURE__ */ new Map();
556
- }
557
- get hasPages() {
558
- return this.pages < 20;
559
- }
560
- deadline(timeoutMs) {
561
- this.assertActive();
562
- return this.deadlineAt ??= performance.now() + timeoutMs;
563
- }
564
- constrainDeadline(absolute) {
565
- this.assertActive();
566
- this.deadlineAt = Math.min(this.deadlineAt ?? absolute, absolute);
567
- return this.deadlineAt;
568
- }
569
- remaining(timeoutMs) {
570
- const remaining = Math.min(timeoutMs, this.deadline(timeoutMs) - performance.now());
571
- if (remaining <= 0) throw new CodexCatalogLoadingError();
572
- return remaining;
573
- }
574
- assertActive() {
575
- if (this.closed) throw new DOMException("Codex session catalog request is closed", "AbortError");
576
- if (this.deadlineAt !== void 0 && this.deadlineAt <= performance.now()) throw new CodexCatalogLoadingError();
577
- }
578
- async run(run) {
579
- this.assertActive();
580
- const pending = listRequest.run(this, run);
581
- const remaining = this.deadlineAt === void 0 ? void 0 : this.deadlineAt - performance.now();
582
- if (remaining !== void 0 && remaining <= 0) {
583
- pending.catch(() => {});
584
- throw new CodexCatalogLoadingError();
585
- }
586
- const result = remaining === void 0 ? await pending : await withTimeout(pending, remaining, "Codex session catalog is still loading", () => new CodexCatalogLoadingError());
587
- this.assertActive();
588
- return result;
589
- }
590
- async read(timeoutMs, read) {
591
- const remaining = this.remaining(timeoutMs);
592
- if (!this.hasPages) throw new CatalogParamsError("Codex catalog native page budget is exhausted");
593
- this.pages++;
594
- try {
595
- const result = await withTimeout(read(remaining), remaining, "Codex session catalog is still loading", () => new CodexCatalogLoadingError());
596
- this.assertActive();
597
- return result;
598
- } catch (error) {
599
- if (!this.closed) this.failure ??= { error };
600
- throw error;
601
- }
602
- }
603
- attempt(owner, key, start) {
604
- this.assertActive();
605
- let attempts = this.attempts.get(owner);
606
- const existing = attempts?.get(key);
607
- if (existing) return existing;
608
- const attempt = start();
609
- if (!attempts) {
610
- attempts = /* @__PURE__ */ new Map();
611
- this.attempts.set(owner, attempts);
612
- }
613
- attempts.set(key, attempt);
614
- return attempt;
615
- }
616
- resolved() {
617
- if (this.failure) {
618
- this.rejected(this.failure.error);
619
- return;
620
- }
621
- this.settle((attempt) => attempt.resolved());
622
- }
623
- rejected(error) {
624
- if (error instanceof Error && error.name === "AbortError") {
625
- this.close();
626
- return;
627
- }
628
- const reason = this.failure?.error ?? error;
629
- this.settle((attempt) => attempt.rejected(reason));
630
- }
631
- close() {
632
- this.settle((attempt) => attempt.abandoned());
633
- }
634
- settle(settle) {
635
- if (this.closed) return;
636
- this.closed = true;
637
- for (const attempts of this.attempts.values()) for (const attempt of attempts.values()) if (attempt.allowed) settle(attempt);
638
- this.attempts.clear();
639
- this.failure = void 0;
640
- }
641
- };
642
- async function withCodexCatalogListRequest(run) {
643
- const current = currentCodexCatalogListRequest();
644
- if (current) {
645
- current.assertActive();
646
- return await run(current);
647
- }
648
- const scope = new CodexCatalogListRequest();
649
- try {
650
- const result = await scope.run(() => run(scope));
651
- scope.resolved();
652
- return result;
653
- } catch (error) {
654
- scope.rejected(error);
655
- throw error;
656
- }
657
- }
658
- //#endregion
659
578
  //#region extensions/codex/src/session-catalog-visible-page.ts
660
579
  /** Fill exclusions from bounded resident pages. */
661
580
  var CodexCatalogVisiblePage = class {
@@ -687,9 +606,7 @@ var CodexCatalogVisiblePage = class {
687
606
  if (this.complete) throw new Error("Codex catalog page is already complete");
688
607
  const params = this.params;
689
608
  params.signal?.throwIfAborted();
690
- const diagnostics = currentCodexCatalogListDiagnostics();
691
- const started = diagnostics ? performance.now() : 0;
692
- if (diagnostics) diagnostics.fields.controlPageCalls++;
609
+ const finishTiming = startCodexCatalogListTiming("controlWaitSumMs", "controlPageCalls");
693
610
  let rawPage;
694
611
  try {
695
612
  rawPage = await params.control.listPage({
@@ -699,7 +616,7 @@ var CodexCatalogVisiblePage = class {
699
616
  ...params.cwd ? { cwd: params.cwd } : {}
700
617
  });
701
618
  } finally {
702
- if (diagnostics && !diagnostics.closed) diagnostics.fields.controlWaitSumMs = (diagnostics.fields.controlWaitSumMs ?? 0) + performance.now() - started;
619
+ finishTiming();
703
620
  }
704
621
  this.request.assertActive();
705
622
  params.signal?.throwIfAborted();
@@ -752,6 +669,24 @@ async function listVisiblePage(params) {
752
669
  }
753
670
  //#endregion
754
671
  //#region extensions/codex/src/session-catalog-list-operation.ts
672
+ async function boundedHost(pending) {
673
+ let timer;
674
+ try {
675
+ return await Promise.race([pending, new Promise((resolve) => {
676
+ timer = setTimeout(() => resolve(void 0), 250);
677
+ })]);
678
+ } finally {
679
+ clearTimeout(timer);
680
+ }
681
+ }
682
+ function measureNodeHost(host, diagnostics, started) {
683
+ return diagnostics ? host.finally(() => {
684
+ if (!diagnostics.closed) {
685
+ diagnostics.fields.pairedNodeSettled = (diagnostics.fields.pairedNodeSettled ?? 0) + 1;
686
+ diagnostics.fields.nodeWaitSumMs = (diagnostics.fields.nodeWaitSumMs ?? 0) + performance.now() - started;
687
+ }
688
+ }) : host;
689
+ }
755
690
  function hostFailure(source, error) {
756
691
  return {
757
692
  hostId: source?.hostId ?? "gateway:local",
@@ -767,12 +702,10 @@ function hostFailure(source, error) {
767
702
  }
768
703
  async function projectLocalHost(params, agentId, source, page) {
769
704
  params.signal?.throwIfAborted();
770
- const { listAdoptedSessionEntries } = await import("./session-catalog-adoption-CR_whkEW.mjs");
705
+ const { listAdoptedSessionEntries } = await import("./session-catalog-adoption-BU_pHWG7.mjs");
771
706
  const { sessionCatalogAdoptedSourceKey } = await import("openclaw/plugin-sdk/session-catalog");
772
707
  params.signal?.throwIfAborted();
773
- const diagnostics = currentCodexCatalogListDiagnostics();
774
- const started = diagnostics ? performance.now() : 0;
775
- if (diagnostics) diagnostics.fields.adoptionCalls++;
708
+ const finishTiming = startCodexCatalogListTiming("adoptionSumMs", "adoptionCalls");
776
709
  let adopted;
777
710
  try {
778
711
  adopted = await listAdoptedSessionEntries({
@@ -783,7 +716,7 @@ async function projectLocalHost(params, agentId, source, page) {
783
716
  sessionEntries: params.sessionEntries
784
717
  });
785
718
  } finally {
786
- if (diagnostics && !diagnostics.closed) diagnostics.fields.adoptionSumMs = (diagnostics.fields.adoptionSumMs ?? 0) + performance.now() - started;
719
+ finishTiming();
787
720
  }
788
721
  const hostId = source?.hostId ?? "gateway:local";
789
722
  const sourceHomeId = source?.sourceHomeId ?? "gateway:local";
@@ -809,9 +742,7 @@ async function projectLocalHost(params, agentId, source, page) {
809
742
  function managedMarker(store, sourceHomeId, managed) {
810
743
  return async ({ threadId, rolloutPath }) => {
811
744
  if (managed?.has(threadId)) return;
812
- const diagnostics = currentCodexCatalogListDiagnostics();
813
- const started = diagnostics ? performance.now() : 0;
814
- if (diagnostics) diagnostics.fields.exclusionMarkCalls++;
745
+ const finishTiming = startCodexCatalogListTiming("exclusionMarkSumMs", "exclusionMarkCalls");
815
746
  try {
816
747
  await store.mark({
817
748
  sourceHomeId,
@@ -819,10 +750,23 @@ function managedMarker(store, sourceHomeId, managed) {
819
750
  ...rolloutPath ? { rolloutPath } : {}
820
751
  });
821
752
  } finally {
822
- if (diagnostics && !diagnostics.closed) diagnostics.fields.exclusionMarkSumMs = (diagnostics.fields.exclusionMarkSumMs ?? 0) + performance.now() - started;
753
+ finishTiming();
823
754
  }
824
755
  };
825
756
  }
757
+ async function finishLocalHost(params, agentId, host) {
758
+ try {
759
+ for (;;) {
760
+ const step = await host.page.next();
761
+ params.signal?.throwIfAborted();
762
+ if (step.done) return await projectLocalHost(params, agentId, host.source, step.page);
763
+ }
764
+ } catch (error) {
765
+ return hostFailure(host.source, error);
766
+ } finally {
767
+ host.page.close();
768
+ }
769
+ }
826
770
  function createNodePublicationTracker(publications, waitUntil) {
827
771
  const settled = () => {
828
772
  publications.pending--;
@@ -838,6 +782,7 @@ var CodexCatalogListDriver = class {
838
782
  constructor(params) {
839
783
  this.locals = [];
840
784
  this.nodeActive = false;
785
+ this.nodeResults = [];
841
786
  this.nodeDiscoveryFailed = false;
842
787
  this.nodePublications = { pending: 0 };
843
788
  this.nodesStarted = false;
@@ -846,6 +791,8 @@ var CodexCatalogListDriver = class {
846
791
  this.running = false;
847
792
  this.complete = false;
848
793
  this.params = params;
794
+ this.nodeSnapshots = params.nodeSnapshots ?? new CodexCatalogNodeSnapshots();
795
+ this.nodeGeneration = this.nodeSnapshots.start(params.config);
849
796
  }
850
797
  request() {
851
798
  if (!this.params) throw new Error("Codex catalog list operation is closed");
@@ -908,6 +855,20 @@ var CodexCatalogListDriver = class {
908
855
  }
909
856
  async readHost(host) {
910
857
  const params = this.request();
858
+ if (params.allowPartialResults === true && params.onHost && params.waitUntil) {
859
+ host.background = true;
860
+ const completion = finishLocalHost(params, this.selection().agentId, host);
861
+ completion.then(host.completion.resolve, host.completion.reject);
862
+ host.value = await boundedHost(completion) ?? {
863
+ hostId: host.source?.hostId ?? "gateway:local",
864
+ label: host.source?.label ?? "Local Codex",
865
+ kind: "gateway",
866
+ connected: true,
867
+ pending: true,
868
+ sessions: []
869
+ };
870
+ return;
871
+ }
911
872
  try {
912
873
  const page = await host.page.next();
913
874
  params.signal?.throwIfAborted();
@@ -940,9 +901,11 @@ var CodexCatalogListDriver = class {
940
901
  const started = diagnostics ? performance.now() : 0;
941
902
  if (diagnostics) diagnostics.fields.nodeRegistryCalls = 1;
942
903
  let nodes;
904
+ let inventory;
943
905
  try {
944
906
  try {
945
- nodes = (await (params.listNodes?.() ?? params.runtime.nodes.list())).nodes.filter((node) => node.gatewayLocal !== true && (node.commands?.includes("codex.appServer.threads.list.v1") || codexNodeTerminalCapability(node).canStartTerminal) && (!requestedHostIds || requestedHostIds.has(`node:${node.nodeId}`))).slice(0, 100 - this.locals.length);
907
+ inventory = (await (params.listNodes?.() ?? params.runtime.nodes.list())).nodes;
908
+ nodes = inventory.filter((node) => node.gatewayLocal !== true && (node.commands?.includes("codex.appServer.threads.list.v1") || codexNodeTerminalCapability(node).canStartTerminal) && (!requestedHostIds || requestedHostIds.has(`node:${node.nodeId}`))).slice(0, 100 - this.locals.length);
946
909
  } finally {
947
910
  if (diagnostics && !diagnostics.closed) diagnostics.fields.nodeRegistryMs = performance.now() - started;
948
911
  }
@@ -961,8 +924,9 @@ var CodexCatalogListDriver = class {
961
924
  return [host];
962
925
  }
963
926
  params.signal?.throwIfAborted();
964
- const { listNodeAdoptedSessionEntries } = await import("./session-catalog-node-adoption-BVRsYOSh.mjs");
965
- const { compareNodeLabels, listPairedNode } = await import("./session-catalog-node-continue-Dowv8osw.mjs");
927
+ this.nodeSnapshots.observe(this.nodeGeneration, inventory);
928
+ const { listNodeAdoptedSessionEntries, nodeAdoptedSourceKey } = await import("./session-catalog-node-adoption-DgXvSGu0.mjs");
929
+ const { compareNodeLabels, listPairedNode, nodeLabel } = await import("./session-catalog-node-continue-DjKXHBbi.mjs");
966
930
  params.signal?.throwIfAborted();
967
931
  const adopted = listNodeAdoptedSessionEntries({
968
932
  agentId,
@@ -975,26 +939,61 @@ var CodexCatalogListDriver = class {
975
939
  diagnostics.fields.pairedNodeSettled = 0;
976
940
  }
977
941
  const trackPublication = createNodePublicationTracker(this.nodePublications, params.waitUntil);
942
+ const partial = params.allowPartialResults === true && Boolean(params.onHost && params.waitUntil);
978
943
  const pendingHosts = nodes.toSorted(compareNodeLabels).map((node) => {
944
+ const key = JSON.stringify([
945
+ agentId,
946
+ query.limitPerHost,
947
+ query.search,
948
+ query.cursors?.[`node:${node.nodeId}`],
949
+ node.displayName,
950
+ node.remoteIp,
951
+ node.caps,
952
+ node.commands,
953
+ node.invocableCommands
954
+ ]);
955
+ const publication = this.nodeSnapshots.forNode(node, this.nodeGeneration, key);
956
+ const { project, publish, publishCached, readPublished } = createNodeHostPublication(publication, adopted, nodeAdoptedSourceKey, params.onHost, params.signal, partial, trackPublication);
957
+ const cached = partial ? publication.read() : void 0;
958
+ let result;
959
+ this.nodeResults.push(() => {
960
+ const latest = partial ? publication.read() : void 0;
961
+ if (latest) {
962
+ publishCached(latest);
963
+ return project(latest.host);
964
+ }
965
+ return !partial ? result : publication.valid() ? readPublished() ?? result : void 0;
966
+ });
967
+ if (cached) publishCached(cached);
979
968
  const nodeStarted = diagnostics ? performance.now() : 0;
980
969
  if (diagnostics && !diagnostics.closed) diagnostics.fields.pairedNodeCalls = (diagnostics.fields.pairedNodeCalls ?? 0) + 1;
981
- const host = listPairedNode({
970
+ const completion = measureNodeHost(listPairedNode({
982
971
  agentId,
983
972
  runtime: params.runtime,
984
973
  node,
985
974
  query,
986
- adoptedSessions: adopted,
987
975
  terminalCapabilities: codexNodeTerminalCapability(node),
988
976
  waitUntil: trackPublication,
989
977
  signal: params.signal,
990
- ...params.onHost ? { onHost: params.onHost } : {}
978
+ onHost: publish
979
+ }), diagnostics, nodeStarted);
980
+ if (cached) {
981
+ completion.catch(() => void 0);
982
+ return Promise.resolve(project(cached.host));
983
+ }
984
+ return (partial ? boundedHost(completion) : completion).then((value) => {
985
+ result = value ? project(value) : {
986
+ hostId: `node:${node.nodeId}`,
987
+ label: nodeLabel(node),
988
+ kind: "node",
989
+ nodeId: node.nodeId,
990
+ connected: true,
991
+ pending: true,
992
+ ...codexNodeTerminalCapability(node),
993
+ sessions: []
994
+ };
995
+ return result;
991
996
  });
992
- return diagnostics ? host.finally(() => {
993
- if (!diagnostics.closed) {
994
- diagnostics.fields.pairedNodeSettled = (diagnostics.fields.pairedNodeSettled ?? 0) + 1;
995
- diagnostics.fields.nodeWaitSumMs = (diagnostics.fields.nodeWaitSumMs ?? 0) + performance.now() - nodeStarted;
996
- }
997
- }) : host;
998
997
  });
999
998
  try {
1000
999
  return await Promise.all(pendingHosts);
@@ -1021,13 +1020,20 @@ var CodexCatalogListDriver = class {
1021
1020
  if (this.active > 0 || !this.step) return;
1022
1021
  if (this.failure) {
1023
1022
  if (!this.nodeActive) this.step.reject(this.failure.error);
1024
- } else if (this.nodeHosts && this.locals.every((host) => host.value !== void 0)) {
1023
+ } else if (this.nodeHosts && this.locals.every((host) => host.value !== void 0)) try {
1025
1024
  this.complete = true;
1026
1025
  this.step.resolve({
1027
1026
  done: true,
1028
- hosts: [...this.locals.flatMap((host) => host.value ? [host.value] : []), ...this.nodeHosts]
1027
+ hosts: [...this.locals.flatMap((host) => host.value ? [host.value] : []), ...this.nodeResults.length ? this.nodeResults.flatMap((read) => {
1028
+ const host = read();
1029
+ return host ? [host] : [];
1030
+ }) : this.nodeHosts]
1029
1031
  });
1030
- } else if (this.canPause()) this.step.resolve({ done: false });
1032
+ } catch (error) {
1033
+ this.failure ??= { error };
1034
+ this.step.reject(error);
1035
+ }
1036
+ else if (this.canPause()) this.step.resolve({ done: false });
1031
1037
  }
1032
1038
  async next() {
1033
1039
  const params = this.request();
@@ -1052,12 +1058,13 @@ var CodexCatalogListDriver = class {
1052
1058
  const reason = this.failure?.error ?? this.params.signal?.reason ?? /* @__PURE__ */ new Error("Codex catalog list operation closed");
1053
1059
  this.params = void 0;
1054
1060
  for (const host of this.locals) {
1055
- host.page.close();
1061
+ if (!host.background) host.page.close();
1056
1062
  if (!host.value) host.completion.reject(reason);
1057
1063
  }
1058
1064
  this.locals = [];
1059
1065
  this.prepared = void 0;
1060
1066
  this.nodeHosts = void 0;
1067
+ this.nodeResults = [];
1061
1068
  this.failure = void 0;
1062
1069
  }
1063
1070
  };
@@ -1082,6 +1089,87 @@ async function listCodexSessionCatalog(params) {
1082
1089
  return { hosts: await runCatalogListInline(createCodexSessionCatalogListOperation(params)) };
1083
1090
  }
1084
1091
  //#endregion
1092
+ //#region extensions/codex/src/app-server/thread-history-page.ts
1093
+ const TURN_ITEM_CURSOR_PREFIX = "turn-item:";
1094
+ function encodeTurnItemCursor(turnCursor, itemId) {
1095
+ return TURN_ITEM_CURSOR_PREFIX + Buffer.from(JSON.stringify([turnCursor, itemId])).toString("base64url");
1096
+ }
1097
+ function decodeTurnItemCursor(cursor) {
1098
+ if (!cursor?.startsWith(TURN_ITEM_CURSOR_PREFIX)) return { turnCursor: cursor };
1099
+ let value;
1100
+ try {
1101
+ value = JSON.parse(Buffer.from(cursor.slice(10), "base64url").toString());
1102
+ } catch {
1103
+ throw new CatalogParamsError("invalid Codex transcript item cursor");
1104
+ }
1105
+ if (!Array.isArray(value) || value.length !== 2 || typeof value[0] !== "string" || !value[0] || typeof value[1] !== "string" || !value[1]) throw new CatalogParamsError("invalid Codex transcript item cursor");
1106
+ return {
1107
+ turnCursor: value[0],
1108
+ itemId: value[1]
1109
+ };
1110
+ }
1111
+ /** Legacy stores expose only turn cursors; an item identity preserves paging across appends. */
1112
+ async function readLegacyCodexHistoryPage(readTurns, request, projection) {
1113
+ const { turnCursor, itemId } = decodeTurnItemCursor(request.cursor);
1114
+ const page = parseTranscriptPage(await readTurns({
1115
+ threadId: request.threadId,
1116
+ limit: 1,
1117
+ sortDirection: "desc",
1118
+ itemsView: "full",
1119
+ ...turnCursor ? { cursor: turnCursor } : {}
1120
+ }));
1121
+ const source = page.data.flatMap(({ items, ...turn }) => items.toReversed().map((item) => ({
1122
+ turnId: turn.id,
1123
+ item,
1124
+ turn
1125
+ })));
1126
+ const anchorIndex = itemId ? source.findIndex(({ item }) => item.id === itemId) : -1;
1127
+ if (itemId && anchorIndex < 0) throw new CatalogParamsError("Codex transcript changed; refresh the session before loading older items");
1128
+ const remaining = source.slice(anchorIndex + 1);
1129
+ const items = projection.project(remaining.slice(0, request.limit), request.limit);
1130
+ const result = () => {
1131
+ const lastSource = remaining[items.length - 1];
1132
+ const partial = lastSource !== void 0 && items.length < remaining.length;
1133
+ const nativeCursor = partial ? page.backwardsCursor : page.nextCursor;
1134
+ const cursor = nativeCursor ? partial ? encodeTurnItemCursor(nativeCursor, lastSource.item.id) : nativeCursor : void 0;
1135
+ if (partial && !cursor) throw new Error("Codex app-server did not provide a transcript continuation anchor");
1136
+ return {
1137
+ items,
1138
+ ...cursor ? { nextCursor: cursor } : {}
1139
+ };
1140
+ };
1141
+ let bounded = result();
1142
+ while (!projection.fits(bounded)) {
1143
+ if (items.length <= 1) throw new Error("Codex transcript item exceeds the safe response size");
1144
+ items.pop();
1145
+ bounded = result();
1146
+ }
1147
+ return bounded;
1148
+ }
1149
+ /** Callers authorize the thread; this reader owns native cursor and response-size semantics. */
1150
+ async function readCodexThreadHistoryPage(control, thread, request, projection) {
1151
+ if (thread.historyMode !== "paginated") return readLegacyCodexHistoryPage((params) => control.listTurnPage(params), request, projection);
1152
+ let limit = request.limit;
1153
+ for (;;) {
1154
+ const page = await control.listItemPage({
1155
+ threadId: request.threadId,
1156
+ limit,
1157
+ sortDirection: "desc",
1158
+ ...request.cursor ? { cursor: request.cursor } : {}
1159
+ });
1160
+ const nextCursor = readControlCursor(page.nextCursor, "transcript next response");
1161
+ const items = projection.project(page.data, limit);
1162
+ const result = {
1163
+ items,
1164
+ ...nextCursor ? { nextCursor } : {}
1165
+ };
1166
+ const fittingCount = items.length - (projection.fits(result) ? 0 : 1);
1167
+ if (fittingCount === page.data.length) return result;
1168
+ if (fittingCount < 1) throw new Error("Codex transcript item exceeds the safe response size");
1169
+ limit = fittingCount;
1170
+ }
1171
+ }
1172
+ //#endregion
1085
1173
  //#region extensions/codex/src/session-catalog-transcript-item.ts
1086
1174
  const CODEX_MESSAGE_TYPES = /* @__PURE__ */ new Map([
1087
1175
  ["userMessage", "userMessage"],
@@ -1135,8 +1223,8 @@ const transcriptPageSchema = z.strictObject({
1135
1223
  function parseCodexCatalogTranscriptPage(value) {
1136
1224
  return transcriptPageSchema.parse(value);
1137
1225
  }
1138
- function projectTranscriptPage(items, limit) {
1139
- const projected = items.map(toGenericTranscriptItem);
1226
+ function projectTranscriptPage(entries, limit) {
1227
+ const projected = entries.map(({ item }) => toGenericTranscriptItem(item));
1140
1228
  const page = sessionCatalogPaging.boundTranscriptPage(projected.toReversed(), limit, 0).items;
1141
1229
  for (const [index, item] of page.entries()) if (item.text !== projected[index]?.text && projected[index]?.text) item.truncated = true;
1142
1230
  return page;
@@ -1147,15 +1235,14 @@ function pageFitsNodeTransport(page) {
1147
1235
  /** The legacy API can anchor a turn, but cannot continue within that turn. */
1148
1236
  async function readLegacyCodexTranscriptPage(readTurns, request) {
1149
1237
  return readLegacyCodexHistoryPage(readTurns, request, {
1150
- project: (entries, limit) => projectTranscriptPage(entries.map(({ item }) => item), limit),
1238
+ project: projectTranscriptPage,
1151
1239
  fits: pageFitsNodeTransport
1152
1240
  });
1153
1241
  }
1154
1242
  /** Uses the native store's item cursor whenever that store supports item history. */
1155
1243
  async function readCodexCatalogTranscriptPage(control, request) {
1156
- const thread = await control.requireEligibleThread(request.threadId);
1157
- return readCodexThreadHistoryPage(control, thread, request, {
1158
- project: (entries, limit) => projectTranscriptPage(entries.map(({ item }) => item), limit),
1244
+ return readCodexThreadHistoryPage(control, await control.requireEligibleThread(request.threadId), request, {
1245
+ project: projectTranscriptPage,
1159
1246
  fits: pageFitsNodeTransport
1160
1247
  });
1161
1248
  }
@@ -1167,19 +1254,42 @@ function createCodexSessionCatalogNodeHostCommands(controlFactory, bindingStore)
1167
1254
  const parsed = parseJsonParams(paramsJSON);
1168
1255
  if (!isRecord(parsed)) throw new CatalogParamsError("Codex session catalog parameters must be an object");
1169
1256
  const agentId = readBoundedOptionalString(parsed, "agentId", 256);
1257
+ const sourceHomeId = readBoundedOptionalString(parsed, "sourceHomeId", 256);
1258
+ const source = await controlFactory.forNode(agentId);
1259
+ if (sourceHomeId && sourceHomeId !== source.sourceHomeId) throw new CatalogParamsError("Codex catalog source home changed. Reopen the session from the catalog.");
1170
1260
  const request = { ...parsed };
1171
1261
  delete request.agentId;
1262
+ delete request.sourceHomeId;
1172
1263
  return {
1173
- ...await controlFactory.forNode(agentId),
1264
+ ...source,
1174
1265
  params: request,
1175
1266
  paramsJSON: JSON.stringify(request)
1176
1267
  };
1177
1268
  };
1269
+ const transcriptCommand = (command, read) => ({
1270
+ command,
1271
+ cap: CODEX_APP_SERVER_THREADS_CAPABILITY,
1272
+ dangerous: false,
1273
+ hasActiveWork: controlFactory.hasActiveWork,
1274
+ onDisconnect: controlFactory.disconnect,
1275
+ handle: async (paramsJSON) => {
1276
+ const request = await bindRequest(paramsJSON);
1277
+ const action = readNodeTranscriptParams(request.params);
1278
+ try {
1279
+ return JSON.stringify(await read(request.control, action));
1280
+ } catch (error) {
1281
+ if (error instanceof CatalogParamsError) throw error;
1282
+ throw new Error("Codex app-server transcript is unavailable", { cause: error });
1283
+ }
1284
+ }
1285
+ });
1178
1286
  const commands = [
1179
1287
  {
1180
1288
  command: CODEX_APP_SERVER_THREADS_LIST_COMMAND,
1181
1289
  cap: CODEX_APP_SERVER_THREADS_CAPABILITY,
1182
1290
  dangerous: false,
1291
+ hasActiveWork: controlFactory.hasActiveWork,
1292
+ onDisconnect: controlFactory.disconnect,
1183
1293
  handle: async (paramsJSON) => {
1184
1294
  const request = await bindRequest(paramsJSON);
1185
1295
  const pageParams = readPageParams(request.params);
@@ -1202,50 +1312,27 @@ function createCodexSessionCatalogNodeHostCommands(controlFactory, bindingStore)
1202
1312
  } } : {},
1203
1313
  searchTerm: pageParams.searchTerm
1204
1314
  });
1205
- return JSON.stringify(page);
1315
+ return JSON.stringify({
1316
+ ...page,
1317
+ sourceHomeId: request.sourceHomeId,
1318
+ canContinueCodex: request.transport === "stdio"
1319
+ });
1206
1320
  } catch {
1207
1321
  throw new Error("Codex app-server catalog is unavailable");
1208
1322
  }
1209
1323
  }
1210
1324
  },
1211
- {
1212
- command: CODEX_APP_SERVER_THREAD_TURNS_LIST_COMMAND,
1213
- cap: CODEX_APP_SERVER_THREADS_CAPABILITY,
1214
- dangerous: false,
1215
- handle: async (paramsJSON) => {
1216
- const request = await bindRequest(paramsJSON);
1217
- const action = readNodeTranscriptParams(request.params);
1218
- try {
1219
- await request.control.requireEligibleThread(action.threadId);
1220
- const page = parseTranscriptPage(await request.control.listTurnPage({
1221
- threadId: action.threadId,
1222
- limit: action.limit,
1223
- sortDirection: "desc",
1224
- itemsView: "full",
1225
- ...action.cursor ? { cursor: action.cursor } : {}
1226
- }));
1227
- return JSON.stringify(page);
1228
- } catch (error) {
1229
- if (error instanceof CatalogParamsError) throw error;
1230
- throw new Error("Codex app-server transcript is unavailable", { cause: error });
1231
- }
1232
- }
1233
- },
1234
- {
1235
- command: CODEX_CATALOG_TRANSCRIPT_READ_COMMAND,
1236
- cap: CODEX_APP_SERVER_THREADS_CAPABILITY,
1237
- dangerous: false,
1238
- handle: async (paramsJSON) => {
1239
- const request = await bindRequest(paramsJSON);
1240
- const action = readNodeTranscriptParams(request.params);
1241
- try {
1242
- return JSON.stringify(await readCodexCatalogTranscriptPage(request.control, action));
1243
- } catch (error) {
1244
- if (error instanceof CatalogParamsError) throw error;
1245
- throw new Error("Codex app-server transcript is unavailable", { cause: error });
1246
- }
1247
- }
1248
- },
1325
+ transcriptCommand(CODEX_APP_SERVER_THREAD_TURNS_LIST_COMMAND, async (control, action) => {
1326
+ await control.requireEligibleThread(action.threadId);
1327
+ return parseTranscriptPage(await control.listTurnPage({
1328
+ threadId: action.threadId,
1329
+ limit: action.limit,
1330
+ sortDirection: "desc",
1331
+ itemsView: "full",
1332
+ ...action.cursor ? { cursor: action.cursor } : {}
1333
+ }));
1334
+ }),
1335
+ transcriptCommand(CODEX_CATALOG_TRANSCRIPT_READ_COMMAND, readCodexCatalogTranscriptPage),
1249
1336
  createCodexTerminalNodeHostCommand(bindRequest),
1250
1337
  createCodexTerminalStartNodeHostCommand()
1251
1338
  ];
@@ -1263,19 +1350,14 @@ function readNodeTranscriptParams(value) {
1263
1350
  const cursor = readBoundedOptionalString(value, "cursor", MAX_CURSOR_LENGTH);
1264
1351
  return {
1265
1352
  threadId,
1266
- limit: readBoundedLimit(value.limit, "limit", 20, 50),
1353
+ limit: normalizeLimit(value.limit, "limit", 20, 50),
1267
1354
  ...cursor ? { cursor } : {}
1268
1355
  };
1269
1356
  }
1270
- function readBoundedLimit(value, key, fallback, max) {
1271
- if (value === void 0) return fallback;
1272
- if (!Number.isInteger(value) || value < 1 || value > max) throw new CatalogParamsError(`${key} must be an integer from 1 to ${max}`);
1273
- return value;
1274
- }
1275
1357
  /** Reads the persisted transcript for a Gateway-local or paired-node Codex session. */
1276
1358
  async function readCodexSessionTranscript(params) {
1277
1359
  const cursor = readControlCursor(params.cursor, "transcript request");
1278
- const limit = readBoundedLimit(params.limit, "limit", 20, 50);
1360
+ const limit = normalizeLimit(params.limit, "limit", 20, 50);
1279
1361
  if (params.source || params.hostId === "gateway:local") {
1280
1362
  const page = await readCodexCatalogTranscriptPage(params.control, {
1281
1363
  threadId: params.threadId,
@@ -1298,6 +1380,7 @@ async function readCodexSessionTranscript(params) {
1298
1380
  params: {
1299
1381
  agentId: params.agentId,
1300
1382
  threadId: params.threadId,
1383
+ ...params.sourceHomeId ? { sourceHomeId: params.sourceHomeId } : {},
1301
1384
  ...request
1302
1385
  },
1303
1386
  timeoutMs: NODE_INVOKE_TIMEOUT_MS,
@@ -1314,7 +1397,7 @@ async function readCodexSessionTranscript(params) {
1314
1397
  cursor,
1315
1398
  limit
1316
1399
  });
1317
- const { nodeLabel } = await import("./session-catalog-node-continue-Dowv8osw.mjs");
1400
+ const { nodeLabel } = await import("./session-catalog-node-continue-DjKXHBbi.mjs");
1318
1401
  return {
1319
1402
  hostId: params.hostId,
1320
1403
  label: nodeLabel(node),
@@ -1330,7 +1413,7 @@ function readMarker(probe) {
1330
1413
  const turnId = probe.marker.turnId;
1331
1414
  if (turnId !== null && typeof turnId !== "string") return;
1332
1415
  const count = probe.marker.userMessageCount;
1333
- if (count !== void 0 && (!Number.isSafeInteger(count) || count < 0)) return;
1416
+ if (count !== void 0 && (typeof count !== "number" || !Number.isSafeInteger(count) || count < 0)) return;
1334
1417
  return {
1335
1418
  turnId,
1336
1419
  ...count === void 0 ? {} : { userMessageCount: count }
@@ -1346,7 +1429,7 @@ function classifyCodexUpstreamTurns(params) {
1346
1429
  if (!newest?.id) return;
1347
1430
  const markerIndex = marker.turnId === null ? -1 : params.turns.findIndex((turn) => turn.id === marker.turnId);
1348
1431
  const candidateTurns = markerIndex < 0 ? params.turns : params.turns.slice(0, markerIndex + 1);
1349
- const newestUserMessageCount = countUserMessages(newest);
1432
+ const newestUserMessageCount = newest.items.filter((item) => item.type === "userMessage").length;
1350
1433
  if (!(marker.turnId !== newest.id || marker.userMessageCount === void 0 || newestUserMessageCount > marker.userMessageCount)) return;
1351
1434
  const ownTexts = new Set(params.probe.ownRecentUserTexts);
1352
1435
  let humanTurns = 0;
@@ -1379,9 +1462,6 @@ function classifyCodexUpstreamTurns(params) {
1379
1462
  } : {}
1380
1463
  };
1381
1464
  }
1382
- function countUserMessages(turn) {
1383
- return turn.items.filter((item) => item.type === "userMessage").length;
1384
- }
1385
1465
  function normalizeUserMessageTexts(item) {
1386
1466
  const typed = item;
1387
1467
  const contentTexts = typed.content?.filter((input) => input.type === "text").map((input) => input.text.trim().replace(/\s+/g, " ")).filter(Boolean);
@@ -1400,9 +1480,11 @@ async function checkCodexUpstreamActivity(probes, control, resolveThreadId = (pr
1400
1480
  limit: CODEX_UPSTREAM_TURN_LIMIT,
1401
1481
  sortDirection: "desc",
1402
1482
  itemsView: "full"
1483
+ }).catch((error) => {
1484
+ if (error instanceof CodexAppServerRpcError && error.code === -32600) return;
1485
+ throw error;
1403
1486
  });
1404
- const marker = readMarker(probe);
1405
- if (page.data.length === 0 && marker) {
1487
+ if (!page?.data.length && readMarker(probe)) {
1406
1488
  try {
1407
1489
  await pinned.readThread(threadId, false);
1408
1490
  } catch (error) {
@@ -1413,7 +1495,7 @@ async function checkCodexUpstreamActivity(probes, control, resolveThreadId = (pr
1413
1495
  }
1414
1496
  continue;
1415
1497
  }
1416
- const activity = classifyCodexUpstreamTurns({
1498
+ const activity = page && classifyCodexUpstreamTurns({
1417
1499
  probe,
1418
1500
  turns: page.data
1419
1501
  });
@@ -1479,8 +1561,8 @@ async function requireEligibleCodexThread(params) {
1479
1561
  remaining();
1480
1562
  if (thread.id !== threadId || thread.ephemeral === true || !isInteractiveThreadSource(thread.source)) throw unverified();
1481
1563
  if (!root) {
1482
- const { CODEX_CATALOG_NATIVE_PAGE_LIMIT } = await import("./session-catalog-native-projection-ChV3cCtm.mjs").then((n) => n.i);
1483
- const { CODEX_CATALOG_MAX_ROWS } = await import("./session-catalog-native-projection-ChV3cCtm.mjs").then((n) => n.U);
1564
+ const { CODEX_CATALOG_NATIVE_PAGE_LIMIT } = await import("./session-catalog-native-projection-DjhwGL6x.mjs").then((n) => n.a);
1565
+ const { CODEX_CATALOG_MAX_ROWS } = await import("./session-catalog-limits-DDxOsQeC.mjs").then((n) => n.r);
1484
1566
  let cursor;
1485
1567
  const seenCursors = /* @__PURE__ */ new Set();
1486
1568
  for (;;) {
@@ -1522,6 +1604,91 @@ async function requireEligibleCodexThread(params) {
1522
1604
  return await withTimeout(verify(), requests.requestTimeoutMs, "Codex session eligibility could not be verified", unverified);
1523
1605
  }
1524
1606
  //#endregion
1607
+ //#region extensions/codex/src/session-catalog-control-requests.ts
1608
+ function createCodexCatalogRequestSnapshot(requestTimeoutMs, request, index, beginList, catalogRead = false) {
1609
+ const read = (method, params, timeoutMs, observation) => {
1610
+ const scope = catalogRead ? void 0 : currentCodexCatalogListRequest();
1611
+ if (!scope) return request(method, params, timeoutMs, void 0, observation);
1612
+ return scope.read(timeoutMs ?? requestTimeoutMs, async (remaining) => {
1613
+ const attempt = beginList(scope);
1614
+ if (!attempt.allowed) throw attempt.error;
1615
+ return await request(method, params, remaining, void 0, observation);
1616
+ });
1617
+ };
1618
+ return {
1619
+ index,
1620
+ beginList,
1621
+ get requestTimeoutMs() {
1622
+ return catalogRead ? requestTimeoutMs : currentCodexCatalogListRequest()?.remaining(requestTimeoutMs) ?? requestTimeoutMs;
1623
+ },
1624
+ listThreads: (params, timeoutMs, observation) => read(CODEX_CONTROL_METHODS.listThreads, params, timeoutMs, observation),
1625
+ listThreadTurns: (params) => read(CODEX_CONTROL_METHODS.listThreadTurns, params),
1626
+ listThreadItems: (params) => read(CODEX_CONTROL_METHODS.listThreadItems, params),
1627
+ forkThread: (params, assertCurrent) => request(CODEX_CONTROL_METHODS.forkThread, assertCodexThreadForkParams(params), void 0, assertCurrent),
1628
+ readThread: async (threadId, includeTurns, timeoutMs) => (await read(CODEX_CONTROL_METHODS.readThread, {
1629
+ threadId,
1630
+ includeTurns
1631
+ }, timeoutMs)).thread,
1632
+ archiveThread: async (threadId, assertCurrent) => {
1633
+ await request(CODEX_CONTROL_METHODS.archiveThread, { threadId }, void 0, assertCurrent);
1634
+ }
1635
+ };
1636
+ }
1637
+ function createCodexSessionCatalogControlFromRequests(params) {
1638
+ return {
1639
+ forkContext: params.forkContext,
1640
+ ...params.clientId ? { clientId: params.clientId } : {},
1641
+ ...params.connectionFingerprint ? { connectionFingerprint: params.connectionFingerprint } : {},
1642
+ withPinnedConnection: params.withPinnedConnection,
1643
+ async initialize() {
1644
+ await (await params.createRequestSnapshot().index()).initialize();
1645
+ },
1646
+ requireEligibleThread: (threadId) => requireEligibleCodexThread({
1647
+ threadId,
1648
+ requests: params.createRequestSnapshot(),
1649
+ localSessionsRoot: params.localSessionsRoot,
1650
+ sourceHomeId: params.sourceHomeId,
1651
+ managedThreads: params.managedThreads,
1652
+ now: params.now
1653
+ }),
1654
+ retireConnection: params.retireConnection,
1655
+ async listPage(pageParams) {
1656
+ readControlCursor(pageParams.cursor, "request");
1657
+ const query = readPageParams(pageParams);
1658
+ return await withCodexCatalogListRequest(async (request) => {
1659
+ const requests = params.createRequestSnapshot();
1660
+ const timeoutMs = Math.min(requests.requestTimeoutMs, 5e3);
1661
+ const deadline = request.constrainDeadline(performance.now() + timeoutMs);
1662
+ return await (await withTimeout(requests.index(), request.remaining(timeoutMs), "Codex session catalog is still loading", () => new CodexCatalogLoadingError())).list(query, deadline);
1663
+ });
1664
+ },
1665
+ async listDescendantPage(listParams) {
1666
+ const requests = params.createRequestSnapshot();
1667
+ return await requests.listThreads(listParams, requests.requestTimeoutMs);
1668
+ },
1669
+ async readThread(threadId, includeTurns = false) {
1670
+ return await params.createRequestSnapshot().readThread(threadId, includeTurns);
1671
+ },
1672
+ async listTurnPage(listParams) {
1673
+ return await params.createRequestSnapshot().listThreadTurns(listParams);
1674
+ },
1675
+ listItemPage: (listParams) => params.createRequestSnapshot().listThreadItems(listParams),
1676
+ async forkThread(forkParams, assertCurrent) {
1677
+ const requests = params.createRequestSnapshot();
1678
+ const index = forkParams.ephemeral === true ? void 0 : await requests.index();
1679
+ const response = await requests.forkThread(forkParams, assertCurrent);
1680
+ if (index && !index.get(response.thread.id)) await index.upsertThread(response.thread);
1681
+ return response;
1682
+ },
1683
+ async archiveThread(threadId, assertCurrent) {
1684
+ const requests = params.createRequestSnapshot();
1685
+ const index = await requests.index();
1686
+ await requests.archiveThread(threadId, assertCurrent);
1687
+ index.archive(threadId);
1688
+ }
1689
+ };
1690
+ }
1691
+ //#endregion
1525
1692
  //#region extensions/codex/src/session-catalog-homes.ts
1526
1693
  /** Discovers path facts on demand; runtime projections belong only to their requesting owner. */
1527
1694
  function createCodexCatalogHomeResolver(params) {
@@ -1560,7 +1727,7 @@ function createCodexCatalogHomeResolver(params) {
1560
1727
  const cached = snapshot.paths.get(value);
1561
1728
  if (cached !== void 0) return cached;
1562
1729
  const resolved = path.resolve(value);
1563
- const discovery = fs.realpath(resolved).catch(() => resolved).then(async (canonical) => {
1730
+ const discovery = canonicalPathFromExistingAncestor(resolved).catch(() => resolved).then(async (canonical) => {
1564
1731
  if (await fs.stat(canonical).then((stat) => stat.isDirectory(), () => false)) snapshot.directories.add(value);
1565
1732
  snapshot.paths.set(value, canonical);
1566
1733
  return canonical;
@@ -1582,7 +1749,8 @@ function createCodexCatalogHomeResolver(params) {
1582
1749
  };
1583
1750
  for (const id of agentIds(snapshot)) {
1584
1751
  await scheduler.yield();
1585
- await append(resolveCodexAppServerHomeDir(agentDir(snapshot, id)), id);
1752
+ const directory = await homePath(snapshot, agentDir(snapshot, id));
1753
+ await append(resolveCodexAppServerHomeDir(directory), id);
1586
1754
  if (candidates.length === 100) return candidates;
1587
1755
  }
1588
1756
  for (const entry of readCodexPluginConfig(snapshot.pluginConfig).sessionCatalog?.homes ?? []) {
@@ -1600,7 +1768,7 @@ function createCodexCatalogHomeResolver(params) {
1600
1768
  await scheduler.yield();
1601
1769
  snapshot.assertCurrent();
1602
1770
  if (!agentIds(snapshot).includes(agentId)) return [];
1603
- const ownerAgentDir = agentDir(snapshot, agentId);
1771
+ const ownerAgentDir = await homePath(snapshot, agentDir(snapshot, agentId));
1604
1772
  const base = params.resolveRuntimeOptions({
1605
1773
  config: snapshot.config,
1606
1774
  pluginConfig: snapshot.pluginConfig,
@@ -1641,15 +1809,18 @@ function createCodexCatalogHomeResolver(params) {
1641
1809
  hostId: primary ? CODEX_LOCAL_SESSION_HOST_ID : `${CODEX_LOCAL_SESSION_HOST_ID}:${sourceHomeId}`,
1642
1810
  label: candidate.label,
1643
1811
  agentDir: ownerAgentDir,
1644
- appServer: primary ? base : {
1812
+ appServer: base.start.transport !== "stdio" ? base : {
1645
1813
  ...base,
1646
1814
  start: {
1647
1815
  ...base.start,
1648
- homeScope: "user",
1649
- env: {
1650
- ...base.start.env,
1651
- CODEX_HOME: candidate.codexHome
1652
- }
1816
+ codexHome: candidate.codexHome,
1817
+ ...!primary ? {
1818
+ homeScope: "user",
1819
+ env: {
1820
+ ...base.start.env,
1821
+ CODEX_HOME: candidate.codexHome
1822
+ }
1823
+ } : {}
1653
1824
  }
1654
1825
  },
1655
1826
  ...base.connectionClass === "remote" ? {} : { localSessionsRoot: path.join(candidate.codexHome, "sessions") },
@@ -1752,7 +1923,7 @@ var CodexCatalogSourceBackoff = class {
1752
1923
  if (failure) failure.probing = false;
1753
1924
  return;
1754
1925
  }
1755
- const delayMs = failure ? Math.min(failure.delayMs * 2 || INITIAL_BACKOFF_MS, MAX_BACKOFF_MS) : 0;
1926
+ const delayMs = findCodexAppServerSpawnError(error) ? Infinity : failure ? Math.min(failure.delayMs * 2 || INITIAL_BACKOFF_MS, MAX_BACKOFF_MS) : 0;
1756
1927
  sources.set(key, { failure: {
1757
1928
  error,
1758
1929
  delayMs,
@@ -1768,127 +1939,66 @@ var CodexCatalogSourceBackoff = class {
1768
1939
  };
1769
1940
  //#endregion
1770
1941
  //#region extensions/codex/src/session-catalog-control.ts
1771
- function createCodexCatalogRequestSnapshot(requestTimeoutMs, request, index, beginList, catalogRead = false) {
1772
- const read = (method, params, timeoutMs, observation) => {
1773
- const scope = catalogRead ? void 0 : currentCodexCatalogListRequest();
1774
- if (!scope) return request(method, params, timeoutMs, void 0, observation);
1775
- return scope.read(timeoutMs ?? requestTimeoutMs, async (remaining) => {
1776
- const attempt = beginList(scope);
1777
- if (!attempt.allowed) throw attempt.error;
1778
- return await request(method, params, remaining, void 0, observation);
1779
- });
1780
- };
1781
- return {
1782
- index,
1783
- beginList,
1784
- get requestTimeoutMs() {
1785
- return catalogRead ? requestTimeoutMs : currentCodexCatalogListRequest()?.remaining(requestTimeoutMs) ?? requestTimeoutMs;
1786
- },
1787
- listThreads: (params, timeoutMs, observation) => read(CODEX_CONTROL_METHODS.listThreads, params, timeoutMs, observation),
1788
- listThreadTurns: (params) => read(CODEX_CONTROL_METHODS.listThreadTurns, params),
1789
- listThreadItems: (params) => read(CODEX_CONTROL_METHODS.listThreadItems, params),
1790
- forkThread: (params, assertCurrent) => request(CODEX_CONTROL_METHODS.forkThread, assertCodexThreadForkParams(params), void 0, assertCurrent),
1791
- readThread: async (threadId, includeTurns, timeoutMs) => (await read(CODEX_CONTROL_METHODS.readThread, {
1792
- threadId,
1793
- includeTurns
1794
- }, timeoutMs)).thread,
1795
- archiveThread: async (threadId, assertCurrent) => {
1796
- await request(CODEX_CONTROL_METHODS.archiveThread, { threadId }, void 0, assertCurrent);
1797
- }
1798
- };
1799
- }
1800
- function createCodexSessionCatalogControlFromRequests(params) {
1801
- return {
1802
- forkContext: params.forkContext,
1803
- ...params.clientId ? { clientId: params.clientId } : {},
1804
- ...params.connectionFingerprint ? { connectionFingerprint: params.connectionFingerprint } : {},
1805
- withPinnedConnection: params.withPinnedConnection,
1806
- async initialize() {
1807
- await (await params.createRequestSnapshot().index()).initialize();
1808
- },
1809
- requireEligibleThread: (threadId) => requireEligibleCodexThread({
1810
- threadId,
1811
- requests: params.createRequestSnapshot(),
1812
- localSessionsRoot: params.localSessionsRoot,
1813
- sourceHomeId: params.sourceHomeId,
1814
- managedThreads: params.managedThreads,
1815
- now: params.now
1816
- }),
1817
- retireConnection: params.retireConnection,
1818
- async listPage(pageParams) {
1819
- readControlCursor(pageParams.cursor, "request");
1820
- const query = readPageParams(pageParams);
1821
- return await withCodexCatalogListRequest(async (request) => {
1822
- const requests = params.createRequestSnapshot();
1823
- const deadline = request.deadline(requests.requestTimeoutMs);
1824
- return await (await withTimeout(requests.index(), request.remaining(requests.requestTimeoutMs), "Codex session catalog is still loading", () => new CodexCatalogLoadingError())).list(query, deadline);
1825
- });
1826
- },
1827
- async listDescendantPage(listParams) {
1828
- const requests = params.createRequestSnapshot();
1829
- return await requests.listThreads(listParams, requests.requestTimeoutMs);
1830
- },
1831
- async readThread(threadId, includeTurns = false) {
1832
- return await params.createRequestSnapshot().readThread(threadId, includeTurns);
1833
- },
1834
- async listTurnPage(listParams) {
1835
- return await params.createRequestSnapshot().listThreadTurns(listParams);
1836
- },
1837
- listItemPage: (listParams) => params.createRequestSnapshot().listThreadItems(listParams),
1838
- async forkThread(forkParams, assertCurrent) {
1839
- const requests = params.createRequestSnapshot();
1840
- const index = forkParams.ephemeral === true ? void 0 : await requests.index();
1841
- const response = await requests.forkThread(forkParams, assertCurrent);
1842
- if (index && !index.get(response.thread.id)) await index.upsertThread(response.thread);
1843
- return response;
1844
- },
1845
- async archiveThread(threadId, assertCurrent) {
1846
- const requests = params.createRequestSnapshot();
1847
- const index = await requests.index();
1848
- await requests.archiveThread(threadId, assertCurrent);
1849
- index.archive(threadId);
1850
- }
1851
- };
1852
- }
1853
1942
  /** Builds the passive catalog over the Codex plugin's canonical shared client. */
1854
1943
  function createCodexSessionCatalogControl(params) {
1855
1944
  const now = params.now ?? Date.now;
1856
1945
  const sourceBackoff = new CodexCatalogSourceBackoff(now);
1857
1946
  const noConfig = {};
1858
- const getPluginConfig = () => params.getPluginConfig();
1947
+ const resolveRuntimeOptions = (options) => {
1948
+ const runtime = params.resolveRuntimeOptions(options);
1949
+ return runtime.start.transport === "stdio" && runtime.start.commandSource === "managed" ? {
1950
+ ...runtime,
1951
+ start: {
1952
+ ...runtime.start,
1953
+ managedCommandOrder: "package-only"
1954
+ }
1955
+ } : runtime;
1956
+ };
1859
1957
  const homeResolver = createCodexCatalogHomeResolver({
1860
1958
  config: params.config ?? {},
1861
1959
  getRuntimeConfig: params.getRuntimeConfig,
1862
1960
  getPluginConfig: params.getPluginConfig,
1863
- resolveRuntimeOptions: params.resolveRuntimeOptions,
1961
+ resolveRuntimeOptions,
1864
1962
  ...params.env ? { env: params.env } : {}
1865
1963
  });
1866
1964
  const requestOptionsByConfig = /* @__PURE__ */ new WeakMap();
1867
1965
  const indexes = /* @__PURE__ */ new Map();
1868
1966
  const retiringState = /* @__PURE__ */ new Map();
1869
1967
  const directHomes = /* @__PURE__ */ new Map();
1968
+ const residentRequests = /* @__PURE__ */ new Set();
1870
1969
  let generation = params.getRuntimeConfig();
1970
+ let residentEpoch = 0;
1971
+ let starting = 0;
1871
1972
  let closed = false;
1872
1973
  let runBackground = (run) => run();
1873
- let retiring = Promise.resolve();
1874
- const residentFor = async (agentId, source) => {
1974
+ let retiring;
1975
+ const retireIndexes = () => {
1976
+ residentEpoch++;
1977
+ const closing = [];
1978
+ for (const [homeId, index] of indexes) {
1979
+ const writes = index.retire().finally(() => {
1980
+ if (retiringState.get(homeId) === writes) retiringState.delete(homeId);
1981
+ });
1982
+ retiringState.set(homeId, writes);
1983
+ closing.push(writes, index.close());
1984
+ }
1985
+ indexes.clear();
1986
+ directHomes.clear();
1987
+ const drain = Promise.allSettled([retiring, ...closing]).then(() => {
1988
+ if (retiring === drain) retiring = void 0;
1989
+ });
1990
+ retiring = drain;
1991
+ return drain;
1992
+ };
1993
+ const resolveResident = async (agentId, source) => {
1875
1994
  if (closed) throw new Error("Codex resident catalog is closed");
1876
1995
  const config = params.getRuntimeConfig();
1877
1996
  if (generation !== config) {
1878
1997
  generation = config;
1879
- const closing = [];
1880
- for (const [homeId, index] of indexes) {
1881
- const writes = index.retire().finally(() => {
1882
- if (retiringState.get(homeId) === writes) retiringState.delete(homeId);
1883
- });
1884
- retiringState.set(homeId, writes);
1885
- closing.push(writes, index.close());
1886
- }
1887
- retiring = Promise.allSettled([retiring, ...closing]).then(() => void 0);
1888
- indexes.clear();
1889
- directHomes.clear();
1998
+ retireIndexes();
1890
1999
  }
1891
- const runtime = source?.appServer ?? params.resolveRuntimeOptions({ pluginConfig: getPluginConfig() });
2000
+ const epoch = residentEpoch;
2001
+ const runtime = source?.appServer ?? resolveRuntimeOptions({ pluginConfig: params.getPluginConfig() });
1892
2002
  const requestOptions = resolveRequestOptions(runtime.start, agentId, source);
1893
2003
  const key = source?.sourceHomeId ?? agentId ?? "";
1894
2004
  let home = directHomes.get(key);
@@ -1902,12 +2012,12 @@ function createCodexSessionCatalogControl(params) {
1902
2012
  }
1903
2013
  const homeId = await home;
1904
2014
  await retiringState.get(homeId);
1905
- if (closed || generation !== config) throw new Error("Codex catalog configuration changed");
2015
+ if (closed || generation !== config || residentEpoch !== epoch) throw new Error("Codex catalog configuration changed");
1906
2016
  let index = indexes.get(homeId);
1907
2017
  if (!index) {
1908
- const [{ CodexCatalogIndex }, { canReuseCodexCatalogPreview, projectCodexCatalogDeltaPage, projectCodexCatalogPage }] = await Promise.all([import("./session-catalog-index-B141u15s.mjs"), import("./session-catalog-projection-C1Bj9Jl-.mjs")]);
2018
+ const [{ CodexCatalogIndex }, { canReuseCodexCatalogPreview, projectCodexCatalogDeltaPage, projectCodexCatalogPage }] = await Promise.all([import("./session-catalog-index-CZvDzC6z.mjs"), import("./session-catalog-projection-Cr5qP5Dj.mjs")]);
1909
2019
  source?.assertCurrent();
1910
- if (closed || generation !== config) throw new Error("Codex catalog configuration changed");
2020
+ if (closed || generation !== config || residentEpoch !== epoch) throw new Error("Codex catalog configuration changed");
1911
2021
  index = indexes.get(homeId);
1912
2022
  if (index) return index;
1913
2023
  const root = source?.localSessionsRoot ?? (runtime.connectionClass !== "remote" ? path.join(resolveCodexAppServerLocalHomeDir(requestOptions.startOptions, requestOptions.agentDir, params.env), "sessions") : void 0);
@@ -1940,17 +2050,9 @@ function createCodexSessionCatalogControl(params) {
1940
2050
  const page = await project(response, diagnostics);
1941
2051
  foreground?.assertActive();
1942
2052
  outcome = "resolved";
1943
- if (!foreground && !page.nextCursor) {
1944
- attempt.resolved();
1945
- nativeAttempt = void 0;
1946
- }
1947
2053
  return page;
1948
2054
  } catch (error) {
1949
2055
  observation?.rejected();
1950
- if (!foreground) {
1951
- attempt.rejected(error);
1952
- nativeAttempt = void 0;
1953
- }
1954
2056
  throw error;
1955
2057
  } finally {
1956
2058
  observation?.close();
@@ -1963,9 +2065,21 @@ function createCodexSessionCatalogControl(params) {
1963
2065
  runBackground: (run) => runBackground(run),
1964
2066
  localSessionsRoot: root,
1965
2067
  state: params.openResidentState?.(homeId),
2068
+ runNativeWalk: async (run) => {
2069
+ try {
2070
+ const result = await run();
2071
+ if (nativeAttempt?.allowed) nativeAttempt.resolved();
2072
+ return result;
2073
+ } catch (error) {
2074
+ if (nativeAttempt?.allowed) nativeAttempt.rejected(error);
2075
+ throw error;
2076
+ } finally {
2077
+ nativeAttempt = void 0;
2078
+ }
2079
+ },
1966
2080
  assertCurrent: () => {
1967
2081
  source?.assertCurrent();
1968
- if (closed || params.getRuntimeConfig() !== config) throw new Error("Codex catalog configuration changed");
2082
+ if (closed || params.getRuntimeConfig() !== config || residentEpoch !== epoch) throw new Error("Codex catalog configuration changed");
1969
2083
  },
1970
2084
  readNative: (query, remainingRows, foreground) => readNativePage(query, Math.min(64, remainingRows), async (response, diagnostics) => {
1971
2085
  const { sanitizeTerminalText } = await import("openclaw/plugin-sdk/text-chunking");
@@ -1988,6 +2102,13 @@ function createCodexSessionCatalogControl(params) {
1988
2102
  }
1989
2103
  return index;
1990
2104
  };
2105
+ const residentFor = (agentId, source) => {
2106
+ const request = resolveResident(agentId, source);
2107
+ residentRequests.add(request);
2108
+ const release = () => residentRequests.delete(request);
2109
+ request.then(release, release);
2110
+ return request;
2111
+ };
1991
2112
  const resolveRequestOptions = (startOptions, agentId, source) => {
1992
2113
  source?.assertCurrent();
1993
2114
  const runtimeConfig = params.getRuntimeConfig();
@@ -2015,11 +2136,11 @@ function createCodexSessionCatalogControl(params) {
2015
2136
  return resolved;
2016
2137
  };
2017
2138
  const createRequestSnapshot = (agentId, source, catalogPreview, catalogPreviewCache, catalogRows) => {
2018
- const pluginConfig = getPluginConfig();
2019
- const runtime = source?.appServer ?? params.resolveRuntimeOptions({ pluginConfig });
2139
+ const pluginConfig = params.getPluginConfig();
2140
+ const runtime = source?.appServer ?? resolveRuntimeOptions({ pluginConfig });
2020
2141
  const requestOptions = resolveRequestOptions(runtime.start, agentId, source);
2021
2142
  return createCodexCatalogRequestSnapshot(runtime.requestTimeoutMs, async (method, requestParams, timeoutMs, assertCurrent, observation) => {
2022
- const { codexControlRequest } = await import("./command-rpc-DHFpn4le.mjs").then((n) => n.n);
2143
+ const { codexControlRequest } = await import("./command-rpc-CGJGUQ6Y.mjs").then((n) => n.n);
2023
2144
  return await codexControlRequest(pluginConfig, method, requestParams, {
2024
2145
  ...requestOptions,
2025
2146
  authProfileId: null,
@@ -2037,13 +2158,13 @@ function createCodexSessionCatalogControl(params) {
2037
2158
  const forRequest = (agentId, source) => {
2038
2159
  source?.assertCurrent();
2039
2160
  const withPinnedConnection = async (run) => {
2040
- const pluginConfig = getPluginConfig();
2041
- const runtime = source?.appServer ?? params.resolveRuntimeOptions({ pluginConfig });
2161
+ const pluginConfig = params.getPluginConfig();
2162
+ const runtime = source?.appServer ?? resolveRuntimeOptions({ pluginConfig });
2042
2163
  const { agentDir, config: runtimeConfig, startOptions } = resolveRequestOptions(runtime.start, agentId, source);
2043
2164
  let catalogIndex;
2044
- const { getLeasedSharedCodexAppServerClient, releaseLeasedSharedCodexAppServerClient, retireSharedCodexAppServerClientIfCurrent } = await import("./shared-client-BpTtuLQ5.mjs").then((n) => n.y);
2045
- const { resolveCodexAppServerClientInstanceId } = await import("./client-vXs2929Q.mjs").then((n) => n.n);
2046
- const { requestCodexAppServerClientJson } = await import("./request-BioXJLYa.mjs").then((n) => n.a);
2165
+ const { getLeasedSharedCodexAppServerClient, releaseLeasedSharedCodexAppServerClient, retireSharedCodexAppServerClientIfCurrent } = await import("./shared-client-DqyTMYug.mjs").then((n) => n.v);
2166
+ const { resolveCodexAppServerClientInstanceId } = await import("./client-N0JpgSzF.mjs").then((n) => n.n);
2167
+ const { requestCodexAppServerClientJson } = await import("./request-BHZ1nz8d.mjs").then((n) => n.a);
2047
2168
  const client = await getLeasedSharedCodexAppServerClient({
2048
2169
  agentDir,
2049
2170
  config: runtimeConfig,
@@ -2106,20 +2227,37 @@ function createCodexSessionCatalogControl(params) {
2106
2227
  return source ? forRequest(agentId, source) : void 0;
2107
2228
  };
2108
2229
  return {
2230
+ hasActiveWork: () => starting > 0 || residentRequests.size > 0 || retiring !== void 0 || hasActiveSharedCodexAppServerWork() || [...indexes.values()].some((index) => index.hasActiveWork()),
2231
+ async disconnect() {
2232
+ await retireIndexes();
2233
+ await Promise.allSettled(residentRequests);
2234
+ const clients = getSharedCodexAppServerClientState();
2235
+ if (clients.liveClients.size > 0 || clients.startup.pending.size > 0) {
2236
+ const { clearSharedCodexAppServerClientAndWait } = await import("./shared-client-DqyTMYug.mjs").then((n) => n.v);
2237
+ await clearSharedCodexAppServerClientAndWait();
2238
+ }
2239
+ },
2109
2240
  async start() {
2110
- const serviceScope = AsyncLocalStorage.snapshot();
2111
- runBackground = (run) => serviceScope(run);
2112
- for (const agentId of listAgentIds(params.getRuntimeConfig() ?? params.config ?? {})) for (const source of await homeResolver.forAgent(agentId)) {
2113
- if (source.usesProcessHomeFallback) continue;
2114
- forRequest(agentId, source).initialize().catch((error) => embeddedAgentLog.warn("Codex catalog hydration failed", { error }));
2241
+ const epoch = residentEpoch;
2242
+ starting++;
2243
+ try {
2244
+ const serviceScope = AsyncLocalStorage.snapshot();
2245
+ runBackground = (run) => serviceScope(run);
2246
+ for (const agentId of listAgentIds(params.getRuntimeConfig() ?? params.config ?? {})) for (const source of await homeResolver.forAgent(agentId)) {
2247
+ if (closed || residentEpoch !== epoch) return;
2248
+ if (source.usesProcessHomeFallback) continue;
2249
+ forRequest(agentId, source).initialize().catch((error) => {
2250
+ if (!findCodexAppServerSpawnError(error)) embeddedAgentLog.warn("Codex catalog hydration failed", { error });
2251
+ });
2252
+ }
2253
+ } finally {
2254
+ starting--;
2115
2255
  }
2116
2256
  },
2117
2257
  async stop() {
2118
2258
  closed = true;
2119
- await Promise.allSettled([...indexes.values()].map((index) => index.close()));
2120
- await retiring;
2121
- indexes.clear();
2122
- directHomes.clear();
2259
+ await retireIndexes();
2260
+ await Promise.allSettled(residentRequests);
2123
2261
  },
2124
2262
  forRequest,
2125
2263
  forUpstream,
@@ -2127,9 +2265,11 @@ function createCodexSessionCatalogControl(params) {
2127
2265
  async forNode(agentId) {
2128
2266
  const source = await homeResolver.forNode(agentId);
2129
2267
  return {
2268
+ assertCurrent: () => source.assertCurrent(),
2130
2269
  control: forRequest(source.agentId, source),
2131
2270
  sourceHomeId: source.sourceHomeId,
2132
- codexHome: source.codexHome
2271
+ codexHome: source.codexHome,
2272
+ transport: source.appServer.start.transport
2133
2273
  };
2134
2274
  }
2135
2275
  };
@@ -2167,6 +2307,7 @@ function toGenericCatalogHost(host, localTerminalAvailable) {
2167
2307
  label: host.label,
2168
2308
  kind: host.kind,
2169
2309
  connected: host.connected,
2310
+ ...host.pending ? { pending: true } : {},
2170
2311
  ...host.nodeId ? { nodeId: host.nodeId } : {},
2171
2312
  sessions: host.sessions.map((session) => {
2172
2313
  const continuableStatus = !session.archived && (session.status === "idle" || session.status === "notLoaded");
@@ -2254,15 +2395,15 @@ function withCatalogListScope(initialize) {
2254
2395
  }
2255
2396
  function catalogHostMapper(localTerminalAvailable, localHomes) {
2256
2397
  return (host) => {
2257
- const diagnostics = currentCodexCatalogListDiagnostics();
2258
- const started = diagnostics ? performance.now() : 0;
2398
+ const finishTiming = startCodexCatalogListTiming("mappingMs");
2259
2399
  try {
2400
+ const localSourceAvailable = localTerminalAvailable && localHomes.some((home) => home.hostId === host.hostId && home.appServer.start.transport === "stdio");
2260
2401
  return {
2261
- ...toGenericCatalogHost(host, localTerminalAvailable),
2262
- canStartTerminal: host.kind === "gateway" ? localTerminalAvailable && host.hostId === "gateway:local" && localHomes.some((home) => home.hostId === host.hostId && home.appServer.start.transport === "stdio") : host.canStartTerminal === true
2402
+ ...toGenericCatalogHost(host, localSourceAvailable),
2403
+ canStartTerminal: host.kind === "gateway" ? localSourceAvailable && host.hostId === "gateway:local" : host.canStartTerminal === true
2263
2404
  };
2264
2405
  } finally {
2265
- if (diagnostics && !diagnostics.closed) diagnostics.fields.mappingMs = (diagnostics.fields.mappingMs ?? 0) + performance.now() - started;
2406
+ finishTiming();
2266
2407
  }
2267
2408
  };
2268
2409
  }
@@ -2312,8 +2453,9 @@ function registerCodexSessionCatalog(params) {
2312
2453
  };
2313
2454
  };
2314
2455
  const checkUpstreamActivity = createChecker(params);
2456
+ const nodeSnapshots = new CodexCatalogNodeSnapshots();
2315
2457
  const createListOperation = (query) => withCatalogListScope(async () => {
2316
- const { agentId: requestedAgentId, allowProcessHomeFallback, listNodes, onHost, waitUntil, signal, sessionEntries, ...gatewayQuery } = query;
2458
+ const { agentId: requestedAgentId, allowProcessHomeFallback, allowPartialResults, listNodes, onHost, waitUntil, signal, sessionEntries, ...gatewayQuery } = query;
2317
2459
  const agentId = resolveRequestAgentId(requestedAgentId);
2318
2460
  const selectedQuery = readGatewayParams(gatewayQuery);
2319
2461
  const localHomes = selectedQuery.hostIds && !selectedQuery.hostIds.some(isLocalCodexCatalogHost) ? [] : [...await catalogHomes(agentId, allowProcessHomeFallback)];
@@ -2330,6 +2472,8 @@ function registerCodexSessionCatalog(params) {
2330
2472
  signal,
2331
2473
  sessionEntries,
2332
2474
  localHomes,
2475
+ allowPartialResults,
2476
+ nodeSnapshots,
2333
2477
  ...onHost ? { onHost: mappedHostPublisher(onHost, mapHost) } : {}
2334
2478
  }), mapHost);
2335
2479
  });
@@ -2348,6 +2492,7 @@ function registerCodexSessionCatalog(params) {
2348
2492
  control,
2349
2493
  hostId: request.hostId,
2350
2494
  threadId: request.threadId,
2495
+ sourceHomeId: request.sourceHomeId,
2351
2496
  cursor: request.cursor,
2352
2497
  limit: request.limit ?? 20,
2353
2498
  ...source ? { source } : {}
@@ -2362,6 +2507,7 @@ function registerCodexSessionCatalog(params) {
2362
2507
  config,
2363
2508
  hostId: request.hostId,
2364
2509
  threadId: request.threadId,
2510
+ sourceHomeId: request.sourceHomeId,
2365
2511
  clientScopes: request.clientScopes
2366
2512
  });
2367
2513
  if (!isLocalCodexCatalogHost(request.hostId)) throw new CatalogParamsError("Codex session catalog hostId is invalid");
@@ -2449,16 +2595,16 @@ const codexSessionCatalogRuntime = {
2449
2595
  archiveLocal: archiveLocalCodexSession
2450
2596
  };
2451
2597
  async function continueLocalCodexSession(...args) {
2452
- const { continueLocalCodexSession: run } = await import("./session-catalog-adoption-CR_whkEW.mjs");
2598
+ const { continueLocalCodexSession: run } = await import("./session-catalog-adoption-BU_pHWG7.mjs");
2453
2599
  return run(...args);
2454
2600
  }
2455
2601
  async function archiveLocalCodexSession(...args) {
2456
- const { archiveLocalCodexSession: run } = await import("./session-catalog-archive-CwZaPacf.mjs");
2602
+ const { archiveLocalCodexSession: run } = await import("./session-catalog-archive-spHfihri.mjs");
2457
2603
  return run(...args);
2458
2604
  }
2459
2605
  async function continueNodeCodexSession(...args) {
2460
- const { continueNodeCodexSession: run } = await import("./session-catalog-node-continue-Dowv8osw.mjs");
2606
+ const { continueNodeCodexSession: run } = await import("./session-catalog-node-continue-DjKXHBbi.mjs");
2461
2607
  return run(...args);
2462
2608
  }
2463
2609
  //#endregion
2464
- export { withCodexCatalogListRequest as a, createCodexSessionCatalogNodeHostCommands as i, createCodexSessionCatalogNodeInvokePolicies as n, lookupNodeCodexCatalogRecord as o, createCodexSessionCatalogControl as r, CodexCatalogAvailability as s, codexSessionCatalogRuntime as t };
2610
+ export { createCodexSessionCatalogNodeHostCommands as i, createCodexSessionCatalogNodeInvokePolicies as n, createCodexSessionCatalogControl as r, codexSessionCatalogRuntime as t };