chainlesschain 0.164.0 → 0.165.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +248 -2
- package/package.json +7 -4
- package/src/assets/web-panel/.build-hash +1 -1
- package/src/assets/web-panel/assets/{AIOps-D2MEn7fI.js → AIOps-lS1R0Cza.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-lCW_4Gf0.js → ActionButton-BmlgBPsj.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-Bs7i-nsS.js → Analytics-CNKczv1S.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-CK7B6S_j.js → AppLayout-BuZGJARQ.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-C8ILjpyo.js → Artifacts-Dm73Sl-O.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-Bb9cNaWc.js → Audit-BGMW7A5e.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-sC9ooXIf.js → BackgroundAgents-BQ6M54JR.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-D-DrsplT.js → Backup-DBzGP0bR.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-uCNZpwSK.js → BaseInput-D1mLCoOV.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-CsDK1uE9.js → Chat-BUfcN7p8.js} +6 -6
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-OqSDt50w.js → ChatBubbleRenderer-CY5m8ZHg.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-JhTXM1-K.js → Checkbox-Du0Yg5Pi.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-BbzZLnyD.js → Codegen-B2RXziHW.js} +1 -1
- package/src/assets/web-panel/assets/{Col-D4VW4m4j.js → Col-DWhekOrR.js} +1 -1
- package/src/assets/web-panel/assets/{Community-BXrYawxV.js → Community-HQhrkon4.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-DCihGy1u.js → Compact-izHNb4uz.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-DlyZ-lk8.js → Compliance-BDwLy41-.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-DvGZrhbO.js → Cowork-DFJhLa7K.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-DUncZi8h.js → Cron-DYY9RG7-.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-C_hLuUcm.js → Crosschain-rr7tJTtv.js} +1 -1
- package/src/assets/web-panel/assets/{DID-b6YSUqxr.js → DID-D2sfHRLi.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-uvM15Cfb.js → Dashboard-q_eGdhha.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-D1-Nd4qY.js → Dropdown-Cufrh2Bz.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-8ApvL6Zc.js → EmailListRenderer-B-kdv10f.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-LYJt8811.js → FamilyGuardDashboard-D21XjgfG.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-BbI3HGpv.js → Federation-CAwRTLZH.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-DSoEKuFu.js → FormItemContext-vx3daNDF.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-B0S9OWd5.js → GenericCardRenderer-CRWY2wU4.js} +1 -1
- package/src/assets/web-panel/assets/{Git-DIs9Zhf3.js → Git-Q6SwauyD.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-jzZXrxcl.js → Governance-BJ1q4IQZ.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-JUPjf2ZI.js → Inference-CSWjROgD.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-DxnfJvlP.js → KnowledgeGraph-fzuQsWuY.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-iXiz8BEE.js → Logs-DVF8Mnns.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-BLif4QSg.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-Y3Xch312.js → Marketplace-BQP7LOA4.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-D7kGGbO7.js → McpTools-BNlJCmNc.js} +4 -4
- package/src/assets/web-panel/assets/{Memory-Do_hVxzh.js → Memory-DLLg5WQ4.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-CtrR0Tas.js → MobileBridge-CR2skNAF.js} +1 -1
- package/src/assets/web-panel/assets/MobileProjects-BxVavObl.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-qo5QCTGd.js → Mtc-B17pgqMI.js} +4 -4
- package/src/assets/web-panel/assets/{MtcAudit-cq5mnjYj.js → MtcAudit-4UmV5cIL.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-Bq0MAQHw.js → Multisig-DoMEXEcU.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-DdWE6Vi2.js → NLProgramming-h9DMXFX4.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-BxMBFcIp.js → Notes-Cihn-xX8.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-RTrAcbUe.js → NotificationSettings-BE6ZGa3R.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-DJbpGqzT.js → OrderTableRenderer-CnwojoSI.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-SQzIPdqC.js → Organization-B2vpwmjb.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-02yECh22.js → Overflow-C4z28R0-.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-BNg4pNCM.js → P2P-BVlFkwhW.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-BxPJZsD3.js → PdhVaultBrowser-BXbEdL5B.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-CLnDnPAz.js → Permissions-C28xs4lp.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-C5m0AjGf.js → PersonalDataHub-Dgl_rBjM.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-VwOf5Dhv.js → Pipeline-3QUIhrKI.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-CC0W2hZd.js → Privacy-8Gh33OZ5.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-Dz893Bob.js → ProjectInit-BNmg4tZi.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-CxQkvl0k.js → ProjectSettings-vgMfeCf9.js} +2 -2
- package/src/assets/web-panel/assets/Projects-BhtAVilc.js +1 -0
- package/src/assets/web-panel/assets/{Providers-DeB9IkxK.js → Providers-CXoOa8eX.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-OCeoaswn.js → QrScannerModal-BhfTF0oS.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-DenotaAj.js → QuickAsk-C746HEAj.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-Cies_jjI.js → Recommend-BSej8Eo0.js} +1 -1
- package/src/assets/web-panel/assets/RemoteSession-f3gmnlG3.js +5 -0
- package/src/assets/web-panel/assets/{Reputation-CW0mvxgZ.js → Reputation-CyvybpkN.js} +1 -1
- package/src/assets/web-panel/assets/{Row-SEd32qZU.js → Row-DwV2PeYn.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-BSwnJ3Lm.js → RssFeed-11GrzjZy.js} +3 -3
- package/src/assets/web-panel/assets/{Search-xe2m8bkC.js → Search-BjKXkrAY.js} +1 -1
- package/src/assets/web-panel/assets/{Security-Mq2F9Nro.js → Security-eWiFb9Yk.js} +4 -4
- package/src/assets/web-panel/assets/{Services-BKGw2V3P.js → Services-CdCsMAtt.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-DW95-Rxf.js → Skeleton-4Q2UTKQ5.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-CHgChCv_.js → Skills-v4rtYrRj.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-tKh6k3R7.js → Sla-CRhsFvd_.js} +1 -1
- package/src/assets/web-panel/assets/SpeechSettings-DLjKsDVu.js +1 -0
- package/src/assets/web-panel/assets/{SyncSettings-D0Fw8fVL.js → SyncSettings-D16zonl7.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-20x1GB3D.js → Tasks-Xxozz0i_.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-DJ-lts-a.js → Templates-CXJpPtCT.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-BFdGpbs7.js → Tenant-XRV0L1ZF.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-Xpx61vHL.js → Terminal-CYuO1i_w.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-C6UIvyZQ.js → TimelineRenderer-BXqitWsu.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-Dellq08f.js → Tokens-BvPrDHIy.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-VKw8d0J-.js → Trigger-DhCrSTf5.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-DNftdKT5.js → Trust-DmsuZD6K.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-DX9VAKJI.js → UkeySign-D_yrts5C.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-B2h3jO8q.js → VideoEditing-B01ihPrm.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-CjGkof7f.js → Wallet-DpUjKa-N.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-2Zfcu55P.js → WebAuthn-CL07yON6.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-B9eZ8UxZ.js → WorkflowEditor-CLMflnRr.js} +1 -1
- package/src/assets/web-panel/assets/{chat-CQNfD-YO.js → chat-DtUqe8h_.js} +1 -1
- package/src/assets/web-panel/assets/{colors-D4usyFT2.js → colors-DPKrgVfy.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-s4TpjvjX.js → compact-item-BTt2GtOm.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-BRCSvYxj.js → createContext-D_VeUc1J.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-Bj5nUW2v.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-AdkUbkV-.js → hasIn-1kndiylj.js} +1 -1
- package/src/assets/web-panel/assets/{index-BIoG5yYf.js → index-2eyAXE3d.js} +1 -1
- package/src/assets/web-panel/assets/{index-nXyk8GZ9.js → index-4bna2_SR.js} +1 -1
- package/src/assets/web-panel/assets/{index-B2V-eKfK.js → index-8nz_fmlj.js} +1 -1
- package/src/assets/web-panel/assets/{index-D_XBHopw.js → index-B9KvcS7R.js} +1 -1
- package/src/assets/web-panel/assets/{index-s_buFMEG.js → index-BAXfRKfG.js} +1 -1
- package/src/assets/web-panel/assets/{index-DZT36ZYq.js → index-BHpBMWCh.js} +1 -1
- package/src/assets/web-panel/assets/{index-BMcimU-2.js → index-BaZAbw9A.js} +1 -1
- package/src/assets/web-panel/assets/{index-DzRjHxEv.js → index-BepLZwgB.js} +1 -1
- package/src/assets/web-panel/assets/{index--00U6vXZ.js → index-Bhudc_Ez.js} +1 -1
- package/src/assets/web-panel/assets/{index-C7Y8Aluc.js → index-BlDNVgBt.js} +1 -1
- package/src/assets/web-panel/assets/{index-BtobShro.js → index-By5n8up9.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cvyt-zhm.js → index-CHG-KcS4.js} +1 -1
- package/src/assets/web-panel/assets/index-CPcM-eqo.js +1 -0
- package/src/assets/web-panel/assets/{index-MMN9V6JF.js → index-CX81qSM4.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bad4VNvz.js → index-CauoBQkH.js} +1 -1
- package/src/assets/web-panel/assets/{index-CCsM_Ybx.js → index-CcO04eDn.js} +1 -1
- package/src/assets/web-panel/assets/{index-DARsAyUp.js → index-CtF7EN49.js} +1 -1
- package/src/assets/web-panel/assets/{index-C5KAQFPQ.js → index-CzjkKUmR.js} +1 -1
- package/src/assets/web-panel/assets/{index-RfMr79MW.js → index-D95OFht7.js} +1 -1
- package/src/assets/web-panel/assets/{index-DdCB70SS.js → index-DFIZ_1Sf.js} +1 -1
- package/src/assets/web-panel/assets/{index-CYdoQsa1.js → index-DG2MZQ3f.js} +1 -1
- package/src/assets/web-panel/assets/{index-BPhkFZ1I.js → index-DJ8vXGOa.js} +1 -1
- package/src/assets/web-panel/assets/{index-_IRVsV9X.js → index-Dbbymxpj.js} +1 -1
- package/src/assets/web-panel/assets/{index-DVKfQ0Ux.js → index-DdkplL9R.js} +1 -1
- package/src/assets/web-panel/assets/{index-CkwiSLhU.js → index-DfGl8CqG.js} +1 -1
- package/src/assets/web-panel/assets/{index-CJVEOa4i.js → index-DfKBRdSS.js} +1 -1
- package/src/assets/web-panel/assets/{index-C1mJtE6q.js → index-DsJCDUJG.js} +1 -1
- package/src/assets/web-panel/assets/{index-BgiXR_-_.js → index-Dwqmtk65.js} +1 -1
- package/src/assets/web-panel/assets/{index-CJCFe2Qf.js → index-DxdTdBix.js} +1 -1
- package/src/assets/web-panel/assets/{index-C484EJiS.js → index-FzdwcSy2.js} +1 -1
- package/src/assets/web-panel/assets/{index-B4JJCfQ2.js → index-GsoUQ2M7.js} +1 -1
- package/src/assets/web-panel/assets/{index-CQhAVU5t.js → index-brCInrzq.js} +1 -1
- package/src/assets/web-panel/assets/{index-CKC1t3Ic.js → index-dVc-CXY4.js} +1 -1
- package/src/assets/web-panel/assets/{index-BQ3DXBtD.js → index-fk2Rjacw.js} +3 -3
- package/src/assets/web-panel/assets/{index-Cduu2Hhr.js → index-l1BETrDb.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bw2MEnUk.js → index-m31Ka8hZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-D2GjI2oe.js → index-ocf06EVQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-CJdQrZth.js → index-sDoMHTNA.js} +1 -1
- package/src/assets/web-panel/assets/index-xeSyVoRe.js +1 -0
- package/src/assets/web-panel/assets/{initDefaultProps-Blmpk7HL.js → initDefaultProps-CvyYJd7z.js} +1 -1
- package/src/assets/web-panel/assets/{motion-DPBJMv1n.js → motion-DYZkhUdz.js} +1 -1
- package/src/assets/web-panel/assets/{move-ButdzCM7.js → move-slnJRVT1.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-cyRC_QCe.js → mtc-parser-DVc0CKmy.js} +1 -1
- package/src/assets/web-panel/assets/{omit-1epSV7hz.js → omit-BCXAtHCq.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-DuPY8xJs.js → pickAttrs-DBsemz_K.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-6XZqarhe.js → placementArrow-BRtkJ-nv.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-B40pXBWM.js → responsiveObserve-Cebq7EZn.js} +1 -1
- package/src/assets/web-panel/assets/{slide-jbZ9Wu4n.js → slide-DT7qvId2.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-BKQQcVy4.js → statusUtils-pQiITLkG.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-NiKfWjUT.js → styleChecker-c-19BVKQ.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-bQUCvPeb.js → useFlexGapSupport-DsS5-0bE.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-CUGji7ph.js → useFs-CxGiMe5n.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-4veyN2N2.js → usePersonalDataHub-D9btVID5.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-1-nLug-Z.js → vnode-CUYFsFEN.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-dhCeRDMo.js → zoom-CXmn_35j.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +1 -1
- package/src/commands/cowork.js +559 -62
- package/src/commands/plugin.js +819 -64
- package/src/commands/session-location.js +318 -7
- package/src/constants.js +2 -2
- package/src/data/changelog.json +28 -2
- package/src/gateways/ws/action-protocol.js +293 -19
- package/src/gateways/ws/message-dispatcher.js +30 -0
- package/src/gateways/ws/remote-session-protocol.js +542 -35
- package/src/gateways/ws/ws-approval-gate.js +5 -0
- package/src/gateways/ws/ws-server.js +462 -38
- package/src/harness/jsonl-session-store.js +638 -2
- package/src/harness/prompt-compressor.js +4 -0
- package/src/harness/remote-session-audit.js +1 -0
- package/src/harness/remote-session-crypto.js +750 -50
- package/src/harness/remote-session-registry.js +795 -27
- package/src/lib/auto-mode-config.js +98 -3
- package/src/lib/background-agent-keeper-client.js +29 -0
- package/src/lib/background-agent-keeper-protocol.js +158 -10
- package/src/lib/background-agent-supervisor.js +870 -48
- package/src/lib/background-session-transport.js +23 -6
- package/src/lib/background-turn-bootstrap-protocol.js +64 -0
- package/src/lib/cowork-task-runner.js +70 -0
- package/src/lib/cowork-workflow.js +887 -62
- package/src/lib/delivery-production-adapter.js +38 -2
- package/src/lib/doctor-checkup.js +34 -10
- package/src/lib/dynamic-workflow-draft.js +535 -0
- package/src/lib/dynamic-workflow-facade.js +1105 -17
- package/src/lib/dynamic-workflow-runtime.js +2974 -0
- package/src/lib/execution-location-contract.js +111 -7
- package/src/lib/execution-location-runtime.js +3 -1
- package/src/lib/execution-location-target.js +910 -0
- package/src/lib/llm-providers.js +1 -0
- package/src/lib/mcp-call-ledger-store.js +35 -0
- package/src/lib/mcp-call-ledger.js +30 -0
- package/src/lib/mcp-stdio-package-materialization.js +1 -1
- package/src/lib/plugin-runtime/__tests__/remote-source.test.js +34 -16
- package/src/lib/plugin-runtime/install.js +4956 -657
- package/src/lib/plugin-runtime/manifest.js +3 -1
- package/src/lib/plugin-runtime/marketplace-artifact-readback.js +671 -31
- package/src/lib/plugin-runtime/marketplace-catalog.js +68 -2
- package/src/lib/plugin-runtime/marketplace-impact.js +208 -15
- package/src/lib/plugin-runtime/marketplace-network.js +317 -0
- package/src/lib/plugin-runtime/marketplace-pac-worker.js +15 -0
- package/src/lib/plugin-runtime/marketplace-remote-artifacts.js +25 -2
- package/src/lib/plugin-runtime/marketplace-source-cache.js +359 -0
- package/src/lib/plugin-runtime/policy.js +21 -6
- package/src/lib/plugin-runtime/publisher-trust.js +332 -0
- package/src/lib/plugin-runtime/remote-source.js +323 -27
- package/src/lib/plugin-runtime/scopes.js +317 -41
- package/src/lib/plugin-runtime/transaction-journal.js +806 -0
- package/src/lib/public-ide-capability-manifest.js +1 -1
- package/src/lib/remote-approval-bridge.js +745 -108
- package/src/lib/remote-control.js +2 -0
- package/src/lib/remote-membership-coordinator.js +612 -46
- package/src/lib/remote-membership-host-store.js +59 -10
- package/src/lib/runtime-provenance-ledger.js +171 -46
- package/src/lib/shell-approval.js +169 -6
- package/src/lib/sub-agent-context.js +268 -2
- package/src/lib/task-model-selector.js +1 -1
- package/src/lib/with-file-lock.js +167 -42
- package/src/repl/agent-repl.js +70 -29
- package/src/repl/remote-approval.js +29 -7
- package/src/runtime/agent-core.js +1695 -194
- package/src/runtime/headless-runner.js +22 -5
- package/src/runtime/headless-stream.js +19 -3
- package/src/workers/background-agent-keeper.js +279 -58
- package/src/workers/background-agent-worker.js +7 -0
- package/src/workers/background-turn-bootstrap.js +29 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-GmB6DOr6.js +0 -1
- package/src/assets/web-panel/assets/MobileProjects-BL0Czcoj.js +0 -1
- package/src/assets/web-panel/assets/Projects-DDAjkUkT.js +0 -1
- package/src/assets/web-panel/assets/RemoteSession-Dxzl5n2T.js +0 -5
- package/src/assets/web-panel/assets/SpeechSettings-D6UL3dA5.js +0 -1
- package/src/assets/web-panel/assets/devWarning-DKJjSWRn.js +0 -1
- package/src/assets/web-panel/assets/index-C61cnl3K.js +0 -1
- package/src/assets/web-panel/assets/index-D4XFHxBr.js +0 -1
|
@@ -16,7 +16,9 @@
|
|
|
16
16
|
*
|
|
17
17
|
* so an in-flight session keeps running its version even while another is
|
|
18
18
|
* installed. The active version per (scope,name) is the one named by a
|
|
19
|
-
* `.active` file, or
|
|
19
|
+
* `.active` file. Missing, unreadable, or dangling pointers fail closed instead
|
|
20
|
+
* of silently selecting another payload; legacy directories must be repaired
|
|
21
|
+
* by a reviewed install/use flow.
|
|
20
22
|
*/
|
|
21
23
|
|
|
22
24
|
import fs from "fs";
|
|
@@ -38,15 +40,25 @@ export const _deps = {
|
|
|
38
40
|
readdirSync: fs.readdirSync,
|
|
39
41
|
readFileSync: fs.readFileSync,
|
|
40
42
|
statSync: fs.statSync,
|
|
43
|
+
lstatSync: fs.lstatSync,
|
|
41
44
|
};
|
|
42
45
|
|
|
46
|
+
const MAX_ACTIVE_POINTER_BYTES = 256;
|
|
47
|
+
|
|
43
48
|
// Lowest → highest precedence.
|
|
44
49
|
export const SCOPES = ["user", "project", "local"];
|
|
45
50
|
export const DISABLED_FILENAME = ".disabled";
|
|
51
|
+
export const PLUGIN_LIFECYCLE_COORDINATOR_DIRNAME =
|
|
52
|
+
"plugin-lifecycle-transactions";
|
|
53
|
+
const PLUGIN_TRANSACTION_LOCK_DIRNAME = ".plugin-transaction-lock";
|
|
46
54
|
|
|
47
55
|
/** Filesystem-safe encoding of a (possibly scoped, e.g. @org/name) plugin name. */
|
|
48
56
|
export function encodeName(name) {
|
|
49
|
-
|
|
57
|
+
const encoded = String(name || "").replace(/[^a-zA-Z0-9._-]/g, "__");
|
|
58
|
+
if (!encoded || encoded === "." || encoded === "..") {
|
|
59
|
+
throw new Error(`invalid plugin name: ${String(name || "")}`);
|
|
60
|
+
}
|
|
61
|
+
return encoded;
|
|
50
62
|
}
|
|
51
63
|
|
|
52
64
|
/**
|
|
@@ -73,15 +85,56 @@ export function pluginNameDir(scope, name, opts = {}) {
|
|
|
73
85
|
return path.join(scopeRoot(scope, opts), encodeName(name));
|
|
74
86
|
}
|
|
75
87
|
|
|
88
|
+
/** Global same-user coordinator shared by every scope for one plugin name. */
|
|
89
|
+
export function pluginLifecycleCoordinatorDir(name, opts = {}) {
|
|
90
|
+
return path.join(pluginLifecycleCoordinatorRoot(opts), encodeName(name));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** Fixed global lock path used by runtime discovery to fence review state. */
|
|
94
|
+
export function pluginLifecycleCoordinatorLock(name, opts = {}) {
|
|
95
|
+
return path.join(
|
|
96
|
+
pluginLifecycleCoordinatorDir(name, opts),
|
|
97
|
+
PLUGIN_TRANSACTION_LOCK_DIRNAME,
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function pluginLifecycleCoordinatorRoot(opts = {}) {
|
|
102
|
+
const configured = String(
|
|
103
|
+
(opts.env || process.env).CC_PLUGIN_TRANSACTION_HOME || "",
|
|
104
|
+
).trim();
|
|
105
|
+
if (!configured) {
|
|
106
|
+
return path.join(
|
|
107
|
+
getElectronUserDataDir(),
|
|
108
|
+
PLUGIN_LIFECYCLE_COORDINATOR_DIRNAME,
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
if (!path.isAbsolute(configured)) {
|
|
112
|
+
throw new Error("CC_PLUGIN_TRANSACTION_HOME must be an absolute path");
|
|
113
|
+
}
|
|
114
|
+
const resolved = path.resolve(configured);
|
|
115
|
+
if (resolved === path.parse(resolved).root) {
|
|
116
|
+
throw new Error("CC_PLUGIN_TRANSACTION_HOME must not be a filesystem root");
|
|
117
|
+
}
|
|
118
|
+
return resolved;
|
|
119
|
+
}
|
|
120
|
+
|
|
76
121
|
/** Immutable install dir for a specific plugin version. */
|
|
77
122
|
export function pluginVersionDir(scope, name, version, opts = {}) {
|
|
78
|
-
|
|
123
|
+
const value = String(version || "");
|
|
124
|
+
if (!semver.valid(value)) {
|
|
125
|
+
throw new Error(`invalid plugin version: ${value}`);
|
|
126
|
+
}
|
|
127
|
+
return path.join(pluginNameDir(scope, name, opts), value);
|
|
79
128
|
}
|
|
80
129
|
|
|
81
130
|
/** Versions present on disk for a plugin, newest semver first. */
|
|
82
131
|
export function listInstalledVersions(scope, name, opts = {}) {
|
|
83
132
|
const dir = pluginNameDir(scope, name, opts);
|
|
84
133
|
if (!dirExists(dir)) return [];
|
|
134
|
+
return listVersionsForDir(dir);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function listVersionsForDir(dir) {
|
|
85
138
|
return _deps
|
|
86
139
|
.readdirSync(dir, { withFileTypes: true })
|
|
87
140
|
.filter((e) => e.isDirectory())
|
|
@@ -90,20 +143,53 @@ export function listInstalledVersions(scope, name, opts = {}) {
|
|
|
90
143
|
.sort(semver.rcompare);
|
|
91
144
|
}
|
|
92
145
|
|
|
93
|
-
/**
|
|
94
|
-
export function
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
146
|
+
/** Inspect pointer authority without silently selecting another payload. */
|
|
147
|
+
export function inspectActivePointer(scope, name, opts = {}) {
|
|
148
|
+
return inspectActivePointerForDir(pluginNameDir(scope, name, opts), {
|
|
149
|
+
strictIo: opts.strictIo === true,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function inspectActivePointerForDir(nameDir, { strictIo = false } = {}) {
|
|
154
|
+
if (!dirExists(nameDir, strictIo)) {
|
|
155
|
+
return { status: "absent", version: null, versions: [] };
|
|
156
|
+
}
|
|
157
|
+
const versions = listVersionsForDir(nameDir);
|
|
158
|
+
if (versions.length === 0) {
|
|
159
|
+
return { status: "absent", version: null, versions };
|
|
160
|
+
}
|
|
161
|
+
const activeFile = path.join(nameDir, ".active");
|
|
162
|
+
if (!_deps.existsSync(activeFile)) {
|
|
163
|
+
return { status: "missing", version: null, versions };
|
|
164
|
+
}
|
|
165
|
+
let pinned;
|
|
166
|
+
try {
|
|
167
|
+
const stat = _deps.lstatSync(activeFile);
|
|
168
|
+
if (!stat.isFile() || stat.size > MAX_ACTIVE_POINTER_BYTES) {
|
|
169
|
+
return { status: "unsafe", version: null, versions };
|
|
104
170
|
}
|
|
171
|
+
pinned = _deps.readFileSync(activeFile, "utf8").trim();
|
|
172
|
+
} catch (error) {
|
|
173
|
+
if (strictIo) throw error;
|
|
174
|
+
return {
|
|
175
|
+
status: "unreadable",
|
|
176
|
+
version: null,
|
|
177
|
+
versions,
|
|
178
|
+
errorCode: error?.code || null,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
if (!semver.valid(pinned)) {
|
|
182
|
+
return { status: "corrupt", version: null, versions };
|
|
105
183
|
}
|
|
106
|
-
|
|
184
|
+
if (!versions.includes(pinned)) {
|
|
185
|
+
return { status: "dangling", version: null, versions, pinned };
|
|
186
|
+
}
|
|
187
|
+
return { status: "valid", version: pinned, versions };
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/** The active version for a plugin; invalid/missing authority fails closed. */
|
|
191
|
+
export function activeVersion(scope, name, opts = {}) {
|
|
192
|
+
return inspectActivePointer(scope, name, opts).version;
|
|
107
193
|
}
|
|
108
194
|
|
|
109
195
|
/** Whether one scoped plugin install is eligible for runtime discovery. */
|
|
@@ -140,17 +226,78 @@ export function discoverPlugins(opts = {}) {
|
|
|
140
226
|
) {
|
|
141
227
|
return [];
|
|
142
228
|
}
|
|
143
|
-
const
|
|
229
|
+
const requestedScopes = new Set(opts.scopes || SCOPES);
|
|
230
|
+
for (const requested of requestedScopes) {
|
|
231
|
+
if (!SCOPES.includes(requested)) {
|
|
232
|
+
throw new Error(`unknown plugin scope: ${requested}`);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
// A caller may select a subset, but cannot reverse canonical precedence.
|
|
236
|
+
const scopes = SCOPES.filter((scope) => requestedScopes.has(scope));
|
|
144
237
|
const byName = new Map(); // name → record (later scope overrides earlier)
|
|
238
|
+
const nameByEncoded = new Map();
|
|
145
239
|
for (const scope of scopes) {
|
|
146
240
|
const root = scopeRoot(scope, opts);
|
|
147
241
|
if (!dirExists(root, opts.strictIo === true)) continue;
|
|
148
242
|
for (const encoded of listDirs(root, opts.strictIo === true)) {
|
|
149
243
|
const nameDir = path.join(root, encoded);
|
|
244
|
+
const lifecycleRecovery = findLifecycleCoordinatorRecovery(encoded, opts);
|
|
150
245
|
const enabled = !_deps.existsSync(path.join(nameDir, DISABLED_FILENAME));
|
|
151
246
|
if (!enabled && opts.includeDisabled !== true) continue;
|
|
152
|
-
const
|
|
153
|
-
|
|
247
|
+
const pointer = inspectActivePointerForDir(nameDir, {
|
|
248
|
+
strictIo: opts.strictIo === true,
|
|
249
|
+
});
|
|
250
|
+
const version = pointer.version;
|
|
251
|
+
if (!version) {
|
|
252
|
+
const recovery =
|
|
253
|
+
findRecoveryInspection(nameDir, encoded) || lifecycleRecovery;
|
|
254
|
+
const pointerStatus = recovery ? "recovery-required" : pointer.status;
|
|
255
|
+
const reservesIdentity =
|
|
256
|
+
pointer.versions.length > 0 || Boolean(recovery);
|
|
257
|
+
if (!reservesIdentity) continue;
|
|
258
|
+
// A broken higher-precedence install reserves its encoded identity.
|
|
259
|
+
// Falling through would silently activate lower-scope bytes. Remove
|
|
260
|
+
// only that name; unrelated plugins remain discoverable.
|
|
261
|
+
const shadowedName = nameByEncoded.get(encoded);
|
|
262
|
+
if (shadowedName) byName.delete(shadowedName);
|
|
263
|
+
nameByEncoded.delete(encoded);
|
|
264
|
+
opts.onBlocked?.({
|
|
265
|
+
scope,
|
|
266
|
+
encodedName: encoded,
|
|
267
|
+
pointerStatus,
|
|
268
|
+
versions: [...pointer.versions],
|
|
269
|
+
});
|
|
270
|
+
if (opts.includeBlocked === true && reservesIdentity) {
|
|
271
|
+
const inspectionVersion = recovery?.version || pointer.versions[0];
|
|
272
|
+
const inspectionRoot =
|
|
273
|
+
recovery?.root ||
|
|
274
|
+
(inspectionVersion
|
|
275
|
+
? path.join(nameDir, inspectionVersion)
|
|
276
|
+
: recovery?.transactionRoot);
|
|
277
|
+
const inspectionManifest =
|
|
278
|
+
recovery?.manifest || parsePluginManifest(inspectionRoot);
|
|
279
|
+
inspectionManifest.scope = scope;
|
|
280
|
+
const inspectedName =
|
|
281
|
+
inspectionManifest.ok === true &&
|
|
282
|
+
encodeName(inspectionManifest.metadata?.name) === encoded
|
|
283
|
+
? inspectionManifest.metadata.name
|
|
284
|
+
: shadowedName || encoded;
|
|
285
|
+
nameByEncoded.set(encoded, inspectedName);
|
|
286
|
+
byName.set(inspectedName, {
|
|
287
|
+
scope,
|
|
288
|
+
name: inspectedName,
|
|
289
|
+
version: null,
|
|
290
|
+
inspectionVersion,
|
|
291
|
+
root: inspectionRoot,
|
|
292
|
+
manifest: inspectionManifest,
|
|
293
|
+
enabled,
|
|
294
|
+
runtimeBlocked: true,
|
|
295
|
+
pointerStatus,
|
|
296
|
+
recoveryRoot: recovery?.root || recovery?.transactionRoot || null,
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
continue;
|
|
300
|
+
}
|
|
154
301
|
const versionDir = path.join(nameDir, version);
|
|
155
302
|
const manifest = parsePluginManifest(versionDir);
|
|
156
303
|
if (opts.strictIo === true && manifest.ok !== true) {
|
|
@@ -160,8 +307,70 @@ export function discoverPlugins(opts = {}) {
|
|
|
160
307
|
}`,
|
|
161
308
|
);
|
|
162
309
|
}
|
|
310
|
+
const manifestName = manifest.metadata?.name || null;
|
|
311
|
+
if (manifest.ok !== true || encodeName(manifestName) !== encoded) {
|
|
312
|
+
const shadowedName = nameByEncoded.get(encoded);
|
|
313
|
+
if (shadowedName) byName.delete(shadowedName);
|
|
314
|
+
nameByEncoded.delete(encoded);
|
|
315
|
+
const pointerStatus =
|
|
316
|
+
manifest.ok === true ? "identity-mismatch" : "manifest-invalid";
|
|
317
|
+
opts.onBlocked?.({
|
|
318
|
+
scope,
|
|
319
|
+
encodedName: encoded,
|
|
320
|
+
pointerStatus,
|
|
321
|
+
versions: [...pointer.versions],
|
|
322
|
+
});
|
|
323
|
+
if (opts.includeBlocked === true) {
|
|
324
|
+
const inspectedName = shadowedName || encoded;
|
|
325
|
+
nameByEncoded.set(encoded, inspectedName);
|
|
326
|
+
byName.set(inspectedName, {
|
|
327
|
+
scope,
|
|
328
|
+
name: inspectedName,
|
|
329
|
+
version: null,
|
|
330
|
+
inspectionVersion: version,
|
|
331
|
+
root: versionDir,
|
|
332
|
+
manifest,
|
|
333
|
+
enabled,
|
|
334
|
+
runtimeBlocked: true,
|
|
335
|
+
pointerStatus,
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
continue;
|
|
339
|
+
}
|
|
163
340
|
manifest.scope = scope;
|
|
164
|
-
const name =
|
|
341
|
+
const name = manifestName;
|
|
342
|
+
const retainedRecovery =
|
|
343
|
+
findRecoveryInspection(nameDir, encoded) || lifecycleRecovery;
|
|
344
|
+
const priorForEncoded = nameByEncoded.get(encoded);
|
|
345
|
+
if (priorForEncoded && priorForEncoded !== name) {
|
|
346
|
+
byName.delete(priorForEncoded);
|
|
347
|
+
}
|
|
348
|
+
nameByEncoded.set(encoded, name);
|
|
349
|
+
if (retainedRecovery && opts.allowRetainedInstall !== true) {
|
|
350
|
+
if (priorForEncoded) byName.delete(priorForEncoded);
|
|
351
|
+
opts.onBlocked?.({
|
|
352
|
+
scope,
|
|
353
|
+
encodedName: encoded,
|
|
354
|
+
pointerStatus: "recovery-required",
|
|
355
|
+
versions: [...pointer.versions],
|
|
356
|
+
});
|
|
357
|
+
if (opts.includeBlocked === true) {
|
|
358
|
+
byName.set(name, {
|
|
359
|
+
scope,
|
|
360
|
+
name,
|
|
361
|
+
version: null,
|
|
362
|
+
inspectionVersion: version,
|
|
363
|
+
root: versionDir,
|
|
364
|
+
manifest,
|
|
365
|
+
enabled,
|
|
366
|
+
runtimeBlocked: true,
|
|
367
|
+
pointerStatus: "recovery-required",
|
|
368
|
+
recoveryRoot:
|
|
369
|
+
retainedRecovery.root || retainedRecovery.transactionRoot,
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
continue;
|
|
373
|
+
}
|
|
165
374
|
byName.set(name, {
|
|
166
375
|
scope,
|
|
167
376
|
name,
|
|
@@ -169,6 +378,10 @@ export function discoverPlugins(opts = {}) {
|
|
|
169
378
|
root: versionDir,
|
|
170
379
|
manifest,
|
|
171
380
|
enabled,
|
|
381
|
+
runtimeBlocked: false,
|
|
382
|
+
pointerStatus: "valid",
|
|
383
|
+
recoveryRoot:
|
|
384
|
+
retainedRecovery?.root || retainedRecovery?.transactionRoot || null,
|
|
172
385
|
});
|
|
173
386
|
}
|
|
174
387
|
}
|
|
@@ -206,28 +419,6 @@ export function discoverPlugins(opts = {}) {
|
|
|
206
419
|
|
|
207
420
|
// ── internals ────────────────────────────────────────────────────────────
|
|
208
421
|
|
|
209
|
-
function activeVersionForDir(nameDir, strictIo = false) {
|
|
210
|
-
if (!dirExists(nameDir, strictIo)) return null;
|
|
211
|
-
const versions = _deps
|
|
212
|
-
.readdirSync(nameDir, { withFileTypes: true })
|
|
213
|
-
.filter((e) => e.isDirectory())
|
|
214
|
-
.map((e) => e.name)
|
|
215
|
-
.filter((v) => semver.valid(v))
|
|
216
|
-
.sort(semver.rcompare);
|
|
217
|
-
if (versions.length === 0) return null;
|
|
218
|
-
const activeFile = path.join(nameDir, ".active");
|
|
219
|
-
if (_deps.existsSync(activeFile)) {
|
|
220
|
-
try {
|
|
221
|
-
const pinned = _deps.readFileSync(activeFile, "utf8").trim();
|
|
222
|
-
if (versions.includes(pinned)) return pinned;
|
|
223
|
-
} catch (error) {
|
|
224
|
-
if (strictIo) throw error;
|
|
225
|
-
/* fall through */
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
return versions[0];
|
|
229
|
-
}
|
|
230
|
-
|
|
231
422
|
function dirExists(dir, strictIo = false) {
|
|
232
423
|
try {
|
|
233
424
|
return _deps.existsSync(dir) && _deps.statSync(dir).isDirectory();
|
|
@@ -237,6 +428,91 @@ function dirExists(dir, strictIo = false) {
|
|
|
237
428
|
}
|
|
238
429
|
}
|
|
239
430
|
|
|
431
|
+
function findRecoveryInspection(nameDir, encodedName) {
|
|
432
|
+
let entries;
|
|
433
|
+
try {
|
|
434
|
+
entries = _deps
|
|
435
|
+
.readdirSync(nameDir, { withFileTypes: true })
|
|
436
|
+
.filter(
|
|
437
|
+
(entry) =>
|
|
438
|
+
entry.isDirectory() &&
|
|
439
|
+
(entry.name.startsWith(".install-") ||
|
|
440
|
+
entry.name.startsWith(".uninstall-") ||
|
|
441
|
+
entry.name === ".plugin-transaction-lock"),
|
|
442
|
+
)
|
|
443
|
+
.sort((left, right) => {
|
|
444
|
+
if (left.name === ".plugin-transaction-lock") return 1;
|
|
445
|
+
if (right.name === ".plugin-transaction-lock") return -1;
|
|
446
|
+
return right.name.localeCompare(left.name);
|
|
447
|
+
});
|
|
448
|
+
} catch {
|
|
449
|
+
return null;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
let fallback = null;
|
|
453
|
+
for (const entry of entries.slice(0, 64)) {
|
|
454
|
+
const transactionRoot = path.join(nameDir, entry.name);
|
|
455
|
+
try {
|
|
456
|
+
const transactionStat = _deps.lstatSync(transactionRoot);
|
|
457
|
+
if (transactionStat.isSymbolicLink() || !transactionStat.isDirectory()) {
|
|
458
|
+
continue;
|
|
459
|
+
}
|
|
460
|
+
} catch {
|
|
461
|
+
continue;
|
|
462
|
+
}
|
|
463
|
+
if (!fallback) {
|
|
464
|
+
fallback = {
|
|
465
|
+
root: null,
|
|
466
|
+
version: null,
|
|
467
|
+
manifest: null,
|
|
468
|
+
transactionRoot,
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
let recoveryChildren = ["previous", "rejected", "staged"];
|
|
472
|
+
if (entry.name.startsWith(".uninstall-")) {
|
|
473
|
+
try {
|
|
474
|
+
recoveryChildren = _deps
|
|
475
|
+
.readdirSync(transactionRoot, { withFileTypes: true })
|
|
476
|
+
.filter((child) => child.isDirectory() && semver.valid(child.name))
|
|
477
|
+
.map((child) => child.name)
|
|
478
|
+
.sort(semver.rcompare);
|
|
479
|
+
} catch {
|
|
480
|
+
recoveryChildren = [];
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
for (const child of recoveryChildren) {
|
|
484
|
+
const root = path.join(transactionRoot, child);
|
|
485
|
+
let stat;
|
|
486
|
+
try {
|
|
487
|
+
stat = _deps.lstatSync(root);
|
|
488
|
+
} catch {
|
|
489
|
+
continue;
|
|
490
|
+
}
|
|
491
|
+
if (stat.isSymbolicLink() || !stat.isDirectory()) continue;
|
|
492
|
+
const manifest = parsePluginManifest(root);
|
|
493
|
+
const version = semver.valid(manifest.metadata?.version)
|
|
494
|
+
? manifest.metadata.version
|
|
495
|
+
: null;
|
|
496
|
+
const candidate = { root, version, manifest, transactionRoot };
|
|
497
|
+
if (!fallback?.root) fallback = candidate;
|
|
498
|
+
if (
|
|
499
|
+
manifest.ok === true &&
|
|
500
|
+
encodeName(manifest.metadata?.name) === encodedName
|
|
501
|
+
) {
|
|
502
|
+
return candidate;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
return fallback;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
function findLifecycleCoordinatorRecovery(encodedName, opts) {
|
|
510
|
+
const lockDir = pluginLifecycleCoordinatorLock(encodedName, opts);
|
|
511
|
+
return _deps.existsSync(lockDir)
|
|
512
|
+
? { transactionRoot: lockDir, global: true }
|
|
513
|
+
: null;
|
|
514
|
+
}
|
|
515
|
+
|
|
240
516
|
function listDirs(dir, strictIo = false) {
|
|
241
517
|
try {
|
|
242
518
|
return _deps
|