chainlesschain 0.163.8 → 0.165.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. package/package.json +7 -4
  2. package/scripts/macos-mcp-launcher-build.mjs +317 -0
  3. package/scripts/macos-mcp-launcher-postinstall.sh +54 -0
  4. package/scripts/macos-mcp-launcher-preinstall.sh +61 -0
  5. package/src/assets/web-panel/.build-hash +1 -1
  6. package/src/assets/web-panel/assets/{AIOps-CavM7W3k.js → AIOps-CYxFDrcm.js} +1 -1
  7. package/src/assets/web-panel/assets/{ActionButton-CUvZGabQ.js → ActionButton-CPBtdiU2.js} +1 -1
  8. package/src/assets/web-panel/assets/{Analytics-DeBnWnbe.js → Analytics-Dayq7Dp7.js} +3 -3
  9. package/src/assets/web-panel/assets/{AppLayout-DbI5kxvd.js → AppLayout-6U7bPb2s.js} +4 -4
  10. package/src/assets/web-panel/assets/{Artifacts-D93bigKm.js → Artifacts-D2Iqg_3D.js} +1 -1
  11. package/src/assets/web-panel/assets/{Audit-CBNvfUZa.js → Audit-CdoOB7WV.js} +1 -1
  12. package/src/assets/web-panel/assets/{BackgroundAgents-CJLyh_YU.js → BackgroundAgents-DrnAVB8w.js} +1 -1
  13. package/src/assets/web-panel/assets/{Backup-D_0yoehD.js → Backup-CesMi5cy.js} +1 -1
  14. package/src/assets/web-panel/assets/{BaseInput-TJxmbObW.js → BaseInput-DaX9ptax.js} +1 -1
  15. package/src/assets/web-panel/assets/{Chat-CE0dto1q.js → Chat-OrwOPxDS.js} +5 -5
  16. package/src/assets/web-panel/assets/{ChatBubbleRenderer-CZ5-yYiD.js → ChatBubbleRenderer-CvPZFRxM.js} +1 -1
  17. package/src/assets/web-panel/assets/{Checkbox-Ck1RVIVo.js → Checkbox-DiHbcysC.js} +1 -1
  18. package/src/assets/web-panel/assets/{Codegen-qpoyf6DK.js → Codegen-CbgCkaBJ.js} +1 -1
  19. package/src/assets/web-panel/assets/{Col-DUyPWjIE.js → Col-Du5hgrh4.js} +1 -1
  20. package/src/assets/web-panel/assets/{Community-D_S1BemS.js → Community-DsPOBW-p.js} +1 -1
  21. package/src/assets/web-panel/assets/{Compact-BjxeK-Gc.js → Compact-BwHIFkNC.js} +1 -1
  22. package/src/assets/web-panel/assets/{Compliance-Dd3CEJsu.js → Compliance-BvrDQSgd.js} +1 -1
  23. package/src/assets/web-panel/assets/{Cowork-B4QG7-ad.js → Cowork-gwAE6arx.js} +3 -3
  24. package/src/assets/web-panel/assets/{Cron-BtZnids5.js → Cron-DW-0l4uF.js} +2 -2
  25. package/src/assets/web-panel/assets/{Crosschain-CHPfCBFD.js → Crosschain-j-NsLesB.js} +1 -1
  26. package/src/assets/web-panel/assets/{DID-DT8DCEOK.js → DID-CibVEBOI.js} +2 -2
  27. package/src/assets/web-panel/assets/{Dashboard-COQab5_U.js → Dashboard-W4z9vSfe.js} +2 -2
  28. package/src/assets/web-panel/assets/{Dropdown-BY1PsQuU.js → Dropdown-DAcrkKxG.js} +1 -1
  29. package/src/assets/web-panel/assets/{EmailListRenderer-CsuAuaq3.js → EmailListRenderer-6GXah-89.js} +1 -1
  30. package/src/assets/web-panel/assets/{FamilyGuardDashboard-BqpinD-j.js → FamilyGuardDashboard-TKDCq8Ku.js} +1 -1
  31. package/src/assets/web-panel/assets/{Federation-D0gkfQFv.js → Federation-BXBLlcNm.js} +1 -1
  32. package/src/assets/web-panel/assets/{FormItemContext-BqgE-axK.js → FormItemContext-BoJJBkG3.js} +1 -1
  33. package/src/assets/web-panel/assets/{GenericCardRenderer-D0hJ2KvC.js → GenericCardRenderer-okjsl46v.js} +1 -1
  34. package/src/assets/web-panel/assets/{Git-CmMB0uPY.js → Git-Rvs7i6nn.js} +2 -2
  35. package/src/assets/web-panel/assets/{Governance-BnVEI0Dk.js → Governance-CHSUxXXS.js} +1 -1
  36. package/src/assets/web-panel/assets/{Inference-YTAMihRP.js → Inference-V3BlfxsB.js} +1 -1
  37. package/src/assets/web-panel/assets/{KnowledgeGraph-0ax7VHop.js → KnowledgeGraph-C_NlD4aR.js} +1 -1
  38. package/src/assets/web-panel/assets/{Logs-B9TRcokL.js → Logs-Nn4LNxhA.js} +2 -2
  39. package/src/assets/web-panel/assets/MarkdownRenderer-SVAgNnkt.js +1 -0
  40. package/src/assets/web-panel/assets/{Marketplace-B6CSuD_H.js → Marketplace-DEmjFcg-.js} +1 -1
  41. package/src/assets/web-panel/assets/{McpTools-CjMXvOVU.js → McpTools-DlopXipI.js} +3 -3
  42. package/src/assets/web-panel/assets/{Memory-CXRF71U3.js → Memory-BG3ynX60.js} +2 -2
  43. package/src/assets/web-panel/assets/{MobileBridge-DQgNp_oS.js → MobileBridge-DeRzWOfT.js} +1 -1
  44. package/src/assets/web-panel/assets/{MobileProjects-DlPwcCbq.js → MobileProjects-Tyd3o2A0.js} +1 -1
  45. package/src/assets/web-panel/assets/{Mtc-6hDTRPe1.js → Mtc-BoPbOv1C.js} +2 -2
  46. package/src/assets/web-panel/assets/{MtcAudit-BlVHU1DS.js → MtcAudit-un-rTHp7.js} +2 -2
  47. package/src/assets/web-panel/assets/{Multisig-DP9pzEbV.js → Multisig-Ds0oveEB.js} +3 -3
  48. package/src/assets/web-panel/assets/{NLProgramming-Djorh8EV.js → NLProgramming-D09JI-yY.js} +1 -1
  49. package/src/assets/web-panel/assets/{Notes-oLZ-JkUg.js → Notes-DTRhiKJn.js} +4 -4
  50. package/src/assets/web-panel/assets/{NotificationSettings-Cg288VH3.js → NotificationSettings-BAnnNCim.js} +1 -1
  51. package/src/assets/web-panel/assets/OrderTableRenderer-Yr-1fSYi.js +1 -0
  52. package/src/assets/web-panel/assets/{Organization-CBdo-bHs.js → Organization-S9EAolpj.js} +4 -4
  53. package/src/assets/web-panel/assets/{Overflow-qZdnVumx.js → Overflow-CqcLKqJ8.js} +1 -1
  54. package/src/assets/web-panel/assets/{P2P-D4kNfGNQ.js → P2P-Dw0F9EcU.js} +2 -2
  55. package/src/assets/web-panel/assets/{PdhVaultBrowser-DnlMemM7.js → PdhVaultBrowser-BDRwUevN.js} +5 -5
  56. package/src/assets/web-panel/assets/{Permissions-DHucHFBJ.js → Permissions-D3_c3nKB.js} +4 -4
  57. package/src/assets/web-panel/assets/{PersonalDataHub-BovlOIPR.js → PersonalDataHub-CxdMV98x.js} +4 -4
  58. package/src/assets/web-panel/assets/{Pipeline-Deru3CQY.js → Pipeline-CgjNQFLI.js} +1 -1
  59. package/src/assets/web-panel/assets/{Privacy-Bq5oTTbU.js → Privacy-BHghIIht.js} +1 -1
  60. package/src/assets/web-panel/assets/{ProjectInit-BfzxVWAz.js → ProjectInit-De6pqaKM.js} +2 -2
  61. package/src/assets/web-panel/assets/{ProjectSettings-CKC6XBtH.js → ProjectSettings-Bg4ZkNYQ.js} +2 -2
  62. package/src/assets/web-panel/assets/Projects-CP8vPvzs.js +1 -0
  63. package/src/assets/web-panel/assets/{Providers-C_jx4TWX.js → Providers-CUnHbNf-.js} +1 -1
  64. package/src/assets/web-panel/assets/{QrScannerModal-BdIHeVGC.js → QrScannerModal-DA2f3Wts.js} +1 -1
  65. package/src/assets/web-panel/assets/{QuickAsk-BwZwAcPD.js → QuickAsk-C1FeHDqp.js} +1 -1
  66. package/src/assets/web-panel/assets/{Recommend-BNTt0L-m.js → Recommend-B5guaUMN.js} +1 -1
  67. package/src/assets/web-panel/assets/RemoteSession-PDADSds3.js +5 -0
  68. package/src/assets/web-panel/assets/{Reputation-D6VpG32B.js → Reputation-eTlRhgvK.js} +1 -1
  69. package/src/assets/web-panel/assets/{Row-D_74OvQQ.js → Row-D7AqSGY0.js} +1 -1
  70. package/src/assets/web-panel/assets/{RssFeed-BTr0a-BQ.js → RssFeed-JiuLm4Ja.js} +3 -3
  71. package/src/assets/web-panel/assets/{Search-C3MCFoNU.js → Search-CwruahW3.js} +1 -1
  72. package/src/assets/web-panel/assets/{Security-CqW9aJ6s.js → Security-CdhqaR0b.js} +4 -4
  73. package/src/assets/web-panel/assets/{Services-Cw5GNaHF.js → Services-CU0ZIlcT.js} +2 -2
  74. package/src/assets/web-panel/assets/{Skeleton-DZps5qeY.js → Skeleton-CtduPfAb.js} +1 -1
  75. package/src/assets/web-panel/assets/{Skills-C6NQ1znT.js → Skills-CROXm6AY.js} +1 -1
  76. package/src/assets/web-panel/assets/{Sla-DFP8G2Sh.js → Sla-DiZiABFD.js} +1 -1
  77. package/src/assets/web-panel/assets/{SpeechSettings-ESt6MB6v.js → SpeechSettings-B5pLcXUw.js} +1 -1
  78. package/src/assets/web-panel/assets/{SyncSettings-BHnN98aM.js → SyncSettings-DBX6J1Oe.js} +2 -2
  79. package/src/assets/web-panel/assets/{Tasks-NiSCaOf-.js → Tasks-BLyRJd3-.js} +1 -1
  80. package/src/assets/web-panel/assets/{Templates-DsKFhW2C.js → Templates-BKa5qzmk.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tenant-CQ0E0ze5.js → Tenant-DnD3a4M6.js} +1 -1
  82. package/src/assets/web-panel/assets/{Terminal-D_rBu_by.js → Terminal-DEitQeTb.js} +2 -2
  83. package/src/assets/web-panel/assets/{TimelineRenderer-D3Vm4Po4.js → TimelineRenderer-CjHggTDq.js} +1 -1
  84. package/src/assets/web-panel/assets/{Tokens-DNTxRH6q.js → Tokens-CsGT7sfl.js} +1 -1
  85. package/src/assets/web-panel/assets/{Trigger-Dgprz1ms.js → Trigger-yr4rFDrW.js} +1 -1
  86. package/src/assets/web-panel/assets/{Trust-B2rUnVBD.js → Trust-CLvu1Sjp.js} +1 -1
  87. package/src/assets/web-panel/assets/{UkeySign-DEGQNc6_.js → UkeySign-B0m7yUP8.js} +1 -1
  88. package/src/assets/web-panel/assets/{VideoEditing-jlsAx3Eh.js → VideoEditing-C0VvP4lc.js} +1 -1
  89. package/src/assets/web-panel/assets/{Wallet-8jQih1ij.js → Wallet-kllBAG1M.js} +4 -4
  90. package/src/assets/web-panel/assets/{WebAuthn-XLeO6xIB.js → WebAuthn-C54UQNLx.js} +3 -3
  91. package/src/assets/web-panel/assets/{WorkflowEditor-De_dgDAG.js → WorkflowEditor-B7y8qSvU.js} +1 -1
  92. package/src/assets/web-panel/assets/{chat-CI19R_Sk.js → chat-DRzTh8CJ.js} +1 -1
  93. package/src/assets/web-panel/assets/{colors-DsYTOYN3.js → colors-BSMwSnCx.js} +1 -1
  94. package/src/assets/web-panel/assets/{compact-item-CM3-t_Qr.js → compact-item-BTg602H5.js} +1 -1
  95. package/src/assets/web-panel/assets/{createContext-BjxlBRZv.js → createContext-B6EGsdvp.js} +1 -1
  96. package/src/assets/web-panel/assets/devWarning-Dol8jLEP.js +1 -0
  97. package/src/assets/web-panel/assets/{hasIn-RDaWX_4i.js → hasIn-DDKqJ8RD.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-nAH87mQP.js → index-323Hhxxt.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-DIUnNOjG.js → index-BICn3Qh1.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-DyIWssPC.js → index-BMuGd2--.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-DX7tuWVJ.js → index-BRqt4fO-.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-Cd3euP_4.js → index-BVTAl5N2.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-Cpqm1qfU.js → index-BsR7Y2NG.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-DcPFB8qJ.js → index-Bx044qDj.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-Cd9OJhHG.js → index-C1GFfuqN.js} +1 -1
  106. package/src/assets/web-panel/assets/index-C3QX5tOl.js +1 -0
  107. package/src/assets/web-panel/assets/{index-B-Z8eFUJ.js → index-C66NpWy5.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-BlT2VAEK.js → index-CDTvsX8t.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-Dsij_KsN.js → index-CGNklbP6.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-C4gkzxkw.js → index-CHfLYwcW.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-D6sm5-Xq.js → index-CNxg61YP.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-C0yx-jtQ.js → index-CQlHFN_g.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-CjTrRt13.js → index-CUEU48o1.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-B7WBt_4T.js → index-CWGax2QW.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-IeiL9RKc.js → index-C_JzIXUq.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-CnHH7bnD.js → index-Cf23wVMs.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-BKJr-TZp.js → index-CmAInUkX.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-CiECJi-Q.js → index-CmAubjDi.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-BCnZyIMA.js → index-Co7oM1qr.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-Drlnwr8F.js → index-CwPUZbMI.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-9R6BxAr0.js → index-D1naNj4U.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-BGqqJfL0.js → index-D5CsBShd.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-Bi46Xu4u.js → index-DBT3YeQ9.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-DXXtGMUJ.js → index-DLdrHhML.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-B0PMlbMs.js → index-Dc77VR3H.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-D0zcy54x.js → index-Dfv2lKu3.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-BN6UPD2E.js → index-DiW0sDkz.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-Dxge-xWl.js → index-DpTHIRfZ.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-CyOGN6a5.js → index-DqFXGzzC.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-B9O9YyWE.js → index-XFe-1twF.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-BHNYPO0b.js → index-p2HYn89m.js} +3 -3
  132. package/src/assets/web-panel/assets/{index-CVQMeiwH.js → index-pqfux8vZ.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-pPL66J85.js → index-rjzk9z1Q.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-DoQA0-52.js → index-th2ihDc0.js} +1 -1
  135. package/src/assets/web-panel/assets/{index-B5REnKt8.js → index-u2YVld9W.js} +1 -1
  136. package/src/assets/web-panel/assets/index-xYybvEic.js +1 -0
  137. package/src/assets/web-panel/assets/{initDefaultProps-BTL88of4.js → initDefaultProps-C3Djh9fa.js} +1 -1
  138. package/src/assets/web-panel/assets/{motion-BUB2pXwB.js → motion-BzqFmbSe.js} +1 -1
  139. package/src/assets/web-panel/assets/{move-egCkkOMm.js → move-DJo_FFaW.js} +1 -1
  140. package/src/assets/web-panel/assets/{mtc-parser-DAWhZC8c.js → mtc-parser-_tlTiBvk.js} +1 -1
  141. package/src/assets/web-panel/assets/{omit-CvOxe_6d.js → omit-CB2ZyxUg.js} +1 -1
  142. package/src/assets/web-panel/assets/{pickAttrs-DZUSLZ5Z.js → pickAttrs-DZwIFD4u.js} +1 -1
  143. package/src/assets/web-panel/assets/{placementArrow-BERxGNMY.js → placementArrow-DxZY0dgk.js} +1 -1
  144. package/src/assets/web-panel/assets/{responsiveObserve-DZuDfZ9n.js → responsiveObserve-CzzGt7GL.js} +1 -1
  145. package/src/assets/web-panel/assets/{slide-DO756sgI.js → slide-BaIK52yz.js} +1 -1
  146. package/src/assets/web-panel/assets/{statusUtils-BRQlIz28.js → statusUtils-3-FHu9_M.js} +1 -1
  147. package/src/assets/web-panel/assets/{styleChecker-DCSfdybl.js → styleChecker-BkRT68fK.js} +1 -1
  148. package/src/assets/web-panel/assets/{useFlexGapSupport-LD8dWVve.js → useFlexGapSupport-DHYwKS-s.js} +1 -1
  149. package/src/assets/web-panel/assets/{useFs-BX9uW2LK.js → useFs-DVVUhV8p.js} +1 -1
  150. package/src/assets/web-panel/assets/{usePersonalDataHub-BPSlPuHU.js → usePersonalDataHub-CkrFKAzQ.js} +1 -1
  151. package/src/assets/web-panel/assets/{vnode-BmOILC9V.js → vnode-BuBLFz0c.js} +1 -1
  152. package/src/assets/web-panel/assets/{zoom-1iKowKGg.js → zoom-kpm6LtXU.js} +1 -1
  153. package/src/assets/web-panel/index.html +1 -1
  154. package/src/command-help-index.json +3 -3
  155. package/src/commands/cowork.js +418 -41
  156. package/src/commands/permissions.js +240 -16
  157. package/src/commands/plugin.js +1293 -56
  158. package/src/commands/session-location.js +276 -0
  159. package/src/commands/session.js +2 -0
  160. package/src/data/changelog.json +28 -2
  161. package/src/gateways/ws/action-protocol.js +316 -17
  162. package/src/gateways/ws/message-dispatcher.js +30 -0
  163. package/src/gateways/ws/remote-session-protocol.js +565 -35
  164. package/src/gateways/ws/ws-agent-handler.js +12 -0
  165. package/src/gateways/ws/ws-approval-gate.js +5 -0
  166. package/src/gateways/ws/ws-server.js +510 -50
  167. package/src/harness/jsonl-session-store.js +341 -24
  168. package/src/harness/mcp-client.js +8 -1
  169. package/src/harness/remote-session-audit.js +2 -0
  170. package/src/harness/remote-session-crypto.js +929 -21
  171. package/src/harness/remote-session-registry.js +945 -24
  172. package/src/harness/session-list-index.js +233 -14
  173. package/src/lib/agent-authority.js +6 -0
  174. package/src/lib/auto-mode-config.js +98 -3
  175. package/src/lib/background-agent-keeper-client.js +248 -0
  176. package/src/lib/background-agent-keeper-protocol.js +291 -0
  177. package/src/lib/background-agent-supervisor.js +1357 -85
  178. package/src/lib/background-interaction-resolver.js +12 -0
  179. package/src/lib/background-session-transport.js +23 -6
  180. package/src/lib/background-turn-bootstrap-protocol.js +190 -0
  181. package/src/lib/cowork-workflow.js +1188 -76
  182. package/src/lib/delivery-production-adapter.js +38 -2
  183. package/src/lib/dynamic-workflow-facade.js +1736 -0
  184. package/src/lib/execution-location-contract.js +551 -0
  185. package/src/lib/execution-location-runtime.js +130 -0
  186. package/src/lib/ide-context.js +94 -6
  187. package/src/lib/mcp-stdio-package-materialization.js +166 -14
  188. package/src/lib/packer/pkg-config-generator.js +2 -0
  189. package/src/lib/permission-authority.js +77 -0
  190. package/src/lib/permission-side-effect-center.js +495 -0
  191. package/src/lib/plugin-runtime/install.js +514 -13
  192. package/src/lib/plugin-runtime/marketplace-artifact-readback.js +900 -0
  193. package/src/lib/plugin-runtime/marketplace-catalog.js +1181 -0
  194. package/src/lib/plugin-runtime/marketplace-impact.js +408 -0
  195. package/src/lib/plugin-runtime/marketplace-remote-artifacts.js +1567 -0
  196. package/src/lib/plugin-security.js +60 -3
  197. package/src/lib/process-execution-broker/index.js +1095 -57
  198. package/src/lib/process-execution-broker/linux-bwrap-descriptor-launch.js +375 -0
  199. package/src/lib/process-execution-broker/linux-generic-bwrap-runtime.js +90 -16
  200. package/src/lib/process-execution-broker/linux-generic-bwrap.js +159 -18
  201. package/src/lib/process-execution-broker/macos-mcp-launcher-contract.js +278 -0
  202. package/src/lib/process-execution-broker/macos-mcp-launcher-protocol.json +23 -0
  203. package/src/lib/process-execution-broker/macos-mcp-launcher.c +1497 -0
  204. package/src/lib/process-execution-broker/mcp-fd-entry-bootstrap.js +37 -0
  205. package/src/lib/process-execution-broker/platform-sandbox.js +2330 -279
  206. package/src/lib/process-execution-broker/windows-sandbox-helper.dll +0 -0
  207. package/src/lib/process-execution-broker/windows-sandbox-helper.exe +0 -0
  208. package/src/lib/process-execution-broker/windows-sandbox.cs +50 -4
  209. package/src/lib/public-ide-capability-manifest.js +3 -0
  210. package/src/lib/remote-approval-bridge.js +777 -34
  211. package/src/lib/remote-control.js +2 -0
  212. package/src/lib/remote-membership-authority.js +632 -0
  213. package/src/lib/remote-membership-coordinator.js +2973 -0
  214. package/src/lib/remote-membership-host-store.js +1799 -0
  215. package/src/lib/runtime-provenance-ledger.js +171 -46
  216. package/src/lib/scoped-permission-store.js +369 -0
  217. package/src/lib/session-anti-rollback-anchor.js +262 -5
  218. package/src/lib/shell-approval.js +169 -6
  219. package/src/lib/sub-agent-context.js +4 -0
  220. package/src/lib/with-file-lock.js +73 -38
  221. package/src/lib/workflow-definition-contract.js +149 -0
  222. package/src/repl/agent-repl.js +111 -36
  223. package/src/repl/chat-repl.js +2 -0
  224. package/src/repl/clipboard-image.js +735 -16
  225. package/src/repl/ide-status.js +1 -1
  226. package/src/repl/prompt-interactions.js +59 -6
  227. package/src/repl/remote-approval.js +29 -7
  228. package/src/runtime/agent-core.js +1182 -155
  229. package/src/runtime/headless-runner.js +52 -30
  230. package/src/runtime/headless-stream.js +51 -28
  231. package/src/workers/background-agent-keeper.js +689 -0
  232. package/src/workers/background-agent-worker.js +365 -13
  233. package/src/workers/background-turn-bootstrap.js +170 -0
  234. package/src/assets/web-panel/assets/MarkdownRenderer-yySN5YNM.js +0 -1
  235. package/src/assets/web-panel/assets/OrderTableRenderer-Bb1O3Ofr.js +0 -1
  236. package/src/assets/web-panel/assets/Projects-CMolGhae.js +0 -1
  237. package/src/assets/web-panel/assets/RemoteSession-Biyn2-Ro.js +0 -5
  238. package/src/assets/web-panel/assets/devWarning-S1ld2LwU.js +0 -1
  239. package/src/assets/web-panel/assets/index-Drz6yq0m.js +0 -1
  240. package/src/assets/web-panel/assets/index-uWiUs7S_.js +0 -1
