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
|
@@ -50,6 +50,12 @@ import {
|
|
|
50
50
|
stripBackgroundLaunchSecrets,
|
|
51
51
|
verifyBackgroundLaunchProfileSources,
|
|
52
52
|
} from "./background-launch-profile.js";
|
|
53
|
+
import {
|
|
54
|
+
BACKGROUND_AGENT_KEEPER_POWERSHELL_TIMEOUT_MS,
|
|
55
|
+
BACKGROUND_AGENT_KEEPER_TASKKILL_TIMEOUT_MS,
|
|
56
|
+
BACKGROUND_AGENT_KEEPER_WMIC_TIMEOUT_MS,
|
|
57
|
+
backgroundAgentKeeperPipePath,
|
|
58
|
+
} from "./background-agent-keeper-protocol.js";
|
|
53
59
|
|
|
54
60
|
export const DEFAULT_HEARTBEAT_INTERVAL_MS = 5000;
|
|
55
61
|
export const DEFAULT_HEARTBEAT_STALE_MS = 120000;
|
|
@@ -126,7 +132,11 @@ function defaultReadProcessStartTimeMs(pid) {
|
|
|
126
132
|
"CreationDate",
|
|
127
133
|
"/value",
|
|
128
134
|
],
|
|
129
|
-
{
|
|
135
|
+
{
|
|
136
|
+
windowsHide: true,
|
|
137
|
+
encoding: "utf8",
|
|
138
|
+
timeout: BACKGROUND_AGENT_KEEPER_WMIC_TIMEOUT_MS,
|
|
139
|
+
},
|
|
130
140
|
"background-agent:process-start-time",
|
|
131
141
|
);
|
|
132
142
|
if (!r.error && r.status === 0) {
|
|
@@ -144,7 +154,11 @@ function defaultReadProcessStartTimeMs(pid) {
|
|
|
144
154
|
const r = runSupervisorCommand(
|
|
145
155
|
"powershell",
|
|
146
156
|
["-NoProfile", "-NonInteractive", "-Command", script],
|
|
147
|
-
{
|
|
157
|
+
{
|
|
158
|
+
windowsHide: true,
|
|
159
|
+
encoding: "utf8",
|
|
160
|
+
timeout: BACKGROUND_AGENT_KEEPER_POWERSHELL_TIMEOUT_MS,
|
|
161
|
+
},
|
|
148
162
|
"background-agent:process-start-time",
|
|
149
163
|
);
|
|
150
164
|
if (!r.error && r.status === 0) {
|
|
@@ -276,6 +290,7 @@ function defaultKillProcessTree(pid, signal = "SIGKILL") {
|
|
|
276
290
|
{
|
|
277
291
|
windowsHide: true,
|
|
278
292
|
encoding: "utf8",
|
|
293
|
+
timeout: BACKGROUND_AGENT_KEEPER_TASKKILL_TIMEOUT_MS,
|
|
279
294
|
},
|
|
280
295
|
"background-agent:process-tree-kill",
|
|
281
296
|
);
|
|
@@ -309,6 +324,7 @@ export const _deps = {
|
|
|
309
324
|
processExitWaitDeadlineMs: 2_000,
|
|
310
325
|
killProcessTree: defaultKillProcessTree,
|
|
311
326
|
terminateOwnedProcessTree,
|
|
327
|
+
withSessionHostRecoveryLease,
|
|
312
328
|
};
|
|
313
329
|
|
|
314
330
|
/**
|
|
@@ -333,6 +349,7 @@ export function stopBackgroundAgentChildTree(
|
|
|
333
349
|
{
|
|
334
350
|
windowsHide: true,
|
|
335
351
|
encoding: "utf8",
|
|
352
|
+
timeout: BACKGROUND_AGENT_KEEPER_TASKKILL_TIMEOUT_MS,
|
|
336
353
|
},
|
|
337
354
|
"background-agent:session-stop-tree",
|
|
338
355
|
);
|
|
@@ -421,6 +438,131 @@ export function logPath(id) {
|
|
|
421
438
|
|
|
422
439
|
const TERMINAL_STATUSES = new Set(["completed", "failed", "stopped", "lost"]);
|
|
423
440
|
|
|
441
|
+
const KEEPER_TERMINAL_STATUSES = new Set([
|
|
442
|
+
"closed",
|
|
443
|
+
"worker-disconnected",
|
|
444
|
+
"startup-timeout",
|
|
445
|
+
"spawn-error",
|
|
446
|
+
"exited",
|
|
447
|
+
]);
|
|
448
|
+
|
|
449
|
+
const TURN_PROCESS_PROJECTION_FIELDS = [
|
|
450
|
+
"agentPid",
|
|
451
|
+
"agentStartedAt",
|
|
452
|
+
"agentRuntimePid",
|
|
453
|
+
"agentRuntimeStartedAt",
|
|
454
|
+
"turnBootstrapStatus",
|
|
455
|
+
"turnBootstrapCommittedAt",
|
|
456
|
+
"turnKeeperStatus",
|
|
457
|
+
"turnKeeperPid",
|
|
458
|
+
"turnKeeperArmedAt",
|
|
459
|
+
"turnKeeperCleanupReason",
|
|
460
|
+
"turnKeeperCleanupRequestedAt",
|
|
461
|
+
"turnKeeperCleanupConfirmedAt",
|
|
462
|
+
"turnKeeperCleanupError",
|
|
463
|
+
];
|
|
464
|
+
|
|
465
|
+
function keeperLifecycleStage(state) {
|
|
466
|
+
if (KEEPER_TERMINAL_STATUSES.has(state?.keeperStatus)) return 4;
|
|
467
|
+
if (state?.keeperStatus === "ready") return 3;
|
|
468
|
+
if (state?.keeperStatus === "listening") return 2;
|
|
469
|
+
if (state?.keeperStatus === "starting") return 1;
|
|
470
|
+
return 0;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
function keeperLifecycleClock(state) {
|
|
474
|
+
return Math.max(
|
|
475
|
+
0,
|
|
476
|
+
Number(state?.keeperStartedAt || 0),
|
|
477
|
+
Number(state?.keeperHeartbeatAt || 0),
|
|
478
|
+
Number(state?.keeperReadyAt || 0),
|
|
479
|
+
Number(state?.keeperEndedAt || 0),
|
|
480
|
+
);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
function turnProcessProjectionStage(state) {
|
|
484
|
+
if (
|
|
485
|
+
["terminated", "not-spawned"].includes(state?.turnLaunchResolution?.outcome)
|
|
486
|
+
) {
|
|
487
|
+
return 100;
|
|
488
|
+
}
|
|
489
|
+
if (
|
|
490
|
+
state?.turnLaunchResolution?.outcome === "spawned" &&
|
|
491
|
+
state?.agentPid == null &&
|
|
492
|
+
state?.agentRuntimePid == null &&
|
|
493
|
+
state?.turnBootstrapStatus == null &&
|
|
494
|
+
state?.turnKeeperStatus == null &&
|
|
495
|
+
["idle", "needs_input"].includes(state?.phase)
|
|
496
|
+
) {
|
|
497
|
+
return 90;
|
|
498
|
+
}
|
|
499
|
+
if (state?.turnKeeperStatus === "cleanup-unconfirmed") return 85;
|
|
500
|
+
if (state?.turnKeeperStatus === "retired") return 80;
|
|
501
|
+
if (state?.turnKeeperStatus === "cleanup-requested") return 70;
|
|
502
|
+
if (state?.turnBootstrapStatus === "released") return 60;
|
|
503
|
+
if (state?.turnKeeperStatus === "armed") return 50;
|
|
504
|
+
if (
|
|
505
|
+
state?.turnKeeperStatus === "arming" ||
|
|
506
|
+
state?.turnBootstrapStatus === "awaiting-keeper"
|
|
507
|
+
) {
|
|
508
|
+
return 40;
|
|
509
|
+
}
|
|
510
|
+
if (Number(state?.agentRuntimePid) > 0) return 30;
|
|
511
|
+
if (
|
|
512
|
+
state?.turnBootstrapStatus === "awaiting-ready" ||
|
|
513
|
+
state?.turnKeeperStatus === "waiting-for-runtime"
|
|
514
|
+
) {
|
|
515
|
+
return 20;
|
|
516
|
+
}
|
|
517
|
+
if (Number(state?.agentPid) > 0) return 10;
|
|
518
|
+
return 0;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
function turnProcessProjectionClock(state) {
|
|
522
|
+
return Math.max(
|
|
523
|
+
0,
|
|
524
|
+
Number(state?.agentStartedAt || 0),
|
|
525
|
+
Number(state?.agentRuntimeStartedAt || 0),
|
|
526
|
+
Number(state?.turnBootstrapCommittedAt || 0),
|
|
527
|
+
Number(state?.turnKeeperArmedAt || 0),
|
|
528
|
+
Number(state?.turnKeeperCleanupRequestedAt || 0),
|
|
529
|
+
Number(state?.turnKeeperCleanupConfirmedAt || 0),
|
|
530
|
+
);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
function turnProjectionIdentity(state) {
|
|
534
|
+
const resolvedRecord = state?.turnLaunchResolution;
|
|
535
|
+
if (
|
|
536
|
+
turnProcessProjectionStage(state) > 0 &&
|
|
537
|
+
Number.isInteger(Number(resolvedRecord?.attempt))
|
|
538
|
+
) {
|
|
539
|
+
return {
|
|
540
|
+
attempt: Number(resolvedRecord.attempt),
|
|
541
|
+
token: resolvedRecord.token || null,
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
const records = [state?.turnLaunchIntent, state?.turnLaunchResolution].filter(
|
|
545
|
+
(record) => Number.isInteger(Number(record?.attempt)),
|
|
546
|
+
);
|
|
547
|
+
const record = records.sort(
|
|
548
|
+
(left, right) => Number(right.attempt) - Number(left.attempt),
|
|
549
|
+
)[0];
|
|
550
|
+
const attempt = Number(record?.attempt ?? state?.turnLaunchAttempt);
|
|
551
|
+
if (!Number.isInteger(attempt) || attempt <= 0) return null;
|
|
552
|
+
return { attempt, token: record?.token || null };
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
function sameTurnProjectionIdentity(leftIdentity, rightIdentity) {
|
|
556
|
+
return Boolean(
|
|
557
|
+
leftIdentity &&
|
|
558
|
+
rightIdentity &&
|
|
559
|
+
leftIdentity.attempt === rightIdentity.attempt &&
|
|
560
|
+
(!leftIdentity.token ||
|
|
561
|
+
!rightIdentity.token ||
|
|
562
|
+
leftIdentity.token === rightIdentity.token),
|
|
563
|
+
);
|
|
564
|
+
}
|
|
565
|
+
|
|
424
566
|
function readBackgroundAgentStateResult(id) {
|
|
425
567
|
const target = statePath(id);
|
|
426
568
|
if (!existsSync(target)) return { state: null, missing: true, error: null };
|
|
@@ -533,6 +675,9 @@ function mergeBackgroundAgentState(current, requested) {
|
|
|
533
675
|
if (current.workerGeneration) {
|
|
534
676
|
next = { ...next, workerGeneration: current.workerGeneration };
|
|
535
677
|
}
|
|
678
|
+
if (current.keeperGeneration) {
|
|
679
|
+
next = { ...next, keeperGeneration: current.keeperGeneration };
|
|
680
|
+
}
|
|
536
681
|
const claimedWorkerPid = Number(current.workerClaimedPid);
|
|
537
682
|
if (
|
|
538
683
|
current.workerClaimedPid != null &&
|
|
@@ -545,6 +690,43 @@ function mergeBackgroundAgentState(current, requested) {
|
|
|
545
690
|
workerClaimedAt: current.workerClaimedAt,
|
|
546
691
|
};
|
|
547
692
|
}
|
|
693
|
+
// Wrapper and keeper identities are write-once ownership evidence for this
|
|
694
|
+
// generation. In particular, a title/pin writer holding the pre-claim
|
|
695
|
+
// launch snapshot must not drop the independent process that owns cleanup.
|
|
696
|
+
if (Number(current.workerWrapperPid) > 0) {
|
|
697
|
+
next = { ...next, workerWrapperPid: Number(current.workerWrapperPid) };
|
|
698
|
+
}
|
|
699
|
+
if (Number(current.keeperPid) > 0) {
|
|
700
|
+
next = {
|
|
701
|
+
...next,
|
|
702
|
+
keeperPid: Number(current.keeperPid),
|
|
703
|
+
keeperStartedAt: current.keeperStartedAt,
|
|
704
|
+
};
|
|
705
|
+
}
|
|
706
|
+
if (Number(current.keeperWrapperPid) > 0) {
|
|
707
|
+
next = {
|
|
708
|
+
...next,
|
|
709
|
+
keeperWrapperPid: Number(current.keeperWrapperPid),
|
|
710
|
+
};
|
|
711
|
+
}
|
|
712
|
+
const currentKeeperStage = keeperLifecycleStage(current);
|
|
713
|
+
const requestedKeeperStage = keeperLifecycleStage(next);
|
|
714
|
+
if (
|
|
715
|
+
currentKeeperStage > requestedKeeperStage ||
|
|
716
|
+
(currentKeeperStage === requestedKeeperStage &&
|
|
717
|
+
keeperLifecycleClock(current) > keeperLifecycleClock(next))
|
|
718
|
+
) {
|
|
719
|
+
next = {
|
|
720
|
+
...next,
|
|
721
|
+
keeperStatus: current.keeperStatus,
|
|
722
|
+
keeperHeartbeatAt: current.keeperHeartbeatAt,
|
|
723
|
+
keeperReadyAt: current.keeperReadyAt,
|
|
724
|
+
keeperEndedAt: current.keeperEndedAt,
|
|
725
|
+
keeperExitCode: current.keeperExitCode,
|
|
726
|
+
keeperSignal: current.keeperSignal,
|
|
727
|
+
keeperError: current.keeperError,
|
|
728
|
+
};
|
|
729
|
+
}
|
|
548
730
|
// A turn launch uses a durable prepare/resolve record. The prepare must
|
|
549
731
|
// reach disk before native spawn so stop/remove can distinguish "no turn"
|
|
550
732
|
// from "a child may exist but its pid commit failed". Only the owner that
|
|
@@ -557,9 +739,25 @@ function mergeBackgroundAgentState(current, requested) {
|
|
|
557
739
|
: 0,
|
|
558
740
|
);
|
|
559
741
|
const requestedTurnAttempt = Number(next.turnLaunchAttempt);
|
|
742
|
+
// Capture each writer's process projection identity before the durable
|
|
743
|
+
// launch record below is reconciled. Otherwise replacing a stale
|
|
744
|
+
// resolution with the current token can accidentally relabel old PIDs as
|
|
745
|
+
// belonging to the newest turn.
|
|
746
|
+
const currentProcessProjectionIdentity = turnProjectionIdentity(current);
|
|
747
|
+
const requestedProcessProjectionIdentity = turnProjectionIdentity(next);
|
|
748
|
+
const currentProcessProjectionStage = turnProcessProjectionStage(current);
|
|
749
|
+
const requestedProcessProjectionStage = turnProcessProjectionStage(next);
|
|
750
|
+
const currentProcessProjectionClock = turnProcessProjectionClock(current);
|
|
751
|
+
const requestedProcessProjectionClock = turnProcessProjectionClock(next);
|
|
560
752
|
const currentTurnIntent = current.turnLaunchIntent;
|
|
561
753
|
const requestedTurnIntent = next.turnLaunchIntent;
|
|
562
754
|
const requestedTurnResolution = next.turnLaunchResolution;
|
|
755
|
+
const requestedCarriesCurrentTurnIntent = Boolean(
|
|
756
|
+
currentTurnIntent &&
|
|
757
|
+
requestedTurnIntent?.token === currentTurnIntent.token &&
|
|
758
|
+
Number(requestedTurnIntent?.attempt) ===
|
|
759
|
+
Number(currentTurnIntent.attempt),
|
|
760
|
+
);
|
|
563
761
|
const resolvesCurrentTurnIntent =
|
|
564
762
|
currentTurnIntent &&
|
|
565
763
|
requestedTurnIntent === null &&
|
|
@@ -591,6 +789,9 @@ function mergeBackgroundAgentState(current, requested) {
|
|
|
591
789
|
...(current.turnLaunchResolution !== undefined
|
|
592
790
|
? { turnLaunchResolution: current.turnLaunchResolution }
|
|
593
791
|
: {}),
|
|
792
|
+
...(!requestedCarriesCurrentTurnIntent && current.phase !== undefined
|
|
793
|
+
? { phase: current.phase }
|
|
794
|
+
: {}),
|
|
594
795
|
};
|
|
595
796
|
} else if (
|
|
596
797
|
!currentTurnIntent &&
|
|
@@ -612,6 +813,59 @@ function mergeBackgroundAgentState(current, requested) {
|
|
|
612
813
|
turnLaunchIntent: null,
|
|
613
814
|
};
|
|
614
815
|
}
|
|
816
|
+
// The target cannot execute Agent main until these fields reach `released`,
|
|
817
|
+
// and the keeper cannot relinquish ownership until cleanup is confirmed.
|
|
818
|
+
// Keep that same-turn projection monotonic across stale generic writers.
|
|
819
|
+
// `retired` -> idle is the only intentional projection clear; once idle,
|
|
820
|
+
// an old active snapshot may not resurrect already-reaped process ids.
|
|
821
|
+
const sameProcessProjection = sameTurnProjectionIdentity(
|
|
822
|
+
currentProcessProjectionIdentity,
|
|
823
|
+
requestedProcessProjectionIdentity,
|
|
824
|
+
);
|
|
825
|
+
const currentProjectionIsNewer = Boolean(
|
|
826
|
+
currentProcessProjectionIdentity &&
|
|
827
|
+
(!requestedProcessProjectionIdentity ||
|
|
828
|
+
currentProcessProjectionIdentity.attempt >
|
|
829
|
+
requestedProcessProjectionIdentity.attempt ||
|
|
830
|
+
(currentProcessProjectionIdentity.attempt ===
|
|
831
|
+
requestedProcessProjectionIdentity.attempt &&
|
|
832
|
+
currentProcessProjectionIdentity.token &&
|
|
833
|
+
requestedProcessProjectionIdentity.token &&
|
|
834
|
+
currentProcessProjectionIdentity.token !==
|
|
835
|
+
requestedProcessProjectionIdentity.token)),
|
|
836
|
+
);
|
|
837
|
+
if (sameProcessProjection || currentProjectionIsNewer) {
|
|
838
|
+
const intentionalIdleClear =
|
|
839
|
+
sameProcessProjection &&
|
|
840
|
+
requestedProcessProjectionStage === 90 &&
|
|
841
|
+
currentProcessProjectionStage === 80 &&
|
|
842
|
+
current.turnKeeperStatus === "retired" &&
|
|
843
|
+
Number(current.turnKeeperCleanupConfirmedAt) > 0;
|
|
844
|
+
const preserveCurrentProjection =
|
|
845
|
+
currentProjectionIsNewer ||
|
|
846
|
+
(!intentionalIdleClear &&
|
|
847
|
+
(currentProcessProjectionStage > requestedProcessProjectionStage ||
|
|
848
|
+
(currentProcessProjectionStage ===
|
|
849
|
+
requestedProcessProjectionStage &&
|
|
850
|
+
currentProcessProjectionClock >
|
|
851
|
+
requestedProcessProjectionClock)));
|
|
852
|
+
if (preserveCurrentProjection) {
|
|
853
|
+
next = {
|
|
854
|
+
...next,
|
|
855
|
+
...((currentProjectionIsNewer ||
|
|
856
|
+
currentProcessProjectionStage === 90) &&
|
|
857
|
+
next.status === "running"
|
|
858
|
+
? { phase: current.phase }
|
|
859
|
+
: {}),
|
|
860
|
+
...Object.fromEntries(
|
|
861
|
+
TURN_PROCESS_PROJECTION_FIELDS.map((field) => [
|
|
862
|
+
field,
|
|
863
|
+
current[field],
|
|
864
|
+
]),
|
|
865
|
+
),
|
|
866
|
+
};
|
|
867
|
+
}
|
|
868
|
+
}
|
|
615
869
|
const turnTerminationConfirmed =
|
|
616
870
|
next.turnLaunchFinalizationUncertain === false &&
|
|
617
871
|
next.turnLaunchTermination?.confirmed === true;
|
|
@@ -1087,15 +1341,36 @@ function inspectDestructiveProcessIdentity(
|
|
|
1087
1341
|
* @returns {boolean} true when a kill was actually issued
|
|
1088
1342
|
*/
|
|
1089
1343
|
export function reclaimOrphanAgentProcess(state) {
|
|
1090
|
-
const
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1344
|
+
const targets = [
|
|
1345
|
+
{
|
|
1346
|
+
pid: Number(state?.agentRuntimePid),
|
|
1347
|
+
startedAt: Number(state?.agentRuntimeStartedAt),
|
|
1348
|
+
},
|
|
1349
|
+
{
|
|
1350
|
+
pid: Number(state?.agentPid),
|
|
1351
|
+
startedAt: Number(state?.agentStartedAt),
|
|
1352
|
+
},
|
|
1353
|
+
].filter(
|
|
1354
|
+
(target, index, values) =>
|
|
1355
|
+
Number.isInteger(target.pid) &&
|
|
1356
|
+
target.pid > 0 &&
|
|
1357
|
+
target.pid !== Number(state?.pid) &&
|
|
1358
|
+
values.findIndex((candidate) => candidate.pid === target.pid) === index,
|
|
1359
|
+
);
|
|
1360
|
+
let killed = false;
|
|
1361
|
+
for (const target of targets) {
|
|
1362
|
+
// Destructive recovery never falls back to a naked PID. Every target must
|
|
1363
|
+
// retain a positive creation-time anchor and pass the fresh OS probe.
|
|
1364
|
+
if (!Number.isFinite(target.startedAt) || target.startedAt <= 0) continue;
|
|
1365
|
+
if (
|
|
1366
|
+
inspectDestructiveProcessIdentity(target.pid, target.startedAt).status !==
|
|
1367
|
+
"match"
|
|
1368
|
+
) {
|
|
1369
|
+
continue;
|
|
1370
|
+
}
|
|
1371
|
+
killed = _deps.killProcessTree(target.pid, "SIGKILL") === true || killed;
|
|
1097
1372
|
}
|
|
1098
|
-
return
|
|
1373
|
+
return killed;
|
|
1099
1374
|
}
|
|
1100
1375
|
|
|
1101
1376
|
export function normalizeBackgroundAgentTitle(title) {
|
|
@@ -1259,7 +1534,7 @@ function recoverTerminalBackgroundInteractions(
|
|
|
1259
1534
|
|
|
1260
1535
|
const fallbackRequest = backgroundInteractionFallback(state);
|
|
1261
1536
|
try {
|
|
1262
|
-
const recovery = withSessionHostRecoveryLease(state.sessionId, () =>
|
|
1537
|
+
const recovery = _deps.withSessionHostRecoveryLease(state.sessionId, () =>
|
|
1263
1538
|
rejectPendingBackgroundInteractions(state.sessionId, state.id, {
|
|
1264
1539
|
fallbackRequest,
|
|
1265
1540
|
code,
|
|
@@ -1859,20 +2134,33 @@ export function isBackgroundWorkerStartedError(error) {
|
|
|
1859
2134
|
async function settleUncertainBackgroundLaunch({
|
|
1860
2135
|
id,
|
|
1861
2136
|
jobFile,
|
|
2137
|
+
jobFiles,
|
|
1862
2138
|
spawnedProcess,
|
|
2139
|
+
spawnedProcesses,
|
|
1863
2140
|
error,
|
|
1864
2141
|
}) {
|
|
1865
|
-
|
|
2142
|
+
const owned = (spawnedProcesses || [spawnedProcess]).filter(Boolean);
|
|
2143
|
+
let terminations;
|
|
1866
2144
|
try {
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
2145
|
+
terminations = await Promise.all(
|
|
2146
|
+
owned.map((processHandle) =>
|
|
2147
|
+
_deps.terminateOwnedProcessTree(processHandle, {
|
|
2148
|
+
treeMode:
|
|
2149
|
+
process.platform === "win32" ? "windows-tree" : "posix-group",
|
|
2150
|
+
}),
|
|
2151
|
+
),
|
|
2152
|
+
);
|
|
1870
2153
|
} catch {
|
|
1871
2154
|
return;
|
|
1872
2155
|
}
|
|
1873
|
-
if (
|
|
2156
|
+
if (
|
|
2157
|
+
terminations.length !== owned.length ||
|
|
2158
|
+
terminations.some((termination) => termination?.confirmed !== true)
|
|
2159
|
+
) {
|
|
2160
|
+
return;
|
|
2161
|
+
}
|
|
1874
2162
|
try {
|
|
1875
|
-
const workerPid = Number(
|
|
2163
|
+
const workerPid = Number(owned[0]?.pid);
|
|
1876
2164
|
const current = readBackgroundAgentState(id);
|
|
1877
2165
|
if (!current || current.launchFinalizationUncertain !== true) return;
|
|
1878
2166
|
if (
|
|
@@ -1901,15 +2189,25 @@ async function settleUncertainBackgroundLaunch({
|
|
|
1901
2189
|
launchFinalizationUncertain: false,
|
|
1902
2190
|
launchTermination: {
|
|
1903
2191
|
confirmed: true,
|
|
1904
|
-
treeMode:
|
|
1905
|
-
|
|
1906
|
-
|
|
2192
|
+
treeMode:
|
|
2193
|
+
terminations.length === 1
|
|
2194
|
+
? terminations[0].treeMode || null
|
|
2195
|
+
: "multiple-owned-trees",
|
|
2196
|
+
closed: terminations.every(
|
|
2197
|
+
(termination) => termination.closed === true,
|
|
2198
|
+
),
|
|
2199
|
+
treeTerminated: terminations.every(
|
|
2200
|
+
(termination) => termination.treeTerminated === true,
|
|
2201
|
+
),
|
|
2202
|
+
ownedTreeCount: terminations.length,
|
|
1907
2203
|
settledAt: Date.now(),
|
|
1908
2204
|
},
|
|
1909
2205
|
});
|
|
1910
2206
|
// State is the durable cleanup authority; remove the one-shot job only
|
|
1911
2207
|
// after the terminal/ownership evidence is safely persisted.
|
|
1912
|
-
|
|
2208
|
+
for (const file of jobFiles || [jobFile]) {
|
|
2209
|
+
if (file) rmSync(file, { force: true });
|
|
2210
|
+
}
|
|
1913
2211
|
} catch {
|
|
1914
2212
|
// Persistence failure must retain the original uncertainty fence and must
|
|
1915
2213
|
// never become an unhandled rejection in the launching CLI process.
|
|
@@ -1976,10 +2274,17 @@ export function launchBackgroundAgent({
|
|
|
1976
2274
|
fingerprintBackgroundLaunchProfile(launchProfileState);
|
|
1977
2275
|
const dir = backgroundAgentsDir();
|
|
1978
2276
|
const workerGeneration = randomBytes(16).toString("hex");
|
|
2277
|
+
const keeperGeneration = randomBytes(16).toString("hex");
|
|
2278
|
+
const keeperToken = randomBytes(32).toString("hex");
|
|
2279
|
+
const keeperPipePath = backgroundAgentKeeperPipePath(id, dir);
|
|
1979
2280
|
const jobFile = join(dir, `${id}.job.${process.pid}.json`);
|
|
2281
|
+
const keeperJobFile = join(dir, `${id}.keeper.${process.pid}.json`);
|
|
1980
2282
|
const worker = fileURLToPath(
|
|
1981
2283
|
new URL("../workers/background-agent-worker.js", import.meta.url),
|
|
1982
2284
|
);
|
|
2285
|
+
const keeper = fileURLToPath(
|
|
2286
|
+
new URL("../workers/background-agent-keeper.js", import.meta.url),
|
|
2287
|
+
);
|
|
1983
2288
|
const job = {
|
|
1984
2289
|
id,
|
|
1985
2290
|
workerGeneration,
|
|
@@ -1990,6 +2295,11 @@ export function launchBackgroundAgent({
|
|
|
1990
2295
|
title: title || "Background agent",
|
|
1991
2296
|
cliEntry: cliEntry || process.argv[1],
|
|
1992
2297
|
logFile: logPath(id),
|
|
2298
|
+
keeper: {
|
|
2299
|
+
generation: keeperGeneration,
|
|
2300
|
+
pipePath: keeperPipePath,
|
|
2301
|
+
token: keeperToken,
|
|
2302
|
+
},
|
|
1993
2303
|
...(worktreeState || {}),
|
|
1994
2304
|
governance: governanceState,
|
|
1995
2305
|
// Present = interactive attach can start follow-up turns; absent = the
|
|
@@ -1998,7 +2308,24 @@ export function launchBackgroundAgent({
|
|
|
1998
2308
|
? { followUpArgv: followUpSecrets.argv }
|
|
1999
2309
|
: {}),
|
|
2000
2310
|
};
|
|
2001
|
-
|
|
2311
|
+
try {
|
|
2312
|
+
writeFileSync(jobFile, JSON.stringify(job), { mode: 0o600 });
|
|
2313
|
+
writeFileSync(
|
|
2314
|
+
keeperJobFile,
|
|
2315
|
+
JSON.stringify({
|
|
2316
|
+
id,
|
|
2317
|
+
workerGeneration,
|
|
2318
|
+
keeperGeneration,
|
|
2319
|
+
pipePath: keeperPipePath,
|
|
2320
|
+
token: keeperToken,
|
|
2321
|
+
}),
|
|
2322
|
+
{ mode: 0o600 },
|
|
2323
|
+
);
|
|
2324
|
+
} catch (error) {
|
|
2325
|
+
rmSync(jobFile, { force: true });
|
|
2326
|
+
rmSync(keeperJobFile, { force: true });
|
|
2327
|
+
throw error;
|
|
2328
|
+
}
|
|
2002
2329
|
// Write the initial state BEFORE spawning so the worker's own merges (the
|
|
2003
2330
|
// transport endpoint lands within its first ~100ms) can never be clobbered
|
|
2004
2331
|
// by a late launcher write racing the worker.
|
|
@@ -2013,6 +2340,13 @@ export function launchBackgroundAgent({
|
|
|
2013
2340
|
workerPid: null,
|
|
2014
2341
|
workerClaimedPid: null,
|
|
2015
2342
|
workerClaimedAt: null,
|
|
2343
|
+
workerWrapperPid: null,
|
|
2344
|
+
keeperGeneration,
|
|
2345
|
+
keeperPid: null,
|
|
2346
|
+
keeperStartedAt: null,
|
|
2347
|
+
keeperWrapperPid: null,
|
|
2348
|
+
keeperStatus: "launching",
|
|
2349
|
+
keeperHeartbeatAt: null,
|
|
2016
2350
|
turnLaunchAttempt: 0,
|
|
2017
2351
|
turnLaunchIntent: null,
|
|
2018
2352
|
turnLaunchResolution: null,
|
|
@@ -2036,10 +2370,13 @@ export function launchBackgroundAgent({
|
|
|
2036
2370
|
writeBackgroundAgentState(state, { createIfMissing: true });
|
|
2037
2371
|
} catch (error) {
|
|
2038
2372
|
rmSync(jobFile, { force: true });
|
|
2373
|
+
rmSync(keeperJobFile, { force: true });
|
|
2039
2374
|
rmSync(statePath(id), { force: true });
|
|
2040
2375
|
throw error;
|
|
2041
2376
|
}
|
|
2042
2377
|
let child;
|
|
2378
|
+
let keeperChild;
|
|
2379
|
+
let keeperStartedAt = null;
|
|
2043
2380
|
let workerLogFd;
|
|
2044
2381
|
let postSpawnError = null;
|
|
2045
2382
|
try {
|
|
@@ -2061,13 +2398,29 @@ export function launchBackgroundAgent({
|
|
|
2061
2398
|
scope: "background-agent",
|
|
2062
2399
|
shell: false,
|
|
2063
2400
|
});
|
|
2401
|
+
keeperStartedAt = Date.now();
|
|
2402
|
+
keeperChild = _deps.spawn(process.execPath, [keeper, keeperJobFile], {
|
|
2403
|
+
cwd,
|
|
2404
|
+
detached: true,
|
|
2405
|
+
stdio: ["ignore", workerLogFd, workerLogFd],
|
|
2406
|
+
windowsHide: true,
|
|
2407
|
+
origin: "background-agent:keeper",
|
|
2408
|
+
policy: "allow",
|
|
2409
|
+
scope: "background-agent",
|
|
2410
|
+
shell: false,
|
|
2411
|
+
});
|
|
2064
2412
|
} catch (error) {
|
|
2065
|
-
|
|
2413
|
+
const ownedProcesses = [child, keeperChild, error?.spawnedProcess].filter(
|
|
2414
|
+
(processHandle, index, values) =>
|
|
2415
|
+
processHandle && values.indexOf(processHandle) === index,
|
|
2416
|
+
);
|
|
2417
|
+
if (ownedProcesses.length > 0) {
|
|
2066
2418
|
// The broker can fail a post-spawn sandbox handshake only after native
|
|
2067
2419
|
// spawn returned. It requests termination, but this synchronous caller
|
|
2068
|
-
// cannot prove
|
|
2069
|
-
// cleanup never races a process that may still hold cwd.
|
|
2070
|
-
const workerPid = Number(error
|
|
2420
|
+
// cannot prove every close fence has settled; retain state/jobs/worktree
|
|
2421
|
+
// so cleanup never races a process that may still hold cwd.
|
|
2422
|
+
const workerPid = Number(child?.pid || error?.spawnedProcess?.pid);
|
|
2423
|
+
const keeperPid = Number(keeperChild?.pid);
|
|
2071
2424
|
try {
|
|
2072
2425
|
const current = readBackgroundAgentState(id) || state;
|
|
2073
2426
|
writeBackgroundAgentState({
|
|
@@ -2075,6 +2428,9 @@ export function launchBackgroundAgent({
|
|
|
2075
2428
|
pid: Number.isInteger(workerPid) && workerPid > 0 ? workerPid : null,
|
|
2076
2429
|
workerPid:
|
|
2077
2430
|
Number.isInteger(workerPid) && workerPid > 0 ? workerPid : null,
|
|
2431
|
+
keeperPid:
|
|
2432
|
+
Number.isInteger(keeperPid) && keeperPid > 0 ? keeperPid : null,
|
|
2433
|
+
keeperStartedAt,
|
|
2078
2434
|
launchFinalizationUncertain: true,
|
|
2079
2435
|
});
|
|
2080
2436
|
} catch {
|
|
@@ -2083,8 +2439,8 @@ export function launchBackgroundAgent({
|
|
|
2083
2439
|
}
|
|
2084
2440
|
void settleUncertainBackgroundLaunch({
|
|
2085
2441
|
id,
|
|
2086
|
-
jobFile,
|
|
2087
|
-
|
|
2442
|
+
jobFiles: [jobFile, keeperJobFile],
|
|
2443
|
+
spawnedProcesses: ownedProcesses,
|
|
2088
2444
|
error,
|
|
2089
2445
|
});
|
|
2090
2446
|
throw new BackgroundWorkerStartedError(error, {
|
|
@@ -2093,6 +2449,7 @@ export function launchBackgroundAgent({
|
|
|
2093
2449
|
});
|
|
2094
2450
|
}
|
|
2095
2451
|
rmSync(jobFile, { force: true });
|
|
2452
|
+
rmSync(keeperJobFile, { force: true });
|
|
2096
2453
|
rmSync(statePath(id), { force: true });
|
|
2097
2454
|
throw error;
|
|
2098
2455
|
} finally {
|
|
@@ -2102,7 +2459,7 @@ export function launchBackgroundAgent({
|
|
|
2102
2459
|
} catch (error) {
|
|
2103
2460
|
// Once spawn returned a child, even fd-finalization errors are
|
|
2104
2461
|
// post-transfer: the worker may already be using the worktree.
|
|
2105
|
-
if (child) postSpawnError = error;
|
|
2462
|
+
if (child || keeperChild) postSpawnError = error;
|
|
2106
2463
|
}
|
|
2107
2464
|
}
|
|
2108
2465
|
}
|
|
@@ -2173,6 +2530,44 @@ export function launchBackgroundAgent({
|
|
|
2173
2530
|
}
|
|
2174
2531
|
});
|
|
2175
2532
|
}
|
|
2533
|
+
if (typeof keeperChild.on === "function") {
|
|
2534
|
+
keeperChild.on("error", (error) => {
|
|
2535
|
+
try {
|
|
2536
|
+
mutateBackgroundAgentState(id, (current) =>
|
|
2537
|
+
current?.status === "running" &&
|
|
2538
|
+
current.keeperGeneration === keeperGeneration
|
|
2539
|
+
? {
|
|
2540
|
+
...current,
|
|
2541
|
+
keeperStatus: "spawn-error",
|
|
2542
|
+
keeperError: error?.message || String(error),
|
|
2543
|
+
keeperEndedAt: Date.now(),
|
|
2544
|
+
}
|
|
2545
|
+
: null,
|
|
2546
|
+
);
|
|
2547
|
+
} catch {
|
|
2548
|
+
/* worker-side channel failure remains authoritative */
|
|
2549
|
+
}
|
|
2550
|
+
});
|
|
2551
|
+
keeperChild.on("exit", (code, signal) => {
|
|
2552
|
+
try {
|
|
2553
|
+
mutateBackgroundAgentState(id, (current) =>
|
|
2554
|
+
current?.status === "running" &&
|
|
2555
|
+
current.keeperGeneration === keeperGeneration
|
|
2556
|
+
? {
|
|
2557
|
+
...current,
|
|
2558
|
+
keeperStatus:
|
|
2559
|
+
current.keeperStatus === "closed" ? "closed" : "exited",
|
|
2560
|
+
keeperExitCode: Number.isInteger(code) ? code : null,
|
|
2561
|
+
keeperSignal: signal || null,
|
|
2562
|
+
keeperEndedAt: Date.now(),
|
|
2563
|
+
}
|
|
2564
|
+
: null,
|
|
2565
|
+
);
|
|
2566
|
+
} catch {
|
|
2567
|
+
/* worker-side channel failure remains authoritative */
|
|
2568
|
+
}
|
|
2569
|
+
});
|
|
2570
|
+
}
|
|
2176
2571
|
// Read child.pid before entering the state transaction. A platform wrapper
|
|
2177
2572
|
// (notably the Windows Job Object adapter) can return from spawn just as the
|
|
2178
2573
|
// real worker claims the state record. Finalize the wrapper pid against the
|
|
@@ -2180,6 +2575,7 @@ export function launchBackgroundAgent({
|
|
|
2180
2575
|
// worker already published (agentPid, pendingQuestion, recovery marker,
|
|
2181
2576
|
// turnCount, ...).
|
|
2182
2577
|
const spawnedWorkerPid = child.pid;
|
|
2578
|
+
const spawnedKeeperPid = keeperChild.pid;
|
|
2183
2579
|
const pidFinalization = mutateBackgroundAgentState(id, (current) => {
|
|
2184
2580
|
if (
|
|
2185
2581
|
!current ||
|
|
@@ -2195,6 +2591,17 @@ export function launchBackgroundAgent({
|
|
|
2195
2591
|
// platform child returned by spawn.
|
|
2196
2592
|
pid: current.pid ?? spawnedWorkerPid,
|
|
2197
2593
|
workerPid: current.workerPid ?? spawnedWorkerPid,
|
|
2594
|
+
workerWrapperPid:
|
|
2595
|
+
current.workerWrapperPid ?? child.sandboxWrapperPid ?? null,
|
|
2596
|
+
keeperPid: current.keeperPid ?? spawnedKeeperPid,
|
|
2597
|
+
keeperStartedAt: current.keeperStartedAt ?? keeperStartedAt,
|
|
2598
|
+
keeperWrapperPid:
|
|
2599
|
+
current.keeperWrapperPid ?? keeperChild.sandboxWrapperPid ?? null,
|
|
2600
|
+
keeperStatus:
|
|
2601
|
+
current.keeperStatus === "listening" ||
|
|
2602
|
+
current.keeperStatus === "ready"
|
|
2603
|
+
? current.keeperStatus
|
|
2604
|
+
: "starting",
|
|
2198
2605
|
launchFinalizationUncertain: false,
|
|
2199
2606
|
};
|
|
2200
2607
|
});
|
|
@@ -2205,6 +2612,7 @@ export function launchBackgroundAgent({
|
|
|
2205
2612
|
}
|
|
2206
2613
|
withPid = pidFinalization.state;
|
|
2207
2614
|
child.unref();
|
|
2615
|
+
keeperChild.unref();
|
|
2208
2616
|
} catch (error) {
|
|
2209
2617
|
postSpawnError ||= error;
|
|
2210
2618
|
}
|
|
@@ -2228,13 +2636,33 @@ export function readBackgroundAgentLog(id, options = {}) {
|
|
|
2228
2636
|
|
|
2229
2637
|
function recordedBackgroundProcessIdentities(state) {
|
|
2230
2638
|
const records = [
|
|
2639
|
+
{
|
|
2640
|
+
role: "agent-runtime",
|
|
2641
|
+
pid: state?.agentRuntimePid,
|
|
2642
|
+
startedAt: state?.agentRuntimeStartedAt,
|
|
2643
|
+
},
|
|
2231
2644
|
{ role: "agent", pid: state?.agentPid, startedAt: state?.agentStartedAt },
|
|
2232
2645
|
{ role: "worker", pid: state?.pid, startedAt: state?.startedAt },
|
|
2233
2646
|
{
|
|
2234
|
-
role: "worker-
|
|
2647
|
+
role: "worker-published",
|
|
2235
2648
|
pid: state?.workerPid,
|
|
2236
2649
|
startedAt: state?.startedAt,
|
|
2237
2650
|
},
|
|
2651
|
+
{
|
|
2652
|
+
role: "worker-wrapper",
|
|
2653
|
+
pid: state?.workerWrapperPid,
|
|
2654
|
+
startedAt: state?.startedAt,
|
|
2655
|
+
},
|
|
2656
|
+
{
|
|
2657
|
+
role: "keeper",
|
|
2658
|
+
pid: state?.keeperPid,
|
|
2659
|
+
startedAt: state?.keeperStartedAt,
|
|
2660
|
+
},
|
|
2661
|
+
{
|
|
2662
|
+
role: "keeper-wrapper",
|
|
2663
|
+
pid: state?.keeperWrapperPid,
|
|
2664
|
+
startedAt: state?.keeperStartedAt,
|
|
2665
|
+
},
|
|
2238
2666
|
];
|
|
2239
2667
|
const seen = new Set();
|
|
2240
2668
|
return records.filter((record) => {
|
|
@@ -2259,7 +2687,7 @@ function recordedBackgroundProcessesAlive(state) {
|
|
|
2259
2687
|
);
|
|
2260
2688
|
}
|
|
2261
2689
|
|
|
2262
|
-
function
|
|
2690
|
+
export function isBackgroundProcessTreeExecutionAlive(pid, startedAt) {
|
|
2263
2691
|
const identity = inspectDestructiveProcessIdentity(pid, startedAt);
|
|
2264
2692
|
// `unverifiable` includes a vanished/zombie POSIX leader whose process group
|
|
2265
2693
|
// is still executable or whose group snapshot failed. Both must block
|
|
@@ -2267,13 +2695,21 @@ function isRecordedProcessTreeExecutionAlive(pid, startedAt) {
|
|
|
2267
2695
|
return ["match", "unverifiable", "self"].includes(identity.status);
|
|
2268
2696
|
}
|
|
2269
2697
|
|
|
2270
|
-
function signalBackgroundProcessTree(
|
|
2698
|
+
export function signalBackgroundProcessTree(
|
|
2699
|
+
pid,
|
|
2700
|
+
signal = "SIGTERM",
|
|
2701
|
+
{ platform = process.platform } = {},
|
|
2702
|
+
) {
|
|
2271
2703
|
const target = Number(pid);
|
|
2272
|
-
if (
|
|
2704
|
+
if (platform === "win32") {
|
|
2273
2705
|
const killed = runSupervisorCommand(
|
|
2274
2706
|
"taskkill",
|
|
2275
2707
|
["/PID", String(target), "/T", "/F"],
|
|
2276
|
-
{
|
|
2708
|
+
{
|
|
2709
|
+
windowsHide: true,
|
|
2710
|
+
encoding: "utf8",
|
|
2711
|
+
timeout: BACKGROUND_AGENT_KEEPER_TASKKILL_TIMEOUT_MS,
|
|
2712
|
+
},
|
|
2277
2713
|
"background-agent:stop-tree",
|
|
2278
2714
|
);
|
|
2279
2715
|
if (killed.error || (killed.status !== 0 && isProcessAlive(target))) {
|
|
@@ -2288,9 +2724,22 @@ function signalBackgroundProcessTree(pid, signal = "SIGTERM") {
|
|
|
2288
2724
|
try {
|
|
2289
2725
|
_deps.kill(-target, signal);
|
|
2290
2726
|
return "process-group";
|
|
2291
|
-
} catch {
|
|
2292
|
-
|
|
2293
|
-
|
|
2727
|
+
} catch (groupError) {
|
|
2728
|
+
// A denied/invalid group signal can leave descendants executing even if a
|
|
2729
|
+
// direct leader signal would succeed. Only ESRCH proves that there is no
|
|
2730
|
+
// process group to terminate and permits the single-process fallback.
|
|
2731
|
+
if (groupError?.code !== "ESRCH") throw groupError;
|
|
2732
|
+
try {
|
|
2733
|
+
_deps.kill(target, signal);
|
|
2734
|
+
return "process";
|
|
2735
|
+
} catch (error) {
|
|
2736
|
+
// The exact-identity probe and signal are necessarily separate syscalls.
|
|
2737
|
+
// A previously signalled group (or a naturally exiting child) can reap
|
|
2738
|
+
// this target between them. ESRCH therefore proves there is no process
|
|
2739
|
+
// left to terminate; permission and all other failures remain fatal.
|
|
2740
|
+
if (error?.code === "ESRCH") return "already-exited";
|
|
2741
|
+
throw error;
|
|
2742
|
+
}
|
|
2294
2743
|
}
|
|
2295
2744
|
}
|
|
2296
2745
|
|
|
@@ -2362,7 +2811,7 @@ function waitForSignalledProcessesToExit(
|
|
|
2362
2811
|
|
|
2363
2812
|
function recoverStoppedInteractions(state) {
|
|
2364
2813
|
if (!state?.sessionId) return { state, recovery: null };
|
|
2365
|
-
const recovery = withSessionHostRecoveryLease(state.sessionId, () =>
|
|
2814
|
+
const recovery = _deps.withSessionHostRecoveryLease(state.sessionId, () =>
|
|
2366
2815
|
rejectPendingBackgroundInteractions(state.sessionId, state.id, {
|
|
2367
2816
|
fallbackRequest: backgroundInteractionFallback(state),
|
|
2368
2817
|
code: "INTERACTION_STOPPED",
|
|
@@ -2493,6 +2942,7 @@ export function stopBackgroundAgent(id) {
|
|
|
2493
2942
|
}
|
|
2494
2943
|
const primaryWorker =
|
|
2495
2944
|
inspected.find(({ role }) => role === "worker") ||
|
|
2945
|
+
inspected.find(({ role }) => role === "worker-published") ||
|
|
2496
2946
|
inspected.find(({ role }) => role === "worker-wrapper");
|
|
2497
2947
|
if (primaryWorker?.identity.status === "reused") workerPidReused = true;
|
|
2498
2948
|
const targets = inspected.filter(
|
|
@@ -2624,17 +3074,47 @@ function activeWorktreeProcesses(state) {
|
|
|
2624
3074
|
if (
|
|
2625
3075
|
Number.isInteger(Number(state?.pid)) &&
|
|
2626
3076
|
Number(state.pid) > 0 &&
|
|
2627
|
-
|
|
3077
|
+
isBackgroundProcessTreeExecutionAlive(state.pid, state.startedAt)
|
|
2628
3078
|
) {
|
|
2629
3079
|
active.push("worker");
|
|
2630
3080
|
}
|
|
2631
3081
|
if (
|
|
2632
3082
|
Number.isInteger(Number(state?.agentPid)) &&
|
|
2633
3083
|
Number(state.agentPid) > 0 &&
|
|
2634
|
-
|
|
3084
|
+
isBackgroundProcessTreeExecutionAlive(state.agentPid, state.agentStartedAt)
|
|
2635
3085
|
) {
|
|
2636
3086
|
active.push("agent");
|
|
2637
3087
|
}
|
|
3088
|
+
if (
|
|
3089
|
+
Number.isInteger(Number(state?.keeperPid)) &&
|
|
3090
|
+
Number(state.keeperPid) > 0 &&
|
|
3091
|
+
isBackgroundProcessTreeExecutionAlive(
|
|
3092
|
+
state.keeperPid,
|
|
3093
|
+
state.keeperStartedAt,
|
|
3094
|
+
)
|
|
3095
|
+
) {
|
|
3096
|
+
active.push("keeper");
|
|
3097
|
+
}
|
|
3098
|
+
if (
|
|
3099
|
+
Number.isInteger(Number(state?.workerWrapperPid)) &&
|
|
3100
|
+
Number(state.workerWrapperPid) > 0 &&
|
|
3101
|
+
isBackgroundProcessTreeExecutionAlive(
|
|
3102
|
+
state.workerWrapperPid,
|
|
3103
|
+
state.startedAt,
|
|
3104
|
+
)
|
|
3105
|
+
) {
|
|
3106
|
+
active.push("worker-wrapper");
|
|
3107
|
+
}
|
|
3108
|
+
if (
|
|
3109
|
+
Number.isInteger(Number(state?.keeperWrapperPid)) &&
|
|
3110
|
+
Number(state.keeperWrapperPid) > 0 &&
|
|
3111
|
+
isBackgroundProcessTreeExecutionAlive(
|
|
3112
|
+
state.keeperWrapperPid,
|
|
3113
|
+
state.keeperStartedAt,
|
|
3114
|
+
)
|
|
3115
|
+
) {
|
|
3116
|
+
active.push("keeper-wrapper");
|
|
3117
|
+
}
|
|
2638
3118
|
return active;
|
|
2639
3119
|
}
|
|
2640
3120
|
|