chainlesschain 0.164.0 → 0.165.2

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 (228) hide show
  1. package/README.md +248 -2
  2. package/package.json +7 -4
  3. package/src/assets/web-panel/.build-hash +1 -1
  4. package/src/assets/web-panel/assets/{AIOps-D2MEn7fI.js → AIOps-lS1R0Cza.js} +1 -1
  5. package/src/assets/web-panel/assets/{ActionButton-lCW_4Gf0.js → ActionButton-BmlgBPsj.js} +1 -1
  6. package/src/assets/web-panel/assets/{Analytics-Bs7i-nsS.js → Analytics-CNKczv1S.js} +3 -3
  7. package/src/assets/web-panel/assets/{AppLayout-CK7B6S_j.js → AppLayout-BuZGJARQ.js} +5 -5
  8. package/src/assets/web-panel/assets/{Artifacts-C8ILjpyo.js → Artifacts-Dm73Sl-O.js} +1 -1
  9. package/src/assets/web-panel/assets/{Audit-Bb9cNaWc.js → Audit-BGMW7A5e.js} +1 -1
  10. package/src/assets/web-panel/assets/{BackgroundAgents-sC9ooXIf.js → BackgroundAgents-BQ6M54JR.js} +1 -1
  11. package/src/assets/web-panel/assets/{Backup-D-DrsplT.js → Backup-DBzGP0bR.js} +1 -1
  12. package/src/assets/web-panel/assets/{BaseInput-uCNZpwSK.js → BaseInput-D1mLCoOV.js} +1 -1
  13. package/src/assets/web-panel/assets/{Chat-CsDK1uE9.js → Chat-BUfcN7p8.js} +6 -6
  14. package/src/assets/web-panel/assets/{ChatBubbleRenderer-OqSDt50w.js → ChatBubbleRenderer-CY5m8ZHg.js} +1 -1
  15. package/src/assets/web-panel/assets/{Checkbox-JhTXM1-K.js → Checkbox-Du0Yg5Pi.js} +1 -1
  16. package/src/assets/web-panel/assets/{Codegen-BbzZLnyD.js → Codegen-B2RXziHW.js} +1 -1
  17. package/src/assets/web-panel/assets/{Col-D4VW4m4j.js → Col-DWhekOrR.js} +1 -1
  18. package/src/assets/web-panel/assets/{Community-BXrYawxV.js → Community-HQhrkon4.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compact-DCihGy1u.js → Compact-izHNb4uz.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compliance-DlyZ-lk8.js → Compliance-BDwLy41-.js} +1 -1
  21. package/src/assets/web-panel/assets/{Cowork-DvGZrhbO.js → Cowork-DFJhLa7K.js} +3 -3
  22. package/src/assets/web-panel/assets/{Cron-DUncZi8h.js → Cron-DYY9RG7-.js} +2 -2
  23. package/src/assets/web-panel/assets/{Crosschain-C_hLuUcm.js → Crosschain-rr7tJTtv.js} +1 -1
  24. package/src/assets/web-panel/assets/{DID-b6YSUqxr.js → DID-D2sfHRLi.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dashboard-uvM15Cfb.js → Dashboard-q_eGdhha.js} +2 -2
  26. package/src/assets/web-panel/assets/{Dropdown-D1-Nd4qY.js → Dropdown-Cufrh2Bz.js} +1 -1
  27. package/src/assets/web-panel/assets/{EmailListRenderer-8ApvL6Zc.js → EmailListRenderer-B-kdv10f.js} +1 -1
  28. package/src/assets/web-panel/assets/{FamilyGuardDashboard-LYJt8811.js → FamilyGuardDashboard-D21XjgfG.js} +1 -1
  29. package/src/assets/web-panel/assets/{Federation-BbI3HGpv.js → Federation-CAwRTLZH.js} +1 -1
  30. package/src/assets/web-panel/assets/{FormItemContext-DSoEKuFu.js → FormItemContext-vx3daNDF.js} +1 -1
  31. package/src/assets/web-panel/assets/{GenericCardRenderer-B0S9OWd5.js → GenericCardRenderer-CRWY2wU4.js} +1 -1
  32. package/src/assets/web-panel/assets/{Git-DIs9Zhf3.js → Git-Q6SwauyD.js} +2 -2
  33. package/src/assets/web-panel/assets/{Governance-jzZXrxcl.js → Governance-BJ1q4IQZ.js} +1 -1
  34. package/src/assets/web-panel/assets/{Inference-JUPjf2ZI.js → Inference-CSWjROgD.js} +1 -1
  35. package/src/assets/web-panel/assets/{KnowledgeGraph-DxnfJvlP.js → KnowledgeGraph-fzuQsWuY.js} +1 -1
  36. package/src/assets/web-panel/assets/{Logs-iXiz8BEE.js → Logs-DVF8Mnns.js} +2 -2
  37. package/src/assets/web-panel/assets/MarkdownRenderer-BLif4QSg.js +1 -0
  38. package/src/assets/web-panel/assets/{Marketplace-Y3Xch312.js → Marketplace-BQP7LOA4.js} +1 -1
  39. package/src/assets/web-panel/assets/{McpTools-D7kGGbO7.js → McpTools-BNlJCmNc.js} +4 -4
  40. package/src/assets/web-panel/assets/{Memory-Do_hVxzh.js → Memory-DLLg5WQ4.js} +2 -2
  41. package/src/assets/web-panel/assets/{MobileBridge-CtrR0Tas.js → MobileBridge-CR2skNAF.js} +1 -1
  42. package/src/assets/web-panel/assets/MobileProjects-BxVavObl.js +1 -0
  43. package/src/assets/web-panel/assets/{Mtc-qo5QCTGd.js → Mtc-B17pgqMI.js} +4 -4
  44. package/src/assets/web-panel/assets/{MtcAudit-cq5mnjYj.js → MtcAudit-4UmV5cIL.js} +2 -2
  45. package/src/assets/web-panel/assets/{Multisig-Bq0MAQHw.js → Multisig-DoMEXEcU.js} +3 -3
  46. package/src/assets/web-panel/assets/{NLProgramming-DdWE6Vi2.js → NLProgramming-h9DMXFX4.js} +1 -1
  47. package/src/assets/web-panel/assets/{Notes-BxMBFcIp.js → Notes-Cihn-xX8.js} +3 -3
  48. package/src/assets/web-panel/assets/{NotificationSettings-RTrAcbUe.js → NotificationSettings-BE6ZGa3R.js} +1 -1
  49. package/src/assets/web-panel/assets/{OrderTableRenderer-DJbpGqzT.js → OrderTableRenderer-CnwojoSI.js} +1 -1
  50. package/src/assets/web-panel/assets/{Organization-SQzIPdqC.js → Organization-B2vpwmjb.js} +4 -4
  51. package/src/assets/web-panel/assets/{Overflow-02yECh22.js → Overflow-C4z28R0-.js} +1 -1
  52. package/src/assets/web-panel/assets/{P2P-BNg4pNCM.js → P2P-BVlFkwhW.js} +2 -2
  53. package/src/assets/web-panel/assets/{PdhVaultBrowser-BxPJZsD3.js → PdhVaultBrowser-BXbEdL5B.js} +3 -3
  54. package/src/assets/web-panel/assets/{Permissions-CLnDnPAz.js → Permissions-C28xs4lp.js} +4 -4
  55. package/src/assets/web-panel/assets/{PersonalDataHub-C5m0AjGf.js → PersonalDataHub-Dgl_rBjM.js} +4 -4
  56. package/src/assets/web-panel/assets/{Pipeline-VwOf5Dhv.js → Pipeline-3QUIhrKI.js} +1 -1
  57. package/src/assets/web-panel/assets/{Privacy-CC0W2hZd.js → Privacy-8Gh33OZ5.js} +1 -1
  58. package/src/assets/web-panel/assets/{ProjectInit-Dz893Bob.js → ProjectInit-BNmg4tZi.js} +2 -2
  59. package/src/assets/web-panel/assets/{ProjectSettings-CxQkvl0k.js → ProjectSettings-vgMfeCf9.js} +2 -2
  60. package/src/assets/web-panel/assets/Projects-BhtAVilc.js +1 -0
  61. package/src/assets/web-panel/assets/{Providers-DeB9IkxK.js → Providers-CXoOa8eX.js} +1 -1
  62. package/src/assets/web-panel/assets/{QrScannerModal-OCeoaswn.js → QrScannerModal-BhfTF0oS.js} +1 -1
  63. package/src/assets/web-panel/assets/{QuickAsk-DenotaAj.js → QuickAsk-C746HEAj.js} +1 -1
  64. package/src/assets/web-panel/assets/{Recommend-Cies_jjI.js → Recommend-BSej8Eo0.js} +1 -1
  65. package/src/assets/web-panel/assets/RemoteSession-f3gmnlG3.js +5 -0
  66. package/src/assets/web-panel/assets/{Reputation-CW0mvxgZ.js → Reputation-CyvybpkN.js} +1 -1
  67. package/src/assets/web-panel/assets/{Row-SEd32qZU.js → Row-DwV2PeYn.js} +1 -1
  68. package/src/assets/web-panel/assets/{RssFeed-BSwnJ3Lm.js → RssFeed-11GrzjZy.js} +3 -3
  69. package/src/assets/web-panel/assets/{Search-xe2m8bkC.js → Search-BjKXkrAY.js} +1 -1
  70. package/src/assets/web-panel/assets/{Security-Mq2F9Nro.js → Security-eWiFb9Yk.js} +4 -4
  71. package/src/assets/web-panel/assets/{Services-BKGw2V3P.js → Services-CdCsMAtt.js} +2 -2
  72. package/src/assets/web-panel/assets/{Skeleton-DW95-Rxf.js → Skeleton-4Q2UTKQ5.js} +1 -1
  73. package/src/assets/web-panel/assets/{Skills-CHgChCv_.js → Skills-v4rtYrRj.js} +1 -1
  74. package/src/assets/web-panel/assets/{Sla-tKh6k3R7.js → Sla-CRhsFvd_.js} +1 -1
  75. package/src/assets/web-panel/assets/SpeechSettings-DLjKsDVu.js +1 -0
  76. package/src/assets/web-panel/assets/{SyncSettings-D0Fw8fVL.js → SyncSettings-D16zonl7.js} +2 -2
  77. package/src/assets/web-panel/assets/{Tasks-20x1GB3D.js → Tasks-Xxozz0i_.js} +1 -1
  78. package/src/assets/web-panel/assets/{Templates-DJ-lts-a.js → Templates-CXJpPtCT.js} +1 -1
  79. package/src/assets/web-panel/assets/{Tenant-BFdGpbs7.js → Tenant-XRV0L1ZF.js} +1 -1
  80. package/src/assets/web-panel/assets/{Terminal-Xpx61vHL.js → Terminal-CYuO1i_w.js} +2 -2
  81. package/src/assets/web-panel/assets/{TimelineRenderer-C6UIvyZQ.js → TimelineRenderer-BXqitWsu.js} +1 -1
  82. package/src/assets/web-panel/assets/{Tokens-Dellq08f.js → Tokens-BvPrDHIy.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trigger-VKw8d0J-.js → Trigger-DhCrSTf5.js} +1 -1
  84. package/src/assets/web-panel/assets/{Trust-DNftdKT5.js → Trust-DmsuZD6K.js} +1 -1
  85. package/src/assets/web-panel/assets/{UkeySign-DX9VAKJI.js → UkeySign-D_yrts5C.js} +1 -1
  86. package/src/assets/web-panel/assets/{VideoEditing-B2h3jO8q.js → VideoEditing-B01ihPrm.js} +1 -1
  87. package/src/assets/web-panel/assets/{Wallet-CjGkof7f.js → Wallet-DpUjKa-N.js} +4 -4
  88. package/src/assets/web-panel/assets/{WebAuthn-2Zfcu55P.js → WebAuthn-CL07yON6.js} +4 -4
  89. package/src/assets/web-panel/assets/{WorkflowEditor-B9eZ8UxZ.js → WorkflowEditor-CLMflnRr.js} +1 -1
  90. package/src/assets/web-panel/assets/{chat-CQNfD-YO.js → chat-DtUqe8h_.js} +1 -1
  91. package/src/assets/web-panel/assets/{colors-D4usyFT2.js → colors-DPKrgVfy.js} +1 -1
  92. package/src/assets/web-panel/assets/{compact-item-s4TpjvjX.js → compact-item-BTt2GtOm.js} +1 -1
  93. package/src/assets/web-panel/assets/{createContext-BRCSvYxj.js → createContext-D_VeUc1J.js} +1 -1
  94. package/src/assets/web-panel/assets/devWarning-Bj5nUW2v.js +1 -0
  95. package/src/assets/web-panel/assets/{hasIn-AdkUbkV-.js → hasIn-1kndiylj.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-BIoG5yYf.js → index-2eyAXE3d.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-nXyk8GZ9.js → index-4bna2_SR.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-B2V-eKfK.js → index-8nz_fmlj.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-D_XBHopw.js → index-B9KvcS7R.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-s_buFMEG.js → index-BAXfRKfG.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-DZT36ZYq.js → index-BHpBMWCh.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-BMcimU-2.js → index-BaZAbw9A.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-DzRjHxEv.js → index-BepLZwgB.js} +1 -1
  104. package/src/assets/web-panel/assets/{index--00U6vXZ.js → index-Bhudc_Ez.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-C7Y8Aluc.js → index-BlDNVgBt.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-BtobShro.js → index-By5n8up9.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-Cvyt-zhm.js → index-CHG-KcS4.js} +1 -1
  108. package/src/assets/web-panel/assets/index-CPcM-eqo.js +1 -0
  109. package/src/assets/web-panel/assets/{index-MMN9V6JF.js → index-CX81qSM4.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-Bad4VNvz.js → index-CauoBQkH.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-CCsM_Ybx.js → index-CcO04eDn.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-DARsAyUp.js → index-CtF7EN49.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-C5KAQFPQ.js → index-CzjkKUmR.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-RfMr79MW.js → index-D95OFht7.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-DdCB70SS.js → index-DFIZ_1Sf.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-CYdoQsa1.js → index-DG2MZQ3f.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-BPhkFZ1I.js → index-DJ8vXGOa.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-_IRVsV9X.js → index-Dbbymxpj.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-DVKfQ0Ux.js → index-DdkplL9R.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-CkwiSLhU.js → index-DfGl8CqG.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-CJVEOa4i.js → index-DfKBRdSS.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-C1mJtE6q.js → index-DsJCDUJG.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-BgiXR_-_.js → index-Dwqmtk65.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-CJCFe2Qf.js → index-DxdTdBix.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-C484EJiS.js → index-FzdwcSy2.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-B4JJCfQ2.js → index-GsoUQ2M7.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-CQhAVU5t.js → index-brCInrzq.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-CKC1t3Ic.js → index-dVc-CXY4.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-BQ3DXBtD.js → index-fk2Rjacw.js} +3 -3
  130. package/src/assets/web-panel/assets/{index-Cduu2Hhr.js → index-l1BETrDb.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-Bw2MEnUk.js → index-m31Ka8hZ.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-D2GjI2oe.js → index-ocf06EVQ.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-CJdQrZth.js → index-sDoMHTNA.js} +1 -1
  134. package/src/assets/web-panel/assets/index-xeSyVoRe.js +1 -0
  135. package/src/assets/web-panel/assets/{initDefaultProps-Blmpk7HL.js → initDefaultProps-CvyYJd7z.js} +1 -1
  136. package/src/assets/web-panel/assets/{motion-DPBJMv1n.js → motion-DYZkhUdz.js} +1 -1
  137. package/src/assets/web-panel/assets/{move-ButdzCM7.js → move-slnJRVT1.js} +1 -1
  138. package/src/assets/web-panel/assets/{mtc-parser-cyRC_QCe.js → mtc-parser-DVc0CKmy.js} +1 -1
  139. package/src/assets/web-panel/assets/{omit-1epSV7hz.js → omit-BCXAtHCq.js} +1 -1
  140. package/src/assets/web-panel/assets/{pickAttrs-DuPY8xJs.js → pickAttrs-DBsemz_K.js} +1 -1
  141. package/src/assets/web-panel/assets/{placementArrow-6XZqarhe.js → placementArrow-BRtkJ-nv.js} +1 -1
  142. package/src/assets/web-panel/assets/{responsiveObserve-B40pXBWM.js → responsiveObserve-Cebq7EZn.js} +1 -1
  143. package/src/assets/web-panel/assets/{slide-jbZ9Wu4n.js → slide-DT7qvId2.js} +1 -1
  144. package/src/assets/web-panel/assets/{statusUtils-BKQQcVy4.js → statusUtils-pQiITLkG.js} +1 -1
  145. package/src/assets/web-panel/assets/{styleChecker-NiKfWjUT.js → styleChecker-c-19BVKQ.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFlexGapSupport-bQUCvPeb.js → useFlexGapSupport-DsS5-0bE.js} +1 -1
  147. package/src/assets/web-panel/assets/{useFs-CUGji7ph.js → useFs-CxGiMe5n.js} +1 -1
  148. package/src/assets/web-panel/assets/{usePersonalDataHub-4veyN2N2.js → usePersonalDataHub-D9btVID5.js} +1 -1
  149. package/src/assets/web-panel/assets/{vnode-1-nLug-Z.js → vnode-CUYFsFEN.js} +1 -1
  150. package/src/assets/web-panel/assets/{zoom-dhCeRDMo.js → zoom-CXmn_35j.js} +1 -1
  151. package/src/assets/web-panel/index.html +1 -1
  152. package/src/command-help-index.json +1 -1
  153. package/src/commands/cowork.js +559 -62
  154. package/src/commands/plugin.js +819 -64
  155. package/src/commands/session-location.js +318 -7
  156. package/src/constants.js +2 -2
  157. package/src/data/changelog.json +28 -2
  158. package/src/gateways/ws/action-protocol.js +293 -19
  159. package/src/gateways/ws/message-dispatcher.js +30 -0
  160. package/src/gateways/ws/remote-session-protocol.js +542 -35
  161. package/src/gateways/ws/ws-approval-gate.js +5 -0
  162. package/src/gateways/ws/ws-server.js +462 -38
  163. package/src/harness/jsonl-session-store.js +638 -2
  164. package/src/harness/prompt-compressor.js +4 -0
  165. package/src/harness/remote-session-audit.js +1 -0
  166. package/src/harness/remote-session-crypto.js +750 -50
  167. package/src/harness/remote-session-registry.js +795 -27
  168. package/src/lib/auto-mode-config.js +98 -3
  169. package/src/lib/background-agent-keeper-client.js +29 -0
  170. package/src/lib/background-agent-keeper-protocol.js +158 -10
  171. package/src/lib/background-agent-supervisor.js +870 -48
  172. package/src/lib/background-session-transport.js +23 -6
  173. package/src/lib/background-turn-bootstrap-protocol.js +64 -0
  174. package/src/lib/cowork-task-runner.js +70 -0
  175. package/src/lib/cowork-workflow.js +887 -62
  176. package/src/lib/delivery-production-adapter.js +38 -2
  177. package/src/lib/doctor-checkup.js +34 -10
  178. package/src/lib/dynamic-workflow-draft.js +535 -0
  179. package/src/lib/dynamic-workflow-facade.js +1105 -17
  180. package/src/lib/dynamic-workflow-runtime.js +2974 -0
  181. package/src/lib/execution-location-contract.js +111 -7
  182. package/src/lib/execution-location-runtime.js +3 -1
  183. package/src/lib/execution-location-target.js +910 -0
  184. package/src/lib/llm-providers.js +1 -0
  185. package/src/lib/mcp-call-ledger-store.js +35 -0
  186. package/src/lib/mcp-call-ledger.js +30 -0
  187. package/src/lib/mcp-stdio-package-materialization.js +1 -1
  188. package/src/lib/plugin-runtime/__tests__/remote-source.test.js +34 -16
  189. package/src/lib/plugin-runtime/install.js +4956 -657
  190. package/src/lib/plugin-runtime/manifest.js +3 -1
  191. package/src/lib/plugin-runtime/marketplace-artifact-readback.js +671 -31
  192. package/src/lib/plugin-runtime/marketplace-catalog.js +68 -2
  193. package/src/lib/plugin-runtime/marketplace-impact.js +208 -15
  194. package/src/lib/plugin-runtime/marketplace-network.js +317 -0
  195. package/src/lib/plugin-runtime/marketplace-pac-worker.js +15 -0
  196. package/src/lib/plugin-runtime/marketplace-remote-artifacts.js +25 -2
  197. package/src/lib/plugin-runtime/marketplace-source-cache.js +359 -0
  198. package/src/lib/plugin-runtime/policy.js +21 -6
  199. package/src/lib/plugin-runtime/publisher-trust.js +332 -0
  200. package/src/lib/plugin-runtime/remote-source.js +323 -27
  201. package/src/lib/plugin-runtime/scopes.js +317 -41
  202. package/src/lib/plugin-runtime/transaction-journal.js +806 -0
  203. package/src/lib/public-ide-capability-manifest.js +1 -1
  204. package/src/lib/remote-approval-bridge.js +745 -108
  205. package/src/lib/remote-control.js +2 -0
  206. package/src/lib/remote-membership-coordinator.js +612 -46
  207. package/src/lib/remote-membership-host-store.js +59 -10
  208. package/src/lib/runtime-provenance-ledger.js +171 -46
  209. package/src/lib/shell-approval.js +169 -6
  210. package/src/lib/sub-agent-context.js +268 -2
  211. package/src/lib/task-model-selector.js +1 -1
  212. package/src/lib/with-file-lock.js +167 -42
  213. package/src/repl/agent-repl.js +70 -29
  214. package/src/repl/remote-approval.js +29 -7
  215. package/src/runtime/agent-core.js +1695 -194
  216. package/src/runtime/headless-runner.js +22 -5
  217. package/src/runtime/headless-stream.js +19 -3
  218. package/src/workers/background-agent-keeper.js +279 -58
  219. package/src/workers/background-agent-worker.js +7 -0
  220. package/src/workers/background-turn-bootstrap.js +29 -2
  221. package/src/assets/web-panel/assets/MarkdownRenderer-GmB6DOr6.js +0 -1
  222. package/src/assets/web-panel/assets/MobileProjects-BL0Czcoj.js +0 -1
  223. package/src/assets/web-panel/assets/Projects-DDAjkUkT.js +0 -1
  224. package/src/assets/web-panel/assets/RemoteSession-Dxzl5n2T.js +0 -5
  225. package/src/assets/web-panel/assets/SpeechSettings-D6UL3dA5.js +0 -1
  226. package/src/assets/web-panel/assets/devWarning-DKJjSWRn.js +0 -1
  227. package/src/assets/web-panel/assets/index-C61cnl3K.js +0 -1
  228. package/src/assets/web-panel/assets/index-D4XFHxBr.js +0 -1
