@jshookmcp/jshook 0.3.0 → 0.3.1

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 (321) hide show
  1. package/README.md +25 -50
  2. package/README.zh.md +25 -48
  3. package/dist/AntiCheatDetector-CGVGNfy5.mjs +1 -0
  4. package/dist/CacheAdapters-CdAxBmVW.mjs +1 -0
  5. package/dist/CodeInjector-BlgyqTOk.mjs +1 -0
  6. package/dist/ConsoleMonitor-Dkqc0HNi.mjs +490 -0
  7. package/dist/DOMInspector-BYY_EJ0C.mjs +95 -0
  8. package/dist/DarwinAPI-DC4HGGLl.mjs +1 -0
  9. package/dist/DetailedDataManager-BniBJlVv.mjs +1 -0
  10. package/dist/EventBus-DgciURGg.mjs +1 -0
  11. package/dist/EvidenceGraphBridge-BIfgB7HP.mjs +1 -0
  12. package/dist/ExtensionManager-erMpqcLk.mjs +1 -0
  13. package/dist/FingerprintManager-N7BZqjxP.mjs +1 -0
  14. package/dist/HardwareBreakpoint-OcJqNFVc.mjs +1 -0
  15. package/dist/HeapAnalyzer-CqAxZzeS.mjs +1 -0
  16. package/dist/{HookGeneratorBuilders.core.generators.storage-CTbB4Lcx.mjs → HookGeneratorBuilders.core.generators.storage-Bf1fbrNK.mjs} +66 -101
  17. package/dist/InstrumentationSession-DxXs0sCp.mjs +1 -0
  18. package/dist/MCPServer.search.handlers.domain-DVbWL1bT.mjs +1 -0
  19. package/dist/MemoryController-BaqstM5w.mjs +2 -0
  20. package/dist/MemoryScanSession-CaxAjZJf.mjs +1 -0
  21. package/dist/MemoryScanner-BLYnMJy6.mjs +1 -0
  22. package/dist/NativeMemoryManager.impl-CI554XbY.mjs +1 -0
  23. package/dist/NativeMemoryManager.utils-DM4NC3FE.mjs +1 -0
  24. package/dist/PEAnalyzer-DJyaJTQJ.mjs +1 -0
  25. package/dist/PageController-D9jVkH0i.mjs +1 -0
  26. package/dist/PointerChainEngine-5nF9eNlu.mjs +1 -0
  27. package/dist/PrerequisiteError-Bl3dK8XA.mjs +1 -0
  28. package/dist/ProcessRegistry-Hf12LlR9.mjs +1 -0
  29. package/dist/ResponseBuilder-B2lu4KEl.mjs +1 -0
  30. package/dist/ReverseEvidenceGraph-B931HeoW.mjs +2 -0
  31. package/dist/ScriptManager-fgqiALgj.mjs +7 -0
  32. package/dist/Speedhack-l6s8L2Qw.mjs +1 -0
  33. package/dist/StealthVerifier-Dhbj4B4P.mjs +1 -0
  34. package/dist/StructureAnalyzer-A-WamfYE.mjs +2 -0
  35. package/dist/ToolCatalog-D_IKl1Hu.mjs +1 -0
  36. package/dist/ToolError-DWU_z7gp.mjs +1 -0
  37. package/dist/ToolProbe-xsfALmN3.mjs +1 -0
  38. package/dist/ToolRegistry-B0Zs-phN.mjs +1 -0
  39. package/dist/ToolRouter.policy-CFHoN_Lw.mjs +4 -0
  40. package/dist/TraceRecorder-Dd8jLXpi.mjs +272 -0
  41. package/dist/VersionDetector-DMoUWyNm.mjs +9 -0
  42. package/dist/Win32API-Bhi5xFBe.mjs +1 -0
  43. package/dist/Win32Debug-CQteFL4F.mjs +1 -0
  44. package/dist/WorkflowEngine-CxEp2WXH.mjs +1 -0
  45. package/dist/analysis-BuR-NgX8.mjs +5 -0
  46. package/dist/{antidebug-BRKeyt27.mjs → antidebug-BOTZH6-0.mjs} +8 -259
  47. package/dist/artifactRetention-NBdncOEW.mjs +1 -0
  48. package/dist/artifacts-B5xQuEa_.mjs +1 -0
  49. package/dist/authorization-schema-B40obG1A.mjs +1 -0
  50. package/dist/betterSqlite3-CGaxz4AX.mjs +1 -0
  51. package/dist/binary-instrument-Cf9qqLlM.mjs +7 -0
  52. package/dist/bind-helpers-BlAOQrFQ.mjs +1 -0
  53. package/dist/boringssl-inspector-BST5vtKx.mjs +2 -0
  54. package/dist/browser-C4Le3xqA.mjs +11 -0
  55. package/dist/capabilities-DbYCv-HF.mjs +1 -0
  56. package/dist/chunk-C_pMuVsO.mjs +1 -0
  57. package/dist/collector-CKO8RPK8.mjs +1 -0
  58. package/dist/concurrency-CcK46d0h.mjs +1 -0
  59. package/dist/constants-Cp6hBrrx.mjs +1 -0
  60. package/dist/coordination-BbijHEHH.mjs +1 -0
  61. package/dist/debugger-CRJq_krh.mjs +1 -0
  62. package/dist/definitions-BGobEDQa.mjs +1 -0
  63. package/dist/definitions-BGwNSkVm.mjs +1 -0
  64. package/dist/definitions-BbxOUiP-.mjs +1 -0
  65. package/dist/definitions-CCP9gphV.mjs +1 -0
  66. package/dist/definitions-CIO9O-Sw.mjs +1 -0
  67. package/dist/definitions-CYFbewnd.mjs +1 -0
  68. package/dist/definitions-CdWEuIkI.mjs +1 -0
  69. package/dist/definitions-CoQFbggH.mjs +1 -0
  70. package/dist/definitions-CuJRsJ6N.mjs +1 -0
  71. package/dist/definitions-DI9YXsJk.mjs +1 -0
  72. package/dist/definitions-DJklW2sS.mjs +1 -0
  73. package/dist/definitions-DZ8uKusP.mjs +1 -0
  74. package/dist/definitions-Dds_zrWx.mjs +1 -0
  75. package/dist/definitions-Dgrg7f3D.mjs +1 -0
  76. package/dist/definitions-DtE0XLrT.mjs +1 -0
  77. package/dist/definitions-LaYTuwQd.mjs +26 -0
  78. package/dist/definitions-NoVp_9Pm.mjs +1 -0
  79. package/dist/definitions-OvGsfxdt.mjs +1 -0
  80. package/dist/definitions-jXPaVy4P.mjs +1 -0
  81. package/dist/encoding-DGcr6Aj_.mjs +2 -0
  82. package/dist/ensure-browser-core-Buls24LQ.mjs +1 -0
  83. package/dist/evidence-graph-bridge-B0yhGPcs.mjs +1 -0
  84. package/dist/factory-Cx_1LorX.mjs +1 -0
  85. package/dist/flat-target-session-CO5g78k3.mjs +1 -0
  86. package/dist/formatAddress-C7j2fDlM.mjs +1 -0
  87. package/dist/graphql-HLf3MS8H.mjs +62 -0
  88. package/dist/handlers-BLMa4X7l.mjs +54 -0
  89. package/dist/handlers-BP12ZsWc.mjs +4 -0
  90. package/dist/handlers-BZoPla6E.mjs +1 -0
  91. package/dist/handlers-BggKiVx9.mjs +2 -0
  92. package/dist/handlers-D3iev8g1.mjs +1 -0
  93. package/dist/handlers-D49r1-1P.mjs +1 -0
  94. package/dist/handlers-DCE45Ww8.mjs +2 -0
  95. package/dist/handlers-DW5AbYs5.mjs +5 -0
  96. package/dist/handlers-De5u62Ga2.mjs +1 -0
  97. package/dist/handlers-DmQzIc44.mjs +31 -0
  98. package/dist/handlers-DnJRGp7t.mjs +302 -0
  99. package/dist/handlers-Dv_runVv.mjs +2 -0
  100. package/dist/handlers-S9Ws0IGy.mjs +2 -0
  101. package/dist/{handlers-Dz9PYsCa.mjs → handlers-pVNpaw4A.mjs} +118 -904
  102. package/dist/handlers.impl-CD2_kOcC.mjs +1 -0
  103. package/dist/hooks-DDKppogd.mjs +600 -0
  104. package/dist/index.mjs +12 -5235
  105. package/dist/logger-sBC6IdRT.mjs +1 -0
  106. package/dist/maintenance-CutEO84j.mjs +1 -0
  107. package/dist/manifest-BFGxlDRh.mjs +123 -0
  108. package/dist/manifest-BPuE6oH2.mjs +1 -0
  109. package/dist/manifest-BXry5N09.mjs +1 -0
  110. package/dist/manifest-BeP_zJGb2.mjs +1 -0
  111. package/dist/manifest-C0g67k6U.mjs +1 -0
  112. package/dist/manifest-C1nZkTkO.mjs +1 -0
  113. package/dist/manifest-C7qV1z7F.mjs +1 -0
  114. package/dist/manifest-CDeUZGUZ.mjs +1 -0
  115. package/dist/manifest-CDiCtaQT.mjs +1 -0
  116. package/dist/manifest-CFn0359q2.mjs +1 -0
  117. package/dist/manifest-CGq4NpqH2.mjs +1 -0
  118. package/dist/manifest-CJMGt7Qy.mjs +1 -0
  119. package/dist/manifest-CRIJq4Hs.mjs +1 -0
  120. package/dist/manifest-C_hEIjSx.mjs +1 -0
  121. package/dist/manifest-CeQmtQOY.mjs +1 -0
  122. package/dist/manifest-Cq0j7GZt.mjs +1 -0
  123. package/dist/manifest-CtPmHAdn.mjs +1 -0
  124. package/dist/manifest-Cx2IVMUY.mjs +1 -0
  125. package/dist/manifest-D16xPXro.mjs +1 -0
  126. package/dist/manifest-D44TaRJU.mjs +1 -0
  127. package/dist/manifest-D610kxZr.mjs +2 -0
  128. package/dist/manifest-DC-SMF6b.mjs +1 -0
  129. package/dist/manifest-DD3rtxvV.mjs +1 -0
  130. package/dist/manifest-DKUorv5M.mjs +1 -0
  131. package/dist/manifest-DMJlcsTR.mjs +1 -0
  132. package/dist/manifest-DWUUWBz0.mjs +1 -0
  133. package/dist/manifest-De-6Wf2R.mjs +1 -0
  134. package/dist/manifest-Dgh0uDW-.mjs +1 -0
  135. package/dist/manifest-Dm0o3i2U.mjs +1 -0
  136. package/dist/manifest-DsVh7Y4U.mjs +1 -0
  137. package/dist/manifest-DtEFSRaq.mjs +1 -0
  138. package/dist/manifest-H-EpAyZQ.mjs +1 -0
  139. package/dist/manifest-ais9Afrw.mjs +1 -0
  140. package/dist/manifest-tmb54wmA.mjs +1 -0
  141. package/dist/manifest-yu2xiQqe.mjs +1 -0
  142. package/dist/manifest-zrbrpKCC.mjs +1 -0
  143. package/dist/matchesWildcardPattern-BGqLSmEs.mjs +1 -0
  144. package/dist/modules-p-PUNv9r.mjs +332 -0
  145. package/dist/mojo-ipc-VGlv3Qyp.mjs +9 -0
  146. package/dist/network-BjZ1Y-GB.mjs +7 -0
  147. package/dist/outputPaths-BonGThuc.mjs +2 -0
  148. package/dist/parse-args-Cuk7-xUt.mjs +1 -0
  149. package/dist/platform-C446Lf97.mjs +93 -0
  150. package/dist/playwright-cdp-fallback-BwVR-_T3.mjs +1 -0
  151. package/dist/process-C9f2A5zk.mjs +962 -0
  152. package/dist/proxy-CvRepxgV.mjs +1 -0
  153. package/dist/registry-DUHIPE-v.mjs +1 -0
  154. package/dist/response-C7rKQst4.mjs +1 -0
  155. package/dist/search-defaults-D2bY-rzH.mjs +1 -0
  156. package/dist/server/plugin-api.mjs +1 -293
  157. package/dist/shared-state-board-Cyg-xh_k.mjs +1 -0
  158. package/dist/sourcemap-D6Q1UuAp.mjs +1 -0
  159. package/dist/ssrf-policy-T96MR3r6.mjs +1 -0
  160. package/dist/streaming-CTX58tbb.mjs +1 -0
  161. package/dist/tool-builder-CI9914Tf.mjs +1 -0
  162. package/dist/transform-Cv9P2vVD.mjs +103 -0
  163. package/dist/types-CuyefmGT.mjs +1 -0
  164. package/dist/types-DtThH00r.mjs +1 -0
  165. package/dist/wasm-DaJa8J0V.mjs +174 -0
  166. package/dist/webcrack-CsLLJIs9.mjs +46 -0
  167. package/dist/workflow-CYIXtrWD.mjs +101 -0
  168. package/package.json +50 -78
  169. package/dist/AntiCheatDetector-CqGDXmfc.mjs +0 -350
  170. package/dist/CacheAdapters-jJFy20G-.mjs +0 -80
  171. package/dist/CodeInjector-BdjRfNx7.mjs +0 -150
  172. package/dist/ConsoleMonitor-DykL3IAw.mjs +0 -2269
  173. package/dist/DarwinAPI-ETyy0xyo.mjs +0 -363
  174. package/dist/DetailedDataManager-HT49OrvF.mjs +0 -217
  175. package/dist/EventBus-DFKvADm3.mjs +0 -141
  176. package/dist/EvidenceGraphBridge-318Oi0Lf.mjs +0 -153
  177. package/dist/ExtensionManager-BDMsY2Dz.mjs +0 -721
  178. package/dist/FingerprintManager-BN4UQWnX.mjs +0 -96
  179. package/dist/HardwareBreakpoint-Cc2AFq1Y.mjs +0 -239
  180. package/dist/HeapAnalyzer-DruMgsgj.mjs +0 -284
  181. package/dist/InstrumentationSession-DLH0vd-z.mjs +0 -244
  182. package/dist/MemoryController-CMtviNW_.mjs +0 -167
  183. package/dist/MemoryScanSession-ITgb_NMi.mjs +0 -278
  184. package/dist/MemoryScanner-CiL7Z3ey.mjs +0 -428
  185. package/dist/NativeMemoryManager.impl-D9Lkovvn.mjs +0 -485
  186. package/dist/NativeMemoryManager.utils-BBlAixF5.mjs +0 -165
  187. package/dist/PEAnalyzer-DMQ44gen.mjs +0 -385
  188. package/dist/PageController-BPJNqqBN.mjs +0 -431
  189. package/dist/PointerChainEngine-K7wN8Z-w.mjs +0 -325
  190. package/dist/PrerequisiteError-TuyZIs6n.mjs +0 -20
  191. package/dist/ProcessRegistry-zGg12QbE.mjs +0 -74
  192. package/dist/ResponseBuilder-CJXWmWNw.mjs +0 -143
  193. package/dist/ReverseEvidenceGraph-C02-gXOh.mjs +0 -269
  194. package/dist/ScriptManager-ZuWD-0Jg.mjs +0 -3003
  195. package/dist/Speedhack-D-z0umeT.mjs +0 -156
  196. package/dist/StealthVerifier-BWmPgQsv.mjs +0 -135
  197. package/dist/StructureAnalyzer-Cav5AVSL.mjs +0 -429
  198. package/dist/ToolCatalog-5OJdMiF0.mjs +0 -582
  199. package/dist/ToolError-jh9whhMd.mjs +0 -15
  200. package/dist/ToolProbe-DbCFGyrg.mjs +0 -45
  201. package/dist/ToolRegistry-B9krbTtI.mjs +0 -180
  202. package/dist/ToolRouter.policy-BGDAGyeH.mjs +0 -344
  203. package/dist/TraceRecorder-B41Z5XBj.mjs +0 -1286
  204. package/dist/VersionDetector-K3V4vGsw.mjs +0 -104
  205. package/dist/Win32API-C2kjj0ze.mjs +0 -346
  206. package/dist/Win32Debug-CKrGOTpo.mjs +0 -274
  207. package/dist/WorkflowEngine-DJ6M4opp.mjs +0 -569
  208. package/dist/analysis-BHeJW2Nb.mjs +0 -1234
  209. package/dist/artifactRetention-CPXkUJXp.mjs +0 -598
  210. package/dist/artifacts-DkfosXH3.mjs +0 -59
  211. package/dist/authorization-schema-DRqyJMSk.mjs +0 -31
  212. package/dist/betterSqlite3-DLSBZodi.mjs +0 -74
  213. package/dist/binary-instrument--V3MAhJ4.mjs +0 -971
  214. package/dist/bind-helpers-ClV34xdn.mjs +0 -42
  215. package/dist/boringssl-inspector-Bo_LOLaS.mjs +0 -180
  216. package/dist/browser-Dx3_S2cG.mjs +0 -4369
  217. package/dist/capabilities-CcHlvWgK.mjs +0 -33
  218. package/dist/chunk-CjcI7cDX.mjs +0 -15
  219. package/dist/concurrency-Drev_Vz9.mjs +0 -41
  220. package/dist/constants-CDZLOoVv.mjs +0 -534
  221. package/dist/coordination-DgItD9DL.mjs +0 -259
  222. package/dist/debugger-RS3RSAqs.mjs +0 -1288
  223. package/dist/definitions-BEoYofW5.mjs +0 -47
  224. package/dist/definitions-BRaefg3u.mjs +0 -365
  225. package/dist/definitions-BbkvZkiv.mjs +0 -96
  226. package/dist/definitions-BtWSHJ3o.mjs +0 -17
  227. package/dist/definitions-C1gCHO0i.mjs +0 -43
  228. package/dist/definitions-CDOg_b-l.mjs +0 -138
  229. package/dist/definitions-CVPD9hzZ.mjs +0 -54
  230. package/dist/definitions-Cea8Lgl7.mjs +0 -94
  231. package/dist/definitions-DAgIyjxM.mjs +0 -10
  232. package/dist/definitions-DJA27nsL.mjs +0 -66
  233. package/dist/definitions-DKPFU3LW.mjs +0 -25
  234. package/dist/definitions-DPRpZQ96.mjs +0 -47
  235. package/dist/definitions-DUE5gmdn.mjs +0 -18
  236. package/dist/definitions-DYVjOtxa.mjs +0 -26
  237. package/dist/definitions-DcYLVLCo.mjs +0 -37
  238. package/dist/definitions-Pp5LI2H4.mjs +0 -27
  239. package/dist/definitions-j9KdHVNR.mjs +0 -14
  240. package/dist/definitions-uzkjBwa7.mjs +0 -258
  241. package/dist/definitions-va-AnLuQ.mjs +0 -28
  242. package/dist/encoding-DJeqHmpd.mjs +0 -1079
  243. package/dist/evidence-graph-bridge-DcYizFk2.mjs +0 -136
  244. package/dist/factory-C90tBff6.mjs +0 -575
  245. package/dist/flat-target-session-Dgax2Cy3.mjs +0 -29
  246. package/dist/formatAddress-nnMvEohD.mjs +0 -17
  247. package/dist/graphql-CoHrhweh.mjs +0 -1197
  248. package/dist/handlers-4jmR0nMs.mjs +0 -898
  249. package/dist/handlers-BAHPxcch.mjs +0 -789
  250. package/dist/handlers-BOs9b907.mjs +0 -2600
  251. package/dist/handlers-BWXEy6ef.mjs +0 -917
  252. package/dist/handlers-Bndn6QvE.mjs +0 -111
  253. package/dist/handlers-BqC4bD4s.mjs +0 -681
  254. package/dist/handlers-BtYq60bM2.mjs +0 -276
  255. package/dist/handlers-BzgcB4iv.mjs +0 -799
  256. package/dist/handlers-CRyRWj2b.mjs +0 -859
  257. package/dist/handlers-CVv2H1uq.mjs +0 -592
  258. package/dist/handlers-Dl5a7JS4.mjs +0 -572
  259. package/dist/handlers-Dx2d7jt7.mjs +0 -2537
  260. package/dist/handlers-HujRKC3b.mjs +0 -661
  261. package/dist/handlers.impl-XWXkQfyi.mjs +0 -807
  262. package/dist/hooks-B1B8NRHL.mjs +0 -898
  263. package/dist/logger-Dh_xb7_2.mjs +0 -93
  264. package/dist/maintenance-PRMkLVRW.mjs +0 -835
  265. package/dist/manifest-67Bok-Si.mjs +0 -58
  266. package/dist/manifest-6lNTMZAB2.mjs +0 -87
  267. package/dist/manifest-B2duEHiH.mjs +0 -90
  268. package/dist/manifest-B6EY9Vm8.mjs +0 -57
  269. package/dist/manifest-B6nKSbyY.mjs +0 -95
  270. package/dist/manifest-BL8AQNPF.mjs +0 -106
  271. package/dist/manifest-BSZvJJmV.mjs +0 -47
  272. package/dist/manifest-BU7qzUyX.mjs +0 -418
  273. package/dist/manifest-Bl62e8WK.mjs +0 -49
  274. package/dist/manifest-Bo5cXjdt.mjs +0 -82
  275. package/dist/manifest-BpS4gtUK.mjs +0 -1347
  276. package/dist/manifest-Bv65_e2W.mjs +0 -101
  277. package/dist/manifest-BytNIF4Z.mjs +0 -117
  278. package/dist/manifest-C-xtsjS3.mjs +0 -81
  279. package/dist/manifest-CDYl7OhA.mjs +0 -66
  280. package/dist/manifest-CRZ3xmkD.mjs +0 -61
  281. package/dist/manifest-CoW6u4Tp.mjs +0 -132
  282. package/dist/manifest-Cq5zN_8A.mjs +0 -50
  283. package/dist/manifest-D7YZM_2e.mjs +0 -194
  284. package/dist/manifest-DE_VrAeQ.mjs +0 -314
  285. package/dist/manifest-DGsXSCpT.mjs +0 -39
  286. package/dist/manifest-DJ2vfEuW.mjs +0 -156
  287. package/dist/manifest-DPXDYhEu.mjs +0 -80
  288. package/dist/manifest-Dd4fQb0a.mjs +0 -322
  289. package/dist/manifest-Deq6opGg.mjs +0 -223
  290. package/dist/manifest-DfJTafJK.mjs +0 -37
  291. package/dist/manifest-DgOdgN_j.mjs +0 -50
  292. package/dist/manifest-DlbMW4v4.mjs +0 -47
  293. package/dist/manifest-DmVfbH0w.mjs +0 -374
  294. package/dist/manifest-Dog6Ddjr.mjs +0 -109
  295. package/dist/manifest-DvgU5FWb.mjs +0 -58
  296. package/dist/manifest-HsfDBs7j.mjs +0 -50
  297. package/dist/manifest-I8oQHvCG.mjs +0 -186
  298. package/dist/manifest-NvH_a-av.mjs +0 -786
  299. package/dist/manifest-cEJU1v0Z.mjs +0 -129
  300. package/dist/manifest-wOl5XLB12.mjs +0 -112
  301. package/dist/modules-tZozf0LQ.mjs +0 -10635
  302. package/dist/mojo-ipc-DXNEXEqb.mjs +0 -640
  303. package/dist/network-CPVvwvFg.mjs +0 -3852
  304. package/dist/outputPaths-um7lCRY3.mjs +0 -1141
  305. package/dist/parse-args-B4cY5Vx5.mjs +0 -39
  306. package/dist/platform-CYeFoTWp.mjs +0 -2161
  307. package/dist/process-BTbgcVc6.mjs +0 -1306
  308. package/dist/proxy-r8YN6nP1.mjs +0 -192
  309. package/dist/registry-Bl8ZQW61.mjs +0 -34
  310. package/dist/response-CWhh2aLo.mjs +0 -34
  311. package/dist/shared-state-board-BoZnSoj-.mjs +0 -586
  312. package/dist/sourcemap-BIDHUVXy.mjs +0 -934
  313. package/dist/ssrf-policy-Dsqd-DTX.mjs +0 -166
  314. package/dist/streaming-Dal6utPp.mjs +0 -725
  315. package/dist/tool-builder-BHJp32mV.mjs +0 -186
  316. package/dist/transform-DRVgGG90.mjs +0 -1011
  317. package/dist/types-Bx92KJfT.mjs +0 -4
  318. package/dist/types-DDBWs9UP.mjs +0 -37
  319. package/dist/wasm-BYx5UOeG.mjs +0 -1044
  320. package/dist/webcrack-Be0_FccV.mjs +0 -747
  321. package/dist/workflow-BpuKEtvn.mjs +0 -725
