@jshookmcp/jshook 0.2.7 → 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.
- package/README.md +36 -5
- package/README.zh.md +36 -5
- package/dist/{AntiCheatDetector-S8VRj-dD.mjs → AntiCheatDetector-BNk-EoBt.mjs} +3 -3
- package/dist/{CodeInjector-4Z3ngPoX.mjs → CodeInjector-Cq8q01kp.mjs} +5 -5
- package/dist/ConsoleMonitor-CPVQW1Y-.mjs +2201 -0
- package/dist/{DarwinAPI-B8hg_yhz.mjs → DarwinAPI-BNPxu0RH.mjs} +1 -1
- package/dist/DetailedDataManager-BQQcxh64.mjs +217 -0
- package/dist/EventBus-DgPmwpeu.mjs +141 -0
- package/dist/EvidenceGraphBridge-SFesNera.mjs +153 -0
- package/dist/{ExtensionManager-CZ6IveoV.mjs → ExtensionManager-CWYgw0YW.mjs} +13 -6
- package/dist/{FingerprintManager-BVxFJL2-.mjs → FingerprintManager-gzWtkKuf.mjs} +1 -1
- package/dist/{HardwareBreakpoint-DK1yjWkV.mjs → HardwareBreakpoint-B9gZCdFP.mjs} +3 -3
- package/dist/{HeapAnalyzer-CEbo10xU.mjs → HeapAnalyzer-BLDH0dCv.mjs} +4 -4
- package/dist/HookGeneratorBuilders.core.generators.storage-CtcdK78Q.mjs +639 -0
- package/dist/InstrumentationSession-CvPC7Jwy.mjs +244 -0
- package/dist/{MemoryController-DdtnBdD4.mjs → MemoryController-CbVdCIJF.mjs} +3 -3
- package/dist/{MemoryScanSession-RMixN3bX.mjs → MemoryScanSession-BsDZbLYm.mjs} +81 -78
- package/dist/{MemoryScanner-QjK4ld0B.mjs → MemoryScanner-Bcpml6II.mjs} +44 -18
- package/dist/{NativeMemoryManager.impl-CB6gJ0NM.mjs → NativeMemoryManager.impl-dZtA1ZGn.mjs} +14 -53
- package/dist/{NativeMemoryManager.utils-BML4q1ry.mjs → NativeMemoryManager.utils-B-FjA2mJ.mjs} +1 -1
- package/dist/{PEAnalyzer-CK0xe0Fs.mjs → PEAnalyzer-D1lzJ_VG.mjs} +2 -2
- package/dist/PageController-Bqm2kZ_X.mjs +417 -0
- package/dist/{PointerChainEngine-Cd73qu5b.mjs → PointerChainEngine-BOhyVsjx.mjs} +4 -4
- package/dist/PrerequisiteError-Dl33Svkz.mjs +20 -0
- package/dist/ResponseBuilder-D3iFYx2N.mjs +143 -0
- package/dist/ReverseEvidenceGraph-Dlsk94LC.mjs +269 -0
- package/dist/ScriptManager-aHHq0X7U.mjs +3000 -0
- package/dist/{Speedhack-CeF0XmEz.mjs → Speedhack-CqdIFlQl.mjs} +2 -2
- package/dist/{StructureAnalyzer-D4GkMduU.mjs → StructureAnalyzer-DhFaPvRO.mjs} +3 -3
- package/dist/ToolCatalog-C0JGZoOm.mjs +582 -0
- package/dist/ToolError-jh9whhMd.mjs +15 -0
- package/dist/ToolProbe-oC7aPrkv.mjs +45 -0
- package/dist/ToolRegistry-BjaF4oNz.mjs +131 -0
- package/dist/ToolRouter.policy-BWV67ZK-.mjs +304 -0
- package/dist/TraceRecorder-DgxyVbdQ.mjs +519 -0
- package/dist/{Win32API-Bc0QnQsN.mjs → Win32API-CePkipZY.mjs} +1 -1
- package/dist/{Win32Debug-DUHt9XUn.mjs → Win32Debug-BvKs-gxc.mjs} +2 -2
- package/dist/WorkflowEngine-CuvkZtWu.mjs +598 -0
- package/dist/analysis-CL9uACt9.mjs +463 -0
- package/dist/antidebug-CqDTB_uk.mjs +1081 -0
- package/dist/artifactRetention-CFEprwPw.mjs +591 -0
- package/dist/artifacts-Bk2-_uPq.mjs +59 -0
- package/dist/betterSqlite3-0pqusHHH.mjs +74 -0
- package/dist/binary-instrument-CXfpx6fT.mjs +979 -0
- package/dist/bind-helpers-xFfRF-qm.mjs +22 -0
- package/dist/boringssl-inspector-BH2D3VKc.mjs +180 -0
- package/dist/browser-BpOr5PEx.mjs +4082 -0
- package/dist/concurrency-Bt0yv1kJ.mjs +41 -0
- package/dist/{constants-CCvsN80K.mjs → constants-B0OANIBL.mjs} +88 -46
- package/dist/coordination-qUbyF8KU.mjs +259 -0
- package/dist/debugger-gnKxRSN0.mjs +1271 -0
- package/dist/definitions-6M-eejaT.mjs +53 -0
- package/dist/definitions-B18eyf0B.mjs +18 -0
- package/dist/definitions-B3QdlrHv.mjs +34 -0
- package/dist/definitions-B4rAvHNZ.mjs +63 -0
- package/dist/definitions-BB_4jnmy.mjs +37 -0
- package/dist/definitions-BMfYXoNC.mjs +43 -0
- package/dist/definitions-Beid2EB3.mjs +27 -0
- package/dist/definitions-C1UvM5Iy.mjs +126 -0
- package/dist/definitions-CXEI7QC72.mjs +216 -0
- package/dist/definitions-C_4r7Fo-2.mjs +14 -0
- package/dist/definitions-CkFDALoa.mjs +26 -0
- package/dist/definitions-Cke7zEb8.mjs +94 -0
- package/dist/definitions-ClJLzsJQ.mjs +25 -0
- package/dist/definitions-Cq-zroAU.mjs +28 -0
- package/dist/definitions-Cy3Sl6gV.mjs +34 -0
- package/dist/definitions-D3VsGcvz.mjs +47 -0
- package/dist/definitions-DVGfrn7y.mjs +96 -0
- package/dist/definitions-LKpC3-nL.mjs +9 -0
- package/dist/definitions-bAhHQJq9.mjs +359 -0
- package/dist/encoding-Bvz5jLRv.mjs +1065 -0
- package/dist/evidence-graph-bridge-C_fv9PuC.mjs +135 -0
- package/dist/{factory-CibqTNC8.mjs → factory-DxlGh9Xf.mjs} +37 -52
- package/dist/graphql-DYWzJ29s.mjs +1026 -0
- package/dist/handlers-9sAbfIg-.mjs +2552 -0
- package/dist/handlers-Bl8zkwz1.mjs +2716 -0
- package/dist/handlers-C67ktuRN.mjs +710 -0
- package/dist/handlers-C87g8oCe.mjs +276 -0
- package/dist/handlers-CTsDAO6p.mjs +681 -0
- package/dist/handlers-Cgyg6c0U.mjs +645 -0
- package/dist/handlers-D6j6yka7.mjs +2124 -0
- package/dist/handlers-DdFzXLvF.mjs +446 -0
- package/dist/handlers-DeLOCd5m.mjs +799 -0
- package/dist/handlers-DlCJN4Td.mjs +757 -0
- package/dist/handlers-DxGIq15_2.mjs +917 -0
- package/dist/handlers-U6L4xhuF.mjs +585 -0
- package/dist/handlers-tB9Mp9ZK.mjs +84 -0
- package/dist/handlers-tiy7EIBp.mjs +572 -0
- package/dist/handlers.impl-DS0d9fUw.mjs +761 -0
- package/dist/hooks-CzCWByww.mjs +898 -0
- package/dist/index.mjs +384 -155
- package/dist/{logger-BmWzC2lM.mjs → logger-Dh_xb7_2.mjs} +14 -6
- package/dist/maintenance-P7ePRXQC.mjs +830 -0
- package/dist/manifest-2ToTpjv8.mjs +106 -0
- package/dist/manifest-3g71z6Bg.mjs +79 -0
- package/dist/manifest-82baTv4U.mjs +45 -0
- package/dist/manifest-B3QVVeBS.mjs +82 -0
- package/dist/manifest-BB2J8IMJ.mjs +149 -0
- package/dist/manifest-BKbgbSiY.mjs +60 -0
- package/dist/manifest-Bcf-TJzH.mjs +848 -0
- package/dist/manifest-BmtZzQiQ2.mjs +45 -0
- package/dist/manifest-Bnd7kqEY.mjs +55 -0
- package/dist/manifest-BqQX6OQC2.mjs +65 -0
- package/dist/manifest-BqrQ4Tpj.mjs +81 -0
- package/dist/manifest-Br4RPFt5.mjs +370 -0
- package/dist/manifest-C5qDjysN.mjs +107 -0
- package/dist/manifest-C9RT5nk32.mjs +34 -0
- package/dist/manifest-CAhOuvSl.mjs +204 -0
- package/dist/manifest-CBYWCUBJ.mjs +51 -0
- package/dist/manifest-CFADCRa1.mjs +37 -0
- package/dist/manifest-CQVhavRF.mjs +114 -0
- package/dist/manifest-CT7zZBV1.mjs +48 -0
- package/dist/manifest-CV12bcrF.mjs +121 -0
- package/dist/manifest-CXsRWjjI.mjs +224 -0
- package/dist/manifest-CZLUCfG02.mjs +95 -0
- package/dist/manifest-D6phHKFd.mjs +131 -0
- package/dist/manifest-DCyjf4n2.mjs +294 -0
- package/dist/manifest-DHsnKgP6.mjs +60 -0
- package/dist/manifest-Df_dliIe.mjs +55 -0
- package/dist/manifest-Dh8WBmEW.mjs +129 -0
- package/dist/manifest-DhKRAT8_.mjs +92 -0
- package/dist/manifest-DlpTj4ic2.mjs +193 -0
- package/dist/manifest-DrbmZcFl2.mjs +253 -0
- package/dist/manifest-DuwHjUa5.mjs +70 -0
- package/dist/manifest-DzwvxPJX.mjs +38 -0
- package/dist/manifest-NXctwWQq.mjs +68 -0
- package/dist/manifest-Sc_0JQ13.mjs +418 -0
- package/dist/manifest-gZ4s_UtG.mjs +96 -0
- package/dist/manifest-qSleDqdO.mjs +1023 -0
- package/dist/modules-C184v-S9.mjs +11365 -0
- package/dist/mojo-ipc-B_H61Afw.mjs +525 -0
- package/dist/network-671Cw6hV.mjs +3346 -0
- package/dist/{artifacts-BbdOMET5.mjs → outputPaths-B1uGmrWZ.mjs} +219 -212
- package/dist/parse-args-BlRjqlkL.mjs +39 -0
- package/dist/platform-WmNn8Sxb.mjs +2070 -0
- package/dist/process-QcbIy5Zq.mjs +1401 -0
- package/dist/proxy-DqNs0bAd.mjs +170 -0
- package/dist/registry-D-6e18lB.mjs +34 -0
- package/dist/response-BQVP-xUn.mjs +28 -0
- package/dist/server/plugin-api.mjs +2 -2
- package/dist/shared-state-board-DV-dpHFJ.mjs +586 -0
- package/dist/sourcemap-Dq8ez8vS.mjs +650 -0
- package/dist/ssrf-policy-ZaUfvhq7.mjs +166 -0
- package/dist/streaming-BUQ0VJsg.mjs +725 -0
- package/dist/tool-builder-DCbIC5Eo.mjs +186 -0
- package/dist/transform-CiYJfNX0.mjs +1007 -0
- package/dist/types-Bx92KJfT.mjs +4 -0
- package/dist/wasm-DQTnHDs4.mjs +531 -0
- package/dist/workflow-f3xJOcjx.mjs +725 -0
- package/package.json +48 -78
- package/dist/ExtensionManager-DqUSOamB.mjs +0 -2
- package/dist/ToolCatalog-CnwmMIw3.mjs +0 -61483
- package/dist/{CacheAdapters-CzFNpD9a.mjs → CacheAdapters-CDe5WPSV.mjs} +0 -0
- package/dist/{StealthVerifier-BzBCFiwx.mjs → StealthVerifier-Bo4T3bz8.mjs} +0 -0
- package/dist/{VersionDetector-CNXcvD46.mjs → VersionDetector-CwVLVdDM.mjs} +0 -0
- package/dist/{formatAddress-ChCSIRWT.mjs → formatAddress-DVkj9kpI.mjs} +0 -0
- 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-
|
|
3
|
-
import { $t as
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
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();
|
|
@@ -1097,6 +1116,11 @@ async function closeServer(ctx) {
|
|
|
1097
1116
|
} catch (error) {
|
|
1098
1117
|
logger.warn("MCP server close failed:", error);
|
|
1099
1118
|
}
|
|
1119
|
+
try {
|
|
1120
|
+
await ProcessRegistry.terminateAll();
|
|
1121
|
+
} catch (error) {
|
|
1122
|
+
logger.warn("ProcessRegistry cleanup failed:", error);
|
|
1123
|
+
}
|
|
1100
1124
|
logger.success("MCP server closed");
|
|
1101
1125
|
})();
|
|
1102
1126
|
return ctx.shutdownPromise;
|
|
@@ -1757,7 +1781,10 @@ var EmbeddingEngine = class {
|
|
|
1757
1781
|
}
|
|
1758
1782
|
ensureWorker() {
|
|
1759
1783
|
if (this.worker) return;
|
|
1760
|
-
|
|
1784
|
+
const workerPath = new URL("./EmbeddingWorker.js", import.meta.url);
|
|
1785
|
+
this.worker = new Worker(workerPath);
|
|
1786
|
+
if (typeof this.worker.unref === "function") this.worker.unref();
|
|
1787
|
+
ProcessRegistry.register(this.worker);
|
|
1761
1788
|
this.worker.on("message", (msg) => {
|
|
1762
1789
|
const req = this.pending.get(msg.id);
|
|
1763
1790
|
if (!req) return;
|
|
@@ -1865,7 +1892,7 @@ var TrigramIndex = class TrigramIndex {
|
|
|
1865
1892
|
* @param threshold Minimum Jaccard similarity to include in results (default 0.3).
|
|
1866
1893
|
* @returns Map from document index to similarity score (0–1).
|
|
1867
1894
|
*/
|
|
1868
|
-
search(query, threshold =
|
|
1895
|
+
search(query, threshold = SEARCH_TRIGRAM_THRESHOLD) {
|
|
1869
1896
|
const queryTrigrams = TrigramIndex.extractTrigrams(query);
|
|
1870
1897
|
if (queryTrigrams.size === 0) return /* @__PURE__ */ new Map();
|
|
1871
1898
|
const results = /* @__PURE__ */ new Map();
|
|
@@ -2022,6 +2049,13 @@ const PARAM_DESCRIPTION_STOP_WORDS = new Set([
|
|
|
2022
2049
|
* and tool metadata for indexing.
|
|
2023
2050
|
*/
|
|
2024
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
|
+
*/
|
|
2025
2059
|
extractParamTokens(inputSchema) {
|
|
2026
2060
|
const tokens = [];
|
|
2027
2061
|
if (!inputSchema || typeof inputSchema !== "object") return tokens;
|
|
@@ -2043,6 +2077,13 @@ const QueryNormalizer = {
|
|
|
2043
2077
|
}
|
|
2044
2078
|
return tokens;
|
|
2045
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
|
+
*/
|
|
2046
2087
|
extractShortDescription(description) {
|
|
2047
2088
|
if (!description) return "";
|
|
2048
2089
|
const firstSentence = description.match(/^[^.!?\n]+[.!?]?/);
|
|
@@ -2052,9 +2093,21 @@ const QueryNormalizer = {
|
|
|
2052
2093
|
}
|
|
2053
2094
|
return description.length > 120 ? description.slice(0, 117) + "..." : description;
|
|
2054
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
|
+
*/
|
|
2055
2102
|
containsCJK(query) {
|
|
2056
2103
|
return /[\u4e00-\u9fff\u3040-\u309f\u30a0-\u30ff\uac00-\ud7af]/.test(query);
|
|
2057
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
|
+
*/
|
|
2058
2111
|
normalizeToolName(query) {
|
|
2059
2112
|
return query.toLowerCase().replace(/[\s-]+/g, "_");
|
|
2060
2113
|
}
|
|
@@ -2065,10 +2118,10 @@ const QueryNormalizer = {
|
|
|
2065
2118
|
* Hybrid BM25 + RRF multi-signal tool search engine for progressive tool discovery.
|
|
2066
2119
|
*
|
|
2067
2120
|
* Enhancements:
|
|
2068
|
-
* - BM25 keyword scoring with synonym-expanded queries
|
|
2069
|
-
* - TF-IDF cosine similarity as an independent RRF signal
|
|
2121
|
+
* - BM25 keyword scoring with synonym-expanded queries and field weights
|
|
2070
2122
|
* - Trigram fuzzy matching for typo tolerance
|
|
2071
2123
|
* - RRF (Reciprocal Rank Fusion) combining all signals
|
|
2124
|
+
* - Dense vector similarity (384-dim embeddings) as semantic signal
|
|
2072
2125
|
* - Tool affinity graph with prefix-group expansion (§4.1.4 dependency hull)
|
|
2073
2126
|
* - Query category adaptive domain weights (§4.1.3 task-type encoding)
|
|
2074
2127
|
* - Parameter name indexing for schema-aware search
|
|
@@ -2127,8 +2180,6 @@ var ToolSearchEngine = class {
|
|
|
2127
2180
|
domainOverrides;
|
|
2128
2181
|
domainScoreMultipliers;
|
|
2129
2182
|
toolScoreMultipliers;
|
|
2130
|
-
/** IDF values per term, used for TF-IDF cosine computation. */
|
|
2131
|
-
idfMap;
|
|
2132
2183
|
/** Name → doc index for O(1) lookup during affinity expansion. */
|
|
2133
2184
|
docNameIndex = /* @__PURE__ */ new Map();
|
|
2134
2185
|
/** Prefix-group affinity graph: docIndex → neighbor edges. */
|
|
@@ -2157,7 +2208,8 @@ var ToolSearchEngine = class {
|
|
|
2157
2208
|
this.toolScoreMultipliers = toolScoreMultipliers;
|
|
2158
2209
|
this.docCount = source.length;
|
|
2159
2210
|
this.bm25Scorer = new BM25ScorerImpl(searchConfig);
|
|
2160
|
-
|
|
2211
|
+
const vectorEnabled = searchConfig?.vectorEnabled ?? SEARCH_VECTOR_ENABLED;
|
|
2212
|
+
this.embeddingEngine = vectorEnabled ? new EmbeddingEngine() : null;
|
|
2161
2213
|
this.feedbackTracker = new FeedbackTracker(searchConfig);
|
|
2162
2214
|
this.intentBoost = new IntentBoostImpl(searchConfig?.intentToolBoostRules);
|
|
2163
2215
|
let totalLength = 0;
|
|
@@ -2186,9 +2238,7 @@ var ToolSearchEngine = class {
|
|
|
2186
2238
|
length: allTokens.length,
|
|
2187
2239
|
nameTokens,
|
|
2188
2240
|
nameTokenSet,
|
|
2189
|
-
nameTokenCount: nameTokenSet.size
|
|
2190
|
-
tfidfWeights: /* @__PURE__ */ new Map(),
|
|
2191
|
-
tfidfMagnitude: 0
|
|
2241
|
+
nameTokenCount: nameTokenSet.size
|
|
2192
2242
|
};
|
|
2193
2243
|
this.docs.push(doc);
|
|
2194
2244
|
this.docNameIndex.set(tool.name, i);
|
|
@@ -2245,31 +2295,30 @@ var ToolSearchEngine = class {
|
|
|
2245
2295
|
}
|
|
2246
2296
|
this.avgDocLength = this.docCount > 0 ? totalLength / this.docCount : 1;
|
|
2247
2297
|
this.sortedKeys = [...this.invertedIndex.keys()].toSorted();
|
|
2248
|
-
const idfMap = /* @__PURE__ */ new Map();
|
|
2249
|
-
for (const [term, postings] of this.invertedIndex) idfMap.set(term, Math.log(1 + this.docCount / postings.length));
|
|
2250
|
-
this.idfMap = idfMap;
|
|
2251
|
-
for (let i = 0; i < this.docCount; i++) {
|
|
2252
|
-
const doc = this.docs[i];
|
|
2253
|
-
const rawTf = /* @__PURE__ */ new Map();
|
|
2254
|
-
for (const token of doc.tokens) rawTf.set(token, (rawTf.get(token) ?? 0) + 1);
|
|
2255
|
-
const tfidfWeights = /* @__PURE__ */ new Map();
|
|
2256
|
-
let magnitudeSq = 0;
|
|
2257
|
-
for (const [term, tf] of rawTf) {
|
|
2258
|
-
const idf = idfMap.get(term) ?? 0;
|
|
2259
|
-
const w = (1 + Math.log(tf)) * idf;
|
|
2260
|
-
tfidfWeights.set(term, w);
|
|
2261
|
-
magnitudeSq += w * w;
|
|
2262
|
-
}
|
|
2263
|
-
doc.tfidfWeights = tfidfWeights;
|
|
2264
|
-
doc.tfidfMagnitude = Math.sqrt(magnitudeSq);
|
|
2265
|
-
}
|
|
2266
2298
|
this.affinityGraph = this.buildAffinityGraph();
|
|
2267
2299
|
this.trigramIndex = new TrigramIndex(this.docs.map((d) => d.name));
|
|
2268
2300
|
this.queryCache = new LRUCache(SEARCH_QUERY_CACHE_CAPACITY);
|
|
2269
2301
|
}
|
|
2270
|
-
async search(query, topK = 10, activeToolNames, visibleDomains) {
|
|
2271
|
-
|
|
2302
|
+
async search(query, topK = 10, activeToolNames, visibleDomains, profile) {
|
|
2303
|
+
let queryTokens = this.bm25Scorer.tokenise(query);
|
|
2272
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);
|
|
2273
2322
|
const explicitToolMention = (() => {
|
|
2274
2323
|
const lower = query.toLowerCase();
|
|
2275
2324
|
if (!/(?:\b(?:call|use|run|invoke|execute)\b|调用|执行|使用|运行)/i.test(lower)) return null;
|
|
@@ -2340,11 +2389,10 @@ var ToolSearchEngine = class {
|
|
|
2340
2389
|
const toolMultiplier = this.toolScoreMultipliers?.get(doc.name) ?? 1;
|
|
2341
2390
|
if (toolMultiplier !== 1) scores[i] *= toolMultiplier;
|
|
2342
2391
|
}
|
|
2343
|
-
this.
|
|
2344
|
-
this.applyDomainHubExpansion(scores);
|
|
2392
|
+
this.applyGraphExpansion(scores);
|
|
2345
2393
|
this.applyIntentBonusBand(scores, intentToolBonuses);
|
|
2346
2394
|
this.applyRecencyBoost(scores);
|
|
2347
|
-
this.applyTierPenalty(scores, visibleDomains);
|
|
2395
|
+
this.applyTierPenalty(scores, visibleDomains, profile);
|
|
2348
2396
|
if (explicitToolMention) {
|
|
2349
2397
|
const explicitIdx = this.docNameIndex.get(explicitToolMention);
|
|
2350
2398
|
if (explicitIdx !== void 0) {
|
|
@@ -2414,9 +2462,9 @@ var ToolSearchEngine = class {
|
|
|
2414
2462
|
* tier. The penalty is a soft multiplier in [0, 1]; 1 disables the feature.
|
|
2415
2463
|
* Tools without a resolved domain are left untouched.
|
|
2416
2464
|
*/
|
|
2417
|
-
applyTierPenalty(scores, visibleDomains) {
|
|
2465
|
+
applyTierPenalty(scores, visibleDomains, profile) {
|
|
2418
2466
|
if (!visibleDomains || visibleDomains.size === 0) return;
|
|
2419
|
-
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;
|
|
2420
2468
|
if (penalty >= 1 || penalty <= 0) return;
|
|
2421
2469
|
for (let i = 0; i < this.docCount; i++) {
|
|
2422
2470
|
if (scores[i] <= 0) continue;
|
|
@@ -2489,28 +2537,34 @@ var ToolSearchEngine = class {
|
|
|
2489
2537
|
* independently contribute — a document with BM25=0 but high trigram
|
|
2490
2538
|
* similarity can still surface.
|
|
2491
2539
|
*/
|
|
2492
|
-
async applyRRFFusion(
|
|
2540
|
+
async applyRRFFusion(_queryTokens, query, scores) {
|
|
2493
2541
|
const k = SEARCH_RRF_K;
|
|
2494
2542
|
const trigramWeight = SEARCH_TRIGRAM_WEIGHT;
|
|
2495
|
-
const tfidfWeight = SEARCH_TFIDF_COSINE_WEIGHT;
|
|
2496
2543
|
const bm25Ranked = this.rankByScores(scores);
|
|
2497
|
-
const cosineScores = this.computeTfidfCosineScores(queryTokens);
|
|
2498
|
-
const cosineRanked = this.rankByMap(cosineScores);
|
|
2499
2544
|
const trigramScores = this.trigramIndex.search(query, SEARCH_TRIGRAM_THRESHOLD);
|
|
2500
2545
|
const trigramRanked = this.rankByMap(trigramScores);
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
if (
|
|
2504
|
-
const
|
|
2505
|
-
|
|
2506
|
-
|
|
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);
|
|
2507
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);
|
|
2508
2564
|
for (let i = 0; i < this.docCount; i++) {
|
|
2509
2565
|
let rrfScore = 0;
|
|
2510
2566
|
const bm25Rank = bm25Ranked.get(i);
|
|
2511
2567
|
if (bm25Rank !== void 0) rrfScore += 1 / (k + bm25Rank);
|
|
2512
|
-
const cosineRank = cosineRanked.get(i);
|
|
2513
|
-
if (cosineRank !== void 0 && tfidfWeight > 0) rrfScore += tfidfWeight * (1 / (k + cosineRank));
|
|
2514
2568
|
const trigramRank = trigramRanked.get(i);
|
|
2515
2569
|
if (trigramRank !== void 0 && trigramWeight > 0) rrfScore += trigramWeight * (1 / (k + trigramRank));
|
|
2516
2570
|
const vectorRank = vectorRanked.get(i);
|
|
@@ -2524,38 +2578,6 @@ var ToolSearchEngine = class {
|
|
|
2524
2578
|
}
|
|
2525
2579
|
}
|
|
2526
2580
|
/**
|
|
2527
|
-
* Compute raw TF-IDF cosine similarity scores for each document.
|
|
2528
|
-
* Returns Map<docIndex, cosineScore>.
|
|
2529
|
-
*/
|
|
2530
|
-
computeTfidfCosineScores(queryTokens) {
|
|
2531
|
-
const queryTf = /* @__PURE__ */ new Map();
|
|
2532
|
-
for (const token of queryTokens) queryTf.set(token, (queryTf.get(token) ?? 0) + 1);
|
|
2533
|
-
const queryWeights = /* @__PURE__ */ new Map();
|
|
2534
|
-
let queryMagSq = 0;
|
|
2535
|
-
for (const [term, tf] of queryTf) {
|
|
2536
|
-
const idf = this.idfMap.get(term) ?? 0;
|
|
2537
|
-
if (idf === 0) continue;
|
|
2538
|
-
const w = (1 + Math.log(tf)) * idf;
|
|
2539
|
-
queryWeights.set(term, w);
|
|
2540
|
-
queryMagSq += w * w;
|
|
2541
|
-
}
|
|
2542
|
-
if (queryMagSq === 0) return /* @__PURE__ */ new Map();
|
|
2543
|
-
const queryMagnitude = Math.sqrt(queryMagSq);
|
|
2544
|
-
const results = /* @__PURE__ */ new Map();
|
|
2545
|
-
for (let i = 0; i < this.docCount; i++) {
|
|
2546
|
-
const doc = this.docs[i];
|
|
2547
|
-
if (doc.tfidfMagnitude === 0) continue;
|
|
2548
|
-
let dot = 0;
|
|
2549
|
-
for (const [term, qw] of queryWeights) {
|
|
2550
|
-
const dw = doc.tfidfWeights.get(term);
|
|
2551
|
-
if (dw !== void 0) dot += qw * dw;
|
|
2552
|
-
}
|
|
2553
|
-
if (dot <= 0) continue;
|
|
2554
|
-
results.set(i, dot / (queryMagnitude * doc.tfidfMagnitude));
|
|
2555
|
-
}
|
|
2556
|
-
return results;
|
|
2557
|
-
}
|
|
2558
|
-
/**
|
|
2559
2581
|
* Rank documents by Float64Array scores.
|
|
2560
2582
|
* Returns Map<docIndex, rank> (0-based, lower = better).
|
|
2561
2583
|
*/
|
|
@@ -2697,51 +2719,41 @@ var ToolSearchEngine = class {
|
|
|
2697
2719
|
return graph;
|
|
2698
2720
|
}
|
|
2699
2721
|
/**
|
|
2700
|
-
*
|
|
2701
|
-
*
|
|
2702
|
-
*
|
|
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.
|
|
2703
2725
|
*/
|
|
2704
|
-
|
|
2705
|
-
if (this.affinityGraph.size === 0) return;
|
|
2706
|
-
const topN = SEARCH_AFFINITY_TOP_N;
|
|
2726
|
+
applyGraphExpansion(scores) {
|
|
2707
2727
|
const scored = [];
|
|
2708
2728
|
for (let i = 0; i < this.docCount; i++) if (scores[i] > 0) scored.push({
|
|
2709
2729
|
idx: i,
|
|
2710
2730
|
score: scores[i]
|
|
2711
2731
|
});
|
|
2732
|
+
if (scored.length === 0) return;
|
|
2712
2733
|
scored.sort((a, b) => b.score - a.score);
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
const
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
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
|
+
}
|
|
2721
2745
|
}
|
|
2722
|
-
}
|
|
2723
|
-
/**
|
|
2724
|
-
* Domain hub expansion (§4.1.4): when a domain is heavily represented
|
|
2725
|
-
* in top results, slightly boost remaining tools from that domain.
|
|
2726
|
-
*/
|
|
2727
|
-
applyDomainHubExpansion(scores) {
|
|
2728
2746
|
const threshold = SEARCH_DOMAIN_HUB_THRESHOLD;
|
|
2729
|
-
if (threshold
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
idx
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
for (const { idx } of top10) {
|
|
2740
|
-
const domain = this.docs[idx].domain;
|
|
2741
|
-
if (domain) domainCounts.set(domain, (domainCounts.get(domain) ?? 0) + 1);
|
|
2742
|
-
}
|
|
2743
|
-
for (const [domain, count] of domainCounts) if (count >= threshold) {
|
|
2744
|
-
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
|
+
}
|
|
2745
2757
|
}
|
|
2746
2758
|
}
|
|
2747
2759
|
};
|
|
@@ -2781,18 +2793,22 @@ function getVisibleDomainsForTier(ctx) {
|
|
|
2781
2793
|
}
|
|
2782
2794
|
return visible;
|
|
2783
2795
|
}
|
|
2796
|
+
function getBaseTier(ctx) {
|
|
2797
|
+
return ctx.baseTier;
|
|
2798
|
+
}
|
|
2784
2799
|
function getExtensionDomainMap(ctx) {
|
|
2785
2800
|
const map = /* @__PURE__ */ new Map();
|
|
2786
2801
|
for (const record of ctx.extensionToolsByName.values()) map.set(record.name, record.domain);
|
|
2787
2802
|
return map;
|
|
2788
2803
|
}
|
|
2789
|
-
function getCombinedTools(ctx) {
|
|
2804
|
+
async function getCombinedTools(ctx) {
|
|
2805
|
+
await ensureAllDomainsLoaded();
|
|
2790
2806
|
const tools = new Map(allTools.map((tool) => [tool.name, tool]));
|
|
2791
2807
|
for (const record of ctx.extensionToolsByName.values()) tools.set(record.name, record.tool);
|
|
2792
2808
|
return [...tools.values()];
|
|
2793
2809
|
}
|
|
2794
|
-
function getToolByName(ctx) {
|
|
2795
|
-
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]));
|
|
2796
2812
|
}
|
|
2797
2813
|
const searchEngineCache = /* @__PURE__ */ new WeakMap();
|
|
2798
2814
|
/**
|
|
@@ -2805,11 +2821,12 @@ function buildSearchSignature(ctx) {
|
|
|
2805
2821
|
extParts.sort();
|
|
2806
2822
|
return [ctx.extensionWorkflowRuntimeById.size, extParts.join("|")].join("::");
|
|
2807
2823
|
}
|
|
2808
|
-
function getSearchEngine(ctx) {
|
|
2824
|
+
async function getSearchEngine(ctx) {
|
|
2825
|
+
await ensureAllDomainsLoaded();
|
|
2809
2826
|
const signature = buildSearchSignature(ctx);
|
|
2810
2827
|
const cached = searchEngineCache.get(ctx);
|
|
2811
2828
|
if (cached?.signature === signature) return cached.engine;
|
|
2812
|
-
const tools = getCombinedTools(ctx);
|
|
2829
|
+
const tools = await getCombinedTools(ctx);
|
|
2813
2830
|
const extensionDomains = getExtensionDomainMap(ctx);
|
|
2814
2831
|
const domainScoreMultipliers = /* @__PURE__ */ new Map();
|
|
2815
2832
|
const toolScoreMultipliers = /* @__PURE__ */ new Map();
|
|
@@ -2826,14 +2843,14 @@ function getSearchEngine(ctx) {
|
|
|
2826
2843
|
});
|
|
2827
2844
|
return engine;
|
|
2828
2845
|
}
|
|
2829
|
-
/** Generate domain summary description
|
|
2846
|
+
/** Generate domain summary description. Uses metadata when not all domains are loaded. */
|
|
2830
2847
|
function buildDomainDescription(ctx) {
|
|
2831
2848
|
const groups = {};
|
|
2832
2849
|
for (const r of getAllRegistrations()) groups[r.domain] = (groups[r.domain] ?? 0) + 1;
|
|
2833
2850
|
for (const record of ctx.extensionToolsByName.values()) groups[record.domain] = (groups[record.domain] ?? 0) + 1;
|
|
2834
|
-
const
|
|
2835
|
-
const
|
|
2836
|
-
return `Search ${
|
|
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.`;
|
|
2837
2854
|
}
|
|
2838
2855
|
//#endregion
|
|
2839
2856
|
//#region src/server/MCPServer.search.handlers.domain.ts
|
|
@@ -2846,12 +2863,13 @@ async function handleActivateDomain(ctx, args) {
|
|
|
2846
2863
|
success: false,
|
|
2847
2864
|
error: "domain must be a non-empty string"
|
|
2848
2865
|
}));
|
|
2849
|
-
const validDomains = new Set(
|
|
2866
|
+
const validDomains = new Set(getAllKnownDomains());
|
|
2850
2867
|
for (const record of ctx.extensionToolsByName.values()) validDomains.add(record.domain);
|
|
2851
2868
|
if (!validDomains.has(domain)) return asTextResponse(JSON.stringify({
|
|
2852
2869
|
success: false,
|
|
2853
2870
|
error: `Unknown domain "${domain}". Valid: ${[...validDomains].join(", ")}`
|
|
2854
2871
|
}));
|
|
2872
|
+
await ensureDomainLoaded(domain);
|
|
2855
2873
|
const ttlMinutes = typeof args.ttlMinutes === "number" ? args.ttlMinutes : ACTIVATION_TTL_MINUTES;
|
|
2856
2874
|
const domainTools = [...getToolsByDomains([domain]), ...[...ctx.extensionToolsByName.values()].filter((record) => record.domain === domain).map((record) => record.tool)];
|
|
2857
2875
|
const activeNames = getActiveToolNames(ctx);
|
|
@@ -3409,7 +3427,8 @@ var ActivationController = class {
|
|
|
3409
3427
|
this.boostRules = [...DEFAULT_BOOST_RULES, ...customRules].toSorted((a, b) => b.priority - a.priority);
|
|
3410
3428
|
this.compoundEngine = new CompoundConditionEngine();
|
|
3411
3429
|
this.predictiveBooster = new PredictiveBooster();
|
|
3412
|
-
|
|
3430
|
+
const baseDomains = new Set(getProfileDomains(ctx.baseTier));
|
|
3431
|
+
this.autoPruner = new AutoPruner(eventBus, baseDomains, (domain) => {
|
|
3413
3432
|
logger.info(`[ActivationController] Auto-pruning domain "${domain}"`);
|
|
3414
3433
|
});
|
|
3415
3434
|
this.subscribe();
|
|
@@ -3641,10 +3660,27 @@ function handleToolError(toolName, error) {
|
|
|
3641
3660
|
logger.error(`Tool execution failed: ${toolName}`, error);
|
|
3642
3661
|
throw new McpError(ErrorCode.InternalError, `Execution Failed in ${toolName}: ${error instanceof Error ? error.message : String(error)}`);
|
|
3643
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
|
+
}
|
|
3644
3680
|
function registerSingleTool(ctx, toolDef) {
|
|
3645
3681
|
const builtTool = toolDef;
|
|
3646
3682
|
if (builtTool.__autocomplete) ctx.toolAutocompleteHandlers.set(toolDef.name, builtTool.__autocomplete);
|
|
3647
|
-
const rawSchema = toolDef.inputSchema;
|
|
3683
|
+
const rawSchema = MCP_COMPACT_SCHEMA && toolDef.inputSchema ? stripParamDescriptions(toolDef.inputSchema) : toolDef.inputSchema;
|
|
3648
3684
|
const shape = rawSchema && typeof rawSchema === "object" ? buildZodShape(rawSchema) : {};
|
|
3649
3685
|
const description = toolDef.description ?? toolDef.name;
|
|
3650
3686
|
if (Object.keys(shape).length > 0) {
|
|
@@ -3730,7 +3766,7 @@ async function routeToolRequest(request, ctx, searchEngine) {
|
|
|
3730
3766
|
const availableToolNames = getAvailableToolNames(ctx);
|
|
3731
3767
|
const routeMatch = matchWorkflowRoute(task, ctx);
|
|
3732
3768
|
let presetPlannedToolNames = null;
|
|
3733
|
-
const searchResults = await searchEngine.search(task, maxRecommendations * 2, activeNames, visibleDomains);
|
|
3769
|
+
const searchResults = await searchEngine.search(task, maxRecommendations * 2, activeNames, visibleDomains, getBaseTier(ctx));
|
|
3734
3770
|
let finalResults = [];
|
|
3735
3771
|
if (routeMatch?.workflow.route.kind === "preset") {
|
|
3736
3772
|
const presetTools = buildPresetRecommendations(routeMatch, routingState, ctx, availableToolNames);
|
|
@@ -3897,10 +3933,10 @@ async function routeToolRequest(request, ctx, searchEngine) {
|
|
|
3897
3933
|
async function handleSearchTools(ctx, args) {
|
|
3898
3934
|
const query = args.query;
|
|
3899
3935
|
const topK = args.top_k ?? 10;
|
|
3900
|
-
const engine = getSearchEngine(ctx);
|
|
3936
|
+
const engine = await getSearchEngine(ctx);
|
|
3901
3937
|
const activeNames = getActiveToolNames(ctx);
|
|
3902
3938
|
const visibleDomains = getVisibleDomainsForTier(ctx);
|
|
3903
|
-
const results = await engine.search(query, topK, activeNames, visibleDomains);
|
|
3939
|
+
const results = await engine.search(query, topK, activeNames, visibleDomains, getBaseTier(ctx));
|
|
3904
3940
|
const topResult = results[0];
|
|
3905
3941
|
const topTool = topResult ? describeTool(topResult.name, ctx) : null;
|
|
3906
3942
|
const topExampleArgs = topTool ? generateExampleArgs(topTool.inputSchema) : void 0;
|
|
@@ -3927,12 +3963,14 @@ async function handleSearchTools(ctx, args) {
|
|
|
3927
3963
|
exampleArgs: topExampleArgs,
|
|
3928
3964
|
description: `Call ${topResult.name} directly. Use describe_tool("${topResult.name}") only if you need the full schema.`
|
|
3929
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\")." : "";
|
|
3930
3968
|
const response = {
|
|
3931
3969
|
query,
|
|
3932
3970
|
resultCount: results.length,
|
|
3933
3971
|
results,
|
|
3934
3972
|
nextActions: searchNextActions,
|
|
3935
|
-
hint:
|
|
3973
|
+
hint: baseHint + refinementHint
|
|
3936
3974
|
};
|
|
3937
3975
|
return asTextResponse(JSON.stringify(response, null, 2));
|
|
3938
3976
|
}
|
|
@@ -3950,6 +3988,7 @@ async function notifyToolListChanged(ctx, changed) {
|
|
|
3950
3988
|
}
|
|
3951
3989
|
}
|
|
3952
3990
|
async function activateToolNames(ctx, names) {
|
|
3991
|
+
await ensureAllDomainsLoaded();
|
|
3953
3992
|
const activeNames = getActiveToolNames(ctx);
|
|
3954
3993
|
const activated = [];
|
|
3955
3994
|
const alreadyActive = [];
|
|
@@ -3960,7 +3999,7 @@ async function activateToolNames(ctx, names) {
|
|
|
3960
3999
|
alreadyActive.push(name);
|
|
3961
4000
|
continue;
|
|
3962
4001
|
}
|
|
3963
|
-
const toolDef = getToolByName(ctx).get(name);
|
|
4002
|
+
const toolDef = (await getToolByName(ctx)).get(name);
|
|
3964
4003
|
if (!toolDef) {
|
|
3965
4004
|
notFound.push(name);
|
|
3966
4005
|
continue;
|
|
@@ -4060,7 +4099,7 @@ async function handleRouteTool(ctx, args) {
|
|
|
4060
4099
|
success: false,
|
|
4061
4100
|
error: "task must be a non-empty string"
|
|
4062
4101
|
}));
|
|
4063
|
-
const engine = getSearchEngine(ctx);
|
|
4102
|
+
const engine = await getSearchEngine(ctx);
|
|
4064
4103
|
const autoActivate = context?.autoActivate === true;
|
|
4065
4104
|
let response = populateCallCommands(await routeToolRequest({
|
|
4066
4105
|
task,
|
|
@@ -4174,7 +4213,7 @@ async function handleCallTool(ctx, args) {
|
|
|
4174
4213
|
try {
|
|
4175
4214
|
const response = await ctx.executeToolWithTracking(name, toolArgs);
|
|
4176
4215
|
try {
|
|
4177
|
-
getSearchEngine(ctx).recordToolCallFeedback(name, "");
|
|
4216
|
+
(await getSearchEngine(ctx)).recordToolCallFeedback(name, "");
|
|
4178
4217
|
} catch {}
|
|
4179
4218
|
return attachCallToolMetadata(response, callMetadata);
|
|
4180
4219
|
} catch (error) {
|
|
@@ -4199,7 +4238,7 @@ function buildMetaToolDefinitions(ctx) {
|
|
|
4199
4238
|
properties: {
|
|
4200
4239
|
query: {
|
|
4201
4240
|
type: "string",
|
|
4202
|
-
description: "
|
|
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."
|
|
4203
4242
|
},
|
|
4204
4243
|
top_k: {
|
|
4205
4244
|
type: "number",
|
|
@@ -4475,7 +4514,164 @@ Generally, you have three options to deploy hooks:
|
|
|
4475
4514
|
}] }));
|
|
4476
4515
|
}
|
|
4477
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
|
|
4478
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
|
+
}
|
|
4479
4675
|
var MCPServer = class {
|
|
4480
4676
|
config;
|
|
4481
4677
|
server;
|
|
@@ -4531,12 +4727,32 @@ var MCPServer = class {
|
|
|
4531
4727
|
this.enabledDomains = this.resolveEnabledDomains(this.selectedTools);
|
|
4532
4728
|
const depsEntries = [];
|
|
4533
4729
|
const manifests = getAllManifests();
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
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
|
+
}
|
|
4540
4756
|
}
|
|
4541
4757
|
this.handlerDeps = Object.fromEntries(depsEntries);
|
|
4542
4758
|
const selectedToolNames = new Set(this.selectedTools.map((t) => t.name));
|
|
@@ -4573,6 +4789,11 @@ var MCPServer = class {
|
|
|
4573
4789
|
this.samplingBridge = new LLMSamplingBridge(this.server);
|
|
4574
4790
|
this.elicitationBridge = new ElicitationBridge(this.server);
|
|
4575
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));
|
|
4576
4797
|
this.eventBus.on("tool:progress", async (payload) => {
|
|
4577
4798
|
try {
|
|
4578
4799
|
await this.server.server.notification({
|
|
@@ -4651,7 +4872,7 @@ var MCPServer = class {
|
|
|
4651
4872
|
}
|
|
4652
4873
|
this.cacheRegistrationPromise = (async () => {
|
|
4653
4874
|
try {
|
|
4654
|
-
const { createCacheAdapters } = await import("./CacheAdapters-
|
|
4875
|
+
const { createCacheAdapters } = await import("./CacheAdapters-CDe5WPSV.mjs");
|
|
4655
4876
|
const codeCache = this.collector.getCache();
|
|
4656
4877
|
const codeCompressor = this.collector.getCompressor();
|
|
4657
4878
|
const adapters = createCacheAdapters(this.detailedData, codeCache, codeCompressor);
|
|
@@ -4672,6 +4893,12 @@ var MCPServer = class {
|
|
|
4672
4893
|
}
|
|
4673
4894
|
async executeToolWithTracking(name, args) {
|
|
4674
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;
|
|
4675
4902
|
try {
|
|
4676
4903
|
timeoutTimer = setTimeout(() => {
|
|
4677
4904
|
try {
|
|
@@ -4680,7 +4907,7 @@ var MCPServer = class {
|
|
|
4680
4907
|
} catch {
|
|
4681
4908
|
logger.warn(`Telemetry Alert [ERR-03]: Tool execution hung (>30s) for '${name}'.`);
|
|
4682
4909
|
}
|
|
4683
|
-
},
|
|
4910
|
+
}, timeoutMs);
|
|
4684
4911
|
timeoutTimer.unref();
|
|
4685
4912
|
let response;
|
|
4686
4913
|
try {
|
|
@@ -4689,7 +4916,8 @@ var MCPServer = class {
|
|
|
4689
4916
|
if (timeoutTimer) clearTimeout(timeoutTimer);
|
|
4690
4917
|
}
|
|
4691
4918
|
this.contextGuard.recordCall(name);
|
|
4692
|
-
|
|
4919
|
+
let enriched = this.contextGuard.enrichResponse(name, response);
|
|
4920
|
+
if (collectExecutionMetrics && executionStartedAt && executionCpuStart && executionMemoryBefore) enriched = appendExecutionMetrics(enriched, buildExecutionMetrics(executionStartedAt, executionStartTime, timeoutMs, executionCpuStart, executionMemoryBefore));
|
|
4693
4921
|
try {
|
|
4694
4922
|
this.tokenBudget.recordToolCall(name, args, enriched);
|
|
4695
4923
|
} catch (trackingError) {
|
|
@@ -4903,7 +5131,8 @@ async function main() {
|
|
|
4903
5131
|
if (cleanup.removedFiles > 0) logger.info(`[artifacts] Startup cleanup removed ${cleanup.removedFiles} files (${cleanup.removedBytes} bytes)`);
|
|
4904
5132
|
}
|
|
4905
5133
|
logger.info("Creating MCP server instance...");
|
|
4906
|
-
|
|
5134
|
+
const explicitProfile = (process.env.MCP_TOOL_PROFILE ?? "").trim().toLowerCase();
|
|
5135
|
+
await initRegistry(explicitProfile === "full" || explicitProfile === "workflow" || explicitProfile === "search" ? explicitProfile : "search");
|
|
4907
5136
|
const server = new MCPServer(config);
|
|
4908
5137
|
const stopArtifactRetentionScheduler = startArtifactRetentionScheduler();
|
|
4909
5138
|
const recoveryWindowMs = Math.max(1e3, RUNTIME_ERROR_WINDOW_MS);
|