@@ -1,7 +1,14 @@
1
+ import { createHash } from "node:crypto";
2
+ import { posix as posixPath, win32 as win32Path } from "node:path";
3
+ import { types as utilTypes } from "node:util";
1
4
  import {
5
+ COWORK_WORKFLOW_RUN_RECORD_SCHEMA,
2
6
  MAX_FAN_OUT,
7
+ executeWorkflow as executeCoworkWorkflow,
3
8
  loopIterationCap,
4
9
  planBatches,
10
+ resolveForEachItems,
11
+ shouldRunStep,
5
12
  validateWorkflow,
6
13
  } from "./cowork-workflow.js";
7
14
  import {
@@ -16,10 +23,25 @@ import {
16
23
  createWorkflowDefinitionAuthority,
17
24
  normalizeWorkflowDefinitionDigest,
18
25
  } from "./workflow-definition-contract.js";
26
+ import { canonicalJson } from "./scheduler-kernel/contract.js";
19
27
 
20
28
  export const DYNAMIC_WORKFLOW_DEFINITION_SCHEMA = WORKFLOW_DEFINITION_SCHEMA;
21
29
  export const DYNAMIC_WORKFLOW_PREFLIGHT_SCHEMA =
22
30
  "cc-dynamic-workflow-preflight/v1";
31
+ export const DYNAMIC_WORKFLOW_RUN_ADMISSION_SCHEMA =
32
+ "cc-dynamic-workflow-run-admission/v1";
33
+ export const SESSION_EXECUTION_LOCATION_AUTHORITY_SCHEMA =
34
+ "cc-session-execution-location-authority/v1";
35
+ export const DYNAMIC_WORKFLOW_PREFLIGHT_BLOCKED_CODE =
36
+ "CC_DYNAMIC_WORKFLOW_PREFLIGHT_BLOCKED";
37
+ export const DYNAMIC_WORKFLOW_EXECUTION_AUTHORITY_INVALID_CODE =
38
+ "CC_DYNAMIC_WORKFLOW_EXECUTION_AUTHORITY_INVALID";
39
+ export const DYNAMIC_WORKFLOW_DEFINITION_AUTHORITY_INVALID_CODE =
40
+ "CC_DYNAMIC_WORKFLOW_DEFINITION_AUTHORITY_INVALID";
41
+ export const DYNAMIC_WORKFLOW_EXECUTION_OPTIONS_INVALID_CODE =
42
+ "CC_DYNAMIC_WORKFLOW_EXECUTION_OPTIONS_INVALID";
43
+ export const DYNAMIC_WORKFLOW_EXECUTION_RESULT_INVALID_CODE =
44
+ "CC_DYNAMIC_WORKFLOW_EXECUTION_RESULT_INVALID";
23
45
 
24
46
  export const DYNAMIC_WORKFLOW_ENGINE_CAPABILITIES = Object.freeze([
25
47
  "condition",
@@ -68,19 +90,291 @@ const DATA_BOUNDARY_KINDS = new Set([
68
90
  const SANDBOX_RANK = Object.freeze({ none: 0, partial: 1, strong: 2 });
69
91
  const DEFAULT_SOFT_TASK_GUIDELINE = 16;
70
92
  const DEFAULT_HARD_TASK_LIMIT = 64;
93
+ const MAX_AUTHORITY_SNAPSHOT_NODES = 25_000;
94
+ const MAX_CANONICAL_SNAPSHOT_BYTES = 1024 * 1024;
95
+ const MAX_RUN_RECORD_STEPS = DEFAULT_HARD_TASK_LIMIT;
96
+ const RUN_INPUT_FIELDS = new Set([
97
+ "definitionAuthority",
98
+ "executionAuthoritySessionId",
99
+ "maxParallel",
100
+ "execution",
101
+ "onAdmitted",
102
+ ]);
103
+ const RUN_DEPENDENCY_FIELDS = new Set(["executeWorkflow", "verifyAuthorities"]);
104
+ const VERIFIED_AUTHORITIES_FIELDS = new Set([
105
+ "definitionAuthority",
106
+ "executionLocationAuthority",
107
+ ]);
108
+ const VERIFIED_SESSION_AUTHORITY_FIELDS = new Set([
109
+ "schema",
110
+ "authority",
111
+ "sessionId",
112
+ "headHash",
113
+ "eventCount",
114
+ "binding",
115
+ ]);
116
+ const DEFINITION_AUTHORITY_FIELDS = new Set([
117
+ "status",
118
+ "recordSchema",
119
+ "definitionSchema",
120
+ "definitionDigest",
121
+ "definition",
122
+ ]);
123
+ const EXECUTION_OPTION_FIELDS = new Set([
124
+ "cwd",
125
+ "continueOnError",
126
+ "pipeline",
127
+ "provider",
128
+ "model",
129
+ "llmOptions",
130
+ "onStepStart",
131
+ "onStepComplete",
132
+ ]);
133
+ const RUN_RECORD_FIELDS = new Set([
134
+ "schema",
135
+ "workflowId",
136
+ "workflowName",
137
+ "definitionSchema",
138
+ "definitionDigest",
139
+ "runAdmission",
140
+ "status",
141
+ "steps",
142
+ "startedAt",
143
+ "finishedAt",
144
+ ]);
145
+ const RUN_RECORD_STATUSES = new Set(["completed", "failed", "partial"]);
146
+ const RUN_RECORD_STEP_FIELDS = new Set(["id", "status", "taskId", "result"]);
147
+ const RUN_RECORD_STEP_STATUSES = new Set([
148
+ "completed",
149
+ "failed",
150
+ "partial",
151
+ "skipped",
152
+ ]);
153
+
154
+ export class DynamicWorkflowAdmissionError extends Error {
155
+ constructor(code, message, details = undefined, options = {}) {
156
+ super(message);
157
+ this.name = "DynamicWorkflowAdmissionError";
158
+ this.code = code;
159
+ this.record = null;
160
+ this.executionStarted = options.executionStarted === true;
161
+ if (details !== undefined) this.details = details;
162
+ }
163
+ }
164
+
165
+ function admissionError(code, message, details, options) {
166
+ return new DynamicWorkflowAdmissionError(code, message, details, options);
167
+ }
168
+
169
+ function snapshotObjectFields(
170
+ value,
171
+ fields,
172
+ code,
173
+ field,
174
+ { exact = true } = {},
175
+ ) {
176
+ if (
177
+ !value ||
178
+ typeof value !== "object" ||
179
+ Array.isArray(value) ||
180
+ utilTypes.isProxy(value)
181
+ ) {
182
+ throw admissionError(code, `${field} must be a non-proxy plain object`);
183
+ }
184
+ const prototype = Object.getPrototypeOf(value);
185
+ if (prototype !== Object.prototype && prototype !== null) {
186
+ throw admissionError(code, `${field} must be a plain object`);
187
+ }
188
+
189
+ const keys = Reflect.ownKeys(value);
190
+ if (
191
+ (exact && keys.length !== fields.size) ||
192
+ keys.some((key) => typeof key !== "string" || !fields.has(key))
193
+ ) {
194
+ throw admissionError(code, `${field} contains missing or unknown fields`);
195
+ }
196
+
197
+ const snapshot = {};
198
+ for (const key of keys) {
199
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
200
+ if (
201
+ !descriptor ||
202
+ descriptor.enumerable !== true ||
203
+ !Object.hasOwn(descriptor, "value")
204
+ ) {
205
+ throw admissionError(
206
+ code,
207
+ `${field}.${key} must be an enumerable data property`,
208
+ );
209
+ }
210
+ Object.defineProperty(snapshot, key, {
211
+ configurable: true,
212
+ enumerable: true,
213
+ writable: true,
214
+ value: descriptor.value,
215
+ });
216
+ }
217
+ return Object.freeze(snapshot);
218
+ }
219
+
220
+ function snapshotCanonicalValue(
221
+ value,
222
+ code,
223
+ field,
224
+ {
225
+ maxBytes = MAX_CANONICAL_SNAPSHOT_BYTES,
226
+ maxNodes = MAX_AUTHORITY_SNAPSHOT_NODES,
227
+ } = {},
228
+ ) {
229
+ const seen = new WeakSet();
230
+ let nodes = 0;
231
+ let roughCharacters = 0;
232
+
233
+ const invalid = (reason) => {
234
+ throw admissionError(code, `${field} ${reason}`);
235
+ };
236
+ const account = (count = 1) => {
237
+ nodes += 1;
238
+ roughCharacters += count;
239
+ if (nodes > maxNodes || roughCharacters > maxBytes) {
240
+ invalid("exceeds snapshot limits");
241
+ }
242
+ };
243
+ const accountCharacters = (count) => {
244
+ roughCharacters += count;
245
+ if (roughCharacters > maxBytes) invalid("exceeds snapshot limits");
246
+ };
247
+ const visit = (current, depth) => {
248
+ if (depth > 64) invalid("exceeds snapshot depth");
249
+ if (current === null || typeof current === "boolean") {
250
+ account();
251
+ return current;
252
+ }
253
+ if (typeof current === "string") {
254
+ account(current.length);
255
+ return current;
256
+ }
257
+ if (typeof current === "number") {
258
+ if (!Number.isFinite(current)) invalid("contains a non-finite number");
259
+ account();
260
+ return current;
261
+ }
262
+ if (!current || typeof current !== "object" || utilTypes.isProxy(current)) {
263
+ invalid("must contain only non-proxy canonical JSON values");
264
+ }
265
+ if (seen.has(current)) invalid("contains a cycle or repeated reference");
266
+ seen.add(current);
267
+ account();
268
+
269
+ if (Array.isArray(current)) {
270
+ if (Object.getPrototypeOf(current) !== Array.prototype) {
271
+ invalid("contains a non-plain array");
272
+ }
273
+ if (current.length > maxNodes) invalid("contains an oversized array");
274
+ const keys = Reflect.ownKeys(current);
275
+ if (keys.length !== current.length + 1) {
276
+ invalid("contains a sparse or extended array");
277
+ }
278
+ const output = [];
279
+ for (let index = 0; index < current.length; index += 1) {
280
+ const key = String(index);
281
+ const descriptor = Object.getOwnPropertyDescriptor(current, key);
282
+ if (
283
+ !descriptor ||
284
+ descriptor.enumerable !== true ||
285
+ !Object.hasOwn(descriptor, "value")
286
+ ) {
287
+ invalid("contains an accessor or sparse array entry");
288
+ }
289
+ output.push(visit(descriptor.value, depth + 1));
290
+ }
291
+ if (
292
+ keys.some(
293
+ (key) =>
294
+ key !== "length" &&
295
+ (typeof key !== "string" ||
296
+ !/^(0|[1-9][0-9]*)$/u.test(key) ||
297
+ Number(key) >= current.length),
298
+ )
299
+ ) {
300
+ invalid("contains an extended array");
301
+ }
302
+ return Object.freeze(output);
303
+ }
304
+
305
+ const prototype = Object.getPrototypeOf(current);
306
+ if (prototype !== Object.prototype && prototype !== null) {
307
+ invalid("contains a non-plain object");
308
+ }
309
+ const keys = Reflect.ownKeys(current);
310
+ if (keys.length > maxNodes) invalid("contains an oversized object");
311
+ const output = {};
312
+ for (const key of keys) {
313
+ if (typeof key !== "string") invalid("contains a symbol property");
314
+ accountCharacters(key.length);
315
+ const descriptor = Object.getOwnPropertyDescriptor(current, key);
316
+ if (
317
+ !descriptor ||
318
+ descriptor.enumerable !== true ||
319
+ !Object.hasOwn(descriptor, "value")
320
+ ) {
321
+ invalid("contains an accessor or non-enumerable property");
322
+ }
323
+ Object.defineProperty(output, key, {
324
+ configurable: false,
325
+ enumerable: true,
326
+ writable: false,
327
+ value: visit(descriptor.value, depth + 1),
328
+ });
329
+ }
330
+ return Object.freeze(output);
331
+ };
332
+
333
+ const snapshot = visit(value, 0);
334
+ let encoded;
335
+ try {
336
+ encoded = canonicalJson(snapshot, field);
337
+ } catch {
338
+ invalid("is not canonical JSON");
339
+ }
340
+ if (Buffer.byteLength(encoded, "utf8") > maxBytes) {
341
+ invalid("exceeds encoded byte limits");
342
+ }
343
+ return snapshot;
344
+ }
345
+
346
+ function domainSeparatedDigest(domain, value, field) {
347
+ return `sha256:${createHash("sha256")
348
+ .update(domain, "utf8")
349
+ .update(canonicalJson(value, field), "utf8")
350
+ .digest("hex")}`;
351
+ }
71
352
 
72
353
  function safeString(value, max = 256) {
73
354
  if (typeof value !== "string") return null;
74
355
  const output = value.trim();
75
- // eslint-disable-next-line no-control-regex -- rejecting ASCII controls is the validation boundary
76
- if (!output || output.length > max || /[\u0000-\u001f\u007f]/u.test(output)) {
356
+ let containsControlCharacter = false;
357
+ for (let index = 0; index < output.length; index += 1) {
358
+ const code = output.charCodeAt(index);
359
+ if (code <= 0x1f || code === 0x7f) {
360
+ containsControlCharacter = true;
361
+ break;
362
+ }
363
+ }
364
+ if (!output || output.length > max || containsControlCharacter) {
77
365
  return null;
78
366
  }
79
367
  return output;
80
368
  }
81
369
 
82
370
  function finiteNumber(value, { integer = false, min = 0 } = {}) {
83
- const output = Number(value);
371
+ const output =
372
+ typeof value === "number"
373
+ ? value
374
+ : typeof value === "string" &&
375
+ /^(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?$/u.test(value)
376
+ ? Number(value)
377
+ : Number.NaN;
84
378
  if (!Number.isFinite(output) || output < min) return null;
85
379
  if (integer && !Number.isSafeInteger(output)) return null;
86
380
  return output;
@@ -105,7 +399,10 @@ function usedCapabilities(workflow, batches) {
105
399
  if (workflow.pipeline === true) capabilities.add("pipeline");
106
400
  for (const step of workflow.steps) {
107
401
  if (step.when != null) capabilities.add("condition");
108
- if (step.forEach != null) capabilities.add("for-each");
402
+ if (step.forEach != null) {
403
+ capabilities.add("for-each");
404
+ capabilities.add("parallel");
405
+ }
109
406
  if (step.loopWhile != null || step.loopUntil != null)
110
407
  capabilities.add("loop");
111
408
  if (Number(step.retries) > 0) capabilities.add("retry");
@@ -396,19 +693,19 @@ function projectedDurationSlots(plan, requestedParallel) {
396
693
  const byId = new Map(plan.steps.map((step) => [step.id, step]));
397
694
  let total = 0;
398
695
  for (const batch of plan.batches) {
399
- for (
400
- let index = 0;
401
- index < batch.steps.length;
402
- index += requestedParallel
403
- ) {
404
- const chunk = batch.steps.slice(index, index + requestedParallel);
405
- const chunkDuration = Math.max(
406
- 0,
407
- ...chunk.map((id) => byId.get(id)?.worstCaseDurationSlots ?? 0),
408
- );
409
- total += chunkDuration;
410
- if (!Number.isSafeInteger(total)) return null;
411
- }
696
+ const steps = batch.steps.map((id) => byId.get(id));
697
+ const taskCalls = steps.reduce(
698
+ (sum, step) => sum + (step?.worstCaseTaskCalls ?? 0),
699
+ 0,
700
+ );
701
+ if (!Number.isSafeInteger(taskCalls)) return null;
702
+ const criticalPath = Math.max(
703
+ 0,
704
+ ...steps.map((step) => step?.worstCaseDurationSlots ?? 0),
705
+ );
706
+ const scheduledSlots = Math.ceil(taskCalls / requestedParallel);
707
+ total += Math.max(criticalPath, scheduledSlots);
708
+ if (!Number.isSafeInteger(total)) return null;
412
709
  }
413
710
  return total;
414
711
  }
@@ -421,6 +718,793 @@ function multiplyProjection(...values) {
421
718
  : null;
422
719
  }
423
720
 
721
+ function normalizeDefinitionAuthorityForRun(value) {
722
+ const code = DYNAMIC_WORKFLOW_DEFINITION_AUTHORITY_INVALID_CODE;
723
+ const authority = snapshotObjectFields(
724
+ value,
725
+ DEFINITION_AUTHORITY_FIELDS,
726
+ code,
727
+ "definitionAuthority",
728
+ );
729
+ if (!new Set(["versioned", "legacy-unversioned"]).has(authority.status)) {
730
+ throw admissionError(code, "definitionAuthority status is invalid");
731
+ }
732
+ if (
733
+ authority.definitionSchema !== WORKFLOW_DEFINITION_SCHEMA ||
734
+ (authority.status === "versioned"
735
+ ? authority.recordSchema !== COWORK_WORKFLOW_RECORD_SCHEMA
736
+ : authority.recordSchema !== null)
737
+ ) {
738
+ throw admissionError(code, "definitionAuthority schema is invalid");
739
+ }
740
+ const declaredDigest = normalizeWorkflowDefinitionDigest(
741
+ authority.definitionDigest,
742
+ );
743
+ if (!declaredDigest || declaredDigest !== authority.definitionDigest) {
744
+ throw admissionError(code, "definitionAuthority digest is invalid");
745
+ }
746
+ let computed;
747
+ try {
748
+ computed = createWorkflowDefinitionAuthority(
749
+ snapshotCanonicalValue(
750
+ authority.definition,
751
+ code,
752
+ "definitionAuthority.definition",
753
+ ),
754
+ );
755
+ } catch {
756
+ throw admissionError(code, "definitionAuthority definition is invalid");
757
+ }
758
+ if (computed.definitionDigest !== declaredDigest) {
759
+ throw admissionError(code, "definitionAuthority digest does not match");
760
+ }
761
+ return Object.freeze({
762
+ status: authority.status,
763
+ recordSchema: authority.recordSchema,
764
+ definitionSchema: computed.schema,
765
+ definitionDigest: computed.definitionDigest,
766
+ definition: computed.definition,
767
+ });
768
+ }
769
+
770
+ function canonicalObservedAt(value) {
771
+ if (typeof value !== "string") return false;
772
+ const epoch = Date.parse(value);
773
+ return Number.isFinite(epoch) && new Date(epoch).toISOString() === value;
774
+ }
775
+
776
+ export function normalizeSessionExecutionLocationAuthority(value) {
777
+ const code = DYNAMIC_WORKFLOW_EXECUTION_AUTHORITY_INVALID_CODE;
778
+ const authority = snapshotObjectFields(
779
+ value,
780
+ VERIFIED_SESSION_AUTHORITY_FIELDS,
781
+ code,
782
+ "executionLocationAuthority",
783
+ );
784
+ if (authority.schema !== SESSION_EXECUTION_LOCATION_AUTHORITY_SCHEMA) {
785
+ throw admissionError(
786
+ code,
787
+ `executionLocationAuthority must use ${SESSION_EXECUTION_LOCATION_AUTHORITY_SCHEMA}`,
788
+ );
789
+ }
790
+ const verified = new Set([
791
+ "verified-session-start",
792
+ "verified-session-location-handoff",
793
+ ]).has(authority.authority);
794
+ if (!verified) {
795
+ throw admissionError(
796
+ code,
797
+ "executionLocationAuthority must be a verified session location authority",
798
+ );
799
+ }
800
+ let binding;
801
+ try {
802
+ const bindingSnapshot = snapshotCanonicalValue(
803
+ authority.binding,
804
+ code,
805
+ "executionLocationAuthority.binding",
806
+ );
807
+ binding = normalizeExecutionLocationBinding(bindingSnapshot);
808
+ if (
809
+ canonicalJson(bindingSnapshot, "executionLocationAuthority.binding") !==
810
+ canonicalJson(binding, "executionLocationAuthority.binding")
811
+ ) {
812
+ throw new TypeError("binding is not canonical");
813
+ }
814
+ } catch {
815
+ throw admissionError(
816
+ code,
817
+ "executionLocationAuthority binding is invalid or non-canonical",
818
+ );
819
+ }
820
+ if (binding.observed !== true || !canonicalObservedAt(binding.observedAt)) {
821
+ throw admissionError(
822
+ code,
823
+ "executionLocationAuthority binding is not an observed instant",
824
+ );
825
+ }
826
+
827
+ const sessionId = safeString(authority.sessionId);
828
+ if (
829
+ sessionId !== authority.sessionId ||
830
+ !/^[a-f0-9]{64}$/u.test(authority.headHash) ||
831
+ !Number.isSafeInteger(authority.eventCount) ||
832
+ authority.eventCount < 1
833
+ ) {
834
+ throw admissionError(
835
+ code,
836
+ "executionLocationAuthority session proof is invalid",
837
+ );
838
+ }
839
+ return Object.freeze({
840
+ schema: SESSION_EXECUTION_LOCATION_AUTHORITY_SCHEMA,
841
+ authority: authority.authority,
842
+ sessionId,
843
+ headHash: authority.headHash,
844
+ eventCount: authority.eventCount,
845
+ binding,
846
+ });
847
+ }
848
+
849
+ function pathWithinDataBoundary(cwd, boundary) {
850
+ const root = boundary?.root;
851
+ if (typeof cwd !== "string" || typeof root !== "string") return false;
852
+ const windowsPath =
853
+ /^[A-Za-z]:[\\/]/u.test(root) ||
854
+ root.startsWith("\\\\") ||
855
+ /^[A-Za-z]:[\\/]/u.test(cwd) ||
856
+ cwd.startsWith("\\\\");
857
+ const paths = windowsPath ? win32Path : posixPath;
858
+ if (!paths.isAbsolute(root) || !paths.isAbsolute(cwd)) return false;
859
+ const relative = paths.relative(paths.normalize(root), paths.normalize(cwd));
860
+ return (
861
+ relative === "" ||
862
+ (relative !== ".." &&
863
+ !relative.startsWith(`..${paths.sep}`) &&
864
+ !paths.isAbsolute(relative))
865
+ );
866
+ }
867
+
868
+ function normalizeExecutionOptions(value, definition, executionAuthority) {
869
+ const code = DYNAMIC_WORKFLOW_EXECUTION_OPTIONS_INVALID_CODE;
870
+ const execution =
871
+ value == null
872
+ ? Object.freeze({})
873
+ : snapshotObjectFields(
874
+ value,
875
+ EXECUTION_OPTION_FIELDS,
876
+ code,
877
+ "execution",
878
+ { exact: false },
879
+ );
880
+ if (Object.hasOwn(execution, "llmOptions")) {
881
+ throw admissionError(
882
+ code,
883
+ "execution.llmOptions is not admitted; use the verified model binding",
884
+ );
885
+ }
886
+
887
+ for (const callback of ["onStepStart", "onStepComplete"]) {
888
+ if (
889
+ Object.hasOwn(execution, callback) &&
890
+ (typeof execution[callback] !== "function" ||
891
+ utilTypes.isProxy(execution[callback]))
892
+ ) {
893
+ throw admissionError(code, `execution.${callback} must be a function`);
894
+ }
895
+ }
896
+ if (
897
+ Object.hasOwn(execution, "continueOnError") &&
898
+ typeof execution.continueOnError !== "boolean"
899
+ ) {
900
+ throw admissionError(code, "execution.continueOnError must be a boolean");
901
+ }
902
+
903
+ const binding = executionAuthority.binding;
904
+ const cwd = binding.source.cwd;
905
+ const dataBoundary = binding.policy.dataBoundary;
906
+ if (!pathWithinDataBoundary(cwd, dataBoundary)) {
907
+ throw admissionError(
908
+ DYNAMIC_WORKFLOW_EXECUTION_AUTHORITY_INVALID_CODE,
909
+ "verified execution cwd is outside its data boundary",
910
+ );
911
+ }
912
+ const policy = Object.freeze({
913
+ cwd,
914
+ continueOnError: execution.continueOnError ?? false,
915
+ pipeline: definition.pipeline === true,
916
+ provider: binding.model.provider,
917
+ model: binding.model.name,
918
+ });
919
+ for (const field of ["cwd", "pipeline", "provider", "model"]) {
920
+ if (Object.hasOwn(execution, field) && execution[field] !== policy[field]) {
921
+ throw admissionError(
922
+ code,
923
+ `execution.${field} does not match verified authority`,
924
+ );
925
+ }
926
+ }
927
+
928
+ return Object.freeze({
929
+ policy,
930
+ onStepStart: execution.onStepStart,
931
+ onStepComplete: execution.onStepComplete,
932
+ });
933
+ }
934
+
935
+ function normalizeRunInput(input) {
936
+ const code = DYNAMIC_WORKFLOW_EXECUTION_AUTHORITY_INVALID_CODE;
937
+ const snapshot = snapshotObjectFields(
938
+ input,
939
+ RUN_INPUT_FIELDS,
940
+ code,
941
+ "dynamicWorkflowRun",
942
+ { exact: false },
943
+ );
944
+ if (
945
+ !Object.hasOwn(snapshot, "definitionAuthority") ||
946
+ !Object.hasOwn(snapshot, "executionAuthoritySessionId")
947
+ ) {
948
+ throw admissionError(
949
+ code,
950
+ "definitionAuthority and executionAuthoritySessionId are required",
951
+ );
952
+ }
953
+ const executionAuthoritySessionId = safeString(
954
+ snapshot.executionAuthoritySessionId,
955
+ );
956
+ if (executionAuthoritySessionId !== snapshot.executionAuthoritySessionId) {
957
+ throw admissionError(code, "executionAuthoritySessionId is invalid");
958
+ }
959
+ if (
960
+ Object.hasOwn(snapshot, "onAdmitted") &&
961
+ (typeof snapshot.onAdmitted !== "function" ||
962
+ utilTypes.isProxy(snapshot.onAdmitted))
963
+ ) {
964
+ throw admissionError(
965
+ DYNAMIC_WORKFLOW_EXECUTION_OPTIONS_INVALID_CODE,
966
+ "onAdmitted must be a function",
967
+ );
968
+ }
969
+ const definitionAuthority = normalizeDefinitionAuthorityForRun(
970
+ snapshot.definitionAuthority,
971
+ );
972
+ return Object.freeze({
973
+ definitionAuthority,
974
+ executionAuthoritySessionId,
975
+ maxParallel: snapshot.maxParallel,
976
+ execution: snapshot.execution,
977
+ onAdmitted: snapshot.onAdmitted,
978
+ });
979
+ }
980
+
981
+ function normalizeRunDependencies(deps) {
982
+ const code = DYNAMIC_WORKFLOW_EXECUTION_AUTHORITY_INVALID_CODE;
983
+ const snapshot = snapshotObjectFields(
984
+ deps,
985
+ RUN_DEPENDENCY_FIELDS,
986
+ code,
987
+ "dynamicWorkflowRunDependencies",
988
+ { exact: false },
989
+ );
990
+ if (
991
+ typeof snapshot.verifyAuthorities !== "function" ||
992
+ utilTypes.isProxy(snapshot.verifyAuthorities)
993
+ ) {
994
+ throw admissionError(code, "verifyAuthorities dependency is required");
995
+ }
996
+ if (
997
+ Object.hasOwn(snapshot, "executeWorkflow") &&
998
+ (typeof snapshot.executeWorkflow !== "function" ||
999
+ utilTypes.isProxy(snapshot.executeWorkflow))
1000
+ ) {
1001
+ throw admissionError(
1002
+ DYNAMIC_WORKFLOW_EXECUTION_OPTIONS_INVALID_CODE,
1003
+ "executeWorkflow dependency must be a function",
1004
+ );
1005
+ }
1006
+ return snapshot;
1007
+ }
1008
+
1009
+ function authorityLookup(runInput) {
1010
+ return Object.freeze({
1011
+ workflowId: runInput.definitionAuthority.definition.id,
1012
+ definitionDigest: runInput.definitionAuthority.definitionDigest,
1013
+ executionAuthoritySessionId: runInput.executionAuthoritySessionId,
1014
+ });
1015
+ }
1016
+
1017
+ function normalizeVerifiedAuthorities(value, runInput) {
1018
+ const code = DYNAMIC_WORKFLOW_EXECUTION_AUTHORITY_INVALID_CODE;
1019
+ const snapshot = snapshotObjectFields(
1020
+ value,
1021
+ VERIFIED_AUTHORITIES_FIELDS,
1022
+ code,
1023
+ "verifiedAuthorities",
1024
+ );
1025
+ const definitionAuthority = normalizeDefinitionAuthorityForRun(
1026
+ snapshot.definitionAuthority,
1027
+ );
1028
+ const executionLocationAuthority = normalizeSessionExecutionLocationAuthority(
1029
+ snapshot.executionLocationAuthority,
1030
+ );
1031
+ if (
1032
+ canonicalJson(definitionAuthority, "verifiedDefinitionAuthority") !==
1033
+ canonicalJson(runInput.definitionAuthority, "inputDefinitionAuthority")
1034
+ ) {
1035
+ throw admissionError(
1036
+ code,
1037
+ "verified definition authority does not exactly match the requested record",
1038
+ );
1039
+ }
1040
+ if (
1041
+ executionLocationAuthority.sessionId !==
1042
+ runInput.executionAuthoritySessionId
1043
+ ) {
1044
+ throw admissionError(
1045
+ code,
1046
+ "verified execution authority does not match the requested session",
1047
+ );
1048
+ }
1049
+ return Object.freeze({ definitionAuthority, executionLocationAuthority });
1050
+ }
1051
+
1052
+ function verifyAuthoritiesSynchronously(verifier, lookup, runInput) {
1053
+ let verified;
1054
+ try {
1055
+ verified = verifier(lookup);
1056
+ } catch {
1057
+ throw admissionError(
1058
+ DYNAMIC_WORKFLOW_EXECUTION_AUTHORITY_INVALID_CODE,
1059
+ "authority verification failed",
1060
+ );
1061
+ }
1062
+ if (utilTypes.isPromise(verified)) {
1063
+ throw admissionError(
1064
+ DYNAMIC_WORKFLOW_EXECUTION_AUTHORITY_INVALID_CODE,
1065
+ "buildDynamicWorkflowRunAdmission requires a synchronous authority verifier",
1066
+ );
1067
+ }
1068
+ return normalizeVerifiedAuthorities(verified, runInput);
1069
+ }
1070
+
1071
+ async function verifyAuthoritiesAsynchronously(verifier, lookup, runInput) {
1072
+ let verified;
1073
+ try {
1074
+ verified = await verifier(lookup);
1075
+ } catch {
1076
+ throw admissionError(
1077
+ DYNAMIC_WORKFLOW_EXECUTION_AUTHORITY_INVALID_CODE,
1078
+ "authority verification failed",
1079
+ );
1080
+ }
1081
+ return normalizeVerifiedAuthorities(verified, runInput);
1082
+ }
1083
+
1084
+ function authoritiesExactlyMatch(left, right) {
1085
+ return (
1086
+ canonicalJson(left, "firstVerifiedAuthorities") ===
1087
+ canonicalJson(right, "finalVerifiedAuthorities")
1088
+ );
1089
+ }
1090
+
1091
+ function blockedError(preflight) {
1092
+ return Object.freeze({
1093
+ name: "DynamicWorkflowAdmissionError",
1094
+ code: DYNAMIC_WORKFLOW_PREFLIGHT_BLOCKED_CODE,
1095
+ message: "dynamic workflow execution was blocked by preflight",
1096
+ details: Object.freeze({ blockers: preflight.blockers }),
1097
+ });
1098
+ }
1099
+
1100
+ function prepareDynamicWorkflowRun(runInput, verifiedAuthorities, execution) {
1101
+ const { definitionAuthority, executionLocationAuthority } =
1102
+ verifiedAuthorities;
1103
+ const workflow = definitionAuthority.definition;
1104
+ const preflight = buildDynamicWorkflowPreflight({
1105
+ workflow,
1106
+ definitionAuthority,
1107
+ executionLocation: executionLocationAuthority.binding,
1108
+ maxParallel: runInput.maxParallel,
1109
+ requireDefinitionAuthority: true,
1110
+ });
1111
+ const executionLocationDigest = domainSeparatedDigest(
1112
+ "chainlesschain.dynamic-workflow.execution-location.v1\0",
1113
+ executionLocationAuthority,
1114
+ "executionLocationAuthority",
1115
+ );
1116
+ const preflightDigest = domainSeparatedDigest(
1117
+ "chainlesschain.dynamic-workflow.preflight.v1\0",
1118
+ preflight,
1119
+ "dynamicWorkflowPreflight",
1120
+ );
1121
+
1122
+ if (!preflight.allowed) {
1123
+ return Object.freeze({
1124
+ workflow: definitionAuthority.definition,
1125
+ outcome: Object.freeze({
1126
+ allowed: false,
1127
+ admission: null,
1128
+ preflight,
1129
+ definitionDigest: preflight.definition.definitionDigest,
1130
+ executionLocationDigest,
1131
+ preflightDigest,
1132
+ admissionDigest: null,
1133
+ authorityVerified: true,
1134
+ error: blockedError(preflight),
1135
+ }),
1136
+ });
1137
+ }
1138
+
1139
+ const admissionMaterial = Object.freeze({
1140
+ schema: DYNAMIC_WORKFLOW_RUN_ADMISSION_SCHEMA,
1141
+ definition: Object.freeze({
1142
+ schema: preflight.definition.schema,
1143
+ definitionDigest: preflight.definition.definitionDigest,
1144
+ authority: preflight.definition.authority,
1145
+ }),
1146
+ executionLocation: Object.freeze({
1147
+ authoritySchema: executionLocationAuthority.schema,
1148
+ authority: executionLocationAuthority.authority,
1149
+ session: Object.freeze({
1150
+ sessionId: executionLocationAuthority.sessionId,
1151
+ headHash: executionLocationAuthority.headHash,
1152
+ eventCount: executionLocationAuthority.eventCount,
1153
+ }),
1154
+ bindingSchema: executionLocationAuthority.binding.schema,
1155
+ location: executionLocationAuthority.binding.location,
1156
+ }),
1157
+ definitionDigest: preflight.definition.definitionDigest,
1158
+ executionLocationDigest,
1159
+ preflightDigest,
1160
+ maxParallel: preflight.scale.requestedParallel,
1161
+ executionPolicy: execution.policy,
1162
+ credentialValuesTransferred: false,
1163
+ });
1164
+ const admissionDigest = domainSeparatedDigest(
1165
+ "chainlesschain.dynamic-workflow.admission.v1\0",
1166
+ admissionMaterial,
1167
+ "dynamicWorkflowAdmission",
1168
+ );
1169
+ const admission = Object.freeze({
1170
+ ...admissionMaterial,
1171
+ admissionDigest,
1172
+ });
1173
+
1174
+ return Object.freeze({
1175
+ workflow: definitionAuthority.definition,
1176
+ outcome: Object.freeze({
1177
+ allowed: true,
1178
+ admission,
1179
+ preflight,
1180
+ definitionDigest: admission.definitionDigest,
1181
+ executionLocationDigest,
1182
+ preflightDigest,
1183
+ admissionDigest,
1184
+ authorityVerified: true,
1185
+ error: null,
1186
+ }),
1187
+ });
1188
+ }
1189
+
1190
+ export function buildDynamicWorkflowRunAdmission(input = {}, deps = {}) {
1191
+ const runInput = normalizeRunInput(input);
1192
+ const dependencies = normalizeRunDependencies(deps);
1193
+ const verifiedAuthorities = verifyAuthoritiesSynchronously(
1194
+ dependencies.verifyAuthorities,
1195
+ authorityLookup(runInput),
1196
+ runInput,
1197
+ );
1198
+ const execution = normalizeExecutionOptions(
1199
+ runInput.execution,
1200
+ verifiedAuthorities.definitionAuthority.definition,
1201
+ verifiedAuthorities.executionLocationAuthority,
1202
+ );
1203
+ return prepareDynamicWorkflowRun(runInput, verifiedAuthorities, execution)
1204
+ .outcome;
1205
+ }
1206
+
1207
+ function canonicalTimestamp(value) {
1208
+ if (typeof value !== "string") return false;
1209
+ const epoch = Date.parse(value);
1210
+ return Number.isFinite(epoch) && new Date(epoch).toISOString() === value;
1211
+ }
1212
+
1213
+ function declaredDependencyIds(step, stepsById) {
1214
+ const dependencies = new Set();
1215
+ const pending = [...(step.dependsOn || [])];
1216
+ while (pending.length > 0) {
1217
+ const dependencyId = pending.pop();
1218
+ if (dependencies.has(dependencyId)) continue;
1219
+ dependencies.add(dependencyId);
1220
+ const dependency = stepsById.get(dependencyId);
1221
+ if (dependency) pending.push(...(dependency.dependsOn || []));
1222
+ }
1223
+ return dependencies;
1224
+ }
1225
+
1226
+ function runtimeForEachSourceId(value) {
1227
+ if (typeof value !== "string") return null;
1228
+ const match = value.trim().match(/^\$\{step\.([^.{}]+)\.[^.{}]+\}$/u);
1229
+ return match?.[1] || null;
1230
+ }
1231
+
1232
+ function assertCompletedRecordCoverage(record, workflow, code) {
1233
+ const outcomesById = new Map(record.steps.map((step) => [step.id, step]));
1234
+ const expectedOutcomeIds = new Set();
1235
+ const resultsById = new Map();
1236
+ const stepsById = new Map(workflow.steps.map((step) => [step.id, step]));
1237
+
1238
+ const requireOutcome = (id) => {
1239
+ if (expectedOutcomeIds.has(id)) {
1240
+ throw admissionError(
1241
+ code,
1242
+ "completed workflow definition produces colliding outcome ids",
1243
+ );
1244
+ }
1245
+ const outcome = outcomesById.get(id);
1246
+ if (!outcome) {
1247
+ throw admissionError(
1248
+ code,
1249
+ `completed workflow record is missing outcome '${id}'`,
1250
+ );
1251
+ }
1252
+ expectedOutcomeIds.add(id);
1253
+ return outcome;
1254
+ };
1255
+
1256
+ for (const batch of planBatches(workflow.steps)) {
1257
+ // Outcomes from independent steps in the same batch are not authoritative
1258
+ // inputs to one another. Publish only parent outcomes after the whole batch
1259
+ // has been reconstructed.
1260
+ const batchResults = [];
1261
+ for (const step of batch) {
1262
+ if (!shouldRunStep(step, resultsById)) {
1263
+ throw admissionError(
1264
+ code,
1265
+ `completed workflow record includes non-runnable step '${step.id}'`,
1266
+ );
1267
+ }
1268
+
1269
+ if (step.forEach === undefined) {
1270
+ batchResults.push([step.id, requireOutcome(step.id)]);
1271
+ continue;
1272
+ }
1273
+
1274
+ if (typeof step.forEach === "string") {
1275
+ const sourceId = runtimeForEachSourceId(step.forEach);
1276
+ if (
1277
+ !sourceId ||
1278
+ !declaredDependencyIds(step, stepsById).has(sourceId)
1279
+ ) {
1280
+ throw admissionError(
1281
+ code,
1282
+ `runtime forEach on '${step.id}' is not bound to a declared dependency`,
1283
+ );
1284
+ }
1285
+ }
1286
+
1287
+ const items = resolveForEachItems(step.forEach, resultsById);
1288
+ if (items.length === 0) {
1289
+ throw admissionError(
1290
+ code,
1291
+ `completed workflow record cannot cover empty forEach '${step.id}'`,
1292
+ );
1293
+ }
1294
+ const children = [];
1295
+ for (let index = 0; index < items.length; index += 1) {
1296
+ children.push(requireOutcome(`${step.id}[${index}]`));
1297
+ }
1298
+ batchResults.push([
1299
+ step.id,
1300
+ Object.freeze({
1301
+ id: step.id,
1302
+ status: "completed",
1303
+ taskId: null,
1304
+ result: Object.freeze({
1305
+ summary: children
1306
+ .map((child) => child.result?.summary ?? "")
1307
+ .join("\n"),
1308
+ children: children.length,
1309
+ }),
1310
+ }),
1311
+ ]);
1312
+ }
1313
+ for (const [stepId, outcome] of batchResults) {
1314
+ resultsById.set(stepId, outcome);
1315
+ }
1316
+ }
1317
+
1318
+ if (
1319
+ expectedOutcomeIds.size !== record.steps.length ||
1320
+ record.steps.some((step) => !expectedOutcomeIds.has(step.id))
1321
+ ) {
1322
+ throw admissionError(
1323
+ code,
1324
+ "completed workflow record contains outcomes outside its definition",
1325
+ );
1326
+ }
1327
+ }
1328
+
1329
+ function normalizeExecutionRecord(value, prepared) {
1330
+ const code = DYNAMIC_WORKFLOW_EXECUTION_RESULT_INVALID_CODE;
1331
+ try {
1332
+ const fields = snapshotObjectFields(
1333
+ value,
1334
+ RUN_RECORD_FIELDS,
1335
+ code,
1336
+ "executeWorkflowRecord",
1337
+ );
1338
+ if (
1339
+ !Array.isArray(fields.steps) ||
1340
+ utilTypes.isProxy(fields.steps) ||
1341
+ fields.steps.length > MAX_RUN_RECORD_STEPS
1342
+ ) {
1343
+ throw admissionError(code, "executeWorkflowRecord steps are invalid");
1344
+ }
1345
+ const record = snapshotCanonicalValue(
1346
+ fields,
1347
+ code,
1348
+ "executeWorkflowRecord",
1349
+ );
1350
+ const admission = prepared.outcome.admission;
1351
+ const workflow = prepared.workflow;
1352
+ if (
1353
+ record.schema !== COWORK_WORKFLOW_RUN_RECORD_SCHEMA ||
1354
+ record.workflowId !== workflow.id ||
1355
+ record.workflowName !== workflow.name ||
1356
+ record.definitionSchema !== WORKFLOW_DEFINITION_SCHEMA ||
1357
+ record.definitionDigest !== admission.definitionDigest ||
1358
+ !RUN_RECORD_STATUSES.has(record.status) ||
1359
+ !canonicalTimestamp(record.startedAt) ||
1360
+ !canonicalTimestamp(record.finishedAt) ||
1361
+ Date.parse(record.finishedAt) < Date.parse(record.startedAt)
1362
+ ) {
1363
+ throw admissionError(
1364
+ code,
1365
+ "executeWorkflowRecord does not match the admitted workflow",
1366
+ );
1367
+ }
1368
+ if (
1369
+ !record.runAdmission ||
1370
+ record.runAdmission.admissionDigest !== admission.admissionDigest ||
1371
+ canonicalJson(record.runAdmission, "recordRunAdmission") !==
1372
+ canonicalJson(admission, "admittedRunAdmission")
1373
+ ) {
1374
+ throw admissionError(
1375
+ code,
1376
+ "executeWorkflowRecord run admission does not match",
1377
+ );
1378
+ }
1379
+
1380
+ const stepIds = new Set();
1381
+ for (const [index, step] of record.steps.entries()) {
1382
+ const normalizedStep = snapshotObjectFields(
1383
+ step,
1384
+ RUN_RECORD_STEP_FIELDS,
1385
+ code,
1386
+ `executeWorkflowRecord.steps[${index}]`,
1387
+ );
1388
+ const id = safeString(normalizedStep.id, 512);
1389
+ if (
1390
+ id !== normalizedStep.id ||
1391
+ stepIds.has(id) ||
1392
+ !RUN_RECORD_STEP_STATUSES.has(normalizedStep.status) ||
1393
+ (normalizedStep.taskId !== null &&
1394
+ safeString(normalizedStep.taskId, 512) !== normalizedStep.taskId)
1395
+ ) {
1396
+ throw admissionError(
1397
+ code,
1398
+ "executeWorkflowRecord contains an invalid step outcome",
1399
+ );
1400
+ }
1401
+ stepIds.add(id);
1402
+ }
1403
+ const expectedStatus = record.steps.every(
1404
+ (step) => step.status === "completed",
1405
+ )
1406
+ ? "completed"
1407
+ : record.steps.some((step) => step.status === "completed")
1408
+ ? "partial"
1409
+ : "failed";
1410
+ if (record.status !== expectedStatus) {
1411
+ throw admissionError(
1412
+ code,
1413
+ "executeWorkflowRecord status does not match its step outcomes",
1414
+ );
1415
+ }
1416
+ if (record.status === "completed") {
1417
+ assertCompletedRecordCoverage(record, workflow, code);
1418
+ }
1419
+ return Object.freeze({ ...record, runAdmission: admission });
1420
+ } catch {
1421
+ throw admissionError(
1422
+ code,
1423
+ "executeWorkflow returned an invalid admitted run record",
1424
+ Object.freeze({
1425
+ expectedDefinitionDigest: prepared.outcome.admission.definitionDigest,
1426
+ expectedAdmissionDigest: prepared.outcome.admission.admissionDigest,
1427
+ }),
1428
+ { executionStarted: true },
1429
+ );
1430
+ }
1431
+ }
1432
+
1433
+ export async function executeDynamicWorkflowWithAdmission(
1434
+ input = {},
1435
+ deps = {},
1436
+ ) {
1437
+ const runInput = normalizeRunInput(input);
1438
+ const dependencies = normalizeRunDependencies(deps);
1439
+ const executor = Object.hasOwn(dependencies, "executeWorkflow")
1440
+ ? dependencies.executeWorkflow
1441
+ : executeCoworkWorkflow;
1442
+ const lookup = authorityLookup(runInput);
1443
+ const verifiedAuthorities = await verifyAuthoritiesAsynchronously(
1444
+ dependencies.verifyAuthorities,
1445
+ lookup,
1446
+ runInput,
1447
+ );
1448
+ const execution = normalizeExecutionOptions(
1449
+ runInput.execution,
1450
+ verifiedAuthorities.definitionAuthority.definition,
1451
+ verifiedAuthorities.executionLocationAuthority,
1452
+ );
1453
+ const prepared = prepareDynamicWorkflowRun(
1454
+ runInput,
1455
+ verifiedAuthorities,
1456
+ execution,
1457
+ );
1458
+ if (!prepared.outcome.allowed) {
1459
+ return Object.freeze({
1460
+ ...prepared.outcome,
1461
+ record: null,
1462
+ executionStarted: false,
1463
+ });
1464
+ }
1465
+
1466
+ const finalAuthorities = await verifyAuthoritiesAsynchronously(
1467
+ dependencies.verifyAuthorities,
1468
+ lookup,
1469
+ runInput,
1470
+ );
1471
+ if (!authoritiesExactlyMatch(verifiedAuthorities, finalAuthorities)) {
1472
+ throw admissionError(
1473
+ DYNAMIC_WORKFLOW_EXECUTION_AUTHORITY_INVALID_CODE,
1474
+ "verified authorities changed during run admission",
1475
+ );
1476
+ }
1477
+ if (runInput.onAdmitted) {
1478
+ await runInput.onAdmitted(
1479
+ prepared.outcome.admission,
1480
+ prepared.outcome.preflight,
1481
+ );
1482
+ }
1483
+ const policy = prepared.outcome.admission.executionPolicy;
1484
+ const record = await executor({
1485
+ cwd: policy.cwd,
1486
+ continueOnError: policy.continueOnError,
1487
+ pipeline: policy.pipeline,
1488
+ llmOptions: Object.freeze({
1489
+ provider: policy.provider,
1490
+ model: policy.model,
1491
+ }),
1492
+ onStepStart: execution.onStepStart,
1493
+ onStepComplete: execution.onStepComplete,
1494
+ workflow: prepared.workflow,
1495
+ definitionDigest: prepared.outcome.admission.definitionDigest,
1496
+ maxParallel: prepared.outcome.admission.maxParallel,
1497
+ runAdmission: prepared.outcome.admission,
1498
+ });
1499
+ const normalizedRecord = normalizeExecutionRecord(record, prepared);
1500
+
1501
+ return Object.freeze({
1502
+ ...prepared.outcome,
1503
+ record: normalizedRecord,
1504
+ executionStarted: true,
1505
+ });
1506
+ }
1507
+
424
1508
  export function buildDynamicWorkflowPreflight(input = {}) {
425
1509
  const suppliedManifest =
426
1510
  input.manifest?.schema === DYNAMIC_WORKFLOW_DEFINITION_SCHEMA
@@ -452,6 +1536,10 @@ export function buildDynamicWorkflowPreflight(input = {}) {
452
1536
  })
453
1537
  : null;
454
1538
 
1539
+ if (input.requireDefinitionAuthority === true && !definitionAuthority) {
1540
+ addUnique(blockers, "definition-authority-missing");
1541
+ }
1542
+
455
1543
  if (
456
1544
  suppliedManifest &&
457
1545
  suppliedManifest.definitionDigest !== manifest.definitionDigest