@jshookmcp/jshook 0.2.8 → 0.2.9

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 (157) hide show
  1. package/README.md +36 -5
  2. package/README.zh.md +36 -5
  3. package/dist/{AntiCheatDetector-S8VRj-dD.mjs → AntiCheatDetector-BNk-EoBt.mjs} +3 -3
  4. package/dist/{CodeInjector-4Z3ngPoX.mjs → CodeInjector-Cq8q01kp.mjs} +5 -5
  5. package/dist/ConsoleMonitor-CPVQW1Y-.mjs +2201 -0
  6. package/dist/{DarwinAPI-B8hg_yhz.mjs → DarwinAPI-BNPxu0RH.mjs} +1 -1
  7. package/dist/DetailedDataManager-BQQcxh64.mjs +217 -0
  8. package/dist/EventBus-DgPmwpeu.mjs +141 -0
  9. package/dist/EvidenceGraphBridge-SFesNera.mjs +153 -0
  10. package/dist/{ExtensionManager-D5-bO9D8.mjs → ExtensionManager-CWYgw0YW.mjs} +13 -6
  11. package/dist/{FingerprintManager-BVxFJL2-.mjs → FingerprintManager-gzWtkKuf.mjs} +1 -1
  12. package/dist/{HardwareBreakpoint-DK1yjWkV.mjs → HardwareBreakpoint-B9gZCdFP.mjs} +3 -3
  13. package/dist/{HeapAnalyzer-CEbo10xU.mjs → HeapAnalyzer-BLDH0dCv.mjs} +4 -4
  14. package/dist/HookGeneratorBuilders.core.generators.storage-CtcdK78Q.mjs +639 -0
  15. package/dist/InstrumentationSession-CvPC7Jwy.mjs +244 -0
  16. package/dist/{MemoryController-DdtnBdD4.mjs → MemoryController-CbVdCIJF.mjs} +3 -3
  17. package/dist/{MemoryScanSession-RMixN3bX.mjs → MemoryScanSession-BsDZbLYm.mjs} +81 -78
  18. package/dist/{MemoryScanner-QjK4ld0B.mjs → MemoryScanner-Bcpml6II.mjs} +44 -18
  19. package/dist/{NativeMemoryManager.impl-CB6gJ0NM.mjs → NativeMemoryManager.impl-dZtA1ZGn.mjs} +14 -53
  20. package/dist/{NativeMemoryManager.utils-BML4q1ry.mjs → NativeMemoryManager.utils-B-FjA2mJ.mjs} +1 -1
  21. package/dist/{PEAnalyzer-CK0xe0Fs.mjs → PEAnalyzer-D1lzJ_VG.mjs} +2 -2
  22. package/dist/PageController-Bqm2kZ_X.mjs +417 -0
  23. package/dist/{PointerChainEngine-Cd73qu5b.mjs → PointerChainEngine-BOhyVsjx.mjs} +4 -4
  24. package/dist/PrerequisiteError-Dl33Svkz.mjs +20 -0
  25. package/dist/ResponseBuilder-D3iFYx2N.mjs +143 -0
  26. package/dist/ReverseEvidenceGraph-Dlsk94LC.mjs +269 -0
  27. package/dist/ScriptManager-aHHq0X7U.mjs +3000 -0
  28. package/dist/{Speedhack-CeF0XmEz.mjs → Speedhack-CqdIFlQl.mjs} +2 -2
  29. package/dist/{StructureAnalyzer-D4GkMduU.mjs → StructureAnalyzer-DhFaPvRO.mjs} +3 -3
  30. package/dist/ToolCatalog-C0JGZoOm.mjs +582 -0
  31. package/dist/ToolError-jh9whhMd.mjs +15 -0
  32. package/dist/ToolProbe-oC7aPrkv.mjs +45 -0
  33. package/dist/ToolRegistry-BjaF4oNz.mjs +131 -0
  34. package/dist/ToolRouter.policy-BWV67ZK-.mjs +304 -0
  35. package/dist/TraceRecorder-DgxyVbdQ.mjs +519 -0
  36. package/dist/{Win32API-Bc0QnQsN.mjs → Win32API-CePkipZY.mjs} +1 -1
  37. package/dist/{Win32Debug-DUHt9XUn.mjs → Win32Debug-BvKs-gxc.mjs} +2 -2
  38. package/dist/WorkflowEngine-CuvkZtWu.mjs +598 -0
  39. package/dist/analysis-CL9uACt9.mjs +463 -0
  40. package/dist/antidebug-CqDTB_uk.mjs +1081 -0
  41. package/dist/artifactRetention-CFEprwPw.mjs +591 -0
  42. package/dist/artifacts-Bk2-_uPq.mjs +59 -0
  43. package/dist/betterSqlite3-0pqusHHH.mjs +74 -0
  44. package/dist/binary-instrument-CXfpx6fT.mjs +979 -0
  45. package/dist/bind-helpers-xFfRF-qm.mjs +22 -0
  46. package/dist/boringssl-inspector-BH2D3VKc.mjs +180 -0
  47. package/dist/browser-BpOr5PEx.mjs +4082 -0
  48. package/dist/concurrency-Bt0yv1kJ.mjs +41 -0
  49. package/dist/{constants-CCvsN80K.mjs → constants-B0OANIBL.mjs} +88 -46
  50. package/dist/coordination-qUbyF8KU.mjs +259 -0
  51. package/dist/debugger-gnKxRSN0.mjs +1271 -0
  52. package/dist/definitions-6M-eejaT.mjs +53 -0
  53. package/dist/definitions-B18eyf0B.mjs +18 -0
  54. package/dist/definitions-B3QdlrHv.mjs +34 -0
  55. package/dist/definitions-B4rAvHNZ.mjs +63 -0
  56. package/dist/definitions-BB_4jnmy.mjs +37 -0
  57. package/dist/definitions-BMfYXoNC.mjs +43 -0
  58. package/dist/definitions-Beid2EB3.mjs +27 -0
  59. package/dist/definitions-C1UvM5Iy.mjs +126 -0
  60. package/dist/definitions-CXEI7QC72.mjs +216 -0
  61. package/dist/definitions-C_4r7Fo-2.mjs +14 -0
  62. package/dist/definitions-CkFDALoa.mjs +26 -0
  63. package/dist/definitions-Cke7zEb8.mjs +94 -0
  64. package/dist/definitions-ClJLzsJQ.mjs +25 -0
  65. package/dist/definitions-Cq-zroAU.mjs +28 -0
  66. package/dist/definitions-Cy3Sl6gV.mjs +34 -0
  67. package/dist/definitions-D3VsGcvz.mjs +47 -0
  68. package/dist/definitions-DVGfrn7y.mjs +96 -0
  69. package/dist/definitions-LKpC3-nL.mjs +9 -0
  70. package/dist/definitions-bAhHQJq9.mjs +359 -0
  71. package/dist/encoding-Bvz5jLRv.mjs +1065 -0
  72. package/dist/evidence-graph-bridge-C_fv9PuC.mjs +135 -0
  73. package/dist/{factory-CibqTNC8.mjs → factory-DxlGh9Xf.mjs} +37 -52
  74. package/dist/graphql-DYWzJ29s.mjs +1026 -0
  75. package/dist/handlers-9sAbfIg-.mjs +2552 -0
  76. package/dist/handlers-Bl8zkwz1.mjs +2716 -0
  77. package/dist/handlers-C67ktuRN.mjs +710 -0
  78. package/dist/handlers-C87g8oCe.mjs +276 -0
  79. package/dist/handlers-CTsDAO6p.mjs +681 -0
  80. package/dist/handlers-Cgyg6c0U.mjs +645 -0
  81. package/dist/handlers-D6j6yka7.mjs +2124 -0
  82. package/dist/handlers-DdFzXLvF.mjs +446 -0
  83. package/dist/handlers-DeLOCd5m.mjs +799 -0
  84. package/dist/handlers-DlCJN4Td.mjs +757 -0
  85. package/dist/handlers-DxGIq15_2.mjs +917 -0
  86. package/dist/handlers-U6L4xhuF.mjs +585 -0
  87. package/dist/handlers-tB9Mp9ZK.mjs +84 -0
  88. package/dist/handlers-tiy7EIBp.mjs +572 -0
  89. package/dist/handlers.impl-DS0d9fUw.mjs +761 -0
  90. package/dist/hooks-CzCWByww.mjs +898 -0
  91. package/dist/index.mjs +377 -155
  92. package/dist/{logger-BmWzC2lM.mjs → logger-Dh_xb7_2.mjs} +14 -6
  93. package/dist/maintenance-P7ePRXQC.mjs +830 -0
  94. package/dist/manifest-2ToTpjv8.mjs +106 -0
  95. package/dist/manifest-3g71z6Bg.mjs +79 -0
  96. package/dist/manifest-82baTv4U.mjs +45 -0
  97. package/dist/manifest-B3QVVeBS.mjs +82 -0
  98. package/dist/manifest-BB2J8IMJ.mjs +149 -0
  99. package/dist/manifest-BKbgbSiY.mjs +60 -0
  100. package/dist/manifest-Bcf-TJzH.mjs +848 -0
  101. package/dist/manifest-BmtZzQiQ2.mjs +45 -0
  102. package/dist/manifest-Bnd7kqEY.mjs +55 -0
  103. package/dist/manifest-BqQX6OQC2.mjs +65 -0
  104. package/dist/manifest-BqrQ4Tpj.mjs +81 -0
  105. package/dist/manifest-Br4RPFt5.mjs +370 -0
  106. package/dist/manifest-C5qDjysN.mjs +107 -0
  107. package/dist/manifest-C9RT5nk32.mjs +34 -0
  108. package/dist/manifest-CAhOuvSl.mjs +204 -0
  109. package/dist/manifest-CBYWCUBJ.mjs +51 -0
  110. package/dist/manifest-CFADCRa1.mjs +37 -0
  111. package/dist/manifest-CQVhavRF.mjs +114 -0
  112. package/dist/manifest-CT7zZBV1.mjs +48 -0
  113. package/dist/manifest-CV12bcrF.mjs +121 -0
  114. package/dist/manifest-CXsRWjjI.mjs +224 -0
  115. package/dist/manifest-CZLUCfG02.mjs +95 -0
  116. package/dist/manifest-D6phHKFd.mjs +131 -0
  117. package/dist/manifest-DCyjf4n2.mjs +294 -0
  118. package/dist/manifest-DHsnKgP6.mjs +60 -0
  119. package/dist/manifest-Df_dliIe.mjs +55 -0
  120. package/dist/manifest-Dh8WBmEW.mjs +129 -0
  121. package/dist/manifest-DhKRAT8_.mjs +92 -0
  122. package/dist/manifest-DlpTj4ic2.mjs +193 -0
  123. package/dist/manifest-DrbmZcFl2.mjs +253 -0
  124. package/dist/manifest-DuwHjUa5.mjs +70 -0
  125. package/dist/manifest-DzwvxPJX.mjs +38 -0
  126. package/dist/manifest-NXctwWQq.mjs +68 -0
  127. package/dist/manifest-Sc_0JQ13.mjs +418 -0
  128. package/dist/manifest-gZ4s_UtG.mjs +96 -0
  129. package/dist/manifest-qSleDqdO.mjs +1023 -0
  130. package/dist/modules-C184v-S9.mjs +11365 -0
  131. package/dist/mojo-ipc-B_H61Afw.mjs +525 -0
  132. package/dist/network-671Cw6hV.mjs +3346 -0
  133. package/dist/{artifacts-BbdOMET5.mjs → outputPaths-B1uGmrWZ.mjs} +219 -212
  134. package/dist/parse-args-BlRjqlkL.mjs +39 -0
  135. package/dist/platform-WmNn8Sxb.mjs +2070 -0
  136. package/dist/process-QcbIy5Zq.mjs +1401 -0
  137. package/dist/proxy-DqNs0bAd.mjs +170 -0
  138. package/dist/registry-D-6e18lB.mjs +34 -0
  139. package/dist/response-BQVP-xUn.mjs +28 -0
  140. package/dist/server/plugin-api.mjs +2 -2
  141. package/dist/shared-state-board-DV-dpHFJ.mjs +586 -0
  142. package/dist/sourcemap-Dq8ez8vS.mjs +650 -0
  143. package/dist/ssrf-policy-ZaUfvhq7.mjs +166 -0
  144. package/dist/streaming-BUQ0VJsg.mjs +725 -0
  145. package/dist/tool-builder-DCbIC5Eo.mjs +186 -0
  146. package/dist/transform-CiYJfNX0.mjs +1007 -0
  147. package/dist/types-Bx92KJfT.mjs +4 -0
  148. package/dist/wasm-DQTnHDs4.mjs +531 -0
  149. package/dist/workflow-f3xJOcjx.mjs +725 -0
  150. package/package.json +16 -16
  151. package/dist/ExtensionManager-CPTJhHFg.mjs +0 -2
  152. package/dist/ToolCatalog-Bq4V2sbJ.mjs +0 -67201
  153. package/dist/{CacheAdapters-CzFNpD9a.mjs → CacheAdapters-CDe5WPSV.mjs} +0 -0
  154. package/dist/{StealthVerifier-BzBCFiwx.mjs → StealthVerifier-Bo4T3bz8.mjs} +0 -0
  155. package/dist/{VersionDetector-CNXcvD46.mjs → VersionDetector-CwVLVdDM.mjs} +0 -0
  156. package/dist/{formatAddress-ChCSIRWT.mjs → formatAddress-DVkj9kpI.mjs} +0 -0
  157. package/dist/{types-BBjOqye-.mjs → types-CPhOReNX.mjs} +1 -1
