chainlesschain 0.162.147 → 0.162.149

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 (257) hide show
  1. package/README.md +1 -1
  2. package/package.json +2 -2
  3. package/src/assets/web-panel/.build-hash +1 -1
  4. package/src/assets/web-panel/assets/{AIOps-DywJ7xTv.js → AIOps-BJif14yR.js} +1 -1
  5. package/src/assets/web-panel/assets/{ActionButton-BTlqcY-q.js → ActionButton-CXek6gJY.js} +1 -1
  6. package/src/assets/web-panel/assets/{Analytics-FdG1Mvwy.js → Analytics-BgQhdAJi.js} +3 -3
  7. package/src/assets/web-panel/assets/{AppLayout-CVsnbvN1.js → AppLayout-DTYl5NtR.js} +5 -5
  8. package/src/assets/web-panel/assets/{Audit-ITdpJ7vR.js → Audit-BzATQAeR.js} +1 -1
  9. package/src/assets/web-panel/assets/{Backup-BfXqnXo1.js → Backup-BzdPEQhL.js} +1 -1
  10. package/src/assets/web-panel/assets/{BaseInput-C09ip3_E.js → BaseInput-BM0KVh8E.js} +1 -1
  11. package/src/assets/web-panel/assets/{Chat-qdkhB42l.js → Chat-D7fHXHkz.js} +6 -6
  12. package/src/assets/web-panel/assets/{ChatBubbleRenderer-D2KfETZD.js → ChatBubbleRenderer-Wm34RR-b.js} +1 -1
  13. package/src/assets/web-panel/assets/{Checkbox-j6WZCuff.js → Checkbox-CAiSQ9vO.js} +1 -1
  14. package/src/assets/web-panel/assets/{Codegen-CGZ-K3uK.js → Codegen-Df40CrEe.js} +1 -1
  15. package/src/assets/web-panel/assets/{Col-CIlPOAu6.js → Col-DIT2fNFU.js} +1 -1
  16. package/src/assets/web-panel/assets/{Community-sY-i-hic.js → Community-CSTIbW2k.js} +1 -1
  17. package/src/assets/web-panel/assets/{Compact-DcoEfyL8.js → Compact-DtqXZZUi.js} +1 -1
  18. package/src/assets/web-panel/assets/Compliance-CUtzw6o7.js +1 -0
  19. package/src/assets/web-panel/assets/{Cowork-DLY_fkLv.js → Cowork-CezmlnmU.js} +3 -3
  20. package/src/assets/web-panel/assets/{Cron-D049pZBC.js → Cron-P4BITarg.js} +2 -2
  21. package/src/assets/web-panel/assets/{Crosschain-DCXdE8M9.js → Crosschain-BRRiYwvq.js} +1 -1
  22. package/src/assets/web-panel/assets/{DID-JCvPZtjW.js → DID-L5ijB9i4.js} +2 -2
  23. package/src/assets/web-panel/assets/{Dashboard-Cg2xu3iE.js → Dashboard-CFxro4ob.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dropdown-DjJLjbLh.js → Dropdown-BmAFCQ71.js} +1 -1
  25. package/src/assets/web-panel/assets/{EmailListRenderer-DugNcSLR.js → EmailListRenderer-DJBCEuon.js} +1 -1
  26. package/src/assets/web-panel/assets/{FamilyGuardDashboard-J6Nb-E30.js → FamilyGuardDashboard-z4oLq6eT.js} +1 -1
  27. package/src/assets/web-panel/assets/{Federation-CQ3Ttpbl.js → Federation-DsVCpHMF.js} +1 -1
  28. package/src/assets/web-panel/assets/{FormItemContext-Cz0NKag4.js → FormItemContext-DP3bP5th.js} +1 -1
  29. package/src/assets/web-panel/assets/{GenericCardRenderer-NYcMP6iz.js → GenericCardRenderer-BAXP2Gc6.js} +1 -1
  30. package/src/assets/web-panel/assets/{Git-B4hYN18N.js → Git-I3g_bAw9.js} +2 -2
  31. package/src/assets/web-panel/assets/{Governance-DOQPCcC0.js → Governance-jHS5-ioS.js} +1 -1
  32. package/src/assets/web-panel/assets/{Inference-HtLF746W.js → Inference-CPL7sfx9.js} +1 -1
  33. package/src/assets/web-panel/assets/{KnowledgeGraph-BXrk8rMm.js → KnowledgeGraph-Jf236h4C.js} +1 -1
  34. package/src/assets/web-panel/assets/{Logs-DS0JnD3-.js → Logs-Cm2tcSKg.js} +2 -2
  35. package/src/assets/web-panel/assets/{Marketplace-Cqnjihrz.js → Marketplace-CZK82rhi.js} +1 -1
  36. package/src/assets/web-panel/assets/{McpTools-Cx3Psk-U.js → McpTools-CZCeji7a.js} +5 -5
  37. package/src/assets/web-panel/assets/{Memory-BjyysPtj.js → Memory-3l2KVS9k.js} +2 -2
  38. package/src/assets/web-panel/assets/MobileBridge-D3Arxfeg.css +1 -0
  39. package/src/assets/web-panel/assets/MobileBridge-VYdpoLh6.js +1 -0
  40. package/src/assets/web-panel/assets/{MobileProjects-Xwf-fdOQ.js → MobileProjects-CiB9cmm1.js} +1 -1
  41. package/src/assets/web-panel/assets/{Mtc-Djkql5m5.js → Mtc-wCFZbBuL.js} +2 -2
  42. package/src/assets/web-panel/assets/{MtcAudit-D2BAZlu0.js → MtcAudit-1a3THIyG.js} +2 -2
  43. package/src/assets/web-panel/assets/{Multisig-ByqP1ZzH.js → Multisig-DMzLB2hG.js} +3 -3
  44. package/src/assets/web-panel/assets/{NLProgramming-C_kn0nE2.js → NLProgramming-D9wZbf6l.js} +1 -1
  45. package/src/assets/web-panel/assets/{Notes-7l7eXHPq.js → Notes-hrFe2ZM-.js} +3 -3
  46. package/src/assets/web-panel/assets/{NotificationSettings-BrCDoitw.js → NotificationSettings-CHGX5Jwm.js} +1 -1
  47. package/src/assets/web-panel/assets/OrderTableRenderer-CRIFE2Tj.js +1 -0
  48. package/src/assets/web-panel/assets/{Organization-DdoNAxsM.js → Organization-By7FkhtY.js} +4 -4
  49. package/src/assets/web-panel/assets/{Overflow-Bw7R6dE3.js → Overflow--khGSzJn.js} +1 -1
  50. package/src/assets/web-panel/assets/{OverrideContext-C2r4vyBb.js → OverrideContext-BlgL9440.js} +1 -1
  51. package/src/assets/web-panel/assets/{P2P-DJNtBugA.js → P2P-CAG9dH35.js} +2 -2
  52. package/src/assets/web-panel/assets/{PdhVaultBrowser-Dwhd5_ue.js → PdhVaultBrowser-B3SQZmK9.js} +3 -3
  53. package/src/assets/web-panel/assets/{Permissions-BYoSfhPR.js → Permissions-D35ec6JA.js} +4 -4
  54. package/src/assets/web-panel/assets/{PersonalDataHub-aYCYJbnH.js → PersonalDataHub-CxBF7hW_.js} +2 -2
  55. package/src/assets/web-panel/assets/{Pipeline-DJp6CprF.js → Pipeline-s6EtOO1s.js} +1 -1
  56. package/src/assets/web-panel/assets/{Privacy-Cq9HZweR.js → Privacy-BbJYmWmO.js} +1 -1
  57. package/src/assets/web-panel/assets/{ProjectInit-CmF0HsSt.js → ProjectInit-VGQq1jMT.js} +2 -2
  58. package/src/assets/web-panel/assets/{ProjectSettings-P8V5Aea2.js → ProjectSettings-B1ew3Teh.js} +2 -2
  59. package/src/assets/web-panel/assets/Projects-CGcNIs_g.js +1 -0
  60. package/src/assets/web-panel/assets/{Providers-D589v0q2.js → Providers-mrO47FIK.js} +1 -1
  61. package/src/assets/web-panel/assets/QrScannerModal-IJF2mHyw.js +1 -0
  62. package/src/assets/web-panel/assets/{MobileBridge-zJpPuf4E.css → QrScannerModal-NwAHNfiJ.css} +1 -1
  63. package/src/assets/web-panel/assets/{QuickAsk-lvRV2osB.js → QuickAsk-CU0wN_Z0.js} +1 -1
  64. package/src/assets/web-panel/assets/{Recommend-sb84MTpY.js → Recommend-DhN37R6G.js} +1 -1
  65. package/src/assets/web-panel/assets/RemoteSession-D_xOX_hu.js +4 -0
  66. package/src/assets/web-panel/assets/{Reputation-d9Y3vy-W.js → Reputation-D_Ssv7uH.js} +1 -1
  67. package/src/assets/web-panel/assets/{Row-DMdhLUTp.js → Row-Kx5dKxX7.js} +1 -1
  68. package/src/assets/web-panel/assets/{RssFeed-OL-SMDkz.js → RssFeed-BlGwqZkY.js} +2 -2
  69. package/src/assets/web-panel/assets/{Search-BjStLKq1.js → Search-hLFQzxpb.js} +1 -1
  70. package/src/assets/web-panel/assets/{Security-MeI411qr.js → Security-DMlvsVt4.js} +2 -2
  71. package/src/assets/web-panel/assets/{Services-UajosuhT.js → Services-Bd0Qsj2m.js} +2 -2
  72. package/src/assets/web-panel/assets/{Skeleton-CGpG-QJ1.js → Skeleton-DFclq9X3.js} +1 -1
  73. package/src/assets/web-panel/assets/{Skills-C6P2RPY-.js → Skills-BNtln2qY.js} +1 -1
  74. package/src/assets/web-panel/assets/{Sla-B_fPprgw.js → Sla-Dch5H19G.js} +1 -1
  75. package/src/assets/web-panel/assets/{SpeechSettings-CqxLjSlQ.js → SpeechSettings-2UfQcU1g.js} +1 -1
  76. package/src/assets/web-panel/assets/{SyncSettings-DixSfFOQ.js → SyncSettings-CD9YQr4i.js} +2 -2
  77. package/src/assets/web-panel/assets/{Tasks-PavzPBxc.js → Tasks-BNu-7MzI.js} +1 -1
  78. package/src/assets/web-panel/assets/{Templates-BYdGRnfX.js → Templates-D1n9CaIR.js} +1 -1
  79. package/src/assets/web-panel/assets/{Tenant-BQLgnarD.js → Tenant-DenL3iBW.js} +1 -1
  80. package/src/assets/web-panel/assets/Terminal-ZzU0Io1Y.js +3 -0
  81. package/src/assets/web-panel/assets/{TimelineRenderer-Bv7uZRM7.js → TimelineRenderer-D87IfukO.js} +1 -1
  82. package/src/assets/web-panel/assets/{Tokens-DxhgszRJ.js → Tokens-BkiZc8E3.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trigger-nQYHayuc.js → Trigger-BNRSytGN.js} +1 -1
  84. package/src/assets/web-panel/assets/{Trust-CvqZDuZ4.js → Trust-Bwbd4X2m.js} +1 -1
  85. package/src/assets/web-panel/assets/{UkeySign-DaR8GV2I.js → UkeySign-B8O2bs0o.js} +1 -1
  86. package/src/assets/web-panel/assets/{VideoEditing-C6Mpsokw.js → VideoEditing-C2fL8zmH.js} +1 -1
  87. package/src/assets/web-panel/assets/{Wallet-B57VRrWc.js → Wallet-BORYDdE1.js} +4 -4
  88. package/src/assets/web-panel/assets/{WebAuthn-BbtEEtpq.js → WebAuthn-C0V5S2FM.js} +4 -4
  89. package/src/assets/web-panel/assets/{WorkflowEditor-C5LwvKmH.js → WorkflowEditor-2dR0fcHL.js} +1 -1
  90. package/src/assets/web-panel/assets/{chat-MzuPR5jh.js → chat-BmuAFAn8.js} +1 -1
  91. package/src/assets/web-panel/assets/{collapseMotion-mxzzcDsg.js → collapseMotion-DVfhbsdP.js} +1 -1
  92. package/src/assets/web-panel/assets/{colors-HyW8mi_y.js → colors-CN3smMcK.js} +1 -1
  93. package/src/assets/web-panel/assets/{compact-item-DvUSzWAp.js → compact-item-DCnxb4kW.js} +1 -1
  94. package/src/assets/web-panel/assets/{createContext-4MppZl7X.js → createContext-vlR43pHn.js} +1 -1
  95. package/src/assets/web-panel/assets/devWarning-DxwmsL4j.js +1 -0
  96. package/src/assets/web-panel/assets/{echarts-jxgIOFUZ.js → echarts-CL0F2SnX.js} +1 -1
  97. package/src/assets/web-panel/assets/{hasIn-D9q3CJ-u.js → hasIn-D04tHYFd.js} +1 -1
  98. package/src/assets/web-panel/assets/{icons-DP3uiYxy.js → icons-BsDmGpcT.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-C9I5MuJ0.js → index-0DnaZGkC.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-Caqtu6Et.js → index-430S68MN.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-eOQO6KnV.js → index-B78xL3s2.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-Ci6adKh8.js → index-BTPEZTk1.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-CifKUNtV.js → index-BXRg8GFQ.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-D7TDMMfu.js → index-BasvsWDM.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-DNYqw0MO.js → index-BeGDEXFs.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-m0b6Fj9q.js → index-BqhASEL4.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-BF2JsbiX.js → index-BudvKQfG.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-DFqvWeGc.js → index-C-6NO5il.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-SDblbKj6.js → index-C5Sxb1sE.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-UUMCA2Sq.js → index-CP9m9Ggr.js} +4 -4
  111. package/src/assets/web-panel/assets/{index--Bm6OqmU.js → index-CTOCnIQ7.js} +1 -1
  112. package/src/assets/web-panel/assets/index-Cg2ldRfU.js +1 -0
  113. package/src/assets/web-panel/assets/{index-Dv7ffI2g.js → index-ClhAHDK3.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-BcunsBIx.js → index-CnXebZLL.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-CvAqCAo9.js → index-CngCC8hC.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-DcMkjb92.js → index-Cr-A0FYJ.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-BFGfC5RS.js → index-CsAsCPJ6.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-DDZ6fP5Z.js → index-D28DeAAB.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-CgIfXOD9.js → index-D5LZVZ0L.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-DmZ6-suL.js → index-D65_XseV.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-Cs-RKRUM.js → index-D8vwp4qp.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-B994UQfE.js → index-DDwLgQY9.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-Btz8pU68.js → index-DIpY0qM5.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-B5E4DhVc.js → index-DTWg-18U.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-D2jrnaq3.js → index-DTtRscUa.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-BmCo2Xdp.js → index-DYAtmqiv.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-Zvtru2oE.js → index-D_n8_vfI.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-CLAZs1Vd.js → index-DbADHwhr.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-CucRo4Vz.js → index-DbVsQBOH.js} +1 -1
  130. package/src/assets/web-panel/assets/index-Dwzo-dtJ.js +1 -0
  131. package/src/assets/web-panel/assets/{index-C0DiL97c.js → index-HhNjnCfe.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-Bl-E4W4q.js → index-ToUh2b1-.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-ryFLxB1p.js → index-TslMTwNy.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-BGQtFso0.js → index-_FIkN3jd.js} +1 -1
  135. package/src/assets/web-panel/assets/{index-zLwYpvX0.js → index-hpvvtAZ3.js} +1 -1
  136. package/src/assets/web-panel/assets/{index-Dvg5xYuP.js → index-jzR7Ujuw.js} +1 -1
  137. package/src/assets/web-panel/assets/{index-xvUVuFnA.js → index-ljuBiQW9.js} +1 -1
  138. package/src/assets/web-panel/assets/{initDefaultProps-CC--PMsC.js → initDefaultProps-C3wUb4je.js} +1 -1
  139. package/src/assets/web-panel/assets/{motion-DdrBjRF1.js → motion-D-jYFUNA.js} +1 -1
  140. package/src/assets/web-panel/assets/{move-D712Gwl2.js → move-tqb8nwJ2.js} +1 -1
  141. package/src/assets/web-panel/assets/{mtc-parser-39y-keKO.js → mtc-parser-DSOjMJMz.js} +1 -1
  142. package/src/assets/web-panel/assets/{omit-6Y51gDB9.js → omit-CJ7VimIW.js} +1 -1
  143. package/src/assets/web-panel/assets/{pickAttrs-Cy6EHbq9.js → pickAttrs-qXiG1iT3.js} +1 -1
  144. package/src/assets/web-panel/assets/{placementArrow-BYxdAm0p.js → placementArrow-CkGBcy1Z.js} +1 -1
  145. package/src/assets/web-panel/assets/{responsiveObserve-C9R6q_cr.js → responsiveObserve-D3WvTlLO.js} +1 -1
  146. package/src/assets/web-panel/assets/{slide-CXUJlilB.js → slide-BEE2ftge.js} +1 -1
  147. package/src/assets/web-panel/assets/{statusUtils-DOtrOeql.js → statusUtils-CsfBpxiG.js} +1 -1
  148. package/src/assets/web-panel/assets/{styleChecker-D5r39o92.js → styleChecker-xPrIiJPI.js} +1 -1
  149. package/src/assets/web-panel/assets/useFlexGapSupport-C5Yd-SCR.js +1 -0
  150. package/src/assets/web-panel/assets/{useFs-BkrT-Zbc.js → useFs-D_MDS8HI.js} +1 -1
  151. package/src/assets/web-panel/assets/{useMergedState-Cl2q1fes.js → useMergedState-Dc9sO2d7.js} +1 -1
  152. package/src/assets/web-panel/assets/{usePersonalDataHub-BwnnnZjU.js → usePersonalDataHub-BqJh-usA.js} +1 -1
  153. package/src/assets/web-panel/assets/{useRefs-DD9q4mOT.js → useRefs-CAeFRzPf.js} +1 -1
  154. package/src/assets/web-panel/assets/{useState-BK4hy8Ma.js → useState-LwExUYDO.js} +1 -1
  155. package/src/assets/web-panel/assets/{vendor-BvqAck49.js → vendor-BMxUs6UX.js} +16 -16
  156. package/src/assets/web-panel/assets/{vnode-SU-N4pum.js → vnode-chm_p-gz.js} +1 -1
  157. package/src/assets/web-panel/assets/{zoom-DHScfpTP.js → zoom-3-YDNz0Z.js} +1 -1
  158. package/src/assets/web-panel/index.html +3 -3
  159. package/src/assets/web-panel/remote-session-sw.js +43 -0
  160. package/src/command-manifest.json +22 -1
  161. package/src/commands/agent.js +44 -5
  162. package/src/commands/codeintel.js +252 -0
  163. package/src/commands/eval.js +248 -0
  164. package/src/commands/plugin.js +354 -0
  165. package/src/commands/serve.js +10 -0
  166. package/src/commands/team.js +456 -0
  167. package/src/gateways/remote-session-relay.js +160 -0
  168. package/src/gateways/ws/message-dispatcher.js +77 -2
  169. package/src/gateways/ws/remote-session-protocol.js +466 -0
  170. package/src/gateways/ws/ws-server.js +299 -0
  171. package/src/harness/golden-transcript.js +65 -0
  172. package/src/harness/mcp-client.js +6 -2
  173. package/src/harness/prompt-compressor.js +27 -1
  174. package/src/harness/remote-command-ledger.js +158 -0
  175. package/src/harness/remote-session-audit-sink.js +132 -0
  176. package/src/harness/remote-session-audit.js +110 -0
  177. package/src/harness/remote-session-crypto.js +217 -0
  178. package/src/harness/remote-session-push-apns.js +246 -0
  179. package/src/harness/remote-session-push-errors.js +15 -0
  180. package/src/harness/remote-session-push-fcm.js +238 -0
  181. package/src/harness/remote-session-push-huawei.js +174 -0
  182. package/src/harness/remote-session-push-oppo.js +171 -0
  183. package/src/harness/remote-session-push-senders.js +42 -0
  184. package/src/harness/remote-session-push-vivo.js +179 -0
  185. package/src/harness/remote-session-push-web.js +299 -0
  186. package/src/harness/remote-session-push-xiaomi.js +99 -0
  187. package/src/harness/remote-session-push.js +104 -0
  188. package/src/harness/remote-session-registry.js +420 -0
  189. package/src/index.js +6 -0
  190. package/src/lib/agent-core.js +2 -0
  191. package/src/lib/agent-sandbox.js +161 -5
  192. package/src/lib/agent-team/task-lease.js +434 -0
  193. package/src/lib/agent-team/team-budget.js +165 -0
  194. package/src/lib/agent-team/team-mailbox.js +106 -0
  195. package/src/lib/agent-team/team-runner.js +266 -0
  196. package/src/lib/agent-team/team-worktree.js +204 -0
  197. package/src/lib/agents.js +18 -0
  198. package/src/lib/async-hook-supervisor.cjs +305 -0
  199. package/src/lib/did-manager.js +6 -4
  200. package/src/lib/eval/runner.js +163 -0
  201. package/src/lib/eval/tasks.js +456 -0
  202. package/src/lib/eval/trend.js +185 -0
  203. package/src/lib/lsp/__tests__/code-intelligence.integration.test.js +129 -0
  204. package/src/lib/lsp/__tests__/code-intelligence.test.js +228 -0
  205. package/src/lib/lsp/__tests__/jsonrpc-stream.test.js +104 -0
  206. package/src/lib/lsp/__tests__/lsp-client.test.js +258 -0
  207. package/src/lib/lsp/__tests__/lsp-manager.test.js +264 -0
  208. package/src/lib/lsp/__tests__/lsp-server-registry.test.js +128 -0
  209. package/src/lib/lsp/code-intelligence.js +356 -0
  210. package/src/lib/lsp/jsonrpc-stream.js +139 -0
  211. package/src/lib/lsp/lsp-client.js +318 -0
  212. package/src/lib/lsp/lsp-manager.js +323 -0
  213. package/src/lib/lsp/lsp-server-registry.js +196 -0
  214. package/src/lib/mcp-oauth.js +23 -6
  215. package/src/lib/plugin-monitor-supervisor.js +238 -0
  216. package/src/lib/plugin-runtime/agents.js +51 -0
  217. package/src/lib/plugin-runtime/bin.js +100 -0
  218. package/src/lib/plugin-runtime/hooks.js +100 -0
  219. package/src/lib/plugin-runtime/install.js +388 -0
  220. package/src/lib/plugin-runtime/lsp.js +75 -0
  221. package/src/lib/plugin-runtime/manifest.js +458 -0
  222. package/src/lib/plugin-runtime/mcp.js +89 -0
  223. package/src/lib/plugin-runtime/monitors.js +100 -0
  224. package/src/lib/plugin-runtime/policy.js +144 -0
  225. package/src/lib/plugin-runtime/reload.js +79 -0
  226. package/src/lib/plugin-runtime/scopes.js +197 -0
  227. package/src/lib/plugin-runtime/settings.js +119 -0
  228. package/src/lib/plugin-runtime/signature.js +107 -0
  229. package/src/lib/plugin-runtime/skills.js +43 -0
  230. package/src/lib/plugin-runtime/trust.js +140 -0
  231. package/src/lib/sandbox-egress-proxy.js +162 -0
  232. package/src/lib/sandbox-network-policy.js +134 -0
  233. package/src/lib/sandbox-v2.js +10 -4
  234. package/src/lib/session-manager.js +7 -3
  235. package/src/lib/settings-hook-events.cjs +78 -6
  236. package/src/lib/settings-hooks.cjs +29 -3
  237. package/src/lib/settings-loader.cjs +35 -1
  238. package/src/lib/skill-loader.js +18 -0
  239. package/src/lib/telemetry/span-recorder.js +237 -0
  240. package/src/repl/agent-repl.js +400 -4
  241. package/src/runtime/agent-core.js +546 -52
  242. package/src/runtime/agent-runtime.js +8 -13
  243. package/src/runtime/coding-agent-contract-shared.cjs +82 -8
  244. package/src/runtime/coding-agent-policy.cjs +32 -7
  245. package/src/runtime/fallback-model.js +134 -7
  246. package/src/runtime/headless-runner.js +353 -108
  247. package/src/runtime/mcp-config.js +46 -0
  248. package/src/runtime/policies/agent-policy.js +2 -0
  249. package/src/assets/web-panel/assets/Compliance-T8EtTecW.js +0 -1
  250. package/src/assets/web-panel/assets/MobileBridge-CYaITZ7w.js +0 -1
  251. package/src/assets/web-panel/assets/OrderTableRenderer-CmtqIdwr.js +0 -1
  252. package/src/assets/web-panel/assets/Projects-DPd5-lNS.js +0 -1
  253. package/src/assets/web-panel/assets/Terminal-BzOHpq-B.js +0 -3
  254. package/src/assets/web-panel/assets/devWarning-6YJJMjSH.js +0 -1
  255. package/src/assets/web-panel/assets/index-D_oeGLr6.js +0 -1
  256. package/src/assets/web-panel/assets/index-Qa57YG19.js +0 -1
  257. package/src/assets/web-panel/assets/useFlexGapSupport-DfAD5U4Z.js +0 -1
