@jshookmcp/jshook 0.2.8 → 0.3.0

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 (162) hide show
  1. package/README.md +36 -5
  2. package/README.zh.md +36 -5
  3. package/dist/{AntiCheatDetector-S8VRj-dD.mjs → AntiCheatDetector-CqGDXmfc.mjs} +160 -54
  4. package/dist/{CodeInjector-4Z3ngPoX.mjs → CodeInjector-BdjRfNx7.mjs} +5 -5
  5. package/dist/ConsoleMonitor-DykL3IAw.mjs +2269 -0
  6. package/dist/{DarwinAPI-B8hg_yhz.mjs → DarwinAPI-ETyy0xyo.mjs} +1 -1
  7. package/dist/DetailedDataManager-HT49OrvF.mjs +217 -0
  8. package/dist/EventBus-DFKvADm3.mjs +141 -0
  9. package/dist/EvidenceGraphBridge-318Oi0Lf.mjs +153 -0
  10. package/dist/{ExtensionManager-D5-bO9D8.mjs → ExtensionManager-BDMsY2Dz.mjs} +27 -13
  11. package/dist/{FingerprintManager-BVxFJL2-.mjs → FingerprintManager-BN4UQWnX.mjs} +1 -1
  12. package/dist/{HardwareBreakpoint-DK1yjWkV.mjs → HardwareBreakpoint-Cc2AFq1Y.mjs} +3 -3
  13. package/dist/{HeapAnalyzer-CEbo10xU.mjs → HeapAnalyzer-DruMgsgj.mjs} +21 -21
  14. package/dist/HookGeneratorBuilders.core.generators.storage-CTbB4Lcx.mjs +566 -0
  15. package/dist/InstrumentationSession-DLH0vd-z.mjs +244 -0
  16. package/dist/{MemoryController-DdtnBdD4.mjs → MemoryController-CMtviNW_.mjs} +3 -3
  17. package/dist/{MemoryScanSession-RMixN3bX.mjs → MemoryScanSession-ITgb_NMi.mjs} +81 -78
  18. package/dist/{MemoryScanner-QjK4ld0B.mjs → MemoryScanner-CiL7Z3ey.mjs} +50 -21
  19. package/dist/{NativeMemoryManager.impl-CB6gJ0NM.mjs → NativeMemoryManager.impl-D9Lkovvn.mjs} +20 -56
  20. package/dist/{NativeMemoryManager.utils-BML4q1ry.mjs → NativeMemoryManager.utils-BBlAixF5.mjs} +1 -1
  21. package/dist/{PEAnalyzer-CK0xe0Fs.mjs → PEAnalyzer-DMQ44gen.mjs} +16 -16
  22. package/dist/PageController-BPJNqqBN.mjs +431 -0
  23. package/dist/{PointerChainEngine-Cd73qu5b.mjs → PointerChainEngine-K7wN8Z-w.mjs} +10 -7
  24. package/dist/PrerequisiteError-TuyZIs6n.mjs +20 -0
  25. package/dist/ProcessRegistry-zGg12QbE.mjs +74 -0
  26. package/dist/ResponseBuilder-CJXWmWNw.mjs +143 -0
  27. package/dist/ReverseEvidenceGraph-C02-gXOh.mjs +269 -0
  28. package/dist/ScriptManager-ZuWD-0Jg.mjs +3003 -0
  29. package/dist/{Speedhack-CeF0XmEz.mjs → Speedhack-D-z0umeT.mjs} +2 -2
  30. package/dist/{StructureAnalyzer-D4GkMduU.mjs → StructureAnalyzer-Cav5AVSL.mjs} +9 -6
  31. package/dist/ToolCatalog-5OJdMiF0.mjs +582 -0
  32. package/dist/ToolError-jh9whhMd.mjs +15 -0
  33. package/dist/ToolProbe-DbCFGyrg.mjs +45 -0
  34. package/dist/ToolRegistry-B9krbTtI.mjs +180 -0
  35. package/dist/ToolRouter.policy-BGDAGyeH.mjs +344 -0
  36. package/dist/TraceRecorder-B41Z5XBj.mjs +1286 -0
  37. package/dist/{Win32API-Bc0QnQsN.mjs → Win32API-C2kjj0ze.mjs} +19 -13
  38. package/dist/{Win32Debug-DUHt9XUn.mjs → Win32Debug-CKrGOTpo.mjs} +3 -3
  39. package/dist/WorkflowEngine-DJ6M4opp.mjs +569 -0
  40. package/dist/analysis-BHeJW2Nb.mjs +1234 -0
  41. package/dist/antidebug-BRKeyt27.mjs +1081 -0
  42. package/dist/artifactRetention-CPXkUJXp.mjs +598 -0
  43. package/dist/artifacts-DkfosXH3.mjs +59 -0
  44. package/dist/authorization-schema-DRqyJMSk.mjs +31 -0
  45. package/dist/betterSqlite3-DLSBZodi.mjs +74 -0
  46. package/dist/binary-instrument--V3MAhJ4.mjs +971 -0
  47. package/dist/bind-helpers-ClV34xdn.mjs +42 -0
  48. package/dist/boringssl-inspector-Bo_LOLaS.mjs +180 -0
  49. package/dist/browser-Dx3_S2cG.mjs +4369 -0
  50. package/dist/capabilities-CcHlvWgK.mjs +33 -0
  51. package/dist/concurrency-Drev_Vz9.mjs +41 -0
  52. package/dist/{constants-CCvsN80K.mjs → constants-CDZLOoVv.mjs} +105 -48
  53. package/dist/coordination-DgItD9DL.mjs +259 -0
  54. package/dist/debugger-RS3RSAqs.mjs +1288 -0
  55. package/dist/definitions-BEoYofW5.mjs +47 -0
  56. package/dist/definitions-BRaefg3u.mjs +365 -0
  57. package/dist/definitions-BbkvZkiv.mjs +96 -0
  58. package/dist/definitions-BtWSHJ3o.mjs +17 -0
  59. package/dist/definitions-C1gCHO0i.mjs +43 -0
  60. package/dist/definitions-CDOg_b-l.mjs +138 -0
  61. package/dist/definitions-CVPD9hzZ.mjs +54 -0
  62. package/dist/definitions-Cea8Lgl7.mjs +94 -0
  63. package/dist/definitions-DAgIyjxM.mjs +10 -0
  64. package/dist/definitions-DJA27nsL.mjs +66 -0
  65. package/dist/definitions-DKPFU3LW.mjs +25 -0
  66. package/dist/definitions-DPRpZQ96.mjs +47 -0
  67. package/dist/definitions-DUE5gmdn.mjs +18 -0
  68. package/dist/definitions-DYVjOtxa.mjs +26 -0
  69. package/dist/definitions-DcYLVLCo.mjs +37 -0
  70. package/dist/definitions-Pp5LI2H4.mjs +27 -0
  71. package/dist/definitions-j9KdHVNR.mjs +14 -0
  72. package/dist/definitions-uzkjBwa7.mjs +258 -0
  73. package/dist/definitions-va-AnLuQ.mjs +28 -0
  74. package/dist/encoding-DJeqHmpd.mjs +1079 -0
  75. package/dist/evidence-graph-bridge-DcYizFk2.mjs +136 -0
  76. package/dist/{factory-CibqTNC8.mjs → factory-C90tBff6.mjs} +41 -56
  77. package/dist/flat-target-session-Dgax2Cy3.mjs +29 -0
  78. package/dist/graphql-CoHrhweh.mjs +1197 -0
  79. package/dist/handlers-4jmR0nMs.mjs +898 -0
  80. package/dist/handlers-BAHPxcch.mjs +789 -0
  81. package/dist/handlers-BOs9b907.mjs +2600 -0
  82. package/dist/handlers-BWXEy6ef.mjs +917 -0
  83. package/dist/handlers-Bndn6QvE.mjs +111 -0
  84. package/dist/handlers-BqC4bD4s.mjs +681 -0
  85. package/dist/handlers-BtYq60bM2.mjs +276 -0
  86. package/dist/handlers-BzgcB4iv.mjs +799 -0
  87. package/dist/handlers-CRyRWj2b.mjs +859 -0
  88. package/dist/handlers-CVv2H1uq.mjs +592 -0
  89. package/dist/handlers-Dl5a7JS4.mjs +572 -0
  90. package/dist/handlers-Dx2d7jt7.mjs +2537 -0
  91. package/dist/handlers-Dz9PYsCa.mjs +2805 -0
  92. package/dist/handlers-HujRKC3b.mjs +661 -0
  93. package/dist/handlers.impl-XWXkQfyi.mjs +807 -0
  94. package/dist/hooks-B1B8NRHL.mjs +898 -0
  95. package/dist/index.mjs +491 -259
  96. package/dist/{logger-BmWzC2lM.mjs → logger-Dh_xb7_2.mjs} +14 -6
  97. package/dist/maintenance-PRMkLVRW.mjs +835 -0
  98. package/dist/manifest-67Bok-Si.mjs +58 -0
  99. package/dist/manifest-6lNTMZAB2.mjs +87 -0
  100. package/dist/manifest-B2duEHiH.mjs +90 -0
  101. package/dist/manifest-B6EY9Vm8.mjs +57 -0
  102. package/dist/manifest-B6nKSbyY.mjs +95 -0
  103. package/dist/manifest-BL8AQNPF.mjs +106 -0
  104. package/dist/manifest-BSZvJJmV.mjs +47 -0
  105. package/dist/manifest-BU7qzUyX.mjs +418 -0
  106. package/dist/manifest-Bl62e8WK.mjs +49 -0
  107. package/dist/manifest-Bo5cXjdt.mjs +82 -0
  108. package/dist/manifest-BpS4gtUK.mjs +1347 -0
  109. package/dist/manifest-Bv65_e2W.mjs +101 -0
  110. package/dist/manifest-BytNIF4Z.mjs +117 -0
  111. package/dist/manifest-C-xtsjS3.mjs +81 -0
  112. package/dist/manifest-CDYl7OhA.mjs +66 -0
  113. package/dist/manifest-CRZ3xmkD.mjs +61 -0
  114. package/dist/manifest-CoW6u4Tp.mjs +132 -0
  115. package/dist/manifest-Cq5zN_8A.mjs +50 -0
  116. package/dist/manifest-D7YZM_2e.mjs +194 -0
  117. package/dist/manifest-DE_VrAeQ.mjs +314 -0
  118. package/dist/manifest-DGsXSCpT.mjs +39 -0
  119. package/dist/manifest-DJ2vfEuW.mjs +156 -0
  120. package/dist/manifest-DPXDYhEu.mjs +80 -0
  121. package/dist/manifest-Dd4fQb0a.mjs +322 -0
  122. package/dist/manifest-Deq6opGg.mjs +223 -0
  123. package/dist/manifest-DfJTafJK.mjs +37 -0
  124. package/dist/manifest-DgOdgN_j.mjs +50 -0
  125. package/dist/manifest-DlbMW4v4.mjs +47 -0
  126. package/dist/manifest-DmVfbH0w.mjs +374 -0
  127. package/dist/manifest-Dog6Ddjr.mjs +109 -0
  128. package/dist/manifest-DvgU5FWb.mjs +58 -0
  129. package/dist/manifest-HsfDBs7j.mjs +50 -0
  130. package/dist/manifest-I8oQHvCG.mjs +186 -0
  131. package/dist/manifest-NvH_a-av.mjs +786 -0
  132. package/dist/manifest-cEJU1v0Z.mjs +129 -0
  133. package/dist/manifest-wOl5XLB12.mjs +112 -0
  134. package/dist/modules-tZozf0LQ.mjs +10635 -0
  135. package/dist/mojo-ipc-DXNEXEqb.mjs +640 -0
  136. package/dist/network-CPVvwvFg.mjs +3852 -0
  137. package/dist/{artifacts-BbdOMET5.mjs → outputPaths-um7lCRY3.mjs} +219 -216
  138. package/dist/parse-args-B4cY5Vx5.mjs +39 -0
  139. package/dist/platform-CYeFoTWp.mjs +2161 -0
  140. package/dist/process-BTbgcVc6.mjs +1306 -0
  141. package/dist/proxy-r8YN6nP1.mjs +192 -0
  142. package/dist/registry-Bl8ZQW61.mjs +34 -0
  143. package/dist/response-CWhh2aLo.mjs +34 -0
  144. package/dist/server/plugin-api.mjs +2 -2
  145. package/dist/shared-state-board-BoZnSoj-.mjs +586 -0
  146. package/dist/sourcemap-BIDHUVXy.mjs +934 -0
  147. package/dist/ssrf-policy-Dsqd-DTX.mjs +166 -0
  148. package/dist/streaming-Dal6utPp.mjs +725 -0
  149. package/dist/tool-builder-BHJp32mV.mjs +186 -0
  150. package/dist/transform-DRVgGG90.mjs +1011 -0
  151. package/dist/types-Bx92KJfT.mjs +4 -0
  152. package/dist/wasm-BYx5UOeG.mjs +1044 -0
  153. package/dist/webcrack-Be0_FccV.mjs +747 -0
  154. package/dist/workflow-BpuKEtvn.mjs +725 -0
  155. package/package.json +82 -49
  156. package/dist/ExtensionManager-CPTJhHFg.mjs +0 -2
  157. package/dist/ToolCatalog-Bq4V2sbJ.mjs +0 -67201
  158. package/dist/{CacheAdapters-CzFNpD9a.mjs → CacheAdapters-jJFy20G-.mjs} +0 -0
  159. package/dist/{StealthVerifier-BzBCFiwx.mjs → StealthVerifier-BWmPgQsv.mjs} +0 -0
  160. package/dist/{VersionDetector-CNXcvD46.mjs → VersionDetector-K3V4vGsw.mjs} +0 -0
  161. package/dist/{formatAddress-ChCSIRWT.mjs → formatAddress-nnMvEohD.mjs} +0 -0
  162. package/dist/{types-BBjOqye-.mjs → types-DDBWs9UP.mjs} +1 -1