@@ -1,721 +0,0 @@
1
- import { t as __exportAll } from "./chunk-CjcI7cDX.mjs";
2
- import { t as logger } from "./logger-Dh_xb7_2.mjs";
3
- import { t as allTools } from "./ToolCatalog-5OJdMiF0.mjs";
4
- import { t as INSTALLED_EXTENSION_METADATA_FILENAME } from "./types-Bx92KJfT.mjs";
5
- import { createHash } from "node:crypto";
6
- import { existsSync, readFileSync } from "node:fs";
7
- import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
8
- import { fileURLToPath, pathToFileURL } from "node:url";
9
- import { readFile } from "node:fs/promises";
10
- import { glob } from "tinyglobby";
11
- //#region src/server/extensions/ExtensionManager.roots.ts
12
- /**
13
- * Extension path resolution — root directories for plugins and workflows.
14
- */
15
- /**
16
- * Walk up the directory tree from the given start to find the project root
17
- * (the nearest ancestor that contains a package.json).
18
- *
19
- * This is robust across both dev (`src/server/extensions/`) and production
20
- * (`dist/src/server/extensions/`) layouts — no hard-coded level count needed.
21
- */
22
- function findProjectRoot(startDir) {
23
- let dir = startDir;
24
- while (true) {
25
- if (existsSync(join(dir, "package.json"))) return dir;
26
- const parent = dirname(dir);
27
- if (parent === dir) break;
28
- dir = parent;
29
- }
30
- return resolve(startDir, "..", "..", "..", "..");
31
- }
32
- const EXTENSION_INSTALL_ROOT = findProjectRoot(fileURLToPath(new URL(".", import.meta.url)));
33
- const DEFAULT_PLUGIN_ROOTS = [join(EXTENSION_INSTALL_ROOT, "plugins")];
34
- const DEFAULT_WORKFLOW_ROOTS = [join(EXTENSION_INSTALL_ROOT, "workflows")];
35
- function parseRoots(raw, fallback) {
36
- const value = raw?.trim();
37
- if (!value) return fallback;
38
- const roots = value.split(",").map((item) => item.trim()).filter(Boolean);
39
- return roots.length > 0 ? [...new Set(roots)] : fallback;
40
- }
41
- function resolveRoots(roots, baseDir = EXTENSION_INSTALL_ROOT) {
42
- const resolved = roots.map((root) => isAbsolute(root) ? root : resolve(baseDir, root));
43
- return [...new Set(resolved)].toSorted((a, b) => a.localeCompare(b));
44
- }
45
- //#endregion
46
- //#region src/server/extensions/ExtensionManager.version.ts
47
- /**
48
- * Semver parsing and compatibility checks for extension version constraints.
49
- */
50
- function parseVersionParts(version) {
51
- const match = version.trim().match(/^(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/);
52
- if (!match) return null;
53
- return [
54
- Number(match[1]),
55
- Number(match[2]),
56
- Number(match[3])
57
- ];
58
- }
59
- function compareVersion(a, b) {
60
- const aa = parseVersionParts(a);
61
- const bb = parseVersionParts(b);
62
- if (!aa || !bb) return null;
63
- const [aMajor, aMinor, aPatch] = aa;
64
- const [bMajor, bMinor, bPatch] = bb;
65
- if (aMajor > bMajor) return 1;
66
- if (aMajor < bMajor) return -1;
67
- if (aMinor > bMinor) return 1;
68
- if (aMinor < bMinor) return -1;
69
- if (aPatch > bPatch) return 1;
70
- if (aPatch < bPatch) return -1;
71
- return 0;
72
- }
73
- function isCompatibleVersion(range, currentVersion) {
74
- const input = range.trim();
75
- if (!input || input === "*") return true;
76
- if (input.startsWith(">=")) {
77
- const cmp = compareVersion(currentVersion, input.slice(2).trim());
78
- return cmp !== null && cmp >= 0;
79
- }
80
- if (input.startsWith("^")) {
81
- const base = input.slice(1).trim();
82
- const cc = parseVersionParts(currentVersion);
83
- const bb = parseVersionParts(base);
84
- if (!cc || !bb) return false;
85
- const cmp = compareVersion(currentVersion, base);
86
- return cmp !== null && cmp >= 0 && cc[0] === bb[0];
87
- }
88
- if (input.startsWith("~")) {
89
- const base = input.slice(1).trim();
90
- const cc = parseVersionParts(currentVersion);
91
- const bb = parseVersionParts(base);
92
- if (!cc || !bb) return false;
93
- const cmp = compareVersion(currentVersion, base);
94
- return cmp !== null && cmp >= 0 && cc[0] === bb[0] && cc[1] === bb[1];
95
- }
96
- const cmp = compareVersion(currentVersion, input);
97
- return cmp !== null && cmp === 0;
98
- }
99
- //#endregion
100
- //#region src/server/extensions/ExtensionManager.integrity.ts
101
- /**
102
- * Plugin integrity verification — digest allowlists, env guards, compatibility checks.
103
- */
104
- async function sha256Hex(filePath) {
105
- const content = await readFile(filePath);
106
- return createHash("sha256").update(content).digest("hex");
107
- }
108
- function normalizeHex(value) {
109
- return value.trim().toLowerCase().replace(/^0x/, "");
110
- }
111
- function isTruthyEnv(value) {
112
- return ["1", "true"].includes(value.toLowerCase());
113
- }
114
- function isPluginSignatureRequired() {
115
- const raw = process.env.MCP_PLUGIN_SIGNATURE_REQUIRED;
116
- if (raw === void 0 || raw.trim() === "") return process.env.NODE_ENV === "production";
117
- return isTruthyEnv(raw);
118
- }
119
- function isPluginStrictLoad() {
120
- const raw = process.env.MCP_PLUGIN_STRICT_LOAD;
121
- if (raw === void 0 || raw.trim() === "") return isPluginSignatureRequired();
122
- return isTruthyEnv(raw) || isPluginSignatureRequired();
123
- }
124
- function parseDigestAllowlist(raw) {
125
- const value = raw?.trim();
126
- if (!value) return /* @__PURE__ */ new Set();
127
- return new Set(value.split(",").map((item) => normalizeHex(item)).filter((item) => item.length > 0));
128
- }
129
- async function verifyPluginIntegrity(plugin, currentVersion) {
130
- const errors = [];
131
- const warnings = [];
132
- if (!isCompatibleVersion(plugin.compatibleCoreRange, currentVersion)) errors.push(`Plugin ${plugin.id} incompatible with core ${currentVersion}; requires ${plugin.compatibleCoreRange}`);
133
- return {
134
- ok: errors.length === 0,
135
- errors,
136
- warnings
137
- };
138
- }
139
- //#endregion
140
- //#region src/server/extensions/ExtensionManager.guards.ts
141
- function isExtensionBuilder(value) {
142
- if (!value || typeof value !== "object") return false;
143
- const candidate = value;
144
- return !!(typeof candidate.id === "string" && typeof candidate.version === "string" && Array.isArray(candidate.tools) && (candidate.workflows === void 0 || Array.isArray(candidate.workflows)));
145
- }
146
- function isWorkflowContract(value) {
147
- if (!value || typeof value !== "object") return false;
148
- const candidate = value;
149
- return !!(candidate.kind === "workflow-contract" && candidate.version === 1 && typeof candidate.id === "string" && typeof candidate.displayName === "string" && typeof candidate.build === "function");
150
- }
151
- //#endregion
152
- //#region src/server/extensions/ExtensionManager.discovery.ts
153
- /**
154
- * Extension file discovery — prefers installed registry metadata, then falls back
155
- * to scanning plugin/workflow roots for legacy manifest files.
156
- */
157
- function isJavaScriptLikeFile(file) {
158
- return file.endsWith(".js") || file.endsWith(".mjs") || file.endsWith(".cjs");
159
- }
160
- function isTypeScriptLikeFile(file) {
161
- return file.endsWith(".ts") || file.endsWith(".mts") || file.endsWith(".cts");
162
- }
163
- async function collectMatchingFiles(roots, matcher) {
164
- const files = /* @__PURE__ */ new Set();
165
- for (const root of roots) {
166
- let matchedPaths;
167
- try {
168
- matchedPaths = await glob("**/*", {
169
- cwd: root,
170
- absolute: true,
171
- onlyFiles: true,
172
- dot: true,
173
- ignore: [
174
- "**/node_modules/**",
175
- "**/.git/**",
176
- "**/.pnpm/**"
177
- ]
178
- });
179
- } catch {
180
- continue;
181
- }
182
- for (const file of matchedPaths) if (matcher(basename(file))) files.add(file);
183
- }
184
- return [...files].toSorted((a, b) => a.localeCompare(b));
185
- }
186
- function normalizeExtensionCandidateKey(root, file) {
187
- const normalizedRoot = root.replace(/\\/g, "/").replace(/\/+/g, "/").replace(/^\/+|\/+$/g, "").toLowerCase();
188
- const relDir = relative(root, dirname(file)).replace(/^[/\\]+/, "").replace(/\\/g, "/").replace(/\/+/g, "/").replace(/^\/+|\/+$/g, "").toLowerCase();
189
- if (!relDir || relDir === "dist") return `${normalizedRoot}::`;
190
- return `${normalizedRoot}::${relDir.endsWith("/dist") ? relDir.slice(0, -5) : relDir}`;
191
- }
192
- function extensionRank(candidate) {
193
- if (candidate.isJs) return 0;
194
- if (candidate.isTs) return 1;
195
- return 2;
196
- }
197
- function isInstalledExtensionMetadata(value, kind) {
198
- if (!value || typeof value !== "object") return false;
199
- const record = value;
200
- if (record.version !== 1 || record.kind !== kind) return false;
201
- if (typeof record.slug !== "string" || typeof record.id !== "string") return false;
202
- if (!record.source || typeof record.source !== "object") return false;
203
- const source = record.source;
204
- return typeof source.type === "string" && typeof source.repo === "string" && typeof source.ref === "string" && typeof source.commit === "string" && typeof source.subpath === "string" && typeof source.entry === "string";
205
- }
206
- async function collectInstalledEntryCandidates(roots, kind) {
207
- const candidates = [];
208
- for (const [rootIndex, root] of roots.entries()) {
209
- const metadataFiles = await collectMatchingFiles([root], (filename) => filename === INSTALLED_EXTENSION_METADATA_FILENAME);
210
- for (const metadataFile of metadataFiles) {
211
- let metadataRaw;
212
- try {
213
- metadataRaw = JSON.parse(await readFile(metadataFile, "utf8"));
214
- } catch {
215
- continue;
216
- }
217
- if (!isInstalledExtensionMetadata(metadataRaw, kind)) continue;
218
- const entryPath = metadataRaw.source.entry.trim();
219
- if (!entryPath) continue;
220
- const file = resolve(dirname(metadataFile), entryPath);
221
- if (!existsSync(file)) continue;
222
- candidates.push({
223
- file,
224
- key: normalizeExtensionCandidateKey(root, file),
225
- isJs: isJavaScriptLikeFile(file),
226
- isTs: isTypeScriptLikeFile(file),
227
- rootIndex,
228
- priority: 0
229
- });
230
- }
231
- }
232
- return candidates;
233
- }
234
- function deduplicateCandidates(candidates) {
235
- const byKey = /* @__PURE__ */ new Map();
236
- for (const candidate of candidates.toSorted((a, b) => a.file.localeCompare(b.file))) {
237
- const existing = byKey.get(candidate.key);
238
- if (!existing) {
239
- byKey.set(candidate.key, candidate);
240
- continue;
241
- }
242
- const existingRoot = existing.rootIndex;
243
- const candidateRoot = candidate.rootIndex;
244
- const existingPriority = existing.priority;
245
- const candidatePriority = candidate.priority;
246
- const existingExtRank = extensionRank(existing);
247
- const candidateExtRank = extensionRank(candidate);
248
- if (candidateRoot < existingRoot || candidateRoot === existingRoot && candidatePriority < existingPriority || candidateRoot === existingRoot && candidatePriority === existingPriority && candidateExtRank < existingExtRank || candidateRoot === existingRoot && candidatePriority === existingPriority && candidateExtRank === existingExtRank && candidate.file.localeCompare(existing.file) < 0) byKey.set(candidate.key, candidate);
249
- }
250
- return [...byKey.values()].map((item) => item.file).toSorted((a, b) => a.localeCompare(b));
251
- }
252
- async function discoverPluginFiles(pluginRoots) {
253
- const candidates = await collectInstalledEntryCandidates(pluginRoots, "plugin");
254
- for (const [rootIndex, root] of pluginRoots.entries()) {
255
- const files = await collectMatchingFiles([root], (filename) => filename === "manifest.js" || filename === "manifest.ts");
256
- for (const file of files) candidates.push({
257
- file,
258
- key: normalizeExtensionCandidateKey(root, file),
259
- isJs: isJavaScriptLikeFile(file),
260
- isTs: isTypeScriptLikeFile(file),
261
- rootIndex,
262
- priority: 1
263
- });
264
- }
265
- return deduplicateCandidates(candidates);
266
- }
267
- async function discoverWorkflowFiles(workflowRoots) {
268
- const candidates = await collectInstalledEntryCandidates(workflowRoots, "workflow");
269
- for (const [rootIndex, root] of workflowRoots.entries()) {
270
- const files = await collectMatchingFiles([root], (filename) => filename.endsWith(".workflow.js") || filename.endsWith(".workflow.mjs") || filename.endsWith(".workflow.cjs") || filename.endsWith(".workflow.ts") || filename.endsWith(".workflow.mts") || filename.endsWith(".workflow.cts") || filename === "workflow.js" || filename === "workflow.mjs" || filename === "workflow.cjs" || filename === "workflow.ts" || filename === "workflow.mts" || filename === "workflow.cts");
271
- for (const file of files) candidates.push({
272
- file,
273
- key: normalizeExtensionCandidateKey(root, file),
274
- isJs: isJavaScriptLikeFile(file),
275
- isTs: isTypeScriptLikeFile(file),
276
- rootIndex,
277
- priority: 1
278
- });
279
- }
280
- return deduplicateCandidates(candidates);
281
- }
282
- //#endregion
283
- //#region src/server/extensions/ExtensionManager.lifecycle.ts
284
- /**
285
- * Extension lifecycle helpers — import, cleanup, config extraction, list building.
286
- */
287
- function extractConfigValue(ctx, path, fallback) {
288
- const segments = path.split(".").filter(Boolean);
289
- let current = ctx.config;
290
- for (const segment of segments) {
291
- if (!current || typeof current !== "object") return fallback;
292
- current = current[segment];
293
- }
294
- return current ?? fallback;
295
- }
296
- function createFreshImportUrl(modulePath, kind) {
297
- const moduleUrl = new URL(pathToFileURL(modulePath).href);
298
- moduleUrl.searchParams.set("reloadTs", String(Date.now()));
299
- logger.debug(`[extensions] Loading fresh ${kind} module: ${modulePath}`);
300
- return moduleUrl.href;
301
- }
302
- async function clearLoadedExtensionTools(ctx) {
303
- let removed = 0;
304
- for (const [pluginId, runtime] of ctx.extensionPluginRuntimeById.entries()) {
305
- try {
306
- if (runtime.plugin.onDeactivateHandler && runtime.state === "activated") {
307
- await runtime.plugin.onDeactivateHandler(runtime.lifecycleContext);
308
- runtime.state = "deactivated";
309
- }
310
- } catch (error) {
311
- logger.warn(`Plugin onDeactivate failed for "${pluginId}":`, error);
312
- }
313
- try {
314
- if (runtime.plugin.onDeactivateHandler) runtime.state = "unloaded";
315
- } catch (error) {
316
- logger.warn(`Plugin onUnload failed for "${pluginId}":`, error);
317
- }
318
- }
319
- for (const record of ctx.extensionToolsByName.values()) {
320
- try {
321
- record.registeredTool?.remove();
322
- } catch (error) {
323
- logger.warn(`Failed to remove extension tool "${record.name}":`, error);
324
- }
325
- ctx.router.removeHandler(record.name);
326
- ctx.activatedToolNames.delete(record.name);
327
- ctx.activatedRegisteredTools.delete(record.name);
328
- removed++;
329
- }
330
- ctx.extensionToolsByName.clear();
331
- ctx.extensionPluginsById.clear();
332
- ctx.extensionPluginRuntimeById.clear();
333
- ctx.extensionWorkflowsById.clear();
334
- ctx.extensionWorkflowRuntimeById.clear();
335
- return removed;
336
- }
337
- function buildListResult(ctx, pluginRoots, workflowRoots) {
338
- return {
339
- pluginRoots,
340
- workflowRoots,
341
- pluginCount: ctx.extensionPluginsById.size,
342
- workflowCount: ctx.extensionWorkflowsById.size,
343
- toolCount: ctx.extensionToolsByName.size,
344
- lastReloadAt: ctx.lastExtensionReloadAt,
345
- plugins: [...ctx.extensionPluginsById.values()],
346
- workflows: [...ctx.extensionWorkflowsById.values()],
347
- tools: [...ctx.extensionToolsByName.values()].map((record) => ({
348
- name: record.name,
349
- domain: record.domain,
350
- source: record.source
351
- }))
352
- };
353
- }
354
- //#endregion
355
- //#region src/server/extensions/ExtensionManager.ts
356
- var ExtensionManager_exports = /* @__PURE__ */ __exportAll({
357
- ensureWorkflowsLoaded: () => ensureWorkflowsLoaded,
358
- listExtensions: () => listExtensions,
359
- reloadExtensions: () => reloadExtensions
360
- });
361
- function listExtensions(ctx) {
362
- return buildListResult(ctx, resolveRoots(parseRoots(process.env.MCP_PLUGIN_ROOTS, DEFAULT_PLUGIN_ROOTS)), resolveRoots(parseRoots(process.env.MCP_WORKFLOW_ROOTS, DEFAULT_WORKFLOW_ROOTS)));
363
- }
364
- /**
365
- * Parse a flat key: value YAML file (no nesting, no arrays).
366
- * Returns a Record<string, string> of trimmed key/value pairs.
367
- * Returns empty object on any error (file missing, malformed, etc.).
368
- */
369
- function parseSimpleYaml(filePath) {
370
- try {
371
- const text = readFileSync(filePath, "utf-8");
372
- const result = {};
373
- for (const line of text.split(/\r?\n/)) {
374
- const trimmed = line.trim();
375
- if (!trimmed || trimmed.startsWith("#")) continue;
376
- const colonIdx = trimmed.indexOf(":");
377
- if (colonIdx < 1) continue;
378
- const key = trimmed.slice(0, colonIdx).trim();
379
- const value = trimmed.slice(colonIdx + 1).trim();
380
- if (key) result[key] = value;
381
- }
382
- return result;
383
- } catch {
384
- return {};
385
- }
386
- }
387
- function findInstalledMetadataRoot(startDir) {
388
- let currentDir = startDir;
389
- while (true) {
390
- if (existsSync(join(currentDir, ".jshook-install.json"))) return currentDir;
391
- const parentDir = dirname(currentDir);
392
- if (parentDir === currentDir) return null;
393
- currentDir = parentDir;
394
- }
395
- }
396
- function resolvePluginProjectRoot(pluginFile) {
397
- const entryDir = dirname(pluginFile);
398
- const metadataRoot = findInstalledMetadataRoot(entryDir);
399
- if (metadataRoot) return metadataRoot;
400
- if (basename(entryDir).toLowerCase() === "dist") return dirname(entryDir);
401
- return entryDir;
402
- }
403
- let reloadMutex = Promise.resolve();
404
- const lazyWorkflowLoadAttempted = /* @__PURE__ */ new WeakSet();
405
- const STRICT_PLUGIN_ALLOWLIST_ERROR = "MCP_PLUGIN_ALLOWED_DIGESTS is required when MCP_PLUGIN_SIGNATURE_REQUIRED=true or MCP_PLUGIN_STRICT_LOAD=true. The digest allowlist is the only pre-import trust boundary — without it, plugin code executes before integrity verification. No plugins will be loaded.";
406
- const MISSING_PLUGIN_ALLOWLIST_WARNING = "[extensions] Loading plugins WITHOUT MCP_PLUGIN_ALLOWED_DIGESTS allowlist. Plugin code will execute on import() before post-load integrity checks. Set MCP_PLUGIN_STRICT_LOAD=true to enforce allowlist requirement.";
407
- async function withReloadMutex(operation) {
408
- const prev = reloadMutex;
409
- let resolve;
410
- reloadMutex = new Promise((r) => {
411
- resolve = r;
412
- });
413
- await prev;
414
- try {
415
- return await operation();
416
- } finally {
417
- resolve();
418
- }
419
- }
420
- async function reloadExtensions(ctx) {
421
- return withReloadMutex(() => reloadExtensionsInner(ctx));
422
- }
423
- async function ensureWorkflowsLoaded(ctx) {
424
- if (ctx.extensionWorkflowRuntimeById.size > 0 || lazyWorkflowLoadAttempted.has(ctx)) return;
425
- await withReloadMutex(async () => {
426
- if (ctx.extensionWorkflowRuntimeById.size > 0 || lazyWorkflowLoadAttempted.has(ctx)) return;
427
- lazyWorkflowLoadAttempted.add(ctx);
428
- const warnings = [];
429
- const errors = [];
430
- const pluginRoots = resolveRoots(parseRoots(process.env.MCP_PLUGIN_ROOTS, DEFAULT_PLUGIN_ROOTS));
431
- const workflowRoots = resolveRoots(parseRoots(process.env.MCP_WORKFLOW_ROOTS, DEFAULT_WORKFLOW_ROOTS));
432
- await loadPluginWorkflowContributions(ctx, pluginRoots, warnings, errors);
433
- await loadWorkflows(ctx, await discoverWorkflowFiles(workflowRoots), warnings, errors);
434
- for (const warning of warnings) logger.warn(`[extensions] ${warning}`);
435
- for (const error of errors) logger.error(`[extensions] ${error}`);
436
- });
437
- }
438
- async function loadWorkflows(ctx, workflowFiles, warnings, errors) {
439
- for (const workflowFile of workflowFiles) try {
440
- const mod = await import(createFreshImportUrl(workflowFile, "workflow"));
441
- const candidate = mod.default ?? mod;
442
- if (!isWorkflowContract(candidate)) {
443
- warnings.push(`Skip workflow file without valid WorkflowContract: ${workflowFile}`);
444
- continue;
445
- }
446
- registerWorkflowContract(ctx, candidate, workflowFile, warnings);
447
- } catch (error) {
448
- errors.push(`Failed to import workflow file ${workflowFile}: ${String(error)}`);
449
- }
450
- }
451
- function registerWorkflowContract(ctx, workflow, source, warnings) {
452
- if (ctx.extensionWorkflowsById.has(workflow.id)) {
453
- warnings.push(`Skip workflow "${workflow.id}" from ${source}: duplicate id`);
454
- return false;
455
- }
456
- const record = {
457
- id: workflow.id,
458
- displayName: workflow.displayName,
459
- source,
460
- description: workflow.description,
461
- tags: workflow.tags,
462
- timeoutMs: workflow.timeoutMs,
463
- defaultMaxConcurrency: workflow.defaultMaxConcurrency,
464
- route: workflow.route
465
- };
466
- ctx.extensionWorkflowsById.set(record.id, record);
467
- const runtimeRecord = {
468
- workflow,
469
- source,
470
- route: workflow.route
471
- };
472
- ctx.extensionWorkflowRuntimeById.set(record.id, runtimeRecord);
473
- return true;
474
- }
475
- function buildPluginRecord(plugin, pluginFile, loadedTools, loadedWorkflows) {
476
- return {
477
- id: plugin.id,
478
- name: plugin.pluginName,
479
- source: pluginFile,
480
- author: plugin.pluginAuthor || void 0,
481
- sourceRepo: plugin.pluginSourceRepo || void 0,
482
- domains: [],
483
- workflows: loadedWorkflows,
484
- tools: loadedTools
485
- };
486
- }
487
- async function loadPluginWorkflowContributions(ctx, pluginRoots, warnings, errors) {
488
- const allowedDigests = parseDigestAllowlist(process.env.MCP_PLUGIN_ALLOWED_DIGESTS);
489
- if (isPluginStrictLoad() && allowedDigests.size === 0) {
490
- errors.push(STRICT_PLUGIN_ALLOWLIST_ERROR);
491
- logger.error("[extensions] " + STRICT_PLUGIN_ALLOWLIST_ERROR);
492
- return;
493
- }
494
- if (allowedDigests.size === 0) logger.warn(MISSING_PLUGIN_ALLOWLIST_WARNING);
495
- const pluginFiles = await discoverPluginFiles(pluginRoots);
496
- const coreVersion = ctx.config?.mcp?.version ?? "0.0.0";
497
- for (const pluginFile of pluginFiles) {
498
- let fileDigest;
499
- try {
500
- fileDigest = normalizeHex(await sha256Hex(pluginFile));
501
- if (allowedDigests.size > 0 && !allowedDigests.has(fileDigest)) {
502
- warnings.push(`Skip plugin file not in MCP_PLUGIN_ALLOWED_DIGESTS allowlist: ${pluginFile}`);
503
- continue;
504
- }
505
- } catch (error) {
506
- errors.push(`Failed to hash plugin file ${pluginFile}: ${String(error)}`);
507
- continue;
508
- }
509
- let plugin;
510
- try {
511
- const mod = await import(createFreshImportUrl(pluginFile, "plugin"));
512
- const candidate = mod.default ?? mod;
513
- if (!isExtensionBuilder(candidate)) {
514
- warnings.push(`Skip plugin file without valid ExtensionBuilder: ${pluginFile}`);
515
- continue;
516
- }
517
- plugin = candidate;
518
- } catch (error) {
519
- errors.push(`Failed to import plugin file ${pluginFile}: ${String(error)}`);
520
- continue;
521
- }
522
- const meta = parseSimpleYaml(join(resolvePluginProjectRoot(pluginFile), "meta.yaml"));
523
- plugin.mergeMetadata(meta);
524
- if (ctx.extensionPluginsById.has(plugin.id)) {
525
- warnings.push(`Skip plugin "${plugin.id}" from ${pluginFile}: duplicate plugin id`);
526
- continue;
527
- }
528
- try {
529
- const verification = await verifyPluginIntegrity(plugin, coreVersion);
530
- warnings.push(...verification.warnings);
531
- if (!verification.ok) {
532
- errors.push(...verification.errors);
533
- continue;
534
- }
535
- } catch (error) {
536
- errors.push(`Failed to verify plugin ${plugin.id}: ${String(error)}`);
537
- continue;
538
- }
539
- const loadedWorkflows = [];
540
- const pluginWorkflows = Array.isArray(plugin.workflows) ? plugin.workflows : [];
541
- for (const candidate of pluginWorkflows) {
542
- if (!isWorkflowContract(candidate)) {
543
- warnings.push(`Skip invalid workflow contribution from plugin "${plugin.id}" in ${pluginFile}`);
544
- continue;
545
- }
546
- if (registerWorkflowContract(ctx, candidate, `${pluginFile}#workflow:${candidate.id}`, warnings)) loadedWorkflows.push(candidate.id);
547
- }
548
- if (loadedWorkflows.length === 0) continue;
549
- ctx.extensionPluginsById.set(plugin.id, buildPluginRecord(plugin, pluginFile, [], loadedWorkflows));
550
- }
551
- }
552
- async function reloadExtensionsInner(ctx) {
553
- const warnings = [];
554
- const errors = [];
555
- const removedTools = await clearLoadedExtensionTools(ctx);
556
- const pluginRoots = resolveRoots(parseRoots(process.env.MCP_PLUGIN_ROOTS, DEFAULT_PLUGIN_ROOTS));
557
- const workflowRoots = resolveRoots(parseRoots(process.env.MCP_WORKFLOW_ROOTS, DEFAULT_WORKFLOW_ROOTS));
558
- const allowedDigests = parseDigestAllowlist(process.env.MCP_PLUGIN_ALLOWED_DIGESTS);
559
- if (isPluginStrictLoad() && allowedDigests.size === 0) {
560
- const msg = STRICT_PLUGIN_ALLOWLIST_ERROR;
561
- errors.push(msg);
562
- logger.error("[extensions] " + msg);
563
- await loadWorkflows(ctx, await discoverWorkflowFiles(workflowRoots), warnings, errors);
564
- ctx.lastExtensionReloadAt = (/* @__PURE__ */ new Date()).toISOString();
565
- return {
566
- ...buildListResult(ctx, pluginRoots, workflowRoots),
567
- addedTools: 0,
568
- removedTools,
569
- warnings,
570
- errors
571
- };
572
- }
573
- if (allowedDigests.size === 0) logger.warn(MISSING_PLUGIN_ALLOWLIST_WARNING);
574
- const baseToolNames = new Set(allTools.map((tool) => tool.name));
575
- const pluginFiles = await discoverPluginFiles(pluginRoots);
576
- const coreVersion = ctx.config?.mcp?.version ?? "0.0.0";
577
- for (const pluginFile of pluginFiles) {
578
- let fileDigest;
579
- try {
580
- fileDigest = normalizeHex(await sha256Hex(pluginFile));
581
- if (allowedDigests.size > 0 && !allowedDigests.has(fileDigest)) {
582
- warnings.push(`Skip plugin file not in MCP_PLUGIN_ALLOWED_DIGESTS allowlist: ${pluginFile}`);
583
- continue;
584
- }
585
- } catch (error) {
586
- errors.push(`Failed to hash plugin file ${pluginFile}: ${String(error)}`);
587
- continue;
588
- }
589
- let plugin;
590
- try {
591
- const mod = await import(createFreshImportUrl(pluginFile, "plugin"));
592
- const candidate = mod.default ?? mod;
593
- if (!isExtensionBuilder(candidate)) {
594
- warnings.push(`Skip plugin file without valid ExtensionBuilder: ${pluginFile}`);
595
- continue;
596
- }
597
- plugin = candidate;
598
- } catch (error) {
599
- errors.push(`Failed to import plugin file ${pluginFile}: ${String(error)}`);
600
- continue;
601
- }
602
- const pluginProjectRoot = resolvePluginProjectRoot(pluginFile);
603
- const meta = parseSimpleYaml(join(pluginProjectRoot, "meta.yaml"));
604
- plugin.mergeMetadata(meta);
605
- if (ctx.extensionPluginsById.has(plugin.id)) {
606
- warnings.push(`Skip plugin "${plugin.id}" from ${pluginFile}: duplicate plugin id`);
607
- continue;
608
- }
609
- try {
610
- const verification = await verifyPluginIntegrity(plugin, coreVersion);
611
- warnings.push(...verification.warnings);
612
- if (!verification.ok) {
613
- errors.push(...verification.errors);
614
- continue;
615
- }
616
- } catch (error) {
617
- errors.push(`Failed to verify plugin ${plugin.id}: ${String(error)}`);
618
- continue;
619
- }
620
- const runtimeData = /* @__PURE__ */ new Map();
621
- const metrics = /* @__PURE__ */ new Set();
622
- let pluginState = "loaded";
623
- const allowInvokeAll = plugin.allowedTools.includes("*");
624
- const lifecycleContext = {
625
- pluginId: plugin.id,
626
- pluginRoot: pluginProjectRoot,
627
- config: ctx.config,
628
- get state() {
629
- return pluginState;
630
- },
631
- registerMetric(metricName) {
632
- metrics.add(metricName);
633
- },
634
- async invokeTool(name, args = {}) {
635
- if (typeof name !== "string" || name.length === 0) throw new Error("invokeTool requires a non-empty tool name");
636
- if (!allowInvokeAll && !plugin.allowedTools.includes(name)) throw new Error(`Plugin "${plugin.id}" is not allowed to invoke "${name}". Declare it in allowTool calls.`);
637
- if (!baseToolNames.has(name)) throw new Error(`Plugin "${plugin.id}" can only invoke built-in tools. "${name}" is not built-in.`);
638
- if (!ctx.router.has(name)) throw new Error(`Tool "${name}" is not available in the current active profile.`);
639
- return ctx.executeToolWithTracking(name, args ?? {});
640
- },
641
- hasPermission(_capability) {
642
- return true;
643
- },
644
- getConfig(path, fallback) {
645
- return extractConfigValue(ctx, path, fallback);
646
- },
647
- setRuntimeData(key, value) {
648
- runtimeData.set(key, value);
649
- },
650
- getRuntimeData(key) {
651
- return runtimeData.get(key);
652
- }
653
- };
654
- const runtimeRecord = {
655
- plugin,
656
- lifecycleContext,
657
- state: pluginState,
658
- source: pluginFile
659
- };
660
- try {
661
- if (plugin.onLoadHandler) await plugin.onLoadHandler(lifecycleContext);
662
- pluginState = "loaded";
663
- runtimeRecord.state = pluginState;
664
- if (plugin.onValidateHandler) {
665
- const validation = await plugin.onValidateHandler(lifecycleContext);
666
- if (!validation.valid) {
667
- warnings.push(`Plugin ${plugin.id} validation failed: ${validation.errors.join("; ")}`);
668
- continue;
669
- }
670
- pluginState = "validated";
671
- runtimeRecord.state = pluginState;
672
- }
673
- if (plugin.onActivateHandler) {
674
- await plugin.onActivateHandler(lifecycleContext);
675
- pluginState = "activated";
676
- runtimeRecord.state = pluginState;
677
- }
678
- ctx.extensionPluginRuntimeById.set(plugin.id, runtimeRecord);
679
- } catch (error) {
680
- try {
681
- if (plugin.onDeactivateHandler && pluginState === "activated") {
682
- await plugin.onDeactivateHandler(lifecycleContext);
683
- pluginState = "deactivated";
684
- runtimeRecord.state = pluginState;
685
- }
686
- } catch (deactivateError) {
687
- logger.warn(`Plugin onDeactivate failed during rollback for ${plugin.id}:`, deactivateError);
688
- }
689
- errors.push(`Plugin lifecycle failed for ${plugin.id}: ${String(error)}`);
690
- continue;
691
- }
692
- const loadedTools = plugin.tools.map((t) => t.name);
693
- const loadedWorkflows = [];
694
- const pluginWorkflows = Array.isArray(plugin.workflows) ? plugin.workflows : [];
695
- for (const candidate of pluginWorkflows) {
696
- if (!isWorkflowContract(candidate)) {
697
- warnings.push(`Skip invalid workflow contribution from plugin "${plugin.id}" in ${pluginFile}`);
698
- continue;
699
- }
700
- if (registerWorkflowContract(ctx, candidate, `${pluginFile}#workflow:${candidate.id}`, warnings)) loadedWorkflows.push(candidate.id);
701
- }
702
- const record = buildPluginRecord(plugin, pluginFile, loadedTools, loadedWorkflows);
703
- ctx.extensionPluginsById.set(record.id, record);
704
- }
705
- await loadWorkflows(ctx, await discoverWorkflowFiles(workflowRoots), warnings, errors);
706
- if (ctx.extensionToolsByName.size > 0 || removedTools > 0) try {
707
- await ctx.server.sendToolListChanged();
708
- } catch (error) {
709
- logger.warn("sendToolListChanged failed after extension reload:", error);
710
- }
711
- ctx.lastExtensionReloadAt = (/* @__PURE__ */ new Date()).toISOString();
712
- return {
713
- ...buildListResult(ctx, pluginRoots, workflowRoots),
714
- addedTools: ctx.extensionToolsByName.size,
715
- removedTools,
716
- warnings,
717
- errors
718
- };
719
- }
720
- //#endregion
721
- export { reloadExtensions as i, ensureWorkflowsLoaded as n, listExtensions as r, ExtensionManager_exports as t };