@jshookmcp/jshook 0.2.3 → 0.2.5

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 (385) hide show
  1. package/README.md +14 -5
  2. package/README.zh.md +18 -3
  3. package/dist/packages/extension-sdk/src/bridges/shared.js +2 -2
  4. package/dist/packages/extension-sdk/src/plugin.d.ts +5 -0
  5. package/dist/packages/extension-sdk/src/plugin.js +119 -33
  6. package/dist/packages/extension-sdk/src/workflow.d.ts +156 -0
  7. package/dist/packages/extension-sdk/src/workflow.js +236 -0
  8. package/dist/src/config/search-defaults.js +161 -0
  9. package/dist/src/constants.d.ts +3 -0
  10. package/dist/src/constants.js +4 -1
  11. package/dist/src/index.d.ts +1 -1
  12. package/dist/src/index.js +13 -17
  13. package/dist/src/modules/analyzer/CodeAnalyzer.d.ts +1 -3
  14. package/dist/src/modules/analyzer/CodeAnalyzer.js +16 -28
  15. package/dist/src/modules/analyzer/CodeAnalyzerDataFlow.d.ts +1 -2
  16. package/dist/src/modules/analyzer/CodeAnalyzerDataFlow.js +1 -45
  17. package/dist/src/modules/analyzer/IntelligentAnalyzer.d.ts +1 -37
  18. package/dist/src/modules/analyzer/IntelligentAnalyzer.js +9 -142
  19. package/dist/src/modules/analyzer/PatternDetector.js +3 -3
  20. package/dist/src/modules/analyzer/PatternDetectorAuthPatterns.js +1 -1
  21. package/dist/src/modules/browser/BrowserDiscovery.js +2 -2
  22. package/dist/src/modules/browser/BrowserModeManager.js +11 -10
  23. package/dist/src/modules/browser/TabRegistry.js +2 -2
  24. package/dist/src/modules/browser/UnifiedBrowserManager.d.ts +1 -0
  25. package/dist/src/modules/browser/UnifiedBrowserManager.js +18 -3
  26. package/dist/src/modules/captcha/AICaptchaDetector.d.ts +1 -10
  27. package/dist/src/modules/captcha/AICaptchaDetector.js +7 -201
  28. package/dist/src/modules/collector/CodeCollector.js +4 -5
  29. package/dist/src/modules/collector/DOMInspector.js +48 -58
  30. package/dist/src/modules/collector/PageController.d.ts +17 -4
  31. package/dist/src/modules/collector/PageController.js +2 -5
  32. package/dist/src/modules/collector/PageScriptCollectors.js +3 -3
  33. package/dist/src/modules/crypto/CryptoDetector.d.ts +1 -4
  34. package/dist/src/modules/crypto/CryptoDetector.js +2 -42
  35. package/dist/src/modules/crypto/CryptoRules.js +1 -1
  36. package/dist/src/modules/debugger/BlackboxManager.js +1 -1
  37. package/dist/src/modules/debugger/DebuggerManager.impl.core.scope.js +1 -1
  38. package/dist/src/modules/debugger/ScriptManager.impl.extract-function-tree.js +4 -2
  39. package/dist/src/modules/debugger/WatchExpressionManager.js +1 -1
  40. package/dist/src/modules/deobfuscator/Deobfuscator.d.ts +1 -4
  41. package/dist/src/modules/deobfuscator/Deobfuscator.js +4 -39
  42. package/dist/src/modules/deobfuscator/JSVMPDeobfuscator.d.ts +0 -3
  43. package/dist/src/modules/deobfuscator/JSVMPDeobfuscator.js +2 -8
  44. package/dist/src/modules/deobfuscator/JSVMPDeobfuscator.restore.d.ts +1 -2
  45. package/dist/src/modules/deobfuscator/JSVMPDeobfuscator.restore.js +3 -55
  46. package/dist/src/modules/deobfuscator/JScramblerDeobfuscator.js +3 -4
  47. package/dist/src/modules/deobfuscator/VMDeobfuscator.d.ts +2 -10
  48. package/dist/src/modules/deobfuscator/VMDeobfuscator.js +3 -128
  49. package/dist/src/modules/deobfuscator/webcrack.js +15 -2
  50. package/dist/src/modules/emulator/AIEnvironmentAnalyzer.d.ts +5 -8
  51. package/dist/src/modules/emulator/AIEnvironmentAnalyzer.js +10 -102
  52. package/dist/src/modules/emulator/EnvironmentEmulator.d.ts +1 -5
  53. package/dist/src/modules/emulator/EnvironmentEmulator.js +7 -91
  54. package/dist/src/modules/emulator/EnvironmentEmulatorFetch.js +58 -61
  55. package/dist/src/modules/emulator/templates/chrome-env.d.ts +17 -7
  56. package/dist/src/modules/emulator/templates/chrome-env.js +14 -7
  57. package/dist/src/modules/external/ExternalToolRunner.js +25 -22
  58. package/dist/src/modules/hook/HookGeneratorBuilders.core.generators.compose.js +5 -5
  59. package/dist/src/modules/hook/HookGeneratorBuilders.core.generators.network.js +311 -311
  60. package/dist/src/modules/hook/HookGeneratorBuilders.core.generators.runtime.js +410 -410
  61. package/dist/src/modules/hook/HookGeneratorBuilders.core.generators.storage.js +122 -122
  62. package/dist/src/modules/monitor/ConsoleMonitor.impl.core.class.d.ts +13 -0
  63. package/dist/src/modules/monitor/ConsoleMonitor.impl.core.class.js +42 -0
  64. package/dist/src/modules/monitor/ConsoleMonitor.impl.core.dynamic.js +194 -194
  65. package/dist/src/modules/monitor/FetchInterceptor.d.ts +46 -0
  66. package/dist/src/modules/monitor/FetchInterceptor.js +191 -0
  67. package/dist/src/modules/monitor/PerformanceMonitor.js +8 -7
  68. package/dist/src/modules/monitor/PlaywrightNetworkMonitor.js +62 -62
  69. package/dist/src/modules/process/BaseMemoryManager.d.ts +1 -1
  70. package/dist/src/modules/process/LinuxProcessManager.js +2 -0
  71. package/dist/src/modules/process/MacProcessManager.js +25 -25
  72. package/dist/src/modules/process/MemoryManager.d.ts +1 -1
  73. package/dist/src/modules/process/MemoryManager.js +2 -2
  74. package/dist/src/modules/process/memory/AuditTrail.js +1 -1
  75. package/dist/src/modules/process/memory/availability.js +49 -49
  76. package/dist/src/modules/process/memory/injector.js +185 -185
  77. package/dist/src/modules/process/memory/reader.js +85 -53
  78. package/dist/src/modules/process/memory/regions.dump.js +51 -51
  79. package/dist/src/modules/process/memory/regions.enumerate.js +108 -108
  80. package/dist/src/modules/process/memory/regions.modules.js +80 -80
  81. package/dist/src/modules/process/memory/regions.protection.js +148 -115
  82. package/dist/src/modules/process/memory/scanner.d.ts +5 -1
  83. package/dist/src/modules/process/memory/scanner.darwin.js +98 -41
  84. package/dist/src/modules/process/memory/scanner.js +88 -4
  85. package/dist/src/modules/process/memory/scanner.windows.js +124 -124
  86. package/dist/src/modules/process/memory/writer.js +98 -58
  87. package/dist/src/modules/security/ExecutionSandbox.js +51 -52
  88. package/dist/src/modules/stealth/FingerprintManager.js +1 -1
  89. package/dist/src/modules/stealth/StealthScripts.d.ts +1 -0
  90. package/dist/src/modules/stealth/StealthScripts.js +18 -13
  91. package/dist/src/modules/stealth/StealthVerifier.js +1 -3
  92. package/dist/src/modules/symbolic/JSVMPSymbolicExecutor.d.ts +14 -0
  93. package/dist/src/modules/symbolic/JSVMPSymbolicExecutor.js +181 -2
  94. package/dist/src/modules/trace/TraceDB.js +75 -69
  95. package/dist/src/modules/trace/TraceRecorder.js +1 -5
  96. package/dist/src/native/AntiCheatDetector.js +67 -16
  97. package/dist/src/native/CodeInjector.js +3 -3
  98. package/dist/src/native/HardwareBreakpoint.js +24 -15
  99. package/dist/src/native/HeapAnalyzer.js +2 -2
  100. package/dist/src/native/MemoryController.js +1 -1
  101. package/dist/src/native/MemoryScanSession.js +2 -2
  102. package/dist/src/native/MemoryScanner.js +4 -8
  103. package/dist/src/native/NativeMemoryManager.impl.js +2 -2
  104. package/dist/src/native/PEAnalyzer.js +14 -15
  105. package/dist/src/native/PointerChainEngine.js +2 -4
  106. package/dist/src/native/ScriptLoader.js +4 -9
  107. package/dist/src/native/Speedhack.js +1 -1
  108. package/dist/src/native/StructureAnalyzer.js +52 -33
  109. package/dist/src/native/Win32API.d.ts +1 -0
  110. package/dist/src/native/Win32API.js +13 -0
  111. package/dist/src/native/Win32Debug.js +19 -19
  112. package/dist/src/native/platform/darwin/DarwinAPI.d.ts +2 -0
  113. package/dist/src/native/platform/darwin/DarwinAPI.js +8 -0
  114. package/dist/src/native/platform/darwin/DarwinMemoryProvider.js +6 -1
  115. package/dist/src/server/MCPServer.context.d.ts +2 -1
  116. package/dist/src/server/MCPServer.d.ts +2 -1
  117. package/dist/src/server/MCPServer.domain.d.ts +1 -1
  118. package/dist/src/server/MCPServer.domain.js +81 -16
  119. package/dist/src/server/MCPServer.js +41 -14
  120. package/dist/src/server/MCPServer.resources.d.ts +2 -0
  121. package/dist/src/server/MCPServer.resources.js +91 -0
  122. package/dist/src/server/MCPServer.search.handlers.call.js +2 -1
  123. package/dist/src/server/MCPServer.search.helpers.js +1 -1
  124. package/dist/src/server/MCPServer.transport.js +12 -0
  125. package/dist/src/server/ToolCallContextGuard.js +8 -0
  126. package/dist/src/server/ToolRouter.d.ts +25 -9
  127. package/dist/src/server/ToolRouter.intent.d.ts +26 -0
  128. package/dist/src/server/ToolRouter.intent.js +77 -0
  129. package/dist/src/server/ToolRouter.js +103 -284
  130. package/dist/src/server/ToolRouter.policy.d.ts +22 -0
  131. package/dist/src/server/ToolRouter.policy.js +163 -0
  132. package/dist/src/server/ToolRouter.probe.d.ts +17 -0
  133. package/dist/src/server/ToolRouter.probe.js +103 -0
  134. package/dist/src/server/ToolRouter.renderer.d.ts +9 -0
  135. package/dist/src/server/ToolRouter.renderer.js +52 -0
  136. package/dist/src/server/activation/ActivationController.js +15 -12
  137. package/dist/src/server/activation/CompoundConditionEngine.js +1 -1
  138. package/dist/src/server/activation/PredictiveBooster.js +1 -3
  139. package/dist/src/server/domains/analysis/definitions.js +155 -655
  140. package/dist/src/server/domains/analysis/handlers.impl.js +26 -20
  141. package/dist/src/server/domains/analysis/handlers.web-tools.js +2 -1
  142. package/dist/src/server/domains/analysis/manifest.js +6 -4
  143. package/dist/src/server/domains/antidebug/definitions.js +25 -111
  144. package/dist/src/server/domains/browser/definitions.tools.advanced.js +59 -88
  145. package/dist/src/server/domains/browser/definitions.tools.behavior.js +120 -227
  146. package/dist/src/server/domains/browser/definitions.tools.page-core.js +210 -439
  147. package/dist/src/server/domains/browser/definitions.tools.page-system.js +108 -250
  148. package/dist/src/server/domains/browser/definitions.tools.runtime.js +98 -211
  149. package/dist/src/server/domains/browser/definitions.tools.security.js +194 -339
  150. package/dist/src/server/domains/browser/handlers/camoufox-browser.js +3 -2
  151. package/dist/src/server/domains/browser/handlers/captcha-solver.js +3 -3
  152. package/dist/src/server/domains/browser/handlers/dom-query.js +2 -1
  153. package/dist/src/server/domains/browser/handlers/framework-state.js +27 -9
  154. package/dist/src/server/domains/browser/handlers/indexeddb-dump.js +21 -20
  155. package/dist/src/server/domains/browser/handlers/script-management.js +1 -1
  156. package/dist/src/server/domains/browser/handlers.impl.d.ts +1 -2
  157. package/dist/src/server/domains/browser/handlers.impl.js +2 -3
  158. package/dist/src/server/domains/browser/manifest.js +37 -13
  159. package/dist/src/server/domains/coordination/definitions.js +50 -216
  160. package/dist/src/server/domains/coordination/index.d.ts +2 -1
  161. package/dist/src/server/domains/coordination/index.js +1 -0
  162. package/dist/src/server/domains/debugger/definitions.tools.advanced.js +72 -189
  163. package/dist/src/server/domains/debugger/definitions.tools.core.js +114 -288
  164. package/dist/src/server/domains/debugger/manifest.js +9 -2
  165. package/dist/src/server/domains/encoding/definitions.js +43 -153
  166. package/dist/src/server/domains/encoding/handlers.base.js +2 -2
  167. package/dist/src/server/domains/evidence/definitions.d.ts +2 -0
  168. package/dist/src/server/domains/evidence/definitions.js +42 -0
  169. package/dist/src/server/domains/evidence/handlers.d.ts +582 -0
  170. package/dist/src/server/domains/evidence/handlers.js +60 -0
  171. package/dist/src/server/domains/evidence/index.d.ts +2 -0
  172. package/dist/src/server/domains/evidence/index.js +2 -0
  173. package/dist/src/server/domains/evidence/manifest.d.ts +63 -0
  174. package/dist/src/server/domains/evidence/manifest.js +78 -0
  175. package/dist/src/server/domains/graphql/definitions.js +53 -141
  176. package/dist/src/server/domains/graphql/handlers.impl.core.runtime.replay.js +92 -114
  177. package/dist/src/server/domains/graphql/handlers.impl.core.runtime.shared.js +77 -77
  178. package/dist/src/server/domains/hooks/ai-handlers.d.ts +0 -7
  179. package/dist/src/server/domains/hooks/ai-handlers.js +1 -67
  180. package/dist/src/server/domains/hooks/definitions.js +69 -335
  181. package/dist/src/server/domains/hooks/manifest.d.ts +1 -1
  182. package/dist/src/server/domains/hooks/manifest.js +1 -2
  183. package/dist/src/server/domains/instrumentation/definitions.d.ts +2 -0
  184. package/dist/src/server/domains/instrumentation/definitions.js +99 -0
  185. package/dist/src/server/domains/instrumentation/handlers.d.ts +78 -0
  186. package/dist/src/server/domains/instrumentation/handlers.js +206 -0
  187. package/dist/src/server/domains/instrumentation/index.d.ts +2 -0
  188. package/dist/src/server/domains/instrumentation/index.js +2 -0
  189. package/dist/src/server/domains/instrumentation/manifest.d.ts +63 -0
  190. package/dist/src/server/domains/instrumentation/manifest.js +114 -0
  191. package/dist/src/server/domains/macro/definitions.js +16 -43
  192. package/dist/src/server/domains/maintenance/definitions.js +60 -219
  193. package/dist/src/server/domains/maintenance/handlers.extensions.js +78 -20
  194. package/dist/src/server/domains/memory/definitions.js +387 -559
  195. package/dist/src/server/domains/memory/handlers/hooks.d.ts +55 -0
  196. package/dist/src/server/domains/memory/handlers/hooks.js +115 -0
  197. package/dist/src/server/domains/memory/handlers/integrity.d.ts +77 -0
  198. package/dist/src/server/domains/memory/handlers/integrity.js +180 -0
  199. package/dist/src/server/domains/memory/handlers/pointer-chain.d.ts +29 -0
  200. package/dist/src/server/domains/memory/handlers/pointer-chain.js +82 -0
  201. package/dist/src/server/domains/memory/handlers/readwrite.d.ts +41 -0
  202. package/dist/src/server/domains/memory/handlers/readwrite.js +78 -0
  203. package/dist/src/server/domains/memory/handlers/scan.d.ts +35 -0
  204. package/dist/src/server/domains/memory/handlers/scan.js +97 -0
  205. package/dist/src/server/domains/memory/handlers/session.d.ts +23 -0
  206. package/dist/src/server/domains/memory/handlers/session.js +49 -0
  207. package/dist/src/server/domains/memory/handlers/structure.d.ts +29 -0
  208. package/dist/src/server/domains/memory/handlers/structure.js +74 -0
  209. package/dist/src/server/domains/memory/handlers.impl.d.ts +49 -54
  210. package/dist/src/server/domains/memory/handlers.impl.js +63 -494
  211. package/dist/src/server/domains/memory/manifest.js +236 -64
  212. package/dist/src/server/domains/native-bridge/definitions.js +54 -192
  213. package/dist/src/server/domains/native-bridge/index.d.ts +1 -0
  214. package/dist/src/server/domains/native-bridge/index.js +2 -1
  215. package/dist/src/server/domains/network/auth-extractor.js +1 -1
  216. package/dist/src/server/domains/network/definitions.js +175 -578
  217. package/dist/src/server/domains/network/handlers.base.core.d.ts +64 -0
  218. package/dist/src/server/domains/network/handlers.base.core.js +623 -0
  219. package/dist/src/server/domains/network/handlers.base.d.ts +2 -124
  220. package/dist/src/server/domains/network/handlers.base.js +3 -878
  221. package/dist/src/server/domains/network/handlers.base.performance.d.ts +63 -0
  222. package/dist/src/server/domains/network/handlers.base.performance.js +193 -0
  223. package/dist/src/server/domains/network/handlers.base.types.d.ts +42 -0
  224. package/dist/src/server/domains/network/handlers.base.types.js +89 -0
  225. package/dist/src/server/domains/network/handlers.impl.core.runtime.d.ts +1 -1
  226. package/dist/src/server/domains/network/handlers.impl.core.runtime.intercept.d.ts +21 -0
  227. package/dist/src/server/domains/network/handlers.impl.core.runtime.intercept.js +186 -0
  228. package/dist/src/server/domains/network/handlers.impl.core.runtime.js +1 -1
  229. package/dist/src/server/domains/network/manifest.js +15 -0
  230. package/dist/src/server/domains/network/replay.js +1 -4
  231. package/dist/src/server/domains/platform/definitions.js +121 -112
  232. package/dist/src/server/domains/platform/handlers/bridge-handlers.d.ts +4 -0
  233. package/dist/src/server/domains/platform/handlers/bridge-handlers.js +193 -4
  234. package/dist/src/server/domains/platform/handlers/electron-asar-helpers.js +26 -6
  235. package/dist/src/server/domains/platform/handlers/electron-dual-cdp.d.ts +3 -0
  236. package/dist/src/server/domains/platform/handlers/electron-dual-cdp.js +170 -0
  237. package/dist/src/server/domains/platform/handlers/electron-fuse-handler.d.ts +3 -0
  238. package/dist/src/server/domains/platform/handlers/electron-fuse-handler.js +193 -0
  239. package/dist/src/server/domains/platform/handlers/electron-handlers.d.ts +6 -0
  240. package/dist/src/server/domains/platform/handlers/electron-handlers.js +95 -2
  241. package/dist/src/server/domains/platform/handlers/electron-ipc-sniffer.d.ts +2 -0
  242. package/dist/src/server/domains/platform/handlers/electron-ipc-sniffer.js +370 -0
  243. package/dist/src/server/domains/platform/handlers/electron-userdata-handler.d.ts +2 -0
  244. package/dist/src/server/domains/platform/handlers/electron-userdata-handler.js +78 -0
  245. package/dist/src/server/domains/platform/handlers/miniapp-handlers.js +3 -3
  246. package/dist/src/server/domains/platform/handlers/v8-bytecode-handler.d.ts +2 -0
  247. package/dist/src/server/domains/platform/handlers/v8-bytecode-handler.js +207 -0
  248. package/dist/src/server/domains/platform/handlers.d.ts +48 -0
  249. package/dist/src/server/domains/platform/handlers.js +29 -0
  250. package/dist/src/server/domains/platform/manifest.js +38 -0
  251. package/dist/src/server/domains/process/definitions.js +163 -647
  252. package/dist/src/server/domains/process/handlers.base.d.ts +3 -95
  253. package/dist/src/server/domains/process/handlers.base.js +7 -462
  254. package/dist/src/server/domains/process/handlers.base.process.d.ts +61 -0
  255. package/dist/src/server/domains/process/handlers.base.process.js +417 -0
  256. package/dist/src/server/domains/process/handlers.base.types.d.ts +57 -0
  257. package/dist/src/server/domains/process/handlers.base.types.js +50 -0
  258. package/dist/src/server/domains/process/handlers.impl.core.runtime.inject.js +18 -16
  259. package/dist/src/server/domains/process/manifest.js +6 -1
  260. package/dist/src/server/domains/sandbox/definitions.js +11 -33
  261. package/dist/src/server/domains/sandbox/handlers.js +8 -3
  262. package/dist/src/server/domains/shared/ResponseBuilder.d.ts +209 -0
  263. package/dist/src/server/domains/shared/ResponseBuilder.js +48 -0
  264. package/dist/src/server/domains/shared/modules.d.ts +0 -2
  265. package/dist/src/server/domains/shared/modules.js +0 -1
  266. package/dist/src/server/domains/sourcemap/definitions.js +27 -111
  267. package/dist/src/server/domains/sourcemap/handlers.impl.sourcemap-common.js +7 -2
  268. package/dist/src/server/domains/sourcemap/handlers.impl.sourcemap-main.js +1 -1
  269. package/dist/src/server/domains/sourcemap/handlers.impl.sourcemap-parse-base.js +1 -1
  270. package/dist/src/server/domains/sourcemap/manifest.d.ts +1 -1
  271. package/dist/src/server/domains/sourcemap/manifest.js +1 -1
  272. package/dist/src/server/domains/streaming/definitions.js +36 -148
  273. package/dist/src/server/domains/streaming/handlers.impl.streaming-sse.js +163 -164
  274. package/dist/src/server/domains/streaming/handlers.impl.streaming-ws.js +1 -1
  275. package/dist/src/server/domains/trace/TraceSummarizer.js +8 -5
  276. package/dist/src/server/domains/trace/definitions.tools.js +51 -206
  277. package/dist/src/server/domains/trace/handlers.js +10 -12
  278. package/dist/src/server/domains/trace/index.d.ts +2 -1
  279. package/dist/src/server/domains/trace/index.js +2 -1
  280. package/dist/src/server/domains/trace/manifest.js +15 -3
  281. package/dist/src/server/domains/transform/definitions.js +50 -210
  282. package/dist/src/server/domains/transform/handlers.impl.transform-base.js +108 -108
  283. package/dist/src/server/domains/transform/handlers.impl.transform-crypto.js +18 -19
  284. package/dist/src/server/domains/transform/manifest.d.ts +1 -1
  285. package/dist/src/server/domains/transform/manifest.js +1 -1
  286. package/dist/src/server/domains/wasm/definitions.js +55 -232
  287. package/dist/src/server/domains/wasm/handlers.js +1 -1
  288. package/dist/src/server/domains/workflow/definitions.js +144 -414
  289. package/dist/src/server/domains/workflow/handlers.impl.workflow-account-bundle.js +1 -1
  290. package/dist/src/server/domains/workflow/handlers.impl.workflow-api.js +51 -51
  291. package/dist/src/server/domains/workflow/handlers.impl.workflow-base.d.ts +2 -0
  292. package/dist/src/server/domains/workflow/handlers.impl.workflow-base.js +126 -87
  293. package/dist/src/server/domains/workflow/handlers.impl.workflow-batch.js +5 -5
  294. package/dist/src/server/evidence/ReverseEvidenceGraph.d.ts +20 -0
  295. package/dist/src/server/evidence/ReverseEvidenceGraph.js +208 -0
  296. package/dist/src/server/evidence/index.d.ts +2 -0
  297. package/dist/src/server/evidence/index.js +1 -0
  298. package/dist/src/server/evidence/types.d.ts +22 -0
  299. package/dist/src/server/evidence/types.js +1 -0
  300. package/dist/src/server/extensions/ExtensionManager.d.ts +1 -0
  301. package/dist/src/server/extensions/ExtensionManager.discovery.js +72 -9
  302. package/dist/src/server/extensions/ExtensionManager.integrity.js +1 -1
  303. package/dist/src/server/extensions/ExtensionManager.js +193 -40
  304. package/dist/src/server/extensions/ExtensionManager.roots.d.ts +1 -1
  305. package/dist/src/server/extensions/ExtensionManager.roots.js +4 -4
  306. package/dist/src/server/extensions/plugin-config.js +1 -1
  307. package/dist/src/server/extensions/plugin-env.d.ts +1 -1
  308. package/dist/src/server/extensions/plugin-env.js +10 -4
  309. package/dist/src/server/extensions/types.d.ts +17 -0
  310. package/dist/src/server/extensions/types.js +1 -1
  311. package/dist/src/server/instrumentation/EvidenceGraphBridge.d.ts +13 -0
  312. package/dist/src/server/instrumentation/EvidenceGraphBridge.js +150 -0
  313. package/dist/src/server/instrumentation/InstrumentationSession.d.ts +60 -0
  314. package/dist/src/server/instrumentation/InstrumentationSession.js +269 -0
  315. package/dist/src/server/instrumentation/index.d.ts +2 -0
  316. package/dist/src/server/instrumentation/index.js +2 -0
  317. package/dist/src/server/instrumentation/types.d.ts +62 -0
  318. package/dist/src/server/instrumentation/types.js +7 -0
  319. package/dist/src/server/macros/MacroConfigLoader.d.ts +6 -5
  320. package/dist/src/server/macros/MacroConfigLoader.js +61 -59
  321. package/dist/src/server/macros/MacroRunner.js +6 -2
  322. package/dist/src/server/macros/builtins/index.d.ts +2 -3
  323. package/dist/src/server/macros/builtins/index.js +51 -7
  324. package/dist/src/server/plugins/PluginContract.d.ts +1 -1
  325. package/dist/src/server/registry/contracts.d.ts +1 -1
  326. package/dist/src/server/registry/discovery.js +5 -4
  327. package/dist/src/server/registry/ensure-browser-core.js +0 -3
  328. package/dist/src/server/registry/index.js +4 -4
  329. package/dist/src/server/registry/tool-builder.d.ts +46 -0
  330. package/dist/src/server/registry/tool-builder.js +105 -0
  331. package/dist/src/server/sandbox/QuickJSSandbox.js +16 -5
  332. package/dist/src/server/sandbox/SandboxHelpers.js +250 -250
  333. package/dist/src/server/search/EmbeddingWorker.js +5 -3
  334. package/dist/src/server/search/FeedbackTracker.d.ts +9 -0
  335. package/dist/src/server/search/FeedbackTracker.js +26 -0
  336. package/dist/src/server/search/QueryNormalizer.d.ts +6 -0
  337. package/dist/src/server/search/QueryNormalizer.js +94 -0
  338. package/dist/src/server/search/ToolSearchEngineImpl.d.ts +2 -3
  339. package/dist/src/server/search/ToolSearchEngineImpl.js +38 -88
  340. package/dist/src/server/workflows/WorkflowContract.d.ts +24 -0
  341. package/dist/src/server/workflows/WorkflowContract.js +12 -0
  342. package/dist/src/server/workflows/WorkflowEngine.d.ts +1 -0
  343. package/dist/src/server/workflows/WorkflowEngine.js +136 -3
  344. package/dist/src/types/config.d.ts +0 -14
  345. package/dist/src/types/deobfuscator.d.ts +0 -1
  346. package/dist/src/types/index.d.ts +1 -1
  347. package/dist/src/utils/DetailedDataManager.js +2 -0
  348. package/dist/src/utils/RingBuffer.js +5 -5
  349. package/dist/src/utils/TokenBudgetManager.js +1 -1
  350. package/dist/src/utils/UnifiedCacheManager.js +1 -1
  351. package/dist/src/utils/artifactRetention.js +2 -2
  352. package/dist/src/utils/betterSqlite3.d.ts +11 -0
  353. package/dist/src/utils/betterSqlite3.js +88 -0
  354. package/dist/src/utils/browserExecutable.js +2 -2
  355. package/dist/src/utils/cliFastPath.js +5 -8
  356. package/dist/src/utils/config.js +4 -26
  357. package/dist/src/utils/environmentDoctor.js +138 -11
  358. package/dist/src/utils/outputPaths.js +16 -9
  359. package/dist/src/utils/parallel.js +1 -3
  360. package/package.json +74 -72
  361. package/workflows/.gitkeep +0 -0
  362. package/dist/src/modules/analyzer/AISummarizer.d.ts +0 -39
  363. package/dist/src/modules/analyzer/AISummarizer.js +0 -122
  364. package/dist/src/modules/hook/AIHookGenerator.d.ts +0 -52
  365. package/dist/src/modules/hook/AIHookGenerator.js +0 -360
  366. package/dist/src/modules/hook/AIHookGeneratorTemplates.d.ts +0 -9
  367. package/dist/src/modules/hook/AIHookGeneratorTemplates.js +0 -157
  368. package/dist/src/server/macros/builtins/deobfuscate-ast-flow.d.ts +0 -2
  369. package/dist/src/server/macros/builtins/deobfuscate-ast-flow.js +0 -25
  370. package/dist/src/server/macros/builtins/unpacker-flow.d.ts +0 -2
  371. package/dist/src/server/macros/builtins/unpacker-flow.js +0 -25
  372. package/dist/src/services/LLMService.d.ts +0 -37
  373. package/dist/src/services/LLMService.js +0 -233
  374. package/dist/src/services/prompts/analysis.d.ts +0 -9
  375. package/dist/src/services/prompts/analysis.js +0 -158
  376. package/dist/src/services/prompts/crypto.d.ts +0 -2
  377. package/dist/src/services/prompts/crypto.js +0 -108
  378. package/dist/src/services/prompts/deobfuscation.d.ts +0 -6
  379. package/dist/src/services/prompts/deobfuscation.js +0 -300
  380. package/dist/src/services/prompts/environment.d.ts +0 -16
  381. package/dist/src/services/prompts/environment.js +0 -372
  382. package/dist/src/services/prompts/intelligence.d.ts +0 -4
  383. package/dist/src/services/prompts/intelligence.js +0 -250
  384. package/dist/src/services/prompts/taint.d.ts +0 -2
  385. package/dist/src/services/prompts/taint.js +0 -54
