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,458 @@
1
+ /**
2
+ * Unified plugin manifest — parse + normalize a ChainlessChain plugin into the
3
+ * full set of components it contributes (Phase 3 of the CLI parity plan).
4
+ *
5
+ * Today the CLI only understands `manifest.skills[]` (harness/plugin-manager.js).
6
+ * A real extension unit bundles more than skills, so this module reads the
7
+ * unified layout:
8
+ *
9
+ * plugin/
10
+ * ├── .chainlesschain-plugin/plugin.json (metadata; legacy top-level plugin.json accepted)
11
+ * ├── skills/<name>/SKILL.md
12
+ * ├── agents/<name>.md
13
+ * ├── hooks/hooks.json
14
+ * ├── .mcp.json
15
+ * ├── .lsp.json
16
+ * ├── monitors/monitors.json
17
+ * ├── bin/<exe>
18
+ * └── settings.json
19
+ *
20
+ * Each component may be declared EXPLICITLY in plugin.json or discovered BY
21
+ * CONVENTION (explicit wins). Every resolved path is checked to stay inside the
22
+ * plugin root — a manifest that points at `../../etc` is rejected, never
23
+ * followed. Pure + `_deps`-injectable so it is fully unit-testable with no real
24
+ * filesystem.
25
+ */
26
+
27
+ import fs from "fs";
28
+ import path from "path";
29
+ import semver from "semver";
30
+
31
+ export const _deps = {
32
+ existsSync: fs.existsSync,
33
+ readFileSync: fs.readFileSync,
34
+ readdirSync: fs.readdirSync,
35
+ statSync: fs.statSync,
36
+ };
37
+
38
+ /** True when `child` resolves to `parent` or a path strictly inside it. */
39
+ export function isWithin(parent, child) {
40
+ const rel = path.relative(path.resolve(parent), path.resolve(child));
41
+ return rel === "" || (!rel.startsWith("..") && !path.isAbsolute(rel));
42
+ }
43
+
44
+ /**
45
+ * Locate the manifest file for a plugin root, preferring the namespaced
46
+ * `.chainlesschain-plugin/plugin.json` over the legacy top-level `plugin.json`.
47
+ * @returns {string|null} absolute manifest path
48
+ */
49
+ export function findManifestPath(root) {
50
+ const preferred = path.join(root, ".chainlesschain-plugin", "plugin.json");
51
+ if (_deps.existsSync(preferred)) return preferred;
52
+ const legacy = path.join(root, "plugin.json");
53
+ if (_deps.existsSync(legacy)) return legacy;
54
+ return null;
55
+ }
56
+
57
+ /**
58
+ * Parse and normalize a plugin at `root`. Never throws — problems are collected
59
+ * in `errors`/`warnings` and `ok` reflects whether it is safe to load.
60
+ *
61
+ * @param {string} root plugin root directory
62
+ * @returns {object} normalized manifest (see module doc)
63
+ */
64
+ export function parsePluginManifest(root) {
65
+ const errors = [];
66
+ const warnings = [];
67
+ const abs = path.resolve(root);
68
+
69
+ const result = {
70
+ ok: false,
71
+ root: abs,
72
+ manifestPath: null,
73
+ scope: null,
74
+ metadata: {},
75
+ components: emptyComponents(),
76
+ errors,
77
+ warnings,
78
+ };
79
+
80
+ if (!_deps.existsSync(abs)) {
81
+ errors.push(`plugin root does not exist: ${abs}`);
82
+ return result;
83
+ }
84
+
85
+ const manifestPath = findManifestPath(abs);
86
+ if (!manifestPath) {
87
+ errors.push(
88
+ "no manifest found (.chainlesschain-plugin/plugin.json or plugin.json)",
89
+ );
90
+ return result;
91
+ }
92
+ result.manifestPath = manifestPath;
93
+
94
+ let manifest;
95
+ try {
96
+ manifest = JSON.parse(_deps.readFileSync(manifestPath, "utf8"));
97
+ } catch (err) {
98
+ errors.push(`manifest is not valid JSON: ${err.message}`);
99
+ return result;
100
+ }
101
+ if (!manifest || typeof manifest !== "object" || Array.isArray(manifest)) {
102
+ errors.push("manifest must be a JSON object");
103
+ return result;
104
+ }
105
+
106
+ // ── metadata ──
107
+ const name = typeof manifest.name === "string" ? manifest.name.trim() : "";
108
+ if (!name) errors.push("manifest.name is required");
109
+ else if (!/^[a-zA-Z0-9._@/-]+$/.test(name)) {
110
+ errors.push(`manifest.name has invalid characters: "${name}"`);
111
+ }
112
+ const version =
113
+ typeof manifest.version === "string" ? manifest.version.trim() : "";
114
+ if (!version) errors.push("manifest.version is required");
115
+ else if (!semver.valid(version)) {
116
+ errors.push(`manifest.version is not valid semver: "${version}"`);
117
+ }
118
+ result.metadata = {
119
+ name,
120
+ version,
121
+ description: strOr(manifest.description, ""),
122
+ author: strOr(manifest.author, ""),
123
+ homepage: strOr(manifest.homepage, ""),
124
+ license: strOr(manifest.license, ""),
125
+ };
126
+
127
+ // A helper that resolves a plugin-relative path safely, recording an error if
128
+ // it escapes the root or is absolute. Returns the absolute path or null.
129
+ const safeResolve = (rel, label) => {
130
+ if (typeof rel !== "string" || rel === "") {
131
+ errors.push(`${label}: path must be a non-empty string`);
132
+ return null;
133
+ }
134
+ if (path.isAbsolute(rel)) {
135
+ errors.push(`${label}: absolute paths are not allowed ("${rel}")`);
136
+ return null;
137
+ }
138
+ const resolved = path.resolve(abs, rel);
139
+ if (!isWithin(abs, resolved)) {
140
+ errors.push(`${label}: path escapes the plugin root ("${rel}")`);
141
+ return null;
142
+ }
143
+ return resolved;
144
+ };
145
+
146
+ const c = result.components;
147
+ c.skills = resolveSkills(abs, manifest, safeResolve, warnings);
148
+ c.agents = resolveAgents(abs, manifest, safeResolve, warnings);
149
+ c.hooks = resolveJsonComponent(abs, manifest, safeResolve, {
150
+ field: "hooks",
151
+ conventionPath: ["hooks", "hooks.json"],
152
+ listKey: "hooks",
153
+ });
154
+ c.mcp = resolveJsonComponent(abs, manifest, safeResolve, {
155
+ field: "mcp",
156
+ conventionPath: [".mcp.json"],
157
+ listKey: "mcpServers",
158
+ });
159
+ c.monitors = resolveJsonComponent(abs, manifest, safeResolve, {
160
+ field: "monitors",
161
+ conventionPath: ["monitors", "monitors.json"],
162
+ listKey: "monitors",
163
+ });
164
+ c.lsp = resolveLsp(abs, manifest, safeResolve, errors, warnings);
165
+ c.bin = resolveBin(abs, manifest, safeResolve, warnings);
166
+ c.settings = resolveSettings(abs, manifest, safeResolve);
167
+
168
+ result.ok = errors.length === 0;
169
+ return result;
170
+ }
171
+
172
+ /** Per-type counts for a parsed manifest (used by validate/list output). */
173
+ export function summarizeComponents(manifest) {
174
+ const c = manifest.components || emptyComponents();
175
+ return {
176
+ skills: c.skills.length,
177
+ agents: c.agents.length,
178
+ hooks: c.hooks ? c.hooks.count || (c.hooks.file ? 1 : 0) : 0,
179
+ mcp: c.mcp ? c.mcp.count || 0 : 0,
180
+ lsp: c.lsp.length,
181
+ monitors: c.monitors ? c.monitors.count || 0 : 0,
182
+ bin: c.bin.length,
183
+ settings: c.settings ? 1 : 0,
184
+ };
185
+ }
186
+
187
+ // ── component resolvers ──────────────────────────────────────────────────
188
+
189
+ function emptyComponents() {
190
+ return {
191
+ skills: [],
192
+ agents: [],
193
+ hooks: null,
194
+ mcp: null,
195
+ lsp: [],
196
+ monitors: null,
197
+ bin: [],
198
+ settings: null,
199
+ };
200
+ }
201
+
202
+ function resolveSkills(root, manifest, safeResolve, warnings) {
203
+ const out = [];
204
+ const seen = new Set();
205
+ const push = (name, rel) => {
206
+ const absPath = safeResolve(rel, `skills["${name}"]`);
207
+ if (!absPath) return;
208
+ if (!_deps.existsSync(absPath)) {
209
+ warnings.push(`skill "${name}" path not found: ${rel}`);
210
+ return;
211
+ }
212
+ if (seen.has(name)) return;
213
+ seen.add(name);
214
+ out.push({ name, path: rel, absPath });
215
+ };
216
+
217
+ if (Array.isArray(manifest.skills)) {
218
+ for (const entry of manifest.skills) {
219
+ if (entry && typeof entry === "object") {
220
+ if (typeof entry.name === "string" && typeof entry.path === "string") {
221
+ push(entry.name, entry.path);
222
+ }
223
+ }
224
+ }
225
+ return out;
226
+ }
227
+
228
+ // Convention: skills/<name>/ (each a skill dir, ideally with SKILL.md).
229
+ const dir = path.join(root, "skills");
230
+ if (dirExists(dir)) {
231
+ for (const name of listDirs(dir)) {
232
+ push(name, path.join("skills", name));
233
+ }
234
+ }
235
+ return out;
236
+ }
237
+
238
+ function resolveAgents(root, manifest, safeResolve, warnings) {
239
+ const out = [];
240
+ const seen = new Set();
241
+ const push = (name, rel) => {
242
+ const absPath = safeResolve(rel, `agents["${name}"]`);
243
+ if (!absPath) return;
244
+ if (!_deps.existsSync(absPath)) {
245
+ warnings.push(`agent "${name}" path not found: ${rel}`);
246
+ return;
247
+ }
248
+ if (seen.has(name)) return;
249
+ seen.add(name);
250
+ out.push({ name, path: rel, absPath });
251
+ };
252
+
253
+ if (Array.isArray(manifest.agents)) {
254
+ for (const entry of manifest.agents) {
255
+ if (entry && typeof entry === "object") {
256
+ if (typeof entry.name === "string" && typeof entry.path === "string") {
257
+ push(entry.name, entry.path);
258
+ }
259
+ }
260
+ }
261
+ return out;
262
+ }
263
+
264
+ const dir = path.join(root, "agents");
265
+ if (dirExists(dir)) {
266
+ for (const file of listFiles(dir, /\.(md|json)$/i)) {
267
+ push(file.replace(/\.(md|json)$/i, ""), path.join("agents", file));
268
+ }
269
+ }
270
+ return out;
271
+ }
272
+
273
+ /**
274
+ * Resolve a JSON-file component (hooks / mcp / monitors). Accepts an inline
275
+ * object in the manifest, an explicit path string, or a convention path.
276
+ */
277
+ function resolveJsonComponent(root, manifest, safeResolve, opts) {
278
+ const { field, conventionPath, listKey } = opts;
279
+ const inline = manifest[field];
280
+
281
+ // Inline object literal in the manifest (no separate file).
282
+ if (
283
+ inline &&
284
+ typeof inline === "object" &&
285
+ !Array.isArray(inline) &&
286
+ !inline.path
287
+ ) {
288
+ return { inline: true, file: null, ...extractList(inline, listKey) };
289
+ }
290
+
291
+ let rel = null;
292
+ if (typeof inline === "string") rel = inline;
293
+ else if (
294
+ inline &&
295
+ typeof inline === "object" &&
296
+ typeof inline.path === "string"
297
+ ) {
298
+ rel = inline.path;
299
+ } else {
300
+ const conv = path.join(root, ...conventionPath);
301
+ if (_deps.existsSync(conv)) rel = path.join(...conventionPath);
302
+ }
303
+ if (!rel) return null;
304
+
305
+ const absPath = safeResolve(rel, field);
306
+ if (!absPath || !_deps.existsSync(absPath)) return null;
307
+ let content = null;
308
+ try {
309
+ content = JSON.parse(_deps.readFileSync(absPath, "utf8"));
310
+ } catch {
311
+ content = null;
312
+ }
313
+ return {
314
+ inline: false,
315
+ file: rel,
316
+ absPath,
317
+ ...extractList(content || {}, listKey),
318
+ };
319
+ }
320
+
321
+ function extractList(obj, listKey) {
322
+ const val = obj && obj[listKey];
323
+ if (Array.isArray(val)) {
324
+ return {
325
+ count: val.length,
326
+ names: val.map((v) => v?.name || v?.id || null).filter(Boolean),
327
+ };
328
+ }
329
+ if (val && typeof val === "object") {
330
+ const names = Object.keys(val);
331
+ return { count: names.length, names };
332
+ }
333
+ return { count: 0, names: [] };
334
+ }
335
+
336
+ function resolveLsp(root, manifest, safeResolve, errors, warnings) {
337
+ let content = manifest.lsp;
338
+ // Convention file `.lsp.json`.
339
+ if (!content) {
340
+ const conv = path.join(root, ".lsp.json");
341
+ if (_deps.existsSync(conv)) {
342
+ try {
343
+ content = JSON.parse(_deps.readFileSync(conv, "utf8"));
344
+ } catch (err) {
345
+ errors.push(`.lsp.json is not valid JSON: ${err.message}`);
346
+ return [];
347
+ }
348
+ }
349
+ }
350
+ if (!content) return [];
351
+
352
+ // Accept either { servers: [...] } or a bare array.
353
+ const servers = Array.isArray(content)
354
+ ? content
355
+ : Array.isArray(content.servers)
356
+ ? content.servers
357
+ : [];
358
+ const out = [];
359
+ for (const s of servers) {
360
+ if (!s || typeof s !== "object") continue;
361
+ if (typeof s.languageId !== "string" || typeof s.command !== "string") {
362
+ warnings.push("lsp server entry missing languageId/command — skipped");
363
+ continue;
364
+ }
365
+ out.push({
366
+ languageId: s.languageId,
367
+ command: s.command,
368
+ args: Array.isArray(s.args) ? s.args.map(String) : [],
369
+ extensions: Array.isArray(s.extensions) ? s.extensions.map(String) : [],
370
+ id: typeof s.id === "string" ? s.id : s.command,
371
+ });
372
+ }
373
+ return out;
374
+ }
375
+
376
+ function resolveBin(root, manifest, safeResolve, warnings) {
377
+ const out = [];
378
+ const seen = new Set();
379
+ const push = (name, rel) => {
380
+ const absPath = safeResolve(rel, `bin["${name}"]`);
381
+ if (!absPath) return;
382
+ if (!_deps.existsSync(absPath)) {
383
+ warnings.push(`bin "${name}" path not found: ${rel}`);
384
+ return;
385
+ }
386
+ if (seen.has(name)) return;
387
+ seen.add(name);
388
+ out.push({ name, path: rel, absPath });
389
+ };
390
+
391
+ if (
392
+ manifest.bin &&
393
+ typeof manifest.bin === "object" &&
394
+ !Array.isArray(manifest.bin)
395
+ ) {
396
+ for (const [name, rel] of Object.entries(manifest.bin)) {
397
+ if (typeof rel === "string") push(name, rel);
398
+ }
399
+ return out;
400
+ }
401
+
402
+ const dir = path.join(root, "bin");
403
+ if (dirExists(dir)) {
404
+ for (const file of listFiles(dir, null)) {
405
+ push(file, path.join("bin", file));
406
+ }
407
+ }
408
+ return out;
409
+ }
410
+
411
+ function resolveSettings(root, manifest, safeResolve) {
412
+ let rel = null;
413
+ if (typeof manifest.settings === "string") rel = manifest.settings;
414
+ else {
415
+ const conv = path.join(root, "settings.json");
416
+ if (_deps.existsSync(conv)) rel = "settings.json";
417
+ }
418
+ if (!rel) return null;
419
+ const absPath = safeResolve(rel, "settings");
420
+ if (!absPath || !_deps.existsSync(absPath)) return null;
421
+ return { file: rel, absPath };
422
+ }
423
+
424
+ // ── small fs helpers (all through _deps) ─────────────────────────────────
425
+
426
+ function strOr(v, fallback) {
427
+ return typeof v === "string" ? v : fallback;
428
+ }
429
+
430
+ function dirExists(dir) {
431
+ try {
432
+ return _deps.existsSync(dir) && _deps.statSync(dir).isDirectory();
433
+ } catch {
434
+ return false;
435
+ }
436
+ }
437
+
438
+ function listDirs(dir) {
439
+ try {
440
+ return _deps
441
+ .readdirSync(dir, { withFileTypes: true })
442
+ .filter((e) => e.isDirectory())
443
+ .map((e) => e.name);
444
+ } catch {
445
+ return [];
446
+ }
447
+ }
448
+
449
+ function listFiles(dir, pattern) {
450
+ try {
451
+ return _deps
452
+ .readdirSync(dir, { withFileTypes: true })
453
+ .filter((e) => e.isFile() && (!pattern || pattern.test(e.name)))
454
+ .map((e) => e.name);
455
+ } catch {
456
+ return [];
457
+ }
458
+ }
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Collect installed plugins' `.mcp.json` servers so a plugin's MCP component
3
+ * reaches the agent's tool surface (Phase 3.3g — plugin MCP → agent chain).
4
+ *
5
+ * A plugin ships MCP servers in the same shape as a project `.mcp.json`: a
6
+ * top-level `mcpServers` (or `servers`) map of name → `{command,args,env,url,…}`.
7
+ * Those are folded into the agent's combined MCP client alongside the user's
8
+ * registered + project servers.
9
+ *
10
+ * SECURITY: an MCP stdio server spawns a command, so a plugin's `.mcp.json`
11
+ * carries the same RCE weight as its hooks/LSP components. Only TRUSTED plugins
12
+ * contribute (user/local scope auto-trusted; project scope must be
13
+ * `cc plugin trust`-ed at its exact version) — an untrusted project plugin from
14
+ * a cloned repo can NOT get a server spawned the moment the agent starts.
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 `{ mcpServers: {...} }`, `{ servers: {...} }`, or a bare map. */
24
+ function normalizeServerMap(parsed) {
25
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
26
+ const block = parsed.mcpServers || parsed.servers || parsed;
27
+ if (!block || typeof block !== "object" || Array.isArray(block)) return {};
28
+ return block;
29
+ }
30
+
31
+ /**
32
+ * Merge every trusted, installed plugin's `.mcp.json` servers into one map,
33
+ * keyed by server name. A later plugin (in discovery precedence) wins on a name
34
+ * clash; callers merging this into their own servers keep their own on a clash.
35
+ *
36
+ * @param {object} [opts] { cwd, scopes }
37
+ * @returns {{ servers: Record<string,object>, sources: string[] }}
38
+ */
39
+ export function collectPluginMcpServers(opts = {}) {
40
+ let plugins = [];
41
+ try {
42
+ plugins = discoverPlugins({ cwd: opts.cwd, scopes: opts.scopes });
43
+ } catch {
44
+ return { servers: {}, sources: [] };
45
+ }
46
+ // An MCP stdio server spawns a command — gate it behind trust so a cloned
47
+ // repo's project plugin can't get a server launched the moment cc starts.
48
+ const { trusted, skipped } = partitionByTrust(plugins);
49
+ warnUntrustedOnce(
50
+ skipped.filter((p) => p.manifest?.components?.mcp).map((p) => p.name),
51
+ "mcp",
52
+ );
53
+ const servers = {};
54
+ const sources = [];
55
+ for (const p of trusted) {
56
+ if (!p.manifest || p.manifest.ok !== true) continue;
57
+ const m = p.manifest.components?.mcp;
58
+ if (!m) continue;
59
+ let parsed = null;
60
+ if (m.absPath) {
61
+ try {
62
+ parsed = JSON.parse(_deps.readFileSync(m.absPath, "utf8"));
63
+ } catch {
64
+ continue;
65
+ }
66
+ } else if (m.inline) {
67
+ // Inline MCP declared directly in the manifest — re-read the raw manifest
68
+ // so we get the server bodies (the normalized component keeps only counts).
69
+ try {
70
+ parsed = JSON.parse(
71
+ _deps.readFileSync(p.manifest.manifestPath, "utf8"),
72
+ );
73
+ parsed = parsed && typeof parsed === "object" ? parsed.mcp : null;
74
+ } catch {
75
+ continue;
76
+ }
77
+ }
78
+ const map = normalizeServerMap(parsed);
79
+ let added = 0;
80
+ for (const [name, cfg] of Object.entries(map)) {
81
+ if (!cfg || typeof cfg !== "object") continue;
82
+ if (name in servers) continue; // first plugin wins on a clash
83
+ servers[name] = cfg;
84
+ added++;
85
+ }
86
+ if (added > 0 && m.absPath) sources.push(m.absPath);
87
+ }
88
+ return { servers, sources };
89
+ }
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Collect installed plugins' background-monitor declarations (Phase 3.3i /
3
+ * Phase 6 down payment — plugin Monitor component reaches a real supervisor).
4
+ *
5
+ * A plugin ships monitors in `monitors/monitors.json`:
6
+ * { "monitors": [
7
+ * { "name": "tests", "command": "npm", "args": ["test"],
8
+ * "mode": "interval", "intervalMs": 60000 },
9
+ * { "name": "logtail", "command": "tail", "args": ["-f","app.log"],
10
+ * "mode": "longRunning" }
11
+ * ] }
12
+ * Each monitor is a background process the supervisor spawns to watch logs /
13
+ * files / external state; its output can be injected into the next agent turn.
14
+ *
15
+ * SECURITY: a monitor spawns a command, so — exactly like hooks/LSP/MCP — only
16
+ * TRUSTED plugins contribute (user/local scope auto-trusted; project scope must
17
+ * be `cc plugin trust`-ed at its exact version). An untrusted cloned-repo plugin
18
+ * can NOT get a background process launched.
19
+ */
20
+
21
+ import fs from "fs";
22
+ import { discoverPlugins } from "./scopes.js";
23
+ import { partitionByTrust, warnUntrustedOnce } from "./trust.js";
24
+
25
+ export const _deps = { readFileSync: fs.readFileSync };
26
+
27
+ const VALID_MODES = new Set(["interval", "longRunning"]);
28
+
29
+ /** Normalize one raw monitor entry into a validated descriptor, or null. */
30
+ function normalizeMonitor(plugin, raw) {
31
+ if (!raw || typeof raw !== "object") return null;
32
+ if (typeof raw.name !== "string" || raw.name === "") return null;
33
+ if (typeof raw.command !== "string" || raw.command === "") return null;
34
+ const mode = VALID_MODES.has(raw.mode) ? raw.mode : "interval";
35
+ const args = Array.isArray(raw.args) ? raw.args.map((a) => String(a)) : [];
36
+ const intervalMs =
37
+ Number.isFinite(raw.intervalMs) && raw.intervalMs > 0
38
+ ? Math.floor(raw.intervalMs)
39
+ : null;
40
+ const env =
41
+ raw.env && typeof raw.env === "object" && !Array.isArray(raw.env)
42
+ ? raw.env
43
+ : null;
44
+ return {
45
+ plugin: plugin.name,
46
+ scope: plugin.scope,
47
+ version: plugin.version,
48
+ // Namespaced so two plugins' "tests" monitors never collide.
49
+ id: `${plugin.name}:${raw.name}`,
50
+ name: raw.name,
51
+ command: raw.command,
52
+ args,
53
+ mode,
54
+ intervalMs,
55
+ env,
56
+ cwd: plugin.root,
57
+ };
58
+ }
59
+
60
+ /**
61
+ * Flatten every trusted, installed plugin's monitor declarations.
62
+ * @param {object} [opts] { cwd, scopes }
63
+ * @returns {Array<object>} validated monitor descriptors
64
+ */
65
+ export function collectPluginMonitors(opts = {}) {
66
+ let plugins = [];
67
+ try {
68
+ plugins = discoverPlugins({ cwd: opts.cwd, scopes: opts.scopes });
69
+ } catch {
70
+ return [];
71
+ }
72
+ // A monitor spawns a command — gate it behind trust.
73
+ const { trusted, skipped } = partitionByTrust(plugins);
74
+ warnUntrustedOnce(
75
+ skipped.filter((p) => p.manifest?.components?.monitors).map((p) => p.name),
76
+ "monitors",
77
+ );
78
+ const out = [];
79
+ for (const p of trusted) {
80
+ if (!p.manifest || p.manifest.ok !== true) continue;
81
+ const m = p.manifest.components?.monitors;
82
+ if (!m || !m.absPath) continue;
83
+ let parsed;
84
+ try {
85
+ parsed = JSON.parse(_deps.readFileSync(m.absPath, "utf8"));
86
+ } catch {
87
+ continue;
88
+ }
89
+ const list = Array.isArray(parsed?.monitors)
90
+ ? parsed.monitors
91
+ : Array.isArray(parsed)
92
+ ? parsed
93
+ : [];
94
+ for (const raw of list) {
95
+ const desc = normalizeMonitor(p, raw);
96
+ if (desc) out.push(desc);
97
+ }
98
+ }
99
+ return out;
100
+ }