@@ -0,0 +1,1736 @@
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";
4
+ import {
5
+ COWORK_WORKFLOW_RUN_RECORD_SCHEMA,
6
+ MAX_FAN_OUT,
7
+ executeWorkflow as executeCoworkWorkflow,
8
+ loopIterationCap,
9
+ planBatches,
10
+ resolveForEachItems,
11
+ shouldRunStep,
12
+ validateWorkflow,
13
+ } from "./cowork-workflow.js";
14
+ import {
15
+ EXECUTION_LOCATION,
16
+ normalizeExecutionLocation,
17
+ redactCredentialRefs,
18
+ } from "./execution-location.js";
19
+ import { normalizeExecutionLocationBinding } from "./execution-location-contract.js";
20
+ import {
21
+ COWORK_WORKFLOW_RECORD_SCHEMA,
22
+ WORKFLOW_DEFINITION_SCHEMA,
23
+ createWorkflowDefinitionAuthority,
24
+ normalizeWorkflowDefinitionDigest,
25
+ } from "./workflow-definition-contract.js";
26
+ import { canonicalJson } from "./scheduler-kernel/contract.js";
27
+
28
+ export const DYNAMIC_WORKFLOW_DEFINITION_SCHEMA = WORKFLOW_DEFINITION_SCHEMA;
29
+ export const DYNAMIC_WORKFLOW_PREFLIGHT_SCHEMA =
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";
45
+
46
+ export const DYNAMIC_WORKFLOW_ENGINE_CAPABILITIES = Object.freeze([
47
+ "condition",
48
+ "cowork-task",
49
+ "dag",
50
+ "for-each",
51
+ "loop",
52
+ "parallel",
53
+ "pipeline",
54
+ "retry",
55
+ "timeout",
56
+ "variables",
57
+ ]);
58
+
59
+ const CAPABILITY_SET = new Set(DYNAMIC_WORKFLOW_ENGINE_CAPABILITIES);
60
+ const FORBIDDEN_CREDENTIAL_KEYS = new Set([
61
+ "accesstoken",
62
+ "apikey",
63
+ "authorization",
64
+ "bearer",
65
+ "clientsecret",
66
+ "credentialvalue",
67
+ "key",
68
+ "password",
69
+ "privatekey",
70
+ "secret",
71
+ "token",
72
+ "value",
73
+ ]);
74
+ const CREDENTIAL_SOURCES = new Set([
75
+ "config",
76
+ "env",
77
+ "environment",
78
+ "keychain",
79
+ "local-provider",
80
+ "managed-secret",
81
+ "none",
82
+ "not-observed",
83
+ "unknown",
84
+ ]);
85
+ const DATA_BOUNDARY_KINDS = new Set([
86
+ "declared",
87
+ "repository",
88
+ "working-directory",
89
+ ]);
90
+ const SANDBOX_RANK = Object.freeze({ none: 0, partial: 1, strong: 2 });
91
+ const DEFAULT_SOFT_TASK_GUIDELINE = 16;
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
+ }
352
+
353
+ function safeString(value, max = 256) {
354
+ if (typeof value !== "string") return null;
355
+ const output = value.trim();
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) {
365
+ return null;
366
+ }
367
+ return output;
368
+ }
369
+
370
+ function finiteNumber(value, { integer = false, min = 0 } = {}) {
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;
378
+ if (!Number.isFinite(output) || output < min) return null;
379
+ if (integer && !Number.isSafeInteger(output)) return null;
380
+ return output;
381
+ }
382
+
383
+ function uniqueNames(values) {
384
+ const output = [];
385
+ for (const value of Array.isArray(values) ? values : []) {
386
+ const name = safeString(value, 64)?.toLowerCase();
387
+ if (name && /^[a-z0-9_.:-]+$/u.test(name) && !output.includes(name)) {
388
+ output.push(name);
389
+ }
390
+ }
391
+ return output.sort();
392
+ }
393
+
394
+ function usedCapabilities(workflow, batches) {
395
+ const capabilities = new Set(["cowork-task", "dag", "variables"]);
396
+ if (batches.some((batch) => batch.steps.length > 1)) {
397
+ capabilities.add("parallel");
398
+ }
399
+ if (workflow.pipeline === true) capabilities.add("pipeline");
400
+ for (const step of workflow.steps) {
401
+ if (step.when != null) capabilities.add("condition");
402
+ if (step.forEach != null) {
403
+ capabilities.add("for-each");
404
+ capabilities.add("parallel");
405
+ }
406
+ if (step.loopWhile != null || step.loopUntil != null)
407
+ capabilities.add("loop");
408
+ if (Number(step.retries) > 0) capabilities.add("retry");
409
+ if (Number(step.timeoutMs) > 0) capabilities.add("timeout");
410
+ }
411
+ return [...capabilities].sort();
412
+ }
413
+
414
+ function stepProjection(step) {
415
+ const retries =
416
+ step.retries == null
417
+ ? 0
418
+ : finiteNumber(step.retries, { integer: true, min: 0 });
419
+ if (retries == null || retries >= Number.MAX_SAFE_INTEGER) {
420
+ throw new TypeError(
421
+ `workflow step '${step.id}' retries exceed safe projection limits`,
422
+ );
423
+ }
424
+ const attempts = retries + 1;
425
+ let expansion = 1;
426
+ let expansionKnown = true;
427
+ let expansionSource = "single";
428
+ if (Array.isArray(step.forEach)) {
429
+ if (step.forEach.length > MAX_FAN_OUT) {
430
+ throw new TypeError(
431
+ `workflow step '${step.id}' exceeds MAX_FAN_OUT=${MAX_FAN_OUT}`,
432
+ );
433
+ }
434
+ expansion = step.forEach.length;
435
+ expansionSource = "literal-for-each";
436
+ } else if (typeof step.forEach === "string") {
437
+ expansion = null;
438
+ expansionKnown = false;
439
+ expansionSource = "runtime-for-each";
440
+ } else if (step.loopWhile != null || step.loopUntil != null) {
441
+ expansion = loopIterationCap(step);
442
+ expansionSource = "loop-cap";
443
+ }
444
+ return Object.freeze({
445
+ id: step.id,
446
+ dependencies: Object.freeze([...(step.dependsOn || [])].sort()),
447
+ attemptsPerTask: attempts,
448
+ expansion,
449
+ expansionKnown,
450
+ expansionSource,
451
+ worstCaseTaskCalls: expansionKnown ? expansion * attempts : null,
452
+ worstCaseDurationSlots: expansionKnown
453
+ ? expansionSource === "literal-for-each"
454
+ ? expansion === 0
455
+ ? 0
456
+ : attempts
457
+ : expansion * attempts
458
+ : null,
459
+ });
460
+ }
461
+
462
+ function containsCredentialValue(value, seen = new Set()) {
463
+ if (!value || typeof value !== "object") return false;
464
+ if (seen.has(value)) return true;
465
+ seen.add(value);
466
+ for (const [key, child] of Object.entries(value)) {
467
+ const normalizedKey = key.toLowerCase().replace(/[^a-z0-9]/gu, "");
468
+ if (FORBIDDEN_CREDENTIAL_KEYS.has(normalizedKey) && child != null) {
469
+ return true;
470
+ }
471
+ if (containsCredentialValue(child, seen)) return true;
472
+ }
473
+ return false;
474
+ }
475
+
476
+ function normalizeGovernance(workflow) {
477
+ const facade =
478
+ workflow.facade && typeof workflow.facade === "object"
479
+ ? workflow.facade
480
+ : {};
481
+ const requirements =
482
+ facade.requirements && typeof facade.requirements === "object"
483
+ ? facade.requirements
484
+ : {};
485
+ const rawCredentials = Array.isArray(requirements.credentials)
486
+ ? requirements.credentials
487
+ : [];
488
+ const credentialValuePresent = containsCredentialValue(rawCredentials);
489
+ const redactedCredentials = credentialValuePresent
490
+ ? []
491
+ : redactCredentialRefs(rawCredentials).map((credential) => {
492
+ const source = safeString(credential.source)?.toLowerCase();
493
+ return Object.freeze({
494
+ name: safeString(credential.name),
495
+ source: CREDENTIAL_SOURCES.has(source) ? source : "unknown",
496
+ scope: safeString(credential.scope),
497
+ });
498
+ });
499
+ const credentialKeys = redactedCredentials.map(
500
+ (credential) =>
501
+ `${credential.name || ""}\u0000${credential.source}\u0000${credential.scope || ""}`,
502
+ );
503
+ const credentialDeclarationInvalid =
504
+ !credentialValuePresent &&
505
+ (redactedCredentials.length !== rawCredentials.length ||
506
+ redactedCredentials.some(
507
+ (credential) =>
508
+ !credential.name ||
509
+ ["none", "not-observed", "unknown"].includes(credential.source),
510
+ ) ||
511
+ new Set(credentialKeys).size !== credentialKeys.length);
512
+ const credentials = credentialDeclarationInvalid ? [] : redactedCredentials;
513
+ const rawCapabilities = Array.isArray(requirements.capabilities)
514
+ ? requirements.capabilities
515
+ : [];
516
+ const capabilities = uniqueNames(rawCapabilities);
517
+ const rawLocations = Array.isArray(requirements.executionLocations)
518
+ ? requirements.executionLocations
519
+ : [];
520
+ const executionLocations = [
521
+ ...new Set(
522
+ uniqueNames(rawLocations)
523
+ .map(normalizeExecutionLocation)
524
+ .filter((location) => location !== EXECUTION_LOCATION.UNKNOWN),
525
+ ),
526
+ ].sort();
527
+ const permissionInput =
528
+ requirements.permissions && typeof requirements.permissions === "object"
529
+ ? requirements.permissions
530
+ : null;
531
+ const permissionDeclarationInvalid =
532
+ permissionInput != null &&
533
+ (!Object.hasOwn(permissionInput, "file") ||
534
+ !["none", "read", "write"].includes(permissionInput.file) ||
535
+ ["shell", "network", "mcp", "externalSystems"].some(
536
+ (key) =>
537
+ Object.hasOwn(permissionInput, key) &&
538
+ typeof permissionInput[key] !== "boolean",
539
+ ));
540
+ const permissions = permissionInput
541
+ ? Object.freeze({
542
+ file: ["none", "read", "write"].includes(permissionInput.file)
543
+ ? permissionInput.file
544
+ : null,
545
+ shell: permissionInput.shell === true,
546
+ network: permissionInput.network === true,
547
+ mcp: permissionInput.mcp === true,
548
+ externalSystems: permissionInput.externalSystems === true,
549
+ })
550
+ : null;
551
+ const sandbox = ["none", "partial", "strong"].includes(requirements.sandbox)
552
+ ? requirements.sandbox
553
+ : null;
554
+ const estimatesInput =
555
+ facade.estimates && typeof facade.estimates === "object"
556
+ ? facade.estimates
557
+ : {};
558
+ const budgetInput =
559
+ facade.budget && typeof facade.budget === "object" ? facade.budget : {};
560
+ return Object.freeze({
561
+ requirements: Object.freeze({
562
+ capabilities: Object.freeze(capabilities),
563
+ capabilityDeclarationInvalid:
564
+ rawCapabilities.length !== capabilities.length,
565
+ executionLocations: Object.freeze(executionLocations),
566
+ executionLocationDeclarationInvalid:
567
+ rawLocations.length !== executionLocations.length,
568
+ permissions,
569
+ permissionDeclarationInvalid,
570
+ sandbox,
571
+ dataBoundary: DATA_BOUNDARY_KINDS.has(requirements.dataBoundary)
572
+ ? requirements.dataBoundary
573
+ : null,
574
+ credentials: Object.freeze(credentials),
575
+ credentialValuePresent,
576
+ credentialDeclarationInvalid,
577
+ }),
578
+ estimates: Object.freeze({
579
+ tokensPerTask: finiteNumber(estimatesInput.tokensPerTask, {
580
+ integer: true,
581
+ min: 1,
582
+ }),
583
+ usdPerTask: finiteNumber(estimatesInput.usdPerTask, { min: 0 }),
584
+ durationMsPerTask: finiteNumber(estimatesInput.durationMsPerTask, {
585
+ integer: true,
586
+ min: 1,
587
+ }),
588
+ }),
589
+ budget: Object.freeze({
590
+ maxExpandedTasks: finiteNumber(budgetInput.maxExpandedTasks, {
591
+ integer: true,
592
+ min: 1,
593
+ }),
594
+ maxParallel: finiteNumber(budgetInput.maxParallel, {
595
+ integer: true,
596
+ min: 1,
597
+ }),
598
+ maxTokens: finiteNumber(budgetInput.maxTokens, {
599
+ integer: true,
600
+ min: 1,
601
+ }),
602
+ maxUsd: finiteNumber(budgetInput.maxUsd, { min: 0 }),
603
+ maxDurationMs: finiteNumber(budgetInput.maxDurationMs, {
604
+ integer: true,
605
+ min: 1,
606
+ }),
607
+ }),
608
+ });
609
+ }
610
+
611
+ export function createDynamicWorkflowManifest(workflow) {
612
+ const validation = validateWorkflow(workflow);
613
+ if (!validation.valid) {
614
+ throw new TypeError(`Invalid workflow: ${validation.errors.join("; ")}`);
615
+ }
616
+ const governance = normalizeGovernance(workflow);
617
+ if (governance.requirements.credentialValuePresent) {
618
+ throw new TypeError(
619
+ "workflow credential requirements must not contain values",
620
+ );
621
+ }
622
+ const authority = createWorkflowDefinitionAuthority(workflow);
623
+ const definition = authority.definition;
624
+ const batches = planBatches(workflow.steps).map((batch, index) =>
625
+ Object.freeze({
626
+ index,
627
+ steps: Object.freeze(batch.map((step) => step.id)),
628
+ }),
629
+ );
630
+ const steps = workflow.steps.map(stepProjection);
631
+ const expansionKnown = steps.every((step) => step.expansionKnown);
632
+ const worstCaseTaskCalls = expansionKnown
633
+ ? steps.reduce((total, step) => total + step.worstCaseTaskCalls, 0)
634
+ : null;
635
+ if (worstCaseTaskCalls != null && !Number.isSafeInteger(worstCaseTaskCalls)) {
636
+ throw new TypeError("workflow task-call projection exceeds safe limits");
637
+ }
638
+ return Object.freeze({
639
+ schema: DYNAMIC_WORKFLOW_DEFINITION_SCHEMA,
640
+ adapter: "cowork-workflow",
641
+ definitionDigest: authority.definitionDigest,
642
+ definition,
643
+ engineCapabilities: DYNAMIC_WORKFLOW_ENGINE_CAPABILITIES,
644
+ usedCapabilities: Object.freeze(usedCapabilities(workflow, batches)),
645
+ plan: Object.freeze({
646
+ mode: workflow.pipeline === true ? "pipeline" : "batched-dag",
647
+ batches: Object.freeze(batches),
648
+ steps: Object.freeze(steps),
649
+ expansionKnown,
650
+ worstCaseTaskCalls,
651
+ }),
652
+ governance,
653
+ runtimeClaims: Object.freeze({
654
+ durablePauseResume: false,
655
+ exactlyOnceAfterResume: false,
656
+ historyDurability: "best-effort",
657
+ needsInputBetweenStages: false,
658
+ }),
659
+ });
660
+ }
661
+
662
+ function addUnique(output, value) {
663
+ if (!output.includes(value)) output.push(value);
664
+ }
665
+
666
+ function permissionsCover(actual, required) {
667
+ if (!actual || !required) return false;
668
+ const fileRank = { none: 0, read: 1, write: 2 };
669
+ if ((fileRank[actual.file] ?? -1) < (fileRank[required.file] ?? -1)) {
670
+ return false;
671
+ }
672
+ for (const key of ["shell", "network", "mcp", "externalSystems"]) {
673
+ if (required[key] === true && actual[key] !== true) return false;
674
+ }
675
+ return true;
676
+ }
677
+
678
+ function credentialsCover(actual, required) {
679
+ const available = Array.isArray(actual) ? actual : [];
680
+ return required.filter(
681
+ (credential) =>
682
+ !available.some(
683
+ (candidate) =>
684
+ candidate.name === credential.name &&
685
+ candidate.source === credential.source &&
686
+ (credential.scope == null || candidate.scope === credential.scope),
687
+ ),
688
+ );
689
+ }
690
+
691
+ function projectedDurationSlots(plan, requestedParallel) {
692
+ if (!plan.expansionKnown || requestedParallel == null) return null;
693
+ const byId = new Map(plan.steps.map((step) => [step.id, step]));
694
+ let total = 0;
695
+ for (const batch of plan.batches) {
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;
709
+ }
710
+ return total;
711
+ }
712
+
713
+ function multiplyProjection(...values) {
714
+ if (values.some((value) => value == null)) return null;
715
+ const product = values.reduce((total, value) => total * value, 1);
716
+ return Number.isFinite(product) && product <= Number.MAX_SAFE_INTEGER
717
+ ? product
718
+ : null;
719
+ }
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 = authority.authority === "verified-session-start";
791
+ if (!verified) {
792
+ throw admissionError(
793
+ code,
794
+ "executionLocationAuthority must be a verified session start",
795
+ );
796
+ }
797
+ let binding;
798
+ try {
799
+ const bindingSnapshot = snapshotCanonicalValue(
800
+ authority.binding,
801
+ code,
802
+ "executionLocationAuthority.binding",
803
+ );
804
+ binding = normalizeExecutionLocationBinding(bindingSnapshot);
805
+ if (
806
+ canonicalJson(bindingSnapshot, "executionLocationAuthority.binding") !==
807
+ canonicalJson(binding, "executionLocationAuthority.binding")
808
+ ) {
809
+ throw new TypeError("binding is not canonical");
810
+ }
811
+ } catch {
812
+ throw admissionError(
813
+ code,
814
+ "executionLocationAuthority binding is invalid or non-canonical",
815
+ );
816
+ }
817
+ if (binding.observed !== true || !canonicalObservedAt(binding.observedAt)) {
818
+ throw admissionError(
819
+ code,
820
+ "executionLocationAuthority binding is not an observed instant",
821
+ );
822
+ }
823
+
824
+ const sessionId = safeString(authority.sessionId);
825
+ if (
826
+ sessionId !== authority.sessionId ||
827
+ !/^[a-f0-9]{64}$/u.test(authority.headHash) ||
828
+ !Number.isSafeInteger(authority.eventCount) ||
829
+ authority.eventCount < 1
830
+ ) {
831
+ throw admissionError(
832
+ code,
833
+ "executionLocationAuthority session proof is invalid",
834
+ );
835
+ }
836
+ return Object.freeze({
837
+ schema: SESSION_EXECUTION_LOCATION_AUTHORITY_SCHEMA,
838
+ authority: "verified-session-start",
839
+ sessionId,
840
+ headHash: authority.headHash,
841
+ eventCount: authority.eventCount,
842
+ binding,
843
+ });
844
+ }
845
+
846
+ function pathWithinDataBoundary(cwd, boundary) {
847
+ const root = boundary?.root;
848
+ if (typeof cwd !== "string" || typeof root !== "string") return false;
849
+ const windowsPath =
850
+ /^[A-Za-z]:[\\/]/u.test(root) ||
851
+ root.startsWith("\\\\") ||
852
+ /^[A-Za-z]:[\\/]/u.test(cwd) ||
853
+ cwd.startsWith("\\\\");
854
+ const paths = windowsPath ? win32Path : posixPath;
855
+ if (!paths.isAbsolute(root) || !paths.isAbsolute(cwd)) return false;
856
+ const relative = paths.relative(paths.normalize(root), paths.normalize(cwd));
857
+ return (
858
+ relative === "" ||
859
+ (relative !== ".." &&
860
+ !relative.startsWith(`..${paths.sep}`) &&
861
+ !paths.isAbsolute(relative))
862
+ );
863
+ }
864
+
865
+ function normalizeExecutionOptions(value, definition, executionAuthority) {
866
+ const code = DYNAMIC_WORKFLOW_EXECUTION_OPTIONS_INVALID_CODE;
867
+ const execution =
868
+ value == null
869
+ ? Object.freeze({})
870
+ : snapshotObjectFields(
871
+ value,
872
+ EXECUTION_OPTION_FIELDS,
873
+ code,
874
+ "execution",
875
+ { exact: false },
876
+ );
877
+ if (Object.hasOwn(execution, "llmOptions")) {
878
+ throw admissionError(
879
+ code,
880
+ "execution.llmOptions is not admitted; use the verified model binding",
881
+ );
882
+ }
883
+
884
+ for (const callback of ["onStepStart", "onStepComplete"]) {
885
+ if (
886
+ Object.hasOwn(execution, callback) &&
887
+ (typeof execution[callback] !== "function" ||
888
+ utilTypes.isProxy(execution[callback]))
889
+ ) {
890
+ throw admissionError(code, `execution.${callback} must be a function`);
891
+ }
892
+ }
893
+ if (
894
+ Object.hasOwn(execution, "continueOnError") &&
895
+ typeof execution.continueOnError !== "boolean"
896
+ ) {
897
+ throw admissionError(code, "execution.continueOnError must be a boolean");
898
+ }
899
+
900
+ const binding = executionAuthority.binding;
901
+ const cwd = binding.source.cwd;
902
+ const dataBoundary = binding.policy.dataBoundary;
903
+ if (!pathWithinDataBoundary(cwd, dataBoundary)) {
904
+ throw admissionError(
905
+ DYNAMIC_WORKFLOW_EXECUTION_AUTHORITY_INVALID_CODE,
906
+ "verified execution cwd is outside its data boundary",
907
+ );
908
+ }
909
+ const policy = Object.freeze({
910
+ cwd,
911
+ continueOnError: execution.continueOnError ?? false,
912
+ pipeline: definition.pipeline === true,
913
+ provider: binding.model.provider,
914
+ model: binding.model.name,
915
+ });
916
+ for (const field of ["cwd", "pipeline", "provider", "model"]) {
917
+ if (Object.hasOwn(execution, field) && execution[field] !== policy[field]) {
918
+ throw admissionError(
919
+ code,
920
+ `execution.${field} does not match verified authority`,
921
+ );
922
+ }
923
+ }
924
+
925
+ return Object.freeze({
926
+ policy,
927
+ onStepStart: execution.onStepStart,
928
+ onStepComplete: execution.onStepComplete,
929
+ });
930
+ }
931
+
932
+ function normalizeRunInput(input) {
933
+ const code = DYNAMIC_WORKFLOW_EXECUTION_AUTHORITY_INVALID_CODE;
934
+ const snapshot = snapshotObjectFields(
935
+ input,
936
+ RUN_INPUT_FIELDS,
937
+ code,
938
+ "dynamicWorkflowRun",
939
+ { exact: false },
940
+ );
941
+ if (
942
+ !Object.hasOwn(snapshot, "definitionAuthority") ||
943
+ !Object.hasOwn(snapshot, "executionAuthoritySessionId")
944
+ ) {
945
+ throw admissionError(
946
+ code,
947
+ "definitionAuthority and executionAuthoritySessionId are required",
948
+ );
949
+ }
950
+ const executionAuthoritySessionId = safeString(
951
+ snapshot.executionAuthoritySessionId,
952
+ );
953
+ if (executionAuthoritySessionId !== snapshot.executionAuthoritySessionId) {
954
+ throw admissionError(code, "executionAuthoritySessionId is invalid");
955
+ }
956
+ if (
957
+ Object.hasOwn(snapshot, "onAdmitted") &&
958
+ (typeof snapshot.onAdmitted !== "function" ||
959
+ utilTypes.isProxy(snapshot.onAdmitted))
960
+ ) {
961
+ throw admissionError(
962
+ DYNAMIC_WORKFLOW_EXECUTION_OPTIONS_INVALID_CODE,
963
+ "onAdmitted must be a function",
964
+ );
965
+ }
966
+ const definitionAuthority = normalizeDefinitionAuthorityForRun(
967
+ snapshot.definitionAuthority,
968
+ );
969
+ return Object.freeze({
970
+ definitionAuthority,
971
+ executionAuthoritySessionId,
972
+ maxParallel: snapshot.maxParallel,
973
+ execution: snapshot.execution,
974
+ onAdmitted: snapshot.onAdmitted,
975
+ });
976
+ }
977
+
978
+ function normalizeRunDependencies(deps) {
979
+ const code = DYNAMIC_WORKFLOW_EXECUTION_AUTHORITY_INVALID_CODE;
980
+ const snapshot = snapshotObjectFields(
981
+ deps,
982
+ RUN_DEPENDENCY_FIELDS,
983
+ code,
984
+ "dynamicWorkflowRunDependencies",
985
+ { exact: false },
986
+ );
987
+ if (
988
+ typeof snapshot.verifyAuthorities !== "function" ||
989
+ utilTypes.isProxy(snapshot.verifyAuthorities)
990
+ ) {
991
+ throw admissionError(code, "verifyAuthorities dependency is required");
992
+ }
993
+ if (
994
+ Object.hasOwn(snapshot, "executeWorkflow") &&
995
+ (typeof snapshot.executeWorkflow !== "function" ||
996
+ utilTypes.isProxy(snapshot.executeWorkflow))
997
+ ) {
998
+ throw admissionError(
999
+ DYNAMIC_WORKFLOW_EXECUTION_OPTIONS_INVALID_CODE,
1000
+ "executeWorkflow dependency must be a function",
1001
+ );
1002
+ }
1003
+ return snapshot;
1004
+ }
1005
+
1006
+ function authorityLookup(runInput) {
1007
+ return Object.freeze({
1008
+ workflowId: runInput.definitionAuthority.definition.id,
1009
+ definitionDigest: runInput.definitionAuthority.definitionDigest,
1010
+ executionAuthoritySessionId: runInput.executionAuthoritySessionId,
1011
+ });
1012
+ }
1013
+
1014
+ function normalizeVerifiedAuthorities(value, runInput) {
1015
+ const code = DYNAMIC_WORKFLOW_EXECUTION_AUTHORITY_INVALID_CODE;
1016
+ const snapshot = snapshotObjectFields(
1017
+ value,
1018
+ VERIFIED_AUTHORITIES_FIELDS,
1019
+ code,
1020
+ "verifiedAuthorities",
1021
+ );
1022
+ const definitionAuthority = normalizeDefinitionAuthorityForRun(
1023
+ snapshot.definitionAuthority,
1024
+ );
1025
+ const executionLocationAuthority = normalizeSessionExecutionLocationAuthority(
1026
+ snapshot.executionLocationAuthority,
1027
+ );
1028
+ if (
1029
+ canonicalJson(definitionAuthority, "verifiedDefinitionAuthority") !==
1030
+ canonicalJson(runInput.definitionAuthority, "inputDefinitionAuthority")
1031
+ ) {
1032
+ throw admissionError(
1033
+ code,
1034
+ "verified definition authority does not exactly match the requested record",
1035
+ );
1036
+ }
1037
+ if (
1038
+ executionLocationAuthority.sessionId !==
1039
+ runInput.executionAuthoritySessionId
1040
+ ) {
1041
+ throw admissionError(
1042
+ code,
1043
+ "verified execution authority does not match the requested session",
1044
+ );
1045
+ }
1046
+ return Object.freeze({ definitionAuthority, executionLocationAuthority });
1047
+ }
1048
+
1049
+ function verifyAuthoritiesSynchronously(verifier, lookup, runInput) {
1050
+ let verified;
1051
+ try {
1052
+ verified = verifier(lookup);
1053
+ } catch {
1054
+ throw admissionError(
1055
+ DYNAMIC_WORKFLOW_EXECUTION_AUTHORITY_INVALID_CODE,
1056
+ "authority verification failed",
1057
+ );
1058
+ }
1059
+ if (utilTypes.isPromise(verified)) {
1060
+ throw admissionError(
1061
+ DYNAMIC_WORKFLOW_EXECUTION_AUTHORITY_INVALID_CODE,
1062
+ "buildDynamicWorkflowRunAdmission requires a synchronous authority verifier",
1063
+ );
1064
+ }
1065
+ return normalizeVerifiedAuthorities(verified, runInput);
1066
+ }
1067
+
1068
+ async function verifyAuthoritiesAsynchronously(verifier, lookup, runInput) {
1069
+ let verified;
1070
+ try {
1071
+ verified = await verifier(lookup);
1072
+ } catch {
1073
+ throw admissionError(
1074
+ DYNAMIC_WORKFLOW_EXECUTION_AUTHORITY_INVALID_CODE,
1075
+ "authority verification failed",
1076
+ );
1077
+ }
1078
+ return normalizeVerifiedAuthorities(verified, runInput);
1079
+ }
1080
+
1081
+ function authoritiesExactlyMatch(left, right) {
1082
+ return (
1083
+ canonicalJson(left, "firstVerifiedAuthorities") ===
1084
+ canonicalJson(right, "finalVerifiedAuthorities")
1085
+ );
1086
+ }
1087
+
1088
+ function blockedError(preflight) {
1089
+ return Object.freeze({
1090
+ name: "DynamicWorkflowAdmissionError",
1091
+ code: DYNAMIC_WORKFLOW_PREFLIGHT_BLOCKED_CODE,
1092
+ message: "dynamic workflow execution was blocked by preflight",
1093
+ details: Object.freeze({ blockers: preflight.blockers }),
1094
+ });
1095
+ }
1096
+
1097
+ function prepareDynamicWorkflowRun(runInput, verifiedAuthorities, execution) {
1098
+ const { definitionAuthority, executionLocationAuthority } =
1099
+ verifiedAuthorities;
1100
+ const workflow = definitionAuthority.definition;
1101
+ const preflight = buildDynamicWorkflowPreflight({
1102
+ workflow,
1103
+ definitionAuthority,
1104
+ executionLocation: executionLocationAuthority.binding,
1105
+ maxParallel: runInput.maxParallel,
1106
+ requireDefinitionAuthority: true,
1107
+ });
1108
+ const executionLocationDigest = domainSeparatedDigest(
1109
+ "chainlesschain.dynamic-workflow.execution-location.v1\0",
1110
+ executionLocationAuthority,
1111
+ "executionLocationAuthority",
1112
+ );
1113
+ const preflightDigest = domainSeparatedDigest(
1114
+ "chainlesschain.dynamic-workflow.preflight.v1\0",
1115
+ preflight,
1116
+ "dynamicWorkflowPreflight",
1117
+ );
1118
+
1119
+ if (!preflight.allowed) {
1120
+ return Object.freeze({
1121
+ workflow: definitionAuthority.definition,
1122
+ outcome: Object.freeze({
1123
+ allowed: false,
1124
+ admission: null,
1125
+ preflight,
1126
+ definitionDigest: preflight.definition.definitionDigest,
1127
+ executionLocationDigest,
1128
+ preflightDigest,
1129
+ admissionDigest: null,
1130
+ authorityVerified: true,
1131
+ error: blockedError(preflight),
1132
+ }),
1133
+ });
1134
+ }
1135
+
1136
+ const admissionMaterial = Object.freeze({
1137
+ schema: DYNAMIC_WORKFLOW_RUN_ADMISSION_SCHEMA,
1138
+ definition: Object.freeze({
1139
+ schema: preflight.definition.schema,
1140
+ definitionDigest: preflight.definition.definitionDigest,
1141
+ authority: preflight.definition.authority,
1142
+ }),
1143
+ executionLocation: Object.freeze({
1144
+ authoritySchema: executionLocationAuthority.schema,
1145
+ authority: executionLocationAuthority.authority,
1146
+ session:
1147
+ executionLocationAuthority.authority === "verified-session-start"
1148
+ ? Object.freeze({
1149
+ sessionId: executionLocationAuthority.sessionId,
1150
+ headHash: executionLocationAuthority.headHash,
1151
+ eventCount: executionLocationAuthority.eventCount,
1152
+ })
1153
+ : null,
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
+
1508
+ export function buildDynamicWorkflowPreflight(input = {}) {
1509
+ const suppliedManifest =
1510
+ input.manifest?.schema === DYNAMIC_WORKFLOW_DEFINITION_SCHEMA
1511
+ ? input.manifest
1512
+ : null;
1513
+ const manifest = createDynamicWorkflowManifest(
1514
+ input.workflow || suppliedManifest?.definition,
1515
+ );
1516
+ const binding = normalizeExecutionLocationBinding(input.executionLocation);
1517
+ const governance = manifest.governance;
1518
+ const requirements = governance.requirements;
1519
+ const estimates = governance.estimates;
1520
+ const budget = governance.budget;
1521
+ const blockers = [];
1522
+ const warnings = [];
1523
+ const definitionAuthority = input.definitionAuthority
1524
+ ? Object.freeze({
1525
+ status:
1526
+ input.definitionAuthority.status === "versioned"
1527
+ ? "versioned"
1528
+ : "legacy-unversioned",
1529
+ recordSchema: safeString(input.definitionAuthority.recordSchema),
1530
+ definitionSchema: safeString(
1531
+ input.definitionAuthority.definitionSchema,
1532
+ ),
1533
+ definitionDigest: normalizeWorkflowDefinitionDigest(
1534
+ input.definitionAuthority.definitionDigest,
1535
+ ),
1536
+ })
1537
+ : null;
1538
+
1539
+ if (input.requireDefinitionAuthority === true && !definitionAuthority) {
1540
+ addUnique(blockers, "definition-authority-missing");
1541
+ }
1542
+
1543
+ if (
1544
+ suppliedManifest &&
1545
+ suppliedManifest.definitionDigest !== manifest.definitionDigest
1546
+ ) {
1547
+ addUnique(blockers, "definition-digest-mismatch");
1548
+ }
1549
+ if (definitionAuthority) {
1550
+ if (definitionAuthority.status !== "versioned") {
1551
+ addUnique(blockers, "definition-authority-unversioned");
1552
+ }
1553
+ if (
1554
+ definitionAuthority.recordSchema !== COWORK_WORKFLOW_RECORD_SCHEMA ||
1555
+ definitionAuthority.definitionSchema !== manifest.schema ||
1556
+ definitionAuthority.definitionDigest !== manifest.definitionDigest
1557
+ ) {
1558
+ addUnique(blockers, "definition-authority-mismatch");
1559
+ }
1560
+ }
1561
+
1562
+ if (requirements.capabilities.length === 0) {
1563
+ addUnique(blockers, "required-capabilities-missing");
1564
+ }
1565
+ if (requirements.capabilityDeclarationInvalid) {
1566
+ addUnique(blockers, "capability-declaration-invalid");
1567
+ }
1568
+ for (const capability of requirements.capabilities) {
1569
+ if (!CAPABILITY_SET.has(capability)) {
1570
+ addUnique(blockers, `unsupported-capability:${capability}`);
1571
+ }
1572
+ }
1573
+ for (const capability of manifest.usedCapabilities) {
1574
+ if (!requirements.capabilities.includes(capability)) {
1575
+ addUnique(blockers, `undeclared-capability:${capability}`);
1576
+ }
1577
+ }
1578
+ if (requirements.executionLocations.length === 0) {
1579
+ addUnique(blockers, "execution-locations-missing");
1580
+ } else if (requirements.executionLocationDeclarationInvalid) {
1581
+ addUnique(blockers, "execution-location-declaration-invalid");
1582
+ } else if (!requirements.executionLocations.includes(binding.location)) {
1583
+ addUnique(blockers, `execution-location-not-allowed:${binding.location}`);
1584
+ }
1585
+ if (!requirements.permissions) {
1586
+ addUnique(blockers, "permission-requirements-missing");
1587
+ } else if (requirements.permissionDeclarationInvalid) {
1588
+ addUnique(blockers, "permission-requirements-invalid");
1589
+ } else if (binding.permissions.status !== "declared") {
1590
+ addUnique(blockers, "environment-permissions-not-observed");
1591
+ } else if (!permissionsCover(binding.permissions, requirements.permissions)) {
1592
+ addUnique(blockers, "environment-permissions-insufficient");
1593
+ }
1594
+ if (requirements.permissions?.network === true) {
1595
+ if (binding.policy.network === "unknown") {
1596
+ addUnique(blockers, "environment-network-policy-unknown");
1597
+ } else if (binding.policy.network === "offline") {
1598
+ addUnique(blockers, "environment-network-policy-insufficient");
1599
+ }
1600
+ }
1601
+ if (!requirements.sandbox) {
1602
+ addUnique(blockers, "sandbox-requirement-missing");
1603
+ } else if (!(binding.policy.sandbox in SANDBOX_RANK)) {
1604
+ addUnique(blockers, "environment-sandbox-unknown");
1605
+ } else if (
1606
+ SANDBOX_RANK[binding.policy.sandbox] < SANDBOX_RANK[requirements.sandbox]
1607
+ ) {
1608
+ addUnique(blockers, "environment-sandbox-insufficient");
1609
+ }
1610
+ if (requirements.credentialValuePresent) {
1611
+ addUnique(blockers, "credential-value-present");
1612
+ }
1613
+ if (requirements.credentialDeclarationInvalid) {
1614
+ addUnique(blockers, "credential-declaration-invalid");
1615
+ } else {
1616
+ for (const credential of credentialsCover(
1617
+ binding.credentials,
1618
+ requirements.credentials,
1619
+ )) {
1620
+ addUnique(blockers, `environment-credential-missing:${credential.name}`);
1621
+ }
1622
+ }
1623
+ if (!requirements.dataBoundary) {
1624
+ addUnique(blockers, "data-boundary-requirement-missing");
1625
+ } else if (binding.policy.dataBoundary.kind === "unknown") {
1626
+ addUnique(blockers, "environment-data-boundary-unknown");
1627
+ } else if (binding.policy.dataBoundary.kind !== requirements.dataBoundary) {
1628
+ addUnique(blockers, "environment-data-boundary-mismatch");
1629
+ }
1630
+
1631
+ if (!manifest.plan.expansionKnown) {
1632
+ addUnique(blockers, "runtime-expansion-unknown");
1633
+ }
1634
+ const taskCalls = manifest.plan.worstCaseTaskCalls;
1635
+ const hardLimit = Math.min(
1636
+ budget.maxExpandedTasks ?? DEFAULT_HARD_TASK_LIMIT,
1637
+ DEFAULT_HARD_TASK_LIMIT,
1638
+ );
1639
+ if (budget.maxExpandedTasks > DEFAULT_HARD_TASK_LIMIT) {
1640
+ addUnique(blockers, "expanded-task-budget-exceeds-engine-limit");
1641
+ }
1642
+ if (taskCalls != null && taskCalls > hardLimit) {
1643
+ addUnique(blockers, "expanded-task-budget-exceeded");
1644
+ } else if (taskCalls != null && taskCalls > DEFAULT_SOFT_TASK_GUIDELINE) {
1645
+ warnings.push("expanded task count exceeds the soft size guideline");
1646
+ }
1647
+ const requestedParallel = finiteNumber(input.maxParallel ?? 4, {
1648
+ integer: true,
1649
+ min: 1,
1650
+ });
1651
+ if (requestedParallel == null) {
1652
+ addUnique(blockers, "requested-parallel-invalid");
1653
+ } else if (requestedParallel > DEFAULT_HARD_TASK_LIMIT) {
1654
+ addUnique(blockers, "requested-parallel-exceeds-engine-limit");
1655
+ }
1656
+ if (budget.maxParallel == null) {
1657
+ addUnique(blockers, "parallel-budget-missing");
1658
+ } else if (
1659
+ requestedParallel != null &&
1660
+ requestedParallel > budget.maxParallel
1661
+ ) {
1662
+ addUnique(blockers, "parallel-budget-exceeded");
1663
+ }
1664
+
1665
+ const durationSlots = projectedDurationSlots(
1666
+ manifest.plan,
1667
+ requestedParallel,
1668
+ );
1669
+ const projectedTokens = multiplyProjection(
1670
+ taskCalls,
1671
+ estimates.tokensPerTask,
1672
+ );
1673
+ const projectedUsd = multiplyProjection(taskCalls, estimates.usdPerTask);
1674
+ const projectedDurationMs = multiplyProjection(
1675
+ durationSlots,
1676
+ estimates.durationMsPerTask,
1677
+ );
1678
+ for (const [name, projected, maximum] of [
1679
+ ["token", projectedTokens, budget.maxTokens],
1680
+ ["usd", projectedUsd, budget.maxUsd],
1681
+ ["duration", projectedDurationMs, budget.maxDurationMs],
1682
+ ]) {
1683
+ if (projected == null || maximum == null) {
1684
+ addUnique(blockers, `${name}-budget-unevaluable`);
1685
+ } else if (projected > maximum) {
1686
+ addUnique(blockers, `${name}-budget-exceeded`);
1687
+ }
1688
+ }
1689
+
1690
+ return Object.freeze({
1691
+ schema: DYNAMIC_WORKFLOW_PREFLIGHT_SCHEMA,
1692
+ allowed: blockers.length === 0,
1693
+ definition: Object.freeze({
1694
+ schema: manifest.schema,
1695
+ adapter: manifest.adapter,
1696
+ id: manifest.definition.id,
1697
+ name: manifest.definition.name,
1698
+ definitionDigest: manifest.definitionDigest,
1699
+ authority: definitionAuthority,
1700
+ }),
1701
+ executionLocation: Object.freeze({
1702
+ schema: binding.schema,
1703
+ location: binding.location,
1704
+ source: binding.source,
1705
+ permissions: binding.permissions,
1706
+ policy: binding.policy,
1707
+ }),
1708
+ capabilities: Object.freeze({
1709
+ engine: manifest.engineCapabilities,
1710
+ used: manifest.usedCapabilities,
1711
+ required: requirements.capabilities,
1712
+ }),
1713
+ permissions: Object.freeze({
1714
+ required: requirements.permissions,
1715
+ credentialRefs: requirements.credentials,
1716
+ credentialValuesTransferred: false,
1717
+ }),
1718
+ scale: Object.freeze({
1719
+ expansionKnown: manifest.plan.expansionKnown,
1720
+ worstCaseTaskCalls: taskCalls,
1721
+ softTaskGuideline: DEFAULT_SOFT_TASK_GUIDELINE,
1722
+ hardTaskLimit: hardLimit,
1723
+ requestedParallel,
1724
+ }),
1725
+ cost: Object.freeze({
1726
+ projectedTokens,
1727
+ projectedUsd,
1728
+ projectedDurationMs,
1729
+ projectedDurationSlots: durationSlots,
1730
+ budget,
1731
+ }),
1732
+ runtimeClaims: manifest.runtimeClaims,
1733
+ blockers: Object.freeze(blockers),
1734
+ warnings: Object.freeze(warnings),
1735
+ });
1736
+ }