chainlesschain 0.162.182 → 0.162.184

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 (202) hide show
  1. package/package.json +1 -1
  2. package/src/assets/web-panel/.build-hash +1 -1
  3. package/src/assets/web-panel/assets/{AIOps-DzZ5_xoj.js → AIOps-DzAl5fGx.js} +1 -1
  4. package/src/assets/web-panel/assets/{ActionButton-DeLXddIg.js → ActionButton-DAHtMGeC.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-rvDCmet1.js → Analytics-BHQaexv5.js} +3 -3
  6. package/src/assets/web-panel/assets/{AppLayout-Yt6QVDnp.js → AppLayout-Phz_pD0n.js} +5 -5
  7. package/src/assets/web-panel/assets/{Artifacts-BS112K5L.js → Artifacts-DHt47kCA.js} +1 -1
  8. package/src/assets/web-panel/assets/{Audit-0wJuQrNu.js → Audit--Y_8FULl.js} +1 -1
  9. package/src/assets/web-panel/assets/{BackgroundAgents-B90PMgbn.js → BackgroundAgents-N1zchH7D.js} +1 -1
  10. package/src/assets/web-panel/assets/{Backup-TkgMglQQ.js → Backup-B_BoyN30.js} +1 -1
  11. package/src/assets/web-panel/assets/{BaseInput-CQVS9p1l.js → BaseInput-Gl4uQHcT.js} +1 -1
  12. package/src/assets/web-panel/assets/{Chat-YTjQHoC7.js → Chat-Cg-eIyAZ.js} +5 -5
  13. package/src/assets/web-panel/assets/ChatBubbleRenderer-BzeUi3JH.js +1 -0
  14. package/src/assets/web-panel/assets/{Checkbox-5bwaOabq.js → Checkbox-D0MGR2wA.js} +1 -1
  15. package/src/assets/web-panel/assets/{Codegen-BFmNQ_Xe.js → Codegen-BdObJEFn.js} +1 -1
  16. package/src/assets/web-panel/assets/{Col-BT_u4Dzp.js → Col--ghxXT3z.js} +1 -1
  17. package/src/assets/web-panel/assets/{Community-CJP52u5b.js → Community-BUFeXOqz.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compact-BpzhJE9i.js → Compact-DhQO2_Mr.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compliance-Cg7rfslp.js → Compliance-3HoTqKYd.js} +1 -1
  20. package/src/assets/web-panel/assets/{Cowork-JisxL6Yy.js → Cowork-B3zmO4VW.js} +3 -3
  21. package/src/assets/web-panel/assets/{Cron-Bu7Ug_MC.js → Cron-CJDrZOcc.js} +2 -2
  22. package/src/assets/web-panel/assets/{Crosschain-CvuqoLdj.js → Crosschain-SMl15obd.js} +1 -1
  23. package/src/assets/web-panel/assets/{DID-C2u9G8Pu.js → DID-CgTrTWrl.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dashboard-BFt5Yv3d.js → Dashboard-dXFKaKol.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dropdown-DIaT9Wxq.js → Dropdown-qQHEhCvI.js} +1 -1
  26. package/src/assets/web-panel/assets/{EmailListRenderer-D_A601Y4.js → EmailListRenderer-C_ej0MWH.js} +1 -1
  27. package/src/assets/web-panel/assets/{FamilyGuardDashboard--IyQ8I8w.js → FamilyGuardDashboard-D6ajoE7I.js} +1 -1
  28. package/src/assets/web-panel/assets/{Federation-BihWHxuY.js → Federation-Cio2y49h.js} +1 -1
  29. package/src/assets/web-panel/assets/{FormItemContext-BB8dOXc_.js → FormItemContext-ClJz1cYp.js} +1 -1
  30. package/src/assets/web-panel/assets/{GenericCardRenderer-DQYhj1HH.js → GenericCardRenderer-Dr_8Maca.js} +1 -1
  31. package/src/assets/web-panel/assets/{Git-B-2QZxGf.js → Git-CevLwp5u.js} +2 -2
  32. package/src/assets/web-panel/assets/{Governance-CusSb-nG.js → Governance-CW9YyQUY.js} +1 -1
  33. package/src/assets/web-panel/assets/{Inference-BAjmvPPL.js → Inference-CQqeAyER.js} +1 -1
  34. package/src/assets/web-panel/assets/{KnowledgeGraph-DoNYWKYq.js → KnowledgeGraph-cuGVxHrw.js} +1 -1
  35. package/src/assets/web-panel/assets/{Logs-B8fKWD-n.js → Logs-DIuHri5d.js} +2 -2
  36. package/src/assets/web-panel/assets/{MarkdownRenderer-BlJm1J7E.js → MarkdownRenderer-R91Qw5JA.js} +1 -1
  37. package/src/assets/web-panel/assets/{Marketplace-CyOscbSL.js → Marketplace-CY1VhFGx.js} +1 -1
  38. package/src/assets/web-panel/assets/{McpTools-Ex6Om5da.js → McpTools-BBAbi1vt.js} +5 -5
  39. package/src/assets/web-panel/assets/{Memory-CDcD8l8r.js → Memory-BWYGHxJA.js} +2 -2
  40. package/src/assets/web-panel/assets/{MobileBridge-xfBqoFDg.js → MobileBridge-CPIFkW7A.js} +1 -1
  41. package/src/assets/web-panel/assets/{MobileProjects-BwObMMA2.js → MobileProjects-DQyWxCho.js} +1 -1
  42. package/src/assets/web-panel/assets/{Mtc-CIWd36OV.js → Mtc-Bo3GnQbx.js} +4 -4
  43. package/src/assets/web-panel/assets/{MtcAudit-CPX0ouuA.js → MtcAudit-C8-c4rSW.js} +4 -4
  44. package/src/assets/web-panel/assets/{Multisig-BDJsIUuW.js → Multisig-ChqMTtoq.js} +3 -3
  45. package/src/assets/web-panel/assets/{NLProgramming-DEkbuD3N.js → NLProgramming-C48TyhvI.js} +1 -1
  46. package/src/assets/web-panel/assets/{Notes-DJpHRhH1.js → Notes-zogUFWxp.js} +3 -3
  47. package/src/assets/web-panel/assets/{NotificationSettings-C1UZ-Qd5.js → NotificationSettings-v-K9XpSB.js} +1 -1
  48. package/src/assets/web-panel/assets/OrderTableRenderer-P94JGGNz.js +1 -0
  49. package/src/assets/web-panel/assets/{Organization-Bbhj0fac.js → Organization-Boi1dQfR.js} +4 -4
  50. package/src/assets/web-panel/assets/{Overflow-1H04x3kx.js → Overflow-DM5YWwgA.js} +1 -1
  51. package/src/assets/web-panel/assets/{P2P-CDpPe3et.js → P2P-C57LKpKK.js} +2 -2
  52. package/src/assets/web-panel/assets/{PdhVaultBrowser-MUX0Bpvw.js → PdhVaultBrowser-BFkPqu6Q.js} +3 -3
  53. package/src/assets/web-panel/assets/{Permissions-A07-0Ci1.js → Permissions-D6fB9YSp.js} +4 -4
  54. package/src/assets/web-panel/assets/{PersonalDataHub-DhhDWxAZ.js → PersonalDataHub-Bp7EefEo.js} +5 -5
  55. package/src/assets/web-panel/assets/{Pipeline-CyfbJfe-.js → Pipeline-BVln3hZf.js} +1 -1
  56. package/src/assets/web-panel/assets/{Privacy-CNFps3ED.js → Privacy-Bf8P3nF6.js} +1 -1
  57. package/src/assets/web-panel/assets/{ProjectInit--T-u3Dr5.js → ProjectInit-DM6wA2E2.js} +2 -2
  58. package/src/assets/web-panel/assets/{ProjectSettings-DJmrK2fC.js → ProjectSettings-CGbc5Iho.js} +2 -2
  59. package/src/assets/web-panel/assets/Projects-D0p9EOxm.js +1 -0
  60. package/src/assets/web-panel/assets/{Providers-DLzzbOZd.js → Providers-B2kJcxS6.js} +1 -1
  61. package/src/assets/web-panel/assets/{QrScannerModal-CexOomKS.js → QrScannerModal-Cxu7dXYy.js} +1 -1
  62. package/src/assets/web-panel/assets/{QuickAsk-QklGi19_.js → QuickAsk-DTlrTPms.js} +1 -1
  63. package/src/assets/web-panel/assets/{Recommend-Bb9kwSw8.js → Recommend-Cm3X-cCj.js} +1 -1
  64. package/src/assets/web-panel/assets/{RemoteSession-DZuVNNN5.js → RemoteSession-DNb2kjvt.js} +2 -2
  65. package/src/assets/web-panel/assets/{Reputation-Dr5cLP0N.js → Reputation-CZUFFjc1.js} +1 -1
  66. package/src/assets/web-panel/assets/{Row-oCQHYv5t.js → Row-DAPgloxA.js} +1 -1
  67. package/src/assets/web-panel/assets/{RssFeed-IFDEykIR.js → RssFeed-dsx9S793.js} +2 -2
  68. package/src/assets/web-panel/assets/{Search-CspVIxDc.js → Search-DnnC8kz-.js} +1 -1
  69. package/src/assets/web-panel/assets/{Security-Bm66o_DH.js → Security-VuZknRMK.js} +4 -4
  70. package/src/assets/web-panel/assets/{Services-DvanNqXl.js → Services-B3XNX8Vx.js} +2 -2
  71. package/src/assets/web-panel/assets/{Skeleton-CHjEe9_O.js → Skeleton-Dl1nVtCj.js} +1 -1
  72. package/src/assets/web-panel/assets/Skills-CY09CZ_W.js +1 -0
  73. package/src/assets/web-panel/assets/{Sla-DxZm1491.js → Sla-HzU56n1z.js} +1 -1
  74. package/src/assets/web-panel/assets/{SpeechSettings-DWxEEclC.js → SpeechSettings-CRle7Jl2.js} +1 -1
  75. package/src/assets/web-panel/assets/{SyncSettings-FIvOFw5p.js → SyncSettings-DWadz7Sl.js} +2 -2
  76. package/src/assets/web-panel/assets/Tasks-CNVTDGg8.js +1 -0
  77. package/src/assets/web-panel/assets/{Templates-CaNjzV_t.js → Templates-BBAgvrlM.js} +1 -1
  78. package/src/assets/web-panel/assets/{Tenant-DjlP6TmH.js → Tenant-BsbbvGN8.js} +1 -1
  79. package/src/assets/web-panel/assets/Terminal-uscpZI4q.js +3 -0
  80. package/src/assets/web-panel/assets/{TimelineRenderer-DoZ8y7y8.js → TimelineRenderer-mTyjNE6r.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tokens-390cg2TC.js → Tokens-Bz97oBgs.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trigger-CLrtCj5_.js → Trigger-BTRKC140.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trust-DpESfSPn.js → Trust-B4A_KuyX.js} +1 -1
  84. package/src/assets/web-panel/assets/{UkeySign-CN6279O0.js → UkeySign-DES9TmLU.js} +1 -1
  85. package/src/assets/web-panel/assets/{VideoEditing-DPtAUlSe.js → VideoEditing-ClXs7Qxp.js} +1 -1
  86. package/src/assets/web-panel/assets/{Wallet-nKOMV_1n.js → Wallet-IzZqFz-7.js} +4 -4
  87. package/src/assets/web-panel/assets/{WebAuthn-HuXlSOc4.js → WebAuthn-BtOP04g_.js} +5 -5
  88. package/src/assets/web-panel/assets/{WorkflowEditor-CUfFjARi.js → WorkflowEditor-_0cqnopY.js} +1 -1
  89. package/src/assets/web-panel/assets/{chat-6Eq0PcZJ.js → chat-ax7193uU.js} +1 -1
  90. package/src/assets/web-panel/assets/{colors-BP_Sf6Iy.js → colors-Bu4WGJah.js} +1 -1
  91. package/src/assets/web-panel/assets/{compact-item-BufMKIh5.js → compact-item-BX1dlTW0.js} +1 -1
  92. package/src/assets/web-panel/assets/{createContext-BBMXxWSW.js → createContext-CktA_Dj7.js} +1 -1
  93. package/src/assets/web-panel/assets/devWarning-x877iKKS.js +1 -0
  94. package/src/assets/web-panel/assets/{hasIn-fUK_tRO2.js → hasIn-D5wd817l.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-t8N1tSeX.js → index-5PYYkr8S.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-DLpIs_P_.js → index-A4uBPQCz.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-DVsqvI4M.js → index-BAtBNfkr.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-Bkg4ZePE.js → index-BLLsUNDc.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-cpEli44X.js → index-BQtoRyTO.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-wKTLbKyc.js → index-BRfXoRuh.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-B7Etk0Te.js → index-Bad2CYeH.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-CwSf5pnf.js → index-BcGdL3sG.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-3FuwBewR.js → index-C3HmzCLt.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-BHy6yNiF.js → index-C8DkWyNr.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-CgiECHu2.js → index-C8tLR2TG.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-C44atv4k.js → index-CP8ELJBc.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-CW_G-MXw.js → index-CUForzsG.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-pum7HYBA.js → index-CYRE0NJA.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-BWKoBU8R.js → index-CeVZaJSC.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-D4_MuGkd.js → index-CfzxR61U.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-Dyngbd29.js → index-Ci3y1ZAv.js} +19 -19
  112. package/src/assets/web-panel/assets/{index-fzaMtSJ8.js → index-CjEJjl5C.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-Cp8vhyZy.js → index-Cv7bVWJ5.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-DPdUNk1i.js → index-D-o4Rwjk.js} +1 -1
  115. package/src/assets/web-panel/assets/index-D7pfPouB.js +1 -0
  116. package/src/assets/web-panel/assets/{index-CeASi4fr.js → index-D9op8poE.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-DASluSqY.js → index-DF1TysIF.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-DocdRcbd.js → index-DYo9S5OT.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-2A5ph8b2.js → index-D_cycOET.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-wV6iGdpY.js → index-Db3CpWTr.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-BMLHv389.js → index-DkD1K-fF.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-B9WYSn4m.js → index-DmPJ6T6F.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-uCbEN7cY.js → index-DmVUeWUk.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-DmkMXwnR.js → index-Dzdr0zDf.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-CZ6Yt17L.js → index-PBLzwYnu.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-CE2DdTP2.js → index-bFCaM7Eq.js} +1 -1
  127. package/src/assets/web-panel/assets/index-e4i-VLBd.js +1 -0
  128. package/src/assets/web-panel/assets/{index-GwdRUZ-x.js → index-h3KJZr95.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-B2vS66eI.js → index-iHcPtQ2e.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-6GmBa4Kg.js → index-jzlzm4VK.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-D9vU25ij.js → index-o14NNnxw.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-CGjmILDm.js → index-tYPSfGbd.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-LvCBfTLo.js → index-ytp2H5Zx.js} +1 -1
  134. package/src/assets/web-panel/assets/{initDefaultProps-V5Fo95FM.js → initDefaultProps-D2Iut83B.js} +1 -1
  135. package/src/assets/web-panel/assets/{motion-BYWU0hUT.js → motion-BuaJVdK9.js} +1 -1
  136. package/src/assets/web-panel/assets/{move-Cr1M-J2h.js → move-CaEuM92y.js} +1 -1
  137. package/src/assets/web-panel/assets/{mtc-parser-BysQKi2N.js → mtc-parser-wuKNBwys.js} +1 -1
  138. package/src/assets/web-panel/assets/{omit-D1zHU8GC.js → omit-7a3eklaq.js} +1 -1
  139. package/src/assets/web-panel/assets/{pickAttrs-CUArxtfi.js → pickAttrs-Dn4z7KvJ.js} +1 -1
  140. package/src/assets/web-panel/assets/{placementArrow-ChoYEys0.js → placementArrow-DVn_qT4-.js} +1 -1
  141. package/src/assets/web-panel/assets/{responsiveObserve-BQRs3Mo7.js → responsiveObserve-Dodz1OMQ.js} +1 -1
  142. package/src/assets/web-panel/assets/{slide-B8zbsCkg.js → slide-CxoGskbp.js} +1 -1
  143. package/src/assets/web-panel/assets/{statusUtils-C2U8Gs6h.js → statusUtils-DBh_epQH.js} +1 -1
  144. package/src/assets/web-panel/assets/{styleChecker-Dd8MgL_V.js → styleChecker-RXQ4gG5P.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFlexGapSupport-hknqY5NH.js → useFlexGapSupport-1Wxm0HEG.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFs-CLTAmcfw.js → useFs-CI_ySNxJ.js} +1 -1
  147. package/src/assets/web-panel/assets/{usePersonalDataHub-ByegHbiB.js → usePersonalDataHub-C6973rZP.js} +1 -1
  148. package/src/assets/web-panel/assets/{vnode-DqlAy5DP.js → vnode-CalynwKr.js} +1 -1
  149. package/src/assets/web-panel/assets/{zoom-DiXiztQn.js → zoom-CM1cd-Q0.js} +1 -1
  150. package/src/assets/web-panel/index.html +1 -1
  151. package/src/commands/agenda.js +74 -1
  152. package/src/commands/agent.js +9 -0
  153. package/src/commands/background-session.js +60 -1
  154. package/src/commands/batch.js +160 -5
  155. package/src/commands/plugin.js +318 -43
  156. package/src/commands/session.js +44 -1
  157. package/src/commands/team.js +212 -6
  158. package/src/data/changelog.json +26 -0
  159. package/src/harness/jsonl-session-store.js +59 -6
  160. package/src/harness/mcp-client.js +65 -43
  161. package/src/lib/agent-batch.js +4 -1
  162. package/src/lib/agent-team/team-runner.js +19 -1
  163. package/src/lib/agent-team/team-worktree.js +3 -0
  164. package/src/lib/async-hook-supervisor.cjs +82 -10
  165. package/src/lib/async-hook-supervisor.js +50 -4
  166. package/src/lib/background-agent-supervisor.js +49 -0
  167. package/src/lib/collaboration-run-store.js +362 -0
  168. package/src/lib/hook-runner.cjs +98 -17
  169. package/src/lib/hook-runner.js +77 -6
  170. package/src/lib/hook-shell-command.cjs +148 -0
  171. package/src/lib/hooks-v2-runtime.js +188 -77
  172. package/src/lib/jsonl-session-store.js +2 -0
  173. package/src/lib/lsp/__tests__/lsp-client.test.js +18 -0
  174. package/src/lib/lsp/lsp-client.js +12 -1
  175. package/src/lib/plugin-monitor-supervisor.js +53 -16
  176. package/src/lib/plugin-runtime/bin.js +1 -1
  177. package/src/lib/plugin-runtime/install.js +465 -54
  178. package/src/lib/plugin-runtime/mcp.js +21 -2
  179. package/src/lib/plugin-runtime/monitors.js +19 -3
  180. package/src/lib/plugin-runtime/sandbox-policy.js +99 -0
  181. package/src/lib/plugin-runtime/scopes.js +13 -2
  182. package/src/lib/plugin-usage-attribution.js +44 -0
  183. package/src/lib/process-execution-broker/index.js +705 -13
  184. package/src/lib/process-execution-broker/linux-generic-bwrap-runtime.js +1347 -0
  185. package/src/lib/process-execution-broker/linux-generic-bwrap.js +1260 -0
  186. package/src/lib/process-execution-broker/platform-sandbox.js +1831 -157
  187. package/src/lib/session-usage.js +278 -1
  188. package/src/lib/stream-retry.js +29 -0
  189. package/src/repl/agent-repl.js +38 -9
  190. package/src/runtime/agent-core.js +32 -4
  191. package/src/runtime/headless-runner.js +46 -1
  192. package/src/runtime/headless-stream.js +54 -3
  193. package/src/runtime/mcp-config.js +15 -5
  194. package/src/assets/web-panel/assets/ChatBubbleRenderer-PR074hUN.js +0 -1
  195. package/src/assets/web-panel/assets/OrderTableRenderer-GlJtqLjT.js +0 -1
  196. package/src/assets/web-panel/assets/Projects-Qx_MdX9k.js +0 -1
  197. package/src/assets/web-panel/assets/Skills-Cb8jWjMX.js +0 -1
  198. package/src/assets/web-panel/assets/Tasks-CyuLnDFR.js +0 -1
  199. package/src/assets/web-panel/assets/Terminal-DwzGMniO.js +0 -3
  200. package/src/assets/web-panel/assets/devWarning-DgVKduH2.js +0 -1
  201. package/src/assets/web-panel/assets/index-DOZTSoS7.js +0 -1
  202. package/src/assets/web-panel/assets/index-DhpvjpqI.js +0 -1
