chainlesschain 0.163.7 → 0.164.0
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.
- package/package.json +5 -1
- package/scripts/macos-mcp-launcher-build.mjs +317 -0
- package/scripts/macos-mcp-launcher-postinstall.sh +54 -0
- package/scripts/macos-mcp-launcher-preinstall.sh +61 -0
- package/src/assets/web-panel/assets/{AIOps-axqQfwv8.js → AIOps-D2MEn7fI.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-DV-Ro0By.js → ActionButton-lCW_4Gf0.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-Bt72WEVu.js → Analytics-Bs7i-nsS.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-BtepG55E.js → AppLayout-CK7B6S_j.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-B7KaJ7S_.js → Artifacts-C8ILjpyo.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-FNFaUg7A.js → Audit-Bb9cNaWc.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-DFb6J2wQ.js → BackgroundAgents-sC9ooXIf.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-CC7YBhyj.js → Backup-D-DrsplT.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-RkgTNVtj.js → BaseInput-uCNZpwSK.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-hHEmGZy-.js → Chat-CsDK1uE9.js} +6 -6
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-CAP9YhHv.js → ChatBubbleRenderer-OqSDt50w.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-z5wXOQP1.js → Checkbox-JhTXM1-K.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-DVaDJnxy.js → Codegen-BbzZLnyD.js} +1 -1
- package/src/assets/web-panel/assets/{Col-CJmaRDR5.js → Col-D4VW4m4j.js} +1 -1
- package/src/assets/web-panel/assets/{Community-DF29_2bI.js → Community-BXrYawxV.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-DtkQkBzn.js → Compact-DCihGy1u.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-xoHDxp7I.js → Compliance-DlyZ-lk8.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-BUm-R7ht.js → Cowork-DvGZrhbO.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-Cgl14ZkB.js → Cron-DUncZi8h.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-BNcbmoqh.js → Crosschain-C_hLuUcm.js} +1 -1
- package/src/assets/web-panel/assets/{DID-Bwja0Zo9.js → DID-b6YSUqxr.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-Bk5XjEdJ.js → Dashboard-uvM15Cfb.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-Ci36Oitq.js → Dropdown-D1-Nd4qY.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer--U04ZN4q.js → EmailListRenderer-8ApvL6Zc.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-B2gNPR2s.js → FamilyGuardDashboard-LYJt8811.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-C4KghYn7.js → Federation-BbI3HGpv.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-QL7x_Q_0.js → FormItemContext-DSoEKuFu.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-F3Ryltwm.js → GenericCardRenderer-B0S9OWd5.js} +1 -1
- package/src/assets/web-panel/assets/{Git-2HassK5k.js → Git-DIs9Zhf3.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-DoBIp7oe.js → Governance-jzZXrxcl.js} +1 -1
- package/src/assets/web-panel/assets/{Inference--W01QhZ-.js → Inference-JUPjf2ZI.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-DmvwqGpT.js → KnowledgeGraph-DxnfJvlP.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-BBJ4yAel.js → Logs-iXiz8BEE.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-BLCZMzhJ.js → MarkdownRenderer-GmB6DOr6.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-D5lNngSI.js → Marketplace-Y3Xch312.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-CkEVOMKH.js → McpTools-D7kGGbO7.js} +4 -4
- package/src/assets/web-panel/assets/{Memory-B1Ow1xVE.js → Memory-Do_hVxzh.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-SgYbUfb6.js → MobileBridge-CtrR0Tas.js} +1 -1
- package/src/assets/web-panel/assets/MobileProjects-BL0Czcoj.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-DcTXSSma.js → Mtc-qo5QCTGd.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-Dt3WG4oj.js → MtcAudit-cq5mnjYj.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-B9B38UZx.js → Multisig-Bq0MAQHw.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-B0S4GGvG.js → NLProgramming-DdWE6Vi2.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-DZ5U58Ng.js → Notes-BxMBFcIp.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-PjL5ZW34.js → NotificationSettings-RTrAcbUe.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-DrAX2ESt.js → OrderTableRenderer-DJbpGqzT.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-Cv1GYs-c.js → Organization-SQzIPdqC.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-Bbkp_PL3.js → Overflow-02yECh22.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-BD8QUgoZ.js → P2P-BNg4pNCM.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-BO-2PeaB.js → PdhVaultBrowser-BxPJZsD3.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-D_OPVa02.js → Permissions-CLnDnPAz.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-mh-pEmaB.js → PersonalDataHub-C5m0AjGf.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-6JC2EDdb.js → Pipeline-VwOf5Dhv.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-CUshzUAG.js → Privacy-CC0W2hZd.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-Cs2Aalri.js → ProjectInit-Dz893Bob.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-1ak49tcj.js → ProjectSettings-CxQkvl0k.js} +2 -2
- package/src/assets/web-panel/assets/Projects-DDAjkUkT.js +1 -0
- package/src/assets/web-panel/assets/{Providers-CXXxvafH.js → Providers-DeB9IkxK.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-PTcDsF58.js → QrScannerModal-OCeoaswn.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-CDwucrJw.js → QuickAsk-DenotaAj.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-CJlLVRXR.js → Recommend-Cies_jjI.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-DlN-ETsO.js → RemoteSession-Dxzl5n2T.js} +3 -3
- package/src/assets/web-panel/assets/{Reputation-DI23LR6m.js → Reputation-CW0mvxgZ.js} +1 -1
- package/src/assets/web-panel/assets/{Row-Cl7UQMrM.js → Row-SEd32qZU.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-CexHNfh8.js → RssFeed-BSwnJ3Lm.js} +3 -3
- package/src/assets/web-panel/assets/{Search-BneBWvRN.js → Search-xe2m8bkC.js} +1 -1
- package/src/assets/web-panel/assets/{Security-DX7Phgrp.js → Security-Mq2F9Nro.js} +4 -4
- package/src/assets/web-panel/assets/{Services-BWXO8Mte.js → Services-BKGw2V3P.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-DCyOjKPJ.js → Skeleton-DW95-Rxf.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-CXqERsTB.js → Skills-CHgChCv_.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-bhbrbz8E.js → Sla-tKh6k3R7.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-3IPU0HBZ.js → SpeechSettings-D6UL3dA5.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-DBNTQLbM.js → SyncSettings-D0Fw8fVL.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-quP0bkN-.js → Tasks-20x1GB3D.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-BouWmgho.js → Templates-DJ-lts-a.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-qv0D9s7z.js → Tenant-BFdGpbs7.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-BxvbE8BB.js → Terminal-Xpx61vHL.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-D-IeLnJ2.js → TimelineRenderer-C6UIvyZQ.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-CFMKKyVG.js → Tokens-Dellq08f.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-L8as3UuJ.js → Trigger-VKw8d0J-.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-MxmA4VZG.js → Trust-DNftdKT5.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-C0VvJYRi.js → UkeySign-DX9VAKJI.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-Bf5QZj8N.js → VideoEditing-B2h3jO8q.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-BIJ9riRz.js → Wallet-CjGkof7f.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-B8p9Mhkw.js → WebAuthn-2Zfcu55P.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-BVsuaPen.js → WorkflowEditor-B9eZ8UxZ.js} +1 -1
- package/src/assets/web-panel/assets/{chat-BfkjoKpV.js → chat-CQNfD-YO.js} +1 -1
- package/src/assets/web-panel/assets/{colors-DeAlsWK8.js → colors-D4usyFT2.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-Cs97bz5j.js → compact-item-s4TpjvjX.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-BqbG60LH.js → createContext-BRCSvYxj.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-DKJjSWRn.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-i_RY0b1X.js → hasIn-AdkUbkV-.js} +1 -1
- package/src/assets/web-panel/assets/{index-BOVkf1K3.js → index--00U6vXZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-B-3tEpTc.js → index-B2V-eKfK.js} +1 -1
- package/src/assets/web-panel/assets/{index-D2B4VPyP.js → index-B4JJCfQ2.js} +1 -1
- package/src/assets/web-panel/assets/{index-BkBi5TmC.js → index-BIoG5yYf.js} +1 -1
- package/src/assets/web-panel/assets/{index-79V_zv1s.js → index-BMcimU-2.js} +1 -1
- package/src/assets/web-panel/assets/{index-U4f5izHz.js → index-BPhkFZ1I.js} +1 -1
- package/src/assets/web-panel/assets/{index-DiSkx4UB.js → index-BQ3DXBtD.js} +3 -3
- package/src/assets/web-panel/assets/{index-dIHr4B_u.js → index-Bad4VNvz.js} +1 -1
- package/src/assets/web-panel/assets/{index-CIG8fQ2_.js → index-BgiXR_-_.js} +1 -1
- package/src/assets/web-panel/assets/{index-DqBgBpgp.js → index-BtobShro.js} +1 -1
- package/src/assets/web-panel/assets/{index-ZxO_-E8a.js → index-Bw2MEnUk.js} +1 -1
- package/src/assets/web-panel/assets/{index-DUUrv141.js → index-C1mJtE6q.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bm7lLR4c.js → index-C484EJiS.js} +1 -1
- package/src/assets/web-panel/assets/{index-COdGA-8n.js → index-C5KAQFPQ.js} +1 -1
- package/src/assets/web-panel/assets/index-C61cnl3K.js +1 -0
- package/src/assets/web-panel/assets/{index-CED2PL_y.js → index-C7Y8Aluc.js} +1 -1
- package/src/assets/web-panel/assets/{index-YXgLng0K.js → index-CCsM_Ybx.js} +1 -1
- package/src/assets/web-panel/assets/{index-0-agYlWL.js → index-CJCFe2Qf.js} +1 -1
- package/src/assets/web-panel/assets/{index-B5UkyA3c.js → index-CJVEOa4i.js} +1 -1
- package/src/assets/web-panel/assets/{index-B1CbOH1i.js → index-CJdQrZth.js} +1 -1
- package/src/assets/web-panel/assets/{index-s1opAL-M.js → index-CKC1t3Ic.js} +1 -1
- package/src/assets/web-panel/assets/{index-yObj1O4n.js → index-CQhAVU5t.js} +1 -1
- package/src/assets/web-panel/assets/{index-CgsqdnRV.js → index-CYdoQsa1.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dk7-v4hP.js → index-Cduu2Hhr.js} +1 -1
- package/src/assets/web-panel/assets/{index-B-JVTrpr.js → index-CkwiSLhU.js} +1 -1
- package/src/assets/web-panel/assets/{index-CeWoNHau.js → index-Cvyt-zhm.js} +1 -1
- package/src/assets/web-panel/assets/{index-CE2VtTlp.js → index-D2GjI2oe.js} +1 -1
- package/src/assets/web-panel/assets/index-D4XFHxBr.js +1 -0
- package/src/assets/web-panel/assets/{index-DmbfhJUP.js → index-DARsAyUp.js} +1 -1
- package/src/assets/web-panel/assets/{index-BESLFt4q.js → index-DVKfQ0Ux.js} +1 -1
- package/src/assets/web-panel/assets/{index-PT_5sBMA.js → index-DZT36ZYq.js} +1 -1
- package/src/assets/web-panel/assets/{index-gyFpvL7l.js → index-D_XBHopw.js} +1 -1
- package/src/assets/web-panel/assets/{index-BYUVuwKt.js → index-DdCB70SS.js} +1 -1
- package/src/assets/web-panel/assets/{index-BcUXAB2s.js → index-DzRjHxEv.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dk2qouAz.js → index-MMN9V6JF.js} +1 -1
- package/src/assets/web-panel/assets/{index-D9evtvg2.js → index-RfMr79MW.js} +1 -1
- package/src/assets/web-panel/assets/{index-BuLQobzW.js → index-_IRVsV9X.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cf3WCLmy.js → index-nXyk8GZ9.js} +1 -1
- package/src/assets/web-panel/assets/{index-CG3PRyAL.js → index-s_buFMEG.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-C9h9yKL3.js → initDefaultProps-Blmpk7HL.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BvmLsPdu.js → motion-DPBJMv1n.js} +1 -1
- package/src/assets/web-panel/assets/{move-CoL4ekU1.js → move-ButdzCM7.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-C4pMy6xV.js → mtc-parser-cyRC_QCe.js} +1 -1
- package/src/assets/web-panel/assets/{omit-DPuJfNxx.js → omit-1epSV7hz.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-D0KEeaK2.js → pickAttrs-DuPY8xJs.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-BpkyINxt.js → placementArrow-6XZqarhe.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-DQI_wOq8.js → responsiveObserve-B40pXBWM.js} +1 -1
- package/src/assets/web-panel/assets/{slide-DYfdDiRg.js → slide-jbZ9Wu4n.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-B5dtvb0D.js → statusUtils-BKQQcVy4.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-CF310mSj.js → styleChecker-NiKfWjUT.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-D1Qp4BLp.js → useFlexGapSupport-bQUCvPeb.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-C7_iyvJK.js → useFs-CUGji7ph.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-DZUt_fIm.js → usePersonalDataHub-4veyN2N2.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-D3dsi0lZ.js → vnode-1-nLug-Z.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-WdbOlvdQ.js → zoom-dhCeRDMo.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +6 -6
- package/src/commands/automation.js +103 -1
- package/src/commands/cowork.js +174 -19
- package/src/commands/permissions.js +240 -16
- package/src/commands/plugin.js +1293 -56
- package/src/commands/session-location.js +276 -0
- package/src/commands/session.js +2 -0
- package/src/commands/team-merge-review.js +937 -0
- package/src/commands/team.js +2 -0
- package/src/data/changelog.json +27 -1
- package/src/gateways/ws/action-protocol.js +35 -10
- package/src/gateways/ws/remote-session-protocol.js +24 -1
- package/src/gateways/ws/ws-agent-handler.js +12 -0
- package/src/gateways/ws/ws-server.js +48 -12
- package/src/harness/jsonl-session-store.js +341 -24
- package/src/harness/mcp-client.js +8 -1
- package/src/harness/remote-session-audit.js +1 -0
- package/src/harness/remote-session-crypto.js +210 -2
- package/src/harness/remote-session-registry.js +159 -6
- package/src/harness/session-list-index.js +233 -14
- package/src/lib/agent-authority.js +6 -0
- package/src/lib/agent-schedule-store.js +139 -28
- package/src/lib/agent-team/team-merge-review-store.js +765 -0
- package/src/lib/agent-team/team-merge-review-transaction.js +1223 -0
- package/src/lib/agent-team/team-merge-review.js +1847 -0
- package/src/lib/automation-center-incidents.js +314 -0
- package/src/lib/automation-center-runtime.js +448 -0
- package/src/lib/automation-center.js +182 -38
- package/src/lib/automation-engine.js +41 -0
- package/src/lib/automation-execution-authority.js +241 -12
- package/src/lib/automation-execution-incident.js +737 -0
- package/src/lib/background-agent-keeper-client.js +248 -0
- package/src/lib/background-agent-keeper-protocol.js +147 -0
- package/src/lib/background-agent-supervisor.js +520 -40
- package/src/lib/background-interaction-resolver.js +12 -0
- package/src/lib/background-turn-bootstrap-protocol.js +126 -0
- package/src/lib/cowork-cron.js +85 -14
- package/src/lib/cowork-workflow.js +336 -16
- package/src/lib/dynamic-workflow-facade.js +648 -0
- package/src/lib/execution-location-contract.js +551 -0
- package/src/lib/execution-location-runtime.js +130 -0
- package/src/lib/ide-context.js +94 -6
- package/src/lib/mcp-stdio-package-materialization.js +166 -14
- package/src/lib/packer/pkg-config-generator.js +2 -0
- package/src/lib/permission-authority.js +77 -0
- package/src/lib/permission-side-effect-center.js +495 -0
- package/src/lib/plugin-runtime/install.js +514 -13
- package/src/lib/plugin-runtime/marketplace-artifact-readback.js +900 -0
- package/src/lib/plugin-runtime/marketplace-catalog.js +1181 -0
- package/src/lib/plugin-runtime/marketplace-impact.js +408 -0
- package/src/lib/plugin-runtime/marketplace-remote-artifacts.js +1567 -0
- package/src/lib/plugin-security.js +60 -3
- package/src/lib/process-execution-broker/index.js +1095 -57
- package/src/lib/process-execution-broker/linux-bwrap-descriptor-launch.js +375 -0
- package/src/lib/process-execution-broker/linux-generic-bwrap-runtime.js +90 -16
- package/src/lib/process-execution-broker/linux-generic-bwrap.js +159 -18
- package/src/lib/process-execution-broker/macos-mcp-launcher-contract.js +278 -0
- package/src/lib/process-execution-broker/macos-mcp-launcher-protocol.json +23 -0
- package/src/lib/process-execution-broker/macos-mcp-launcher.c +1497 -0
- package/src/lib/process-execution-broker/mcp-fd-entry-bootstrap.js +37 -0
- package/src/lib/process-execution-broker/platform-sandbox.js +2330 -279
- package/src/lib/process-execution-broker/windows-sandbox-helper.dll +0 -0
- package/src/lib/process-execution-broker/windows-sandbox-helper.exe +0 -0
- package/src/lib/process-execution-broker/windows-sandbox.cs +50 -4
- package/src/lib/public-ide-capability-manifest.js +3 -0
- package/src/lib/remote-approval-bridge.js +123 -17
- package/src/lib/remote-membership-authority.js +632 -0
- package/src/lib/remote-membership-coordinator.js +2409 -0
- package/src/lib/remote-membership-host-store.js +1750 -0
- package/src/lib/scheduler-kernel/agenda-adapter.js +17 -7
- package/src/lib/scheduler-kernel/automation-adapter.js +105 -11
- package/src/lib/scheduler-kernel/automation-event-adapter.js +87 -11
- package/src/lib/scheduler-kernel/contract.js +91 -0
- package/src/lib/scheduler-kernel/cowork-cron-adapter.js +12 -1
- package/src/lib/scheduler-kernel/loop-adapter.js +7 -1
- package/src/lib/scheduler-kernel/routine-adapter.js +7 -1
- package/src/lib/scheduler-kernel/runtime-control-capabilities.js +31 -0
- package/src/lib/scheduler-kernel/runtime.js +176 -3
- package/src/lib/scheduler-kernel/store.js +1253 -45
- package/src/lib/scoped-permission-store.js +369 -0
- package/src/lib/session-anti-rollback-anchor.js +262 -5
- package/src/lib/sub-agent-context.js +4 -0
- package/src/lib/workflow-definition-contract.js +149 -0
- package/src/repl/agent-repl.js +41 -7
- package/src/repl/chat-repl.js +2 -0
- package/src/repl/clipboard-image.js +735 -16
- package/src/repl/ide-status.js +1 -1
- package/src/repl/prompt-interactions.js +59 -6
- package/src/runtime/agent-core.js +93 -3
- package/src/runtime/headless-runner.js +30 -25
- package/src/runtime/headless-stream.js +32 -25
- package/src/runtime/mcp-config.js +81 -10
- package/src/workers/background-agent-keeper.js +498 -0
- package/src/workers/background-agent-worker.js +358 -13
- package/src/workers/background-turn-bootstrap.js +143 -0
- package/src/assets/web-panel/assets/MobileProjects-BWdOvQAj.js +0 -1
- package/src/assets/web-panel/assets/Projects-BV4oApsm.js +0 -1
- package/src/assets/web-panel/assets/devWarning-DPty0mGN.js +0 -1
- package/src/assets/web-panel/assets/index-Bt7g0Vq_.js +0 -1
- package/src/assets/web-panel/assets/index-ChVT0p9u.js +0 -1
|
@@ -11,9 +11,10 @@
|
|
|
11
11
|
* 3. substitutes placeholders in `message` from completed step outputs
|
|
12
12
|
* 4. halts on first failure unless `continueOnError` is set
|
|
13
13
|
*
|
|
14
|
-
* Persistence
|
|
15
|
-
* `.chainlesschain/cowork/workflows/<id>.json`,
|
|
16
|
-
*
|
|
14
|
+
* Persistence keeps a versioned current envelope under
|
|
15
|
+
* `.chainlesschain/cowork/workflows/<id>.json`, immutable content-addressed
|
|
16
|
+
* definitions under `workflow-versions/<id>/<digest>.json`, plus a
|
|
17
|
+
* `run-history.jsonl` capturing each execution.
|
|
17
18
|
*
|
|
18
19
|
* The runner itself is injected via `_deps.runTask` to avoid a circular import
|
|
19
20
|
* with `cowork-task-runner.js`.
|
|
@@ -21,7 +22,7 @@
|
|
|
21
22
|
* @module cowork-workflow
|
|
22
23
|
*/
|
|
23
24
|
|
|
24
|
-
import {
|
|
25
|
+
import fs, {
|
|
25
26
|
existsSync,
|
|
26
27
|
mkdirSync,
|
|
27
28
|
readFileSync,
|
|
@@ -30,15 +31,34 @@ import {
|
|
|
30
31
|
unlinkSync,
|
|
31
32
|
appendFileSync,
|
|
32
33
|
renameSync,
|
|
34
|
+
lstatSync,
|
|
35
|
+
openSync,
|
|
36
|
+
fstatSync,
|
|
37
|
+
closeSync,
|
|
38
|
+
realpathSync,
|
|
39
|
+
constants as fsConstants,
|
|
33
40
|
} from "node:fs";
|
|
34
|
-
import { join } from "node:path";
|
|
41
|
+
import { isAbsolute, join, relative } from "node:path";
|
|
42
|
+
import {
|
|
43
|
+
sameFileStatIdentity,
|
|
44
|
+
samePathHandleFileIdentity,
|
|
45
|
+
withTrustedFileParentSync,
|
|
46
|
+
} from "./secure-file-identity.js";
|
|
35
47
|
import { evaluate as evalExpr, resolveReference } from "./workflow-expr.js";
|
|
48
|
+
import {
|
|
49
|
+
MAX_WORKFLOW_DEFINITION_BYTES,
|
|
50
|
+
createCoworkWorkflowRecord,
|
|
51
|
+
createWorkflowDefinitionAuthority,
|
|
52
|
+
normalizeWorkflowDefinitionDigest,
|
|
53
|
+
verifyCoworkWorkflowRecord,
|
|
54
|
+
} from "./workflow-definition-contract.js";
|
|
36
55
|
|
|
37
56
|
/** Maximum number of items a single forEach step can expand into. */
|
|
38
57
|
export const MAX_FAN_OUT = 500;
|
|
39
58
|
|
|
40
59
|
/** Absolute ceiling on a single loop step's iterations (infinite-loop guard). */
|
|
41
60
|
export const MAX_LOOP_ITERATIONS = 100;
|
|
61
|
+
export const COWORK_WORKFLOW_RUN_RECORD_SCHEMA = "cc-cowork-workflow-run/v1";
|
|
42
62
|
|
|
43
63
|
export const _deps = {
|
|
44
64
|
existsSync,
|
|
@@ -49,6 +69,12 @@ export const _deps = {
|
|
|
49
69
|
unlinkSync,
|
|
50
70
|
appendFileSync,
|
|
51
71
|
renameSync,
|
|
72
|
+
lstatSync,
|
|
73
|
+
openSync,
|
|
74
|
+
fstatSync,
|
|
75
|
+
closeSync,
|
|
76
|
+
realpathSync,
|
|
77
|
+
fsConstants,
|
|
52
78
|
now: () => Date.now(),
|
|
53
79
|
runTask: null, // injected by CLI
|
|
54
80
|
// Timer seams (injectable for deterministic retry/timeout tests).
|
|
@@ -83,14 +109,174 @@ function _atomicWriteJson(file, data) {
|
|
|
83
109
|
}
|
|
84
110
|
}
|
|
85
111
|
|
|
112
|
+
function _parseBoundedWorkflowJson(raw) {
|
|
113
|
+
const text =
|
|
114
|
+
typeof raw === "string" ? raw : Buffer.from(raw).toString("utf8");
|
|
115
|
+
const bytes = Buffer.byteLength(text, "utf8");
|
|
116
|
+
if (bytes <= 0 || bytes > MAX_WORKFLOW_DEFINITION_BYTES) {
|
|
117
|
+
throw new Error(
|
|
118
|
+
`workflow record must be 1..${MAX_WORKFLOW_DEFINITION_BYTES} bytes`,
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
return JSON.parse(text);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function _pathIsInside(root, candidate) {
|
|
125
|
+
const offset = relative(root, candidate);
|
|
126
|
+
return offset === "" || (!offset.startsWith("..") && !isAbsolute(offset));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function _canonicalWorkflowStoragePath(candidate, runtimeRealpath) {
|
|
130
|
+
const nativeRealpath = runtimeRealpath?.native;
|
|
131
|
+
return typeof nativeRealpath === "function"
|
|
132
|
+
? nativeRealpath(candidate)
|
|
133
|
+
: runtimeRealpath(candidate);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function workflowStoragePathIsContained(
|
|
137
|
+
cwd,
|
|
138
|
+
candidate,
|
|
139
|
+
runtimeRealpath = realpathSync,
|
|
140
|
+
) {
|
|
141
|
+
const realRoot = _canonicalWorkflowStoragePath(cwd, runtimeRealpath);
|
|
142
|
+
const realCandidate = _canonicalWorkflowStoragePath(
|
|
143
|
+
candidate,
|
|
144
|
+
runtimeRealpath,
|
|
145
|
+
);
|
|
146
|
+
return _pathIsInside(realRoot, realCandidate);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function _assertWorkflowStoragePath(cwd, candidate) {
|
|
150
|
+
const usingRuntimeFs =
|
|
151
|
+
_deps.readFileSync === readFileSync &&
|
|
152
|
+
_deps.realpathSync === realpathSync &&
|
|
153
|
+
_deps.lstatSync === lstatSync;
|
|
154
|
+
if (!usingRuntimeFs) return;
|
|
155
|
+
// Canonicalize both sides through the same native API. Windows hosted
|
|
156
|
+
// runners can expose cwd through an 8.3 alias while a trusted-parent read
|
|
157
|
+
// returns the expanded path; mixing legacy/native realpath projections can
|
|
158
|
+
// otherwise misclassify the same directory as an escape.
|
|
159
|
+
if (!workflowStoragePathIsContained(cwd, candidate, _deps.realpathSync)) {
|
|
160
|
+
throw new Error("workflow storage path escapes the working directory");
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function _assertWorkflowStorageDirectory(cwd, directory) {
|
|
165
|
+
_assertWorkflowStoragePath(cwd, directory);
|
|
166
|
+
if (
|
|
167
|
+
_deps.readFileSync === readFileSync &&
|
|
168
|
+
_deps.lstatSync === lstatSync &&
|
|
169
|
+
_deps.realpathSync === realpathSync
|
|
170
|
+
) {
|
|
171
|
+
const stat = _deps.lstatSync(directory);
|
|
172
|
+
if (!stat.isDirectory() || stat.isSymbolicLink()) {
|
|
173
|
+
throw new Error("workflow storage directory must not be a symlink");
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function _readBoundedWorkflowJson(cwd, file) {
|
|
179
|
+
const usingRuntimeFs =
|
|
180
|
+
_deps.readFileSync === readFileSync &&
|
|
181
|
+
_deps.lstatSync === lstatSync &&
|
|
182
|
+
_deps.openSync === openSync &&
|
|
183
|
+
_deps.fstatSync === fstatSync &&
|
|
184
|
+
_deps.closeSync === closeSync &&
|
|
185
|
+
_deps.realpathSync === realpathSync;
|
|
186
|
+
if (!usingRuntimeFs) {
|
|
187
|
+
return _parseBoundedWorkflowJson(_deps.readFileSync(file, "utf8"));
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
_assertWorkflowStoragePath(cwd, file);
|
|
191
|
+
return withTrustedFileParentSync(
|
|
192
|
+
fs,
|
|
193
|
+
file,
|
|
194
|
+
({ canonicalPath, parentDevice }) => {
|
|
195
|
+
_assertWorkflowStoragePath(cwd, canonicalPath);
|
|
196
|
+
const before = _deps.lstatSync(canonicalPath, { bigint: true });
|
|
197
|
+
if (
|
|
198
|
+
!before.isFile() ||
|
|
199
|
+
before.isSymbolicLink() ||
|
|
200
|
+
Number(before.nlink) !== 1
|
|
201
|
+
) {
|
|
202
|
+
throw new Error("workflow record must be a regular, single-link file");
|
|
203
|
+
}
|
|
204
|
+
if (
|
|
205
|
+
Number(before.size) <= 0 ||
|
|
206
|
+
Number(before.size) > MAX_WORKFLOW_DEFINITION_BYTES
|
|
207
|
+
) {
|
|
208
|
+
throw new Error(
|
|
209
|
+
`workflow record must be 1..${MAX_WORKFLOW_DEFINITION_BYTES} bytes`,
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
let descriptor;
|
|
214
|
+
try {
|
|
215
|
+
let flags = Number(_deps.fsConstants.O_RDONLY || 0);
|
|
216
|
+
if (typeof _deps.fsConstants.O_NOFOLLOW === "number") {
|
|
217
|
+
flags |= _deps.fsConstants.O_NOFOLLOW;
|
|
218
|
+
}
|
|
219
|
+
descriptor = _deps.openSync(canonicalPath, flags);
|
|
220
|
+
const opened = _deps.fstatSync(descriptor, { bigint: true });
|
|
221
|
+
if (
|
|
222
|
+
!opened.isFile() ||
|
|
223
|
+
Number(opened.nlink) !== 1 ||
|
|
224
|
+
!samePathHandleFileIdentity(before, opened, parentDevice)
|
|
225
|
+
) {
|
|
226
|
+
throw new Error("workflow record identity changed while opening");
|
|
227
|
+
}
|
|
228
|
+
const value = _parseBoundedWorkflowJson(
|
|
229
|
+
_deps.readFileSync(descriptor, "utf8"),
|
|
230
|
+
);
|
|
231
|
+
const after = _deps.fstatSync(descriptor, { bigint: true });
|
|
232
|
+
if (!sameFileStatIdentity(opened, after)) {
|
|
233
|
+
throw new Error("workflow record changed while being read");
|
|
234
|
+
}
|
|
235
|
+
return value;
|
|
236
|
+
} finally {
|
|
237
|
+
if (descriptor !== undefined) _deps.closeSync(descriptor);
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
|
|
86
243
|
// ─── Paths ───────────────────────────────────────────────────────────────────
|
|
87
244
|
|
|
88
245
|
function workflowsDir(cwd) {
|
|
89
246
|
return join(cwd, ".chainlesschain", "cowork", "workflows");
|
|
90
247
|
}
|
|
91
248
|
|
|
249
|
+
function assertWorkflowId(id) {
|
|
250
|
+
if (
|
|
251
|
+
typeof id !== "string" ||
|
|
252
|
+
!/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u.test(id) ||
|
|
253
|
+
id.includes("..")
|
|
254
|
+
) {
|
|
255
|
+
throw new TypeError(
|
|
256
|
+
"workflow id must be 1..128 safe filename characters without '..'",
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
return id;
|
|
260
|
+
}
|
|
261
|
+
|
|
92
262
|
function workflowFile(cwd, id) {
|
|
93
|
-
return join(workflowsDir(cwd), `${id}.json`);
|
|
263
|
+
return join(workflowsDir(cwd), `${assertWorkflowId(id)}.json`);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
function workflowVersionsDir(cwd, id) {
|
|
267
|
+
return join(
|
|
268
|
+
cwd,
|
|
269
|
+
".chainlesschain",
|
|
270
|
+
"cowork",
|
|
271
|
+
"workflow-versions",
|
|
272
|
+
assertWorkflowId(id),
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
function workflowVersionFile(cwd, id, definitionDigest) {
|
|
277
|
+
const digest = normalizeWorkflowDefinitionDigest(definitionDigest);
|
|
278
|
+
if (!digest) throw new TypeError("workflow definition digest is invalid");
|
|
279
|
+
return join(workflowVersionsDir(cwd, id), `${digest.slice(7)}.json`);
|
|
94
280
|
}
|
|
95
281
|
|
|
96
282
|
function historyFile(cwd) {
|
|
@@ -107,7 +293,15 @@ export function validateWorkflow(wf) {
|
|
|
107
293
|
if (!wf || typeof wf !== "object") {
|
|
108
294
|
return { valid: false, errors: ["workflow must be an object"] };
|
|
109
295
|
}
|
|
110
|
-
if (!wf.id || typeof wf.id !== "string")
|
|
296
|
+
if (!wf.id || typeof wf.id !== "string") {
|
|
297
|
+
errors.push("id required");
|
|
298
|
+
} else {
|
|
299
|
+
try {
|
|
300
|
+
assertWorkflowId(wf.id);
|
|
301
|
+
} catch (error) {
|
|
302
|
+
errors.push(error.message);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
111
305
|
if (!wf.name || typeof wf.name !== "string") errors.push("name required");
|
|
112
306
|
if (!Array.isArray(wf.steps) || wf.steps.length === 0) {
|
|
113
307
|
errors.push("steps must be a non-empty array");
|
|
@@ -375,6 +569,40 @@ export function substitutePlaceholders(template, resultsById) {
|
|
|
375
569
|
|
|
376
570
|
// ─── Persistence ─────────────────────────────────────────────────────────────
|
|
377
571
|
|
|
572
|
+
function _storedWorkflowError(message) {
|
|
573
|
+
const error = new Error(message);
|
|
574
|
+
error.code = "WORKFLOW_DEFINITION_INTEGRITY";
|
|
575
|
+
return error;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
function _readStoredWorkflowRecord(
|
|
579
|
+
cwd,
|
|
580
|
+
file,
|
|
581
|
+
{ allowLegacy = true, expectedId, expectedDigest } = {},
|
|
582
|
+
) {
|
|
583
|
+
const record = verifyCoworkWorkflowRecord(
|
|
584
|
+
_readBoundedWorkflowJson(cwd, file),
|
|
585
|
+
{
|
|
586
|
+
allowLegacy,
|
|
587
|
+
},
|
|
588
|
+
);
|
|
589
|
+
const validation = validateWorkflow(record.definition);
|
|
590
|
+
if (!validation.valid) {
|
|
591
|
+
throw _storedWorkflowError(
|
|
592
|
+
`stored workflow is invalid: ${validation.errors.join("; ")}`,
|
|
593
|
+
);
|
|
594
|
+
}
|
|
595
|
+
if (expectedId && record.definition.id !== expectedId) {
|
|
596
|
+
throw _storedWorkflowError("stored workflow id does not match its path");
|
|
597
|
+
}
|
|
598
|
+
if (expectedDigest && record.definitionDigest !== expectedDigest) {
|
|
599
|
+
throw _storedWorkflowError(
|
|
600
|
+
"stored workflow digest does not match its version path",
|
|
601
|
+
);
|
|
602
|
+
}
|
|
603
|
+
return record;
|
|
604
|
+
}
|
|
605
|
+
|
|
378
606
|
export function listWorkflows(cwd) {
|
|
379
607
|
const dir = workflowsDir(cwd);
|
|
380
608
|
if (!_deps.existsSync(dir)) return [];
|
|
@@ -383,21 +611,28 @@ export function listWorkflows(cwd) {
|
|
|
383
611
|
for (const name of entries) {
|
|
384
612
|
if (!name.endsWith(".json")) continue;
|
|
385
613
|
try {
|
|
386
|
-
const
|
|
387
|
-
|
|
388
|
-
|
|
614
|
+
const id = name.slice(0, -5);
|
|
615
|
+
const record = _readStoredWorkflowRecord(cwd, join(dir, name), {
|
|
616
|
+
expectedId: id,
|
|
617
|
+
});
|
|
618
|
+
out.push(record.definition);
|
|
619
|
+
} catch {
|
|
389
620
|
// skip malformed files
|
|
390
621
|
}
|
|
391
622
|
}
|
|
392
623
|
return out;
|
|
393
624
|
}
|
|
394
625
|
|
|
395
|
-
export function
|
|
626
|
+
export function getWorkflowRecord(cwd, id) {
|
|
396
627
|
const file = workflowFile(cwd, id);
|
|
397
628
|
if (!_deps.existsSync(file)) return null;
|
|
629
|
+
return _readStoredWorkflowRecord(cwd, file, { expectedId: id });
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
export function getWorkflow(cwd, id) {
|
|
398
633
|
try {
|
|
399
|
-
return
|
|
400
|
-
} catch
|
|
634
|
+
return getWorkflowRecord(cwd, id)?.definition || null;
|
|
635
|
+
} catch {
|
|
401
636
|
return null;
|
|
402
637
|
}
|
|
403
638
|
}
|
|
@@ -405,14 +640,82 @@ export function getWorkflow(cwd, id) {
|
|
|
405
640
|
export function saveWorkflow(cwd, wf) {
|
|
406
641
|
const { valid, errors } = validateWorkflow(wf);
|
|
407
642
|
if (!valid) throw new Error(`Invalid workflow: ${errors.join("; ")}`);
|
|
643
|
+
const record = createCoworkWorkflowRecord(wf);
|
|
644
|
+
const serialized = JSON.stringify(record, null, 2);
|
|
408
645
|
const dir = workflowsDir(cwd);
|
|
409
646
|
_deps.mkdirSync(dir, { recursive: true });
|
|
410
|
-
|
|
647
|
+
_assertWorkflowStorageDirectory(cwd, dir);
|
|
648
|
+
const versionDir = workflowVersionsDir(cwd, wf.id);
|
|
649
|
+
_deps.mkdirSync(versionDir, { recursive: true });
|
|
650
|
+
_assertWorkflowStorageDirectory(cwd, versionDir);
|
|
651
|
+
const versionFile = workflowVersionFile(cwd, wf.id, record.definitionDigest);
|
|
652
|
+
if (_deps.existsSync(versionFile)) {
|
|
653
|
+
_readStoredWorkflowRecord(cwd, versionFile, {
|
|
654
|
+
allowLegacy: false,
|
|
655
|
+
expectedId: wf.id,
|
|
656
|
+
expectedDigest: record.definitionDigest,
|
|
657
|
+
});
|
|
658
|
+
} else {
|
|
659
|
+
_atomicWriteJson(versionFile, serialized);
|
|
660
|
+
}
|
|
661
|
+
const currentFile = workflowFile(cwd, wf.id);
|
|
662
|
+
if (_deps.existsSync(currentFile)) {
|
|
663
|
+
_readStoredWorkflowRecord(cwd, currentFile, {
|
|
664
|
+
expectedId: wf.id,
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
_atomicWriteJson(currentFile, serialized);
|
|
411
668
|
return wf;
|
|
412
669
|
}
|
|
413
670
|
|
|
671
|
+
export function getWorkflowVersion(cwd, id, definitionDigest) {
|
|
672
|
+
const digest = normalizeWorkflowDefinitionDigest(definitionDigest);
|
|
673
|
+
if (!digest) throw new TypeError("workflow definition digest is invalid");
|
|
674
|
+
const file = workflowVersionFile(cwd, id, digest);
|
|
675
|
+
if (!_deps.existsSync(file)) return null;
|
|
676
|
+
return _readStoredWorkflowRecord(cwd, file, {
|
|
677
|
+
allowLegacy: false,
|
|
678
|
+
expectedId: id,
|
|
679
|
+
expectedDigest: digest,
|
|
680
|
+
});
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
export function listWorkflowVersions(cwd, id) {
|
|
684
|
+
const dir = workflowVersionsDir(cwd, id);
|
|
685
|
+
if (!_deps.existsSync(dir)) return [];
|
|
686
|
+
const versions = [];
|
|
687
|
+
for (const name of _deps.readdirSync(dir) || []) {
|
|
688
|
+
const match = /^([a-f0-9]{64})\.json$/u.exec(name);
|
|
689
|
+
if (!match) continue;
|
|
690
|
+
const digest = `sha256:${match[1]}`;
|
|
691
|
+
const record = _readStoredWorkflowRecord(cwd, join(dir, name), {
|
|
692
|
+
allowLegacy: false,
|
|
693
|
+
expectedId: id,
|
|
694
|
+
expectedDigest: digest,
|
|
695
|
+
});
|
|
696
|
+
versions.push(
|
|
697
|
+
Object.freeze({
|
|
698
|
+
status: record.status,
|
|
699
|
+
recordSchema: record.recordSchema,
|
|
700
|
+
definitionSchema: record.definitionSchema,
|
|
701
|
+
definitionDigest: record.definitionDigest,
|
|
702
|
+
id: record.definition.id,
|
|
703
|
+
name: record.definition.name,
|
|
704
|
+
}),
|
|
705
|
+
);
|
|
706
|
+
}
|
|
707
|
+
return versions.sort((left, right) =>
|
|
708
|
+
left.definitionDigest.localeCompare(right.definitionDigest),
|
|
709
|
+
);
|
|
710
|
+
}
|
|
711
|
+
|
|
414
712
|
export function removeWorkflow(cwd, id) {
|
|
415
|
-
|
|
713
|
+
let file;
|
|
714
|
+
try {
|
|
715
|
+
file = workflowFile(cwd, id);
|
|
716
|
+
} catch {
|
|
717
|
+
return false;
|
|
718
|
+
}
|
|
416
719
|
if (!_deps.existsSync(file)) return false;
|
|
417
720
|
_deps.unlinkSync(file);
|
|
418
721
|
return true;
|
|
@@ -872,6 +1175,7 @@ export async function runPipeline({
|
|
|
872
1175
|
*
|
|
873
1176
|
* @param {object} options
|
|
874
1177
|
* @param {object} options.workflow - Workflow definition
|
|
1178
|
+
* @param {string} [options.definitionDigest] - Exact definition digest to bind
|
|
875
1179
|
* @param {string} [options.cwd] - Working directory for history
|
|
876
1180
|
* @param {number} [options.maxParallel] - Max parallel steps (per batch, or
|
|
877
1181
|
* concurrent step nodes in pipeline mode)
|
|
@@ -893,6 +1197,7 @@ export async function runPipeline({
|
|
|
893
1197
|
export async function executeWorkflow(options = {}) {
|
|
894
1198
|
const {
|
|
895
1199
|
workflow,
|
|
1200
|
+
definitionDigest: requestedDefinitionDigest,
|
|
896
1201
|
cwd = process.cwd(),
|
|
897
1202
|
maxParallel = 4,
|
|
898
1203
|
continueOnError = false,
|
|
@@ -904,6 +1209,18 @@ export async function executeWorkflow(options = {}) {
|
|
|
904
1209
|
|
|
905
1210
|
const { valid, errors } = validateWorkflow(workflow);
|
|
906
1211
|
if (!valid) throw new Error(`Invalid workflow: ${errors.join("; ")}`);
|
|
1212
|
+
const definitionAuthority = createWorkflowDefinitionAuthority(workflow);
|
|
1213
|
+
if (requestedDefinitionDigest != null) {
|
|
1214
|
+
const normalizedDigest = normalizeWorkflowDefinitionDigest(
|
|
1215
|
+
requestedDefinitionDigest,
|
|
1216
|
+
);
|
|
1217
|
+
if (!normalizedDigest) {
|
|
1218
|
+
throw new Error("workflow definition digest is invalid");
|
|
1219
|
+
}
|
|
1220
|
+
if (normalizedDigest !== definitionAuthority.definitionDigest) {
|
|
1221
|
+
throw new Error("workflow definition digest mismatch");
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
907
1224
|
if (typeof _deps.runTask !== "function") {
|
|
908
1225
|
throw new Error(
|
|
909
1226
|
"cowork-workflow: _deps.runTask is not injected (wire runCoworkTask in CLI before executing)",
|
|
@@ -1107,8 +1424,11 @@ export async function executeWorkflow(options = {}) {
|
|
|
1107
1424
|
: "failed";
|
|
1108
1425
|
|
|
1109
1426
|
const record = {
|
|
1427
|
+
schema: COWORK_WORKFLOW_RUN_RECORD_SCHEMA,
|
|
1110
1428
|
workflowId: workflow.id,
|
|
1111
1429
|
workflowName: workflow.name,
|
|
1430
|
+
definitionSchema: definitionAuthority.schema,
|
|
1431
|
+
definitionDigest: definitionAuthority.definitionDigest,
|
|
1112
1432
|
status,
|
|
1113
1433
|
steps: stepOutcomes,
|
|
1114
1434
|
startedAt,
|
|
@@ -1127,7 +1447,7 @@ function _appendHistory(cwd, record) {
|
|
|
1127
1447
|
JSON.stringify(record) + "\n",
|
|
1128
1448
|
"utf-8",
|
|
1129
1449
|
);
|
|
1130
|
-
} catch
|
|
1450
|
+
} catch {
|
|
1131
1451
|
// best-effort
|
|
1132
1452
|
}
|
|
1133
1453
|
}
|