package/dist/index.mjs CHANGED
@@ -1,22 +1,32 @@
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 { $t as PREDICTIVE_CONFIDENCE_THRESHOLD, An as SEARCH_CACHE_VECTOR_WEIGHT_TOLERANCE, Bn as SEARCH_RECENCY_WINDOW_MS, Ct as MCP_HTTP_KEEPALIVE_TIMEOUT_MS, Dn as SEARCH_AFFINITY_TOP_N, En as SEARCH_AFFINITY_BOOST_FACTOR, Fn as SEARCH_PARAM_TOKEN_WEIGHT, Gn as SEARCH_TIER_PENALTY, Hn as SEARCH_RRF_K, In as SEARCH_PREFIX_MATCH_MULTIPLIER, Jn as SEARCH_TIER_PENALTY_WORKFLOW, Kn as SEARCH_TIER_PENALTY_FULL, Ln as SEARCH_QUERY_CACHE_CAPACITY, M as COMPOUND_LONG_WINDOW_MS, Mn as SEARCH_DOMAIN_HUB_BOOST_MULTIPLIER, Nn as SEARCH_DOMAIN_HUB_THRESHOLD, On as SEARCH_BM25_B, Pn as SEARCH_EXACT_NAME_MATCH_MULTIPLIER, Qn as SEARCH_VECTOR_COSINE_WEIGHT, Rn as SEARCH_RECENCY_MAX_BOOST, St as MCP_HTTP_HEADERS_TIMEOUT_MS, Tn as SEARCH_AFFINITY_BASE_WEIGHT, Un as SEARCH_RRF_RESCALE_FACTOR, Vn as SEARCH_RRF_BM25_BLEND, Wn as SEARCH_SYNONYM_EXPANSION_LIMIT, Xn as SEARCH_TRIGRAM_WEIGHT, Yn as SEARCH_TRIGRAM_THRESHOLD, Zn as SEARCH_VECTOR_BM25_SKIP_THRESHOLD, a as ACTIVATION_TTL_MINUTES, ar as SEARCH_WORKFLOW_DOMAIN_BOOST_MULTIPLIER, bt as MCP_COMPACT_SCHEMA, dn as RUNTIME_ERROR_WINDOW_MS, dt as HTTP_RATE_LIMIT_MAX_IPS, en as PREDICTIVE_DECAY_FACTOR, er as SEARCH_VECTOR_ENABLED, h as AUTOPRUNE_MANUAL_INACTIVITY_MS, i as ACTIVATION_EVENT_HISTORY_MAX, j as COMPOUND_EVENT_WINDOW_MS, jn as SEARCH_COVERAGE_PRECISION_FACTOR, kn as SEARCH_BM25_K1, m as AUTOPRUNE_CHECK_INTERVAL_MS, n as ACTIVATION_COMPOUND_EVAL_EVERY, nn as PREDICTIVE_MAX_SECOND_ORDER_KEYS, nr as SEARCH_VECTOR_LEARN_TOP_N, or as SHUTDOWN_TIMEOUT_MS, p as AUTOPRUNE_AUTO_INACTIVITY_MS, qn as SEARCH_TIER_PENALTY_SEARCH, r as ACTIVATION_COOLDOWN_MS, rr as SEARCH_VECTOR_LEARN_UP, t as ACTIVATION_BOOST_WINDOW_MS, tn as PREDICTIVE_MAX_HISTORY, tr as SEARCH_VECTOR_LEARN_DOWN, un as RUNTIME_ERROR_THRESHOLD, ut as HTTP_CLEANUP_INTERVAL_MS, wt as MCP_HTTP_REQUEST_TIMEOUT_MS, xt as MCP_HTTP_FORCE_CLOSE_TIMEOUT_MS, zn as SEARCH_RECENCY_TRACKER_MAX } from "./constants-CDZLOoVv.mjs";
4
+ import { a as TokenBudgetManager, i as UnifiedCacheManager, n as getArtifactRetentionConfig, r as startArtifactRetentionScheduler, t as cleanupArtifacts } from "./artifactRetention-CPXkUJXp.mjs";
5
+ import { t as DetailedDataManager } from "./DetailedDataManager-HT49OrvF.mjs";
6
+ import { r as asTextResponse, t as asErrorResponse } from "./response-CWhh2aLo.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-5OJdMiF0.mjs";
8
+ import { t as ToolError } from "./ToolError-jh9whhMd.mjs";
9
+ import { t as ProcessRegistry } from "./ProcessRegistry-zGg12QbE.mjs";
10
+ import { c as getConfig, d as DEFAULT_SEARCH_CONFIG, u as validateConfig } from "./outputPaths-um7lCRY3.mjs";
11
+ import { i as reloadExtensions, n as ensureWorkflowsLoaded, r as listExtensions } from "./ExtensionManager-BDMsY2Dz.mjs";
12
+ import { _ as isBrowserOrNetworkTask, a as buildWorkflowToolSequence, b as matchWorkflowRoute, c as getAvailableToolNames, d as getToolDomainFromContext, f as getToolInputSchema, g as detectWorkflowIntent, h as validateToolNameArray, i as buildWorkflowRouteRecommendation, l as getRoutingState, m as normalizeToolName, n as buildRouteMatchMetadata, o as getEffectivePrerequisites, p as isToolActive, r as buildStatelessComputeRecommendations, s as rerankResultsForContext, t as buildPresetRecommendations, u as getToolDescription, v as isMaintenanceTask, y as isStatelessComputeTask } from "./ToolRouter.policy-BGDAGyeH.mjs";
13
+ import { i as generateAntiDebugBypass, r as getInjectionInstructions } from "./HookGeneratorBuilders.core.generators.storage-CTbB4Lcx.mjs";
14
+ import { n as createServerEventBus } from "./EventBus-DFKvADm3.mjs";
7
15
  import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
8
16
  import { CompleteRequestSchema, ErrorCode, McpError } from "@modelcontextprotocol/sdk/types.js";
9
17
  import { promises } from "fs";
10
18
  import { join } from "path";
11
19
  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
20
  import { createServer } from "node:http";
21
+ import { randomUUID, timingSafeEqual } from "node:crypto";
17
22
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
18
23
  import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
19
24
  import { Worker } from "worker_threads";