package/dist/index.mjs CHANGED
@@ -1,22 +1,31 @@
1
1
  #!/usr/bin/env node
2
- import { t as logger } from "./logger-BmWzC2lM.mjs";
3
- import { $t as SEARCH_BM25_K1, A as COMPOUND_EVENT_WINDOW_MS, At as PREDICTIVE_MAX_HISTORY, Cn as SEARCH_VECTOR_LEARN_TOP_N, Dn as SHUTDOWN_TIMEOUT_MS, En as SEARCH_WORKFLOW_DOMAIN_BOOST_MULTIPLIER, Ft as RUNTIME_ERROR_WINDOW_MS, Ot as PREDICTIVE_CONFIDENCE_THRESHOLD, Pt as RUNTIME_ERROR_THRESHOLD, Qt as SEARCH_BM25_B, Sn as SEARCH_VECTOR_LEARN_DOWN, Xt as SEARCH_AFFINITY_BOOST_FACTOR, Yt as SEARCH_AFFINITY_BASE_WEIGHT, Zt as SEARCH_AFFINITY_TOP_N, _n as SEARCH_TRIGRAM_THRESHOLD, a as ACTIVATION_TTL_MINUTES, an as SEARCH_PARAM_TOKEN_WEIGHT, cn as SEARCH_RECENCY_MAX_BOOST, dn as SEARCH_RRF_BM25_BLEND, en as SEARCH_CACHE_VECTOR_WEIGHT_TOLERANCE, fn as SEARCH_RRF_K, gn as SEARCH_TIER_PENALTY, gt as MCP_HTTP_REQUEST_TIMEOUT_MS, h as AUTOPRUNE_MANUAL_INACTIVITY_MS, hn as SEARCH_TFIDF_COSINE_WEIGHT, ht as MCP_HTTP_KEEPALIVE_TIMEOUT_MS, i as ACTIVATION_EVENT_HISTORY_MAX, in as SEARCH_EXACT_NAME_MATCH_MULTIPLIER, j as COMPOUND_LONG_WINDOW_MS, jt as PREDICTIVE_MAX_SECOND_ORDER_KEYS, kt as PREDICTIVE_DECAY_FACTOR, ln as SEARCH_RECENCY_TRACKER_MAX, m as AUTOPRUNE_CHECK_INTERVAL_MS, mn as SEARCH_SYNONYM_EXPANSION_LIMIT, mt as MCP_HTTP_HEADERS_TIMEOUT_MS, n as ACTIVATION_COMPOUND_EVAL_EVERY, nn as SEARCH_DOMAIN_HUB_BOOST_MULTIPLIER, on as SEARCH_PREFIX_MATCH_MULTIPLIER, ot as HTTP_CLEANUP_INTERVAL_MS, p as AUTOPRUNE_AUTO_INACTIVITY_MS, pn as SEARCH_RRF_RESCALE_FACTOR, pt as MCP_HTTP_FORCE_CLOSE_TIMEOUT_MS, r as ACTIVATION_COOLDOWN_MS, rn as SEARCH_DOMAIN_HUB_THRESHOLD, sn as SEARCH_QUERY_CACHE_CAPACITY, st as HTTP_RATE_LIMIT_MAX_IPS, t as ACTIVATION_BOOST_WINDOW_MS, tn as SEARCH_COVERAGE_PRECISION_FACTOR, un as SEARCH_RECENCY_WINDOW_MS, vn as SEARCH_TRIGRAM_WEIGHT, wn as SEARCH_VECTOR_LEARN_UP, xn as SEARCH_VECTOR_ENABLED, yn as SEARCH_VECTOR_COSINE_WEIGHT } from "./constants-CCvsN80K.mjs";
4
- import { A as validateToolNameArray, B as asErrorResponse, C as getAvailableToolNames, D as getToolInputSchema, E as getToolDomainFromContext, F as createServerEventBus, H as DetailedDataManager, I as getInjectionInstructions, L as generateAntiDebugBypass, M as isBrowserOrNetworkTask, N as isMaintenanceTask, O as isToolActive, P as matchWorkflowRoute, R as ProcessRegistry, S as rerankResultsForContext, T as getToolDescription, U as UnifiedCacheManager, V as asTextResponse, W as TokenBudgetManager, _ as buildPresetRecommendations, a as getToolsForProfile, b as buildWorkflowToolSequence, c as getAllDomains, d as initRegistry, h as startArtifactRetentionScheduler, i as getToolsByDomains, j as detectWorkflowIntent, k as normalizeToolName, l as getAllManifests, m as getArtifactRetentionConfig, n as getProfileDomains, o as parseToolDomains, p as cleanupArtifacts, r as getToolDomain, s as buildHandlerMapFromRegistry, t as allTools, u as getAllRegistrations, v as buildRouteMatchMetadata, w as getRoutingState, x as getEffectivePrerequisites, y as buildWorkflowRouteRecommendation, z as ToolError } from "./ToolCatalog-Bq4V2sbJ.mjs";
5
- import { f as getConfig, h as DEFAULT_SEARCH_CONFIG, m as validateConfig } from "./artifacts-BbdOMET5.mjs";
6
- import { n as listExtensions, r as reloadExtensions, t as ensureWorkflowsLoaded } from "./ExtensionManager-D5-bO9D8.mjs";
2
+ import { t as logger } from "./logger-Dh_xb7_2.mjs";
3
+ import { $n as SEARCH_WORKFLOW_DOMAIN_BOOST_MULTIPLIER, $t as PREDICTIVE_DECAY_FACTOR, A as COMPOUND_EVENT_WINDOW_MS, An as SEARCH_PREFIX_MATCH_MULTIPLIER, Bn as SEARCH_TIER_PENALTY_FULL, Cn as SEARCH_BM25_K1, Ct as MCP_HTTP_REQUEST_TIMEOUT_MS, Dn as SEARCH_DOMAIN_HUB_THRESHOLD, En as SEARCH_DOMAIN_HUB_BOOST_MULTIPLIER, Fn as SEARCH_RRF_BM25_BLEND, Gn as SEARCH_VECTOR_BM25_SKIP_THRESHOLD, Hn as SEARCH_TIER_PENALTY_WORKFLOW, In as SEARCH_RRF_K, Jn as SEARCH_VECTOR_ENABLED, Kn as SEARCH_VECTOR_COSINE_WEIGHT, Ln as SEARCH_RRF_RESCALE_FACTOR, Mn as SEARCH_RECENCY_MAX_BOOST, Nn as SEARCH_RECENCY_TRACKER_MAX, On as SEARCH_EXACT_NAME_MATCH_MULTIPLIER, Pn as SEARCH_RECENCY_WINDOW_MS, Qt as PREDICTIVE_CONFIDENCE_THRESHOLD, Rn as SEARCH_SYNONYM_EXPANSION_LIMIT, Sn as SEARCH_BM25_B, St as MCP_HTTP_KEEPALIVE_TIMEOUT_MS, Tn as SEARCH_COVERAGE_PRECISION_FACTOR, Un as SEARCH_TRIGRAM_THRESHOLD, Vn as SEARCH_TIER_PENALTY_SEARCH, Wn as SEARCH_TRIGRAM_WEIGHT, Xn as SEARCH_VECTOR_LEARN_TOP_N, Yn as SEARCH_VECTOR_LEARN_DOWN, Zn as SEARCH_VECTOR_LEARN_UP, a as ACTIVATION_TTL_MINUTES, an as RUNTIME_ERROR_WINDOW_MS, bn as SEARCH_AFFINITY_BOOST_FACTOR, bt as MCP_HTTP_FORCE_CLOSE_TIMEOUT_MS, en as PREDICTIVE_MAX_HISTORY, er as SHUTDOWN_TIMEOUT_MS, h as AUTOPRUNE_MANUAL_INACTIVITY_MS, i as ACTIVATION_EVENT_HISTORY_MAX, in as RUNTIME_ERROR_THRESHOLD, j as COMPOUND_LONG_WINDOW_MS, jn as SEARCH_QUERY_CACHE_CAPACITY, kn as SEARCH_PARAM_TOKEN_WEIGHT, lt as HTTP_CLEANUP_INTERVAL_MS, m as AUTOPRUNE_CHECK_INTERVAL_MS, n as ACTIVATION_COMPOUND_EVAL_EVERY, p as AUTOPRUNE_AUTO_INACTIVITY_MS, r as ACTIVATION_COOLDOWN_MS, t as ACTIVATION_BOOST_WINDOW_MS, tn as PREDICTIVE_MAX_SECOND_ORDER_KEYS, ut as HTTP_RATE_LIMIT_MAX_IPS, wn as SEARCH_CACHE_VECTOR_WEIGHT_TOLERANCE, xn as SEARCH_AFFINITY_TOP_N, xt as MCP_HTTP_HEADERS_TIMEOUT_MS, yn as SEARCH_AFFINITY_BASE_WEIGHT, yt as MCP_COMPACT_SCHEMA, zn as SEARCH_TIER_PENALTY } from "./constants-B0OANIBL.mjs";
4
+ import { a as TokenBudgetManager, i as UnifiedCacheManager, n as getArtifactRetentionConfig, r as startArtifactRetentionScheduler, t as cleanupArtifacts } from "./artifactRetention-CFEprwPw.mjs";
5
+ import { t as DetailedDataManager } from "./DetailedDataManager-BQQcxh64.mjs";
6
+ import { r as asTextResponse, t as asErrorResponse } from "./response-BQVP-xUn.mjs";
7
+ import { a as getToolsForProfile, c as ensureAllDomainsLoaded, d as getAllKnownDomains, f as getAllManifests, h as getLoaderMetadata, i as getToolsByDomains, l as ensureDomainLoaded, m as initRegistry, n as getProfileDomains, o as parseToolDomains, p as getAllRegistrations, r as getToolDomain, s as buildHandlerMapFromRegistry, t as allTools, u as getAllDomains } from "./ToolCatalog-C0JGZoOm.mjs";
8
+ import { t as ToolError } from "./ToolError-jh9whhMd.mjs";
9
+ import { i as generateAntiDebugBypass, l as ProcessRegistry, r as getInjectionInstructions } from "./HookGeneratorBuilders.core.generators.storage-CtcdK78Q.mjs";
10
+ import { c as getConfig, d as DEFAULT_SEARCH_CONFIG, u as validateConfig } from "./outputPaths-B1uGmrWZ.mjs";
11
+ import { i as reloadExtensions, n as ensureWorkflowsLoaded, r as listExtensions } from "./ExtensionManager-CWYgw0YW.mjs";
12
+ import { _ as isMaintenanceTask, a as getEffectivePrerequisites, c as getRoutingState, d as getToolInputSchema, f as isToolActive, g as isBrowserOrNetworkTask, h as detectWorkflowIntent, i as buildWorkflowToolSequence, l as getToolDescription, m as validateToolNameArray, n as buildRouteMatchMetadata, o as rerankResultsForContext, p as normalizeToolName, r as buildWorkflowRouteRecommendation, s as getAvailableToolNames, t as buildPresetRecommendations, u as getToolDomainFromContext, v as matchWorkflowRoute } from "./ToolRouter.policy-BWV67ZK-.mjs";
13
+ import { n as createServerEventBus } from "./EventBus-DgPmwpeu.mjs";
7
14
  import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