@@ -0,0 +1,248 @@
1
+ /**
2
+ * `cc eval` — reliability eval harness (Phase 7). Runs a suite of self-checking
3
+ * coding tasks against the real agent and reports the task-success rate.
4
+ *
5
+ * Each task gets a fresh temp workspace; the agent is invoked headlessly
6
+ * (`cc agent -p` in that cwd with acceptEdits so it can write files) and the
7
+ * task's objective check() decides pass/fail. `--dry-run` swaps in a no-op agent
8
+ * so the harness + report can be exercised without a model.
9
+ */
10
+
11
+ import fs from "fs";
12
+ import path from "path";
13
+ import { fileURLToPath } from "url";
14
+ import { spawn } from "child_process";
15
+ import { runEvalSuite } from "../lib/eval/runner.js";
16
+ import { getSuite } from "../lib/eval/tasks.js";
17
+ import {
18
+ TelemetryRecorder,
19
+ formatTelemetry,
20
+ } from "../lib/telemetry/span-recorder.js";
21
+ import { computeTrend, formatTrend } from "../lib/eval/trend.js";
22
+
23
+ /** Append a run summary as one JSONL line to the history file. */
24
+ function appendHistory(file, record) {
25
+ fs.appendFileSync(file, JSON.stringify(record) + "\n", "utf8");
26
+ }
27
+
28
+ /** Read a JSONL eval-history file into an array of run records (skips bad lines). */
29
+ function readHistory(file) {
30
+ if (!fs.existsSync(file)) return [];
31
+ const out = [];
32
+ for (const line of fs.readFileSync(file, "utf8").split(/\r?\n/)) {
33
+ const t = line.trim();
34
+ if (!t) continue;
35
+ try {
36
+ out.push(JSON.parse(t));
37
+ } catch {
38
+ /* skip a corrupt history line rather than abort the report */
39
+ }
40
+ }
41
+ return out;
42
+ }
43
+
44
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
45
+ // This file is src/commands/eval.js → the CLI entry is bin/chainlesschain.js.
46
+ const BIN = path.resolve(__dirname, "..", "..", "bin", "chainlesschain.js");
47
+
48
+ /**
49
+ * Build a runAgent that shells out to a headless `cc agent -p` in the task's
50
+ * workspace. acceptEdits lets it write files without an interactive prompt.
51
+ */
52
+ function makeHeadlessRunAgent(opts = {}) {
53
+ return function runAgent({ prompt, cwd, timeoutMs }) {
54
+ return new Promise((resolve) => {
55
+ const args = [
56
+ BIN,
57
+ "agent",
58
+ "-p",
59
+ prompt,
60
+ "--permission-mode",
61
+ "acceptEdits",
62
+ "--output-format",
63
+ "text",
64
+ ];
65
+ if (opts.model) args.push("--model", opts.model);
66
+ if (opts.provider) args.push("--provider", opts.provider);
67
+ const child = spawn(process.execPath, args, {
68
+ cwd,
69
+ env: { ...process.env, CLAUDECODE: "1" },
70
+ windowsHide: true,
71
+ });
72
+ let out = "";
73
+ let err = "";
74
+ let settled = false;
75
+ const done = (result) => {
76
+ if (settled) return;
77
+ settled = true;
78
+ resolve(result);
79
+ };
80
+ const timer = setTimeout(() => {
81
+ try {
82
+ child.kill("SIGTERM");
83
+ } catch {
84
+ /* already gone */
85
+ }
86
+ done({
87
+ ok: false,
88
+ output: out,
89
+ error: `timed out after ${timeoutMs || 120000}ms`,
90
+ });
91
+ }, timeoutMs || 120000);
92
+ if (typeof timer.unref === "function") timer.unref();
93
+ child.stdout?.on("data", (d) => (out += d.toString("utf8")));
94
+ child.stderr?.on("data", (d) => (err += d.toString("utf8")));
95
+ child.on("error", (e) => {
96
+ clearTimeout(timer);
97
+ done({ ok: false, output: out, error: e.message });
98
+ });
99
+ child.on("close", (code) => {
100
+ clearTimeout(timer);
101
+ done({ ok: code === 0, output: out, error: code === 0 ? null : err });
102
+ });
103
+ });
104
+ };
105
+ }
106
+
107
+ export function registerEvalCommand(program, { logger } = {}) {
108
+ const log = logger || console;
109
+ program
110
+ .command("eval")
111
+ .description(
112
+ "Run the reliability eval suite (self-checking coding tasks) and report the task-success rate",
113
+ )
114
+ .option("--suite <name>", "Suite to run", "builtin")
115
+ .option("--model <model>", "Model for the agent runs")
116
+ .option("--provider <provider>", "Provider for the agent runs")
117
+ .option("--json", "Output the summary as JSON")
118
+ .option("--keep", "Keep the per-task temp workspaces (debug)")
119
+ .option(
120
+ "--otlp <file>",
121
+ "Write OpenTelemetry (OTLP/JSON) spans for the run to a file",
122
+ )
123
+ .option(
124
+ "--dry-run",
125
+ "Use a no-op agent (exercise the harness/report without a model)",
126
+ )
127
+ .option(
128
+ "--history <file>",
129
+ "Append this run's summary (JSONL) for trend tracking",
130
+ )
131
+ .option(
132
+ "--label <label>",
133
+ "Tag this run in the history (e.g. a version/commit)",
134
+ )
135
+ .option(
136
+ "--trend",
137
+ "Report the pass-rate trend from --history instead of running (CI gate)",
138
+ )
139
+ .option(
140
+ "--regression-threshold <pct>",
141
+ "With --trend: pass-rate drop (in points) that fails the gate on its own",
142
+ "0",
143
+ )
144
+ .action(async (options) => {
145
+ // Trend mode: don't run the suite — read the recorded history and report
146
+ // the pass-rate trend + per-task regressions. This is the release-pipeline
147
+ // consumer (the runs themselves need a real model; the report is pure).
148
+ if (options.trend) {
149
+ if (!options.history) {
150
+ (log.error || console.error)("--trend requires --history <file>");
151
+ process.exitCode = 1;
152
+ return;
153
+ }
154
+ const runs = readHistory(options.history);
155
+ const threshold =
156
+ Math.max(0, Number(options.regressionThreshold) || 0) / 100;
157
+ const trend = computeTrend(runs, { regressionThreshold: threshold });
158
+ if (options.json) console.log(JSON.stringify(trend, null, 2));
159
+ else (log.log || console.log)(formatTrend(trend));
160
+ if (trend.regressed) process.exitCode = 1;
161
+ return;
162
+ }
163
+
164
+ let tasks;
165
+ try {
166
+ tasks = getSuite(options.suite);
167
+ } catch (err) {
168
+ log.error ? log.error(err.message) : console.error(err.message);
169
+ process.exitCode = 1;
170
+ return;
171
+ }
172
+ const runAgent = options.dryRun
173
+ ? async () => ({ ok: true, output: "(dry-run: no agent)" })
174
+ : makeHeadlessRunAgent({
175
+ model: options.model,
176
+ provider: options.provider,
177
+ });
178
+
179
+ // OTel-shaped telemetry for the run (per-task span + failure class).
180
+ const recorder = new TelemetryRecorder({ serviceName: "cc-eval" });
181
+
182
+ const summary = await runEvalSuite(tasks, {
183
+ runAgent,
184
+ recorder,
185
+ keepWorkspaces: options.keep === true,
186
+ onResult: options.json
187
+ ? undefined
188
+ : (r) =>
189
+ (log.info || console.log)(
190
+ ` ${r.pass ? "✔" : "✗"} ${r.id} (${r.ms}ms)` +
191
+ (r.error
192
+ ? ` — ${r.error}`
193
+ : r.detail
194
+ ? ` — ${r.detail}`
195
+ : ""),
196
+ ),
197
+ });
198
+
199
+ if (options.otlp) {
200
+ try {
201
+ fs.writeFileSync(
202
+ options.otlp,
203
+ JSON.stringify(recorder.toOtlp(), null, 2),
204
+ "utf8",
205
+ );
206
+ } catch (e) {
207
+ (log.error || console.error)(` otlp write failed: ${e.message}`);
208
+ }
209
+ }
210
+
211
+ // Append to the trend history (a compact record — pass counts + per-task
212
+ // pass/fail + a timestamp/label — so `cc eval --trend` can chart it).
213
+ if (options.history) {
214
+ try {
215
+ appendHistory(options.history, {
216
+ ranAt: new Date().toISOString(),
217
+ label: options.label || null,
218
+ passed: summary.passed,
219
+ total: summary.total,
220
+ passRate: summary.passRate,
221
+ results: (summary.results || []).map((r) => ({
222
+ id: r.id,
223
+ pass: r.pass,
224
+ })),
225
+ });
226
+ } catch (e) {
227
+ (log.error || console.error)(` history write failed: ${e.message}`);
228
+ }
229
+ }
230
+
231
+ if (options.json) {
232
+ console.log(JSON.stringify(summary, null, 2));
233
+ } else {
234
+ // Per-task lines already streamed via onResult; print the summary +
235
+ // the telemetry metrics (durations / failure classification).
236
+ const pct = (summary.passRate * 100).toFixed(1);
237
+ (log.log || console.log)(
238
+ `\nEval: ${summary.passed}/${summary.total} passed (${pct}%) in ${summary.ms}ms`,
239
+ );
240
+ if (summary.telemetry) {
241
+ (log.log || console.log)("\n" + formatTelemetry(summary.telemetry));
242
+ }
243
+ }
244
+ // Non-zero exit when not every task passed — usable as a CI gate.
245
+ if (summary.passed < summary.total) process.exitCode = 1;
246
+ });
247
+ return program;
248
+ }
@@ -495,6 +495,360 @@ export function registerPluginCommand(program) {
495
495
  process.exit(1);
496
496
  }
