chainlesschain 0.165.2 → 0.165.4

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 (210) hide show
  1. package/README.md +151 -29
  2. package/package.json +2 -2
  3. package/src/assets/web-panel/assets/{AIOps-lS1R0Cza.js → AIOps-C__nnraW.js} +1 -1
  4. package/src/assets/web-panel/assets/{ActionButton-BmlgBPsj.js → ActionButton-CsKWHEZ-.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-CNKczv1S.js → Analytics-BhIjfjWO.js} +3 -3
  6. package/src/assets/web-panel/assets/{AppLayout-BuZGJARQ.js → AppLayout-BjuXFzWZ.js} +4 -4
  7. package/src/assets/web-panel/assets/{Artifacts-Dm73Sl-O.js → Artifacts-k6whDkZJ.js} +1 -1
  8. package/src/assets/web-panel/assets/{Audit-BGMW7A5e.js → Audit-C4FBMYRh.js} +1 -1
  9. package/src/assets/web-panel/assets/{BackgroundAgents-BQ6M54JR.js → BackgroundAgents-C_vRrSXk.js} +1 -1
  10. package/src/assets/web-panel/assets/{Backup-DBzGP0bR.js → Backup-CngFZeVp.js} +1 -1
  11. package/src/assets/web-panel/assets/{BaseInput-D1mLCoOV.js → BaseInput-B_H9EBRm.js} +1 -1
  12. package/src/assets/web-panel/assets/{Chat-BUfcN7p8.js → Chat-DLEC5kt7.js} +4 -4
  13. package/src/assets/web-panel/assets/ChatBubbleRenderer-xijcWkJe.js +1 -0
  14. package/src/assets/web-panel/assets/{Checkbox-Du0Yg5Pi.js → Checkbox-m3ClR4xh.js} +1 -1
  15. package/src/assets/web-panel/assets/{Codegen-B2RXziHW.js → Codegen-CmLSFrgp.js} +1 -1
  16. package/src/assets/web-panel/assets/{Col-DWhekOrR.js → Col-DFGQteHN.js} +1 -1
  17. package/src/assets/web-panel/assets/{Community-HQhrkon4.js → Community-EUUVORHE.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compact-izHNb4uz.js → Compact-2PSg0Yr7.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compliance-BDwLy41-.js → Compliance-CcKur7gB.js} +1 -1
  20. package/src/assets/web-panel/assets/{Cowork-DFJhLa7K.js → Cowork-DK_Fezfa.js} +3 -3
  21. package/src/assets/web-panel/assets/{Cron-DYY9RG7-.js → Cron-Dbw89xl7.js} +2 -2
  22. package/src/assets/web-panel/assets/{Crosschain-rr7tJTtv.js → Crosschain-CH66h_Ec.js} +1 -1
  23. package/src/assets/web-panel/assets/{DID-D2sfHRLi.js → DID-D1igRb17.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dashboard-q_eGdhha.js → Dashboard-DVAsrobk.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dropdown-Cufrh2Bz.js → Dropdown-Dl7W8AQs.js} +1 -1
  26. package/src/assets/web-panel/assets/{EmailListRenderer-B-kdv10f.js → EmailListRenderer-D5tpaEQC.js} +1 -1
  27. package/src/assets/web-panel/assets/{FamilyGuardDashboard-D21XjgfG.js → FamilyGuardDashboard-O_VQf8gq.js} +1 -1
  28. package/src/assets/web-panel/assets/{Federation-CAwRTLZH.js → Federation-BTVcgS9n.js} +1 -1
  29. package/src/assets/web-panel/assets/{FormItemContext-vx3daNDF.js → FormItemContext-BRnkJAIz.js} +1 -1
  30. package/src/assets/web-panel/assets/{GenericCardRenderer-CRWY2wU4.js → GenericCardRenderer-8OWSCkDj.js} +1 -1
  31. package/src/assets/web-panel/assets/{Git-Q6SwauyD.js → Git-WXLYTQj2.js} +2 -2
  32. package/src/assets/web-panel/assets/{Governance-BJ1q4IQZ.js → Governance-BezaUhtc.js} +1 -1
  33. package/src/assets/web-panel/assets/{Inference-CSWjROgD.js → Inference-CuRay3Gu.js} +1 -1
  34. package/src/assets/web-panel/assets/{KnowledgeGraph-fzuQsWuY.js → KnowledgeGraph-DfWLDW1m.js} +1 -1
  35. package/src/assets/web-panel/assets/{Logs-DVF8Mnns.js → Logs-C55y2pPY.js} +2 -2
  36. package/src/assets/web-panel/assets/MarkdownRenderer-hDpWdiBc.js +1 -0
  37. package/src/assets/web-panel/assets/{Marketplace-BQP7LOA4.js → Marketplace-Dk08Uycg.js} +1 -1
  38. package/src/assets/web-panel/assets/{McpTools-BNlJCmNc.js → McpTools-C11fSB5V.js} +4 -4
  39. package/src/assets/web-panel/assets/{Memory-DLLg5WQ4.js → Memory-mr0eZc97.js} +2 -2
  40. package/src/assets/web-panel/assets/{MobileBridge-CR2skNAF.js → MobileBridge-C0iCSRbb.js} +1 -1
  41. package/src/assets/web-panel/assets/{MobileProjects-BxVavObl.js → MobileProjects-CY-xMG8Z.js} +1 -1
  42. package/src/assets/web-panel/assets/{Mtc-B17pgqMI.js → Mtc-Bplqc_Wc.js} +4 -4
  43. package/src/assets/web-panel/assets/{MtcAudit-4UmV5cIL.js → MtcAudit-BlzwsoSM.js} +2 -2
  44. package/src/assets/web-panel/assets/{Multisig-DoMEXEcU.js → Multisig-BBLmTty6.js} +3 -3
  45. package/src/assets/web-panel/assets/{NLProgramming-h9DMXFX4.js → NLProgramming-DtT1uf1W.js} +1 -1
  46. package/src/assets/web-panel/assets/{Notes-Cihn-xX8.js → Notes-DcqQAxTK.js} +3 -3
  47. package/src/assets/web-panel/assets/{NotificationSettings-BE6ZGa3R.js → NotificationSettings-cb0kWoZe.js} +1 -1
  48. package/src/assets/web-panel/assets/{OrderTableRenderer-CnwojoSI.js → OrderTableRenderer-kw9HZQNN.js} +1 -1
  49. package/src/assets/web-panel/assets/{Organization-B2vpwmjb.js → Organization-DlTlbkUN.js} +4 -4
  50. package/src/assets/web-panel/assets/{Overflow-C4z28R0-.js → Overflow-pp1qs-oY.js} +1 -1
  51. package/src/assets/web-panel/assets/{P2P-BVlFkwhW.js → P2P-BESLnyYz.js} +2 -2
  52. package/src/assets/web-panel/assets/{PdhVaultBrowser-BXbEdL5B.js → PdhVaultBrowser-B-J1mGuf.js} +3 -3
  53. package/src/assets/web-panel/assets/{Permissions-C28xs4lp.js → Permissions-B36PeT1_.js} +4 -4
  54. package/src/assets/web-panel/assets/{PersonalDataHub-Dgl_rBjM.js → PersonalDataHub-CTK2ad-3.js} +3 -3
  55. package/src/assets/web-panel/assets/{Pipeline-3QUIhrKI.js → Pipeline-zJNGXsac.js} +1 -1
  56. package/src/assets/web-panel/assets/{Privacy-8Gh33OZ5.js → Privacy-b9fz0Qf0.js} +1 -1
  57. package/src/assets/web-panel/assets/{ProjectInit-BNmg4tZi.js → ProjectInit-DjZbZgiB.js} +2 -2
  58. package/src/assets/web-panel/assets/{ProjectSettings-vgMfeCf9.js → ProjectSettings-C-hHJXlD.js} +2 -2
  59. package/src/assets/web-panel/assets/Projects-BC9KSDM6.js +1 -0
  60. package/src/assets/web-panel/assets/{Providers-CXoOa8eX.js → Providers-Dz-CAYYU.js} +1 -1
  61. package/src/assets/web-panel/assets/{QrScannerModal-BhfTF0oS.js → QrScannerModal-A0yoQ3-3.js} +1 -1
  62. package/src/assets/web-panel/assets/{QuickAsk-C746HEAj.js → QuickAsk-DrFgFJNC.js} +1 -1
  63. package/src/assets/web-panel/assets/{Recommend-BSej8Eo0.js → Recommend-KC8hF1g4.js} +1 -1
  64. package/src/assets/web-panel/assets/{RemoteSession-f3gmnlG3.js → RemoteSession-DGTPIk6u.js} +3 -3
  65. package/src/assets/web-panel/assets/{Reputation-CyvybpkN.js → Reputation-QmbwM7Yk.js} +1 -1
  66. package/src/assets/web-panel/assets/{Row-DwV2PeYn.js → Row-BxjJylia.js} +1 -1
  67. package/src/assets/web-panel/assets/{RssFeed-11GrzjZy.js → RssFeed-B7Wda1J6.js} +3 -3
  68. package/src/assets/web-panel/assets/{Search-BjKXkrAY.js → Search-_plQ_YSA.js} +1 -1
  69. package/src/assets/web-panel/assets/{Security-eWiFb9Yk.js → Security-CD2YJZfx.js} +2 -2
  70. package/src/assets/web-panel/assets/{Services-CdCsMAtt.js → Services-qQE7NmwE.js} +2 -2
  71. package/src/assets/web-panel/assets/{Skeleton-4Q2UTKQ5.js → Skeleton-DgQqkFf7.js} +1 -1
  72. package/src/assets/web-panel/assets/{Skills-v4rtYrRj.js → Skills-C4C0oFFt.js} +1 -1
  73. package/src/assets/web-panel/assets/{Sla-CRhsFvd_.js → Sla-Px2N2B5c.js} +1 -1
  74. package/src/assets/web-panel/assets/SpeechSettings-DN6C3lQd.js +1 -0
  75. package/src/assets/web-panel/assets/{SyncSettings-D16zonl7.js → SyncSettings-jm5aH_m7.js} +2 -2
  76. package/src/assets/web-panel/assets/{Tasks-Xxozz0i_.js → Tasks-DlkJcv67.js} +1 -1
  77. package/src/assets/web-panel/assets/{Templates-CXJpPtCT.js → Templates-DyrTHUBs.js} +1 -1
  78. package/src/assets/web-panel/assets/{Tenant-XRV0L1ZF.js → Tenant-mC434PtL.js} +1 -1
  79. package/src/assets/web-panel/assets/{Terminal-CYuO1i_w.js → Terminal-o0_s3NgK.js} +2 -2
  80. package/src/assets/web-panel/assets/{TimelineRenderer-BXqitWsu.js → TimelineRenderer-DAGlAXOw.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tokens-BvPrDHIy.js → Tokens-BnulS_bs.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trigger-DhCrSTf5.js → Trigger-suQbVXYM.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trust-DmsuZD6K.js → Trust-DbIJAPo5.js} +1 -1
  84. package/src/assets/web-panel/assets/{UkeySign-D_yrts5C.js → UkeySign-CQNpbIHi.js} +1 -1
  85. package/src/assets/web-panel/assets/{VideoEditing-B01ihPrm.js → VideoEditing-D8aWCERk.js} +1 -1
  86. package/src/assets/web-panel/assets/{Wallet-DpUjKa-N.js → Wallet-CuLpYfZc.js} +2 -2
  87. package/src/assets/web-panel/assets/{WebAuthn-CL07yON6.js → WebAuthn-CsfG8ZMc.js} +2 -2
  88. package/src/assets/web-panel/assets/{WorkflowEditor-CLMflnRr.js → WorkflowEditor-BYsEAZbd.js} +1 -1
  89. package/src/assets/web-panel/assets/{chat-DtUqe8h_.js → chat-FT4Um3-I.js} +1 -1
  90. package/src/assets/web-panel/assets/{colors-DPKrgVfy.js → colors-CKbS_Wlt.js} +1 -1
  91. package/src/assets/web-panel/assets/{compact-item-BTt2GtOm.js → compact-item-CFJtzuJM.js} +1 -1
  92. package/src/assets/web-panel/assets/{createContext-D_VeUc1J.js → createContext-B9kSRW6K.js} +1 -1
  93. package/src/assets/web-panel/assets/devWarning-DJZ0gAMu.js +1 -0
  94. package/src/assets/web-panel/assets/{hasIn-1kndiylj.js → hasIn-DR-x0Xpi.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-dVc-CXY4.js → index-7jHr_A_k.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-DFIZ_1Sf.js → index-B3ZX81mK.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-fk2Rjacw.js → index-B7osrXqy.js} +3 -3
  98. package/src/assets/web-panel/assets/{index-CHG-KcS4.js → index-BGbPnC5x.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-Dbbymxpj.js → index-BI5hP_qy.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-BaZAbw9A.js → index-BK3TiKVq.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-CzjkKUmR.js → index-BVPU43b1.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-BAXfRKfG.js → index-BW-t9n-q.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-8nz_fmlj.js → index-BfFCQHL3.js} +1 -1
  104. package/src/assets/web-panel/assets/index-Bizb4hkw.js +1 -0
  105. package/src/assets/web-panel/assets/{index-DdkplL9R.js → index-Bt4fS2eL.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-DG2MZQ3f.js → index-BwR7yc2h.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-DfKBRdSS.js → index-Bzz0C1BZ.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-GsoUQ2M7.js → index-C2JvmYRc.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-l1BETrDb.js → index-CGaXUsIs.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-4bna2_SR.js → index-CJmIQ9XR.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-DfGl8CqG.js → index-C_enk9I_.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-D95OFht7.js → index-Cr2FLUsD.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-DsJCDUJG.js → index-CvrCCqJt.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-sDoMHTNA.js → index-D4LfPvWA.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-By5n8up9.js → index-DMGmg497.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-ocf06EVQ.js → index-DShSkww-.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-Bhudc_Ez.js → index-DTxNy0ZU.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-CX81qSM4.js → index-DW4BWjTk.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-BlDNVgBt.js → index-DWdqx7zI.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-CcO04eDn.js → index-Dap9c3eD.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-Dwqmtk65.js → index-DcfxhKXR.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-2eyAXE3d.js → index-DdkIhfi-.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-brCInrzq.js → index-DeSgw-WV.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-DJ8vXGOa.js → index-DiNUEpSQ.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-BHpBMWCh.js → index-DjEP7WkH.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-m31Ka8hZ.js → index-DtkFqPVA.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-CtF7EN49.js → index-KqDaCApw.js} +1 -1
  128. package/src/assets/web-panel/assets/index-OHSl-xCh.js +1 -0
  129. package/src/assets/web-panel/assets/{index-B9KvcS7R.js → index-OSzjTzGM.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-CauoBQkH.js → index-QBSeNVO3.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-FzdwcSy2.js → index-WE08gMJP.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-DxdTdBix.js → index-r2VI1Ikk.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-BepLZwgB.js → index-tqSEHPRT.js} +1 -1
  134. package/src/assets/web-panel/assets/{initDefaultProps-CvyYJd7z.js → initDefaultProps-Dd7n7VgI.js} +1 -1
  135. package/src/assets/web-panel/assets/{motion-DYZkhUdz.js → motion-BwxouRw1.js} +1 -1
  136. package/src/assets/web-panel/assets/{move-slnJRVT1.js → move-DObN0PG9.js} +1 -1
  137. package/src/assets/web-panel/assets/{mtc-parser-DVc0CKmy.js → mtc-parser-B3nOUQc7.js} +1 -1
  138. package/src/assets/web-panel/assets/{omit-BCXAtHCq.js → omit-o9WU2Nbl.js} +1 -1
  139. package/src/assets/web-panel/assets/{pickAttrs-DBsemz_K.js → pickAttrs-CL_vvfQ_.js} +1 -1
  140. package/src/assets/web-panel/assets/{placementArrow-BRtkJ-nv.js → placementArrow-CYrM2tyK.js} +1 -1
  141. package/src/assets/web-panel/assets/{responsiveObserve-Cebq7EZn.js → responsiveObserve-k_06cQ96.js} +1 -1
  142. package/src/assets/web-panel/assets/{slide-DT7qvId2.js → slide-CPKG0pxS.js} +1 -1
  143. package/src/assets/web-panel/assets/{statusUtils-pQiITLkG.js → statusUtils-BDDEeLTw.js} +1 -1
  144. package/src/assets/web-panel/assets/{styleChecker-c-19BVKQ.js → styleChecker-Cmb7RTh7.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFlexGapSupport-DsS5-0bE.js → useFlexGapSupport-e2IedC4N.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFs-CxGiMe5n.js → useFs-CE_gxVnm.js} +1 -1
  147. package/src/assets/web-panel/assets/{usePersonalDataHub-D9btVID5.js → usePersonalDataHub-BkMIIKMz.js} +1 -1
  148. package/src/assets/web-panel/assets/{vnode-CUYFsFEN.js → vnode-DW886XV1.js} +1 -1
  149. package/src/assets/web-panel/assets/{zoom-CXmn_35j.js → zoom-Dwo_adaf.js} +1 -1
  150. package/src/assets/web-panel/index.html +1 -1
  151. package/src/command-help-index.json +3 -3
  152. package/src/commands/agent.js +105 -35
  153. package/src/commands/artifacts.js +363 -33
  154. package/src/commands/cowork.js +202 -36
  155. package/src/commands/session-budget.js +155 -0
  156. package/src/commands/session-location.js +948 -0
  157. package/src/commands/session.js +72 -46
  158. package/src/data/changelog.json +26 -0
  159. package/src/gateways/ws/artifact-protocol.js +77 -13
  160. package/src/gateways/ws/session-protocol.js +391 -24
  161. package/src/gateways/ws/ws-agent-handler.js +191 -14
  162. package/src/gateways/ws/ws-server.js +14 -3
  163. package/src/gateways/ws/ws-session-gateway.js +101 -5
  164. package/src/harness/jsonl-session-store.js +1210 -0
  165. package/src/lib/agent-team/team-runner.js +43 -13
  166. package/src/lib/artifact-access-ledger.js +461 -0
  167. package/src/lib/artifact-cleanup-ledger.js +861 -0
  168. package/src/lib/artifact-deletion-ledger.js +677 -0
  169. package/src/lib/artifact-store.js +256 -51
  170. package/src/lib/background-agent-keeper-protocol.js +75 -4
  171. package/src/lib/background-agent-launch-barrier.js +74 -0
  172. package/src/lib/background-agent-supervisor.js +149 -5
  173. package/src/lib/background-turn-bootstrap-protocol.js +4 -0
  174. package/src/lib/command-lifecycle-report.js +8 -4
  175. package/src/lib/cowork-adapter.js +9 -5
  176. package/src/lib/cowork-task-runner.js +20 -0
  177. package/src/lib/cowork-workflow.js +178 -20
  178. package/src/lib/direct-model-usage.js +62 -22
  179. package/src/lib/dynamic-workflow-runtime.js +3184 -111
  180. package/src/lib/execution-location-result-apply.js +339 -0
  181. package/src/lib/execution-location-result-artifact.js +271 -0
  182. package/src/lib/execution-location-result-review.js +253 -0
  183. package/src/lib/execution-location-result-store.js +331 -0
  184. package/src/lib/execution-location-result.js +617 -0
  185. package/src/lib/execution-location-target.js +236 -1
  186. package/src/lib/managed-tool-checkpoint.js +47 -4
  187. package/src/lib/process-execution-broker/workspace-transaction.js +3 -0
  188. package/src/lib/session-budget-production-root.js +376 -0
  189. package/src/lib/session-budget-runtime.js +109 -18
  190. package/src/lib/session-budget-usage.js +63 -0
  191. package/src/lib/session-host-snapshot.js +19 -2
  192. package/src/lib/session-resource-budget.js +766 -105
  193. package/src/lib/sub-agent-context.js +69 -22
  194. package/src/lib/web-ui-server.js +12 -1
  195. package/src/lib/with-file-lock.js +175 -26
  196. package/src/repl/agent-repl.js +237 -16
  197. package/src/runtime/agent-core.js +123 -0
  198. package/src/runtime/headless-runner.js +135 -46
  199. package/src/runtime/headless-stream.js +133 -25
  200. package/src/runtime/policies/agent-policy.js +10 -0
  201. package/src/workers/background-agent-keeper.js +112 -19
  202. package/src/workers/background-agent-worker.js +383 -134
  203. package/src/workers/background-turn-bootstrap.js +13 -8
  204. package/src/assets/web-panel/assets/ChatBubbleRenderer-CY5m8ZHg.js +0 -1
  205. package/src/assets/web-panel/assets/MarkdownRenderer-BLif4QSg.js +0 -1
  206. package/src/assets/web-panel/assets/Projects-BhtAVilc.js +0 -1
  207. package/src/assets/web-panel/assets/SpeechSettings-DLjKsDVu.js +0 -1
  208. package/src/assets/web-panel/assets/devWarning-Bj5nUW2v.js +0 -1
  209. package/src/assets/web-panel/assets/index-CPcM-eqo.js +0 -1
  210. package/src/assets/web-panel/assets/index-xeSyVoRe.js +0 -1