@@ -0,0 +1,22 @@
1
+ export type EvidenceNodeType = 'request' | 'initiator-stack' | 'script' | 'function' | 'breakpoint-hook' | 'captured-data' | 'replay-artifact';
2
+ export type EvidenceEdgeType = 'initiates' | 'contains' | 'triggers' | 'captures' | 'replays' | 'loads' | 'references';
3
+ export interface EvidenceNode {
4
+ readonly id: string;
5
+ readonly type: EvidenceNodeType;
6
+ label: string;
7
+ metadata: Record<string, unknown>;
8
+ readonly createdAt: number;
9
+ }
10
+ export interface EvidenceEdge {
11
+ readonly id: string;
12
+ readonly source: string;
13
+ readonly target: string;
14
+ readonly type: EvidenceEdgeType;
15
+ metadata?: Record<string, unknown>;
16
+ }
17
+ export interface EvidenceGraphSnapshot {
18
+ version: 1;
19
+ nodes: EvidenceNode[];
20
+ edges: EvidenceEdge[];
21
+ exportedAt: string;
22
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -2,3 +2,4 @@ import type { MCPServerContext } from '../MCPServer.context.js';
2
2
  import type { ExtensionListResult, ExtensionReloadResult } from '../extensions/types.js';
3
3
  export declare function listExtensions(ctx: MCPServerContext): ExtensionListResult;
4
4
  export declare function reloadExtensions(ctx: MCPServerContext): Promise<ExtensionReloadResult>;
5
+ export declare function ensureWorkflowsLoaded(ctx: MCPServerContext): Promise<void>;
@@ -1,5 +1,8 @@
1
- import { basename, dirname } from 'node:path';
1
+ import { existsSync } from 'node:fs';
2
+ import { readFile } from 'node:fs/promises';
3
+ import { basename, dirname, relative, resolve } from 'node:path';
2
4
  import { glob } from 'tinyglobby';
5
+ import { INSTALLED_EXTENSION_METADATA_FILENAME, } from '../extensions/types.js';
3
6
  async function collectMatchingFiles(roots, matcher) {
4
7
  const files = new Set();
5
8
  for (const root of roots) {
@@ -21,7 +24,7 @@ async function collectMatchingFiles(roots, matcher) {
21
24
  }
22
25
  }
23
26
  }
24
- return [...files].sort((a, b) => a.localeCompare(b));
27
+ return [...files].toSorted((a, b) => a.localeCompare(b));
25
28
  }
