chainlesschain 0.163.6 → 0.163.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 (218) hide show
  1. package/package.json +1 -1
  2. package/src/assets/web-panel/assets/{AIOps-DDIUofA8.js → AIOps-axqQfwv8.js} +1 -1
  3. package/src/assets/web-panel/assets/{ActionButton-Bm-5xYRn.js → ActionButton-DV-Ro0By.js} +1 -1
  4. package/src/assets/web-panel/assets/{Analytics-D5UH4ljI.js → Analytics-Bt72WEVu.js} +3 -3
  5. package/src/assets/web-panel/assets/{AppLayout-D_ifjOOP.js → AppLayout-BtepG55E.js} +5 -5
  6. package/src/assets/web-panel/assets/{Artifacts-BY1mXdC7.js → Artifacts-B7KaJ7S_.js} +1 -1
  7. package/src/assets/web-panel/assets/{Audit-Bujr4Ml3.js → Audit-FNFaUg7A.js} +1 -1
  8. package/src/assets/web-panel/assets/{BackgroundAgents-sioKSTcC.js → BackgroundAgents-DFb6J2wQ.js} +1 -1
  9. package/src/assets/web-panel/assets/{Backup-DDOAK8RK.js → Backup-CC7YBhyj.js} +1 -1
  10. package/src/assets/web-panel/assets/{BaseInput-CtCsVVke.js → BaseInput-RkgTNVtj.js} +1 -1
  11. package/src/assets/web-panel/assets/{Chat-DpNj0vnd.js → Chat-hHEmGZy-.js} +4 -4
  12. package/src/assets/web-panel/assets/{ChatBubbleRenderer-CZta3Ftr.js → ChatBubbleRenderer-CAP9YhHv.js} +1 -1
  13. package/src/assets/web-panel/assets/{Checkbox-DoHVNSXq.js → Checkbox-z5wXOQP1.js} +1 -1
  14. package/src/assets/web-panel/assets/{Codegen-DlVl7Qmv.js → Codegen-DVaDJnxy.js} +1 -1
  15. package/src/assets/web-panel/assets/{Col-GIqoPYty.js → Col-CJmaRDR5.js} +1 -1
  16. package/src/assets/web-panel/assets/{Community-CIAPEVji.js → Community-DF29_2bI.js} +1 -1
  17. package/src/assets/web-panel/assets/{Compact-BN7JiI_h.js → Compact-DtkQkBzn.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compliance-CqUWCM9B.js → Compliance-xoHDxp7I.js} +1 -1
  19. package/src/assets/web-panel/assets/{Cowork-A4iPp7A4.js → Cowork-BUm-R7ht.js} +3 -3
  20. package/src/assets/web-panel/assets/{Cron-B2zeXXWb.js → Cron-Cgl14ZkB.js} +2 -2
  21. package/src/assets/web-panel/assets/{Crosschain-BR2xmWr8.js → Crosschain-BNcbmoqh.js} +1 -1
  22. package/src/assets/web-panel/assets/{DID-BzFDjrIv.js → DID-Bwja0Zo9.js} +2 -2
  23. package/src/assets/web-panel/assets/{Dashboard-DKtDo3yA.js → Dashboard-Bk5XjEdJ.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dropdown-RNx43_YG.js → Dropdown-Ci36Oitq.js} +1 -1
  25. package/src/assets/web-panel/assets/{EmailListRenderer-SwMt4Rcy.js → EmailListRenderer--U04ZN4q.js} +1 -1
  26. package/src/assets/web-panel/assets/{FamilyGuardDashboard-CsYebZ4X.js → FamilyGuardDashboard-B2gNPR2s.js} +1 -1
  27. package/src/assets/web-panel/assets/{Federation-BmRKvBTy.js → Federation-C4KghYn7.js} +1 -1
  28. package/src/assets/web-panel/assets/{FormItemContext-CVxGTA-0.js → FormItemContext-QL7x_Q_0.js} +1 -1
  29. package/src/assets/web-panel/assets/{GenericCardRenderer-x2iXpyB7.js → GenericCardRenderer-F3Ryltwm.js} +1 -1
  30. package/src/assets/web-panel/assets/{Git-DfqbkiOP.js → Git-2HassK5k.js} +2 -2
  31. package/src/assets/web-panel/assets/{Governance-RuHyyj5O.js → Governance-DoBIp7oe.js} +1 -1
  32. package/src/assets/web-panel/assets/{Inference-Bn7uZ7rI.js → Inference--W01QhZ-.js} +1 -1
  33. package/src/assets/web-panel/assets/{KnowledgeGraph-DlP7XefZ.js → KnowledgeGraph-DmvwqGpT.js} +1 -1
  34. package/src/assets/web-panel/assets/{Logs-BYNdOiCd.js → Logs-BBJ4yAel.js} +2 -2
  35. package/src/assets/web-panel/assets/{MarkdownRenderer-aMtgN-R6.js → MarkdownRenderer-BLCZMzhJ.js} +1 -1
  36. package/src/assets/web-panel/assets/{Marketplace-JQYmDqM8.js → Marketplace-D5lNngSI.js} +1 -1
  37. package/src/assets/web-panel/assets/{McpTools-Cyx4yZ-9.js → McpTools-CkEVOMKH.js} +4 -4
  38. package/src/assets/web-panel/assets/{Memory-VDuGZTN2.js → Memory-B1Ow1xVE.js} +2 -2
  39. package/src/assets/web-panel/assets/{MobileBridge-_yKo97gi.js → MobileBridge-SgYbUfb6.js} +1 -1
  40. package/src/assets/web-panel/assets/{MobileProjects-CXRXW3q7.js → MobileProjects-BWdOvQAj.js} +1 -1
  41. package/src/assets/web-panel/assets/{Mtc-acTGtfLH.js → Mtc-DcTXSSma.js} +5 -5
  42. package/src/assets/web-panel/assets/{MtcAudit-ClpjXfkY.js → MtcAudit-Dt3WG4oj.js} +4 -4
  43. package/src/assets/web-panel/assets/{Multisig-_6Tn3o96.js → Multisig-B9B38UZx.js} +3 -3
  44. package/src/assets/web-panel/assets/{NLProgramming-CK7pbZzP.js → NLProgramming-B0S4GGvG.js} +1 -1
  45. package/src/assets/web-panel/assets/{Notes-Czy6V_P8.js → Notes-DZ5U58Ng.js} +3 -3
  46. package/src/assets/web-panel/assets/{NotificationSettings-Cqx-UVv3.js → NotificationSettings-PjL5ZW34.js} +1 -1
  47. package/src/assets/web-panel/assets/{OrderTableRenderer-C69WDxGy.js → OrderTableRenderer-DrAX2ESt.js} +1 -1
  48. package/src/assets/web-panel/assets/{Organization-DFnA9vLQ.js → Organization-Cv1GYs-c.js} +4 -4
  49. package/src/assets/web-panel/assets/{Overflow-ReZkk2yT.js → Overflow-Bbkp_PL3.js} +1 -1
  50. package/src/assets/web-panel/assets/{P2P-DzjSI0aI.js → P2P-BD8QUgoZ.js} +2 -2
  51. package/src/assets/web-panel/assets/{PdhVaultBrowser-DKTf5xIP.js → PdhVaultBrowser-BO-2PeaB.js} +3 -3
  52. package/src/assets/web-panel/assets/{Permissions-DhQ5klhR.js → Permissions-D_OPVa02.js} +4 -4
  53. package/src/assets/web-panel/assets/{PersonalDataHub-CUL1iHrW.js → PersonalDataHub-mh-pEmaB.js} +4 -4
  54. package/src/assets/web-panel/assets/{Pipeline-DU88iu4N.js → Pipeline-6JC2EDdb.js} +1 -1
  55. package/src/assets/web-panel/assets/{Privacy-Bw-sYfyK.js → Privacy-CUshzUAG.js} +1 -1
  56. package/src/assets/web-panel/assets/{ProjectInit-Bq3Q5y0z.js → ProjectInit-Cs2Aalri.js} +2 -2
  57. package/src/assets/web-panel/assets/{ProjectSettings-C8spzpho.js → ProjectSettings-1ak49tcj.js} +2 -2
  58. package/src/assets/web-panel/assets/Projects-BV4oApsm.js +1 -0
  59. package/src/assets/web-panel/assets/{Providers-Bf4eTP9W.js → Providers-CXXxvafH.js} +1 -1
  60. package/src/assets/web-panel/assets/{QrScannerModal-Dme9BDU1.js → QrScannerModal-PTcDsF58.js} +1 -1
  61. package/src/assets/web-panel/assets/{QuickAsk-CIXfv1rE.js → QuickAsk-CDwucrJw.js} +1 -1
  62. package/src/assets/web-panel/assets/{Recommend-CIxvdeZ-.js → Recommend-CJlLVRXR.js} +1 -1
  63. package/src/assets/web-panel/assets/{RemoteSession-C6k7MExI.js → RemoteSession-DlN-ETsO.js} +2 -2
  64. package/src/assets/web-panel/assets/{Reputation-CISDz2bl.js → Reputation-DI23LR6m.js} +1 -1
  65. package/src/assets/web-panel/assets/{Row-CdnDxXyf.js → Row-Cl7UQMrM.js} +1 -1
  66. package/src/assets/web-panel/assets/{RssFeed-C-QpRHsl.js → RssFeed-CexHNfh8.js} +3 -3
  67. package/src/assets/web-panel/assets/{Search-DBjaGzSn.js → Search-BneBWvRN.js} +1 -1
  68. package/src/assets/web-panel/assets/{Security-CQKukOeE.js → Security-DX7Phgrp.js} +4 -4
  69. package/src/assets/web-panel/assets/{Services-DZz86jWb.js → Services-BWXO8Mte.js} +2 -2
  70. package/src/assets/web-panel/assets/{Skeleton-jb8RMK0d.js → Skeleton-DCyOjKPJ.js} +1 -1
  71. package/src/assets/web-panel/assets/{Skills-CdY76fZG.js → Skills-CXqERsTB.js} +1 -1
  72. package/src/assets/web-panel/assets/{Sla-C_CSiZX9.js → Sla-bhbrbz8E.js} +1 -1
  73. package/src/assets/web-panel/assets/SpeechSettings-3IPU0HBZ.js +1 -0
  74. package/src/assets/web-panel/assets/{SyncSettings-qvimGO0O.js → SyncSettings-DBNTQLbM.js} +2 -2
  75. package/src/assets/web-panel/assets/{Tasks-Dng5LPJC.js → Tasks-quP0bkN-.js} +1 -1
  76. package/src/assets/web-panel/assets/{Templates-Bwqq5Wll.js → Templates-BouWmgho.js} +1 -1
  77. package/src/assets/web-panel/assets/{Tenant-DNWuwP7Z.js → Tenant-qv0D9s7z.js} +1 -1
  78. package/src/assets/web-panel/assets/{Terminal-B-6Othpp.js → Terminal-BxvbE8BB.js} +2 -2
  79. package/src/assets/web-panel/assets/{TimelineRenderer-DKpKZfzx.js → TimelineRenderer-D-IeLnJ2.js} +1 -1
  80. package/src/assets/web-panel/assets/{Tokens-DzfGMd2J.js → Tokens-CFMKKyVG.js} +1 -1
  81. package/src/assets/web-panel/assets/{Trigger-BXwUi74J.js → Trigger-L8as3UuJ.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trust-BNzUq4ui.js → Trust-MxmA4VZG.js} +1 -1
  83. package/src/assets/web-panel/assets/{UkeySign-BYugxww4.js → UkeySign-C0VvJYRi.js} +1 -1
  84. package/src/assets/web-panel/assets/{VideoEditing-DdauhtSJ.js → VideoEditing-Bf5QZj8N.js} +1 -1
  85. package/src/assets/web-panel/assets/{Wallet-CSC9bCe_.js → Wallet-BIJ9riRz.js} +4 -4
  86. package/src/assets/web-panel/assets/{WebAuthn-Q8AN3bTO.js → WebAuthn-B8p9Mhkw.js} +5 -5
  87. package/src/assets/web-panel/assets/{WorkflowEditor-d-LBGCuA.js → WorkflowEditor-BVsuaPen.js} +1 -1
  88. package/src/assets/web-panel/assets/{chat-BLVDCgsZ.js → chat-BfkjoKpV.js} +1 -1
  89. package/src/assets/web-panel/assets/{colors-BZlPSEHl.js → colors-DeAlsWK8.js} +1 -1
  90. package/src/assets/web-panel/assets/{compact-item-IWseP6R6.js → compact-item-Cs97bz5j.js} +1 -1
  91. package/src/assets/web-panel/assets/{createContext-DnVRV3Ao.js → createContext-BqbG60LH.js} +1 -1
  92. package/src/assets/web-panel/assets/devWarning-DPty0mGN.js +1 -0
  93. package/src/assets/web-panel/assets/{hasIn-DLQZA_Wn.js → hasIn-i_RY0b1X.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-B_N4-Gq9.js → index-0-agYlWL.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-DB0MJgF_.js → index-79V_zv1s.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-BOZJBTWZ.js → index-B-3tEpTc.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-DUq0c7gq.js → index-B-JVTrpr.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-Dy0R5ZED.js → index-B1CbOH1i.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-Bxp7uDD8.js → index-B5UkyA3c.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-DpVrK6fr.js → index-BESLFt4q.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-CT9vVN-X.js → index-BOVkf1K3.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-DOoQpuQY.js → index-BYUVuwKt.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-CINJQEj6.js → index-BcUXAB2s.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-CarMTIyQ.js → index-BkBi5TmC.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-C5dgnilC.js → index-Bm7lLR4c.js} +1 -1
  106. package/src/assets/web-panel/assets/index-Bt7g0Vq_.js +1 -0
  107. package/src/assets/web-panel/assets/{index-CbQNL0ue.js → index-BuLQobzW.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-CpBaJ3TD.js → index-CE2VtTlp.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-jWb70ZgZ.js → index-CED2PL_y.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-BEu2lMBy.js → index-CG3PRyAL.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-DocEhinm.js → index-CIG8fQ2_.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-D_LQodeJ.js → index-COdGA-8n.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-DZpYeqrh.js → index-CeWoNHau.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-gt8bNefW.js → index-Cf3WCLmy.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-N_GoWZX4.js → index-CgsqdnRV.js} +1 -1
  116. package/src/assets/web-panel/assets/index-ChVT0p9u.js +1 -0
  117. package/src/assets/web-panel/assets/{index-CZDekj7T.js → index-D2B4VPyP.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-YSw_gxlZ.js → index-D9evtvg2.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-DTbxp4UH.js → index-DUUrv141.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-Bbj2NS_I.js → index-DiSkx4UB.js} +3 -3
  121. package/src/assets/web-panel/assets/{index-BZs5bBnk.js → index-Dk2qouAz.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-DalA0TKC.js → index-Dk7-v4hP.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-1jeAudHd.js → index-DmbfhJUP.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-C1ifZtXo.js → index-DqBgBpgp.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-BhA3QEni.js → index-PT_5sBMA.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-BSjilZ9L.js → index-U4f5izHz.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-C2FqfMvU.js → index-YXgLng0K.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-COev0W2g.js → index-ZxO_-E8a.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-M7wxfAbm.js → index-dIHr4B_u.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-DjWnONdy.js → index-gyFpvL7l.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-Dkwsi1Kn.js → index-s1opAL-M.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-hwVDeoC0.js → index-yObj1O4n.js} +1 -1
  133. package/src/assets/web-panel/assets/{initDefaultProps-Co67Kqmb.js → initDefaultProps-C9h9yKL3.js} +1 -1
  134. package/src/assets/web-panel/assets/{motion-BMOxQSF_.js → motion-BvmLsPdu.js} +1 -1
  135. package/src/assets/web-panel/assets/{move-C5fWDw-N.js → move-CoL4ekU1.js} +1 -1
  136. package/src/assets/web-panel/assets/{mtc-parser-BJevpL0e.js → mtc-parser-C4pMy6xV.js} +1 -1
  137. package/src/assets/web-panel/assets/{omit-BCzNU8s6.js → omit-DPuJfNxx.js} +1 -1
  138. package/src/assets/web-panel/assets/{pickAttrs-CybWvDPk.js → pickAttrs-D0KEeaK2.js} +1 -1
  139. package/src/assets/web-panel/assets/{placementArrow-BMWS9HnW.js → placementArrow-BpkyINxt.js} +1 -1
  140. package/src/assets/web-panel/assets/{responsiveObserve-BoL2UnGY.js → responsiveObserve-DQI_wOq8.js} +1 -1
  141. package/src/assets/web-panel/assets/{slide-DWNfXraU.js → slide-DYfdDiRg.js} +1 -1
  142. package/src/assets/web-panel/assets/{statusUtils-BquTM3tX.js → statusUtils-B5dtvb0D.js} +1 -1
  143. package/src/assets/web-panel/assets/{styleChecker-BEkCleim.js → styleChecker-CF310mSj.js} +1 -1
  144. package/src/assets/web-panel/assets/{useFlexGapSupport-Oecnq7EA.js → useFlexGapSupport-D1Qp4BLp.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFs-CkDffJ4F.js → useFs-C7_iyvJK.js} +1 -1
  146. package/src/assets/web-panel/assets/{usePersonalDataHub-qbvKXesB.js → usePersonalDataHub-DZUt_fIm.js} +1 -1
  147. package/src/assets/web-panel/assets/{vnode-C6v8n6mA.js → vnode-D3dsi0lZ.js} +1 -1
  148. package/src/assets/web-panel/assets/{zoom-4CTeFILV.js → zoom-WdbOlvdQ.js} +1 -1
  149. package/src/assets/web-panel/index.html +1 -1
  150. package/src/command-help-index.json +2 -2
  151. package/src/commands/agent.js +90 -1
  152. package/src/commands/chat.js +11 -2
  153. package/src/commands/compact.js +106 -23
  154. package/src/commands/loop.js +28 -10
  155. package/src/commands/routine.js +1 -1
  156. package/src/commands/scheduler-daemon.js +359 -2
  157. package/src/commands/session-observability.js +305 -0
  158. package/src/commands/session.js +38 -0
  159. package/src/data/changelog.json +14 -1
  160. package/src/gateways/ws/ws-agent-handler.js +439 -5
  161. package/src/harness/jsonl-session-store.js +463 -125
  162. package/src/harness/prompt-compressor.js +86 -13
  163. package/src/harness/provider-backed-compaction.js +100 -27
  164. package/src/lib/advisor-runtime.js +3 -1
  165. package/src/lib/agent-schedule-store.js +414 -4
  166. package/src/lib/agent-team/team-adjudication.js +40 -1
  167. package/src/lib/automation-engine.js +494 -0
  168. package/src/lib/background-agent-supervisor.js +793 -215
  169. package/src/lib/background-command-argv.js +24 -0
  170. package/src/lib/background-interaction-journal.js +361 -52
  171. package/src/lib/background-interaction-resolver.js +32 -0
  172. package/src/lib/background-launch-profile.js +2 -0
  173. package/src/lib/causal-observability.js +2661 -0
  174. package/src/lib/chat-session-admission.js +76 -0
  175. package/src/lib/cost-budget.js +5 -7
  176. package/src/lib/cowork/ab-comparator-cli.js +11 -0
  177. package/src/lib/cowork/debate-review-cli.js +12 -0
  178. package/src/lib/cowork-adapter.js +159 -38
  179. package/src/lib/cowork-cron.js +357 -1
  180. package/src/lib/cowork-task-runner.js +112 -17
  181. package/src/lib/delivery-coordinator.js +142 -0
  182. package/src/lib/direct-model-usage.js +121 -0
  183. package/src/lib/file-lines.js +183 -47
  184. package/src/lib/llm-pricing.js +12 -17
  185. package/src/lib/loop.js +26 -2
  186. package/src/lib/routine-store.js +380 -21
  187. package/src/lib/runtime-usage-ledger.js +182 -0
  188. package/src/lib/scheduler-kernel/agenda-adapter.js +308 -3
  189. package/src/lib/scheduler-kernel/automation-adapter.js +410 -8
  190. package/src/lib/scheduler-kernel/automation-event-adapter.js +36 -0
  191. package/src/lib/scheduler-kernel/cowork-cron-adapter.js +285 -3
  192. package/src/lib/scheduler-kernel/loop-adapter.js +541 -6
  193. package/src/lib/scheduler-kernel/migration-admin.js +346 -0
  194. package/src/lib/scheduler-kernel/migration-rollback-admin.js +932 -0
  195. package/src/lib/scheduler-kernel/routine-adapter.js +394 -20
  196. package/src/lib/scheduler-kernel/runtime.js +63 -1
  197. package/src/lib/scheduler-kernel/source-locator-path.js +142 -0
  198. package/src/lib/scheduler-kernel/store.js +2586 -85
  199. package/src/lib/session-host-lease.js +171 -2
  200. package/src/lib/session-host-snapshot.js +14 -3
  201. package/src/lib/session-persistence-failure.js +1 -0
  202. package/src/lib/session-tail.js +179 -34
  203. package/src/lib/session-transcript-structure.js +96 -0
  204. package/src/lib/sub-agent-context.js +328 -22
  205. package/src/lib/ws-agent-handler.js +4 -1
  206. package/src/repl/agent-repl.js +732 -91
  207. package/src/repl/chat-repl.js +5 -1
  208. package/src/runtime/agent-core.js +1272 -207
  209. package/src/runtime/fallback-model.js +5 -0
  210. package/src/runtime/headless-runner.js +324 -82
  211. package/src/runtime/headless-stream.js +232 -26
  212. package/src/runtime/policies/agent-policy.js +4 -0
  213. package/src/workers/background-agent-worker.js +403 -96
  214. package/src/assets/web-panel/assets/Projects-Dd-xuPIc.js +0 -1
  215. package/src/assets/web-panel/assets/SpeechSettings-C7tT9iad.js +0 -1
  216. package/src/assets/web-panel/assets/devWarning-Jzu62CLC.js +0 -1
  217. package/src/assets/web-panel/assets/index-Zb2MeDSy.js +0 -1
  218. package/src/assets/web-panel/assets/index-fikqml4k.js +0 -1