@@ -20,10 +20,8 @@ import {
20
20
  removePlugin,
21
21
  updatePlugin,
22
22
  getPluginSettings,
23
- setPluginSetting,
24
23
  searchRegistry,
25
24
  listRegistry,
26
- registerInMarketplace,
27
25
  getPluginSummary,
28
26
  installPluginSkills,
29
27
  removePluginSkills,
@@ -39,7 +37,12 @@ import {
39
37
  * (for --json folding) or null when the plugin declares nothing / can't be
40
38
  * resolved.
41
39
  */
42
- async function resolvePluginCapabilityNotice(name, scope, cwd) {
40
+ async function resolvePluginCapabilityNotice(
41
+ name,
42
+ scope,
43
+ cwd,
44
+ { strict = false } = {},
45
+ ) {
43
46
  try {
44
47
  const { discoverPlugins } = await import("../lib/plugin-runtime/scopes.js");
45
48
  const { describeCapabilities } =
@@ -48,7 +51,12 @@ async function resolvePluginCapabilityNotice(name, scope, cwd) {
48
51
  const installed = discoverPlugins({ cwd, skipPolicy: true }).find(
49
52
  (p) => p.name === name && p.scope === scope,
50
53
  );
51
- if (!installed) return null;
54
+ if (!installed) {
55
+ if (strict) {
56
+ throw new Error(`${name} is not discoverable at ${scope} scope`);
57
+ }
58
+ return null;
59
+ }
52
60
  const declared = installed.manifest?.capabilities;
53
61
  if (!declared || consent.capabilitiesAreEmpty(declared)) return null;
54
62
  const entry = consent.loadConsentStore()[`${scope}:${name}`] || null;
@@ -59,7 +67,12 @@ async function resolvePluginCapabilityNotice(name, scope, cwd) {
59
67
  reason: status.reason,
60
68
  added: status.added,
61
69
  };
62
- } catch {
70
+ } catch (error) {
71
+ if (strict) {
72
+ throw new Error(
73
+ `installed plugin capability validation failed: ${error.message}`,
74
+ );
75
+ }
63
76
  return null; // capability rendering is advisory — never break an install
64
77
  }
65
78
  }
@@ -404,8 +417,28 @@ export function registerPluginCommand(program) {
404
417
  .command("enable")
405
418
  .description("Enable a plugin")
406
419
  .argument("<name>", "Plugin name")
407
- .action(async (name) => {
420
+ .option(
421
+ "--scope <scope>",
422
+ "Enable the unified-runtime install at this scope (user|project|local)",
423
+ )
424
+ .option("--json", "Output unified-runtime result as JSON")
425
+ .action(async (name, options) => {
408
426
  try {
427
+ if (options.scope) {
428
+ const { setPluginEnabled } =
429
+ await import("../lib/plugin-runtime/install.js");
430
+ const result = setPluginEnabled(name, true, {
431
+ scope: options.scope,
432
+ cwd: process.cwd(),
433
+ });
434
+ if (options.json) console.log(JSON.stringify(result, null, 2));
435
+ else {
436
+ logger.success(
437
+ `Enabled ${name} (${options.scope} scope). Reload active plugin sessions to apply the change.`,
438
+ );
439
+ }
440
+ return;
441
+ }
409
442
  enforcePluginPolicy(
410
443
  { name, action: "enable" },
411
444
  loadPluginManagedPolicy(),
@@ -436,8 +469,28 @@ export function registerPluginCommand(program) {
436
469
  .command("disable")
437
470
  .description("Disable a plugin")
438
471
  .argument("<name>", "Plugin name")
439
- .action(async (name) => {
472
+ .option(
473
+ "--scope <scope>",
474
+ "Disable the unified-runtime install at this scope (user|project|local)",
475
+ )
476
+ .option("--json", "Output unified-runtime result as JSON")
477
+ .action(async (name, options) => {
440
478
  try {
479
+ if (options.scope) {
480
+ const { setPluginEnabled } =
481
+ await import("../lib/plugin-runtime/install.js");
482
+ const result = setPluginEnabled(name, false, {
483
+ scope: options.scope,
484
+ cwd: process.cwd(),
485
+ });
486
+ if (options.json) console.log(JSON.stringify(result, null, 2));
487
+ else {
488
+ logger.success(
489
+ `Disabled ${name} (${options.scope} scope). Reload active plugin sessions to apply the change.`,
490
+ );
491
+ }
492
+ return;
493
+ }
441
494
  const ctx = await bootstrap({ verbose: program.opts().verbose });
442
495
  if (!ctx.db) {
443
496
  logger.error("Database not available");
@@ -860,6 +913,7 @@ export function registerPluginCommand(program) {
860
913
  // plugin name) resolves to a git source the installer already handles.
861
914
  let installSource = source;
862
915
  let integritySha = null;
916
+ let sourceMetadata = null;
863
917
  const { isRemoteSource, resolveRemoteSource } =
864
918
  await import("../lib/plugin-runtime/remote-source.js");
865
919
  if (options.registry || isRemoteSource(source)) {
@@ -883,6 +937,19 @@ export function registerPluginCommand(program) {
883
937
  });
884
938
  installSource = resolved.source;
885
939
  integritySha = resolved.sha256;
940
+ sourceMetadata = {
941
+ type: "registry",
942
+ source: url,
943
+ registry: url,
944
+ package: name || source,
945
+ resolvedSource: resolved.source,
946
+ ref:
947
+ (typeof resolved.source === "string" &&
948
+ resolved.source.includes("#") &&
949
+ resolved.source.slice(resolved.source.indexOf("#") + 1)) ||
950
+ null,
951
+ offline: resolved.fromCache === true,
952
+ };
886
953
  if (resolved.fromCache) {
887
954
  logger.warn(
888
955
  chalk.yellow(
@@ -897,13 +964,31 @@ export function registerPluginCommand(program) {
897
964
  }
898
965
  }
899
966
 
967
+ let managed = null;
968
+ try {
969
+ managed = loadPluginManagedPolicy();
970
+ } catch (err) {
971
+ logger.error(`Managed plugin policy is invalid: ${err.message}`);
972
+ process.exitCode = 1;
973
+ return;
974
+ }
975
+ const requiresManagedSignature =
976
+ managed?.requireSignedPlugins === true ||
977
+ managed?.requireSignedPlugins === "require";
900
978
  const signature =
901
- options.sha256 || options.signature || options.publicKey || integritySha
979
+ options.sha256 ||
980
+ options.signature ||
981
+ options.publicKey ||
982
+ integritySha ||
983
+ requiresManagedSignature
902
984
  ? {
903
985
  sha256: options.sha256 || integritySha,
904
986
  signatureFile: options.signature,
905
987
  publicKeyFile: options.publicKey,
906
- requireSignature: Boolean(options.signature),
988
+ requireSignature:
989
+ Boolean(options.signature) || requiresManagedSignature,
990
+ trustedKeySha256: managed?.trustedPluginKeySha256 || null,
991
+ requireTrustedKey: requiresManagedSignature,
907
992
  }
908
993
  : null;
909
994
  try {
@@ -912,6 +997,9 @@ export function registerPluginCommand(program) {
912
997
  cwd: process.cwd(),
913
998
  force: options.force === true,
914
999
  signature,
1000
+ sourceMetadata,
1001
+ managedPolicy: managed,
1002
+ policySource: options.registry || source,
915
1003
  });
916
1004
  const capNotice = await resolvePluginCapabilityNotice(
917
1005
  res.name,
@@ -1060,8 +1148,21 @@ export function registerPluginCommand(program) {
1060
1148
  const trust = isPluginTrusted(r)
1061
1149
  ? chalk.green("trusted")
1062
1150
  : chalk.yellow("untrusted");
1151
+ const state =
1152
+ r.enabled === false
1153
+ ? chalk.yellow("disabled")
1154
+ : chalk.green("enabled");
1155
+ const signed = r.integrity?.signature?.verified
1156
+ ? chalk.green("signed")
1157
+ : chalk.gray("unsigned");
1158
+ const policy =
1159
+ r.policy?.allowed === false
1160
+ ? chalk.red("policy-blocked")
1161
+ : r.policy?.managed
1162
+ ? chalk.cyan("managed")
1163
+ : "";
1063
1164
  logger.log(
1064
- ` ${ok} ${chalk.cyan(r.name)} v${r.version} ${chalk.gray(`[${r.scope}]`)} ${trust}`,
1165
+ ` ${ok} ${chalk.cyan(r.name)} v${r.version} ${chalk.gray(`[${r.scope}]`)} ${state} ${trust} ${signed}${policy ? ` ${policy}` : ""}`,
1065
1166
  );
1066
1167
  }
1067
1168
  });
@@ -1456,23 +1557,212 @@ export function registerPluginCommand(program) {
1456
1557
  plugin
1457
1558
  .command("upgrade <source>")
1458
1559
  .description(
1459
- "Update a runtime plugin from its source (local dir or git); repoints .active",
1560
+ "Update a runtime plugin from its pinned local, git, or registry source; repoints .active",
1460
1561
  )
1461
1562
  .option("--scope <scope>", `Scope to update in (${SCOPES})`, "user")
1462
1563
  .option("--force", "Reinstall even if the version is unchanged")
1564
+ .option("--sha256 <hex>", "Expected SHA-256 of the manifest file")
1565
+ .option("--signature <path>", "Detached Ed25519 signature of the manifest")
1566
+ .option("--public-key <path>", "Public key for signature verification")
1567
+ .option(
1568
+ "--registry <url>",
1569
+ "Resolve <source> as a plugin NAME in this registry URL",
1570
+ )
1571
+ .option(
1572
+ "--name <plugin>",
1573
+ "Plugin name to select from a multi-plugin registry",
1574
+ )
1575
+ .option("--token <token>", "Bearer token for a private registry")
1576
+ .option(
1577
+ "--allow-insecure-registry",
1578
+ "Allow a plain-HTTP registry URL (MITM risk — trusted networks only)",
1579
+ )
1463
1580
  .option(
1464
1581
  "--grant-capabilities",
1465
1582
  "Grant any newly declared capabilities during the upgrade (no separate consent step)",
1466
1583
  )
1584
+ .option("--json", "Output as JSON")
1467
1585
  .action(async (source, options) => {
1468
- const { updatePlugin } = await import("../lib/plugin-runtime/install.js");
1586
+ const { updatePlugin, finalizePluginUpdate, rollbackPluginUpdate } =
1587
+ await import("../lib/plugin-runtime/install.js");
1588
+ let installSource = source;
1589
+ let integritySha = null;
1590
+ let sourceMetadata = null;
1591
+ const { isRemoteSource, resolveRemoteSource } =
1592
+ await import("../lib/plugin-runtime/remote-source.js");
1593
+ if (options.registry || isRemoteSource(source)) {
1594
+ const url = options.registry || source;
1595
+ const name = options.registry ? source : options.name;
1596
+ let config = null;
1597
+ try {
1598
+ const cm = await import("../lib/config-manager.js");
1599
+ config = cm.loadConfig();
1600
+ } catch {
1601
+ config = null;
1602
+ }
1603
+ try {
1604
+ const resolved = await resolveRemoteSource(url, {
1605
+ name,
1606
+ token: options.token,
1607
+ config,
1608
+ allowInsecure: options.allowInsecureRegistry === true,
1609
+ });
1610
+ installSource = resolved.source;
1611
+ integritySha = resolved.sha256;
1612
+ sourceMetadata = {
1613
+ type: "registry",
1614
+ source: url,
1615
+ registry: url,
1616
+ package: name || source,
1617
+ resolvedSource: resolved.source,
1618
+ ref:
1619
+ (typeof resolved.source === "string" &&
1620
+ resolved.source.includes("#") &&
1621
+ resolved.source.slice(resolved.source.indexOf("#") + 1)) ||
1622
+ null,
1623
+ offline: resolved.fromCache === true,
1624
+ };
1625
+ if (resolved.fromCache && !options.json) {
1626
+ logger.warn(
1627
+ chalk.yellow(
1628
+ " ⚠ registry unreachable — using cached copy (offline)",
1629
+ ),
1630
+ );
1631
+ }
1632
+ } catch (err) {
1633
+ logger.error(`Registry resolution failed: ${err.message}`);
1634
+ process.exitCode = 1;
1635
+ return;
1636
+ }
1637
+ }
1638
+
1639
+ let managed = null;
1640
+ try {
1641
+ managed = loadPluginManagedPolicy();
1642
+ } catch (err) {
1643
+ logger.error(`Managed plugin policy is invalid: ${err.message}`);
1644
+ process.exitCode = 1;
1645
+ return;
1646
+ }
1647
+ const requiresManagedSignature =
1648
+ managed?.requireSignedPlugins === true ||
1649
+ managed?.requireSignedPlugins === "require";
1650
+ const signature =
1651
+ options.sha256 ||
1652
+ options.signature ||
1653
+ options.publicKey ||
1654
+ integritySha ||
1655
+ requiresManagedSignature
1656
+ ? {
1657
+ sha256: options.sha256 || integritySha,
1658
+ signatureFile: options.signature,
1659
+ publicKeyFile: options.publicKey,
1660
+ requireSignature:
1661
+ Boolean(options.signature) || requiresManagedSignature,
1662
+ trustedKeySha256: managed?.trustedPluginKeySha256 || null,
1663
+ requireTrustedKey: requiresManagedSignature,
1664
+ }
1665
+ : null;
1666
+ let res = null;
1469
1667
  try {
1470
- const res = updatePlugin(source, {
1668
+ res = updatePlugin(installSource, {
1471
1669
  scope: options.scope,
1472
1670
  cwd: process.cwd(),
1473
1671
  force: options.force,
1672
+ signature,
1673
+ sourceMetadata,
1674
+ managedPolicy: managed,
1675
+ policySource: options.registry || source,
1676
+ transactional: true,
1474
1677
  });
1475
- if (res.updated) {
1678
+ const upgradeNotice = await resolvePluginCapabilityNotice(
1679
+ res.name,
1680
+ options.scope,
1681
+ process.cwd(),
1682
+ { strict: true },
1683
+ );
1684
+ if (res.updated || res.reinstalled)
1685
+ await auditPluginInstall(
1686
+ "upgrade",
1687
+ { ...res, scope: options.scope },
1688
+ installSource,
1689
+ upgradeNotice,
1690
+ );
1691
+
1692
+ let capabilitiesGranted = false;
1693
+ if (options.json) {
1694
+ if (options.grantCapabilities && upgradeNotice?.consented === false) {
1695
+ capabilitiesGranted = await grantInstalledPluginCapabilities(
1696
+ res.name,
1697
+ options.scope,
1698
+ process.cwd(),
1699
+ );
1700
+ }
1701
+ } else {
1702
+ capabilitiesGranted = await applyCapabilityConsentGate(
1703
+ res.name,
1704
+ options.scope,
1705
+ upgradeNotice,
1706
+ process.cwd(),
1707
+ {
1708
+ grant: options.grantCapabilities === true,
1709
+ interactive: Boolean(process.stdin.isTTY),
1710
+ },
1711
+ );
1712
+ }
1713
+
1714
+ const changed = res.updated || res.reinstalled;
1715
+ const consentBlocked =
1716
+ changed &&
1717
+ upgradeNotice?.consented === false &&
1718
+ capabilitiesGranted !== true;
1719
+ const rollbackReason = consentBlocked
1720
+ ? options.grantCapabilities
1721
+ ? "capability_consent_failed"
1722
+ : "capability_consent_required"
1723
+ : null;
1724
+ let activationStatus = changed ? "activated" : "unchanged";
1725
+ let rollbackVersion = null;
1726
+ let cleanupPending = false;
1727
+ if (rollbackReason) {
1728
+ const recovery = rollbackPluginUpdate(res);
1729
+ if (!recovery.rolledBack) {
1730
+ throw new Error("upgrade rollback transaction was unavailable");
1731
+ }
1732
+ activationStatus = "rolled_back";
1733
+ rollbackVersion = recovery.version;
1734
+ } else {
1735
+ cleanupPending = finalizePluginUpdate(res).cleanupPending === true;
1736
+ }
1737
+
1738
+ if (options.json) {
1739
+ console.log(
1740
+ JSON.stringify(
1741
+ {
1742
+ ...res,
1743
+ scope: options.scope,
1744
+ capabilities: upgradeNotice,
1745
+ capabilitiesGranted,
1746
+ activationStatus,
1747
+ rollbackVersion,
1748
+ rollbackReason,
1749
+ cleanupPending,
1750
+ },
1751
+ null,
1752
+ 2,
1753
+ ),
1754
+ );
1755
+ return;
1756
+ }
1757
+
1758
+ if (activationStatus === "rolled_back") {
1759
+ logger.warn(
1760
+ `Upgrade not activated: ${rollbackReason.replaceAll("_", " ")}; ` +
1761
+ (rollbackVersion
1762
+ ? `restored ${res.name} v${rollbackVersion}`
1763
+ : `removed the rejected ${res.name} v${res.version} install`),
1764
+ );
1765
+ } else if (res.updated) {
1476
1766
  logger.success(
1477
1767
  `Updated ${res.name}: ${res.previousVersion ? `v${res.previousVersion} → ` : ""}v${res.version} (${options.scope} scope)`,
1478
1768
  );
@@ -1485,36 +1775,21 @@ export function registerPluginCommand(program) {
1485
1775
  `${res.name} is already up to date at v${res.version} (use --force to reinstall)`,
1486
1776
  );
1487
1777
  }
1488
- // Surface the (possibly widened) capability set + re-consent hint. An
1489
- // upgrade that adds a capability shows a `⚠ capability consent required`
1490
- // notice diffed against the prior consent, then either auto-grants
1491
- // (--grant-capabilities) or blocks interactively to re-consent now.
1492
- const upgradeNotice = await resolvePluginCapabilityNotice(
1493
- res.name,
1494
- options.scope,
1495
- process.cwd(),
1496
- );
1497
- // Only a version that actually landed on disk is an install; an
1498
- // already-up-to-date no-op fetched nothing new to run.
1499
- if (res.updated || res.reinstalled)
1500
- await auditPluginInstall(
1501
- "upgrade",
1502
- { ...res, scope: options.scope },
1503
- source,
1504
- upgradeNotice,
1505
- );
1506
- await applyCapabilityConsentGate(
1507
- res.name,
1508
- options.scope,
1509
- upgradeNotice,
1510
- process.cwd(),
1511
- {
1512
- grant: options.grantCapabilities === true,
1513
- interactive: Boolean(process.stdin.isTTY),
1514
- },
1515
- );
1516
1778
  } catch (err) {
1517
- logger.error(`Upgrade failed: ${err.message}`);
1779
+ let recoveryNote = "";
1780
+ if (res) {
1781
+ try {
1782
+ const recovery = rollbackPluginUpdate(res);
1783
+ if (recovery.rolledBack) {
1784
+ recoveryNote = recovery.version
1785
+ ? `; restored v${recovery.version}`
1786
+ : "; removed the rejected install";
1787
+ }
1788
+ } catch (recoveryError) {
1789
+ recoveryNote = `; automatic recovery failed: ${recoveryError.message}`;
1790
+ }
1791
+ }
1792
+ logger.error(`Upgrade failed: ${err.message}${recoveryNote}`);
1518
1793
  process.exitCode = 1;
1519
1794
  }
1520
1795
  });
@@ -1333,6 +1333,8 @@ export function registerSessionCommand(program) {
1333
1333
  "subagent",
1334
1334
  "tool",
1335
1335
  "mcp",
1336
+ "plugin",
1337
+ "retry",
1336
1338
  "model",
1337
1339
  ];
1338
1340
 
@@ -1346,9 +1348,19 @@ export function registerSessionCommand(program) {
1346
1348
  logger.log(
1347
1349
  ` ${chalk.gray(String(label).padEnd(28))} in=${r.inputTokens} out=${r.outputTokens} total=${chalk.cyan(r.totalTokens.toLocaleString())} calls=${r.calls}`,
1348
1350
  );
1351
+ const elapsed = (ms) => {
1352
+ const value = Math.max(0, Number(ms) || 0);
1353
+ if (value < 1000) return `${Math.round(value)}ms`;
1354
+ return `${(value / 1000).toFixed(2)}s`;
1355
+ };
1349
1356
  const toolRow = (label, r) =>
1350
1357
  logger.log(
1351
- ` ${chalk.gray(String(label).padEnd(28))} calls=${r.calls} errors=${r.errors} turnTokens≈${chalk.cyan((r.turnTokens || 0).toLocaleString())}`,
1358
+ ` ${chalk.gray(String(label).padEnd(28))} calls=${r.calls} errors=${r.errors}` +
1359
+ (r.retries != null ? ` retries=${r.retries}` : "") +
1360
+ (r.timedCalls != null
1361
+ ? ` observed=${elapsed(r.durationMs)} (${r.timedCalls} timed)`
1362
+ : "") +
1363
+ ` turnTokens≈${chalk.cyan((r.turnTokens || 0).toLocaleString())}`,
1352
1364
  );
1353
1365
  const empty = (what) => logger.log(chalk.gray(` (no ${what} recorded)`));
1354
1366
 
@@ -1403,6 +1415,37 @@ export function registerSessionCommand(program) {
1403
1415
  );
1404
1416
  return;
1405
1417
  }
1418
+ case "plugin": {
1419
+ const rows = a.tools?.byPlugin || [];
1420
+ if (rows.length === 0) return empty("plugin-attributed tool calls");
1421
+ for (const r of rows)
1422
+ toolRow(`${r.plugin}${r.version ? `@${r.version}` : ""}`, r);
1423
+ logger.log(
1424
+ chalk.gray(
1425
+ " turnTokens = tokens of turns that used the plugin (approximation; do not sum across rows)",
1426
+ ),
1427
+ );
1428
+ return;
1429
+ }
1430
+ case "retry": {
1431
+ const retry = a.retries || null;
1432
+ if (!retry || !retry.totalRetries)
1433
+ return empty("automatic LLM retries");
1434
+ logger.log(
1435
+ ` ${chalk.gray("all".padEnd(28))} retries=${retry.totalRetries} failedAttemptTime=${chalk.cyan(elapsed(retry.durationMs))}`,
1436
+ );
1437
+ for (const r of retry.byReason || []) {
1438
+ logger.log(
1439
+ ` ${chalk.gray(String(r.reason || "unknown").padEnd(28))} retries=${r.retries} failedAttemptTime=${chalk.cyan(elapsed(r.durationMs))}`,
1440
+ );
1441
+ }
1442
+ for (const r of retry.byModel || []) {
1443
+ logger.log(
1444
+ ` ${chalk.gray(`${r.provider || "?"}/${r.model || "?"}`.padEnd(28))} retries=${r.retries} failedAttemptTime=${chalk.cyan(elapsed(r.durationMs))}`,
1445
+ );
1446
+ }
1447
+ return;
1448
+ }
1406
1449
  default:
1407
1450
  break;
1408
1451
  }