@@ -19,6 +19,17 @@ import {
19
19
  } from "../../lib/mcp-ledger-recovery-admission.js";
20
20
  import { readSessionHostResumeState } from "../../lib/session-host-snapshot.js";
21
21
  import { sanitizePersistedMessages } from "../../lib/session-message-provenance.js";
22
+ import {
23
+ deleteJsonlSession,
24
+ startSession as startJsonlSession,
25
+ } from "../../harness/jsonl-session-store.js";
26
+ import {
27
+ normalizeSessionBudgetRootConfig,
28
+ openProductionSessionBudgetRoot,
29
+ resolveSessionBudgetRootOptions,
30
+ sessionBudgetAdmissionError,
31
+ } from "../../lib/session-budget-production-root.js";
32
+ import { mergePricing } from "../../lib/llm-pricing.js";
22
33
 
23
34
  const PAYLOAD_DIGEST = /^sha256:[0-9a-f]{64}$/;
24
35
  const RAW_AUTHORITY_HASH = /^[0-9a-f]{64}$/;
@@ -467,6 +478,30 @@ function envelopeError(id, code, message, sessionId, details = {}) {
467
478
  // Phase 5 envelope opt-in via beta flag `unified-envelope-2026-04-16`.
468
479
  // Falls back to false if BetaFlags is unavailable so legacy behavior wins.
469
480
  const PHASE5_ENVELOPE_FLAG = "unified-envelope-2026-04-16";
481
+
482
+ function wsBudgetDependency(server, name, fallback) {
483
+ const candidate = server?._sessionBudgetDependencies?.[name];
484
+ return typeof candidate === "function" ? candidate : fallback;
485
+ }
486
+
487
+ function resolveWsSessionBudget(message) {
488
+ return resolveSessionBudgetRootOptions({
489
+ sessionBudget: message.sessionBudget,
490
+ sessionMaxConcurrent: message.sessionMaxConcurrent,
491
+ sessionMaxSpawns: message.sessionMaxSpawns,
492
+ sessionMaxDepth: message.sessionMaxDepth,
493
+ sessionMaxTurns: message.sessionMaxTurns,
494
+ sessionMaxTokens: message.sessionMaxTokens,
495
+ sessionMaxCostUsd: message.sessionMaxCostUsd,
496
+ sessionMaxWallMs: message.sessionMaxWallMs,
497
+ sessionMaxToolMs: message.sessionMaxToolMs,
498
+ });
499
+ }
500
+
501
+ function sameSessionBudgetConfig(left, right) {
502
+ return JSON.stringify(left || null) === JSON.stringify(right || null);
503
+ }
504
+
470
505
  async function _isPhase5EnvelopesEnabled() {
471
506
  try {
472
507
  const { getBetaFlags } =
@@ -478,9 +513,22 @@ async function _isPhase5EnvelopesEnabled() {
478
513
  }
479
514
  }
480
515
 
481
- async function ensureSessionHandler(server, ws, session) {
482
- if (server.sessionHandlers.has(session.id)) {
483
- return server.sessionHandlers.get(session.id);
516
+ async function ensureSessionHandler(
517
+ server,
518
+ ws,
519
+ session,
520
+ { sessionHostLease: suppliedSessionHostLease = null } = {},
521
+ ) {
522
+ const budgetConfig = session.sessionBudgetRoot
523
+ ? normalizeSessionBudgetRootConfig(session.sessionBudgetRoot)
524
+ : resolveSessionBudgetRootOptions({});
525
+ if (budgetConfig.enabled && session.type === "chat") {
526
+ const error = new Error(
527
+ "Durable WebSocket session budgets require an agent session",
528
+ );
529
+ error.code = "CC_SESSION_BUDGET_WS_AGENT_REQUIRED";
530
+ suppliedSessionHostLease?.release?.();
531
+ throw error;
484
532
  }
485
533
 
486
534
  const { WebSocketInteractionAdapter } =
@@ -503,6 +551,17 @@ async function ensureSessionHandler(server, ws, session) {
503
551
  },
504
552
  });
505
553
 
554
+ const existingHandler = server.sessionHandlers.get(session.id);
555
+ if (existingHandler) {
556
+ suppliedSessionHostLease?.release?.();
557
+ existingHandler.assertSessionBudgetAdmission?.("WebSocket resume");
558
+ if (typeof existingHandler.attachInteraction === "function") {
559
+ existingHandler.attachInteraction(session.interaction);
560
+ } else {
561
+ existingHandler.interaction = session.interaction;
562
+ }
563
+ }
564
+
506
565
  // Route MCP elicitation through the authenticated WS question channel. The
507
566
  // MCP client may be shared by the runtime, so this is deliberately only a
508
567
  // transport hook; the MCP request/answer ids remain inside the pending
@@ -524,6 +583,8 @@ async function ensureSessionHandler(server, ws, session) {
524
583
  );
525
584
  }
526
585
 
586
+ if (existingHandler) return existingHandler;
587
+
527
588
  let handler;
528
589
  if (session.type === "chat") {
529
590
  const { WSChatHandler } = await import("../../lib/ws-chat-handler.js");
@@ -533,18 +594,79 @@ async function ensureSessionHandler(server, ws, session) {
533
594
  });
534
595
  } else {
535
596
  const { WSAgentHandler } = await import("./ws-agent-handler.js");
536
- const sessionHostLease = acquireSessionHostLease(session.id, {
537
- hostKind: "ws",
538
- });
597
+ let sessionHostLease =
598
+ suppliedSessionHostLease ||
599
+ wsBudgetDependency(
600
+ server,
601
+ "acquireSessionHostLease",
602
+ acquireSessionHostLease,
603
+ )(session.id, { hostKind: "ws" });
604
+ let sessionBudgetRoot = null;
539
605
  try {
606
+ if (budgetConfig.enabled) {
607
+ const priceTable =
608
+ budgetConfig.limits.maxUsd != null
609
+ ? wsBudgetDependency(server, "mergePricing", mergePricing)(
610
+ server.sessionManager.config?.llm?.pricing,
611
+ )
612
+ : undefined;
613
+ sessionBudgetRoot = wsBudgetDependency(
614
+ server,
615
+ "openProductionSessionBudgetRoot",
616
+ openProductionSessionBudgetRoot,
617
+ )(session.id, budgetConfig, {
618
+ persist: true,
619
+ signal: sessionHostLease.signal || null,
620
+ table: priceTable,
621
+ });
622
+ if (
623
+ sessionBudgetRoot?.enabled !== true ||
624
+ !sessionBudgetRoot.budget ||
625
+ !sessionBudgetRoot.options ||
626
+ sessionBudgetRoot.options.sessionBudget !==
627
+ sessionBudgetRoot.budget ||
628
+ typeof sessionBudgetRoot.close !== "function"
629
+ ) {
630
+ const error = new Error(
631
+ "WebSocket session budget root is invalid",
632
+ );
633
+ error.code = "CC_SESSION_BUDGET_ROOT_INVALID";
634
+ throw error;
635
+ }
636
+ if (sessionBudgetRoot.budget.signal?.aborted === true) {
637
+ throw sessionBudgetAdmissionError(
638
+ sessionBudgetRoot.budget.reason?.(),
639
+ "WebSocket startup",
640
+ );
641
+ }
642
+ }
540
643
  handler = new WSAgentHandler({
541
644
  session,
542
645
  interaction: session.interaction,
543
646
  db: server.sessionManager.db,
544
647
  sessionHostLease,
648
+ sessionBudgetRoot,
545
649
  });
650
+ sessionHostLease = null;
651
+ sessionBudgetRoot = null;
546
652
  } catch (error) {
547
- sessionHostLease.release();
653
+ const cleanupErrors = [];
654
+ try {
655
+ sessionBudgetRoot?.close?.();
656
+ } catch (cleanupError) {
657
+ cleanupErrors.push(cleanupError);
658
+ }
659
+ try {
660
+ sessionHostLease?.release?.();
661
+ } catch (cleanupError) {
662
+ cleanupErrors.push(cleanupError);
663
+ }
664
+ if (cleanupErrors.length > 0) {
665
+ throw new AggregateError(
666
+ [error, ...cleanupErrors],
667
+ "WebSocket handler bootstrap and authority cleanup both failed",
668
+ );
669
+ }
548
670
  throw error;
549
671
  }
550
672
  }
@@ -578,9 +700,40 @@ export async function handleSessionCreate(server, id, ws, message) {
578
700
  worktreeIsolation,
579
701
  systemPromptExtension,
580
702
  shellPolicyOverrides,
703
+ sessionBudget,
704
+ sessionMaxConcurrent,
705
+ sessionMaxSpawns,
706
+ sessionMaxDepth,
707
+ sessionMaxTurns,
708
+ sessionMaxTokens,
709
+ sessionMaxCostUsd,
710
+ sessionMaxWallMs,
711
+ sessionMaxToolMs,
581
712
  } = message;
582
713
 
714
+ let createdSessionId = null;
715
+ let canonicalSessionCreated = false;
716
+ let bootstrapLease = null;
717
+ let delegatedBootstrapLease = null;
583
718
  try {
719
+ const sessionBudgetRoot = resolveWsSessionBudget({
720
+ sessionBudget,
721
+ sessionMaxConcurrent,
722
+ sessionMaxSpawns,
723
+ sessionMaxDepth,
724
+ sessionMaxTurns,
725
+ sessionMaxTokens,
726
+ sessionMaxCostUsd,
727
+ sessionMaxWallMs,
728
+ sessionMaxToolMs,
729
+ });
730
+ if (sessionBudgetRoot.enabled && (sessionType || "agent") !== "agent") {
731
+ const error = new Error(
732
+ "Durable WebSocket session budgets require sessionType=agent",
733
+ );
734
+ error.code = "CC_SESSION_BUDGET_WS_AGENT_REQUIRED";
735
+ throw error;
736
+ }
584
737
  const { sessionId } = server.sessionManager.createSession({
585
738
  type: sessionType || "agent",
586
739
  provider,
@@ -593,9 +746,76 @@ export async function handleSessionCreate(server, id, ws, message) {
593
746
  worktreeIsolation,
594
747
  systemPromptExtension,
595
748
  shellPolicyOverrides,
749
+ sessionBudgetRoot: sessionBudgetRoot.enabled
750
+ ? sessionBudgetRoot
751
+ : null,
752
+ requireDurable: sessionBudgetRoot.enabled,
596
753
  });
754
+ createdSessionId = sessionId;
597
755
 
598
756
  const session = server.sessionManager.getSession(sessionId);
757
+ if (sessionBudgetRoot.enabled) {
758
+ bootstrapLease = wsBudgetDependency(
759
+ server,
760
+ "acquireSessionHostLease",
761
+ acquireSessionHostLease,
762
+ )(sessionId, { hostKind: "ws" });
763
+ let startedSessionId;
764
+ try {
765
+ startedSessionId = wsBudgetDependency(
766
+ server,
767
+ "startJsonlSession",
768
+ startJsonlSession,
769
+ )(sessionId, {
770
+ title: `WS agent ${new Date().toISOString().slice(0, 10)}`,
771
+ provider: session.provider,
772
+ model: session.model || "",
773
+ sessionBudgetRoot,
774
+ });
775
+ canonicalSessionCreated = true;
776
+ } catch (cause) {
777
+ const error = new Error(
778
+ "Budgeted WebSocket JSONL session could not be durably created",
779
+ { cause },
780
+ );
781
+ error.code = "CC_SESSION_BUDGET_SESSION_START_FAILED";
782
+ throw error;
783
+ }
784
+ if (startedSessionId !== sessionId) {
785
+ const error = new Error(
786
+ "Budgeted WebSocket JSONL session returned a different session id",
787
+ );
788
+ error.code = "CC_SESSION_BUDGET_SESSION_START_FAILED";
789
+ throw error;
790
+ }
791
+ const canonicalStart = wsBudgetDependency(
792
+ server,
793
+ "readSessionHostResumeState",
794
+ readSessionHostResumeState,
795
+ )(sessionId);
796
+ if (!canonicalStart?.snapshot?.verified) {
797
+ const error = new Error(
798
+ "Budgeted WebSocket JSONL session could not be verified",
799
+ );
800
+ error.code = "CC_SESSION_BUDGET_SESSION_START_FAILED";
801
+ throw error;
802
+ }
803
+ if (
804
+ !canonicalStart.sessionBudgetRoot ||
805
+ !sameSessionBudgetConfig(
806
+ canonicalStart.sessionBudgetRoot,
807
+ sessionBudgetRoot,
808
+ )
809
+ ) {
810
+ const error = new Error(
811
+ "Budgeted WebSocket JSONL declaration does not match the requested root",
812
+ );
813
+ error.code = "CC_SESSION_BUDGET_CONFIG_MISMATCH";
814
+ throw error;
815
+ }
816
+ session.canonicalJsonlSession = true;
817
+ session.sessionHostSnapshot = canonicalStart.snapshot;
818
+ }
599
819
  const record = createSessionRecord(session, {
600
820
  sessionId,
601
821
  sessionType: sessionType || "agent",
@@ -608,11 +828,12 @@ export async function handleSessionCreate(server, id, ws, message) {
608
828
  status: "created",
609
829
  });
610
830
 
611
- try {
612
- await ensureSessionHandler(server, ws, session);
613
- } catch (_err) {
614
- // Session exists even if handler bootstrapping fails.
615
- }
831
+ delegatedBootstrapLease = bootstrapLease;
832
+ bootstrapLease = null;
833
+ await ensureSessionHandler(server, ws, session, {
834
+ sessionHostLease: delegatedBootstrapLease,
835
+ });
836
+ delegatedBootstrapLease = null;
616
837
 
617
838
  server.emit("session:create", { sessionId, type: sessionType || "agent" });
618
839
 
@@ -659,7 +880,60 @@ export async function handleSessionCreate(server, id, ws, message) {
659
880
  ),
660
881
  );
661
882
  } catch (err) {
662
- server._send(ws, envelopeError(id, "SESSION_CREATE_FAILED", err.message));
883
+ if (createdSessionId) {
884
+ const createdSession = server.sessionManager.getSession(createdSessionId);
885
+ createdSession?.mcpClient?.clearElicitationHandler?.(createdSessionId);
886
+ const handler = server.sessionHandlers.get(createdSessionId);
887
+ try {
888
+ handler?.destroy?.();
889
+ } catch {
890
+ // The creation failure remains authoritative; rollback below still
891
+ // removes the unpublished manager/database state.
892
+ }
893
+ server.sessionHandlers.delete(createdSessionId);
894
+ if (canonicalSessionCreated) {
895
+ try {
896
+ wsBudgetDependency(
897
+ server,
898
+ "deleteJsonlSession",
899
+ deleteJsonlSession,
900
+ )(createdSessionId);
901
+ } catch {
902
+ // The bootstrap failure remains authoritative. A durable tombstone
903
+ // or orphan cleanup incident must never become session.started.
904
+ }
905
+ }
906
+ try {
907
+ if (
908
+ typeof server.sessionManager.rollbackSessionCreation === "function"
909
+ ) {
910
+ server.sessionManager.rollbackSessionCreation(createdSessionId);
911
+ } else {
912
+ server.sessionManager.closeSession(createdSessionId);
913
+ }
914
+ } catch {
915
+ // Do not turn a failed bootstrap into a successful protocol response.
916
+ }
917
+ }
918
+ try {
919
+ bootstrapLease?.release?.();
920
+ } catch {
921
+ // Preserve the bootstrap error sent below.
922
+ }
923
+ try {
924
+ delegatedBootstrapLease?.release?.();
925
+ } catch {
926
+ // ensureSessionHandler may already have attempted this release.
927
+ }
928
+ server._send(
929
+ ws,
930
+ envelopeError(
931
+ id,
932
+ err?.code || "SESSION_CREATE_FAILED",
933
+ err?.message || "WebSocket session creation failed",
934
+ createdSessionId,
935
+ ),
936
+ );
663
937
  }
664
938
  }
665
939
 
@@ -673,7 +947,11 @@ export async function handleSessionResume(server, id, ws, message) {
673
947
  }
674
948
 
675
949
  const { sessionId } = message;
676
- const canonicalResume = readSessionHostResumeState(sessionId);
950
+ const canonicalResume = wsBudgetDependency(
951
+ server,
952
+ "readSessionHostResumeState",
953
+ readSessionHostResumeState,
954
+ )(sessionId);
677
955
  if (canonicalResume && !canonicalResume.snapshot.verified) {
678
956
  server._send(
679
957
  ws,
@@ -702,6 +980,66 @@ export async function handleSessionResume(server, id, ws, message) {
702
980
  return;
703
981
  }
704
982
 
983
+ let sessionBudgetRoot;
984
+ let canonicalSessionBudgetRoot = null;
985
+ try {
986
+ sessionBudgetRoot = session.sessionBudgetRoot
987
+ ? normalizeSessionBudgetRootConfig(session.sessionBudgetRoot)
988
+ : resolveSessionBudgetRootOptions({});
989
+ canonicalSessionBudgetRoot = canonicalResume?.sessionBudgetRoot
990
+ ? normalizeSessionBudgetRootConfig(canonicalResume.sessionBudgetRoot)
991
+ : null;
992
+ } catch (error) {
993
+ server._send(
994
+ ws,
995
+ envelopeError(
996
+ id,
997
+ error?.code || "CC_SESSION_BUDGET_CONFIG_INVALID",
998
+ error?.message || "Persisted WebSocket session budget is invalid",
999
+ sessionId,
1000
+ ),
1001
+ );
1002
+ return;
1003
+ }
1004
+ if (
1005
+ sessionBudgetRoot.enabled &&
1006
+ (!canonicalResume || !canonicalSessionBudgetRoot)
1007
+ ) {
1008
+ server._send(
1009
+ ws,
1010
+ envelopeError(
1011
+ id,
1012
+ "CC_SESSION_BUDGET_JSONL_REQUIRED",
1013
+ "Budgeted WebSocket session has no canonical JSONL budget authority",
1014
+ sessionId,
1015
+ ),
1016
+ );
1017
+ return;
1018
+ }
1019
+ if (
1020
+ canonicalSessionBudgetRoot?.enabled === true &&
1021
+ sessionBudgetRoot.enabled !== true
1022
+ ) {
1023
+ sessionBudgetRoot = canonicalSessionBudgetRoot;
1024
+ } else if (
1025
+ canonicalSessionBudgetRoot &&
1026
+ !sameSessionBudgetConfig(canonicalSessionBudgetRoot, sessionBudgetRoot)
1027
+ ) {
1028
+ server._send(
1029
+ ws,
1030
+ envelopeError(
1031
+ id,
1032
+ "CC_SESSION_BUDGET_CONFIG_MISMATCH",
1033
+ "WebSocket DB and canonical JSONL budget declarations do not match",
1034
+ sessionId,
1035
+ ),
1036
+ );
1037
+ return;
1038
+ }
1039
+ session.sessionBudgetRoot = sessionBudgetRoot.enabled
1040
+ ? sessionBudgetRoot
1041
+ : null;
1042
+
705
1043
  // A JSONL transcript is the cross-host fact source. A fully verified one
706
1044
  // replaces a stale DB/WS copy. The damaged case returned above before the
707
1045
  // manager or agent handler could be resumed; only a genuinely absent JSONL
@@ -760,13 +1098,24 @@ export async function handleSessionResume(server, id, ws, message) {
760
1098
  // Recovery authority must be attached before a handler is created/refreshed
761
1099
  // or history is exposed. Otherwise an existing clean controller can admit a
762
1100
  // turn in the resume window before the unsafe projection reaches it.
763
- if (!server.sessionHandlers.has(sessionId)) {
764
- try {
765
- await ensureSessionHandler(server, ws, session);
766
- } catch (_err) {
767
- // Session resumed without live handler. A future handler still reads the
768
- // already-attached fail-closed recovery authority from the session.
769
- }
1101
+ try {
1102
+ // Existing handlers retain the durable lease and budget root, but their
1103
+ // interaction adapter belongs to the previous WebSocket transport. Route
1104
+ // every resume through the common bootstrap so it can reattach the new
1105
+ // transport without reopening either authority.
1106
+ await ensureSessionHandler(server, ws, session);
1107
+ } catch (error) {
1108
+ server._send(
1109
+ ws,
1110
+ envelopeError(
1111
+ id,
1112
+ error?.code || "SESSION_RESUME_FAILED",
1113
+ error?.message || "WebSocket session handler could not be resumed",
1114
+ sessionId,
1115
+ { ...(sessionSnapshot ? { sessionSnapshot } : {}) },
1116
+ ),
1117
+ );
1118
+ return;
770
1119
  }
771
1120
  const handler = server.sessionHandlers.get(sessionId);
772
1121
  if (typeof handler?.refreshMcpRecoveryRuntime === "function") {
@@ -986,6 +1335,7 @@ export function handleSessionList(server, id, ws) {
986
1335
 
987
1336
  export function handleSessionClose(server, id, ws, message) {
988
1337
  const { sessionId } = message;
1338
+ const cleanupErrors = [];
989
1339
 
990
1340
  const closingSession = server.sessionManager?.getSession?.(sessionId);
991
1341
  if (closingSession?.mcpClient?.clearElicitationHandler) {
@@ -994,18 +1344,35 @@ export function handleSessionClose(server, id, ws, message) {
994
1344
 
995
1345
  const handler = server.sessionHandlers.get(sessionId);
996
1346
  if (handler && handler.destroy) {
997
- handler.destroy();
1347
+ try {
1348
+ handler.destroy();
1349
+ } catch (error) {
1350
+ cleanupErrors.push(error);
1351
+ }
998
1352
  }
999
1353
  server.sessionHandlers.delete(sessionId);
1000
1354
 
1001
1355
  if (server.sessionManager) {
1002
1356
  try {
1003
1357
  server.sessionManager.closeSession(sessionId);
1004
- } catch (_err) {
1005
- // Non-critical.
1358
+ } catch (error) {
1359
+ cleanupErrors.push(error);
1006
1360
  }
1007
1361
  }
1008
1362
 
1363
+ if (cleanupErrors.length > 0) {
1364
+ server._send(
1365
+ ws,
1366
+ envelopeError(
1367
+ id,
1368
+ "CC_WS_SESSION_CLOSE_FAILED",
1369
+ "WebSocket session authority could not be durably closed",
1370
+ sessionId,
1371
+ ),
1372
+ );
1373
+ return;
1374
+ }
1375
+
1009
1376
  server.emit("session:close", { sessionId });
1010
1377
 
1011
1378
  // Phase 5: broadcast service envelope for unified subscribers.