@@ -1,4 +1,4 @@
1
- import { createHash } from "node:crypto";
1
+ import { createHash, randomUUID } from "node:crypto";
2
2
  import { nextCronTime } from "../agent-schedule-store.js";
3
3
  import {
4
4
  automationExecutionAuthorityDigest,
@@ -11,10 +11,19 @@ import {
11
11
  EXECUTION_STATUS,
12
12
  FLOW_STATUS,
13
13
  TRIGGER_TYPE,
14
+ automationEffectiveSchedulerFlow,
15
+ automationMigrationSourceDigest,
16
+ automationMigrationSourceSnapshot,
14
17
  executeFlow,
18
+ adjudicateAutomationExecution,
15
19
  getExecution,
16
20
  getFlow,
21
+ getAutomationSchedulerMigration,
17
22
  listFlows,
23
+ listAutomationSchedulerFlows,
24
+ prepareAutomationSchedulerMigration,
25
+ restoreAutomationSchedulerMigration,
26
+ retireAutomationSchedulerMigration,
18
27
  } from "../automation-engine.js";
19
28
  import {
20
29
  SchedulerKernelError,
@@ -24,15 +33,43 @@ import {
24
33
  normalizeJson,
25
34
  } from "./contract.js";
26
35
  import { SchedulerRuntime } from "./runtime.js";
36
+ import {
37
+ schedulerJobDefinitionDigest,
38
+ schedulerMigrationSourceDigest,
39
+ } from "./store.js";
27
40
  import {
28
41
  bindSchedulerAuthorityPolicy,
29
42
  createSchedulerAuthorityResolver,
30
43
  } from "./authority-resolver.js";
44
+ import { canonicalSchedulerSourcePath } from "./source-locator-path.js";
31
45
 
32
46
  export const AUTOMATION_SCHEDULER_KIND = "automation";
33
47
  export const AUTOMATION_SCHEDULER_CAPABILITY = "automation.execute";
34
48
  export const AUTOMATION_SCHEDULER_CHANNEL = "scheduled";
35
49
  export const AUTOMATION_SCHEDULER_MAX_CATCHUP_STEPS = 527_040;
50
+ const AUTOMATION_MEMORY_DATABASE_IDENTITIES = new WeakMap();
51
+
52
+ export function automationDatabaseIdentity(db, pathOptions = undefined) {
53
+ if (typeof db?.databasePath === "string" && db.databasePath.length > 0) {
54
+ return canonicalSchedulerSourcePath(db.databasePath, pathOptions);
55
+ }
56
+ const main = db
57
+ .prepare("PRAGMA database_list")
58
+ .all()
59
+ .find((entry) => entry.name === "main");
60
+ const file = typeof main?.file === "string" ? main.file : "";
61
+ if (!file) {
62
+ // In-memory stores exist only for one process and are never safe to reopen
63
+ // from an operator command. Keep their scope isolated to this handle.
64
+ let identity = AUTOMATION_MEMORY_DATABASE_IDENTITIES.get(db);
65
+ if (!identity) {
66
+ identity = `memory:${randomUUID()}`;
67
+ AUTOMATION_MEMORY_DATABASE_IDENTITIES.set(db, identity);
68
+ }
69
+ return identity;
70
+ }
71
+ return canonicalSchedulerSourcePath(file, pathOptions);
72
+ }
36
73
 
37
74
  function automationError(
38
75
  code,
@@ -231,6 +268,311 @@ export function syncAutomationSchedulerJob(
231
268
  }
232
269
  }
233
270
 
271
+ export function migrateAutomationFlow({
272
+ db,
273
+ schedulerStore,
274
+ flow,
275
+ executionAuthority,
276
+ }) {
277
+ if (db?.__isSqlJsCompat === true) {
278
+ throw automationError(
279
+ "AUTOMATION_SCHEDULER_MIGRATION_DURABILITY_UNAVAILABLE",
280
+ "Automation scheduler migration requires native SQLite durability",
281
+ );
282
+ }
283
+ const effective = automationEffectiveSchedulerFlow(db, flow);
284
+ const snapshot = automationFlowSnapshot(effective);
285
+ const database = automationDatabaseIdentity(db);
286
+ const sourceScope = { store: "automation-engine", database };
287
+ const sourceLocator = {
288
+ schemaVersion: 1,
289
+ type: "automation-database",
290
+ database,
291
+ };
292
+ const desired = buildAutomationSchedulerJob(effective, executionAuthority);
293
+ desired.authority = bindSchedulerAuthorityPolicy(
294
+ schedulerStore,
295
+ desired.authority,
296
+ );
297
+ const sourceSnapshot = automationMigrationSourceSnapshot(effective);
298
+ const sourceDigest = automationMigrationSourceDigest(effective);
299
+ const targetJobDigest = schedulerJobDefinitionDigest(desired);
300
+ const marker = getAutomationSchedulerMigration(db, snapshot.id);
301
+ let prepared;
302
+ if (marker) {
303
+ if (
304
+ marker.schemaVersion !== 1 ||
305
+ !["prepared", "retired"].includes(marker.state) ||
306
+ marker.sourceDigest !== sourceDigest ||
307
+ marker.targetJobId !== desired.id ||
308
+ (marker.state === "prepared" && marker.retirementToken !== null)
309
+ ) {
310
+ throw automationError(
311
+ "AUTOMATION_SCHEDULER_MIGRATION_CONFLICT",
312
+ `Automation migration marker is invalid: ${snapshot.id}`,
313
+ );
314
+ }
315
+ prepared = schedulerStore.getDomainMigration(marker.migrationId);
316
+ if (
317
+ prepared.entries.length !== 1 ||
318
+ prepared.entries[0].domain !== "automation" ||
319
+ prepared.entries[0].sourceId !== snapshot.id ||
320
+ prepared.entries[0].sourceDigest !==
321
+ schedulerMigrationSourceDigest(sourceSnapshot) ||
322
+ prepared.entries[0].targetJobId !== desired.id ||
323
+ prepared.entries[0].targetJobDigest !== targetJobDigest ||
324
+ (marker.state === "retired" &&
325
+ prepared.entries[0].retirementToken !== marker.retirementToken)
326
+ ) {
327
+ throw automationError(
328
+ "AUTOMATION_SCHEDULER_MIGRATION_CONFLICT",
329
+ `Automation migration marker does not match its journal: ${snapshot.id}`,
330
+ );
331
+ }
332
+ schedulerStore.bindDomainMigrationSourceLocator({
333
+ migrationId: prepared.id,
334
+ entryId: prepared.entries[0].entryId,
335
+ sourceLocator,
336
+ expectedSourceDigest: prepared.entries[0].sourceDigest,
337
+ expectedTargetJobId: desired.id,
338
+ });
339
+ prepared = schedulerStore.getDomainMigration(prepared.id);
340
+ } else {
341
+ const unboundLegacy = schedulerStore.getActiveDomainMigrationBySource({
342
+ domain: "automation",
343
+ sourceScope: { store: "automation-engine", database: "current" },
344
+ sourceId: snapshot.id,
345
+ });
346
+ if (unboundLegacy) {
347
+ throw automationError(
348
+ "AUTOMATION_SCHEDULER_MIGRATION_SOURCE_UNBOUND",
349
+ `Legacy Automation migration has no source marker and cannot be bound safely: ${snapshot.id}`,
350
+ );
351
+ }
352
+ prepared = schedulerStore.prepareDomainMigration({
353
+ entries: [
354
+ {
355
+ domain: "automation",
356
+ sourceId: snapshot.id,
357
+ sourceScope,
358
+ sourceLocator,
359
+ source: sourceSnapshot,
360
+ targetJob: desired,
361
+ rollbackStrategy: "disable",
362
+ },
363
+ ],
364
+ });
365
+ }
366
+ if (
367
+ prepared.entries.length !== 1 ||
368
+ prepared.entries[0].domain !== "automation"
369
+ ) {
370
+ throw automationError(
371
+ "AUTOMATION_SCHEDULER_MIGRATION_DOMAIN_MISMATCH",
372
+ "Automation flow belongs to an invalid mixed-domain migration",
373
+ );
374
+ }
375
+ if (
376
+ prepared.entries[0].sourceDigest !==
377
+ schedulerMigrationSourceDigest(sourceSnapshot) ||
378
+ prepared.entries[0].targetJobId !== desired.id ||
379
+ prepared.entries[0].targetJobDigest !== targetJobDigest
380
+ ) {
381
+ throw automationError(
382
+ "AUTOMATION_SCHEDULER_MIGRATION_SOURCE_CHANGED",
383
+ `Automation flow changed after migration started: ${snapshot.id}`,
384
+ );
385
+ }
386
+ let migration = prepared;
387
+ if (["rolling_back", "rolled_back"].includes(migration.state)) {
388
+ throw automationError(
389
+ "AUTOMATION_SCHEDULER_MIGRATION_STATE_CONFLICT",
390
+ `Automation migration cannot resume from state ${migration.state}`,
391
+ );
392
+ }
393
+ if (migration.state === "retired") {
394
+ retireAutomationSchedulerMigration(db, snapshot.id, {
395
+ migrationId: migration.id,
396
+ sourceDigest,
397
+ targetJobId: desired.id,
398
+ retirementToken: migration.entries[0].retirementToken,
399
+ });
400
+ return migration;
401
+ }
402
+ if (migration.state === "prepared") {
403
+ prepareAutomationSchedulerMigration(db, snapshot.id, {
404
+ migrationId: migration.id,
405
+ sourceDigest,
406
+ targetJobId: desired.id,
407
+ });
408
+ migration = schedulerStore.applyDomainMigration(migration.id);
409
+ }
410
+ if (migration.state === "applied") {
411
+ migration = schedulerStore.verifyDomainMigration(migration.id, {
412
+ sources: [
413
+ { entryId: migration.entries[0].entryId, source: sourceSnapshot },
414
+ ],
415
+ });
416
+ }
417
+ const retiring =
418
+ migration.state === "retiring"
419
+ ? migration
420
+ : schedulerStore.beginDomainMigrationRetirement(migration.id);
421
+ const entry = retiring.entries[0];
422
+ const retired = retireAutomationSchedulerMigration(db, snapshot.id, {
423
+ migrationId: migration.id,
424
+ sourceDigest,
425
+ targetJobId: desired.id,
426
+ retirementToken: entry.retirementToken,
427
+ });
428
+ schedulerStore.confirmDomainMigrationEntryRetired({
429
+ migrationId: migration.id,
430
+ entryId: entry.entryId,
431
+ retirementToken: entry.retirementToken,
432
+ source: retired,
433
+ });
434
+ return schedulerStore.getDomainMigration(migration.id);
435
+ }
436
+
437
+ function assertAutomationRollbackBinding({
438
+ db,
439
+ migration,
440
+ migrationId,
441
+ database,
442
+ }) {
443
+ if (
444
+ migration?.id !== migrationId ||
445
+ !Array.isArray(migration.entries) ||
446
+ migration.entries.length === 0 ||
447
+ migration.entries.some((entry) => entry.domain !== "automation")
448
+ ) {
449
+ throw automationError(
450
+ "AUTOMATION_SCHEDULER_MIGRATION_DOMAIN_MISMATCH",
451
+ "Automation rollback cannot operate on a mixed-domain migration",
452
+ );
453
+ }
454
+ for (const entry of migration.entries) {
455
+ const locator = entry.sourceLocator;
456
+ if (
457
+ locator?.schemaVersion !== 1 ||
458
+ locator.type !== "automation-database" ||
459
+ locator.database !== database
460
+ ) {
461
+ throw automationError(
462
+ "AUTOMATION_SCHEDULER_MIGRATION_SOURCE_UNBOUND",
463
+ `Automation rollback source locator does not match its database: ${entry.sourceId}`,
464
+ );
465
+ }
466
+ const current = getFlow(db, entry.sourceId);
467
+ if (!current) {
468
+ throw automationError(
469
+ "AUTOMATION_SCHEDULER_MIGRATION_SOURCE_CHANGED",
470
+ `Automation rollback source does not exist: ${entry.sourceId}`,
471
+ );
472
+ }
473
+ const marker = getAutomationSchedulerMigration(db, entry.sourceId);
474
+ const effective = automationEffectiveSchedulerFlow(db, current);
475
+ if (
476
+ schedulerMigrationSourceDigest(
477
+ automationMigrationSourceSnapshot(effective),
478
+ ) !== entry.sourceDigest
479
+ ) {
480
+ throw automationError(
481
+ "AUTOMATION_SCHEDULER_MIGRATION_SOURCE_CHANGED",
482
+ `Automation rollback source changed: ${entry.sourceId}`,
483
+ );
484
+ }
485
+ if (!marker) {
486
+ if (
487
+ !["prepared", "rolling_back", "rolled_back"].includes(migration.state)
488
+ ) {
489
+ throw automationError(
490
+ "AUTOMATION_SCHEDULER_MIGRATION_CONFLICT",
491
+ `Automation rollback source marker is missing: ${entry.sourceId}`,
492
+ );
493
+ }
494
+ continue;
495
+ }
496
+ if (
497
+ marker.schemaVersion !== 1 ||
498
+ !["prepared", "retired"].includes(marker.state) ||
499
+ marker.migrationId !== migrationId ||
500
+ marker.targetJobId !== entry.targetJobId ||
501
+ marker.sourceDigest !== automationMigrationSourceDigest(effective) ||
502
+ (marker.state === "prepared" && marker.retirementToken !== null) ||
503
+ (marker.state === "retired" &&
504
+ marker.retirementToken !== entry.retirementToken)
505
+ ) {
506
+ throw automationError(
507
+ "AUTOMATION_SCHEDULER_MIGRATION_CONFLICT",
508
+ `Automation rollback source marker does not match its journal: ${entry.sourceId}`,
509
+ );
510
+ }
511
+ }
512
+ return migration;
513
+ }
514
+
515
+ export function rollbackAutomationMigration({
516
+ db,
517
+ schedulerStore,
518
+ migrationId,
519
+ }) {
520
+ const database = automationDatabaseIdentity(db);
521
+ assertAutomationRollbackBinding({
522
+ db,
523
+ migration: schedulerStore.getDomainMigration(migrationId),
524
+ migrationId,
525
+ database,
526
+ });
527
+ const migration = assertAutomationRollbackBinding({
528
+ db,
529
+ migration: schedulerStore.beginDomainMigrationRollback(migrationId),
530
+ migrationId,
531
+ database,
532
+ });
533
+ if (migration.state === "rolled_back") return migration;
534
+ for (const entry of migration.entries) {
535
+ if (entry.state === "rolled_back") continue;
536
+ schedulerStore.restoreDomainMigrationEntrySource({
537
+ migrationId,
538
+ entryId: entry.entryId,
539
+ retirementToken: entry.retirementToken,
540
+ restoreSource: () => {
541
+ const current = getFlow(db, entry.sourceId);
542
+ const marker = getAutomationSchedulerMigration(db, entry.sourceId);
543
+ let restored;
544
+ if (!marker) {
545
+ const source = automationMigrationSourceSnapshot(current);
546
+ if (schedulerMigrationSourceDigest(source) !== entry.sourceDigest) {
547
+ throw automationError(
548
+ "AUTOMATION_SCHEDULER_MIGRATION_SOURCE_CHANGED",
549
+ `Automation flow changed after rollback source restoration: ${entry.sourceId}`,
550
+ );
551
+ }
552
+ restored = current;
553
+ } else {
554
+ const effective = automationEffectiveSchedulerFlow(db, current);
555
+ restored = restoreAutomationSchedulerMigration(db, entry.sourceId, {
556
+ migrationId,
557
+ sourceDigest: automationMigrationSourceDigest(effective),
558
+ targetJobId: entry.targetJobId,
559
+ // The scheduler journal allocates its retirement token before the
560
+ // Automation source transaction advances its marker from prepared
561
+ // to retired. A crash in that window therefore has a journal token
562
+ // but an intentionally null source-marker token. Keep the source
563
+ // marker authoritative for this phase; the restore primitive still
564
+ // verifies migration/source/target identity before deleting it.
565
+ retirementToken:
566
+ marker.state === "prepared" ? null : entry.retirementToken,
567
+ });
568
+ }
569
+ return automationMigrationSourceSnapshot(restored);
570
+ },
571
+ });
572
+ }
573
+ return schedulerStore.getDomainMigration(migrationId);
574
+ }
575
+
234
576
  function latestEnqueuedScheduledFor(schedulerStore, jobId) {
235
577
  const event = schedulerStore
236
578
  .history({ jobId, limit: 100 })
@@ -399,6 +741,37 @@ export function createAutomationSchedulerAdapter({ db, now = Date.now } = {}) {
399
741
  }
400
742
  return {
401
743
  kind: AUTOMATION_SCHEDULER_KIND,
744
+ async adjudicate({ occurrence, adjudication }) {
745
+ const payload = occurrence?.payload;
746
+ const expected = automationFlowSnapshot(payload?.flow);
747
+ if (payload?.snapshotDigest !== automationFlowSnapshotDigest(expected)) {
748
+ throw automationError(
749
+ "AUTOMATION_SCHEDULER_ADJUDICATION_SNAPSHOT_INVALID",
750
+ `Automation adjudication snapshot is invalid: ${occurrence.id}`,
751
+ );
752
+ }
753
+ adjudicateAutomationExecution(
754
+ db,
755
+ automationSchedulerExecutionId(occurrence.id),
756
+ {
757
+ flowId: expected.id,
758
+ triggerType: TRIGGER_TYPE.SCHEDULE,
759
+ decision: adjudication.decision,
760
+ requestId: adjudication.requestId,
761
+ },
762
+ );
763
+ if (adjudication.decision === "confirmed_applied") {
764
+ return {
765
+ settled: true,
766
+ result: {
767
+ executionId: automationSchedulerExecutionId(occurrence.id),
768
+ status: "adjudicated-applied",
769
+ adjudicationRequestId: adjudication.requestId,
770
+ },
771
+ };
772
+ }
773
+ return { continue: true };
774
+ },
402
775
  async execute({ occurrence }) {
403
776
  const payload = occurrence?.payload;
404
777
  const expected = automationFlowSnapshot(payload?.flow);
@@ -426,13 +799,14 @@ export function createAutomationSchedulerAdapter({ db, now = Date.now } = {}) {
426
799
  `Automation flow disappeared before execution: ${expected.id}`,
427
800
  );
428
801
  }
429
- if (current.status !== FLOW_STATUS.ACTIVE) {
802
+ const effectiveCurrent = automationEffectiveSchedulerFlow(db, current);
803
+ if (effectiveCurrent.status !== FLOW_STATUS.ACTIVE) {
430
804
  throw automationError(
431
805
  "AUTOMATION_SCHEDULER_FLOW_NOT_ACTIVE",
432
806
  `Automation flow is not active: ${expected.id}`,
433
807
  );
434
808
  }
435
- if (automationFlowSnapshotDigest(current) !== expectedDigest) {
809
+ if (automationFlowSnapshotDigest(effectiveCurrent) !== expectedDigest) {
436
810
  throw automationError(
437
811
  "AUTOMATION_SCHEDULER_STALE_SNAPSHOT",
438
812
  `Automation flow changed after occurrence enqueue: ${expected.id}`,
@@ -441,7 +815,7 @@ export function createAutomationSchedulerAdapter({ db, now = Date.now } = {}) {
441
815
 
442
816
  reserveAutomationExecutionAuthority(
443
817
  db,
444
- current,
818
+ effectiveCurrent,
445
819
  occurrence.id,
446
820
  payload.executionAuthority,
447
821
  payload.executionAuthorityDigest,
@@ -490,6 +864,7 @@ export class AutomationSchedulerBridge {
490
864
  leaseMs,
491
865
  renewIntervalMs,
492
866
  authorityResolver,
867
+ migrateLegacy = true,
493
868
  } = {}) {
494
869
  if (typeof now !== "function") {
495
870
  throw automationError(
@@ -500,6 +875,7 @@ export class AutomationSchedulerBridge {
500
875
  this.db = db;
501
876
  this.schedulerStore = schedulerStore;
502
877
  this.now = now;
878
+ this.migrateLegacy = migrateLegacy !== false;
503
879
  this.runtime = new SchedulerRuntime({
504
880
  store: schedulerStore,
505
881
  adapters: [createAutomationSchedulerAdapter({ db, now })],
@@ -545,10 +921,36 @@ export class AutomationSchedulerBridge {
545
921
  if (signal?.aborted) return results;
546
922
 
547
923
  const now = normalizeEpochMs(Number(this.now()), "now");
548
- const flows = listFlows(this.db, {
549
- status: FLOW_STATUS.ACTIVE,
550
- limit: 10_000,
551
- }).filter((flow) => typeof flow.schedule === "string" && flow.schedule);
924
+ if (this.migrateLegacy) {
925
+ const candidates = listFlows(this.db, {
926
+ status: FLOW_STATUS.ACTIVE,
927
+ limit: 10_000,
928
+ }).filter((flow) => typeof flow.schedule === "string" && flow.schedule);
929
+ for (const flow of candidates) {
930
+ try {
931
+ migrateAutomationFlow({
932
+ db: this.db,
933
+ schedulerStore: this.schedulerStore,
934
+ flow,
935
+ executionAuthority: automationExecutionAuthoritySnapshot(
936
+ this.db,
937
+ flow,
938
+ ),
939
+ });
940
+ } catch (error) {
941
+ if (!String(error?.code || "").startsWith("AUTOMATION_EXECUTION_")) {
942
+ throw error;
943
+ }
944
+ }
945
+ }
946
+ }
947
+ const flows = [
948
+ ...listFlows(this.db, {
949
+ status: FLOW_STATUS.ACTIVE,
950
+ limit: 10_000,
951
+ }),
952
+ ...listAutomationSchedulerFlows(this.db, { limit: 10_000 }),
953
+ ].filter((flow) => typeof flow.schedule === "string" && flow.schedule);
552
954
  for (const flow of flows) {
553
955
  let occurrence;
554
956
  try {
@@ -11,6 +11,7 @@ import {
11
11
  EXECUTION_STATUS,
12
12
  FLOW_STATUS,
13
13
  TRIGGER_TYPE,
14
+ adjudicateAutomationExecution,
14
15
  executeFlow,
15
16
  getExecution,
16
17
  getFlow,
@@ -552,6 +553,41 @@ export function createAutomationEventAdapter({ db, now = Date.now } = {}) {
552
553
  }
553
554
  return {
554
555
  kind: AUTOMATION_EVENT_KIND,
556
+ async adjudicate({ occurrence, adjudication }) {
557
+ const payload = occurrence?.payload;
558
+ const expectedFlow = automationEventFlowSnapshot(payload?.flow);
559
+ const expectedTrigger = automationEventTriggerSnapshot(payload?.trigger);
560
+ if (
561
+ payload?.definitionDigest !==
562
+ automationEventDefinitionDigest(expectedFlow, expectedTrigger)
563
+ ) {
564
+ throw eventError(
565
+ "AUTOMATION_EVENT_ADJUDICATION_SNAPSHOT_INVALID",
566
+ `automation event adjudication snapshot is invalid: ${occurrence.id}`,
567
+ );
568
+ }
569
+ adjudicateAutomationExecution(
570
+ db,
571
+ automationEventExecutionId(occurrence.id),
572
+ {
573
+ flowId: expectedFlow.id,
574
+ triggerType: TRIGGER_TYPE.EVENT,
575
+ decision: adjudication.decision,
576
+ requestId: adjudication.requestId,
577
+ },
578
+ );
579
+ if (adjudication.decision === "confirmed_applied") {
580
+ return {
581
+ settled: true,
582
+ result: {
583
+ executionId: automationEventExecutionId(occurrence.id),
584
+ status: "adjudicated-applied",
585
+ adjudicationRequestId: adjudication.requestId,
586
+ },
587
+ };
588
+ }
589
+ return { continue: true };
590
+ },
555
591
  async execute({ occurrence }) {
556
592
  const payload = occurrence?.payload;
557
593
  const expectedFlow = automationEventFlowSnapshot(payload?.flow);