26
29
  function normalizeExtensionCandidateKey(root, file) {
27
30
  const normalizedRoot = root
@@ -29,8 +32,7 @@ function normalizeExtensionCandidateKey(root, file) {
29
32
  .replace(/\/+/g, '/')
30
33
  .replace(/^\/+|\/+$/g, '')
31
34
  .toLowerCase();
32
- const relDir = dirname(file)
33
- .slice(root.length)
35
+ const relDir = relative(root, dirname(file))
34
36
  .replace(/^[/\\]+/, '')
35
37
  .replace(/\\/g, '/')
36
38
  .replace(/\/+/g, '/')
@@ -49,9 +51,62 @@ function extensionRank(candidate) {
49
51
  return 1;
50
52
  return 2;
51
53
  }
54
+ function isInstalledExtensionMetadata(value, kind) {
55
+ if (!value || typeof value !== 'object')
56
+ return false;
57
+ const record = value;
58
+ if (record.version !== 1 || record.kind !== kind)
59
+ return false;
60
+ if (typeof record.slug !== 'string' || typeof record.id !== 'string')
61
+ return false;
62
+ if (!record.source || typeof record.source !== 'object')
63
+ return false;
64
+ const source = record.source;
65
+ return (typeof source.type === 'string' &&
66
+ typeof source.repo === 'string' &&
67
+ typeof source.ref === 'string' &&
68
+ typeof source.commit === 'string' &&
69
+ typeof source.subpath === 'string' &&
70
+ typeof source.entry === 'string');
71
+ }
72
+ async function collectInstalledEntryCandidates(roots, kind) {
73
+ const candidates = [];
74
+ for (const [rootIndex, root] of roots.entries()) {
75
+ const metadataFiles = await collectMatchingFiles([root], (filename) => filename === INSTALLED_EXTENSION_METADATA_FILENAME);
76
+ for (const metadataFile of metadataFiles) {
77
+ let metadataRaw;
78
+ try {
79
+ metadataRaw = JSON.parse(await readFile(metadataFile, 'utf8'));
80
+ }
81
+ catch {
82
+ continue;
83
+ }
84
+ if (!isInstalledExtensionMetadata(metadataRaw, kind)) {
85
+ continue;
86
+ }
87
+ const entryPath = metadataRaw.source.entry.trim();
88
+ if (!entryPath) {
89
+ continue;
90
+ }
91
+ const file = resolve(dirname(metadataFile), entryPath);
92
+ if (!existsSync(file)) {
93
+ continue;
94
+ }
95
+ candidates.push({
96
+ file,
97
+ key: normalizeExtensionCandidateKey(root, file),
98
+ isJs: file.endsWith('.js'),
99
+ isTs: file.endsWith('.ts'),
100
+ rootIndex,
101
+ priority: 0,
102
+ });
103
+ }
104
+ }
105
+ return candidates;
106
+ }
52
107
  function deduplicateCandidates(candidates) {
53
108
  const byKey = new Map();
54
- for (const candidate of candidates.sort((a, b) => a.file.localeCompare(b.file))) {
109
+ for (const candidate of candidates.toSorted((a, b) => a.file.localeCompare(b.file))) {
55
110
  const existing = byKey.get(candidate.key);
56
111
  if (!existing) {
57
112
  byKey.set(candidate.key, candidate);
@@ -59,21 +114,27 @@ function deduplicateCandidates(candidates) {
59
114
  }
60
115
  const existingRoot = existing.rootIndex;
61
116
  const candidateRoot = candidate.rootIndex;
117
+ const existingPriority = existing.priority;
118
+ const candidatePriority = candidate.priority;
62
119
  const existingExtRank = extensionRank(existing);
63
120
  const candidateExtRank = extensionRank(candidate);
64
121
  const shouldReplace = candidateRoot < existingRoot ||
65
- (candidateRoot === existingRoot && candidateExtRank < existingExtRank) ||
122
+ (candidateRoot === existingRoot && candidatePriority < existingPriority) ||
123
+ (candidateRoot === existingRoot &&
124
+ candidatePriority === existingPriority &&
125
+ candidateExtRank < existingExtRank) ||
66
126
  (candidateRoot === existingRoot &&
127
+ candidatePriority === existingPriority &&
67
128
  candidateExtRank === existingExtRank &&
68
129
  candidate.file.localeCompare(existing.file) < 0);
69
130
  if (shouldReplace) {
70
131
  byKey.set(candidate.key, candidate);
71
132
  }
72
133
  }
73
- return [...byKey.values()].map((item) => item.file).sort((a, b) => a.localeCompare(b));
134
+ return [...byKey.values()].map((item) => item.file).toSorted((a, b) => a.localeCompare(b));
74
135
  }
75
136
  export async function discoverPluginFiles(pluginRoots) {
76
- const candidates = [];
137
+ const candidates = await collectInstalledEntryCandidates(pluginRoots, 'plugin');
77
138
  for (const [rootIndex, root] of pluginRoots.entries()) {
78
139
  const files = await collectMatchingFiles([root], (filename) => filename === 'manifest.js' || filename === 'manifest.ts');
79
140
  for (const file of files) {
@@ -83,13 +144,14 @@ export async function discoverPluginFiles(pluginRoots) {
83
144
  isJs: file.endsWith('.js'),
84
145
  isTs: file.endsWith('.ts'),
85
146
  rootIndex,
147
+ priority: 1,
86
148
  });
87
149
  }
88
150
  }
89
151
  return deduplicateCandidates(candidates);
90
152
  }
91
153
  export async function discoverWorkflowFiles(workflowRoots) {
92
- const candidates = [];
154
+ const candidates = await collectInstalledEntryCandidates(workflowRoots, 'workflow');
93
155
  for (const [rootIndex, root] of workflowRoots.entries()) {
94
156
  const files = await collectMatchingFiles([root], (filename) => filename.endsWith('.workflow.js') ||
95
157
  filename.endsWith('.workflow.ts') ||
@@ -102,6 +164,7 @@ export async function discoverWorkflowFiles(workflowRoots) {
102
164
  isJs: file.endsWith('.js'),
103
165
  isTs: file.endsWith('.ts'),
104
166
  rootIndex,
167
+ priority: 1,
105
168
  });
106
169
  }
107
170
  }
@@ -9,7 +9,7 @@ export function normalizeHex(value) {
9
9
  return value.trim().toLowerCase().replace(/^0x/, '');
10
10
  }
11
11
  function isTruthyEnv(value) {
12
- return ['1', 'true'].includes((value ?? '').toLowerCase());
12
+ return ['1', 'true'].includes(value.toLowerCase());
13
13
  }
14
14
  export function isPluginSignatureRequired() {
15
15
  const raw = process.env.MCP_PLUGIN_SIGNATURE_REQUIRED;
@@ -1,7 +1,8 @@
1
- import { readFileSync } from 'node:fs';
2
- import { dirname, join } from 'node:path';
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { basename, dirname, join } from 'node:path';
3
3
  import { allTools } from '../ToolCatalog.js';
4
4
  import { logger } from '../../utils/logger.js';
5
+ import { INSTALLED_EXTENSION_METADATA_FILENAME } from '../extensions/types.js';
5
6
  import { DEFAULT_PLUGIN_ROOTS, DEFAULT_WORKFLOW_ROOTS, parseRoots, resolveRoots, } from './ExtensionManager.roots.js';
6
7
  import { sha256Hex, normalizeHex, isPluginStrictLoad, parseDigestAllowlist, verifyPluginIntegrity, } from './ExtensionManager.integrity.js';
7
8
  import { isExtensionBuilder, isWorkflowContract } from './ExtensionManager.guards.js';
@@ -34,8 +35,39 @@ function parseSimpleYaml(filePath) {
34
35
  return {};
35
36
  }
36
37
  }
38
+ function findInstalledMetadataRoot(startDir) {
39
+ let currentDir = startDir;
40
+ while (true) {
41
+ if (existsSync(join(currentDir, INSTALLED_EXTENSION_METADATA_FILENAME))) {
42
+ return currentDir;
43
+ }
44
+ const parentDir = dirname(currentDir);
45
+ if (parentDir === currentDir) {
46
+ return null;
47
+ }
48
+ currentDir = parentDir;
49
+ }
50
+ }
51
+ function resolvePluginProjectRoot(pluginFile) {
52
+ const entryDir = dirname(pluginFile);
53
+ const metadataRoot = findInstalledMetadataRoot(entryDir);
54
+ if (metadataRoot) {
55
+ return metadataRoot;
56
+ }
57
+ if (basename(entryDir).toLowerCase() === 'dist') {
58
+ return dirname(entryDir);
59
+ }
60
+ return entryDir;
61
+ }
37
62
  let reloadMutex = Promise.resolve();
38
- export async function reloadExtensions(ctx) {
63
+ const lazyWorkflowLoadAttempted = new WeakSet();
64
+ const STRICT_PLUGIN_ALLOWLIST_ERROR = 'MCP_PLUGIN_ALLOWED_DIGESTS is required when MCP_PLUGIN_SIGNATURE_REQUIRED=true ' +
65
+ 'or MCP_PLUGIN_STRICT_LOAD=true. The digest allowlist is the only pre-import trust boundary — ' +
66
+ 'without it, plugin code executes before integrity verification. No plugins will be loaded.';
67
+ const MISSING_PLUGIN_ALLOWLIST_WARNING = '[extensions] Loading plugins WITHOUT MCP_PLUGIN_ALLOWED_DIGESTS allowlist. ' +
68
+ 'Plugin code will execute on import() before post-load integrity checks. ' +
69
+ 'Set MCP_PLUGIN_STRICT_LOAD=true to enforce allowlist requirement.';
70
+ async function withReloadMutex(operation) {
39
71
  const prev = reloadMutex;
40
72
  let resolve;
41
73
  reloadMutex = new Promise((r) => {
@@ -43,12 +75,39 @@ export async function reloadExtensions(ctx) {
43
75
  });
44
76
  await prev;
45
77
  try {
46
- return await reloadExtensionsInner(ctx);
78
+ return await operation();
47
79
  }
48
80
  finally {
49
81
  resolve();
50
82
  }
51
83
  }
84
+ export async function reloadExtensions(ctx) {
85
+ return withReloadMutex(() => reloadExtensionsInner(ctx));
86
+ }
87
+ export async function ensureWorkflowsLoaded(ctx) {
88
+ if (ctx.extensionWorkflowRuntimeById.size > 0 || lazyWorkflowLoadAttempted.has(ctx)) {
89
+ return;
90
+ }
91
+ await withReloadMutex(async () => {
92
+ if (ctx.extensionWorkflowRuntimeById.size > 0 || lazyWorkflowLoadAttempted.has(ctx)) {
93
+ return;
94
+ }
95
+ lazyWorkflowLoadAttempted.add(ctx);
96
+ const warnings = [];
97
+ const errors = [];
98
+ const pluginRoots = resolveRoots(parseRoots(process.env.MCP_PLUGIN_ROOTS, DEFAULT_PLUGIN_ROOTS));
99
+ const workflowRoots = resolveRoots(parseRoots(process.env.MCP_WORKFLOW_ROOTS, DEFAULT_WORKFLOW_ROOTS));
100
+ await loadPluginWorkflowContributions(ctx, pluginRoots, warnings, errors);
101
+ const workflowFiles = await discoverWorkflowFiles(workflowRoots);
102
+ await loadWorkflows(ctx, workflowFiles, warnings, errors);
103
+ for (const warning of warnings) {
104
+ logger.warn(`[extensions] ${warning}`);
105
+ }
106
+ for (const error of errors) {
107
+ logger.error(`[extensions] ${error}`);
108
+ }
109
+ });
110
+ }
52
111
  async function loadWorkflows(ctx, workflowFiles, warnings, errors) {
53
112
  for (const workflowFile of workflowFiles) {
54
113
  try {
@@ -59,29 +118,124 @@ async function loadWorkflows(ctx, workflowFiles, warnings, errors) {
59
118
  continue;
60
119
  }
61
120
  const workflow = candidate;
62
- if (ctx.extensionWorkflowsById.has(workflow.id)) {
63
- warnings.push(`Skip workflow "${workflow.id}" from ${workflowFile}: duplicate id`);
121
+ registerWorkflowContract(ctx, workflow, workflowFile, warnings);
122
+ }
123
+ catch (error) {
124
+ errors.push(`Failed to import workflow file ${workflowFile}: ${String(error)}`);
125
+ }
126
+ }
127
+ }
128
+ function registerWorkflowContract(ctx, workflow, source, warnings) {
129
+ if (ctx.extensionWorkflowsById.has(workflow.id)) {
130
+ warnings.push(`Skip workflow "${workflow.id}" from ${source}: duplicate id`);
131
+ return false;
132
+ }
133
+ const record = {
134
+ id: workflow.id,
135
+ displayName: workflow.displayName,
136
+ source,
137
+ description: workflow.description,
138
+ tags: workflow.tags,
139
+ timeoutMs: workflow.timeoutMs,
140
+ defaultMaxConcurrency: workflow.defaultMaxConcurrency,
141
+ route: workflow.route,
142
+ };
143
+ ctx.extensionWorkflowsById.set(record.id, record);
144
+ const runtimeRecord = {
145
+ workflow,
146
+ source,
147
+ route: workflow.route,
148
+ };
149
+ ctx.extensionWorkflowRuntimeById.set(record.id, runtimeRecord);
150
+ return true;
151
+ }
152
+ function buildPluginRecord(plugin, pluginFile, loadedTools, loadedWorkflows) {
153
+ return {
154
+ id: plugin.id,
155
+ name: plugin.pluginName,
156
+ source: pluginFile,
157
+ author: plugin.pluginAuthor || undefined,
158
+ sourceRepo: plugin.pluginSourceRepo || undefined,
159
+ domains: [],
160
+ workflows: loadedWorkflows,
161
+ tools: loadedTools,
162
+ };
163
+ }
164
+ async function loadPluginWorkflowContributions(ctx, pluginRoots, warnings, errors) {
165
+ const allowedDigests = parseDigestAllowlist(process.env.MCP_PLUGIN_ALLOWED_DIGESTS);
166
+ const strictLoad = isPluginStrictLoad();
167
+ if (strictLoad && allowedDigests.size === 0) {
168
+ errors.push(STRICT_PLUGIN_ALLOWLIST_ERROR);
169
+ logger.error('[extensions] ' + STRICT_PLUGIN_ALLOWLIST_ERROR);
170
+ return;
171
+ }
172
+ if (allowedDigests.size === 0) {
173
+ logger.warn(MISSING_PLUGIN_ALLOWLIST_WARNING);
174
+ }
175
+ const pluginFiles = await discoverPluginFiles(pluginRoots);
176
+ const coreVersion = ctx.config?.mcp?.version ?? '0.0.0';
177
+ for (const pluginFile of pluginFiles) {
178
+ let fileDigest;
179
+ try {
180
+ fileDigest = normalizeHex(await sha256Hex(pluginFile));
181
+ if (allowedDigests.size > 0 && !allowedDigests.has(fileDigest)) {
182
+ warnings.push(`Skip plugin file not in MCP_PLUGIN_ALLOWED_DIGESTS allowlist: ${pluginFile}`);
64
183
  continue;
65
184
  }
66
- const record = {
67
- id: workflow.id,
68
- displayName: workflow.displayName,
69
- source: workflowFile,
70
- description: workflow.description,
71
- tags: workflow.tags,
72
- timeoutMs: workflow.timeoutMs,
73
- defaultMaxConcurrency: workflow.defaultMaxConcurrency,
74
- };
75
- ctx.extensionWorkflowsById.set(record.id, record);
76
- const runtimeRecord = {
77
- workflow,
78
- source: workflowFile,
79
- };
80
- ctx.extensionWorkflowRuntimeById.set(record.id, runtimeRecord);
81
185
  }
82
186
  catch (error) {
83
- errors.push(`Failed to import workflow file ${workflowFile}: ${String(error)}`);
187
+ errors.push(`Failed to hash plugin file ${pluginFile}: ${String(error)}`);
188
+ continue;
189
+ }
190
+ let plugin;
191
+ try {
192
+ const mod = await import(createFreshImportUrl(pluginFile, 'plugin'));
193
+ const candidate = mod.default ?? mod;
194
+ if (!isExtensionBuilder(candidate)) {
195
+ warnings.push(`Skip plugin file without valid ExtensionBuilder: ${pluginFile}`);
196
+ continue;
197
+ }
198
+ plugin = candidate;
199
+ }
200
+ catch (error) {
201
+ errors.push(`Failed to import plugin file ${pluginFile}: ${String(error)}`);
202
+ continue;
203
+ }
204
+ const pluginProjectRoot = resolvePluginProjectRoot(pluginFile);
205
+ const metaYamlPath = join(pluginProjectRoot, 'meta.yaml');
206
+ const meta = parseSimpleYaml(metaYamlPath);
207
+ plugin.mergeMetadata(meta);
208
+ if (ctx.extensionPluginsById.has(plugin.id)) {
209
+ warnings.push(`Skip plugin "${plugin.id}" from ${pluginFile}: duplicate plugin id`);
210
+ continue;
84
211
  }
212
+ try {
213
+ const verification = await verifyPluginIntegrity(plugin, coreVersion);
214
+ warnings.push(...verification.warnings);
215
+ if (!verification.ok) {
216
+ errors.push(...verification.errors);
217
+ continue;
218
+ }
219
+ }
220
+ catch (error) {
221
+ errors.push(`Failed to verify plugin ${plugin.id}: ${String(error)}`);
222
+ continue;
223
+ }
224
+ const loadedWorkflows = [];
225
+ for (const candidate of plugin.workflows) {
226
+ if (!isWorkflowContract(candidate)) {
227
+ warnings.push(`Skip invalid workflow contribution from plugin "${plugin.id}" in ${pluginFile}`);
228
+ continue;
229
+ }
230
+ const workflowSource = `${pluginFile}#workflow:${candidate.id}`;
231
+ if (registerWorkflowContract(ctx, candidate, workflowSource, warnings)) {
232
+ loadedWorkflows.push(candidate.id);
233
+ }
234
+ }
235
+ if (loadedWorkflows.length === 0) {
236
+ continue;
237
+ }
238
+ ctx.extensionPluginsById.set(plugin.id, buildPluginRecord(plugin, pluginFile, [], loadedWorkflows));
85
239
  }
86
240
  }
87
241
  async function reloadExtensionsInner(ctx) {
@@ -93,9 +247,7 @@ async function reloadExtensionsInner(ctx) {
93
247
  const allowedDigests = parseDigestAllowlist(process.env.MCP_PLUGIN_ALLOWED_DIGESTS);
94
248
  const strictLoad = isPluginStrictLoad();
95
249
  if (strictLoad && allowedDigests.size === 0) {
96
- const msg = 'MCP_PLUGIN_ALLOWED_DIGESTS is required when MCP_PLUGIN_SIGNATURE_REQUIRED=true ' +
97
- 'or MCP_PLUGIN_STRICT_LOAD=true. The digest allowlist is the only pre-import trust boundary — ' +
98
- 'without it, plugin code executes before integrity verification. No plugins will be loaded.';
250
+ const msg = STRICT_PLUGIN_ALLOWLIST_ERROR;
99
251
  errors.push(msg);
100
252
  logger.error('[extensions] ' + msg);
101
253
  const workflowFiles = await discoverWorkflowFiles(workflowRoots);
@@ -105,9 +257,7 @@ async function reloadExtensionsInner(ctx) {
105
257
  return { ...list, addedTools: 0, removedTools, warnings, errors };
106
258
  }
107
259
  if (allowedDigests.size === 0) {
108
- logger.warn('[extensions] Loading plugins WITHOUT MCP_PLUGIN_ALLOWED_DIGESTS allowlist. ' +
109
- 'Plugin code will execute on import() before post-load integrity checks. ' +
110
- 'Set MCP_PLUGIN_STRICT_LOAD=true to enforce allowlist requirement.');
260
+ logger.warn(MISSING_PLUGIN_ALLOWLIST_WARNING);
111
261
  }
112
262
  const baseToolNames = new Set(allTools.map((tool) => tool.name));
113
263
  const pluginFiles = await discoverPluginFiles(pluginRoots);
@@ -139,7 +289,8 @@ async function reloadExtensionsInner(ctx) {
139
289
  errors.push(`Failed to import plugin file ${pluginFile}: ${String(error)}`);
140
290
  continue;
141
291
  }
142
- const metaYamlPath = join(dirname(pluginFile), 'meta.yaml');
292
+ const pluginProjectRoot = resolvePluginProjectRoot(pluginFile);
293
+ const metaYamlPath = join(pluginProjectRoot, 'meta.yaml');
143
294
  const meta = parseSimpleYaml(metaYamlPath);
144
295
  plugin.mergeMetadata(meta);
145
296
  if (ctx.extensionPluginsById.has(plugin.id)) {
@@ -164,7 +315,7 @@ async function reloadExtensionsInner(ctx) {
164
315
  const allowInvokeAll = plugin.allowedTools.includes('*');
165
316
  const lifecycleContext = {
166
317
  pluginId: plugin.id,
167
- pluginRoot: pluginFile,
318
+ pluginRoot: pluginProjectRoot,
168
319
  config: ctx.config,
169
320
  get state() {
170
321
  return pluginState;
@@ -244,16 +395,18 @@ async function reloadExtensionsInner(ctx) {
244
395
  continue;
245
396
  }
246
397
  const loadedTools = plugin.tools.map((t) => t.name);
247
- const record = {
248
- id: plugin.id,
249
- name: plugin.pluginName,
250
- source: pluginFile,
251
- author: plugin.pluginAuthor || undefined,
252
- sourceRepo: plugin.pluginSourceRepo || undefined,
253
- domains: [],
254
- workflows: [],
255
- tools: loadedTools,
256
- };
398
+ const loadedWorkflows = [];
399
+ for (const candidate of plugin.workflows) {
400
+ if (!isWorkflowContract(candidate)) {
401
+ warnings.push(`Skip invalid workflow contribution from plugin "${plugin.id}" in ${pluginFile}`);
402
+ continue;
403
+ }
404
+ const workflowSource = `${pluginFile}#workflow:${candidate.id}`;
405
+ if (registerWorkflowContract(ctx, candidate, workflowSource, warnings)) {
406
+ loadedWorkflows.push(candidate.id);
407
+ }
408
+ }
409
+ const record = buildPluginRecord(plugin, pluginFile, loadedTools, loadedWorkflows);
257
410
  ctx.extensionPluginsById.set(record.id, record);
258
411
  }
259
412
  const workflowFiles = await discoverWorkflowFiles(workflowRoots);
@@ -1,4 +1,4 @@
1
1
  export declare const DEFAULT_PLUGIN_ROOTS: string[];
2
2
  export declare const DEFAULT_WORKFLOW_ROOTS: string[];
3
3
  export declare function parseRoots(raw: string | undefined, fallback: string[]): string[];
4
- export declare function resolveRoots(roots: string[]): string[];
4
+ export declare function resolveRoots(roots: string[], baseDir?: string): string[];
@@ -13,7 +13,7 @@ function findProjectRoot(startDir) {
13
13
  }
14
14
  return resolve(startDir, '..', '..', '..', '..');
15
15
  }
16
- const EXTENSION_MANAGER_DIR = dirname(fileURLToPath(import.meta.url));
16
+ const EXTENSION_MANAGER_DIR = fileURLToPath(new URL('.', import.meta.url));
17
17
  const EXTENSION_INSTALL_ROOT = findProjectRoot(EXTENSION_MANAGER_DIR);
18
18
  export const DEFAULT_PLUGIN_ROOTS = [join(EXTENSION_INSTALL_ROOT, 'plugins')];
19
19
  export const DEFAULT_WORKFLOW_ROOTS = [join(EXTENSION_INSTALL_ROOT, 'workflows')];
@@ -27,7 +27,7 @@ export function parseRoots(raw, fallback) {
27
27
  .filter(Boolean);
28
28
  return roots.length > 0 ? [...new Set(roots)] : fallback;
29
29
  }
30
- export function resolveRoots(roots) {
31
- const resolved = roots.map((root) => (isAbsolute(root) ? root : resolve(process.cwd(), root)));
32
- return [...new Set(resolved)].sort((a, b) => a.localeCompare(b));
30
+ export function resolveRoots(roots, baseDir = EXTENSION_INSTALL_ROOT) {
31
+ const resolved = roots.map((root) => (isAbsolute(root) ? root : resolve(baseDir, root)));
32
+ return [...new Set(resolved)].toSorted((a, b) => a.localeCompare(b));
33
33
  }
@@ -11,7 +11,7 @@ function envCandidates(pluginId, key) {
11
11
  return [`PLUGIN_${pluginSegment}_${keySegment}`, `PLUGINS_${pluginSegment}_${keySegment}`];
12
12
  }
13
13
  function parseBoolean(raw) {
14
- if (raw == null)
14
+ if (raw === undefined)
15
15
  return undefined;
16
16
  const value = raw.trim().toLowerCase();
17
17
  if (['1', 'true', 'yes', 'on'].includes(value))
@@ -1 +1 @@
1
- export declare function loadPluginEnv(manifestUrl: string): void;
1
+ export declare function loadPluginEnv(manifestLocation: string): void;
@@ -1,10 +1,16 @@
1
1
  import { existsSync } from 'node:fs';
2
- import { dirname, join } from 'node:path';
3
- import { fileURLToPath } from 'node:url';
2
+ import { join } from 'node:path';
3
+ import { fileURLToPath, pathToFileURL } from 'node:url';
4
4
  import dotenv from 'dotenv';
5
5
  const loadedEnvPaths = new Set();
6
- export function loadPluginEnv(manifestUrl) {
7
- const pluginDir = dirname(fileURLToPath(manifestUrl));
6
+ function toManifestUrl(manifestLocation) {
7
+ return manifestLocation.startsWith('file:')
8
+ ? new URL(manifestLocation)
9
+ : pathToFileURL(manifestLocation);
10
+ }
11
+ export function loadPluginEnv(manifestLocation) {
12
+ const pluginDirUrl = new URL('.', toManifestUrl(manifestLocation));
13
+ const pluginDir = fileURLToPath(pluginDirUrl);
8
14
  const envPath = join(pluginDir, '.env');
9
15
  if (loadedEnvPaths.has(envPath))
10
16
  return;
@@ -2,6 +2,21 @@ import type { RegisteredTool } from '@modelcontextprotocol/sdk/server/mcp.js';
2
2
  import type { Tool } from '@modelcontextprotocol/sdk/types.js';
3
3
  import type { ExtensionBuilder, PluginLifecycleContext, PluginState } from '../plugins/PluginContract.js';
4
4
  import type { WorkflowContract } from '../workflows/WorkflowContract.js';
5
+ export declare const INSTALLED_EXTENSION_METADATA_FILENAME = ".jshook-install.json";
6
+ export interface InstalledExtensionMetadata {
7
+ version: 1;
8
+ kind: 'plugin' | 'workflow';
9
+ slug: string;
10
+ id: string;
11
+ source: {
12
+ type: string;
13
+ repo: string;
14
+ ref: string;
15
+ commit: string;
16
+ subpath: string;
17
+ entry: string;
18
+ };
19
+ }
5
20
  export interface ExtensionToolRecord {
6
21
  name: string;
7
22
  domain: string;
@@ -30,6 +45,7 @@ export interface ExtensionPluginRuntimeRecord {
30
45
  export interface ExtensionWorkflowRuntimeRecord {
31
46
  workflow: WorkflowContract;
32
47
  source: string;
48
+ route?: WorkflowContract['route'];
33
49
  }
34
50
  export interface ExtensionWorkflowRecord {
35
51
  id: string;
@@ -39,6 +55,7 @@ export interface ExtensionWorkflowRecord {
39
55
  tags?: string[];
40
56
  timeoutMs?: number;
41
57
  defaultMaxConcurrency?: number;
58
+ route?: WorkflowContract['route'];
42
59
  }
43
60
  export interface ExtensionListResult {
44
61
  pluginRoots: string[];
@@ -1 +1 @@
1
- export {};
1
+ export const INSTALLED_EXTENSION_METADATA_FILENAME = '.jshook-install.json';
@@ -0,0 +1,13 @@
1
+ import type { ReverseEvidenceGraph } from '../evidence/ReverseEvidenceGraph.js';
2
+ import type { InstrumentationOperation, InstrumentationArtifact } from './types.js';
3
+ export declare class EvidenceGraphBridge {
4
+ private readonly graph;
5
+ private readonly operationNodeMap;
6
+ private readonly requestNodeMap;
7
+ constructor(graph: ReverseEvidenceGraph);
8
+ private getString;
9
+ private getInitiatorLabel;
10
+ linkRequestToInitiator(requestNodeId: string, initiatorStackNodeId: string): void;
11
+ onOperation(op: InstrumentationOperation): string | null;
12
+ onArtifact(artifact: InstrumentationArtifact): void;
13
+ }