chainlesschain 0.162.148 → 0.162.150

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (322) hide show
  1. package/README.md +1 -1
  2. package/package.json +1 -1
  3. package/src/assets/web-panel/.build-hash +1 -1
  4. package/src/assets/web-panel/assets/{AIOps-DwpCCp64.js → AIOps-CBLvrjeG.js} +1 -1
  5. package/src/assets/web-panel/assets/{ActionButton-C9pBYocA.js → ActionButton-DYv2GtE0.js} +1 -1
  6. package/src/assets/web-panel/assets/{Analytics-BWAkeXxK.js → Analytics-CL6PZ-Ww.js} +3 -3
  7. package/src/assets/web-panel/assets/{AppLayout-CivFGH6B.js → AppLayout-xuyHt4uA.js} +3 -3
  8. package/src/assets/web-panel/assets/{Audit-Cm8hRpZm.js → Audit-DOvSVycq.js} +1 -1
  9. package/src/assets/web-panel/assets/{Backup-DXdFMsE8.js → Backup-DMhfTswr.js} +1 -1
  10. package/src/assets/web-panel/assets/{BaseInput-uAwSTeql.js → BaseInput-CQxDdm63.js} +1 -1
  11. package/src/assets/web-panel/assets/{Chat-KU8eeJJE.js → Chat-BEeNhK2a.js} +5 -5
  12. package/src/assets/web-panel/assets/ChatBubbleRenderer-8nul8eTq.js +1 -0
  13. package/src/assets/web-panel/assets/{Checkbox-C6AMDkjd.js → Checkbox-CL04O-ER.js} +1 -1
  14. package/src/assets/web-panel/assets/{Codegen-t2moDxcO.js → Codegen-C50o-n7x.js} +1 -1
  15. package/src/assets/web-panel/assets/{Col-DCcsRRhN.js → Col-CH-bDkzs.js} +1 -1
  16. package/src/assets/web-panel/assets/{Community-DtB-8SAC.js → Community-DqAIMvSe.js} +1 -1
  17. package/src/assets/web-panel/assets/{Compact-CZm8THYA.js → Compact-C43fo_my.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compliance-LiQgC7g1.js → Compliance-BERnMrdP.js} +1 -1
  19. package/src/assets/web-panel/assets/{Cowork-CA8SAxht.js → Cowork-Baw3w1gp.js} +4 -4
  20. package/src/assets/web-panel/assets/{Cron-CtRaF1wD.js → Cron-BEqAHF1-.js} +2 -2
  21. package/src/assets/web-panel/assets/{Crosschain-6-br6Hub.js → Crosschain-CvnmKwK4.js} +1 -1
  22. package/src/assets/web-panel/assets/{DID-Do2EccrL.js → DID-iMPxgVdt.js} +2 -2
  23. package/src/assets/web-panel/assets/{Dashboard-wrXcbzGe.js → Dashboard--4SJX3YR.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dropdown-p3FsT245.js → Dropdown-BgLV6xgz.js} +1 -1
  25. package/src/assets/web-panel/assets/{EmailListRenderer-D95A2L8q.js → EmailListRenderer-Bvb8oUD8.js} +1 -1
  26. package/src/assets/web-panel/assets/{FamilyGuardDashboard-cLuJW2zo.js → FamilyGuardDashboard-DpXPjJB5.js} +1 -1
  27. package/src/assets/web-panel/assets/{Federation-Brgq_cbN.js → Federation-BbFfJ1Xi.js} +1 -1
  28. package/src/assets/web-panel/assets/{FormItemContext-DWLCkNgh.js → FormItemContext-DeGq1B-q.js} +1 -1
  29. package/src/assets/web-panel/assets/{GenericCardRenderer-BBqUfQd6.js → GenericCardRenderer-CNW7s9zM.js} +1 -1
  30. package/src/assets/web-panel/assets/{Git-8F090w4I.js → Git-L1PjW-lT.js} +2 -2
  31. package/src/assets/web-panel/assets/{Governance-CCogEbxb.js → Governance-PK-X58to.js} +1 -1
  32. package/src/assets/web-panel/assets/{Inference-CfLD7v7C.js → Inference-BePWEH-d.js} +1 -1
  33. package/src/assets/web-panel/assets/{KnowledgeGraph-DDuHJewd.js → KnowledgeGraph-LF_sBvdL.js} +1 -1
  34. package/src/assets/web-panel/assets/{Logs-CE8KSEVC.js → Logs-BKkfk9hy.js} +2 -2
  35. package/src/assets/web-panel/assets/{Marketplace-DmwpZmhT.js → Marketplace-BNMqUDla.js} +1 -1
  36. package/src/assets/web-panel/assets/{McpTools-Bf7AazU8.js → McpTools-w4WPiyz2.js} +5 -5
  37. package/src/assets/web-panel/assets/{Memory-D0QU_00S.js → Memory-DUKMVGNi.js} +2 -2
  38. package/src/assets/web-panel/assets/{MobileBridge-yXS9xdhx.js → MobileBridge-BWhiEyTJ.js} +1 -1
  39. package/src/assets/web-panel/assets/{MobileProjects-BuDUoGUP.js → MobileProjects-Ocf5JEkX.js} +1 -1
  40. package/src/assets/web-panel/assets/{Mtc-BYyHy28p.js → Mtc-D2B6MMhU.js} +4 -4
  41. package/src/assets/web-panel/assets/{MtcAudit-CK0aqpiZ.js → MtcAudit-DdYjCq1O.js} +4 -4
  42. package/src/assets/web-panel/assets/{Multisig-mNimKYeb.js → Multisig-Cb1hfuUZ.js} +3 -3
  43. package/src/assets/web-panel/assets/{NLProgramming-AioAJ0YA.js → NLProgramming-CTeImGp7.js} +1 -1
  44. package/src/assets/web-panel/assets/{Notes-CVVNCLHE.js → Notes-BjYNc7eQ.js} +4 -4
  45. package/src/assets/web-panel/assets/{NotificationSettings-C4ABj-TK.js → NotificationSettings-Dn_NtRXQ.js} +1 -1
  46. package/src/assets/web-panel/assets/{OrderTableRenderer-DIp8Xcbd.js → OrderTableRenderer-DVYYIizh.js} +1 -1
  47. package/src/assets/web-panel/assets/{Organization-uozl_gWK.js → Organization-Be2Kmr5j.js} +4 -4
  48. package/src/assets/web-panel/assets/{Overflow-BCZOM2hK.js → Overflow-Cu_-qRlR.js} +1 -1
  49. package/src/assets/web-panel/assets/{P2P-CArcaiaj.js → P2P-DD2HoGzE.js} +2 -2
  50. package/src/assets/web-panel/assets/{PdhVaultBrowser-Sgq2Srr8.js → PdhVaultBrowser-BRI7DVth.js} +3 -3
  51. package/src/assets/web-panel/assets/{Permissions-BYrQrXnH.js → Permissions-C9Srcs2M.js} +4 -4
  52. package/src/assets/web-panel/assets/{PersonalDataHub-BzHStAbz.js → PersonalDataHub-CUqcMgo1.js} +3 -3
  53. package/src/assets/web-panel/assets/{Pipeline-k7KqxX1M.js → Pipeline-HBrQGLXt.js} +1 -1
  54. package/src/assets/web-panel/assets/{Privacy-IumTUWqx.js → Privacy-D-B0vjwh.js} +1 -1
  55. package/src/assets/web-panel/assets/{ProjectInit-BRyImYTf.js → ProjectInit-eTeLIu9e.js} +2 -2
  56. package/src/assets/web-panel/assets/{ProjectSettings-BFIqTBFk.js → ProjectSettings-DrRqCsC6.js} +2 -2
  57. package/src/assets/web-panel/assets/{Projects-Dpid9CDg.js → Projects-1G9DNOhI.js} +1 -1
  58. package/src/assets/web-panel/assets/{Providers-CyyFnUPs.js → Providers-RkTZzpxP.js} +1 -1
  59. package/src/assets/web-panel/assets/{QrScannerModal-C82cRx-X.js → QrScannerModal-BSCUgsgC.js} +1 -1
  60. package/src/assets/web-panel/assets/{QuickAsk-DGxDF521.js → QuickAsk-CHgyM3Bz.js} +1 -1
  61. package/src/assets/web-panel/assets/{Recommend-Cns-Am1y.js → Recommend-0lry4OZq.js} +1 -1
  62. package/src/assets/web-panel/assets/{RemoteSession-R7OqAIlg.js → RemoteSession-Cn45UroZ.js} +2 -2
  63. package/src/assets/web-panel/assets/{Reputation-D7mgPIYV.js → Reputation-Q-Zjb707.js} +1 -1
  64. package/src/assets/web-panel/assets/{Row-B3lEURyd.js → Row-BdM70oda.js} +1 -1
  65. package/src/assets/web-panel/assets/{RssFeed-9_UVrpBt.js → RssFeed-DmOAKKap.js} +2 -2
  66. package/src/assets/web-panel/assets/{Search-ClZeO80q.js → Search-Dwavbm07.js} +1 -1
  67. package/src/assets/web-panel/assets/{Security-BNNJczEp.js → Security-DukXFCnk.js} +3 -3
  68. package/src/assets/web-panel/assets/{Services-C5SjrWUj.js → Services-BIlRnITu.js} +2 -2
  69. package/src/assets/web-panel/assets/{Skeleton-Ci_obQ-g.js → Skeleton-YYVQdhhQ.js} +1 -1
  70. package/src/assets/web-panel/assets/{Skills-DdebN15P.js → Skills-B8_iYHz2.js} +1 -1
  71. package/src/assets/web-panel/assets/{Sla-OinZP2vi.js → Sla-BdVrhT31.js} +1 -1
  72. package/src/assets/web-panel/assets/{SpeechSettings-CxzbNF51.js → SpeechSettings-CD3ggRx7.js} +1 -1
  73. package/src/assets/web-panel/assets/{SyncSettings-D06N_66b.js → SyncSettings-Bp02VZFH.js} +2 -2
  74. package/src/assets/web-panel/assets/{Tasks-BdEdW0AZ.js → Tasks-DEVmCEsr.js} +1 -1
  75. package/src/assets/web-panel/assets/{Templates-F1ctKmPa.js → Templates-B6czWc4N.js} +1 -1
  76. package/src/assets/web-panel/assets/{Tenant-CVz1Urot.js → Tenant-BCJLv17r.js} +1 -1
  77. package/src/assets/web-panel/assets/Terminal-CD132d2Y.js +3 -0
  78. package/src/assets/web-panel/assets/{TimelineRenderer-Doitzjmf.js → TimelineRenderer-ZB-CvkZl.js} +1 -1
  79. package/src/assets/web-panel/assets/{Tokens-BpyVRpVA.js → Tokens-BnSY0S-s.js} +1 -1
  80. package/src/assets/web-panel/assets/{Trigger-nWhWYTbU.js → Trigger-VZw9Oy2w.js} +1 -1
  81. package/src/assets/web-panel/assets/{Trust-DK_G-wLx.js → Trust-pZq7Hjd2.js} +1 -1
  82. package/src/assets/web-panel/assets/{UkeySign-B5yBUojO.js → UkeySign-DnQaqk4q.js} +1 -1
  83. package/src/assets/web-panel/assets/{VideoEditing-C5D51qAe.js → VideoEditing-BEUfmvJV.js} +1 -1
  84. package/src/assets/web-panel/assets/{Wallet-CLbL9K7v.js → Wallet-CoZKMXJ2.js} +4 -4
  85. package/src/assets/web-panel/assets/{WebAuthn-DZUelI3V.js → WebAuthn-CBOGVx1I.js} +5 -5
  86. package/src/assets/web-panel/assets/{WorkflowEditor-8RPxt4KW.js → WorkflowEditor-huSKn7TT.js} +1 -1
  87. package/src/assets/web-panel/assets/{chat-4N4tOA3d.js → chat-A_3w6FBO.js} +1 -1
  88. package/src/assets/web-panel/assets/{colors-zbbGVrua.js → colors-D1Bem9Oy.js} +1 -1
  89. package/src/assets/web-panel/assets/{compact-item-D7iMkbnE.js → compact-item-CJYJj0oO.js} +1 -1
  90. package/src/assets/web-panel/assets/{createContext-CBzPJv-w.js → createContext-BkbFiKT4.js} +1 -1
  91. package/src/assets/web-panel/assets/devWarning-WDr3_M_N.js +1 -0
  92. package/src/assets/web-panel/assets/{hasIn-bHdrQSqZ.js → hasIn-CKvUafVY.js} +1 -1
  93. package/src/assets/web-panel/assets/{index-DbE5D0WL.js → index-AjrSPnvv.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-BCr0geV9.js → index-B8i0lViZ.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-CiG1IZao.js → index-B9Svn0zc.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-B1s0Bz9O.js → index-BHdHSX06.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-QFObYeo1.js → index-BHdailyo.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-BnBOpqv3.js → index-BJwlEnYo.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-CdmMoYN1.js → index-BOoAQjJz.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-DUyjUkY7.js → index-BSgWxAOG.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-CqdPyWm5.js → index-BdutMsne.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-DmqlJed-.js → index-BiDWxzbn.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-S74FpAIn.js → index-By5a0T_W.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-kmh1TxRa.js → index-C-WIY-FQ.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-BTIjjXry.js → index-C37f6iey.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-BS4_Mwk6.js → index-C9bWmTcO.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-BBNr77E1.js → index-CBaosWRO.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-QNAG4JtR.js → index-CBlBVJ_m.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-Bqmx24kh.js → index-CD62EEGo.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-CQfu1U78.js → index-CUj-l7GM.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-BJ4ZGyW0.js → index-CVS8Ymuq.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-Ci009ijp.js → index-ChkXUj3f.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-oDKNgCsP.js → index-Cj0OZ-37.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-BZb8F8YG.js → index-Co3OFL0t.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-308gCGh7.js → index-Crp8CbRg.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-CPxkoKgA.js → index-D22zNXiS.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-xYCm6W2h.js → index-DTs_D1OL.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-BtbbdLnf.js → index-DfgCdFrN.js} +3 -3
  119. package/src/assets/web-panel/assets/{index-BsKehmmS.js → index-DjYrecNb.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-CkxK86vf.js → index-DpW9cf3e.js} +1 -1
  121. package/src/assets/web-panel/assets/index-Dwix3p4g.js +1 -0
  122. package/src/assets/web-panel/assets/{index-CvRMA9uT.js → index-F--HuPG1.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-DE9j5YgT.js → index-Fuk6t_3K.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-B7b1hGry.js → index-JEAGMii9.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-D1YDh7Wr.js → index-PF-mpv8K.js} +1 -1
  126. package/src/assets/web-panel/assets/index-SHaoZ0CA.js +1 -0
  127. package/src/assets/web-panel/assets/{index-CQ6NcfWz.js → index-b-sbVdjQ.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-DyoNgbXl.js → index-pyvMVX8r.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-DISWAYce.js → index-qNTtOVi_.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-D4XKpj6c.js → index-tgO8iza6.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-CahryTX0.js → index-ttDQVhZy.js} +1 -1
  132. package/src/assets/web-panel/assets/{initDefaultProps-BD55yNBt.js → initDefaultProps-DtrnfsZH.js} +1 -1
  133. package/src/assets/web-panel/assets/{motion-B5Bbe77U.js → motion-D4zqSaX3.js} +1 -1
  134. package/src/assets/web-panel/assets/{move-CTvIqHEH.js → move-CGFGOUQj.js} +1 -1
  135. package/src/assets/web-panel/assets/{mtc-parser-BkNyPQKB.js → mtc-parser-DH2HvkJl.js} +1 -1
  136. package/src/assets/web-panel/assets/{omit-BaXJXgHA.js → omit-jJ2at5HX.js} +1 -1
  137. package/src/assets/web-panel/assets/{pickAttrs-Bw6-YTxH.js → pickAttrs-CRyMT1Fv.js} +1 -1
  138. package/src/assets/web-panel/assets/{placementArrow-BLdbkLqJ.js → placementArrow-DZ_CX0Pt.js} +1 -1
  139. package/src/assets/web-panel/assets/{responsiveObserve-IVYkzntU.js → responsiveObserve-wruHk-h5.js} +1 -1
  140. package/src/assets/web-panel/assets/{slide-DFMFwwtY.js → slide-BGgx8q67.js} +1 -1
  141. package/src/assets/web-panel/assets/{statusUtils-CURYRtZ1.js → statusUtils-Do5M7gKm.js} +1 -1
  142. package/src/assets/web-panel/assets/{styleChecker-Cfz63s1r.js → styleChecker-CRa-GZpX.js} +1 -1
  143. package/src/assets/web-panel/assets/{useFlexGapSupport-COJL0KE3.js → useFlexGapSupport-BxPcq6pj.js} +1 -1
  144. package/src/assets/web-panel/assets/{useFs-YLLojQQf.js → useFs-v5O2ZcJm.js} +1 -1
  145. package/src/assets/web-panel/assets/{usePersonalDataHub-BF_21qUC.js → usePersonalDataHub--z2FU0Px.js} +1 -1
  146. package/src/assets/web-panel/assets/{vnode-9ZpkA7bb.js → vnode-1emidVKd.js} +1 -1
  147. package/src/assets/web-panel/assets/{zoom-DhtAfhl8.js → zoom-CcJaRyHs.js} +1 -1
  148. package/src/assets/web-panel/index.html +1 -1
  149. package/src/assets/web-panel/remote-session-sw.js +43 -0
  150. package/src/command-manifest.json +22 -1
  151. package/src/commands/a2a.js +19 -4
  152. package/src/commands/activitypub.js +20 -3
  153. package/src/commands/agent.js +71 -10
  154. package/src/commands/audit.js +40 -24
  155. package/src/commands/codeintel.js +320 -0
  156. package/src/commands/collab.js +15 -2
  157. package/src/commands/compliance.js +5 -0
  158. package/src/commands/config.js +4 -1
  159. package/src/commands/dao.js +86 -14
  160. package/src/commands/dev.js +2 -0
  161. package/src/commands/did.js +7 -1
  162. package/src/commands/dlp.js +23 -1
  163. package/src/commands/economy.js +29 -3
  164. package/src/commands/eval.js +255 -0
  165. package/src/commands/evomap.js +26 -0
  166. package/src/commands/governance.js +17 -3
  167. package/src/commands/hardening.js +18 -0
  168. package/src/commands/incentive.js +5 -0
  169. package/src/commands/init.js +46 -2
  170. package/src/commands/kg.js +4 -0
  171. package/src/commands/loop.js +6 -1
  172. package/src/commands/lowcode.js +15 -2
  173. package/src/commands/marketplace.js +40 -6
  174. package/src/commands/matrix.js +20 -1
  175. package/src/commands/memory.js +4 -1
  176. package/src/commands/mtc.js +7 -1
  177. package/src/commands/nostr.js +31 -4
  178. package/src/commands/note.js +7 -4
  179. package/src/commands/plugin.js +474 -0
  180. package/src/commands/pqc.js +5 -0
  181. package/src/commands/reputation.js +10 -1
  182. package/src/commands/scim.js +6 -0
  183. package/src/commands/session.js +32 -10
  184. package/src/commands/siem.js +11 -0
  185. package/src/commands/sla.js +18 -3
  186. package/src/commands/social.js +38 -5
  187. package/src/commands/sso.js +10 -2
  188. package/src/commands/stress.js +23 -4
  189. package/src/commands/team.js +463 -0
  190. package/src/commands/tech.js +2 -0
  191. package/src/commands/tenant.js +10 -1
  192. package/src/commands/terraform.js +6 -0
  193. package/src/commands/update.js +1 -1
  194. package/src/commands/zkp.js +20 -0
  195. package/src/gateways/ws/message-dispatcher.js +48 -2
  196. package/src/gateways/ws/remote-session-protocol.js +140 -42
  197. package/src/gateways/ws/ws-server.js +1 -1
  198. package/src/harness/jsonl-session-store.js +12 -5
  199. package/src/harness/plugin-manager.js +16 -4
  200. package/src/harness/prompt-compressor.js +27 -1
  201. package/src/harness/remote-command-ledger.js +189 -0
  202. package/src/harness/remote-session-push-apns.js +246 -0
  203. package/src/harness/remote-session-push-errors.js +15 -0
  204. package/src/harness/remote-session-push-fcm.js +9 -25
  205. package/src/harness/remote-session-push-huawei.js +174 -0
  206. package/src/harness/remote-session-push-oppo.js +171 -0
  207. package/src/harness/remote-session-push-senders.js +42 -0
  208. package/src/harness/remote-session-push-vivo.js +179 -0
  209. package/src/harness/remote-session-push-web.js +299 -0
  210. package/src/harness/remote-session-push-xiaomi.js +99 -0
  211. package/src/harness/worktree-isolator.js +16 -6
  212. package/src/index.js +6 -0
  213. package/src/lib/__tests__/logger.test.js +5 -2
  214. package/src/lib/a2a-protocol.js +25 -1
  215. package/src/lib/activitypub-bridge.js +61 -0
  216. package/src/lib/agent-core.js +4 -0
  217. package/src/lib/agent-economy.js +262 -29
  218. package/src/lib/agent-network.js +7 -1
  219. package/src/lib/agent-sandbox.js +161 -5
  220. package/src/lib/agent-team/task-lease.js +434 -0
  221. package/src/lib/agent-team/team-budget.js +165 -0
  222. package/src/lib/agent-team/team-mailbox.js +106 -0
  223. package/src/lib/agent-team/team-runner.js +282 -0
  224. package/src/lib/agent-team/team-worktree.js +236 -0
  225. package/src/lib/agents.js +18 -0
  226. package/src/lib/async-hook-supervisor.cjs +391 -0
  227. package/src/lib/audit-logger.js +7 -6
  228. package/src/lib/autonomous-developer.js +60 -0
  229. package/src/lib/chat-core.js +17 -4
  230. package/src/lib/collaboration-governance.js +56 -0
  231. package/src/lib/community-governance.js +68 -0
  232. package/src/lib/compliance-manager.js +63 -0
  233. package/src/lib/cross-chain.js +5 -0
  234. package/src/lib/dao-governance.js +151 -2
  235. package/src/lib/did-manager.js +23 -10
  236. package/src/lib/dlp-engine.js +70 -0
  237. package/src/lib/eval/runner.js +251 -0
  238. package/src/lib/eval/tasks.js +626 -0
  239. package/src/lib/eval/trend.js +200 -0
  240. package/src/lib/evolution-system.js +92 -0
  241. package/src/lib/evomap-federation.js +55 -0
  242. package/src/lib/evomap-governance.js +94 -0
  243. package/src/lib/fatal-handler.js +17 -1
  244. package/src/lib/hardening-manager.js +73 -0
  245. package/src/lib/hierarchical-memory.js +14 -8
  246. package/src/lib/knowledge-exporter.js +8 -2
  247. package/src/lib/knowledge-graph.js +79 -0
  248. package/src/lib/llm-providers.js +23 -14
  249. package/src/lib/logger.js +4 -1
  250. package/src/lib/lsp/__tests__/benchmark.test.js +88 -0
  251. package/src/lib/lsp/__tests__/code-intelligence.integration.test.js +129 -0
  252. package/src/lib/lsp/__tests__/code-intelligence.test.js +228 -0
  253. package/src/lib/lsp/__tests__/jsonrpc-stream.test.js +104 -0
  254. package/src/lib/lsp/__tests__/lsp-client.test.js +269 -0
  255. package/src/lib/lsp/__tests__/lsp-manager.test.js +333 -0
  256. package/src/lib/lsp/__tests__/lsp-server-registry.test.js +128 -0
  257. package/src/lib/lsp/benchmark.js +257 -0
  258. package/src/lib/lsp/code-intelligence.js +356 -0
  259. package/src/lib/lsp/jsonrpc-stream.js +139 -0
  260. package/src/lib/lsp/lsp-client.js +339 -0
  261. package/src/lib/lsp/lsp-manager.js +375 -0
  262. package/src/lib/lsp/lsp-server-registry.js +196 -0
  263. package/src/lib/matrix-bridge.js +84 -0
  264. package/src/lib/memory-manager.js +5 -3
  265. package/src/lib/nostr-bridge.js +53 -0
  266. package/src/lib/permission-engine.js +22 -4
  267. package/src/lib/plugin-monitor-supervisor.js +238 -0
  268. package/src/lib/plugin-runtime/__tests__/remote-source.test.js +256 -0
  269. package/src/lib/plugin-runtime/agents.js +51 -0
  270. package/src/lib/plugin-runtime/bin.js +100 -0
  271. package/src/lib/plugin-runtime/hooks.js +100 -0
  272. package/src/lib/plugin-runtime/install.js +396 -0
  273. package/src/lib/plugin-runtime/lsp.js +75 -0
  274. package/src/lib/plugin-runtime/manifest.js +458 -0
  275. package/src/lib/plugin-runtime/mcp.js +89 -0
  276. package/src/lib/plugin-runtime/monitors.js +100 -0
  277. package/src/lib/plugin-runtime/policy.js +152 -0
  278. package/src/lib/plugin-runtime/reload.js +79 -0
  279. package/src/lib/plugin-runtime/remote-source.js +240 -0
  280. package/src/lib/plugin-runtime/scopes.js +197 -0
  281. package/src/lib/plugin-runtime/settings.js +119 -0
  282. package/src/lib/plugin-runtime/signature.js +107 -0
  283. package/src/lib/plugin-runtime/skills.js +43 -0
  284. package/src/lib/plugin-runtime/trust.js +140 -0
  285. package/src/lib/pqc-manager.js +64 -0
  286. package/src/lib/reputation-optimizer.js +101 -0
  287. package/src/lib/sandbox-egress-proxy.js +262 -0
  288. package/src/lib/sandbox-fs-policy.js +112 -0
  289. package/src/lib/sandbox-network-policy.js +151 -0
  290. package/src/lib/sandbox-v2.js +24 -18
  291. package/src/lib/scim-manager.js +36 -0
  292. package/src/lib/session-manager.js +5 -2
  293. package/src/lib/settings-hook-events.cjs +78 -6
  294. package/src/lib/settings-hooks.cjs +30 -3
  295. package/src/lib/settings-loader.cjs +35 -1
  296. package/src/lib/siem-exporter.js +45 -0
  297. package/src/lib/skill-loader.js +38 -2
  298. package/src/lib/skill-marketplace.js +83 -0
  299. package/src/lib/sla-manager.js +88 -0
  300. package/src/lib/social-manager.js +74 -0
  301. package/src/lib/stress-tester.js +65 -0
  302. package/src/lib/tech-learning-engine.js +75 -0
  303. package/src/lib/telemetry/span-recorder.js +237 -0
  304. package/src/lib/tenant-saas.js +107 -0
  305. package/src/lib/terraform-manager.js +67 -0
  306. package/src/lib/token-incentive.js +180 -29
  307. package/src/lib/wallet-manager.js +81 -35
  308. package/src/lib/zkp-engine.js +87 -0
  309. package/src/repl/agent-repl.js +417 -6
  310. package/src/runtime/__tests__/auto-pin.test.js +104 -0
  311. package/src/runtime/agent-core.js +771 -104
  312. package/src/runtime/auto-pin.js +117 -0
  313. package/src/runtime/coding-agent-contract-shared.cjs +82 -8
  314. package/src/runtime/coding-agent-policy.cjs +32 -7
  315. package/src/runtime/fallback-model.js +134 -7
  316. package/src/runtime/headless-runner.js +388 -108
  317. package/src/runtime/mcp-config.js +46 -0
  318. package/src/assets/web-panel/assets/ChatBubbleRenderer-DCNfbdlx.js +0 -1
  319. package/src/assets/web-panel/assets/Terminal-BvAK_Zel.js +0 -3
  320. package/src/assets/web-panel/assets/devWarning-C2Z5LRgq.js +0 -1
  321. package/src/assets/web-panel/assets/index-BGp6Yr-Y.js +0 -1
  322. package/src/assets/web-panel/assets/index-BXiw9dQf.js +0 -1
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Plugin `bin` component — put a trusted plugin's executables on PATH for the
3
+ * session (Phase 3.3n). A plugin ships helper executables under `bin/`; making
4
+ * them resolvable means the agent's `run_shell` (and monitors/hooks, which
5
+ * inherit the process env) can invoke `some-plugin-tool` by name.
6
+ *
7
+ * Wiring: prepend the trusted plugins' bin dirs to `process.env.PATH` at session
8
+ * start and RESTORE the original PATH at session end — session-scoped, so no
9
+ * plugin executable stays resolvable after the session. Every child process
10
+ * inherits process.env, so this one mutation covers run_shell (foreground +
11
+ * background), the monitor supervisor, and hook commands uniformly.
12
+ *
13
+ * SECURITY: an executable on PATH runs code, so — like hooks/LSP/MCP/monitors —
14
+ * only TRUSTED plugins contribute (user/local auto-trusted; project needs
15
+ * `cc plugin trust`). An untrusted cloned-repo plugin can NOT shadow a system
16
+ * command or get its binary invoked.
17
+ */
18
+
19
+ import path from "path";
20
+ import { discoverPlugins } from "./scopes.js";
21
+ import { partitionByTrust, warnUntrustedOnce } from "./trust.js";
22
+
23
+ /**
24
+ * Collect trusted, installed plugins' `bin/` directories.
25
+ * @param {object} [opts] { cwd, scopes }
26
+ * @returns {Array<{plugin, scope, version, dir}>}
27
+ */
28
+ export function collectPluginBinDirs(opts = {}) {
29
+ let plugins = [];
30
+ try {
31
+ plugins = discoverPlugins({ cwd: opts.cwd, scopes: opts.scopes });
32
+ } catch {
33
+ return [];
34
+ }
35
+ const { trusted, skipped } = partitionByTrust(plugins);
36
+ warnUntrustedOnce(
37
+ skipped
38
+ .filter((p) => p.manifest?.components?.bin?.length)
39
+ .map((p) => p.name),
40
+ "bin",
41
+ );
42
+ const out = [];
43
+ for (const p of trusted) {
44
+ if (!p.manifest || p.manifest.ok !== true) continue;
45
+ const bins = p.manifest.components?.bin;
46
+ if (!Array.isArray(bins) || bins.length === 0) continue;
47
+ // Every bin entry's absPath is a file inside the plugin's bin dir; collect
48
+ // the unique parent directories (usually just `<root>/bin`).
49
+ const dirs = new Set(bins.map((b) => path.dirname(b.absPath)));
50
+ for (const dir of dirs) {
51
+ out.push({
52
+ plugin: p.name,
53
+ scope: p.scope,
54
+ version: p.version,
55
+ dir,
56
+ });
57
+ }
58
+ }
59
+ return out;
60
+ }
61
+
62
+ /**
63
+ * Prepend trusted plugins' bin dirs to `env.PATH` (defaults to process.env).
64
+ * Returns a `restore()` that puts PATH back, plus the dirs added. Idempotent per
65
+ * call — a dir already on PATH is not added twice.
66
+ *
67
+ * @param {object} [opts] { cwd, scopes, env }
68
+ * @returns {{ added: string[], restore: () => void }}
69
+ */
70
+ export function applyPluginBinPath(opts = {}) {
71
+ const env = opts.env || process.env;
72
+ const dirs = collectPluginBinDirs({ cwd: opts.cwd, scopes: opts.scopes }).map(
73
+ (b) => b.dir,
74
+ );
75
+ const prevPath = env.PATH;
76
+ if (dirs.length === 0) {
77
+ return { added: [], restore: () => {} };
78
+ }
79
+ const existing = new Set(
80
+ String(prevPath || "")
81
+ .split(path.delimiter)
82
+ .filter(Boolean),
83
+ );
84
+ const added = dirs.filter((d) => !existing.has(d));
85
+ if (added.length === 0) {
86
+ return { added: [], restore: () => {} };
87
+ }
88
+ env.PATH = [...added, prevPath].filter(Boolean).join(path.delimiter);
89
+ let restored = false;
90
+ return {
91
+ added,
92
+ restore: () => {
93
+ if (restored) return;
94
+ restored = true;
95
+ // Restore only if nothing else re-touched PATH out from under us; either
96
+ // way, put the recorded previous value back (session-scoped semantics).
97
+ env.PATH = prevPath;
98
+ },
99
+ };
100
+ }
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Merge installed plugins' `hooks/hooks.json` into the effective settings-hook
3
+ * map (Phase 3.3c — plugin Hook component reaches the agent lifecycle).
4
+ *
5
+ * A plugin ships lifecycle hooks in the same shape as `.claude/settings.json`
6
+ * `hooks`: a map of event name → array of `{ matcher?, hooks: [{type,command}] }`
7
+ * entries, optionally wrapped under a top-level `hooks` key. Those entries are
8
+ * concatenated onto whatever the user's settings already declared, so a plugin
9
+ * ADDS hooks without being able to silently replace the user's.
10
+ *
11
+ * Only plugins whose manifest fully validated (`manifest.ok`) contribute. Note:
12
+ * a hook can run a shell command, so a plugin's hooks carry the same trust as
13
+ * the user installing it (same as an npm package's lifecycle scripts) and run
14
+ * through the existing hook-runner (which applies the project-hook trust model).
15
+ */
16
+
17
+ import fs from "fs";
18
+ import { discoverPlugins } from "./scopes.js";
19
+ import { partitionByTrust, warnUntrustedOnce } from "./trust.js";
20
+
21
+ export const _deps = { readFileSync: fs.readFileSync };
22
+
23
+ /** Accept either `{ hooks: {Event:[...]} }` (plugin wrap) or `{Event:[...]}`. */
24
+ function normalizeHookMap(parsed) {
25
+ if (
26
+ parsed &&
27
+ typeof parsed === "object" &&
28
+ !Array.isArray(parsed) &&
29
+ parsed.hooks &&
30
+ typeof parsed.hooks === "object" &&
31
+ !Array.isArray(parsed.hooks)
32
+ ) {
33
+ return parsed.hooks;
34
+ }
35
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed)
36
+ ? parsed
37
+ : {};
38
+ }
39
+
40
+ /**
41
+ * Collect + merge every installed plugin's hook entries into one event map.
42
+ * @param {object} [opts] { cwd, scopes }
43
+ * @returns {Record<string, Array>} event name → concatenated hook entries
44
+ */
45
+ export function collectPluginHooks(opts = {}) {
46
+ let plugins = [];
47
+ try {
48
+ plugins = discoverPlugins({ cwd: opts.cwd, scopes: opts.scopes });
49
+ } catch {
50
+ return {};
51
+ }
52
+ // A hook runs a shell command — gate it behind trust so a cloned repo's
53
+ // project plugin can't run commands the moment the agent starts.
54
+ const { trusted, skipped } = partitionByTrust(plugins);
55
+ warnUntrustedOnce(
56
+ skipped.filter((p) => p.manifest?.components?.hooks).map((p) => p.name),
57
+ "hooks",
58
+ );
59
+ const merged = {};
60
+ for (const p of trusted) {
61
+ if (!p.manifest || p.manifest.ok !== true) continue;
62
+ const h = p.manifest.components?.hooks;
63
+ if (!h || !h.absPath) continue;
64
+ let parsed;
65
+ try {
66
+ parsed = JSON.parse(_deps.readFileSync(h.absPath, "utf8"));
67
+ } catch {
68
+ continue;
69
+ }
70
+ const map = normalizeHookMap(parsed);
71
+ for (const [event, entries] of Object.entries(map)) {
72
+ if (!Array.isArray(entries)) continue;
73
+ merged[event] = (merged[event] || []).concat(entries);
74
+ }
75
+ }
76
+ return merged;
77
+ }
78
+
79
+ /**
80
+ * Return a settings-hook map that ADDS the installed plugins' hooks to the
81
+ * user's own. Returns the input unchanged when no plugin contributes hooks.
82
+ *
83
+ * @param {object|null} settingsHooks the user's loaded settings hooks
84
+ * @param {object} [opts] { cwd, scopes }
85
+ */
86
+ export function mergePluginHooks(settingsHooks, opts = {}) {
87
+ const plugin = collectPluginHooks(opts);
88
+ const events = Object.keys(plugin);
89
+ if (events.length === 0) return settingsHooks;
90
+ const out =
91
+ settingsHooks && typeof settingsHooks === "object"
92
+ ? { ...settingsHooks }
93
+ : {};
94
+ for (const event of events) {
95
+ out[event] = (Array.isArray(out[event]) ? out[event] : []).concat(
96
+ plugin[event],
97
+ );
98
+ }
99
+ return out;
100
+ }
@@ -0,0 +1,396 @@
1
+ /**
2
+ * Plugin install lifecycle (Phase 3.3d) — put a plugin ONTO disk in an immutable
3
+ * scope version directory, so the component wirings (skills / lsp / hooks) built
4
+ * in 3.2–3.3c actually reach the agent for a real user instead of only for
5
+ * hand-placed fixtures.
6
+ *
7
+ * installFromDirectory(src, {scope}) → validate manifest → copy into
8
+ * <scopeRoot>/<encodedName>/<version>/ → mark that version active
9
+ * listInstalled({cwd}) → discover across scopes
10
+ * uninstall(name, {scope, version}) → remove a version (or the whole plugin)
11
+ * setActiveVersion(name, version) → repoint `.active` (rollback)
12
+ *
13
+ * Version directories are immutable: re-installing the same version refuses
14
+ * unless `force`, so an in-flight session keeps running its bytes. The copy
15
+ * skips symlinks (a symlink could later resolve outside the sandbox) and only
16
+ * writes inside the destination version dir.
17
+ */
18
+
19
+ import fs from "fs";
20
+ import os from "os";
21
+ import path from "path";
22
+ import { spawnSync } from "child_process";
23
+ import { parsePluginManifest, isWithin } from "./manifest.js";
24
+ import {
25
+ pluginNameDir,
26
+ pluginVersionDir,
27
+ listInstalledVersions,
28
+ activeVersion,
29
+ discoverPlugins,
30
+ } from "./scopes.js";
31
+ import { verifyPluginManifest } from "../plugin-security.js";
32
+ import { writePluginLock } from "./signature.js";
33
+
34
+ export const _deps = {
35
+ existsSync: fs.existsSync,
36
+ mkdirSync: fs.mkdirSync,
37
+ rmSync: fs.rmSync,
38
+ readdirSync: fs.readdirSync,
39
+ copyFileSync: fs.copyFileSync,
40
+ lstatSync: fs.lstatSync,
41
+ writeFileSync: fs.writeFileSync,
42
+ mkdtempSync: fs.mkdtempSync,
43
+ spawnSync,
44
+ };
45
+
46
+ /**
47
+ * Install a plugin from a local directory into a scope's immutable version dir.
48
+ * @param {string} srcDir directory containing the plugin (with its manifest)
49
+ * @param {object} opts { scope="user", cwd, force=false }
50
+ * @returns {{ name, version, scope, dir, warnings }}
51
+ */
52
+ export function installFromDirectory(srcDir, opts = {}) {
53
+ const scope = opts.scope || "user";
54
+ const src = path.resolve(srcDir);
55
+ if (!_deps.existsSync(src)) {
56
+ throw new Error(`source directory does not exist: ${src}`);
57
+ }
58
+
59
+ const manifest = parsePluginManifest(src);
60
+ if (!manifest.ok) {
61
+ throw new Error(
62
+ `plugin manifest is invalid:\n - ${manifest.errors.join("\n - ")}`,
63
+ );
64
+ }
65
+ const { name, version } = manifest.metadata;
66
+
67
+ // Optional signature/integrity verification of the manifest at install time
68
+ // (Phase 3.3l). verifyPluginManifest THROWS on any mismatch/failure — a signed
69
+ // install that fails verification must not land on disk (fail-closed). On
70
+ // success we record a `.plugin-lock.json` so load-time requireSignedPlugins
71
+ // can re-check it without the original signature/key files.
72
+ let verification = null;
73
+ const sig = opts.signature;
74
+ if (sig && (sig.sha256 || sig.signatureFile || sig.requireSignature)) {
75
+ verification = verifyPluginManifest({
76
+ manifestFile: manifest.manifestPath,
77
+ expectedSha256: sig.sha256,
78
+ signatureFile: sig.signatureFile,
79
+ publicKeyFile: sig.publicKeyFile,
80
+ requireSignature: sig.requireSignature === true,
81
+ trustedKeySha256: sig.trustedKeySha256 || null,
82
+ requireTrustedKey: sig.requireTrustedKey === true,
83
+ });
84
+ }
85
+
86
+ const dest = pluginVersionDir(scope, name, version, { cwd: opts.cwd });
87
+ if (_deps.existsSync(dest)) {
88
+ if (!opts.force) {
89
+ throw new Error(
90
+ `${name}@${version} is already installed at ${scope} scope (immutable). ` +
91
+ `Use --force to reinstall, or bump the version.`,
92
+ );
93
+ }
94
+ _deps.rmSync(dest, { recursive: true, force: true });
95
+ }
96
+
97
+ _deps.mkdirSync(dest, { recursive: true });
98
+ copyDirGuarded(src, dest, dest);
99
+
100
+ // Record the verified signature into the installed (immutable) version dir so
101
+ // load-time enforcement can re-check it. The manifest was copied verbatim, so
102
+ // its bytes/sha in `dest` match what we verified in `src`.
103
+ if (verification) {
104
+ const destManifest = path.join(
105
+ dest,
106
+ path.relative(src, manifest.manifestPath),
107
+ );
108
+ writePluginLock(dest, {
109
+ manifestFile: destManifest,
110
+ sha256: verification.sha256,
111
+ publicKeySha256: verification.publicKeySha256,
112
+ signatureVerified: verification.signatureVerified === true,
113
+ });
114
+ }
115
+
116
+ // Make the freshly-installed version active.
117
+ setActiveVersion(name, version, { scope, cwd: opts.cwd });
118
+
119
+ return {
120
+ name,
121
+ version,
122
+ scope,
123
+ dir: dest,
124
+ warnings: manifest.warnings,
125
+ signatureVerified: verification?.signatureVerified === true,
126
+ };
127
+ }
128
+
129
+ /**
130
+ * Install from a source string:
131
+ * - a local directory → copied in directly
132
+ * - a git URL (https://…, git@…, ….git, file://…) → shallow-cloned then installed
133
+ * - GitHub shorthand `owner/repo` → https://github.com/owner/repo.git
134
+ * An optional `#ref` (branch / tag / commit) pins the checkout.
135
+ */
136
+ export function installFromSource(source, opts = {}) {
137
+ return _withMaterializedSource(source, (dir, info) => {
138
+ const res = installFromDirectory(dir, opts);
139
+ return info ? { ...res, source: info.url, ref: info.ref || null } : res;
140
+ });
141
+ }
142
+
143
+ /**
144
+ * Materialize a source string into a local directory (cloning a git source into
145
+ * a temp dir), invoke `fn(dir, gitInfo|null)`, then clean up any temp checkout.
146
+ * Single fetch shared by installFromSource + updatePlugin.
147
+ */
148
+ function _withMaterializedSource(source, fn) {
149
+ const raw = String(source || "");
150
+ const asDir = path.resolve(raw);
151
+ if (_deps.existsSync(asDir) && _deps.lstatSync(asDir).isDirectory()) {
152
+ return fn(asDir, null);
153
+ }
154
+ const git = parseGitSource(raw);
155
+ if (git) {
156
+ const cloned = fetchGitRepo(git.url, git.ref);
157
+ try {
158
+ return fn(cloned, git);
159
+ } finally {
160
+ try {
161
+ _deps.rmSync(path.dirname(cloned), { recursive: true, force: true });
162
+ } catch {
163
+ /* temp cleanup is best-effort */
164
+ }
165
+ }
166
+ }
167
+ throw new Error(
168
+ `source not found as a local directory or git URL: ${source}`,
169
+ );
170
+ }
171
+
172
+ /**
173
+ * Update an installed plugin from a source (local dir or git). Fetches the
174
+ * source ONCE, reads its name+version, and:
175
+ * - a NEW version → installs the new immutable version dir + repoints
176
+ * `.active` (the old version stays on disk for rollback via `cc plugin use`);
177
+ * - the SAME version → no-op unless `--force` reinstalls it.
178
+ * Returns { name, version, previousVersion, updated, reinstalled }.
179
+ */
180
+ export function updatePlugin(source, opts = {}) {
181
+ const scope = opts.scope || "user";
182
+ return _withMaterializedSource(source, (dir, info) => {
183
+ const manifest = parsePluginManifest(dir);
184
+ if (!manifest.ok) {
185
+ throw new Error(
186
+ `plugin manifest is invalid:\n - ${manifest.errors.join("\n - ")}`,
187
+ );
188
+ }
189
+ const { name, version } = manifest.metadata;
190
+ const previousVersion = getActiveVersion(name, { scope, cwd: opts.cwd });
191
+ const dest = pluginVersionDir(scope, name, version, { cwd: opts.cwd });
192
+ const sameVersionExists = _deps.existsSync(dest);
193
+
194
+ if (sameVersionExists && !opts.force) {
195
+ // Already at this version — make sure it's the active one, but don't
196
+ // reinstall an immutable dir.
197
+ if (previousVersion !== version) {
198
+ setActiveVersion(name, version, { scope, cwd: opts.cwd });
199
+ }
200
+ return {
201
+ name,
202
+ version,
203
+ previousVersion,
204
+ updated: previousVersion !== version,
205
+ reinstalled: false,
206
+ source: info ? info.url : null,
207
+ };
208
+ }
209
+
210
+ const res = installFromDirectory(dir, { ...opts, scope, force: true });
211
+ return {
212
+ ...res,
213
+ previousVersion,
214
+ updated: previousVersion !== version,
215
+ reinstalled: sameVersionExists,
216
+ source: info ? info.url : null,
217
+ ref: info ? info.ref || null : null,
218
+ };
219
+ });
220
+ }
221
+
222
+ /**
223
+ * Classify a source string into a git URL (+ optional ref), or null when it is
224
+ * not remote-looking. `owner/repo` expands to a GitHub HTTPS URL.
225
+ */
226
+ export function parseGitSource(raw) {
227
+ const [loc, ref] = String(raw || "").split("#");
228
+ if (!loc) return null;
229
+ if (
230
+ /^(https?|git|ssh|file):\/\//.test(loc) ||
231
+ loc.endsWith(".git") ||
232
+ /^git@/.test(loc)
233
+ ) {
234
+ return { url: loc, ref: ref || null };
235
+ }
236
+ if (/^[\w.-]+\/[\w.-]+$/.test(loc)) {
237
+ return { url: `https://github.com/${loc}.git`, ref: ref || null };
238
+ }
239
+ return null;
240
+ }
241
+
242
+ /**
243
+ * Shallow-clone `url` (optionally at `ref`) into a fresh temp dir and return the
244
+ * checkout path. Uses `git` via spawn WITHOUT a shell (url/ref are argv, not a
245
+ * command line — no injection). Caller removes the temp dir's parent.
246
+ */
247
+ export function fetchGitRepo(url, ref) {
248
+ const base = _deps.mkdtempSync(path.join(os.tmpdir(), "cc-plugin-git-"));
249
+ const dir = path.join(base, "repo");
250
+ const run = (args) =>
251
+ _deps.spawnSync("git", args, {
252
+ encoding: "utf8",
253
+ timeout: 120000,
254
+ windowsHide: true,
255
+ shell: false,
256
+ });
257
+
258
+ const cloneArgs = ["clone", "--depth", "1"];
259
+ if (ref) cloneArgs.push("--branch", ref);
260
+ cloneArgs.push(url, dir);
261
+ let res = run(cloneArgs);
262
+ if (res.error && res.error.code === "ENOENT") {
263
+ throw new Error("git is not installed (needed to fetch a remote plugin)");
264
+ }
265
+ if (res.status !== 0) {
266
+ // A commit SHA can't be used with --branch/--depth; retry with a full clone
267
+ // then checkout the ref explicitly.
268
+ if (ref) {
269
+ try {
270
+ _deps.rmSync(dir, { recursive: true, force: true });
271
+ } catch {
272
+ /* ignore */
273
+ }
274
+ const full = run(["clone", url, dir]);
275
+ if (!full.error && full.status === 0) {
276
+ const co = run(["-C", dir, "checkout", ref]);
277
+ if (co.status === 0) return dir;
278
+ }
279
+ }
280
+ const reason = (res.stderr || "").trim() || `git exited ${res.status}`;
281
+ throw new Error(`git clone failed for ${url}: ${reason}`);
282
+ }
283
+ return dir;
284
+ }
285
+
286
+ /**
287
+ * List installed plugins (active version per name) across scopes. Uses
288
+ * `skipPolicy` so the ADMIN view shows every plugin on disk — including one an
289
+ * org managed policy blocks from LOADING — otherwise a denied plugin would be
290
+ * invisible and impossible to inspect / uninstall / un-deny.
291
+ */
292
+ export function listInstalled(opts = {}) {
293
+ return discoverPlugins({
294
+ cwd: opts.cwd,
295
+ scopes: opts.scopes,
296
+ skipPolicy: true,
297
+ }).map((p) => ({
298
+ name: p.name,
299
+ version: p.version,
300
+ scope: p.scope,
301
+ dir: p.root,
302
+ ok: p.manifest?.ok === true,
303
+ }));
304
+ }
305
+
306
+ /**
307
+ * Uninstall a plugin. Without `version`, removes the whole plugin (all versions);
308
+ * with `version`, removes just that one and repoints `.active` if needed.
309
+ * @returns {{ removed: string[] }}
310
+ */
311
+ export function uninstall(name, opts = {}) {
312
+ const scope = opts.scope || "user";
313
+ const cwd = opts.cwd;
314
+ const removed = [];
315
+
316
+ if (opts.version) {
317
+ const dir = pluginVersionDir(scope, name, opts.version, { cwd });
318
+ if (!_deps.existsSync(dir)) {
319
+ throw new Error(
320
+ `${name}@${opts.version} is not installed at ${scope} scope`,
321
+ );
322
+ }
323
+ // Capture the active version BEFORE removing, so we only repoint `.active`
324
+ // when the version we removed WAS the active one. Removing a NON-active
325
+ // version (e.g. cleaning up a newer version after rolling back to an older
326
+ // pinned one) must not silently change which version is active — the old
327
+ // code always rewrote `.active` to the newest remaining, so uninstalling an
328
+ // unrelated version could bump the user's pinned choice.
329
+ const removedWasActive =
330
+ getActiveVersion(name, { scope, cwd }) === opts.version;
331
+ _deps.rmSync(dir, { recursive: true, force: true });
332
+ removed.push(opts.version);
333
+ // Repoint .active to the newest remaining version, or clear it.
334
+ const remaining = listInstalledVersions(scope, name, { cwd });
335
+ const activeFile = path.join(
336
+ pluginNameDir(scope, name, { cwd }),
337
+ ".active",
338
+ );
339
+ if (remaining.length === 0) {
340
+ _deps.rmSync(pluginNameDir(scope, name, { cwd }), {
341
+ recursive: true,
342
+ force: true,
343
+ });
344
+ } else if (removedWasActive && _deps.existsSync(activeFile)) {
345
+ _deps.writeFileSync(activeFile, remaining[0], "utf8");
346
+ }
347
+ return { removed };
348
+ }
349
+
350
+ const nameDir = pluginNameDir(scope, name, { cwd });
351
+ if (!_deps.existsSync(nameDir)) {
352
+ throw new Error(`${name} is not installed at ${scope} scope`);
353
+ }
354
+ removed.push(...listInstalledVersions(scope, name, { cwd }));
355
+ _deps.rmSync(nameDir, { recursive: true, force: true });
356
+ return { removed };
357
+ }
358
+
359
+ /** Pin a plugin's active version (rollback / switch). */
360
+ export function setActiveVersion(name, version, opts = {}) {
361
+ const scope = opts.scope || "user";
362
+ const cwd = opts.cwd;
363
+ const versionDir = pluginVersionDir(scope, name, version, { cwd });
364
+ if (!_deps.existsSync(versionDir)) {
365
+ throw new Error(`${name}@${version} is not installed at ${scope} scope`);
366
+ }
367
+ const activeFile = path.join(pluginNameDir(scope, name, { cwd }), ".active");
368
+ _deps.writeFileSync(activeFile, String(version), "utf8");
369
+ return { name, version, scope, active: version };
370
+ }
371
+
372
+ /** Which version is active for a plugin at a scope (or null). */
373
+ export function getActiveVersion(name, opts = {}) {
374
+ return activeVersion(opts.scope || "user", name, { cwd: opts.cwd });
375
+ }
376
+
377
+ // ── guarded recursive copy ────────────────────────────────────────────────
378
+
379
+ /**
380
+ * Copy `src` → `dst`, refusing to write outside `root` and skipping symlinks
381
+ * (which could later resolve outside the plugin sandbox). Directories recurse.
382
+ */
383
+ function copyDirGuarded(src, dst, root) {
384
+ for (const entry of _deps.readdirSync(src, { withFileTypes: true })) {
385
+ const from = path.join(src, entry.name);
386
+ const to = path.join(dst, entry.name);
387
+ if (!isWithin(root, to)) continue; // never escape the version dir
388
+ if (entry.isSymbolicLink()) continue; // do not copy symlinks
389
+ if (entry.isDirectory()) {
390
+ _deps.mkdirSync(to, { recursive: true });
391
+ copyDirGuarded(from, to, root);
392
+ } else if (entry.isFile()) {
393
+ _deps.copyFileSync(from, to);
394
+ }
395
+ }
396
+ }
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Apply installed plugins' `.lsp.json` language-server contributions to the LSP
3
+ * registry (Phase 3.2 — first plugin component actually wired to the agent).
4
+ *
5
+ * A plugin declares extra language servers via `.lsp.json`; this bridges those
6
+ * declarations into `lsp-server-registry.registerLanguageServer`, so the Phase 2
7
+ * `code_intelligence` agent tool and `cc code-intel` command transparently gain
8
+ * definition/references/diagnostics for the plugin's language — no core change
9
+ * per new language.
10
+ *
11
+ * Idempotent + memoized per project root: the first LSP query (agent or CLI)
12
+ * triggers a one-time scan of the user/project/local plugin scopes.
13
+ */
14
+
15
+ import path from "path";
16
+ import { discoverPlugins } from "./scopes.js";
17
+ import { registerLanguageServer } from "../lsp/lsp-server-registry.js";
18
+ import { partitionByTrust, warnUntrustedOnce } from "./trust.js";
19
+
20
+ const _loadedRoots = new Set();
21
+
22
+ /**
23
+ * Register every installed plugin's LSP servers for `cwd` (once per root).
24
+ * Never throws — a broken plugin manifest must not break code navigation.
25
+ *
26
+ * @param {object} [opts] { cwd, scopes, force }
27
+ * @returns {{ registered: Array<{plugin, languageId, id}> }}
28
+ */
29
+ export function ensurePluginLspServers(opts = {}) {
30
+ const cwd = path.resolve(opts.cwd || process.cwd());
31
+ if (_loadedRoots.has(cwd) && !opts.force) return { registered: [] };
32
+ _loadedRoots.add(cwd);
33
+
34
+ const registered = [];
35
+ let plugins = [];
36
+ try {
37
+ plugins = discoverPlugins({ cwd, scopes: opts.scopes });
38
+ } catch {
39
+ return { registered };
40
+ }
41
+
42
+ // An LSP server spawns a binary — gate it behind trust. Untrusted project
43
+ // plugins (e.g. from a cloned repo) don't get to launch processes silently.
44
+ const { trusted, skipped } = partitionByTrust(plugins);
45
+ warnUntrustedOnce(
46
+ skipped
47
+ .filter((p) => (p.manifest?.components?.lsp || []).length > 0)
48
+ .map((p) => p.name),
49
+ "language servers",
50
+ );
51
+
52
+ for (const p of trusted) {
53
+ const servers = p.manifest?.components?.lsp || [];
54
+ for (const s of servers) {
55
+ try {
56
+ registerLanguageServer({
57
+ languageId: s.languageId,
58
+ command: s.command,
59
+ args: s.args,
60
+ extensions: s.extensions,
61
+ id: s.id,
62
+ });
63
+ registered.push({ plugin: p.name, languageId: s.languageId, id: s.id });
64
+ } catch {
65
+ // skip a malformed server entry; other plugins still load
66
+ }
67
+ }
68
+ }
69
+ return { registered };
70
+ }
71
+
72
+ /** Test hook: forget which roots have been scanned so a re-scan can run. */
73
+ export function _resetPluginLspLoadState() {
74
+ _loadedRoots.clear();
75
+ }