8
15
  import { CompleteRequestSchema, ErrorCode, McpError } from "@modelcontextprotocol/sdk/types.js";
9
16
  import { promises } from "fs";
10
17
  import { join } from "path";
11
18
  import { createHash } from "crypto";
12
- import { fileURLToPath } from "node:url";
13
- import { ZodError, z } from "zod";
14
- import { randomUUID, timingSafeEqual } from "node:crypto";
15
- import { readFileSync as readFileSync$1 } from "node:fs";
16
19
  import { createServer } from "node:http";
20
+ import { randomUUID, timingSafeEqual } from "node:crypto";
17
21
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
18
22
  import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
19
23
  import { Worker } from "worker_threads";
24
+ import { ZodError, z } from "zod";
25
+ import { readFileSync as readFileSync$1 } from "node:fs";
26
+ import { dirname, resolve } from "node:path";
27
+ import { fileURLToPath } from "node:url";
28
+ import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
20
29
  //#region src/utils/cache.ts
21
30
  var CacheManager = class {
22
31
  config;
@@ -404,7 +413,7 @@ var ToolCallContextGuard = class {
404
413
  if (!this.isContextSensitive(toolName)) return response;
405
414
  if (response.isError) return response;
406
415
  const provider = this.getProvider();
407
- if (!provider) return response;
416
+ if (!provider || typeof provider.getContextMeta !== "function") return response;
408
417
  const meta = provider.getContextMeta();
409
418
  if (!meta.pageId && meta.tabIndex === null) return response;
410
419
  const content = response.content;
@@ -1024,6 +1033,16 @@ async function closeServer(ctx) {
1024
1033
  if (ctx.shutdownStarted) return ctx.shutdownPromise ?? Promise.resolve();
1025
1034
  ctx.shutdownStarted = true;
1026
1035
  ctx.shutdownPromise = (async () => {
1036
+ const getInst = typeof ctx.getDomainInstance === "function" ? ctx.getDomainInstance.bind(ctx) : null;
1037
+ if (getInst) {
1038
+ const scheduler = getInst("snapshotScheduler");
1039
+ if (scheduler) try {
1040
+ await scheduler.flushAll();
1041
+ scheduler.dispose();
1042
+ } catch (error) {
1043
+ logger.warn("snapshot flush on shutdown failed:", error);
1044
+ }
1045
+ }
1027
1046
  for (const [, entry] of ctx.domainTtlEntries) clearTimeout(entry.timer);
1028
1047
  ctx.domainTtlEntries.clear();
1029
1048
  ctx.detailedData.shutdown();
@@ -1762,7 +1781,8 @@ var EmbeddingEngine = class {
1762
1781
  }
1763
1782
  ensureWorker() {
1764
1783
  if (this.worker) return;
1765
- this.worker = new Worker(new URL("./EmbeddingWorker.js", import.meta.url));
1784
+ const workerPath = new URL("./EmbeddingWorker.js", import.meta.url);
1785
+ this.worker = new Worker(workerPath);
1766
1786
  if (typeof this.worker.unref === "function") this.worker.unref();
1767
1787
  ProcessRegistry.register(this.worker);
1768
1788
  this.worker.on("message", (msg) => {
@@ -1872,7 +1892,7 @@ var TrigramIndex = class TrigramIndex {
1872
1892
  * @param threshold Minimum Jaccard similarity to include in results (default 0.3).
1873
1893
  * @returns Map from document index to similarity score (0–1).
1874
1894
  */
1875
- search(query, threshold = .3) {
1895
+ search(query, threshold = SEARCH_TRIGRAM_THRESHOLD) {
1876
1896
  const queryTrigrams = TrigramIndex.extractTrigrams(query);
1877
1897
  if (queryTrigrams.size === 0) return /* @__PURE__ */ new Map();
1878
1898
  const results = /* @__PURE__ */ new Map();
@@ -2029,6 +2049,13 @@ const PARAM_DESCRIPTION_STOP_WORDS = new Set([
2029
2049
  * and tool metadata for indexing.
2030
2050
  */
2031
2051
  const QueryNormalizer = {
2052
+ /**
2053
+ * Extract parameter names and description tokens from a tool's inputSchema.
2054
+ * Handles both simple flat properties and nested object properties.
2055
+ *
2056
+ * @param inputSchema The tool's inputSchema object
2057
+ * @returns Array of normalized tokens from parameter names and descriptions
2058
+ */
2032
2059
  extractParamTokens(inputSchema) {
2033
2060
  const tokens = [];
2034
2061
  if (!inputSchema || typeof inputSchema !== "object") return tokens;
@@ -2050,6 +2077,13 @@ const QueryNormalizer = {
2050
2077
  }
2051
2078
  return tokens;
2052
2079
  },
2080
+ /**
2081
+ * Extract a short description from a full tool description.
2082
+ * Takes the first sentence and truncates to 120 characters if needed.
2083
+ *
2084
+ * @param description The full tool description
2085
+ * @returns A shortened description suitable for display
2086
+ */
2053
2087
  extractShortDescription(description) {
2054
2088
  if (!description) return "";
2055
2089
  const firstSentence = description.match(/^[^.!?\n]+[.!?]?/);
@@ -2059,9 +2093,21 @@ const QueryNormalizer = {
2059
2093
  }
2060
2094
  return description.length > 120 ? description.slice(0, 117) + "..." : description;
2061
2095
  },
2096
+ /**
2097
+ * Check if a query contains CJK (Chinese, Japanese, Korean) characters.
2098
+ *
2099
+ * @param query The search query
2100
+ * @returns true if the query contains CJK characters
2101
+ */
2062
2102
  containsCJK(query) {
2063
2103
  return /[\u4e00-\u9fff\u3040-\u309f\u30a0-\u30ff\uac00-\ud7af]/.test(query);
2064
2104
  },
2105
+ /**
2106
+ * Normalize a tool name for comparison (lowercase, underscores to hyphens/spaces).
2107
+ *
2108
+ * @param query The search query
2109
+ * @returns Normalized query string
2110
+ */
2065
2111
  normalizeToolName(query) {
2066
2112
  return query.toLowerCase().replace(/[\s-]+/g, "_");
2067
2113
  }
@@ -2072,10 +2118,10 @@ const QueryNormalizer = {
2072
2118
  * Hybrid BM25 + RRF multi-signal tool search engine for progressive tool discovery.
2073
2119
  *
2074
2120
  * Enhancements:
2075
- * - BM25 keyword scoring with synonym-expanded queries
2076
- * - TF-IDF cosine similarity as an independent RRF signal
2121
+ * - BM25 keyword scoring with synonym-expanded queries and field weights
2077
2122
  * - Trigram fuzzy matching for typo tolerance
2078
2123
  * - RRF (Reciprocal Rank Fusion) combining all signals
2124
+ * - Dense vector similarity (384-dim embeddings) as semantic signal
2079
2125
  * - Tool affinity graph with prefix-group expansion (§4.1.4 dependency hull)
2080
2126
  * - Query category adaptive domain weights (§4.1.3 task-type encoding)
2081
2127
  * - Parameter name indexing for schema-aware search
@@ -2134,8 +2180,6 @@ var ToolSearchEngine = class {
2134
2180
  domainOverrides;
2135
2181
  domainScoreMultipliers;
2136
2182
  toolScoreMultipliers;
2137
- /** IDF values per term, used for TF-IDF cosine computation. */
2138
- idfMap;
2139
2183
  /** Name → doc index for O(1) lookup during affinity expansion. */
2140
2184
  docNameIndex = /* @__PURE__ */ new Map();
2141
2185
  /** Prefix-group affinity graph: docIndex → neighbor edges. */
@@ -2164,7 +2208,8 @@ var ToolSearchEngine = class {
2164
2208
  this.toolScoreMultipliers = toolScoreMultipliers;
2165
2209
  this.docCount = source.length;
2166
2210
  this.bm25Scorer = new BM25ScorerImpl(searchConfig);
2167
- this.embeddingEngine = searchConfig?.vectorEnabled ?? SEARCH_VECTOR_ENABLED ? new EmbeddingEngine() : null;
2211
+ const vectorEnabled = searchConfig?.vectorEnabled ?? SEARCH_VECTOR_ENABLED;
2212
+ this.embeddingEngine = vectorEnabled ? new EmbeddingEngine() : null;
2168
2213
  this.feedbackTracker = new FeedbackTracker(searchConfig);
2169
2214
  this.intentBoost = new IntentBoostImpl(searchConfig?.intentToolBoostRules);
2170
2215
  let totalLength = 0;
@@ -2193,9 +2238,7 @@ var ToolSearchEngine = class {
2193
2238
  length: allTokens.length,
2194
2239
  nameTokens,
2195
2240
  nameTokenSet,
2196
- nameTokenCount: nameTokenSet.size,
2197
- tfidfWeights: /* @__PURE__ */ new Map(),
2198
- tfidfMagnitude: 0
2241
+ nameTokenCount: nameTokenSet.size
2199
2242
  };
2200
2243
  this.docs.push(doc);
2201
2244
  this.docNameIndex.set(tool.name, i);
@@ -2252,31 +2295,30 @@ var ToolSearchEngine = class {
2252
2295
  }
2253
2296
  this.avgDocLength = this.docCount > 0 ? totalLength / this.docCount : 1;
2254
2297
  this.sortedKeys = [...this.invertedIndex.keys()].toSorted();
2255
- const idfMap = /* @__PURE__ */ new Map();
2256
- for (const [term, postings] of this.invertedIndex) idfMap.set(term, Math.log(1 + this.docCount / postings.length));
2257
- this.idfMap = idfMap;
2258
- for (let i = 0; i < this.docCount; i++) {
2259
- const doc = this.docs[i];
2260
- const rawTf = /* @__PURE__ */ new Map();
2261
- for (const token of doc.tokens) rawTf.set(token, (rawTf.get(token) ?? 0) + 1);
2262
- const tfidfWeights = /* @__PURE__ */ new Map();
2263
- let magnitudeSq = 0;
2264
- for (const [term, tf] of rawTf) {
2265
- const idf = idfMap.get(term) ?? 0;
2266
- const w = (1 + Math.log(tf)) * idf;
2267
- tfidfWeights.set(term, w);
2268
- magnitudeSq += w * w;
2269
- }
2270
- doc.tfidfWeights = tfidfWeights;
2271
- doc.tfidfMagnitude = Math.sqrt(magnitudeSq);
2272
- }
2273
2298
  this.affinityGraph = this.buildAffinityGraph();
2274
2299
  this.trigramIndex = new TrigramIndex(this.docs.map((d) => d.name));
2275
2300
  this.queryCache = new LRUCache(SEARCH_QUERY_CACHE_CAPACITY);
2276
2301
  }
2277
- async search(query, topK = 10, activeToolNames, visibleDomains) {
2278
- const queryTokens = this.bm25Scorer.tokenise(query, { expandSynonyms: true });
2302
+ async search(query, topK = 10, activeToolNames, visibleDomains, profile) {
2303
+ let queryTokens = this.bm25Scorer.tokenise(query);
2279
2304
  if (queryTokens.length === 0) return [];
2305
+ if (queryTokens.length > 6) {
2306
+ const inVocab = queryTokens.filter((t) => this.invertedIndex.has(t));
2307
+ if (inVocab.length >= 3) {
2308
+ const scored = inVocab.map((t) => {
2309
+ const df = this.invertedIndex.get(t).length;
2310
+ return {
2311
+ token: t,
2312
+ idf: Math.log((this.docCount - df + .5) / (df + .5) + 1)
2313
+ };
2314
+ });
2315
+ scored.sort((a, b) => b.idf - a.idf);
2316
+ const kept = new Set(scored.slice(0, 6).map((s) => s.token));
2317
+ queryTokens = queryTokens.filter((t) => kept.has(t));
2318
+ }
2319
+ }
2320
+ const synonymTokens = this.bm25Scorer.tokenise(queryTokens.join(" "), { expandSynonyms: true }).filter((t) => !queryTokens.includes(t));
2321
+ queryTokens.push(...synonymTokens);
2280
2322
  const explicitToolMention = (() => {
2281
2323
  const lower = query.toLowerCase();
2282
2324
  if (!/(?:\b(?:call|use|run|invoke|execute)\b|调用|执行|使用|运行)/i.test(lower)) return null;
@@ -2347,11 +2389,10 @@ var ToolSearchEngine = class {
2347
2389
  const toolMultiplier = this.toolScoreMultipliers?.get(doc.name) ?? 1;
2348
2390
  if (toolMultiplier !== 1) scores[i] *= toolMultiplier;
2349
2391
  }
2350
- this.applyAffinityExpansion(scores);
2351
- this.applyDomainHubExpansion(scores);
2392
+ this.applyGraphExpansion(scores);
2352
2393
  this.applyIntentBonusBand(scores, intentToolBonuses);
2353
2394
  this.applyRecencyBoost(scores);
2354
- this.applyTierPenalty(scores, visibleDomains);
2395
+ this.applyTierPenalty(scores, visibleDomains, profile);
2355
2396
  if (explicitToolMention) {
2356
2397
  const explicitIdx = this.docNameIndex.get(explicitToolMention);
2357
2398
  if (explicitIdx !== void 0) {
@@ -2421,9 +2462,9 @@ var ToolSearchEngine = class {
2421
2462
  * tier. The penalty is a soft multiplier in [0, 1]; 1 disables the feature.
2422
2463
  * Tools without a resolved domain are left untouched.
2423
2464
  */
2424
- applyTierPenalty(scores, visibleDomains) {
2465
+ applyTierPenalty(scores, visibleDomains, profile) {
2425
2466
  if (!visibleDomains || visibleDomains.size === 0) return;
2426
- const penalty = SEARCH_TIER_PENALTY;
2467
+ const penalty = profile ? profile === "full" ? SEARCH_TIER_PENALTY_FULL : profile === "workflow" ? SEARCH_TIER_PENALTY_WORKFLOW : SEARCH_TIER_PENALTY_SEARCH : SEARCH_TIER_PENALTY;
2427
2468
  if (penalty >= 1 || penalty <= 0) return;
2428
2469
  for (let i = 0; i < this.docCount; i++) {
2429
2470
  if (scores[i] <= 0) continue;
@@ -2496,28 +2537,34 @@ var ToolSearchEngine = class {
2496
2537
  * independently contribute — a document with BM25=0 but high trigram
2497
2538
  * similarity can still surface.
2498
2539
  */
2499
- async applyRRFFusion(queryTokens, query, scores) {
2540
+ async applyRRFFusion(_queryTokens, query, scores) {
2500
2541
  const k = SEARCH_RRF_K;
2501
2542
  const trigramWeight = SEARCH_TRIGRAM_WEIGHT;
2502
- const tfidfWeight = SEARCH_TFIDF_COSINE_WEIGHT;
2503
2543
  const bm25Ranked = this.rankByScores(scores);
2504
- const cosineScores = this.computeTfidfCosineScores(queryTokens);
2505
- const cosineRanked = this.rankByMap(cosineScores);
2506
2544
  const trigramScores = this.trigramIndex.search(query, SEARCH_TRIGRAM_THRESHOLD);
2507
2545
  const trigramRanked = this.rankByMap(trigramScores);
2508
- const vectorScores = await this.computeVectorCosineScores(query);
2509
- const vectorRanked = this.rankByMap(vectorScores);
2510
- if (vectorRanked.size > 0) {
2511
- const ranking = /* @__PURE__ */ new Map();
2512
- for (const [docIdx, rank] of vectorRanked) ranking.set(this.docs[docIdx].name, rank);
2513
- this.feedbackTracker.recordVectorRanking(ranking);
2546
+ let vectorScores;
2547
+ let vectorRanked;
2548
+ if (SEARCH_VECTOR_BM25_SKIP_THRESHOLD > 0 && bm25Ranked.size > 0) {
2549
+ const topBm25Idx = [...bm25Ranked.entries()].find(([, r]) => r === 0)?.[0];
2550
+ if ((topBm25Idx !== void 0 ? scores[topBm25Idx] : 0) >= SEARCH_VECTOR_BM25_SKIP_THRESHOLD) {
2551
+ vectorScores = /* @__PURE__ */ new Map();
2552
+ vectorRanked = /* @__PURE__ */ new Map();
2553
+ } else {
2554
+ vectorScores = await this.computeVectorCosineScores(query);
2555
+ vectorRanked = this.rankByMap(vectorScores);
2556
+ }
2557
+ } else {
2558
+ vectorScores = await this.computeVectorCosineScores(query);
2559
+ vectorRanked = this.rankByMap(vectorScores);
2514
2560
  }
2561
+ const ranking = /* @__PURE__ */ new Map();
2562
+ for (const [docIdx, rank] of vectorRanked) ranking.set(this.docs[docIdx].name, rank);
2563
+ this.feedbackTracker.recordVectorRanking(ranking);
2515
2564
  for (let i = 0; i < this.docCount; i++) {
2516
2565
  let rrfScore = 0;
2517
2566
  const bm25Rank = bm25Ranked.get(i);
2518
2567
  if (bm25Rank !== void 0) rrfScore += 1 / (k + bm25Rank);
2519
- const cosineRank = cosineRanked.get(i);
2520
- if (cosineRank !== void 0 && tfidfWeight > 0) rrfScore += tfidfWeight * (1 / (k + cosineRank));
2521
2568
  const trigramRank = trigramRanked.get(i);
2522
2569
  if (trigramRank !== void 0 && trigramWeight > 0) rrfScore += trigramWeight * (1 / (k + trigramRank));
2523
2570
  const vectorRank = vectorRanked.get(i);
@@ -2531,38 +2578,6 @@ var ToolSearchEngine = class {
2531
2578
  }
2532
2579
  }
2533
2580
  /**
2534
- * Compute raw TF-IDF cosine similarity scores for each document.
2535
- * Returns Map<docIndex, cosineScore>.
2536
- */
2537
- computeTfidfCosineScores(queryTokens) {
2538
- const queryTf = /* @__PURE__ */ new Map();
2539
- for (const token of queryTokens) queryTf.set(token, (queryTf.get(token) ?? 0) + 1);
2540
- const queryWeights = /* @__PURE__ */ new Map();
2541
- let queryMagSq = 0;
2542
- for (const [term, tf] of queryTf) {
2543
- const idf = this.idfMap.get(term) ?? 0;
2544
- if (idf === 0) continue;
2545
- const w = (1 + Math.log(tf)) * idf;
2546
- queryWeights.set(term, w);
2547
- queryMagSq += w * w;
2548
- }
2549
- if (queryMagSq === 0) return /* @__PURE__ */ new Map();
2550
- const queryMagnitude = Math.sqrt(queryMagSq);
2551
- const results = /* @__PURE__ */ new Map();
2552
- for (let i = 0; i < this.docCount; i++) {
2553
- const doc = this.docs[i];
2554
- if (doc.tfidfMagnitude === 0) continue;
2555
- let dot = 0;
2556
- for (const [term, qw] of queryWeights) {
2557
- const dw = doc.tfidfWeights.get(term);
2558
- if (dw !== void 0) dot += qw * dw;
2559
- }
2560
- if (dot <= 0) continue;
2561
- results.set(i, dot / (queryMagnitude * doc.tfidfMagnitude));
2562
- }
2563
- return results;
2564
- }
2565
- /**
2566
2581
  * Rank documents by Float64Array scores.
2567
2582
  * Returns Map<docIndex, rank> (0-based, lower = better).
2568
2583
  */
@@ -2704,51 +2719,41 @@ var ToolSearchEngine = class {
2704
2719
  return graph;
2705
2720
  }
2706
2721
  /**
2707
- * Boost affinity neighbors of top results (§4.1.4).
2708
- * For each of the top-N scored documents, add a fraction of its score
2709
- * to its prefix-group neighbors, encouraging co-retrieval.
2722
+ * Combined graph-based expansion: affinity (prefix-group co-retrieval) +
2723
+ * domain hub (coherence boost for well-represented domains).
2724
+ * Single sort of scored documents feeds both expansion strategies.
2710
2725
  */
2711
- applyAffinityExpansion(scores) {
2712
- if (this.affinityGraph.size === 0) return;
2713
- const topN = SEARCH_AFFINITY_TOP_N;
2726
+ applyGraphExpansion(scores) {
2714
2727
  const scored = [];
2715
2728
  for (let i = 0; i < this.docCount; i++) if (scores[i] > 0) scored.push({
2716
2729
  idx: i,
2717
2730
  score: scores[i]
2718
2731
  });
2732
+ if (scored.length === 0) return;
2719
2733
  scored.sort((a, b) => b.score - a.score);
2720
- const boostFactor = SEARCH_AFFINITY_BOOST_FACTOR;
2721
- const limit = Math.min(topN, scored.length);
2722
- for (let rank = 0; rank < limit; rank++) {
2723
- const { idx, score } = scored[rank];
2724
- const neighbors = this.affinityGraph.get(idx);
2725
- if (!neighbors) continue;
2726
- const rankDecay = 1 / (1 + rank);
2727
- for (const { docIndex, weight } of neighbors) if (scores[docIndex] > 0) scores[docIndex] += score * weight * rankDecay * boostFactor;
2734
+ if (this.affinityGraph.size > 0) {
2735
+ const topN = SEARCH_AFFINITY_TOP_N;
2736
+ const boostFactor = SEARCH_AFFINITY_BOOST_FACTOR;
2737
+ const limit = Math.min(topN, scored.length);
2738
+ for (let rank = 0; rank < limit; rank++) {
2739
+ const { idx, score } = scored[rank];
2740
+ const neighbors = this.affinityGraph.get(idx);
2741
+ if (!neighbors) continue;
2742
+ const rankDecay = 1 / (1 + rank);
2743
+ for (const { docIndex, weight } of neighbors) if (scores[docIndex] > 0) scores[docIndex] += score * weight * rankDecay * boostFactor;
2744
+ }
2728
2745
  }
2729
- }
2730
- /**
2731
- * Domain hub expansion (§4.1.4): when a domain is heavily represented
2732
- * in top results, slightly boost remaining tools from that domain.
2733
- */
2734
- applyDomainHubExpansion(scores) {
2735
2746
  const threshold = SEARCH_DOMAIN_HUB_THRESHOLD;
2736
- if (threshold <= 0) return;
2737
- const scored = [];
2738
- for (let i = 0; i < this.docCount; i++) if (scores[i] > 0) scored.push({
2739
- idx: i,
2740
- score: scores[i]
2741
- });
2742
- if (scored.length < threshold) return;
2743
- scored.sort((a, b) => b.score - a.score);
2744
- const top10 = scored.slice(0, 10);
2745
- const domainCounts = /* @__PURE__ */ new Map();
2746
- for (const { idx } of top10) {
2747
- const domain = this.docs[idx].domain;
2748
- if (domain) domainCounts.set(domain, (domainCounts.get(domain) ?? 0) + 1);
2749
- }
2750
- for (const [domain, count] of domainCounts) if (count >= threshold) {
2751
- for (let i = 0; i < this.docCount; i++) if (scores[i] > 0 && this.docs[i].domain === domain) scores[i] *= SEARCH_DOMAIN_HUB_BOOST_MULTIPLIER;
2747
+ if (threshold > 0 && scored.length >= threshold) {
2748
+ const top10 = scored.slice(0, 10);
2749
+ const domainCounts = /* @__PURE__ */ new Map();
2750
+ for (const { idx } of top10) {
2751
+ const domain = this.docs[idx].domain;
2752
+ if (domain) domainCounts.set(domain, (domainCounts.get(domain) ?? 0) + 1);
2753
+ }
2754
+ for (const [domain, count] of domainCounts) if (count >= threshold) {
2755
+ for (let i = 0; i < this.docCount; i++) if (scores[i] > 0 && this.docs[i].domain === domain) scores[i] *= SEARCH_DOMAIN_HUB_BOOST_MULTIPLIER;
2756
+ }
2752
2757
  }
2753
2758
  }
2754
2759
  };
@@ -2788,18 +2793,22 @@ function getVisibleDomainsForTier(ctx) {
2788
2793
  }
2789
2794
  return visible;
2790
2795
  }
2796
+ function getBaseTier(ctx) {
2797
+ return ctx.baseTier;
2798
+ }
2791
2799
  function getExtensionDomainMap(ctx) {
2792
2800
  const map = /* @__PURE__ */ new Map();
2793
2801
  for (const record of ctx.extensionToolsByName.values()) map.set(record.name, record.domain);
2794
2802
  return map;
2795
2803
  }
2796
- function getCombinedTools(ctx) {
2804
+ async function getCombinedTools(ctx) {
2805
+ await ensureAllDomainsLoaded();
2797
2806
  const tools = new Map(allTools.map((tool) => [tool.name, tool]));
2798
2807
  for (const record of ctx.extensionToolsByName.values()) tools.set(record.name, record.tool);
2799
2808
  return [...tools.values()];
2800
2809
  }
2801
- function getToolByName(ctx) {
2802
- return new Map(getCombinedTools(ctx).map((tool) => [tool.name, tool]));
2810
+ async function getToolByName(ctx) {
2811
+ return new Map((await getCombinedTools(ctx)).map((tool) => [tool.name, tool]));
2803
2812
  }
2804
2813
  const searchEngineCache = /* @__PURE__ */ new WeakMap();
2805
2814
  /**
@@ -2812,11 +2821,12 @@ function buildSearchSignature(ctx) {
2812
2821
  extParts.sort();
2813
2822
  return [ctx.extensionWorkflowRuntimeById.size, extParts.join("|")].join("::");
2814
2823
  }
2815
- function getSearchEngine(ctx) {
2824
+ async function getSearchEngine(ctx) {
2825
+ await ensureAllDomainsLoaded();
2816
2826
  const signature = buildSearchSignature(ctx);
2817
2827
  const cached = searchEngineCache.get(ctx);
2818
2828
  if (cached?.signature === signature) return cached.engine;
2819
- const tools = getCombinedTools(ctx);
2829
+ const tools = await getCombinedTools(ctx);
2820
2830
  const extensionDomains = getExtensionDomainMap(ctx);
2821
2831
  const domainScoreMultipliers = /* @__PURE__ */ new Map();
2822
2832
  const toolScoreMultipliers = /* @__PURE__ */ new Map();
@@ -2833,14 +2843,14 @@ function getSearchEngine(ctx) {
2833
2843
  });
2834
2844
  return engine;
2835
2845
  }
2836
- /** Generate domain summary description from discovered manifests. */
2846
+ /** Generate domain summary description. Uses metadata when not all domains are loaded. */
2837
2847
  function buildDomainDescription(ctx) {
2838
2848
  const groups = {};
2839
2849
  for (const r of getAllRegistrations()) groups[r.domain] = (groups[r.domain] ?? 0) + 1;
2840
2850
  for (const record of ctx.extensionToolsByName.values()) groups[record.domain] = (groups[record.domain] ?? 0) + 1;
2841
- const totalTools = getAllRegistrations().length + ctx.extensionToolsByName.size;
2842
- const parts = Object.entries(groups).toSorted((a, b) => b[1] - a[1]).map(([domain, count]) => `${domain} (${count})`).join(" | ");
2843
- return `Search ${totalTools} tools across ${Object.keys(groups).length} capability domains. This includes built-in tools plus any loaded plugin/workflow tools (${ctx.extensionToolsByName.size} currently loaded). In search-tier sessions, call this before assuming a capability is unavailable. Use activate_tools for exact matches, activate_domain for an entire domain. Domains: ${parts}.`;
2851
+ const loadedCount = getAllRegistrations().length;
2852
+ const extensionCount = ctx.extensionToolsByName.size;
2853
+ return `Search ${loadedCount + extensionCount} tools across ${Object.keys(groups).length} capability domains. This includes built-in tools plus any loaded plugin/workflow tools (${extensionCount} currently loaded). In search-tier sessions, call this before assuming a capability is unavailable. Use activate_tools for exact matches, activate_domain for an entire domain. Domains: ${Object.entries(groups).toSorted((a, b) => b[1] - a[1]).map(([domain, count]) => `${domain} (${count})`).join(" | ")}. Query tip: before searching, distill your intent into key concepts (action verb + target + domain). Pass distilled keywords, not full sentences — the search engine works on token matching, not semantic understanding.`;
2844
2854
  }
2845
2855
  //#endregion
2846
2856
  //#region src/server/MCPServer.search.handlers.domain.ts
@@ -2853,12 +2863,13 @@ async function handleActivateDomain(ctx, args) {
2853
2863
  success: false,
2854
2864
  error: "domain must be a non-empty string"
2855
2865
  }));
2856
- const validDomains = new Set(getAllDomains());
2866
+ const validDomains = new Set(getAllKnownDomains());
2857
2867
  for (const record of ctx.extensionToolsByName.values()) validDomains.add(record.domain);
2858
2868
  if (!validDomains.has(domain)) return asTextResponse(JSON.stringify({
2859
2869
  success: false,
2860
2870
  error: `Unknown domain "${domain}". Valid: ${[...validDomains].join(", ")}`
2861
2871
  }));
2872
+ await ensureDomainLoaded(domain);
2862
2873
  const ttlMinutes = typeof args.ttlMinutes === "number" ? args.ttlMinutes : ACTIVATION_TTL_MINUTES;
2863
2874
  const domainTools = [...getToolsByDomains([domain]), ...[...ctx.extensionToolsByName.values()].filter((record) => record.domain === domain).map((record) => record.tool)];
2864
2875
  const activeNames = getActiveToolNames(ctx);
@@ -3416,7 +3427,8 @@ var ActivationController = class {
3416
3427
  this.boostRules = [...DEFAULT_BOOST_RULES, ...customRules].toSorted((a, b) => b.priority - a.priority);
3417
3428
  this.compoundEngine = new CompoundConditionEngine();
3418
3429
  this.predictiveBooster = new PredictiveBooster();
3419
- this.autoPruner = new AutoPruner(eventBus, new Set(getProfileDomains(ctx.baseTier)), (domain) => {
3430
+ const baseDomains = new Set(getProfileDomains(ctx.baseTier));
3431
+ this.autoPruner = new AutoPruner(eventBus, baseDomains, (domain) => {
3420
3432
  logger.info(`[ActivationController] Auto-pruning domain "${domain}"`);
3421
3433
  });
3422
3434
  this.subscribe();
@@ -3648,10 +3660,27 @@ function handleToolError(toolName, error) {
3648
3660
  logger.error(`Tool execution failed: ${toolName}`, error);
3649
3661
  throw new McpError(ErrorCode.InternalError, `Execution Failed in ${toolName}: ${error instanceof Error ? error.message : String(error)}`);
3650
3662
  }
3663
+ function stripParamDescriptions(schema) {
3664
+ const clone = { ...schema };
3665
+ if (clone.properties) {
3666
+ const props = {};
3667
+ for (const [key, val] of Object.entries(clone.properties)) {
3668
+ const { description: _d, ...rest } = val;
3669
+ props[key] = stripParamDescriptions(rest);
3670
+ }
3671
+ clone.properties = props;
3672
+ }
3673
+ if (clone.items && typeof clone.items === "object") {
3674
+ const { description: _d, ...rest } = clone.items;
3675
+ clone.items = stripParamDescriptions(rest);
3676
+ }
3677
+ if (clone.additionalProperties && typeof clone.additionalProperties === "object" && !Array.isArray(clone.additionalProperties)) clone.additionalProperties = stripParamDescriptions(clone.additionalProperties);
3678
+ return clone;
3679
+ }
3651
3680
  function registerSingleTool(ctx, toolDef) {
3652
3681
  const builtTool = toolDef;
3653
3682
  if (builtTool.__autocomplete) ctx.toolAutocompleteHandlers.set(toolDef.name, builtTool.__autocomplete);
3654
- const rawSchema = toolDef.inputSchema;
3683
+ const rawSchema = MCP_COMPACT_SCHEMA && toolDef.inputSchema ? stripParamDescriptions(toolDef.inputSchema) : toolDef.inputSchema;
3655
3684
  const shape = rawSchema && typeof rawSchema === "object" ? buildZodShape(rawSchema) : {};
3656
3685
  const description = toolDef.description ?? toolDef.name;
3657
3686
  if (Object.keys(shape).length > 0) {
@@ -3737,7 +3766,7 @@ async function routeToolRequest(request, ctx, searchEngine) {
3737
3766
  const availableToolNames = getAvailableToolNames(ctx);
3738
3767
  const routeMatch = matchWorkflowRoute(task, ctx);
3739
3768
  let presetPlannedToolNames = null;
3740
- const searchResults = await searchEngine.search(task, maxRecommendations * 2, activeNames, visibleDomains);
3769
+ const searchResults = await searchEngine.search(task, maxRecommendations * 2, activeNames, visibleDomains, getBaseTier(ctx));
3741
3770
  let finalResults = [];
3742
3771
  if (routeMatch?.workflow.route.kind === "preset") {
3743
3772
  const presetTools = buildPresetRecommendations(routeMatch, routingState, ctx, availableToolNames);
@@ -3904,10 +3933,10 @@ async function routeToolRequest(request, ctx, searchEngine) {
3904
3933
  async function handleSearchTools(ctx, args) {
3905
3934
  const query = args.query;
3906
3935
  const topK = args.top_k ?? 10;
3907
- const engine = getSearchEngine(ctx);
3936
+ const engine = await getSearchEngine(ctx);
3908
3937
  const activeNames = getActiveToolNames(ctx);
3909
3938
  const visibleDomains = getVisibleDomainsForTier(ctx);
3910
- const results = await engine.search(query, topK, activeNames, visibleDomains);
3939
+ const results = await engine.search(query, topK, activeNames, visibleDomains, getBaseTier(ctx));
3911
3940
  const topResult = results[0];
3912
3941
  const topTool = topResult ? describeTool(topResult.name, ctx) : null;
3913
3942
  const topExampleArgs = topTool ? generateExampleArgs(topTool.inputSchema) : void 0;
@@ -3934,12 +3963,14 @@ async function handleSearchTools(ctx, args) {
3934
3963
  exampleArgs: topExampleArgs,
3935
3964
  description: `Call ${topResult.name} directly. Use describe_tool("${topResult.name}") only if you need the full schema.`
3936
3965
  });
3966
+ const baseHint = "For guided tool discovery with workflow detection, use route_tool instead. Use activate_tools to enable specific tools, activate_domain for entire domains.";
3967
+ const refinementHint = results.length < 3 ? " Few results — try distilling your query to key concepts (e.g. \"hook fetch\" instead of \"how to intercept fetch requests\")." : "";
3937
3968
  const response = {
3938
3969
  query,
3939
3970
  resultCount: results.length,
3940
3971
  results,
3941
3972
  nextActions: searchNextActions,
3942
- hint: "For guided tool discovery with workflow detection, use route_tool instead. Use activate_tools to enable specific tools, activate_domain for entire domains."
3973
+ hint: baseHint + refinementHint
3943
3974
  };
3944
3975
  return asTextResponse(JSON.stringify(response, null, 2));
3945
3976
  }
@@ -3957,6 +3988,7 @@ async function notifyToolListChanged(ctx, changed) {
3957
3988
  }
3958
3989
  }
3959
3990
  async function activateToolNames(ctx, names) {
3991
+ await ensureAllDomainsLoaded();
3960
3992
  const activeNames = getActiveToolNames(ctx);
3961
3993
  const activated = [];
3962
3994
  const alreadyActive = [];
@@ -3967,7 +3999,7 @@ async function activateToolNames(ctx, names) {
3967
3999
  alreadyActive.push(name);
3968
4000
  continue;
3969
4001
  }
3970
- const toolDef = getToolByName(ctx).get(name);
4002
+ const toolDef = (await getToolByName(ctx)).get(name);
3971
4003
  if (!toolDef) {
3972
4004
  notFound.push(name);
3973
4005
  continue;
@@ -4067,7 +4099,7 @@ async function handleRouteTool(ctx, args) {
4067
4099
  success: false,
4068
4100
  error: "task must be a non-empty string"
4069
4101
  }));
4070
- const engine = getSearchEngine(ctx);
4102
+ const engine = await getSearchEngine(ctx);
4071
4103
  const autoActivate = context?.autoActivate === true;
4072
4104
  let response = populateCallCommands(await routeToolRequest({
4073
4105
  task,
@@ -4181,7 +4213,7 @@ async function handleCallTool(ctx, args) {
4181
4213
  try {
4182
4214
  const response = await ctx.executeToolWithTracking(name, toolArgs);
4183
4215
  try {
4184
- getSearchEngine(ctx).recordToolCallFeedback(name, "");
4216
+ (await getSearchEngine(ctx)).recordToolCallFeedback(name, "");
4185
4217
  } catch {}
4186
4218
  return attachCallToolMetadata(response, callMetadata);
4187
4219
  } catch (error) {
@@ -4206,7 +4238,7 @@ function buildMetaToolDefinitions(ctx) {
4206
4238
  properties: {
4207
4239
  query: {
4208
4240
  type: "string",
4209
- description: "Search query: keywords, tool name, domain name, or description fragment"
4241
+ description: "Before calling, distill your intent into 2-5 key concepts: what action, on what target, in which domain. Pass only those distilled keywords — not the original user request."
4210
4242
  },
4211
4243
  top_k: {
4212
4244
  type: "number",
@@ -4482,7 +4514,164 @@ Generally, you have three options to deploy hooks:
4482
4514
  }] }));
4483
4515
  }
4484
4516
  //#endregion
4517
+ //#region src/server/persistence/RuntimeSnapshotScheduler.ts
4518
+ var RuntimeSnapshotScheduler = class {
4519
+ sources = [];
4520
+ debounceTimer = null;
4521
+ periodicTimer = null;
4522
+ debounceMs;
4523
+ periodicMs;
4524
+ disposed = false;
4525
+ started = false;
4526
+ constructor(options) {
4527
+ this.debounceMs = options?.debounceMs ?? 2e3;
4528
+ this.periodicMs = options?.periodicMs ?? 3e4;
4529
+ }
4530
+ register(filePath, source) {
4531
+ const existing = this.sources.find((entry) => entry.filePath === filePath || entry.source === source);
4532
+ if (existing) {
4533
+ if (existing.filePath !== filePath || existing.source !== source) logger.warn(`skipping conflicting snapshot registration for ${filePath}`);
4534
+ return;
4535
+ }
4536
+ const entry = {
4537
+ source,
4538
+ filePath
4539
+ };
4540
+ this.sources.push(entry);
4541
+ if (this.started) this.restoreOne(entry).catch((err) => logger.warn(`snapshot restore failed for ${entry.filePath}:`, err));
4542
+ }
4543
+ async start() {
4544
+ if (this.started || this.disposed) return;
4545
+ this.started = true;
4546
+ await this.restoreAll();
4547
+ if (this.disposed || this.periodicTimer) return;
4548
+ this.periodicTimer = setInterval(() => {
4549
+ this.scheduleFlush().catch((err) => logger.warn("periodic snapshot failed:", err));
4550
+ }, this.periodicMs);
4551
+ }
4552
+ notifyDirty() {
4553
+ if (this.disposed) return;
4554
+ if (this.debounceTimer) clearTimeout(this.debounceTimer);
4555
+ this.debounceTimer = setTimeout(() => {
4556
+ this.scheduleFlush().catch((err) => logger.warn("debounce snapshot failed:", err));
4557
+ }, this.debounceMs);
4558
+ }
4559
+ async flushAll() {
4560
+ if (this.debounceTimer) {
4561
+ clearTimeout(this.debounceTimer);
4562
+ this.debounceTimer = null;
4563
+ }
4564
+ await this.writeDirtySources();
4565
+ }
4566
+ dispose() {
4567
+ this.disposed = true;
4568
+ if (this.debounceTimer) {
4569
+ clearTimeout(this.debounceTimer);
4570
+ this.debounceTimer = null;
4571
+ }
4572
+ if (this.periodicTimer) {
4573
+ clearInterval(this.periodicTimer);
4574
+ this.periodicTimer = null;
4575
+ }
4576
+ }
4577
+ async restoreAll() {
4578
+ for (const entry of this.sources) await this.restoreOne(entry);
4579
+ }
4580
+ async restoreOne(entry) {
4581
+ try {
4582
+ const data = await readFile(entry.filePath, "utf-8");
4583
+ const parsed = JSON.parse(data);
4584
+ entry.source.restoreSnapshot(parsed);
4585
+ logger.info(`restored snapshot from ${entry.filePath}`);
4586
+ } catch {}
4587
+ }
4588
+ async scheduleFlush() {
4589
+ await this.writeDirtySources();
4590
+ }
4591
+ async writeDirtySources() {
4592
+ for (const entry of this.sources) {
4593
+ if (!entry.source.isPersistDirty()) continue;
4594
+ try {
4595
+ await this.writeSnapshot(entry);
4596
+ } catch (err) {
4597
+ logger.warn(`snapshot write failed for ${entry.filePath}:`, err);
4598
+ }
4599
+ }
4600
+ }
4601
+ async writeSnapshot(entry) {
4602
+ await mkdir(dirname(entry.filePath), { recursive: true });
4603
+ const data = JSON.stringify(entry.source.exportSnapshot());
4604
+ const tmpPath = entry.filePath + ".tmp";
4605
+ await writeFile(tmpPath, data, "utf-8");
4606
+ await rename(tmpPath, entry.filePath);
4607
+ entry.source.markPersisted();
4608
+ }
4609
+ };
4610
+ function getStateDir(baseDir) {
4611
+ return resolve(baseDir, ".jshookmcp", "state");
4612
+ }
4613
+ //#endregion
4485
4614
  //#region src/server/MCPServer.ts
4615
+ function shouldCollectExecutionMetrics() {
4616
+ return process.env.E2E_COLLECT_PERFORMANCE === "1";
4617
+ }
4618
+ function captureExecutionMetricMemory() {
4619
+ const memory = process.memoryUsage();
4620
+ return {
4621
+ source: "server",
4622
+ rssBytes: memory.rss,
4623
+ privateBytes: null,
4624
+ virtualBytes: null,
4625
+ heapUsedBytes: memory.heapUsed,
4626
+ heapTotalBytes: memory.heapTotal,
4627
+ externalBytes: memory.external,
4628
+ arrayBuffersBytes: memory.arrayBuffers
4629
+ };
4630
+ }
4631
+ function buildExecutionMetrics(startedAt, startTime, timeoutMs, cpuStart, memoryBefore) {
4632
+ const finishedAt = (/* @__PURE__ */ new Date()).toISOString();
4633
+ const cpuUsage = process.cpuUsage(cpuStart);
4634
+ const memoryAfter = captureExecutionMetricMemory();
4635
+ return {
4636
+ source: "server",
4637
+ startedAt,
4638
+ finishedAt,
4639
+ elapsedMs: Number((performance.now() - startTime).toFixed(2)),
4640
+ timeoutMs,
4641
+ serverPid: process.pid,
4642
+ cpuUserMicros: cpuUsage.user,
4643
+ cpuSystemMicros: cpuUsage.system,
4644
+ memoryBefore,
4645
+ memoryAfter,
4646
+ memoryDelta: {
4647
+ rssBytes: memoryAfter.rssBytes - memoryBefore.rssBytes,
4648
+ privateBytes: null,
4649
+ virtualBytes: null,
4650
+ heapUsedBytes: memoryAfter.heapUsedBytes - memoryBefore.heapUsedBytes,
4651
+ heapTotalBytes: memoryAfter.heapTotalBytes - memoryBefore.heapTotalBytes,
4652
+ externalBytes: memoryAfter.externalBytes - memoryBefore.externalBytes,
4653
+ arrayBuffersBytes: memoryAfter.arrayBuffersBytes - memoryBefore.arrayBuffersBytes
4654
+ }
4655
+ };
4656
+ }
4657
+ function appendExecutionMetrics(response, metrics) {
4658
+ const content = response.content;
4659
+ if (!Array.isArray(content)) return response;
4660
+ const firstText = content.find((entry) => typeof entry === "object" && entry !== null && entry.type === "text" && typeof entry.text === "string");
4661
+ if (!firstText) return response;
4662
+ try {
4663
+ const parsed = JSON.parse(firstText.text);
4664
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return response;
4665
+ const record = parsed;
4666
+ if (!("_executionMetrics" in record)) {
4667
+ record._executionMetrics = metrics;
4668
+ firstText.text = JSON.stringify(record);
4669
+ }
4670
+ } catch {
4671
+ return response;
4672
+ }
4673
+ return response;
4674
+ }
4486
4675
  var MCPServer = class {
4487
4676
  config;
4488
4677
  server;
@@ -4538,12 +4727,32 @@ var MCPServer = class {
4538
4727
  this.enabledDomains = this.resolveEnabledDomains(this.selectedTools);
4539
4728
  const depsEntries = [];
4540
4729
  const manifests = getAllManifests();
4541
- for (const m of manifests) depsEntries.push([m.depKey, createDomainProxy(this, m.domain, `${m.domain}:${m.depKey}`, () => m.ensure(this))]);
4542
- for (const m of manifests) if (m.secondaryDepKeys) {
4543
- for (const key of m.secondaryDepKeys) if (!depsEntries.some(([k]) => k === key)) depsEntries.push([key, createDomainProxy(this, m.domain, `${m.domain}:${key}`, async () => {
4544
- await m.ensure(this);
4545
- return this[key];
4546
- })]);
4730
+ const loadedByDomain = new Map(manifests.map((m) => [m.domain, m]));
4731
+ const allMeta = getLoaderMetadata();
4732
+ if (!Array.isArray(allMeta)) logger.warn("[MCPServer] getLoaderMetadata returned non-array, skipping domain proxy setup");
4733
+ else for (const meta of allMeta) {
4734
+ const loaded = loadedByDomain.get(meta.domain);
4735
+ if (loaded) {
4736
+ depsEntries.push([meta.depKey, createDomainProxy(this, meta.domain, `${meta.domain}:${meta.depKey}`, () => loaded.ensure(this))]);
4737
+ if (loaded.secondaryDepKeys) {
4738
+ for (const key of loaded.secondaryDepKeys) if (!depsEntries.some(([k]) => k === key)) depsEntries.push([key, createDomainProxy(this, meta.domain, `${meta.domain}:${key}`, async () => {
4739
+ await loaded.ensure(this);
4740
+ return this[key];
4741
+ })]);
4742
+ }
4743
+ } else {
4744
+ depsEntries.push([meta.depKey, createDomainProxy(this, meta.domain, `${meta.domain}:${meta.depKey}`, async () => {
4745
+ const manifest = await ensureDomainLoaded(meta.domain);
4746
+ if (!manifest) throw new Error(`Failed to load domain ${meta.domain}`);
4747
+ return manifest.ensure(this);
4748
+ })]);
4749
+ for (const key of meta.secondaryDepKeys) if (!depsEntries.some(([k]) => k === key)) depsEntries.push([key, createDomainProxy(this, meta.domain, `${meta.domain}:${key}`, async () => {
4750
+ const manifest = await ensureDomainLoaded(meta.domain);
4751
+ if (!manifest) throw new Error(`Failed to load domain ${meta.domain}`);
4752
+ await manifest.ensure(this);
4753
+ return this[key];
4754
+ })]);
4755
+ }
4547
4756
  }
4548
4757
  this.handlerDeps = Object.fromEntries(depsEntries);
4549
4758
  const selectedToolNames = new Set(this.selectedTools.map((t) => t.name));
@@ -4580,6 +4789,11 @@ var MCPServer = class {
4580
4789
  this.samplingBridge = new LLMSamplingBridge(this.server);
4581
4790
  this.elicitationBridge = new ElicitationBridge(this.server);
4582
4791
  this.setDomainInstance("activationController", new ActivationController(this.eventBus, this));
4792
+ const stateDir = getStateDir(process.cwd());
4793
+ const snapshotScheduler = new RuntimeSnapshotScheduler();
4794
+ this.setDomainInstance("snapshotScheduler", snapshotScheduler);
4795
+ this.setDomainInstance("snapshotStateDir", stateDir);
4796
+ snapshotScheduler.start().catch((err) => logger.warn("snapshot scheduler start failed:", err));
4583
4797
  this.eventBus.on("tool:progress", async (payload) => {
4584
4798
  try {
4585
4799
  await this.server.server.notification({
@@ -4658,7 +4872,7 @@ var MCPServer = class {
4658
4872
  }
4659
4873
  this.cacheRegistrationPromise = (async () => {
4660
4874
  try {
4661
- const { createCacheAdapters } = await import("./CacheAdapters-CzFNpD9a.mjs");
4875
+ const { createCacheAdapters } = await import("./CacheAdapters-CDe5WPSV.mjs");
4662
4876
  const codeCache = this.collector.getCache();
4663
4877
  const codeCompressor = this.collector.getCompressor();
4664
4878
  const adapters = createCacheAdapters(this.detailedData, codeCache, codeCompressor);
@@ -4679,6 +4893,12 @@ var MCPServer = class {
4679
4893
  }
4680
4894
  async executeToolWithTracking(name, args) {
4681
4895
  let timeoutTimer;
4896
+ const timeoutMs = 3e4;
4897
+ const collectExecutionMetrics = shouldCollectExecutionMetrics();
4898
+ const executionStartedAt = collectExecutionMetrics ? (/* @__PURE__ */ new Date()).toISOString() : null;
4899
+ const executionStartTime = collectExecutionMetrics ? performance.now() : 0;
4900
+ const executionCpuStart = collectExecutionMetrics ? process.cpuUsage() : null;
4901
+ const executionMemoryBefore = collectExecutionMetrics ? captureExecutionMetricMemory() : null;
4682
4902
  try {
4683
4903
  timeoutTimer = setTimeout(() => {
4684
4904
  try {
@@ -4687,7 +4907,7 @@ var MCPServer = class {
4687
4907
  } catch {
4688
4908
  logger.warn(`Telemetry Alert [ERR-03]: Tool execution hung (>30s) for '${name}'.`);
4689
4909
  }
4690
- }, 3e4);
4910
+ }, timeoutMs);
4691
4911
  timeoutTimer.unref();
4692
4912
  let response;
4693
4913
  try {
@@ -4696,7 +4916,8 @@ var MCPServer = class {
4696
4916
  if (timeoutTimer) clearTimeout(timeoutTimer);
4697
4917
  }
4698
4918
  this.contextGuard.recordCall(name);
4699
- const enriched = this.contextGuard.enrichResponse(name, response);
4919
+ let enriched = this.contextGuard.enrichResponse(name, response);
4920
+ if (collectExecutionMetrics && executionStartedAt && executionCpuStart && executionMemoryBefore) enriched = appendExecutionMetrics(enriched, buildExecutionMetrics(executionStartedAt, executionStartTime, timeoutMs, executionCpuStart, executionMemoryBefore));
4700
4921
  try {
4701
4922
  this.tokenBudget.recordToolCall(name, args, enriched);
4702
4923
  } catch (trackingError) {
@@ -4910,7 +5131,8 @@ async function main() {
4910
5131
  if (cleanup.removedFiles > 0) logger.info(`[artifacts] Startup cleanup removed ${cleanup.removedFiles} files (${cleanup.removedBytes} bytes)`);
4911
5132
  }
4912
5133
  logger.info("Creating MCP server instance...");
4913
- await initRegistry();
5134
+ const explicitProfile = (process.env.MCP_TOOL_PROFILE ?? "").trim().toLowerCase();
5135
+ await initRegistry(explicitProfile === "full" || explicitProfile === "workflow" || explicitProfile === "search" ? explicitProfile : "search");
4914
5136
  const server = new MCPServer(config);
4915
5137
  const stopArtifactRetentionScheduler = startArtifactRetentionScheduler();
4916
5138
  const recoveryWindowMs = Math.max(1e3, RUNTIME_ERROR_WINDOW_MS);