chainlesschain 0.163.5 → 0.163.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/completions/_cc +1 -1
- package/completions/cc.bash +1 -1
- package/completions/cc.fish +1 -1
- package/completions/cc.ps1 +1 -1
- package/package.json +1 -1
- package/src/assets/web-panel/assets/{AIOps-Cv2EE1Zy.js → AIOps-axqQfwv8.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-CcpxMLuW.js → ActionButton-DV-Ro0By.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-DE8mJoMI.js → Analytics-Bt72WEVu.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-DKn9dk9L.js → AppLayout-BtepG55E.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-Cp3mG3Py.js → Artifacts-B7KaJ7S_.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-zvsQfF2C.js → Audit-FNFaUg7A.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-Bi85SsjN.js → BackgroundAgents-DFb6J2wQ.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-Cw47Dj6s.js → Backup-CC7YBhyj.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-C5Ip2afH.js → BaseInput-RkgTNVtj.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-C0iAFkJv.js → Chat-hHEmGZy-.js} +5 -5
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-BV9Wv7wO.js → ChatBubbleRenderer-CAP9YhHv.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-3KZZCiAF.js → Checkbox-z5wXOQP1.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-C8OMbBAz.js → Codegen-DVaDJnxy.js} +1 -1
- package/src/assets/web-panel/assets/{Col-B-MB84LJ.js → Col-CJmaRDR5.js} +1 -1
- package/src/assets/web-panel/assets/{Community-DpR7Dxao.js → Community-DF29_2bI.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-CyDtz0OS.js → Compact-DtkQkBzn.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-5tiRa2An.js → Compliance-xoHDxp7I.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-DnQaKZ5x.js → Cowork-BUm-R7ht.js} +4 -4
- package/src/assets/web-panel/assets/{Cron-BaWfoEDf.js → Cron-Cgl14ZkB.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-Bu0HoHhb.js → Crosschain-BNcbmoqh.js} +1 -1
- package/src/assets/web-panel/assets/{DID-31zk8upX.js → DID-Bwja0Zo9.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-BmVne-e2.js → Dashboard-Bk5XjEdJ.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-B4PkoOWd.js → Dropdown-Ci36Oitq.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-BZ6tyFtI.js → EmailListRenderer--U04ZN4q.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-Osozn4Ds.js → FamilyGuardDashboard-B2gNPR2s.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-DaH8TOAP.js → Federation-C4KghYn7.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-tbU0uwis.js → FormItemContext-QL7x_Q_0.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-Df8LQBrL.js → GenericCardRenderer-F3Ryltwm.js} +1 -1
- package/src/assets/web-panel/assets/{Git-DsMB6-14.js → Git-2HassK5k.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-BnH0dZzd.js → Governance-DoBIp7oe.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-DhnN1N_P.js → Inference--W01QhZ-.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-DnNshAgn.js → KnowledgeGraph-DmvwqGpT.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-BmBFX3_N.js → Logs-BBJ4yAel.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-DCslfQU3.js → MarkdownRenderer-BLCZMzhJ.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-CPEgWDc3.js → Marketplace-D5lNngSI.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-C36qjgF9.js → McpTools-CkEVOMKH.js} +5 -5
- package/src/assets/web-panel/assets/{Memory-tNHvrgqN.js → Memory-B1Ow1xVE.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-Xaf6cKjc.js → MobileBridge-SgYbUfb6.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-D2E5TTeO.js → MobileProjects-BWdOvQAj.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-D4AJ2dwV.js → Mtc-DcTXSSma.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-Df-gtn2_.js → MtcAudit-Dt3WG4oj.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig-DTCHLWld.js → Multisig-B9B38UZx.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-DruZ_1Jb.js → NLProgramming-B0S4GGvG.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-Dx3pdGDs.js → Notes-DZ5U58Ng.js} +4 -4
- package/src/assets/web-panel/assets/{NotificationSettings-Bi3L69oL.js → NotificationSettings-PjL5ZW34.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-BHY33m7C.js → OrderTableRenderer-DrAX2ESt.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-BG2ZVEV-.js → Organization-Cv1GYs-c.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-Viwtg4Mn.js → Overflow-Bbkp_PL3.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-Clm_yc1Z.js → P2P-BD8QUgoZ.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-NKmmDiOw.js → PdhVaultBrowser-BO-2PeaB.js} +5 -5
- package/src/assets/web-panel/assets/{Permissions-DIL8u9Nk.js → Permissions-D_OPVa02.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-B-jM4wt-.js → PersonalDataHub-mh-pEmaB.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-627I__H5.js → Pipeline-6JC2EDdb.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-2DN2qrkW.js → Privacy-CUshzUAG.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-CN4wC0sF.js → ProjectInit-Cs2Aalri.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-K35vsh5H.js → ProjectSettings-1ak49tcj.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-B_wQadhX.js → Projects-BV4oApsm.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-MckaQUhQ.js → Providers-CXXxvafH.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-BS3mtA_O.js → QrScannerModal-PTcDsF58.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-BHp_nofL.js → QuickAsk-CDwucrJw.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-DlmnPuZj.js → Recommend-CJlLVRXR.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-tsyFbvpy.js → RemoteSession-DlN-ETsO.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-Ba1iWv2D.js → Reputation-DI23LR6m.js} +1 -1
- package/src/assets/web-panel/assets/{Row-NnlGC--f.js → Row-Cl7UQMrM.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-CjThSIRv.js → RssFeed-CexHNfh8.js} +3 -3
- package/src/assets/web-panel/assets/{Search-CojUyC5x.js → Search-BneBWvRN.js} +1 -1
- package/src/assets/web-panel/assets/{Security-c-sxeJEc.js → Security-DX7Phgrp.js} +4 -4
- package/src/assets/web-panel/assets/{Services-CtcKEEmF.js → Services-BWXO8Mte.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-CIBBXflN.js → Skeleton-DCyOjKPJ.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-D1XOOK9n.js → Skills-CXqERsTB.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-hRfEp5Sn.js → Sla-bhbrbz8E.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-Dexb1f_6.js → SpeechSettings-3IPU0HBZ.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-BJsSFGYy.js → SyncSettings-DBNTQLbM.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-CfSZ8A1L.js → Tasks-quP0bkN-.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-idDf47W-.js → Templates-BouWmgho.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-C-UsX6w6.js → Tenant-qv0D9s7z.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-BgJtX5n1.js → Terminal-BxvbE8BB.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-DP0BLKTl.js → TimelineRenderer-D-IeLnJ2.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-LwCzqETp.js → Tokens-CFMKKyVG.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-D_9tVch0.js → Trigger-L8as3UuJ.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-BH2UlEWh.js → Trust-MxmA4VZG.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-CIpD0nYb.js → UkeySign-C0VvJYRi.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-9ShhYxK_.js → VideoEditing-Bf5QZj8N.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-C7afGNIG.js → Wallet-BIJ9riRz.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-bUKn6i5R.js → WebAuthn-B8p9Mhkw.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-CxgQaGyp.js → WorkflowEditor-BVsuaPen.js} +1 -1
- package/src/assets/web-panel/assets/{chat-DMVkmJwx.js → chat-BfkjoKpV.js} +1 -1
- package/src/assets/web-panel/assets/{colors-CDzQh5nS.js → colors-DeAlsWK8.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-C51kEF4D.js → compact-item-Cs97bz5j.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-BTk9bXBn.js → createContext-BqbG60LH.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-DPty0mGN.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-CMje33rb.js → hasIn-i_RY0b1X.js} +1 -1
- package/src/assets/web-panel/assets/{index-DpcrFxMI.js → index-0-agYlWL.js} +1 -1
- package/src/assets/web-panel/assets/{index-BW4F5YDF.js → index-79V_zv1s.js} +1 -1
- package/src/assets/web-panel/assets/{index-DRG-aqOs.js → index-B-3tEpTc.js} +1 -1
- package/src/assets/web-panel/assets/{index-BCRvG9lq.js → index-B-JVTrpr.js} +1 -1
- package/src/assets/web-panel/assets/{index-DgivOKHA.js → index-B1CbOH1i.js} +1 -1
- package/src/assets/web-panel/assets/{index-BzCkNylB.js → index-B5UkyA3c.js} +1 -1
- package/src/assets/web-panel/assets/{index-x53Vf7la.js → index-BESLFt4q.js} +1 -1
- package/src/assets/web-panel/assets/{index-CCLj9hcD.js → index-BOVkf1K3.js} +1 -1
- package/src/assets/web-panel/assets/{index-CypsfcEq.js → index-BYUVuwKt.js} +1 -1
- package/src/assets/web-panel/assets/{index-BtlEqHLP.js → index-BcUXAB2s.js} +1 -1
- package/src/assets/web-panel/assets/{index-Ld_4mFmC.js → index-BkBi5TmC.js} +1 -1
- package/src/assets/web-panel/assets/{index-DqU9njjT.js → index-Bm7lLR4c.js} +1 -1
- package/src/assets/web-panel/assets/index-Bt7g0Vq_.js +1 -0
- package/src/assets/web-panel/assets/{index-CwGPwjUu.js → index-BuLQobzW.js} +1 -1
- package/src/assets/web-panel/assets/{index-C5IWTMVl.js → index-CE2VtTlp.js} +1 -1
- package/src/assets/web-panel/assets/{index-DJfnCuMq.js → index-CED2PL_y.js} +1 -1
- package/src/assets/web-panel/assets/{index-hg_emBsi.js → index-CG3PRyAL.js} +1 -1
- package/src/assets/web-panel/assets/{index-togc_uYn.js → index-CIG8fQ2_.js} +1 -1
- package/src/assets/web-panel/assets/{index-C4rQCS8T.js → index-COdGA-8n.js} +1 -1
- package/src/assets/web-panel/assets/{index-0Auljb10.js → index-CeWoNHau.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cd0hmPxD.js → index-Cf3WCLmy.js} +1 -1
- package/src/assets/web-panel/assets/{index-BXQBPLyE.js → index-CgsqdnRV.js} +1 -1
- package/src/assets/web-panel/assets/index-ChVT0p9u.js +1 -0
- package/src/assets/web-panel/assets/{index-h31MwrME.js → index-D2B4VPyP.js} +1 -1
- package/src/assets/web-panel/assets/{index-C1oZReaY.js → index-D9evtvg2.js} +1 -1
- package/src/assets/web-panel/assets/{index-CfC-piWZ.js → index-DUUrv141.js} +1 -1
- package/src/assets/web-panel/assets/{index-D9rC-fGW.js → index-DiSkx4UB.js} +3 -3
- package/src/assets/web-panel/assets/{index-CvSeVzqe.js → index-Dk2qouAz.js} +1 -1
- package/src/assets/web-panel/assets/{index-CtM8OT_7.js → index-Dk7-v4hP.js} +1 -1
- package/src/assets/web-panel/assets/{index-BBz9LIMS.js → index-DmbfhJUP.js} +1 -1
- package/src/assets/web-panel/assets/{index-BAfY7m7i.js → index-DqBgBpgp.js} +1 -1
- package/src/assets/web-panel/assets/{index-BVePe_Rf.js → index-PT_5sBMA.js} +1 -1
- package/src/assets/web-panel/assets/{index-CDLkNkLj.js → index-U4f5izHz.js} +1 -1
- package/src/assets/web-panel/assets/{index-BTlsE8Df.js → index-YXgLng0K.js} +1 -1
- package/src/assets/web-panel/assets/{index-BeEaAEIp.js → index-ZxO_-E8a.js} +1 -1
- package/src/assets/web-panel/assets/{index-B0-zMtKA.js → index-dIHr4B_u.js} +1 -1
- package/src/assets/web-panel/assets/{index-C1oZQmAA.js → index-gyFpvL7l.js} +1 -1
- package/src/assets/web-panel/assets/{index-DRLQyp2A.js → index-s1opAL-M.js} +1 -1
- package/src/assets/web-panel/assets/{index-OS-vfbTA.js → index-yObj1O4n.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-vrA8K-ac.js → initDefaultProps-C9h9yKL3.js} +1 -1
- package/src/assets/web-panel/assets/{motion-ByEzwIAl.js → motion-BvmLsPdu.js} +1 -1
- package/src/assets/web-panel/assets/{move-Ck4AWjw-.js → move-CoL4ekU1.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-6p0l9SrB.js → mtc-parser-C4pMy6xV.js} +1 -1
- package/src/assets/web-panel/assets/{omit-B1CUPQ6R.js → omit-DPuJfNxx.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-B1STg1iW.js → pickAttrs-D0KEeaK2.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-DTTllkBV.js → placementArrow-BpkyINxt.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-AIrrCfBb.js → responsiveObserve-DQI_wOq8.js} +1 -1
- package/src/assets/web-panel/assets/{slide-C_fPMjdR.js → slide-DYfdDiRg.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-D5ow2yIP.js → statusUtils-B5dtvb0D.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-Dy3hEA--.js → styleChecker-CF310mSj.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-WfzcfSh4.js → useFlexGapSupport-D1Qp4BLp.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-CKSejfas.js → useFs-C7_iyvJK.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-od3zpPBN.js → usePersonalDataHub-DZUt_fIm.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-DRD_2DFA.js → vnode-D3dsi0lZ.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-DmNrEtgf.js → zoom-WdbOlvdQ.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +5 -5
- package/src/command-manifest.json +1 -1
- package/src/commands/agenda.js +76 -4
- package/src/commands/agent.js +90 -1
- package/src/commands/automation.js +462 -3
- package/src/commands/background-session.js +102 -1
- package/src/commands/chat.js +11 -2
- package/src/commands/compact.js +106 -23
- package/src/commands/cowork.js +6 -1
- package/src/commands/loop.js +187 -38
- package/src/commands/routine.js +12 -5
- package/src/commands/scheduler-daemon.js +807 -0
- package/src/commands/session-observability.js +305 -0
- package/src/commands/session.js +38 -0
- package/src/data/changelog.json +28 -2
- package/src/gateways/ws/ws-agent-handler.js +439 -5
- package/src/harness/jsonl-session-store.js +463 -125
- package/src/harness/prompt-compressor.js +86 -13
- package/src/harness/provider-backed-compaction.js +100 -27
- package/src/lib/advisor-runtime.js +3 -1
- package/src/lib/agent-schedule-store.js +737 -47
- package/src/lib/agent-team/team-adjudication.js +40 -1
- package/src/lib/automation-center-routines.js +363 -0
- package/src/lib/automation-center.js +435 -0
- package/src/lib/automation-engine.js +568 -19
- package/src/lib/automation-execution-authority.js +736 -0
- package/src/lib/background-agent-supervisor.js +871 -215
- package/src/lib/background-command-argv.js +24 -0
- package/src/lib/background-interaction-journal.js +361 -52
- package/src/lib/background-interaction-resolver.js +32 -0
- package/src/lib/background-launch-profile.js +2 -0
- package/src/lib/background-needs-input-incident.js +221 -0
- package/src/lib/causal-observability.js +2661 -0
- package/src/lib/chat-session-admission.js +76 -0
- package/src/lib/cost-budget.js +5 -7
- package/src/lib/cowork/ab-comparator-cli.js +11 -0
- package/src/lib/cowork/debate-review-cli.js +12 -0
- package/src/lib/cowork-adapter.js +159 -38
- package/src/lib/cowork-cron.js +673 -19
- package/src/lib/cowork-observe.js +5 -1
- package/src/lib/cowork-task-runner.js +112 -17
- package/src/lib/delivery-coordinator.js +142 -0
- package/src/lib/direct-model-usage.js +121 -0
- package/src/lib/file-lines.js +183 -47
- package/src/lib/llm-pricing.js +12 -17
- package/src/lib/loop.js +62 -3
- package/src/lib/permission-engine.js +14 -7
- package/src/lib/public-ide-capability-manifest.js +2 -0
- package/src/lib/routine-store.js +546 -86
- package/src/lib/runtime-usage-ledger.js +182 -0
- package/src/lib/scheduler-kernel/agenda-adapter.js +604 -29
- package/src/lib/scheduler-kernel/authority-resolver.js +163 -0
- package/src/lib/scheduler-kernel/automation-adapter.js +994 -0
- package/src/lib/scheduler-kernel/automation-event-adapter.js +757 -0
- package/src/lib/scheduler-kernel/contract.js +11 -3
- package/src/lib/scheduler-kernel/cowork-cron-adapter.js +343 -15
- package/src/lib/scheduler-kernel/loop-adapter.js +913 -0
- package/src/lib/scheduler-kernel/migration-admin.js +346 -0
- package/src/lib/scheduler-kernel/migration-rollback-admin.js +932 -0
- package/src/lib/scheduler-kernel/routine-adapter.js +691 -22
- package/src/lib/scheduler-kernel/runtime.js +63 -1
- package/src/lib/scheduler-kernel/service.js +328 -0
- package/src/lib/scheduler-kernel/source-locator-path.js +142 -0
- package/src/lib/scheduler-kernel/store.js +3439 -206
- package/src/lib/session-host-lease.js +171 -2
- package/src/lib/session-host-snapshot.js +14 -3
- package/src/lib/session-persistence-failure.js +1 -0
- package/src/lib/session-tail.js +179 -34
- package/src/lib/session-transcript-structure.js +96 -0
- package/src/lib/sub-agent-context.js +328 -22
- package/src/lib/ws-agent-handler.js +4 -1
- package/src/repl/agent-repl.js +732 -91
- package/src/repl/chat-repl.js +5 -1
- package/src/runtime/agent-core.js +1274 -208
- package/src/runtime/coding-agent-contract-shared.cjs +5 -0
- package/src/runtime/fallback-model.js +5 -0
- package/src/runtime/headless-runner.js +324 -82
- package/src/runtime/headless-stream.js +232 -26
- package/src/runtime/policies/agent-policy.js +4 -0
- package/src/workers/background-agent-worker.js +468 -98
- package/src/assets/web-panel/assets/devWarning-CdwPwYj8.js +0 -1
- package/src/assets/web-panel/assets/index-BEeOdfEe.js +0 -1
- package/src/assets/web-panel/assets/index-BTe0TOu6.js +0 -1
|
@@ -0,0 +1,435 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import {
|
|
3
|
+
automationExecutionAuthorityDigest,
|
|
4
|
+
automationExecutionAuthoritySnapshot,
|
|
5
|
+
inspectAutomationExecutionAuthority,
|
|
6
|
+
reserveAutomationExecutionAuthority,
|
|
7
|
+
} from "./automation-execution-authority.js";
|
|
8
|
+
import {
|
|
9
|
+
EXECUTION_STATUS,
|
|
10
|
+
FLOW_STATUS,
|
|
11
|
+
TRIGGER_TYPE,
|
|
12
|
+
deleteFlow,
|
|
13
|
+
executeFlow,
|
|
14
|
+
getExecution,
|
|
15
|
+
getFlow,
|
|
16
|
+
listExecutions,
|
|
17
|
+
listFlows,
|
|
18
|
+
listTriggers,
|
|
19
|
+
updateFlowStatus,
|
|
20
|
+
} from "./automation-engine.js";
|
|
21
|
+
import {
|
|
22
|
+
SchedulerKernelError,
|
|
23
|
+
canonicalJson,
|
|
24
|
+
normalizeIdentifier,
|
|
25
|
+
} from "./scheduler-kernel/contract.js";
|
|
26
|
+
import { RoutineStore } from "./routine-store.js";
|
|
27
|
+
import { buildRoutineCenterProjection } from "./automation-center-routines.js";
|
|
28
|
+
|
|
29
|
+
export const AUTOMATION_CENTER_SCHEMA = "chainlesschain.automation-center/v2";
|
|
30
|
+
export const AUTOMATION_CENTER_SCHEMA_VERSION = 2;
|
|
31
|
+
export const AUTOMATION_CENTER_ACTIONS = Object.freeze([
|
|
32
|
+
"run_now",
|
|
33
|
+
"retry_failed",
|
|
34
|
+
"pause",
|
|
35
|
+
"resume",
|
|
36
|
+
"disable",
|
|
37
|
+
"delete",
|
|
38
|
+
]);
|
|
39
|
+
|
|
40
|
+
function centerError(code, message, details = undefined) {
|
|
41
|
+
const error = new SchedulerKernelError(code, message, details);
|
|
42
|
+
error.retryable = false;
|
|
43
|
+
return error;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function digest(value) {
|
|
47
|
+
return `sha256:${createHash("sha256")
|
|
48
|
+
.update("chainlesschain.automation-center.v2\0", "utf8")
|
|
49
|
+
.update(canonicalJson(value, "automationCenter"), "utf8")
|
|
50
|
+
.digest("hex")}`;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function boundedText(value, maximum = 240) {
|
|
54
|
+
return String(value || "")
|
|
55
|
+
.replace(/[\r\n]+/g, " ")
|
|
56
|
+
.slice(0, maximum);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function safeTriggerScope(trigger) {
|
|
60
|
+
const config = trigger?.config || {};
|
|
61
|
+
if (trigger.type === TRIGGER_TYPE.EVENT) {
|
|
62
|
+
return {
|
|
63
|
+
event: boundedText(config.event, 80) || null,
|
|
64
|
+
origins: Array.isArray(config.scope?.origins)
|
|
65
|
+
? config.scope.origins
|
|
66
|
+
.map((value) => boundedText(value, 64))
|
|
67
|
+
.slice(0, 16)
|
|
68
|
+
: [],
|
|
69
|
+
senders: Array.isArray(config.scope?.senders)
|
|
70
|
+
? config.scope.senders
|
|
71
|
+
.map((value) => boundedText(value, 96))
|
|
72
|
+
.slice(0, 32)
|
|
73
|
+
: [],
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
if (trigger.type === TRIGGER_TYPE.SCHEDULE) {
|
|
77
|
+
return { cron: boundedText(config.cron, 120) || null };
|
|
78
|
+
}
|
|
79
|
+
if (trigger.type === TRIGGER_TYPE.WEBHOOK) {
|
|
80
|
+
// Webhook URLs often embed bearer material. The center reports that a
|
|
81
|
+
// route is configured without reflecting the URL into privileged IDE UI.
|
|
82
|
+
return {
|
|
83
|
+
endpointConfigured: typeof config.url === "string" && Boolean(config.url),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
if (trigger.type === TRIGGER_TYPE.CONDITION) {
|
|
87
|
+
return { expression: boundedText(config.expression, 240) || null };
|
|
88
|
+
}
|
|
89
|
+
return {};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function projectTrigger(trigger) {
|
|
93
|
+
return {
|
|
94
|
+
id: trigger.id,
|
|
95
|
+
type: trigger.type,
|
|
96
|
+
enabled: trigger.enabled === true,
|
|
97
|
+
scope: safeTriggerScope(trigger),
|
|
98
|
+
triggerCount: Number(trigger.triggerCount) || 0,
|
|
99
|
+
lastTriggeredAt: trigger.lastTriggeredAt || null,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function projectExecution(execution) {
|
|
104
|
+
return {
|
|
105
|
+
id: execution.id,
|
|
106
|
+
status: execution.status,
|
|
107
|
+
triggerType: execution.triggerType || null,
|
|
108
|
+
durationMs: Number(execution.durationMs) || 0,
|
|
109
|
+
startedAt: execution.startedAt || null,
|
|
110
|
+
completedAt: execution.completedAt || null,
|
|
111
|
+
error: execution.error ? boundedText(execution.error, 400) : null,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function projectSecurity(db, flow, now) {
|
|
116
|
+
try {
|
|
117
|
+
const result = inspectAutomationExecutionAuthority(db, flow, { now });
|
|
118
|
+
return {
|
|
119
|
+
state: result.ready ? "ready" : "denied",
|
|
120
|
+
ready: result.ready,
|
|
121
|
+
principalId: result.snapshot.principalId,
|
|
122
|
+
connectors: result.snapshot.connectors,
|
|
123
|
+
permissions: result.permissions,
|
|
124
|
+
budget: {
|
|
125
|
+
revision: result.snapshot.budget.revision,
|
|
126
|
+
windowMs: result.snapshot.budget.windowMs,
|
|
127
|
+
maxRuns: result.snapshot.budget.maxRuns,
|
|
128
|
+
maxActionSteps: result.snapshot.budget.maxActionSteps,
|
|
129
|
+
...result.window,
|
|
130
|
+
},
|
|
131
|
+
issue: null,
|
|
132
|
+
};
|
|
133
|
+
} catch (error) {
|
|
134
|
+
const code = boundedText(
|
|
135
|
+
error?.code || "AUTOMATION_EXECUTION_PREFLIGHT_FAILED",
|
|
136
|
+
96,
|
|
137
|
+
);
|
|
138
|
+
return {
|
|
139
|
+
state:
|
|
140
|
+
code === "AUTOMATION_EXECUTION_BUDGET_REQUIRED" ||
|
|
141
|
+
code === "AUTOMATION_EXECUTION_PRINCIPAL_REQUIRED"
|
|
142
|
+
? "unconfigured"
|
|
143
|
+
: "invalid",
|
|
144
|
+
ready: false,
|
|
145
|
+
principalId:
|
|
146
|
+
typeof flow.createdBy === "string" && flow.createdBy
|
|
147
|
+
? flow.createdBy
|
|
148
|
+
: null,
|
|
149
|
+
connectors: [],
|
|
150
|
+
permissions: [],
|
|
151
|
+
budget: null,
|
|
152
|
+
issue: { code, message: boundedText(error?.message || error, 400) },
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function action(id, available, reason, flowId, itemRevision) {
|
|
158
|
+
return {
|
|
159
|
+
id,
|
|
160
|
+
available,
|
|
161
|
+
reason: available ? null : reason,
|
|
162
|
+
preview: available
|
|
163
|
+
? {
|
|
164
|
+
executor: "cli",
|
|
165
|
+
argv: [
|
|
166
|
+
"automation",
|
|
167
|
+
"center-action",
|
|
168
|
+
flowId,
|
|
169
|
+
id,
|
|
170
|
+
"--expected-revision",
|
|
171
|
+
itemRevision,
|
|
172
|
+
"--json",
|
|
173
|
+
],
|
|
174
|
+
mutates: true,
|
|
175
|
+
}
|
|
176
|
+
: null,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function projectFlow(db, flow, { historyLimit, now }) {
|
|
181
|
+
const triggers = listTriggers(db, flow.id).map(projectTrigger);
|
|
182
|
+
const history = listExecutions(db, {
|
|
183
|
+
flowId: flow.id,
|
|
184
|
+
limit: historyLimit,
|
|
185
|
+
}).map(projectExecution);
|
|
186
|
+
const security = projectSecurity(db, flow, now);
|
|
187
|
+
const content = {
|
|
188
|
+
kind: "flow",
|
|
189
|
+
id: flow.id,
|
|
190
|
+
name: boundedText(flow.name, 200),
|
|
191
|
+
description: boundedText(flow.description, 500),
|
|
192
|
+
status: flow.status,
|
|
193
|
+
schedule: flow.schedule || null,
|
|
194
|
+
updatedAt: flow.updatedAt || null,
|
|
195
|
+
triggers,
|
|
196
|
+
history,
|
|
197
|
+
security,
|
|
198
|
+
};
|
|
199
|
+
const revision = digest(content);
|
|
200
|
+
const active = flow.status === FLOW_STATUS.ACTIVE;
|
|
201
|
+
const paused = flow.status === FLOW_STATUS.PAUSED;
|
|
202
|
+
const archived = flow.status === FLOW_STATUS.ARCHIVED;
|
|
203
|
+
const latestFailed = history[0]?.status === EXECUTION_STATUS.FAILED;
|
|
204
|
+
return {
|
|
205
|
+
...content,
|
|
206
|
+
revision,
|
|
207
|
+
actions: [
|
|
208
|
+
action(
|
|
209
|
+
"run_now",
|
|
210
|
+
active && security.ready,
|
|
211
|
+
!active
|
|
212
|
+
? "flow is not active"
|
|
213
|
+
: "permission or budget preflight denied",
|
|
214
|
+
flow.id,
|
|
215
|
+
revision,
|
|
216
|
+
),
|
|
217
|
+
action(
|
|
218
|
+
"retry_failed",
|
|
219
|
+
active && latestFailed && security.ready,
|
|
220
|
+
!active
|
|
221
|
+
? "flow is not active"
|
|
222
|
+
: !latestFailed
|
|
223
|
+
? "latest run did not fail"
|
|
224
|
+
: "permission or budget preflight denied",
|
|
225
|
+
flow.id,
|
|
226
|
+
revision,
|
|
227
|
+
),
|
|
228
|
+
action(
|
|
229
|
+
"pause",
|
|
230
|
+
active,
|
|
231
|
+
"only an active flow can be paused",
|
|
232
|
+
flow.id,
|
|
233
|
+
revision,
|
|
234
|
+
),
|
|
235
|
+
action(
|
|
236
|
+
"resume",
|
|
237
|
+
paused && security.ready,
|
|
238
|
+
!paused
|
|
239
|
+
? "only a paused flow can be resumed"
|
|
240
|
+
: "permission or budget preflight denied",
|
|
241
|
+
flow.id,
|
|
242
|
+
revision,
|
|
243
|
+
),
|
|
244
|
+
action(
|
|
245
|
+
"disable",
|
|
246
|
+
!archived,
|
|
247
|
+
"flow is already disabled",
|
|
248
|
+
flow.id,
|
|
249
|
+
revision,
|
|
250
|
+
),
|
|
251
|
+
action(
|
|
252
|
+
"delete",
|
|
253
|
+
archived,
|
|
254
|
+
"disable the flow before deleting it",
|
|
255
|
+
flow.id,
|
|
256
|
+
revision,
|
|
257
|
+
),
|
|
258
|
+
],
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export function buildAutomationCenterProjection(
|
|
263
|
+
db,
|
|
264
|
+
{
|
|
265
|
+
limit = 100,
|
|
266
|
+
historyLimit = 20,
|
|
267
|
+
now = Date.now,
|
|
268
|
+
routineStore = new RoutineStore(),
|
|
269
|
+
} = {},
|
|
270
|
+
) {
|
|
271
|
+
if (typeof now !== "function") {
|
|
272
|
+
throw centerError(
|
|
273
|
+
"AUTOMATION_CENTER_CLOCK_REQUIRED",
|
|
274
|
+
"automation center requires a clock",
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
const boundedLimit = Math.max(1, Math.min(1000, Number(limit) || 100));
|
|
278
|
+
const boundedHistory = Math.max(1, Math.min(100, Number(historyLimit) || 20));
|
|
279
|
+
const flows = listFlows(db, { limit: boundedLimit }).map((flow) =>
|
|
280
|
+
projectFlow(db, flow, { historyLimit: boundedHistory, now }),
|
|
281
|
+
);
|
|
282
|
+
const routineProjection = buildRoutineCenterProjection(routineStore, {
|
|
283
|
+
limit: boundedLimit,
|
|
284
|
+
historyLimit: boundedHistory,
|
|
285
|
+
});
|
|
286
|
+
const items = [...flows, ...routineProjection.items];
|
|
287
|
+
const summary = {
|
|
288
|
+
total: items.length,
|
|
289
|
+
flows: flows.length,
|
|
290
|
+
routines: routineProjection.items.length,
|
|
291
|
+
active: items.filter((item) => item.status === FLOW_STATUS.ACTIVE).length,
|
|
292
|
+
paused: items.filter((item) => item.status === FLOW_STATUS.PAUSED).length,
|
|
293
|
+
needsAttention: items.filter(
|
|
294
|
+
(item) =>
|
|
295
|
+
item.security.ready !== true ||
|
|
296
|
+
item.history[0]?.status === EXECUTION_STATUS.FAILED ||
|
|
297
|
+
item.history[0]?.status === "failed",
|
|
298
|
+
).length,
|
|
299
|
+
};
|
|
300
|
+
return {
|
|
301
|
+
schema: AUTOMATION_CENTER_SCHEMA,
|
|
302
|
+
schemaVersion: AUTOMATION_CENTER_SCHEMA_VERSION,
|
|
303
|
+
authority: "cli",
|
|
304
|
+
connected: true,
|
|
305
|
+
generatedAt: new Date(Number(now())).toISOString(),
|
|
306
|
+
routineCatalogRevision: routineProjection.catalogRevision,
|
|
307
|
+
revision: digest({
|
|
308
|
+
summary,
|
|
309
|
+
mutations: {
|
|
310
|
+
createRoutine: routineProjection.createRoutine.preview.argv,
|
|
311
|
+
routineCatalogRevision: routineProjection.catalogRevision,
|
|
312
|
+
},
|
|
313
|
+
items: items.map((item) => ({
|
|
314
|
+
kind: item.kind,
|
|
315
|
+
id: item.id,
|
|
316
|
+
revision: item.revision,
|
|
317
|
+
})),
|
|
318
|
+
}),
|
|
319
|
+
summary,
|
|
320
|
+
mutations: { createRoutine: routineProjection.createRoutine },
|
|
321
|
+
items,
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function executionIdFor(flowId, requestedAction, revision) {
|
|
326
|
+
return `exec-center-${createHash("sha256")
|
|
327
|
+
.update(`${flowId}\0${requestedAction}\0${revision}`, "utf8")
|
|
328
|
+
.digest("hex")}`;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
export function runAutomationCenterAction(
|
|
332
|
+
db,
|
|
333
|
+
{ flowId, action: requestedAction, expectedRevision, now = Date.now } = {},
|
|
334
|
+
) {
|
|
335
|
+
const id = normalizeIdentifier(flowId, "flowId");
|
|
336
|
+
if (!AUTOMATION_CENTER_ACTIONS.includes(requestedAction)) {
|
|
337
|
+
throw centerError(
|
|
338
|
+
"AUTOMATION_CENTER_ACTION_INVALID",
|
|
339
|
+
`unsupported automation center action: ${requestedAction}`,
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
const flow = getFlow(db, id);
|
|
343
|
+
if (!flow) {
|
|
344
|
+
throw centerError(
|
|
345
|
+
"AUTOMATION_CENTER_FLOW_NOT_FOUND",
|
|
346
|
+
`automation flow not found: ${id}`,
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
const item = projectFlow(db, flow, { historyLimit: 20, now });
|
|
350
|
+
if (expectedRevision !== item.revision) {
|
|
351
|
+
throw centerError(
|
|
352
|
+
"AUTOMATION_CENTER_STALE",
|
|
353
|
+
`automation flow changed before ${requestedAction}: ${id}`,
|
|
354
|
+
{ expectedRevision, currentRevision: item.revision },
|
|
355
|
+
);
|
|
356
|
+
}
|
|
357
|
+
const capability = item.actions.find((entry) => entry.id === requestedAction);
|
|
358
|
+
if (!capability?.available) {
|
|
359
|
+
throw centerError(
|
|
360
|
+
"AUTOMATION_CENTER_ACTION_UNAVAILABLE",
|
|
361
|
+
capability?.reason ||
|
|
362
|
+
`automation action is unavailable: ${requestedAction}`,
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
let result;
|
|
367
|
+
let retryOf = null;
|
|
368
|
+
if (requestedAction === "pause") {
|
|
369
|
+
result = updateFlowStatus(db, id, FLOW_STATUS.PAUSED);
|
|
370
|
+
} else if (requestedAction === "resume") {
|
|
371
|
+
result = updateFlowStatus(db, id, FLOW_STATUS.ACTIVE);
|
|
372
|
+
} else if (requestedAction === "disable") {
|
|
373
|
+
result = updateFlowStatus(db, id, FLOW_STATUS.ARCHIVED);
|
|
374
|
+
} else if (requestedAction === "delete") {
|
|
375
|
+
if (typeof db.transaction !== "function") {
|
|
376
|
+
throw centerError(
|
|
377
|
+
"AUTOMATION_CENTER_TRANSACTION_REQUIRED",
|
|
378
|
+
"deleting an automation flow requires a transactional database",
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
result = db
|
|
382
|
+
.transaction(() => {
|
|
383
|
+
db.prepare(
|
|
384
|
+
"DELETE FROM auto_execution_budget_reservations WHERE flow_id = ?",
|
|
385
|
+
).run(id);
|
|
386
|
+
db.prepare(
|
|
387
|
+
"DELETE FROM auto_execution_budget_usage WHERE flow_id = ?",
|
|
388
|
+
).run(id);
|
|
389
|
+
db.prepare("DELETE FROM auto_execution_budgets WHERE flow_id = ?").run(
|
|
390
|
+
id,
|
|
391
|
+
);
|
|
392
|
+
deleteFlow(db, id);
|
|
393
|
+
return { deleted: true };
|
|
394
|
+
})
|
|
395
|
+
.immediate();
|
|
396
|
+
} else {
|
|
397
|
+
const authority = automationExecutionAuthoritySnapshot(db, flow);
|
|
398
|
+
const occurrenceId = `automation-center:${requestedAction}:${id}:${item.revision.slice("sha256:".length)}`;
|
|
399
|
+
reserveAutomationExecutionAuthority(
|
|
400
|
+
db,
|
|
401
|
+
flow,
|
|
402
|
+
occurrenceId,
|
|
403
|
+
authority,
|
|
404
|
+
automationExecutionAuthorityDigest(authority, flow),
|
|
405
|
+
{ now },
|
|
406
|
+
);
|
|
407
|
+
let inputData = { source: "automation-center" };
|
|
408
|
+
if (requestedAction === "retry_failed") {
|
|
409
|
+
const failed = getExecution(db, item.history[0].id);
|
|
410
|
+
if (!failed || failed.status !== EXECUTION_STATUS.FAILED) {
|
|
411
|
+
throw centerError(
|
|
412
|
+
"AUTOMATION_CENTER_FAILED_RUN_CHANGED",
|
|
413
|
+
`failed automation run changed before retry: ${id}`,
|
|
414
|
+
);
|
|
415
|
+
}
|
|
416
|
+
retryOf = failed.id;
|
|
417
|
+
inputData = failed.inputData;
|
|
418
|
+
}
|
|
419
|
+
result = executeFlow(db, id, {
|
|
420
|
+
triggerType: TRIGGER_TYPE.MANUAL,
|
|
421
|
+
inputData,
|
|
422
|
+
executionId: executionIdFor(id, requestedAction, item.revision),
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
return {
|
|
426
|
+
schema: "chainlesschain.automation-center-action/v1",
|
|
427
|
+
schemaVersion: 1,
|
|
428
|
+
authority: "cli",
|
|
429
|
+
flowId: id,
|
|
430
|
+
action: requestedAction,
|
|
431
|
+
previousRevision: item.revision,
|
|
432
|
+
...(retryOf ? { retryOf } : {}),
|
|
433
|
+
result,
|
|
434
|
+
};
|
|
435
|
+
}
|