25
+ import { ZodError, z } from "zod";
26
+ import { readFileSync as readFileSync$1 } from "node:fs";
27
+ import { dirname, resolve } from "node:path";
28
+ import { fileURLToPath } from "node:url";
29
+ import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
20
30
  //#region src/utils/cache.ts
21
31
  var CacheManager = class {
22
32
  config;
@@ -298,7 +308,7 @@ var ToolExecutionRouter = class {
298
308
  * appends `_tabContext` metadata to responses so the LLM always knows which page
299
309
  * it is operating on, preventing silent context drift.
300
310
  *
301
- * Additionally, tracks consecutive identical tool calls and injects `_repeatWarning`
311
+ * Additionally, tracks consecutive identical tool calls and injects `repeatWarning`
302
312
  * when the same tool is called ≥ MAX_CONSECUTIVE_REPEATS times in a row, helping
303
313
  * break LLM degeneration loops (e.g. stealth_inject called 5× instead of page_navigate).
304
314
  */
@@ -336,15 +346,21 @@ const REPEAT_GUARD_EXCLUDES = new Set([
336
346
  const DOMAIN_ALTERNATIVES = new Map([
337
347
  ["stealth", [
338
348
  "page_navigate",
339
- "page_screenshot",
340
- "stealth_verify"
349
+ "page_evaluate",
350
+ "stealth_verify",
351
+ "page_screenshot"
341
352
  ]],
342
353
  ["page", [
343
- "dom_get_structure",
344
- "page_screenshot",
345
- "console_get_logs"
354
+ "browser_jsdom_parse",
355
+ "js_bundle_search",
356
+ "network_get_requests",
357
+ "page_screenshot"
358
+ ]],
359
+ ["console", [
360
+ "page_evaluate",
361
+ "console_get_logs",
362
+ "page_screenshot"
346
363
  ]],
347
- ["console", ["page_evaluate", "page_screenshot"]],
348
364
  ["network", ["network_get_requests", "page_navigate"]],
349
365
  ["captcha", ["captcha_wait", "page_screenshot"]],
350
366
  ["ai_hook", [
@@ -352,8 +368,8 @@ const DOMAIN_ALTERNATIVES = new Map([
352
368
  "page_evaluate",
353
369
  "ai_hook_inject"
354
370
  ]],
355
- ["instrumentation", ["instrumentation_session_list", "instrumentation_artifact_query"]],
356
- ["evidence", ["evidence_query_url", "evidence_chain"]]
371
+ ["instrumentation", ["instrumentation_session", "instrumentation_artifact"]],
372
+ ["evidence", ["evidence_query", "evidence_chain"]]
357
373
  ]);
358
374
  var ToolCallContextGuard = class {
359
375
  /** Memoize prefix-match results — tool names repeat heavily across calls. */
@@ -404,7 +420,7 @@ var ToolCallContextGuard = class {
404
420
  if (!this.isContextSensitive(toolName)) return response;
405
421
  if (response.isError) return response;
406
422
  const provider = this.getProvider();
407
- if (!provider) return response;
423
+ if (!provider || typeof provider.getContextMeta !== "function") return response;
408
424
  const meta = provider.getContextMeta();
409
425
  if (!meta.pageId && meta.tabIndex === null) return response;
410
426
  const content = response.content;
@@ -446,12 +462,17 @@ var ToolCallContextGuard = class {
446
462
  return raw.replace(/\}\s*$/, `,"_tabContext":${compactJson}}`);
447
463
  }
448
464
  /**
449
- * Inject a `_repeatWarning` into the response when a tool call loop is detected.
465
+ * Inject a `repeatWarning` into the response when a tool call loop is detected.
450
466
  * Splices into JSON text content if possible, or appends a new text entry.
451
467
  */
452
468
  injectRepeatWarning(toolName, response) {
453
469
  const prefix = toolName.split("_")[0] ?? "";
454
- const suggestions = (DOMAIN_ALTERNATIVES.get(prefix) ?? ["page_navigate", "page_screenshot"]).filter((t) => t !== toolName);
470
+ const suggestions = (toolName === "page_evaluate" ? [
471
+ "browser_jsdom_parse",
472
+ "js_bundle_search",
473
+ "network_get_requests",
474
+ "page_screenshot"
475
+ ] : DOMAIN_ALTERNATIVES.get(prefix) ?? ["page_navigate", "page_evaluate"]).filter((t) => t !== toolName);
455
476
  const warning = {
456
477
  detected: true,
457
478
  consecutiveCount: this.consecutiveCount,
@@ -467,7 +488,7 @@ var ToolCallContextGuard = class {
467
488
  try {
468
489
  const parsed = JSON.parse(raw);
469
490
  if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
470
- parsed._repeatWarning = warning;
491
+ parsed.repeatWarning = warning;
471
492
  firstText.text = JSON.stringify(parsed, null, 2);
472
493
  return;
473
494
  }
@@ -475,7 +496,7 @@ var ToolCallContextGuard = class {
475
496
  }
476
497
  content.push({
477
498
  type: "text",
478
- text: JSON.stringify({ _repeatWarning: warning }, null, 2)
499
+ text: JSON.stringify({ repeatWarning: warning }, null, 2)
479
500
  });
480
501
  }
481
502
  };
@@ -1024,6 +1045,16 @@ async function closeServer(ctx) {
1024
1045
  if (ctx.shutdownStarted) return ctx.shutdownPromise ?? Promise.resolve();
1025
1046
  ctx.shutdownStarted = true;
1026
1047
  ctx.shutdownPromise = (async () => {
1048
+ const getInst = typeof ctx.getDomainInstance === "function" ? ctx.getDomainInstance.bind(ctx) : null;
1049
+ if (getInst) {
1050
+ const scheduler = getInst("snapshotScheduler");
1051
+ if (scheduler) try {
1052
+ await scheduler.flushAll();
1053
+ scheduler.dispose();
1054
+ } catch (error) {
1055
+ logger.warn("snapshot flush on shutdown failed:", error);
1056
+ }
1057
+ }
1027
1058
  for (const [, entry] of ctx.domainTtlEntries) clearTimeout(entry.timer);
1028
1059
  ctx.domainTtlEntries.clear();
1029
1060
  ctx.detailedData.shutdown();
@@ -1762,7 +1793,8 @@ var EmbeddingEngine = class {
1762
1793
  }
1763
1794
  ensureWorker() {
1764
1795
  if (this.worker) return;
1765
- this.worker = new Worker(new URL("./EmbeddingWorker.js", import.meta.url));
1796
+ const workerPath = new URL("./EmbeddingWorker.js", import.meta.url);
1797
+ this.worker = new Worker(workerPath);
1766
1798
  if (typeof this.worker.unref === "function") this.worker.unref();
1767
1799
  ProcessRegistry.register(this.worker);
1768
1800
  this.worker.on("message", (msg) => {
@@ -1872,7 +1904,7 @@ var TrigramIndex = class TrigramIndex {
1872
1904
  * @param threshold Minimum Jaccard similarity to include in results (default 0.3).
1873
1905
  * @returns Map from document index to similarity score (0–1).
1874
1906
  */
1875
- search(query, threshold = .3) {
1907
+ search(query, threshold = SEARCH_TRIGRAM_THRESHOLD) {
1876
1908
  const queryTrigrams = TrigramIndex.extractTrigrams(query);
1877
1909
  if (queryTrigrams.size === 0) return /* @__PURE__ */ new Map();
1878
1910
  const results = /* @__PURE__ */ new Map();
@@ -2029,6 +2061,13 @@ const PARAM_DESCRIPTION_STOP_WORDS = new Set([
2029
2061
  * and tool metadata for indexing.
2030
2062
  */
2031
2063
  const QueryNormalizer = {
2064
+ /**
2065
+ * Extract parameter names and description tokens from a tool's inputSchema.
2066
+ * Handles both simple flat properties and nested object properties.
2067
+ *
2068
+ * @param inputSchema The tool's inputSchema object
2069
+ * @returns Array of normalized tokens from parameter names and descriptions
2070
+ */
2032
2071
  extractParamTokens(inputSchema) {
2033
2072
  const tokens = [];
2034
2073
  if (!inputSchema || typeof inputSchema !== "object") return tokens;
@@ -2050,6 +2089,13 @@ const QueryNormalizer = {
2050
2089
  }
2051
2090
  return tokens;
2052
2091
  },
2092
+ /**
2093
+ * Extract a short description from a full tool description.
2094
+ * Takes the first sentence and truncates to 120 characters if needed.
2095
+ *
2096
+ * @param description The full tool description
2097
+ * @returns A shortened description suitable for display
2098
+ */
2053
2099
  extractShortDescription(description) {
2054
2100
  if (!description) return "";
2055
2101
  const firstSentence = description.match(/^[^.!?\n]+[.!?]?/);
@@ -2059,28 +2105,27 @@ const QueryNormalizer = {
2059
2105
  }
2060
2106
  return description.length > 120 ? description.slice(0, 117) + "..." : description;
2061
2107
  },
2108
+ /**
2109
+ * Check if a query contains CJK (Chinese, Japanese, Korean) characters.
2110
+ *
2111
+ * @param query The search query
2112
+ * @returns true if the query contains CJK characters
2113
+ */
2062
2114
  containsCJK(query) {
2063
2115
  return /[\u4e00-\u9fff\u3040-\u309f\u30a0-\u30ff\uac00-\ud7af]/.test(query);
2064
2116
  },
2117
+ /**
2118
+ * Normalize a tool name for comparison (lowercase, underscores to hyphens/spaces).
2119
+ *
2120
+ * @param query The search query
2121
+ * @returns Normalized query string
2122
+ */
2065
2123
  normalizeToolName(query) {
2066
2124
  return query.toLowerCase().replace(/[\s-]+/g, "_");
2067
2125
  }
2068
2126
  };
2069
2127
  //#endregion
2070
- //#region src/server/search/ToolSearchEngineImpl.ts
2071
- /**
2072
- * Hybrid BM25 + RRF multi-signal tool search engine for progressive tool discovery.
2073
- *
2074
- * Enhancements:
2075
- * - BM25 keyword scoring with synonym-expanded queries
2076
- * - TF-IDF cosine similarity as an independent RRF signal
2077
- * - Trigram fuzzy matching for typo tolerance
2078
- * - RRF (Reciprocal Rank Fusion) combining all signals
2079
- * - Tool affinity graph with prefix-group expansion (§4.1.4 dependency hull)
2080
- * - Query category adaptive domain weights (§4.1.3 task-type encoding)
2081
- * - Parameter name indexing for schema-aware search
2082
- * - LRU query result cache (§4.3 CSAPC cross-session caching)
2083
- */
2128
+ //#region src/server/search/ToolSearchEngine.helpers.ts
2084
2129
  function findDelimitedIndex(haystack, needle, wordChar) {
2085
2130
  if (!needle) return -1;
2086
2131
  let idx = haystack.indexOf(needle);
@@ -2094,6 +2139,93 @@ function findDelimitedIndex(haystack, needle, wordChar) {
2094
2139
  }
2095
2140
  return -1;
2096
2141
  }
2142
+ function buildAffinityGraph(docs) {
2143
+ const graph = /* @__PURE__ */ new Map();
2144
+ const prefixGroups = /* @__PURE__ */ new Map();
2145
+ for (let i = 0; i < docs.length; i++) {
2146
+ const name = docs[i].name;
2147
+ const underscoreIdx = name.indexOf("_");
2148
+ if (underscoreIdx <= 0) continue;
2149
+ const prefix = name.slice(0, underscoreIdx);
2150
+ const group = prefixGroups.get(prefix) ?? [];
2151
+ group.push(i);
2152
+ prefixGroups.set(prefix, group);
2153
+ }
2154
+ for (const [, members] of prefixGroups) {
2155
+ if (members.length < 2 || members.length > 15) continue;
2156
+ const affinityWeight = SEARCH_AFFINITY_BASE_WEIGHT / Math.sqrt(members.length);
2157
+ for (const src of members) {
2158
+ const edges = graph.get(src) ?? [];
2159
+ for (const dst of members) if (dst !== src) edges.push({
2160
+ docIndex: dst,
2161
+ weight: affinityWeight
2162
+ });
2163
+ graph.set(src, edges);
2164
+ }
2165
+ }
2166
+ return graph;
2167
+ }
2168
+ function rankByScores(scores) {
2169
+ const entries = [];
2170
+ for (let i = 0; i < scores.length; i++) if (scores[i] > 0) entries.push({
2171
+ idx: i,
2172
+ score: scores[i]
2173
+ });
2174
+ entries.sort((a, b) => b.score - a.score);
2175
+ const ranked = /* @__PURE__ */ new Map();
2176
+ for (let rank = 0; rank < entries.length; rank++) ranked.set(entries[rank].idx, rank);
2177
+ return ranked;
2178
+ }
2179
+ function rankByMap(scoreMap) {
2180
+ const entries = [...scoreMap.entries()].toSorted((a, b) => b[1] - a[1]);
2181
+ const ranked = /* @__PURE__ */ new Map();
2182
+ for (let rank = 0; rank < entries.length; rank++) ranked.set(entries[rank][0], rank);
2183
+ return ranked;
2184
+ }
2185
+ function blendRrfIntoScores(scores, rrfScores) {
2186
+ for (let i = 0; i < scores.length; i++) {
2187
+ const rrfScore = rrfScores[i];
2188
+ if (rrfScore <= 0) continue;
2189
+ const bm25Original = scores[i];
2190
+ const rrfRescaled = rrfScore * SEARCH_RRF_RESCALE_FACTOR;
2191
+ const blend = SEARCH_RRF_BM25_BLEND;
2192
+ scores[i] = Math.max(bm25Original, rrfRescaled * blend) + rrfRescaled * blend;
2193
+ }
2194
+ }
2195
+ function applyGraphExpansionToScores(options) {
2196
+ const { scores, docs, affinityGraph } = options;
2197
+ const scored = [];
2198
+ for (let i = 0; i < scores.length; i++) if (scores[i] > 0) scored.push({
2199
+ idx: i,
2200
+ score: scores[i]
2201
+ });
2202
+ if (scored.length === 0) return;
2203
+ scored.sort((a, b) => b.score - a.score);
2204
+ if (affinityGraph.size > 0) {
2205
+ const limit = Math.min(SEARCH_AFFINITY_TOP_N, scored.length);
2206
+ for (let rank = 0; rank < limit; rank++) {
2207
+ const { idx, score } = scored[rank];
2208
+ const neighbors = affinityGraph.get(idx);
2209
+ if (!neighbors) continue;
2210
+ const rankDecay = 1 / (1 + rank);
2211
+ for (const { docIndex, weight } of neighbors) if (scores[docIndex] > 0) scores[docIndex] += score * weight * rankDecay * SEARCH_AFFINITY_BOOST_FACTOR;
2212
+ }
2213
+ }
2214
+ if (SEARCH_DOMAIN_HUB_THRESHOLD > 0 && scored.length >= SEARCH_DOMAIN_HUB_THRESHOLD) {
2215
+ const top10 = scored.slice(0, 10);
2216
+ const domainCounts = /* @__PURE__ */ new Map();
2217
+ for (const { idx } of top10) {
2218
+ const domain = docs[idx].domain;
2219
+ if (domain) domainCounts.set(domain, (domainCounts.get(domain) ?? 0) + 1);
2220
+ }
2221
+ for (const [domain, count] of domainCounts) {
2222
+ if (count < SEARCH_DOMAIN_HUB_THRESHOLD) continue;
2223
+ for (let i = 0; i < docs.length; i++) if (scores[i] > 0 && docs[i].domain === domain) scores[i] *= SEARCH_DOMAIN_HUB_BOOST_MULTIPLIER;
2224
+ }
2225
+ }
2226
+ }
2227
+ //#endregion
2228
+ //#region src/server/search/ToolSearchEngineImpl.ts
2097
2229
  function buildSearchCacheKey(query, topK, visibleDomains) {
2098
2230
  if (!visibleDomains || visibleDomains.size === 0) return `${query}\0${topK}`;
2099
2231
  return `${query}\0${topK}\0${[...visibleDomains].toSorted().join("|")}`;
@@ -2134,8 +2266,6 @@ var ToolSearchEngine = class {
2134
2266
  domainOverrides;
2135
2267
  domainScoreMultipliers;
2136
2268
  toolScoreMultipliers;
2137
- /** IDF values per term, used for TF-IDF cosine computation. */
2138
- idfMap;
2139
2269
  /** Name → doc index for O(1) lookup during affinity expansion. */
2140
2270
  docNameIndex = /* @__PURE__ */ new Map();
2141
2271
  /** Prefix-group affinity graph: docIndex → neighbor edges. */
@@ -2164,7 +2294,8 @@ var ToolSearchEngine = class {
2164
2294
  this.toolScoreMultipliers = toolScoreMultipliers;
2165
2295
  this.docCount = source.length;
2166
2296
  this.bm25Scorer = new BM25ScorerImpl(searchConfig);
2167
- this.embeddingEngine = searchConfig?.vectorEnabled ?? SEARCH_VECTOR_ENABLED ? new EmbeddingEngine() : null;
2297
+ const vectorEnabled = searchConfig?.vectorEnabled ?? SEARCH_VECTOR_ENABLED;
2298
+ this.embeddingEngine = vectorEnabled ? new EmbeddingEngine() : null;
2168
2299
  this.feedbackTracker = new FeedbackTracker(searchConfig);
2169
2300
  this.intentBoost = new IntentBoostImpl(searchConfig?.intentToolBoostRules);
2170
2301
  let totalLength = 0;
@@ -2193,9 +2324,7 @@ var ToolSearchEngine = class {
2193
2324
  length: allTokens.length,
2194
2325
  nameTokens,
2195
2326
  nameTokenSet,
2196
- nameTokenCount: nameTokenSet.size,
2197
- tfidfWeights: /* @__PURE__ */ new Map(),
2198
- tfidfMagnitude: 0
2327
+ nameTokenCount: nameTokenSet.size
2199
2328
  };
2200
2329
  this.docs.push(doc);
2201
2330
  this.docNameIndex.set(tool.name, i);
@@ -2252,31 +2381,30 @@ var ToolSearchEngine = class {
2252
2381
  }
2253
2382
  this.avgDocLength = this.docCount > 0 ? totalLength / this.docCount : 1;
2254
2383
  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
- this.affinityGraph = this.buildAffinityGraph();
2384
+ this.affinityGraph = buildAffinityGraph(this.docs);
2274
2385
  this.trigramIndex = new TrigramIndex(this.docs.map((d) => d.name));
2275
2386
  this.queryCache = new LRUCache(SEARCH_QUERY_CACHE_CAPACITY);
2276
2387
  }
2277
- async search(query, topK = 10, activeToolNames, visibleDomains) {
2278
- const queryTokens = this.bm25Scorer.tokenise(query, { expandSynonyms: true });
2388
+ async search(query, topK = 10, activeToolNames, visibleDomains, profile) {
2389
+ let queryTokens = this.bm25Scorer.tokenise(query);
2279
2390
  if (queryTokens.length === 0) return [];
2391
+ if (queryTokens.length > 6) {
2392
+ const inVocab = queryTokens.filter((t) => this.invertedIndex.has(t));
2393
+ if (inVocab.length >= 3) {
2394
+ const scored = inVocab.map((t) => {
2395
+ const df = this.invertedIndex.get(t).length;
2396
+ return {
2397
+ token: t,
2398
+ idf: Math.log((this.docCount - df + .5) / (df + .5) + 1)
2399
+ };
2400
+ });
2401
+ scored.sort((a, b) => b.idf - a.idf);
2402
+ const kept = new Set(scored.slice(0, 6).map((s) => s.token));
2403
+ queryTokens = queryTokens.filter((t) => kept.has(t));
2404
+ }
2405
+ }
2406
+ const synonymTokens = this.bm25Scorer.tokenise(queryTokens.join(" "), { expandSynonyms: true }).filter((t) => !queryTokens.includes(t));
2407
+ queryTokens.push(...synonymTokens);
2280
2408
  const explicitToolMention = (() => {
2281
2409
  const lower = query.toLowerCase();
2282
2410
  if (!/(?:\b(?:call|use|run|invoke|execute)\b|调用|执行|使用|运行)/i.test(lower)) return null;
@@ -2347,11 +2475,10 @@ var ToolSearchEngine = class {
2347
2475
  const toolMultiplier = this.toolScoreMultipliers?.get(doc.name) ?? 1;
2348
2476
  if (toolMultiplier !== 1) scores[i] *= toolMultiplier;
2349
2477
  }
2350
- this.applyAffinityExpansion(scores);
2351
- this.applyDomainHubExpansion(scores);
2478
+ this.applyGraphExpansion(scores);
2352
2479
  this.applyIntentBonusBand(scores, intentToolBonuses);
2353
2480
  this.applyRecencyBoost(scores);
2354
- this.applyTierPenalty(scores, visibleDomains);
2481
+ this.applyTierPenalty(scores, visibleDomains, profile);
2355
2482
  if (explicitToolMention) {
2356
2483
  const explicitIdx = this.docNameIndex.get(explicitToolMention);
2357
2484
  if (explicitIdx !== void 0) {
@@ -2421,9 +2548,9 @@ var ToolSearchEngine = class {
2421
2548
  * tier. The penalty is a soft multiplier in [0, 1]; 1 disables the feature.
2422
2549
  * Tools without a resolved domain are left untouched.
2423
2550
  */
2424
- applyTierPenalty(scores, visibleDomains) {
2551
+ applyTierPenalty(scores, visibleDomains, profile) {
2425
2552
  if (!visibleDomains || visibleDomains.size === 0) return;
2426
- const penalty = SEARCH_TIER_PENALTY;
2553
+ const penalty = profile ? profile === "full" ? SEARCH_TIER_PENALTY_FULL : profile === "workflow" ? SEARCH_TIER_PENALTY_WORKFLOW : SEARCH_TIER_PENALTY_SEARCH : SEARCH_TIER_PENALTY;
2427
2554
  if (penalty >= 1 || penalty <= 0) return;
2428
2555
  for (let i = 0; i < this.docCount; i++) {
2429
2556
  if (scores[i] <= 0) continue;
@@ -2496,96 +2623,41 @@ var ToolSearchEngine = class {
2496
2623
  * independently contribute — a document with BM25=0 but high trigram
2497
2624
  * similarity can still surface.
2498
2625
  */
2499
- async applyRRFFusion(queryTokens, query, scores) {
2626
+ async applyRRFFusion(_queryTokens, query, scores) {
2500
2627
  const k = SEARCH_RRF_K;
2501
2628
  const trigramWeight = SEARCH_TRIGRAM_WEIGHT;
2502
- const tfidfWeight = SEARCH_TFIDF_COSINE_WEIGHT;
2503
- const bm25Ranked = this.rankByScores(scores);
2504
- const cosineScores = this.computeTfidfCosineScores(queryTokens);
2505
- const cosineRanked = this.rankByMap(cosineScores);
2506
- const trigramScores = this.trigramIndex.search(query, SEARCH_TRIGRAM_THRESHOLD);
2507
- 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);
2629
+ const bm25Ranked = rankByScores(scores);
2630
+ const trigramRanked = rankByMap(this.trigramIndex.search(query, SEARCH_TRIGRAM_THRESHOLD));
2631
+ let vectorScores;
2632
+ let vectorRanked;
2633
+ if (SEARCH_VECTOR_BM25_SKIP_THRESHOLD > 0 && bm25Ranked.size > 0) {
2634
+ const topBm25Idx = [...bm25Ranked.entries()].find(([, r]) => r === 0)?.[0];
2635
+ if ((topBm25Idx !== void 0 ? scores[topBm25Idx] : 0) >= SEARCH_VECTOR_BM25_SKIP_THRESHOLD) {
2636
+ vectorScores = /* @__PURE__ */ new Map();
2637
+ vectorRanked = /* @__PURE__ */ new Map();
2638
+ } else {
2639
+ vectorScores = await this.computeVectorCosineScores(query);
2640
+ vectorRanked = rankByMap(vectorScores);
2641
+ }
2642
+ } else {
2643
+ vectorScores = await this.computeVectorCosineScores(query);
2644
+ vectorRanked = rankByMap(vectorScores);
2514
2645
  }
2646
+ const ranking = /* @__PURE__ */ new Map();
2647
+ for (const [docIdx, rank] of vectorRanked) ranking.set(this.docs[docIdx].name, rank);
2648
+ this.feedbackTracker.recordVectorRanking(ranking);
2649
+ const fusedRrfScores = new Float64Array(this.docCount);
2515
2650
  for (let i = 0; i < this.docCount; i++) {
2516
2651
  let rrfScore = 0;
2517
2652
  const bm25Rank = bm25Ranked.get(i);
2518
2653
  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
2654
  const trigramRank = trigramRanked.get(i);
2522
2655
  if (trigramRank !== void 0 && trigramWeight > 0) rrfScore += trigramWeight * (1 / (k + trigramRank));
2523
2656
  const vectorRank = vectorRanked.get(i);
2524
2657
  if (vectorRank !== void 0 && this.feedbackTracker.getVectorWeight() > 0) rrfScore += this.feedbackTracker.getVectorWeight() * (1 / (k + vectorRank));
2525
- if (rrfScore > 0) {
2526
- const bm25Original = scores[i];
2527
- const rrfRescaled = rrfScore * SEARCH_RRF_RESCALE_FACTOR;
2528
- const blend = SEARCH_RRF_BM25_BLEND;
2529
- scores[i] = Math.max(bm25Original, rrfRescaled * blend) + rrfRescaled * blend;
2530
- }
2658
+ fusedRrfScores[i] = rrfScore;
2531
2659
  }
2532
- }
2533
- /**
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
- * Rank documents by Float64Array scores.
2567
- * Returns Map<docIndex, rank> (0-based, lower = better).
2568
- */
2569
- rankByScores(scores) {
2570
- const entries = [];
2571
- for (let i = 0; i < scores.length; i++) if (scores[i] > 0) entries.push({
2572
- idx: i,
2573
- score: scores[i]
2574
- });
2575
- entries.sort((a, b) => b.score - a.score);
2576
- const ranked = /* @__PURE__ */ new Map();
2577
- for (let rank = 0; rank < entries.length; rank++) ranked.set(entries[rank].idx, rank);
2578
- return ranked;
2579
- }
2580
- /**
2581
- * Rank documents by a score map.
2582
- * Returns Map<docIndex, rank> (0-based, lower = better).
2583
- */
2584
- rankByMap(scoreMap) {
2585
- const entries = [...scoreMap.entries()].toSorted((a, b) => b[1] - a[1]);
2586
- const ranked = /* @__PURE__ */ new Map();
2587
- for (let rank = 0; rank < entries.length; rank++) ranked.set(entries[rank][0], rank);
2588
- return ranked;
2660
+ blendRrfIntoScores(scores, fusedRrfScores);
2589
2661
  }
2590
2662
  /**
2591
2663
  * Lazy-compute and cache tool description embeddings.
@@ -2674,82 +2746,16 @@ var ToolSearchEngine = class {
2674
2746
  }
2675
2747
  /**
2676
2748
  * Build prefix-group affinity graph (§4.1.4 dependency hull).
2677
- * Tools sharing a name prefix (e.g. "breakpoint_set", "breakpoint_list")
2749
+ * Tools sharing a name prefix (e.g. legacy "breakpoint_set"/"breakpoint_list"
2750
+ * or unified families such as "memory_*")
2678
2751
  * form an affinity group with mutual edges.
2679
2752
  */
2680
- buildAffinityGraph() {
2681
- const graph = /* @__PURE__ */ new Map();
2682
- const prefixGroups = /* @__PURE__ */ new Map();
2683
- for (let i = 0; i < this.docCount; i++) {
2684
- const name = this.docs[i].name;
2685
- const underscoreIdx = name.indexOf("_");
2686
- if (underscoreIdx <= 0) continue;
2687
- const prefix = name.slice(0, underscoreIdx);
2688
- const group = prefixGroups.get(prefix) ?? [];
2689
- group.push(i);
2690
- prefixGroups.set(prefix, group);
2691
- }
2692
- for (const [, members] of prefixGroups) {
2693
- if (members.length < 2 || members.length > 15) continue;
2694
- const affinityWeight = SEARCH_AFFINITY_BASE_WEIGHT / Math.sqrt(members.length);
2695
- for (const src of members) {
2696
- const edges = graph.get(src) ?? [];
2697
- for (const dst of members) if (dst !== src) edges.push({
2698
- docIndex: dst,
2699
- weight: affinityWeight
2700
- });
2701
- graph.set(src, edges);
2702
- }
2703
- }
2704
- return graph;
2705
- }
2706
- /**
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.
2710
- */
2711
- applyAffinityExpansion(scores) {
2712
- if (this.affinityGraph.size === 0) return;
2713
- const topN = SEARCH_AFFINITY_TOP_N;
2714
- const scored = [];
2715
- for (let i = 0; i < this.docCount; i++) if (scores[i] > 0) scored.push({
2716
- idx: i,
2717
- score: scores[i]
2718
- });
2719
- 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;
2728
- }
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
- 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]
2753
+ applyGraphExpansion(scores) {
2754
+ applyGraphExpansionToScores({
2755
+ scores,
2756
+ docs: this.docs,
2757
+ affinityGraph: this.affinityGraph
2741
2758
  });
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;
2752
- }
2753
2759
  }
2754
2760
  };
2755
2761
  //#endregion
@@ -2788,18 +2794,22 @@ function getVisibleDomainsForTier(ctx) {
2788
2794
  }
2789
2795
  return visible;
2790
2796
  }
2797
+ function getBaseTier(ctx) {
2798
+ return ctx.baseTier;
2799
+ }
2791
2800
  function getExtensionDomainMap(ctx) {
2792
2801
  const map = /* @__PURE__ */ new Map();
2793
2802
  for (const record of ctx.extensionToolsByName.values()) map.set(record.name, record.domain);
2794
2803
  return map;
2795
2804
  }
2796
- function getCombinedTools(ctx) {
2805
+ async function getCombinedTools(ctx) {
2806
+ await ensureAllDomainsLoaded();
2797
2807
  const tools = new Map(allTools.map((tool) => [tool.name, tool]));
2798
2808
  for (const record of ctx.extensionToolsByName.values()) tools.set(record.name, record.tool);
2799
2809
  return [...tools.values()];
2800
2810
  }
2801
- function getToolByName(ctx) {
2802
- return new Map(getCombinedTools(ctx).map((tool) => [tool.name, tool]));
2811
+ async function getToolByName(ctx) {
2812
+ return new Map((await getCombinedTools(ctx)).map((tool) => [tool.name, tool]));
2803
2813
  }
2804
2814
  const searchEngineCache = /* @__PURE__ */ new WeakMap();
2805
2815
  /**
@@ -2812,11 +2822,12 @@ function buildSearchSignature(ctx) {
2812
2822
  extParts.sort();
2813
2823
  return [ctx.extensionWorkflowRuntimeById.size, extParts.join("|")].join("::");
2814
2824
  }
2815
- function getSearchEngine(ctx) {
2825
+ async function getSearchEngine(ctx) {
2826
+ await ensureAllDomainsLoaded();
2816
2827
  const signature = buildSearchSignature(ctx);
2817
2828
  const cached = searchEngineCache.get(ctx);
2818
2829
  if (cached?.signature === signature) return cached.engine;
2819
- const tools = getCombinedTools(ctx);
2830
+ const tools = await getCombinedTools(ctx);
2820
2831
  const extensionDomains = getExtensionDomainMap(ctx);
2821
2832
  const domainScoreMultipliers = /* @__PURE__ */ new Map();
2822
2833
  const toolScoreMultipliers = /* @__PURE__ */ new Map();
@@ -2833,14 +2844,14 @@ function getSearchEngine(ctx) {
2833
2844
  });
2834
2845
  return engine;
2835
2846
  }
2836
- /** Generate domain summary description from discovered manifests. */
2847
+ /** Generate domain summary description. Uses metadata when not all domains are loaded. */
2837
2848
  function buildDomainDescription(ctx) {
2838
2849
  const groups = {};
2839
2850
  for (const r of getAllRegistrations()) groups[r.domain] = (groups[r.domain] ?? 0) + 1;
2840
2851
  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}.`;
2852
+ const loadedCount = getAllRegistrations().length;
2853
+ const extensionCount = ctx.extensionToolsByName.size;
2854
+ 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
2855
  }
2845
2856
  //#endregion
2846
2857
  //#region src/server/MCPServer.search.handlers.domain.ts
@@ -2853,12 +2864,13 @@ async function handleActivateDomain(ctx, args) {
2853
2864
  success: false,
2854
2865
  error: "domain must be a non-empty string"
2855
2866
  }));
2856
- const validDomains = new Set(getAllDomains());
2867
+ const validDomains = new Set(getAllKnownDomains());
2857
2868
  for (const record of ctx.extensionToolsByName.values()) validDomains.add(record.domain);
2858
2869
  if (!validDomains.has(domain)) return asTextResponse(JSON.stringify({
2859
2870
  success: false,
2860
2871
  error: `Unknown domain "${domain}". Valid: ${[...validDomains].join(", ")}`
2861
2872
  }));
2873
+ await ensureDomainLoaded(domain);
2862
2874
  const ttlMinutes = typeof args.ttlMinutes === "number" ? args.ttlMinutes : ACTIVATION_TTL_MINUTES;
2863
2875
  const domainTools = [...getToolsByDomains([domain]), ...[...ctx.extensionToolsByName.values()].filter((record) => record.domain === domain).map((record) => record.tool)];
2864
2876
  const activeNames = getActiveToolNames(ctx);
@@ -3416,7 +3428,8 @@ var ActivationController = class {
3416
3428
  this.boostRules = [...DEFAULT_BOOST_RULES, ...customRules].toSorted((a, b) => b.priority - a.priority);
3417
3429
  this.compoundEngine = new CompoundConditionEngine();
3418
3430
  this.predictiveBooster = new PredictiveBooster();
3419
- this.autoPruner = new AutoPruner(eventBus, new Set(getProfileDomains(ctx.baseTier)), (domain) => {
3431
+ const baseDomains = new Set(getProfileDomains(ctx.baseTier));
3432
+ this.autoPruner = new AutoPruner(eventBus, baseDomains, (domain) => {
3420
3433
  logger.info(`[ActivationController] Auto-pruning domain "${domain}"`);
3421
3434
  });
3422
3435
  this.subscribe();
@@ -3648,10 +3661,27 @@ function handleToolError(toolName, error) {
3648
3661
  logger.error(`Tool execution failed: ${toolName}`, error);
3649
3662
  throw new McpError(ErrorCode.InternalError, `Execution Failed in ${toolName}: ${error instanceof Error ? error.message : String(error)}`);
3650
3663
  }
3664
+ function stripParamDescriptions(schema) {
3665
+ const clone = { ...schema };
3666
+ if (clone.properties) {
3667
+ const props = {};
3668
+ for (const [key, val] of Object.entries(clone.properties)) {
3669
+ const { description: _d, ...rest } = val;
3670
+ props[key] = stripParamDescriptions(rest);
3671
+ }
3672
+ clone.properties = props;
3673
+ }
3674
+ if (clone.items && typeof clone.items === "object") {
3675
+ const { description: _d, ...rest } = clone.items;
3676
+ clone.items = stripParamDescriptions(rest);
3677
+ }
3678
+ if (clone.additionalProperties && typeof clone.additionalProperties === "object" && !Array.isArray(clone.additionalProperties)) clone.additionalProperties = stripParamDescriptions(clone.additionalProperties);
3679
+ return clone;
3680
+ }
3651
3681
  function registerSingleTool(ctx, toolDef) {
3652
3682
  const builtTool = toolDef;
3653
- if (builtTool.__autocomplete) ctx.toolAutocompleteHandlers.set(toolDef.name, builtTool.__autocomplete);
3654
- const rawSchema = toolDef.inputSchema;
3683
+ if (builtTool.autocompleteHandlers) ctx.toolAutocompleteHandlers.set(toolDef.name, builtTool.autocompleteHandlers);
3684
+ const rawSchema = MCP_COMPACT_SCHEMA && toolDef.inputSchema ? stripParamDescriptions(toolDef.inputSchema) : toolDef.inputSchema;
3655
3685
  const shape = rawSchema && typeof rawSchema === "object" ? buildZodShape(rawSchema) : {};
3656
3686
  const description = toolDef.description ?? toolDef.name;
3657
3687
  if (Object.keys(shape).length > 0) {
@@ -3668,7 +3698,7 @@ function registerSingleTool(ctx, toolDef) {
3668
3698
  }
3669
3699
  });
3670
3700
  if (builtTool.execution) {
3671
- const sdkInternalMap = ctx.server._registeredTools;
3701
+ const sdkInternalMap = ctx.server.registeredTools;
3672
3702
  if (sdkInternalMap && sdkInternalMap[toolDef.name]) sdkInternalMap[toolDef.name].execution = builtTool.execution;
3673
3703
  }
3674
3704
  return registeredTool;
@@ -3683,7 +3713,7 @@ function registerSingleTool(ctx, toolDef) {
3683
3713
  }
3684
3714
  });
3685
3715
  if (builtTool.execution) {
3686
- const sdkInternalMap = ctx.server._registeredTools;
3716
+ const sdkInternalMap = ctx.server.registeredTools;
3687
3717
  if (sdkInternalMap && sdkInternalMap[toolDef.name]) sdkInternalMap[toolDef.name].execution = builtTool.execution;
3688
3718
  }
3689
3719
  return registeredTool;
@@ -3737,7 +3767,7 @@ async function routeToolRequest(request, ctx, searchEngine) {
3737
3767
  const availableToolNames = getAvailableToolNames(ctx);
3738
3768
  const routeMatch = matchWorkflowRoute(task, ctx);
3739
3769
  let presetPlannedToolNames = null;
3740
- const searchResults = await searchEngine.search(task, maxRecommendations * 2, activeNames, visibleDomains);
3770
+ const searchResults = await searchEngine.search(task, maxRecommendations * 2, activeNames, visibleDomains, getBaseTier(ctx));
3741
3771
  let finalResults = [];
3742
3772
  if (routeMatch?.workflow.route.kind === "preset") {
3743
3773
  const presetTools = buildPresetRecommendations(routeMatch, routingState, ctx, availableToolNames);
@@ -3749,17 +3779,25 @@ async function routeToolRequest(request, ctx, searchEngine) {
3749
3779
  const workflowResult = buildWorkflowRouteRecommendation(routeMatch, ctx);
3750
3780
  finalResults = [workflowResult, ...searchResults.filter((result) => result.name !== workflowResult.name)];
3751
3781
  } else if (workflow) {
3782
+ const statelessWorkflow = isStatelessComputeTask(task);
3752
3783
  const workflowSequence = buildWorkflowToolSequence(workflow, routingState, availableToolNames);
3753
3784
  const workflowTools = workflowSequence.map((name, index) => ({
3754
3785
  name,
3755
3786
  domain: getToolDomainFromContext(name, ctx),
3756
3787
  shortDescription: searchResults.find((r) => r.name === name)?.shortDescription ?? ctx.extensionToolsByName.get(name)?.tool.description ?? "",
3757
- score: workflow.priority - index * .01,
3788
+ score: (statelessWorkflow ? 90 : workflow.priority) - index * .01,
3758
3789
  isActive: isToolActive(name, ctx)
3759
3790
  }));
3760
3791
  const workflowNames = new Set(workflowSequence);
3761
3792
  const otherResults = searchResults.filter((result) => !workflowNames.has(result.name));
3762
3793
  finalResults = [...workflowTools, ...otherResults];
3794
+ } else if (task && !isBrowserOrNetworkTask(task, workflow) && !isMaintenanceTask(task)) {
3795
+ const statelessRecommendations = buildStatelessComputeRecommendations(task, ctx, availableToolNames);
3796
+ if (statelessRecommendations.length > 0) {
3797
+ const statelessNames = new Set(statelessRecommendations.map((tool) => tool.name));
3798
+ const otherResults = searchResults.filter((result) => !statelessNames.has(result.name));
3799
+ finalResults = [...statelessRecommendations, ...otherResults];
3800
+ } else finalResults = [...searchResults];
3763
3801
  } else finalResults = [...searchResults];
3764
3802
  const dedupedResults = [];
3765
3803
  const seenNames = /* @__PURE__ */ new Set();
@@ -3904,10 +3942,10 @@ async function routeToolRequest(request, ctx, searchEngine) {
3904
3942
  async function handleSearchTools(ctx, args) {
3905
3943
  const query = args.query;
3906
3944
  const topK = args.top_k ?? 10;
3907
- const engine = getSearchEngine(ctx);
3945
+ const engine = await getSearchEngine(ctx);
3908
3946
  const activeNames = getActiveToolNames(ctx);
3909
3947
  const visibleDomains = getVisibleDomainsForTier(ctx);
3910
- const results = await engine.search(query, topK, activeNames, visibleDomains);
3948
+ const results = await engine.search(query, topK, activeNames, visibleDomains, getBaseTier(ctx));
3911
3949
  const topResult = results[0];
3912
3950
  const topTool = topResult ? describeTool(topResult.name, ctx) : null;
3913
3951
  const topExampleArgs = topTool ? generateExampleArgs(topTool.inputSchema) : void 0;
@@ -3934,12 +3972,14 @@ async function handleSearchTools(ctx, args) {
3934
3972
  exampleArgs: topExampleArgs,
3935
3973
  description: `Call ${topResult.name} directly. Use describe_tool("${topResult.name}") only if you need the full schema.`
3936
3974
  });
3975
+ 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.";
3976
+ 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
3977
  const response = {
3938
3978
  query,
3939
3979
  resultCount: results.length,
3940
3980
  results,
3941
3981
  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."
3982
+ hint: baseHint + refinementHint
3943
3983
  };
3944
3984
  return asTextResponse(JSON.stringify(response, null, 2));
3945
3985
  }
@@ -3957,6 +3997,7 @@ async function notifyToolListChanged(ctx, changed) {
3957
3997
  }
3958
3998
  }
3959
3999
  async function activateToolNames(ctx, names) {
4000
+ await ensureAllDomainsLoaded();
3960
4001
  const activeNames = getActiveToolNames(ctx);
3961
4002
  const activated = [];
3962
4003
  const alreadyActive = [];
@@ -3967,7 +4008,7 @@ async function activateToolNames(ctx, names) {
3967
4008
  alreadyActive.push(name);
3968
4009
  continue;
3969
4010
  }
3970
- const toolDef = getToolByName(ctx).get(name);
4011
+ const toolDef = (await getToolByName(ctx)).get(name);
3971
4012
  if (!toolDef) {
3972
4013
  notFound.push(name);
3973
4014
  continue;
@@ -4067,7 +4108,7 @@ async function handleRouteTool(ctx, args) {
4067
4108
  success: false,
4068
4109
  error: "task must be a non-empty string"
4069
4110
  }));
4070
- const engine = getSearchEngine(ctx);
4111
+ const engine = await getSearchEngine(ctx);
4071
4112
  const autoActivate = context?.autoActivate === true;
4072
4113
  let response = populateCallCommands(await routeToolRequest({
4073
4114
  task,
@@ -4142,6 +4183,7 @@ function buildCallToolMetadata(wasAutoActivated, activatedTools) {
4142
4183
  };
4143
4184
  }
4144
4185
  function attachCallToolMetadata(response, metadata) {
4186
+ if (!response?.content || !Array.isArray(response.content)) return response;
4145
4187
  return {
4146
4188
  ...response,
4147
4189
  content: response.content.map((item) => {
@@ -4181,7 +4223,7 @@ async function handleCallTool(ctx, args) {
4181
4223
  try {
4182
4224
  const response = await ctx.executeToolWithTracking(name, toolArgs);
4183
4225
  try {
4184
- getSearchEngine(ctx).recordToolCallFeedback(name, "");
4226
+ (await getSearchEngine(ctx)).recordToolCallFeedback(name, "");
4185
4227
  } catch {}
4186
4228
  return attachCallToolMetadata(response, callMetadata);
4187
4229
  } catch (error) {
@@ -4206,7 +4248,7 @@ function buildMetaToolDefinitions(ctx) {
4206
4248
  properties: {
4207
4249
  query: {
4208
4250
  type: "string",
4209
- description: "Search query: keywords, tool name, domain name, or description fragment"
4251
+ 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
4252
  },
4211
4253
  top_k: {
4212
4254
  type: "number",
@@ -4237,7 +4279,7 @@ function buildMetaToolDefinitions(ctx) {
4237
4279
  },
4238
4280
  autoActivate: {
4239
4281
  type: "boolean",
4240
- description: "Whether to auto-activate recommended tools (default: true)"
4282
+ description: "Whether to auto-activate recommended tools (default: false)"
4241
4283
  },
4242
4284
  maxRecommendations: {
4243
4285
  type: "number",
@@ -4293,7 +4335,7 @@ function buildMetaToolDefinitions(ctx) {
4293
4335
  },
4294
4336
  {
4295
4337
  name: "activate_domain",
4296
- description: `Activate all tools in a domain at once. Domains: ${[...getAllDomains()].join(", ")}. Use extensions_reload first to include external plugin/workflow domains.`,
4338
+ description: `Activate all tools in a domain at once. Domains: ${[...getAllDomains()].join(", ")}. Use reload_extensions first to include external plugin/workflow domains.`,
4297
4339
  inputSchema: {
4298
4340
  type: "object",
4299
4341
  properties: {
@@ -4312,7 +4354,7 @@ function buildMetaToolDefinitions(ctx) {
4312
4354
  },
4313
4355
  {
4314
4356
  name: "call_tool",
4315
- description: "Execute any tool by name with auto-activation. Use this when activate_tools/activate_domain registered a tool but it does not appear in your tool list (common for clients that do not support tools/list_changed notifications). Accepts the tool name and its arguments object; returns the tool's native response.",
4357
+ description: "Execute an already-active tool by name. Use this when activate_tools/activate_domain registered a tool but your client did not refresh its tool list. Does not auto-activate inactive tools.",
4316
4358
  inputSchema: {
4317
4359
  type: "object",
4318
4360
  properties: {
@@ -4482,7 +4524,164 @@ Generally, you have three options to deploy hooks:
4482
4524
  }] }));
4483
4525
  }
4484
4526
  //#endregion
4527
+ //#region src/server/persistence/RuntimeSnapshotScheduler.ts
4528
+ var RuntimeSnapshotScheduler = class {
4529
+ sources = [];
4530
+ debounceTimer = null;
4531
+ periodicTimer = null;
4532
+ debounceMs;
4533
+ periodicMs;
4534
+ disposed = false;
4535
+ started = false;
4536
+ constructor(options) {
4537
+ this.debounceMs = options?.debounceMs ?? 2e3;
4538
+ this.periodicMs = options?.periodicMs ?? 3e4;
4539
+ }
4540
+ register(filePath, source) {
4541
+ const existing = this.sources.find((entry) => entry.filePath === filePath || entry.source === source);
4542
+ if (existing) {
4543
+ if (existing.filePath !== filePath || existing.source !== source) logger.warn(`skipping conflicting snapshot registration for ${filePath}`);
4544
+ return;
4545
+ }
4546
+ const entry = {
4547
+ source,
4548
+ filePath
4549
+ };
4550
+ this.sources.push(entry);
4551
+ if (this.started) this.restoreOne(entry).catch((err) => logger.warn(`snapshot restore failed for ${entry.filePath}:`, err));
4552
+ }
4553
+ async start() {
4554
+ if (this.started || this.disposed) return;
4555
+ this.started = true;
4556
+ await this.restoreAll();
4557
+ if (this.disposed || this.periodicTimer) return;
4558
+ this.periodicTimer = setInterval(() => {
4559
+ this.scheduleFlush().catch((err) => logger.warn("periodic snapshot failed:", err));
4560
+ }, this.periodicMs);
4561
+ }
4562
+ notifyDirty() {
4563
+ if (this.disposed) return;
4564
+ if (this.debounceTimer) clearTimeout(this.debounceTimer);
4565
+ this.debounceTimer = setTimeout(() => {
4566
+ this.scheduleFlush().catch((err) => logger.warn("debounce snapshot failed:", err));
4567
+ }, this.debounceMs);
4568
+ }
4569
+ async flushAll() {
4570
+ if (this.debounceTimer) {
4571
+ clearTimeout(this.debounceTimer);
4572
+ this.debounceTimer = null;
4573
+ }
4574
+ await this.writeDirtySources();
4575
+ }
4576
+ dispose() {
4577
+ this.disposed = true;
4578
+ if (this.debounceTimer) {
4579
+ clearTimeout(this.debounceTimer);
4580
+ this.debounceTimer = null;
4581
+ }
4582
+ if (this.periodicTimer) {
4583
+ clearInterval(this.periodicTimer);
4584
+ this.periodicTimer = null;
4585
+ }
4586
+ }
4587
+ async restoreAll() {
4588
+ for (const entry of this.sources) await this.restoreOne(entry);
4589
+ }
4590
+ async restoreOne(entry) {
4591
+ try {
4592
+ const data = await readFile(entry.filePath, "utf-8");
4593
+ const parsed = JSON.parse(data);
4594
+ entry.source.restoreSnapshot(parsed);
4595
+ logger.info(`restored snapshot from ${entry.filePath}`);
4596
+ } catch {}
4597
+ }
4598
+ async scheduleFlush() {
4599
+ await this.writeDirtySources();
4600
+ }
4601
+ async writeDirtySources() {
4602
+ for (const entry of this.sources) {
4603
+ if (!entry.source.isPersistDirty()) continue;
4604
+ try {
4605
+ await this.writeSnapshot(entry);
4606
+ } catch (err) {
4607
+ logger.warn(`snapshot write failed for ${entry.filePath}:`, err);
4608
+ }
4609
+ }
4610
+ }
4611
+ async writeSnapshot(entry) {
4612
+ await mkdir(dirname(entry.filePath), { recursive: true });
4613
+ const data = JSON.stringify(entry.source.exportSnapshot());
4614
+ const tmpPath = entry.filePath + ".tmp";
4615
+ await writeFile(tmpPath, data, "utf-8");
4616
+ await rename(tmpPath, entry.filePath);
4617
+ entry.source.markPersisted();
4618
+ }
4619
+ };
4620
+ function getStateDir(baseDir) {
4621
+ return resolve(baseDir, ".jshookmcp", "state");
4622
+ }
4623
+ //#endregion
4485
4624
  //#region src/server/MCPServer.ts
4625
+ function shouldCollectExecutionMetrics() {
4626
+ return process.env.E2E_COLLECT_PERFORMANCE === "1";
4627
+ }
4628
+ function captureExecutionMetricMemory() {
4629
+ const memory = process.memoryUsage();
4630
+ return {
4631
+ source: "server",
4632
+ rssBytes: memory.rss,
4633
+ privateBytes: null,
4634
+ virtualBytes: null,
4635
+ heapUsedBytes: memory.heapUsed,
4636
+ heapTotalBytes: memory.heapTotal,
4637
+ externalBytes: memory.external,
4638
+ arrayBuffersBytes: memory.arrayBuffers
4639
+ };
4640
+ }
4641
+ function buildExecutionMetrics(startedAt, startTime, timeoutMs, cpuStart, memoryBefore) {
4642
+ const finishedAt = (/* @__PURE__ */ new Date()).toISOString();
4643
+ const cpuUsage = process.cpuUsage(cpuStart);
4644
+ const memoryAfter = captureExecutionMetricMemory();
4645
+ return {
4646
+ source: "server",
4647
+ startedAt,
4648
+ finishedAt,
4649
+ elapsedMs: Number((performance.now() - startTime).toFixed(2)),
4650
+ timeoutMs,
4651
+ serverPid: process.pid,
4652
+ cpuUserMicros: cpuUsage.user,
4653
+ cpuSystemMicros: cpuUsage.system,
4654
+ memoryBefore,
4655
+ memoryAfter,
4656
+ memoryDelta: {
4657
+ rssBytes: memoryAfter.rssBytes - memoryBefore.rssBytes,
4658
+ privateBytes: null,
4659
+ virtualBytes: null,
4660
+ heapUsedBytes: memoryAfter.heapUsedBytes - memoryBefore.heapUsedBytes,
4661
+ heapTotalBytes: memoryAfter.heapTotalBytes - memoryBefore.heapTotalBytes,
4662
+ externalBytes: memoryAfter.externalBytes - memoryBefore.externalBytes,
4663
+ arrayBuffersBytes: memoryAfter.arrayBuffersBytes - memoryBefore.arrayBuffersBytes
4664
+ }
4665
+ };
4666
+ }
4667
+ function appendExecutionMetrics(response, metrics) {
4668
+ const content = response.content;
4669
+ if (!Array.isArray(content)) return response;
4670
+ const firstText = content.find((entry) => typeof entry === "object" && entry !== null && entry.type === "text" && typeof entry.text === "string");
4671
+ if (!firstText) return response;
4672
+ try {
4673
+ const parsed = JSON.parse(firstText.text);
4674
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return response;
4675
+ const record = parsed;
4676
+ if (!("_executionMetrics" in record)) {
4677
+ record._executionMetrics = metrics;
4678
+ firstText.text = JSON.stringify(record);
4679
+ }
4680
+ } catch {
4681
+ return response;
4682
+ }
4683
+ return response;
4684
+ }
4486
4685
  var MCPServer = class {
4487
4686
  config;
4488
4687
  server;
@@ -4538,12 +4737,32 @@ var MCPServer = class {
4538
4737
  this.enabledDomains = this.resolveEnabledDomains(this.selectedTools);
4539
4738
  const depsEntries = [];
4540
4739
  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
- })]);
4740
+ const loadedByDomain = new Map(manifests.map((m) => [m.domain, m]));
4741
+ const allMeta = getLoaderMetadata();
4742
+ if (!Array.isArray(allMeta)) logger.warn("[MCPServer] getLoaderMetadata returned non-array, skipping domain proxy setup");
4743
+ else for (const meta of allMeta) {
4744
+ const loaded = loadedByDomain.get(meta.domain);
4745
+ if (loaded) {
4746
+ depsEntries.push([meta.depKey, createDomainProxy(this, meta.domain, `${meta.domain}:${meta.depKey}`, () => loaded.ensure(this))]);
4747
+ if (loaded.secondaryDepKeys) {
4748
+ for (const key of loaded.secondaryDepKeys) if (!depsEntries.some(([k]) => k === key)) depsEntries.push([key, createDomainProxy(this, meta.domain, `${meta.domain}:${key}`, async () => {
4749
+ await loaded.ensure(this);
4750
+ return this[key];
4751
+ })]);
4752
+ }
4753
+ } else {
4754
+ depsEntries.push([meta.depKey, createDomainProxy(this, meta.domain, `${meta.domain}:${meta.depKey}`, async () => {
4755
+ const manifest = await ensureDomainLoaded(meta.domain);
4756
+ if (!manifest) throw new Error(`Failed to load domain ${meta.domain}`);
4757
+ return manifest.ensure(this);
4758
+ })]);
4759
+ for (const key of meta.secondaryDepKeys) if (!depsEntries.some(([k]) => k === key)) depsEntries.push([key, createDomainProxy(this, meta.domain, `${meta.domain}:${key}`, async () => {
4760
+ const manifest = await ensureDomainLoaded(meta.domain);
4761
+ if (!manifest) throw new Error(`Failed to load domain ${meta.domain}`);
4762
+ await manifest.ensure(this);
4763
+ return this[key];
4764
+ })]);
4765
+ }
4547
4766
  }
4548
4767
  this.handlerDeps = Object.fromEntries(depsEntries);
4549
4768
  const selectedToolNames = new Set(this.selectedTools.map((t) => t.name));
@@ -4580,6 +4799,11 @@ var MCPServer = class {
4580
4799
  this.samplingBridge = new LLMSamplingBridge(this.server);
4581
4800
  this.elicitationBridge = new ElicitationBridge(this.server);
4582
4801
  this.setDomainInstance("activationController", new ActivationController(this.eventBus, this));
4802
+ const stateDir = getStateDir(process.cwd());
4803
+ const snapshotScheduler = new RuntimeSnapshotScheduler();
4804
+ this.setDomainInstance("snapshotScheduler", snapshotScheduler);
4805
+ this.setDomainInstance("snapshotStateDir", stateDir);
4806
+ snapshotScheduler.start().catch((err) => logger.warn("snapshot scheduler start failed:", err));
4583
4807
  this.eventBus.on("tool:progress", async (payload) => {
4584
4808
  try {
4585
4809
  await this.server.server.notification({
@@ -4658,7 +4882,7 @@ var MCPServer = class {
4658
4882
  }
4659
4883
  this.cacheRegistrationPromise = (async () => {
4660
4884
  try {
4661
- const { createCacheAdapters } = await import("./CacheAdapters-CzFNpD9a.mjs");
4885
+ const { createCacheAdapters } = await import("./CacheAdapters-jJFy20G-.mjs");
4662
4886
  const codeCache = this.collector.getCache();
4663
4887
  const codeCompressor = this.collector.getCompressor();
4664
4888
  const adapters = createCacheAdapters(this.detailedData, codeCache, codeCompressor);
@@ -4679,6 +4903,12 @@ var MCPServer = class {
4679
4903
  }
4680
4904
  async executeToolWithTracking(name, args) {
4681
4905
  let timeoutTimer;
4906
+ const timeoutMs = 3e4;
4907
+ const collectExecutionMetrics = shouldCollectExecutionMetrics();
4908
+ const executionStartedAt = collectExecutionMetrics ? (/* @__PURE__ */ new Date()).toISOString() : null;
4909
+ const executionStartTime = collectExecutionMetrics ? performance.now() : 0;
4910
+ const executionCpuStart = collectExecutionMetrics ? process.cpuUsage() : null;
4911
+ const executionMemoryBefore = collectExecutionMetrics ? captureExecutionMetricMemory() : null;
4682
4912
  try {
4683
4913
  timeoutTimer = setTimeout(() => {
4684
4914
  try {
@@ -4687,7 +4917,7 @@ var MCPServer = class {
4687
4917
  } catch {
4688
4918
  logger.warn(`Telemetry Alert [ERR-03]: Tool execution hung (>30s) for '${name}'.`);
4689
4919
  }
4690
- }, 3e4);
4920
+ }, timeoutMs);
4691
4921
  timeoutTimer.unref();
4692
4922
  let response;
4693
4923
  try {
@@ -4696,7 +4926,8 @@ var MCPServer = class {
4696
4926
  if (timeoutTimer) clearTimeout(timeoutTimer);
4697
4927
  }
4698
4928
  this.contextGuard.recordCall(name);
4699
- const enriched = this.contextGuard.enrichResponse(name, response);
4929
+ let enriched = this.contextGuard.enrichResponse(name, response);
4930
+ if (collectExecutionMetrics && executionStartedAt && executionCpuStart && executionMemoryBefore) enriched = appendExecutionMetrics(enriched, buildExecutionMetrics(executionStartedAt, executionStartTime, timeoutMs, executionCpuStart, executionMemoryBefore));
4700
4931
  try {
4701
4932
  this.tokenBudget.recordToolCall(name, args, enriched);
4702
4933
  } catch (trackingError) {
@@ -4910,7 +5141,8 @@ async function main() {
4910
5141
  if (cleanup.removedFiles > 0) logger.info(`[artifacts] Startup cleanup removed ${cleanup.removedFiles} files (${cleanup.removedBytes} bytes)`);
4911
5142
  }
4912
5143
  logger.info("Creating MCP server instance...");
4913
- await initRegistry();
5144
+ const explicitProfile = (process.env.MCP_TOOL_PROFILE ?? "").trim().toLowerCase();
5145
+ await initRegistry(explicitProfile === "full" || explicitProfile === "workflow" || explicitProfile === "search" ? explicitProfile : "search");
4914
5146
  const server = new MCPServer(config);
4915
5147
  const stopArtifactRetentionScheduler = startArtifactRetentionScheduler();
4916
5148
  const recoveryWindowMs = Math.max(1e3, RUNTIME_ERROR_WINDOW_MS);