497
497
  });
498
+
499
+ // plugin validate — parse a plugin's unified manifest and report every
500
+ // component it contributes (skills/agents/hooks/mcp/lsp/monitors/bin/settings),
501
+ // plus path-traversal / schema problems. Optional signature/hash verification
502
+ // reuses the real crypto in plugin-security. No DB, no install — pure inspection.
503
+ plugin
504
+ .command("validate <dir>")
505
+ .description("Validate a plugin manifest and list its components")
506
+ .option("--sha256 <hex>", "Expected SHA-256 of the manifest file")
507
+ .option("--signature <path>", "Detached Ed25519 signature of the manifest")
508
+ .option("--public-key <path>", "Public key for signature verification")
509
+ .option("--json", "Output as JSON")
510
+ .action(async (dir, options) => {
511
+ const { parsePluginManifest, summarizeComponents } =
512
+ await import("../lib/plugin-runtime/manifest.js");
513
+ const manifest = parsePluginManifest(dir);
514
+
515
+ // Optional integrity/signature check on the manifest file itself.
516
+ // verifyPluginManifest THROWS on any mismatch/failure and returns a
517
+ // details object on success — so a caught error means verification failed.
518
+ let verification = null;
519
+ if (manifest.manifestPath && (options.sha256 || options.signature)) {
520
+ try {
521
+ const v = verifyPluginManifest({
522
+ manifestFile: manifest.manifestPath,
523
+ expectedSha256: options.sha256,
524
+ signatureFile: options.signature,
525
+ publicKeyFile: options.publicKey,
526
+ });
527
+ verification = {
528
+ ok: true,
529
+ sha256: v?.sha256 || null,
530
+ signatureVerified: v?.signatureVerified === true,
531
+ };
532
+ } catch (err) {
533
+ verification = { ok: false, reason: err.message };
534
+ manifest.ok = false;
535
+ manifest.errors.push(`manifest verification failed: ${err.message}`);
536
+ }
537
+ }
538
+
539
+ const counts = summarizeComponents(manifest);
540
+
541
+ if (options.json) {
542
+ console.log(
543
+ JSON.stringify(
544
+ { ...manifest, componentCounts: counts, verification },
545
+ null,
546
+ 2,
547
+ ),
548
+ );
549
+ if (!manifest.ok) process.exitCode = 1;
550
+ return;
551
+ }
552
+
553
+ const m = manifest.metadata || {};
554
+ logger.log(
555
+ chalk.bold(`Plugin: `) +
556
+ `${chalk.cyan(m.name || "(no name)")} ${chalk.gray("v" + (m.version || "?"))}`,
557
+ );
558
+ if (m.description) logger.log(chalk.gray(" " + m.description));
559
+ logger.log(
560
+ chalk.gray(` manifest: ${manifest.manifestPath || "(none)"}`),
561
+ );
562
+ logger.log(chalk.bold("\nComponents:"));
563
+ for (const [kind, n] of Object.entries(counts)) {
564
+ const mark = n > 0 ? chalk.green(String(n)) : chalk.gray("0");
565
+ logger.log(` ${kind.padEnd(10)} ${mark}`);
566
+ }
567
+ if (verification) {
568
+ logger.log(
569
+ chalk.bold("\nVerification: ") +
570
+ (verification.ok ? chalk.green("passed") : chalk.red("FAILED")),
571
+ );
572
+ }
573
+ for (const w of manifest.warnings) logger.log(chalk.yellow(` ⚠ ${w}`));
574
+ for (const e of manifest.errors) logger.log(chalk.red(` ✖ ${e}`));
575
+ if (manifest.ok) {
576
+ logger.success("\nManifest is valid.");
577
+ } else {
578
+ logger.error("\nManifest is INVALID.");
579
+ process.exitCode = 1;
580
+ }
581
+ });
582
+
583
+ // ── unified plugin runtime install lifecycle (Phase 3) ──
584
+ // These operate on the scope version dirs (user/project/local), independent
585
+ // of the legacy DB-backed `install/list/remove` above. A plugin installed
586
+ // here has its skills/hooks/lsp components picked up by the agent.
587
+
588
+ const SCOPES = "user|project|local";
589
+
590
+ // plugin add <source> — install from a local dir, git URL, or owner/repo
591
+ plugin
592
+ .command("add <source>")
593
+ .description(
594
+ `Install a plugin from a local dir, git URL, or owner/repo[#ref] (scope: ${SCOPES})`,
595
+ )
596
+ .option("--scope <scope>", "Install scope (user|project|local)", "user")
597
+ .option("--force", "Reinstall over an existing immutable version")
598
+ .option("--sha256 <hex>", "Expected SHA-256 of the manifest file")
599
+ .option("--signature <path>", "Detached Ed25519 signature of the manifest")
600
+ .option("--public-key <path>", "Public key for signature verification")
601
+ .option("--json", "Output as JSON")
602
+ .action(async (source, options) => {
603
+ const { installFromSource } =
604
+ await import("../lib/plugin-runtime/install.js");
605
+ const signature =
606
+ options.sha256 || options.signature || options.publicKey
607
+ ? {
608
+ sha256: options.sha256,
609
+ signatureFile: options.signature,
610
+ publicKeyFile: options.publicKey,
611
+ requireSignature: Boolean(options.signature),
612
+ }
613
+ : null;
614
+ try {
615
+ const res = installFromSource(source, {
616
+ scope: options.scope,
617
+ cwd: process.cwd(),
618
+ force: options.force === true,
619
+ signature,
620
+ });
621
+ if (options.json) {
622
+ console.log(JSON.stringify(res, null, 2));
623
+ } else {
624
+ logger.success(
625
+ `Installed ${res.name} v${res.version} (${res.scope} scope)` +
626
+ (res.signatureVerified ? chalk.green(" ✔ signed") : ""),
627
+ );
628
+ logger.log(chalk.gray(` → ${res.dir}`));
629
+ for (const w of res.warnings || [])
630
+ logger.log(chalk.yellow(` ⚠ ${w}`));
631
+ }
632
+ } catch (err) {
633
+ logger.error(`Install failed: ${err.message}`);
634
+ process.exitCode = 1;
635
+ }
636
+ });
637
+
638
+ // plugin installed — list runtime-installed plugins across scopes
639
+ plugin
640
+ .command("installed")
641
+ .description("List plugins installed in the unified runtime (scope dirs)")
642
+ .option("--json", "Output as JSON")
643
+ .action(async (options) => {
644
+ const { listInstalled } =
645
+ await import("../lib/plugin-runtime/install.js");
646
+ const rows = listInstalled({ cwd: process.cwd() });
647
+ if (options.json) {
648
+ console.log(JSON.stringify(rows, null, 2));
649
+ return;
650
+ }
651
+ if (rows.length === 0) {
652
+ logger.info("No plugins installed. Add one with: cc plugin add <dir>");
653
+ return;
654
+ }
655
+ const { isPluginTrusted } =
656
+ await import("../lib/plugin-runtime/trust.js");
657
+ logger.log(chalk.bold(`Installed plugins (${rows.length}):`));
658
+ for (const r of rows) {
659
+ const ok = r.ok ? chalk.green("✔") : chalk.red("✖");
660
+ const trust = isPluginTrusted(r)
661
+ ? chalk.green("trusted")
662
+ : chalk.yellow("untrusted");
663
+ logger.log(
664
+ ` ${ok} ${chalk.cyan(r.name)} v${r.version} ${chalk.gray(`[${r.scope}]`)} ${trust}`,
665
+ );
666
+ }
667
+ });
668
+
669
+ // plugin trust <name> — allow a plugin's code-bearing components to run
670
+ plugin
671
+ .command("trust <name>")
672
+ .description("Trust a plugin so its hooks / LSP servers may run")
673
+ .option("--scope <scope>", "Scope of the plugin", "project")
674
+ .option("--list", "List all trusted plugins instead")
675
+ .action(async (name, options) => {
676
+ const { trustPlugin, listTrust } =
677
+ await import("../lib/plugin-runtime/trust.js");
678
+ const { getActiveVersion } =
679
+ await import("../lib/plugin-runtime/install.js");
680
+ if (options.list) {
681
+ for (const t of listTrust()) {
682
+ logger.log(` ${chalk.cyan(t.name)} v${t.version} [${t.scope}]`);
683
+ }
684
+ return;
685
+ }
686
+ const version = getActiveVersion(name, {
687
+ scope: options.scope,
688
+ cwd: process.cwd(),
689
+ });
690
+ if (!version) {
691
+ logger.error(`${name} is not installed at ${options.scope} scope`);
692
+ process.exitCode = 1;
693
+ return;
694
+ }
695
+ trustPlugin(name, { scope: options.scope, version });
696
+ logger.success(`Trusted ${name} v${version} (${options.scope} scope)`);
697
+ });
698
+
699
+ // plugin untrust <name> — revoke trust
700
+ plugin
701
+ .command("untrust <name>")
702
+ .description(
703
+ "Revoke trust for a plugin (its hooks / LSP servers stop running)",
704
+ )
705
+ .option("--scope <scope>", "Scope of the plugin", "project")
706
+ .action(async (name, options) => {
707
+ const { untrustPlugin } = await import("../lib/plugin-runtime/trust.js");
708
+ const res = untrustPlugin(name, { scope: options.scope });
709
+ if (res.removed) {
710
+ logger.success(`Revoked trust for ${name} (${options.scope} scope)`);
711
+ } else {
712
+ logger.info(`${name} was not trusted at ${options.scope} scope`);
713
+ }
714
+ });
715
+
716
+ // plugin monitors — list (and optionally run) trusted plugins' background
717
+ // monitors. `--run --seconds N` actually starts the supervisor for N seconds,
718
+ // prints captured output, then reaps everything (verifies no leaked process).
719
+ plugin
720
+ .command("monitors")
721
+ .description("List installed plugins' background monitors (trusted only)")
722
+ .option("--json", "Output as JSON")
723
+ .option("--run", "Actually run the monitors for a few seconds, then reap")
724
+ .option("--seconds <n>", "With --run: how long to run", "3")
725
+ .action(async (options) => {
726
+ const { collectPluginMonitors } =
727
+ await import("../lib/plugin-runtime/monitors.js");
728
+ const monitors = collectPluginMonitors({ cwd: process.cwd() });
729
+ if (options.json && !options.run) {
730
+ console.log(JSON.stringify(monitors, null, 2));
731
+ return;
732
+ }
733
+ if (monitors.length === 0) {
734
+ logger.info(
735
+ "No monitors from trusted plugins. (Untrusted project plugins are skipped — `cc plugin trust <name>`.)",
736
+ );
737
+ return;
738
+ }
739
+ logger.log(chalk.bold(`Plugin monitors (${monitors.length}):`));
740
+ for (const m of monitors) {
741
+ const cadence =
742
+ m.mode === "interval"
743
+ ? `every ${m.intervalMs || 60000}ms`
744
+ : "long-running";
745
+ logger.log(
746
+ ` ${chalk.cyan(m.id)} ${chalk.gray(`[${m.scope}]`)} ${m.command} ${m.args.join(" ")} ${chalk.gray(`(${cadence})`)}`,
747
+ );
748
+ }
749
+ if (!options.run) return;
750
+
751
+ const { PluginMonitorSupervisor } =
752
+ await import("../lib/plugin-monitor-supervisor.js");
753
+ const secs = Math.max(1, parseInt(options.seconds, 10) || 3);
754
+ const sup = new PluginMonitorSupervisor();
755
+ const started = sup.start(monitors);
756
+ logger.log(
757
+ chalk.gray(`\nRunning ${started.length} monitor(s) for ${secs}s…`),
758
+ );
759
+ await new Promise((r) => setTimeout(r, secs * 1000));
760
+ const out = sup.drainOutputs();
761
+ sup.stopAll();
762
+ logger.log(chalk.bold(`Captured ${out.length} output line(s):`));
763
+ for (const rec of out.slice(0, 50)) {
764
+ logger.log(
765
+ ` ${chalk.gray(`[${rec.monitor}/${rec.stream}]`)} ${rec.line}`,
766
+ );
767
+ }
768
+ logger.success("Monitors reaped — no process left running.");
769
+ });
770
+
771
+ // plugin uninstall <name> — remove a plugin (or one version) from a scope
772
+ plugin
773
+ .command("uninstall <name>")
774
+ .description(`Uninstall a runtime plugin from a scope (${SCOPES})`)
775
+ .option("--scope <scope>", "Scope to remove from", "user")
776
+ .option("--version <version>", "Remove only this version (default: all)")
777
+ .action(async (name, options) => {
778
+ const { uninstall } = await import("../lib/plugin-runtime/install.js");
779
+ try {
780
+ const res = uninstall(name, {
781
+ scope: options.scope,
782
+ cwd: process.cwd(),
783
+ version: options.version,
784
+ });
785
+ logger.success(
786
+ `Uninstalled ${name} (${res.removed.join(", ") || "nothing"}) from ${options.scope} scope`,
787
+ );
788
+ } catch (err) {
789
+ logger.error(`Uninstall failed: ${err.message}`);
790
+ process.exitCode = 1;
791
+ }
792
+ });
793
+
794
+ // plugin upgrade <source> — re-fetch a source and install its newer version
795
+ plugin
796
+ .command("upgrade <source>")
797
+ .description(
798
+ "Update a runtime plugin from its source (local dir or git); repoints .active",
799
+ )
800
+ .option("--scope <scope>", `Scope to update in (${SCOPES})`, "user")
801
+ .option("--force", "Reinstall even if the version is unchanged")
802
+ .action(async (source, options) => {
803
+ const { updatePlugin } = await import("../lib/plugin-runtime/install.js");
804
+ try {
805
+ const res = updatePlugin(source, {
806
+ scope: options.scope,
807
+ cwd: process.cwd(),
808
+ force: options.force,
809
+ });
810
+ if (res.updated) {
811
+ logger.success(
812
+ `Updated ${res.name}: ${res.previousVersion ? `v${res.previousVersion} → ` : ""}v${res.version} (${options.scope} scope)`,
813
+ );
814
+ } else if (res.reinstalled) {
815
+ logger.success(
816
+ `Reinstalled ${res.name} v${res.version} (${options.scope} scope)`,
817
+ );
818
+ } else {
819
+ logger.info(
820
+ `${res.name} is already up to date at v${res.version} (use --force to reinstall)`,
821
+ );
822
+ }
823
+ } catch (err) {
824
+ logger.error(`Upgrade failed: ${err.message}`);
825
+ process.exitCode = 1;
826
+ }
827
+ });
828
+
829
+ // plugin use <name> <version> — pin the active version (rollback / switch)
830
+ plugin
831
+ .command("use <name> <version>")
832
+ .description("Pin a plugin's active version (rollback or switch)")
833
+ .option("--scope <scope>", "Scope", "user")
834
+ .action(async (name, version, options) => {
835
+ const { setActiveVersion } =
836
+ await import("../lib/plugin-runtime/install.js");
837
+ try {
838
+ setActiveVersion(name, version, {
839
+ scope: options.scope,
840
+ cwd: process.cwd(),
841
+ });
842
+ logger.success(
843
+ `${name} active version → v${version} (${options.scope} scope)`,
844
+ );
845
+ } catch (err) {
846
+ logger.error(`Failed: ${err.message}`);
847
+ process.exitCode = 1;
848
+ }
849
+ });
850
+
851
+ return plugin;
498
852
  }
499
853
 
500
854
  // === Iter26 V2 governance overlay ===
@@ -27,6 +27,14 @@ export function registerServeCommand(program) {
27
27
  "Allow non-localhost connections (requires --token)",
28
28
  )
29
29
  .option("--project <path>", "Default project root for sessions")
30
+ .option(
31
+ "--remote-session-relay-url <url>",
32
+ "Signaling relay URL for Remote Session pairing",
33
+ )
34
+ .option(
35
+ "--remote-session-peer-id <id>",
36
+ "Stable relay peer ID for this local runtime",
37
+ )
30
38
  .option(
31
39
  "--http-port <port>",
32
40
  "Hosted HTTP port for Phase 5 envelope SSE (disabled if unset)",
@@ -47,6 +55,8 @@ export function registerServeCommand(program) {
47
55
  project: opts.project,
48
56
  httpPort: opts.httpPort ? parseInt(opts.httpPort, 10) : null,
49
57
  bundlePath: opts.bundle || null,
58
+ remoteSessionRelayUrl: opts.remoteSessionRelayUrl || null,
59
+ remoteSessionPeerId: opts.remoteSessionPeerId || null,
50
60
  });
51
61
  await runtime.startServer();
52
62
  } catch (err) {