@jshookmcp/jshook 0.2.8 → 0.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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-D5-bO9D8.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 +377 -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 +16 -16
- package/dist/ExtensionManager-CPTJhHFg.mjs +0 -2
- package/dist/ToolCatalog-Bq4V2sbJ.mjs +0 -67201
- 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();
|
|
@@ -1762,7 +1781,8 @@ var EmbeddingEngine = class {
|
|
|
1762
1781
|
}
|
|
1763
1782
|
ensureWorker() {
|
|
1764
1783
|
if (this.worker) return;
|
|
1765
|
-
|
|
1784
|
+
const workerPath = new URL("./EmbeddingWorker.js", import.meta.url);
|
|
1785
|
+
this.worker = new Worker(workerPath);
|
|
1766
1786
|
if (typeof this.worker.unref === "function") this.worker.unref();
|
|
1767
1787
|
ProcessRegistry.register(this.worker);
|
|
1768
1788
|
this.worker.on("message", (msg) => {
|
|
@@ -1872,7 +1892,7 @@ var TrigramIndex = class TrigramIndex {
|
|
|
1872
1892
|
* @param threshold Minimum Jaccard similarity to include in results (default 0.3).
|
|
1873
1893
|
* @returns Map from document index to similarity score (0–1).
|
|
1874
1894
|
*/
|
|
1875
|
-
search(query, threshold =
|
|
1895
|
+
search(query, threshold = SEARCH_TRIGRAM_THRESHOLD) {
|
|
1876
1896
|
const queryTrigrams = TrigramIndex.extractTrigrams(query);
|
|
1877
1897
|
if (queryTrigrams.size === 0) return /* @__PURE__ */ new Map();
|
|
1878
1898
|
const results = /* @__PURE__ */ new Map();
|
|
@@ -2029,6 +2049,13 @@ const PARAM_DESCRIPTION_STOP_WORDS = new Set([
|
|
|
2029
2049
|
* and tool metadata for indexing.
|
|
2030
2050
|
*/
|
|
2031
2051
|
const QueryNormalizer = {
|
|
2052
|
+
/**
|
|
2053
|
+
* Extract parameter names and description tokens from a tool's inputSchema.
|
|
2054
|
+
* Handles both simple flat properties and nested object properties.
|
|
2055
|
+
*
|
|
2056
|
+
* @param inputSchema The tool's inputSchema object
|
|
2057
|
+
* @returns Array of normalized tokens from parameter names and descriptions
|
|
2058
|
+
*/
|
|
2032
2059
|
extractParamTokens(inputSchema) {
|
|
2033
2060
|
const tokens = [];
|
|
2034
2061
|
if (!inputSchema || typeof inputSchema !== "object") return tokens;
|
|
@@ -2050,6 +2077,13 @@ const QueryNormalizer = {
|
|
|
2050
2077
|
}
|
|
2051
2078
|
return tokens;
|
|
2052
2079
|
},
|
|
2080
|
+
/**
|
|
2081
|
+
* Extract a short description from a full tool description.
|
|
2082
|
+
* Takes the first sentence and truncates to 120 characters if needed.
|
|
2083
|
+
*
|
|
2084
|
+
* @param description The full tool description
|
|
2085
|
+
* @returns A shortened description suitable for display
|
|
2086
|
+
*/
|
|
2053
2087
|
extractShortDescription(description) {
|
|
2054
2088
|
if (!description) return "";
|
|
2055
2089
|
const firstSentence = description.match(/^[^.!?\n]+[.!?]?/);
|
|
@@ -2059,9 +2093,21 @@ const QueryNormalizer = {
|
|
|
2059
2093
|
}
|
|
2060
2094
|
return description.length > 120 ? description.slice(0, 117) + "..." : description;
|
|
2061
2095
|
},
|
|
2096
|
+
/**
|
|
2097
|
+
* Check if a query contains CJK (Chinese, Japanese, Korean) characters.
|
|
2098
|
+
*
|
|
2099
|
+
* @param query The search query
|
|
2100
|
+
* @returns true if the query contains CJK characters
|
|
2101
|
+
*/
|
|
2062
2102
|
containsCJK(query) {
|
|
2063
2103
|
return /[\u4e00-\u9fff\u3040-\u309f\u30a0-\u30ff\uac00-\ud7af]/.test(query);
|
|
2064
2104
|
},
|
|
2105
|
+
/**
|
|
2106
|
+
* Normalize a tool name for comparison (lowercase, underscores to hyphens/spaces).
|
|
2107
|
+
*
|
|
2108
|
+
* @param query The search query
|
|
2109
|
+
* @returns Normalized query string
|
|
2110
|
+
*/
|
|
2065
2111
|
normalizeToolName(query) {
|
|
2066
2112
|
return query.toLowerCase().replace(/[\s-]+/g, "_");
|
|
2067
2113
|
}
|
|
@@ -2072,10 +2118,10 @@ const QueryNormalizer = {
|
|
|
2072
2118
|
* Hybrid BM25 + RRF multi-signal tool search engine for progressive tool discovery.
|
|
2073
2119
|
*
|
|
2074
2120
|
* Enhancements:
|
|
2075
|
-
* - BM25 keyword scoring with synonym-expanded queries
|
|
2076
|
-
* - TF-IDF cosine similarity as an independent RRF signal
|
|
2121
|
+
* - BM25 keyword scoring with synonym-expanded queries and field weights
|
|
2077
2122
|
* - Trigram fuzzy matching for typo tolerance
|
|
2078
2123
|
* - RRF (Reciprocal Rank Fusion) combining all signals
|
|
2124
|
+
* - Dense vector similarity (384-dim embeddings) as semantic signal
|
|
2079
2125
|
* - Tool affinity graph with prefix-group expansion (§4.1.4 dependency hull)
|
|
2080
2126
|
* - Query category adaptive domain weights (§4.1.3 task-type encoding)
|
|
2081
2127
|
* - Parameter name indexing for schema-aware search
|
|
@@ -2134,8 +2180,6 @@ var ToolSearchEngine = class {
|
|
|
2134
2180
|
domainOverrides;
|
|
2135
2181
|
domainScoreMultipliers;
|
|
2136
2182
|
toolScoreMultipliers;
|
|
2137
|
-
/** IDF values per term, used for TF-IDF cosine computation. */
|
|
2138
|
-
idfMap;
|
|
2139
2183
|
/** Name → doc index for O(1) lookup during affinity expansion. */
|
|
2140
2184
|
docNameIndex = /* @__PURE__ */ new Map();
|
|
2141
2185
|
/** Prefix-group affinity graph: docIndex → neighbor edges. */
|
|
@@ -2164,7 +2208,8 @@ var ToolSearchEngine = class {
|
|
|
2164
2208
|
this.toolScoreMultipliers = toolScoreMultipliers;
|
|
2165
2209
|
this.docCount = source.length;
|
|
2166
2210
|
this.bm25Scorer = new BM25ScorerImpl(searchConfig);
|
|
2167
|
-
|
|
2211
|
+
const vectorEnabled = searchConfig?.vectorEnabled ?? SEARCH_VECTOR_ENABLED;
|
|
2212
|
+
this.embeddingEngine = vectorEnabled ? new EmbeddingEngine() : null;
|
|
2168
2213
|
this.feedbackTracker = new FeedbackTracker(searchConfig);
|
|
2169
2214
|
this.intentBoost = new IntentBoostImpl(searchConfig?.intentToolBoostRules);
|
|
2170
2215
|
let totalLength = 0;
|
|
@@ -2193,9 +2238,7 @@ var ToolSearchEngine = class {
|
|
|
2193
2238
|
length: allTokens.length,
|
|
2194
2239
|
nameTokens,
|
|
2195
2240
|
nameTokenSet,
|
|
2196
|
-
nameTokenCount: nameTokenSet.size
|
|
2197
|
-
tfidfWeights: /* @__PURE__ */ new Map(),
|
|
2198
|
-
tfidfMagnitude: 0
|
|
2241
|
+
nameTokenCount: nameTokenSet.size
|
|
2199
2242
|
};
|
|
2200
2243
|
this.docs.push(doc);
|
|
2201
2244
|
this.docNameIndex.set(tool.name, i);
|
|
@@ -2252,31 +2295,30 @@ var ToolSearchEngine = class {
|
|
|
2252
2295
|
}
|
|
2253
2296
|
this.avgDocLength = this.docCount > 0 ? totalLength / this.docCount : 1;
|
|
2254
2297
|
this.sortedKeys = [...this.invertedIndex.keys()].toSorted();
|
|
2255
|
-
const idfMap = /* @__PURE__ */ new Map();
|
|
2256
|
-
for (const [term, postings] of this.invertedIndex) idfMap.set(term, Math.log(1 + this.docCount / postings.length));
|
|
2257
|
-
this.idfMap = idfMap;
|
|
2258
|
-
for (let i = 0; i < this.docCount; i++) {
|
|
2259
|
-
const doc = this.docs[i];
|
|
2260
|
-
const rawTf = /* @__PURE__ */ new Map();
|
|
2261
|
-
for (const token of doc.tokens) rawTf.set(token, (rawTf.get(token) ?? 0) + 1);
|
|
2262
|
-
const tfidfWeights = /* @__PURE__ */ new Map();
|
|
2263
|
-
let magnitudeSq = 0;
|
|
2264
|
-
for (const [term, tf] of rawTf) {
|
|
2265
|
-
const idf = idfMap.get(term) ?? 0;
|
|
2266
|
-
const w = (1 + Math.log(tf)) * idf;
|
|
2267
|
-
tfidfWeights.set(term, w);
|
|
2268
|
-
magnitudeSq += w * w;
|
|
2269
|
-
}
|
|
2270
|
-
doc.tfidfWeights = tfidfWeights;
|
|
2271
|
-
doc.tfidfMagnitude = Math.sqrt(magnitudeSq);
|
|
2272
|
-
}
|
|
2273
2298
|
this.affinityGraph = this.buildAffinityGraph();
|
|
2274
2299
|
this.trigramIndex = new TrigramIndex(this.docs.map((d) => d.name));
|
|
2275
2300
|
this.queryCache = new LRUCache(SEARCH_QUERY_CACHE_CAPACITY);
|
|
2276
2301
|
}
|
|
2277
|
-
async search(query, topK = 10, activeToolNames, visibleDomains) {
|
|
2278
|
-
|
|
2302
|
+
async search(query, topK = 10, activeToolNames, visibleDomains, profile) {
|
|
2303
|
+
let queryTokens = this.bm25Scorer.tokenise(query);
|
|
2279
2304
|
if (queryTokens.length === 0) return [];
|
|
2305
|
+
if (queryTokens.length > 6) {
|
|
2306
|
+
const inVocab = queryTokens.filter((t) => this.invertedIndex.has(t));
|
|
2307
|
+
if (inVocab.length >= 3) {
|
|
2308
|
+
const scored = inVocab.map((t) => {
|
|
2309
|
+
const df = this.invertedIndex.get(t).length;
|
|
2310
|
+
return {
|
|
2311
|
+
token: t,
|
|
2312
|
+
idf: Math.log((this.docCount - df + .5) / (df + .5) + 1)
|
|
2313
|
+
};
|
|
2314
|
+
});
|
|
2315
|
+
scored.sort((a, b) => b.idf - a.idf);
|
|
2316
|
+
const kept = new Set(scored.slice(0, 6).map((s) => s.token));
|
|
2317
|
+
queryTokens = queryTokens.filter((t) => kept.has(t));
|
|
2318
|
+
}
|
|
2319
|
+
}
|
|
2320
|
+
const synonymTokens = this.bm25Scorer.tokenise(queryTokens.join(" "), { expandSynonyms: true }).filter((t) => !queryTokens.includes(t));
|
|
2321
|
+
queryTokens.push(...synonymTokens);
|
|
2280
2322
|
const explicitToolMention = (() => {
|
|
2281
2323
|
const lower = query.toLowerCase();
|
|
2282
2324
|
if (!/(?:\b(?:call|use|run|invoke|execute)\b|调用|执行|使用|运行)/i.test(lower)) return null;
|
|
@@ -2347,11 +2389,10 @@ var ToolSearchEngine = class {
|
|
|
2347
2389
|
const toolMultiplier = this.toolScoreMultipliers?.get(doc.name) ?? 1;
|
|
2348
2390
|
if (toolMultiplier !== 1) scores[i] *= toolMultiplier;
|
|
2349
2391
|
}
|
|
2350
|
-
this.
|
|
2351
|
-
this.applyDomainHubExpansion(scores);
|
|
2392
|
+
this.applyGraphExpansion(scores);
|
|
2352
2393
|
this.applyIntentBonusBand(scores, intentToolBonuses);
|
|
2353
2394
|
this.applyRecencyBoost(scores);
|
|
2354
|
-
this.applyTierPenalty(scores, visibleDomains);
|
|
2395
|
+
this.applyTierPenalty(scores, visibleDomains, profile);
|
|
2355
2396
|
if (explicitToolMention) {
|
|
2356
2397
|
const explicitIdx = this.docNameIndex.get(explicitToolMention);
|
|
2357
2398
|
if (explicitIdx !== void 0) {
|
|
@@ -2421,9 +2462,9 @@ var ToolSearchEngine = class {
|
|
|
2421
2462
|
* tier. The penalty is a soft multiplier in [0, 1]; 1 disables the feature.
|
|
2422
2463
|
* Tools without a resolved domain are left untouched.
|
|
2423
2464
|
*/
|
|
2424
|
-
applyTierPenalty(scores, visibleDomains) {
|
|
2465
|
+
applyTierPenalty(scores, visibleDomains, profile) {
|
|
2425
2466
|
if (!visibleDomains || visibleDomains.size === 0) return;
|
|
2426
|
-
const penalty = SEARCH_TIER_PENALTY;
|
|
2467
|
+
const penalty = profile ? profile === "full" ? SEARCH_TIER_PENALTY_FULL : profile === "workflow" ? SEARCH_TIER_PENALTY_WORKFLOW : SEARCH_TIER_PENALTY_SEARCH : SEARCH_TIER_PENALTY;
|
|
2427
2468
|
if (penalty >= 1 || penalty <= 0) return;
|
|
2428
2469
|
for (let i = 0; i < this.docCount; i++) {
|
|
2429
2470
|
if (scores[i] <= 0) continue;
|
|
@@ -2496,28 +2537,34 @@ var ToolSearchEngine = class {
|
|
|
2496
2537
|
* independently contribute — a document with BM25=0 but high trigram
|
|
2497
2538
|
* similarity can still surface.
|
|
2498
2539
|
*/
|
|
2499
|
-
async applyRRFFusion(
|
|
2540
|
+
async applyRRFFusion(_queryTokens, query, scores) {
|
|
2500
2541
|
const k = SEARCH_RRF_K;
|
|
2501
2542
|
const trigramWeight = SEARCH_TRIGRAM_WEIGHT;
|
|
2502
|
-
const tfidfWeight = SEARCH_TFIDF_COSINE_WEIGHT;
|
|
2503
2543
|
const bm25Ranked = this.rankByScores(scores);
|
|
2504
|
-
const cosineScores = this.computeTfidfCosineScores(queryTokens);
|
|
2505
|
-
const cosineRanked = this.rankByMap(cosineScores);
|
|
2506
2544
|
const trigramScores = this.trigramIndex.search(query, SEARCH_TRIGRAM_THRESHOLD);
|
|
2507
2545
|
const trigramRanked = this.rankByMap(trigramScores);
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
if (
|
|
2511
|
-
const
|
|
2512
|
-
|
|
2513
|
-
|
|
2546
|
+
let vectorScores;
|
|
2547
|
+
let vectorRanked;
|
|
2548
|
+
if (SEARCH_VECTOR_BM25_SKIP_THRESHOLD > 0 && bm25Ranked.size > 0) {
|
|
2549
|
+
const topBm25Idx = [...bm25Ranked.entries()].find(([, r]) => r === 0)?.[0];
|
|
2550
|
+
if ((topBm25Idx !== void 0 ? scores[topBm25Idx] : 0) >= SEARCH_VECTOR_BM25_SKIP_THRESHOLD) {
|
|
2551
|
+
vectorScores = /* @__PURE__ */ new Map();
|
|
2552
|
+
vectorRanked = /* @__PURE__ */ new Map();
|
|
2553
|
+
} else {
|
|
2554
|
+
vectorScores = await this.computeVectorCosineScores(query);
|
|
2555
|
+
vectorRanked = this.rankByMap(vectorScores);
|
|
2556
|
+
}
|
|
2557
|
+
} else {
|
|
2558
|
+
vectorScores = await this.computeVectorCosineScores(query);
|
|
2559
|
+
vectorRanked = this.rankByMap(vectorScores);
|
|
2514
2560
|
}
|
|
2561
|
+
const ranking = /* @__PURE__ */ new Map();
|
|
2562
|
+
for (const [docIdx, rank] of vectorRanked) ranking.set(this.docs[docIdx].name, rank);
|
|
2563
|
+
this.feedbackTracker.recordVectorRanking(ranking);
|
|
2515
2564
|
for (let i = 0; i < this.docCount; i++) {
|
|
2516
2565
|
let rrfScore = 0;
|
|
2517
2566
|
const bm25Rank = bm25Ranked.get(i);
|
|
2518
2567
|
if (bm25Rank !== void 0) rrfScore += 1 / (k + bm25Rank);
|
|
2519
|
-
const cosineRank = cosineRanked.get(i);
|
|
2520
|
-
if (cosineRank !== void 0 && tfidfWeight > 0) rrfScore += tfidfWeight * (1 / (k + cosineRank));
|
|
2521
2568
|
const trigramRank = trigramRanked.get(i);
|
|
2522
2569
|
if (trigramRank !== void 0 && trigramWeight > 0) rrfScore += trigramWeight * (1 / (k + trigramRank));
|
|
2523
2570
|
const vectorRank = vectorRanked.get(i);
|
|
@@ -2531,38 +2578,6 @@ var ToolSearchEngine = class {
|
|
|
2531
2578
|
}
|
|
2532
2579
|
}
|
|
2533
2580
|
/**
|
|
2534
|
-
* Compute raw TF-IDF cosine similarity scores for each document.
|
|
2535
|
-
* Returns Map<docIndex, cosineScore>.
|
|
2536
|
-
*/
|
|
2537
|
-
computeTfidfCosineScores(queryTokens) {
|
|
2538
|
-
const queryTf = /* @__PURE__ */ new Map();
|
|
2539
|
-
for (const token of queryTokens) queryTf.set(token, (queryTf.get(token) ?? 0) + 1);
|
|
2540
|
-
const queryWeights = /* @__PURE__ */ new Map();
|
|
2541
|
-
let queryMagSq = 0;
|
|
2542
|
-
for (const [term, tf] of queryTf) {
|
|
2543
|
-
const idf = this.idfMap.get(term) ?? 0;
|
|
2544
|
-
if (idf === 0) continue;
|
|
2545
|
-
const w = (1 + Math.log(tf)) * idf;
|
|
2546
|
-
queryWeights.set(term, w);
|
|
2547
|
-
queryMagSq += w * w;
|
|
2548
|
-
}
|
|
2549
|
-
if (queryMagSq === 0) return /* @__PURE__ */ new Map();
|
|
2550
|
-
const queryMagnitude = Math.sqrt(queryMagSq);
|
|
2551
|
-
const results = /* @__PURE__ */ new Map();
|
|
2552
|
-
for (let i = 0; i < this.docCount; i++) {
|
|
2553
|
-
const doc = this.docs[i];
|
|
2554
|
-
if (doc.tfidfMagnitude === 0) continue;
|
|
2555
|
-
let dot = 0;
|
|
2556
|
-
for (const [term, qw] of queryWeights) {
|
|
2557
|
-
const dw = doc.tfidfWeights.get(term);
|
|
2558
|
-
if (dw !== void 0) dot += qw * dw;
|
|
2559
|
-
}
|
|
2560
|
-
if (dot <= 0) continue;
|
|
2561
|
-
results.set(i, dot / (queryMagnitude * doc.tfidfMagnitude));
|
|
2562
|
-
}
|
|
2563
|
-
return results;
|
|
2564
|
-
}
|
|
2565
|
-
/**
|
|
2566
2581
|
* Rank documents by Float64Array scores.
|
|
2567
2582
|
* Returns Map<docIndex, rank> (0-based, lower = better).
|
|
2568
2583
|
*/
|
|
@@ -2704,51 +2719,41 @@ var ToolSearchEngine = class {
|
|
|
2704
2719
|
return graph;
|
|
2705
2720
|
}
|
|
2706
2721
|
/**
|
|
2707
|
-
*
|
|
2708
|
-
*
|
|
2709
|
-
*
|
|
2722
|
+
* Combined graph-based expansion: affinity (prefix-group co-retrieval) +
|
|
2723
|
+
* domain hub (coherence boost for well-represented domains).
|
|
2724
|
+
* Single sort of scored documents feeds both expansion strategies.
|
|
2710
2725
|
*/
|
|
2711
|
-
|
|
2712
|
-
if (this.affinityGraph.size === 0) return;
|
|
2713
|
-
const topN = SEARCH_AFFINITY_TOP_N;
|
|
2726
|
+
applyGraphExpansion(scores) {
|
|
2714
2727
|
const scored = [];
|
|
2715
2728
|
for (let i = 0; i < this.docCount; i++) if (scores[i] > 0) scored.push({
|
|
2716
2729
|
idx: i,
|
|
2717
2730
|
score: scores[i]
|
|
2718
2731
|
});
|
|
2732
|
+
if (scored.length === 0) return;
|
|
2719
2733
|
scored.sort((a, b) => b.score - a.score);
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
const
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2734
|
+
if (this.affinityGraph.size > 0) {
|
|
2735
|
+
const topN = SEARCH_AFFINITY_TOP_N;
|
|
2736
|
+
const boostFactor = SEARCH_AFFINITY_BOOST_FACTOR;
|
|
2737
|
+
const limit = Math.min(topN, scored.length);
|
|
2738
|
+
for (let rank = 0; rank < limit; rank++) {
|
|
2739
|
+
const { idx, score } = scored[rank];
|
|
2740
|
+
const neighbors = this.affinityGraph.get(idx);
|
|
2741
|
+
if (!neighbors) continue;
|
|
2742
|
+
const rankDecay = 1 / (1 + rank);
|
|
2743
|
+
for (const { docIndex, weight } of neighbors) if (scores[docIndex] > 0) scores[docIndex] += score * weight * rankDecay * boostFactor;
|
|
2744
|
+
}
|
|
2728
2745
|
}
|
|
2729
|
-
}
|
|
2730
|
-
/**
|
|
2731
|
-
* Domain hub expansion (§4.1.4): when a domain is heavily represented
|
|
2732
|
-
* in top results, slightly boost remaining tools from that domain.
|
|
2733
|
-
*/
|
|
2734
|
-
applyDomainHubExpansion(scores) {
|
|
2735
2746
|
const threshold = SEARCH_DOMAIN_HUB_THRESHOLD;
|
|
2736
|
-
if (threshold
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
idx
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
for (const { idx } of top10) {
|
|
2747
|
-
const domain = this.docs[idx].domain;
|
|
2748
|
-
if (domain) domainCounts.set(domain, (domainCounts.get(domain) ?? 0) + 1);
|
|
2749
|
-
}
|
|
2750
|
-
for (const [domain, count] of domainCounts) if (count >= threshold) {
|
|
2751
|
-
for (let i = 0; i < this.docCount; i++) if (scores[i] > 0 && this.docs[i].domain === domain) scores[i] *= SEARCH_DOMAIN_HUB_BOOST_MULTIPLIER;
|
|
2747
|
+
if (threshold > 0 && scored.length >= threshold) {
|
|
2748
|
+
const top10 = scored.slice(0, 10);
|
|
2749
|
+
const domainCounts = /* @__PURE__ */ new Map();
|
|
2750
|
+
for (const { idx } of top10) {
|
|
2751
|
+
const domain = this.docs[idx].domain;
|
|
2752
|
+
if (domain) domainCounts.set(domain, (domainCounts.get(domain) ?? 0) + 1);
|
|
2753
|
+
}
|
|
2754
|
+
for (const [domain, count] of domainCounts) if (count >= threshold) {
|
|
2755
|
+
for (let i = 0; i < this.docCount; i++) if (scores[i] > 0 && this.docs[i].domain === domain) scores[i] *= SEARCH_DOMAIN_HUB_BOOST_MULTIPLIER;
|
|
2756
|
+
}
|
|
2752
2757
|
}
|
|
2753
2758
|
}
|
|
2754
2759
|
};
|
|
@@ -2788,18 +2793,22 @@ function getVisibleDomainsForTier(ctx) {
|
|
|
2788
2793
|
}
|
|
2789
2794
|
return visible;
|
|
2790
2795
|
}
|
|
2796
|
+
function getBaseTier(ctx) {
|
|
2797
|
+
return ctx.baseTier;
|
|
2798
|
+
}
|
|
2791
2799
|
function getExtensionDomainMap(ctx) {
|
|
2792
2800
|
const map = /* @__PURE__ */ new Map();
|
|
2793
2801
|
for (const record of ctx.extensionToolsByName.values()) map.set(record.name, record.domain);
|
|
2794
2802
|
return map;
|
|
2795
2803
|
}
|
|
2796
|
-
function getCombinedTools(ctx) {
|
|
2804
|
+
async function getCombinedTools(ctx) {
|
|
2805
|
+
await ensureAllDomainsLoaded();
|
|
2797
2806
|
const tools = new Map(allTools.map((tool) => [tool.name, tool]));
|
|
2798
2807
|
for (const record of ctx.extensionToolsByName.values()) tools.set(record.name, record.tool);
|
|
2799
2808
|
return [...tools.values()];
|
|
2800
2809
|
}
|
|
2801
|
-
function getToolByName(ctx) {
|
|
2802
|
-
return new Map(getCombinedTools(ctx).map((tool) => [tool.name, tool]));
|
|
2810
|
+
async function getToolByName(ctx) {
|
|
2811
|
+
return new Map((await getCombinedTools(ctx)).map((tool) => [tool.name, tool]));
|
|
2803
2812
|
}
|
|
2804
2813
|
const searchEngineCache = /* @__PURE__ */ new WeakMap();
|
|
2805
2814
|
/**
|
|
@@ -2812,11 +2821,12 @@ function buildSearchSignature(ctx) {
|
|
|
2812
2821
|
extParts.sort();
|
|
2813
2822
|
return [ctx.extensionWorkflowRuntimeById.size, extParts.join("|")].join("::");
|
|
2814
2823
|
}
|
|
2815
|
-
function getSearchEngine(ctx) {
|
|
2824
|
+
async function getSearchEngine(ctx) {
|
|
2825
|
+
await ensureAllDomainsLoaded();
|
|
2816
2826
|
const signature = buildSearchSignature(ctx);
|
|
2817
2827
|
const cached = searchEngineCache.get(ctx);
|
|
2818
2828
|
if (cached?.signature === signature) return cached.engine;
|
|
2819
|
-
const tools = getCombinedTools(ctx);
|
|
2829
|
+
const tools = await getCombinedTools(ctx);
|
|
2820
2830
|
const extensionDomains = getExtensionDomainMap(ctx);
|
|
2821
2831
|
const domainScoreMultipliers = /* @__PURE__ */ new Map();
|
|
2822
2832
|
const toolScoreMultipliers = /* @__PURE__ */ new Map();
|
|
@@ -2833,14 +2843,14 @@ function getSearchEngine(ctx) {
|
|
|
2833
2843
|
});
|
|
2834
2844
|
return engine;
|
|
2835
2845
|
}
|
|
2836
|
-
/** Generate domain summary description
|
|
2846
|
+
/** Generate domain summary description. Uses metadata when not all domains are loaded. */
|
|
2837
2847
|
function buildDomainDescription(ctx) {
|
|
2838
2848
|
const groups = {};
|
|
2839
2849
|
for (const r of getAllRegistrations()) groups[r.domain] = (groups[r.domain] ?? 0) + 1;
|
|
2840
2850
|
for (const record of ctx.extensionToolsByName.values()) groups[record.domain] = (groups[record.domain] ?? 0) + 1;
|
|
2841
|
-
const
|
|
2842
|
-
const
|
|
2843
|
-
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.`;
|
|
2844
2854
|
}
|
|
2845
2855
|
//#endregion
|
|
2846
2856
|
//#region src/server/MCPServer.search.handlers.domain.ts
|
|
@@ -2853,12 +2863,13 @@ async function handleActivateDomain(ctx, args) {
|
|
|
2853
2863
|
success: false,
|
|
2854
2864
|
error: "domain must be a non-empty string"
|
|
2855
2865
|
}));
|
|
2856
|
-
const validDomains = new Set(
|
|
2866
|
+
const validDomains = new Set(getAllKnownDomains());
|
|
2857
2867
|
for (const record of ctx.extensionToolsByName.values()) validDomains.add(record.domain);
|
|
2858
2868
|
if (!validDomains.has(domain)) return asTextResponse(JSON.stringify({
|
|
2859
2869
|
success: false,
|
|
2860
2870
|
error: `Unknown domain "${domain}". Valid: ${[...validDomains].join(", ")}`
|
|
2861
2871
|
}));
|
|
2872
|
+
await ensureDomainLoaded(domain);
|
|
2862
2873
|
const ttlMinutes = typeof args.ttlMinutes === "number" ? args.ttlMinutes : ACTIVATION_TTL_MINUTES;
|
|
2863
2874
|
const domainTools = [...getToolsByDomains([domain]), ...[...ctx.extensionToolsByName.values()].filter((record) => record.domain === domain).map((record) => record.tool)];
|
|
2864
2875
|
const activeNames = getActiveToolNames(ctx);
|
|
@@ -3416,7 +3427,8 @@ var ActivationController = class {
|
|
|
3416
3427
|
this.boostRules = [...DEFAULT_BOOST_RULES, ...customRules].toSorted((a, b) => b.priority - a.priority);
|
|
3417
3428
|
this.compoundEngine = new CompoundConditionEngine();
|
|
3418
3429
|
this.predictiveBooster = new PredictiveBooster();
|
|
3419
|
-
|
|
3430
|
+
const baseDomains = new Set(getProfileDomains(ctx.baseTier));
|
|
3431
|
+
this.autoPruner = new AutoPruner(eventBus, baseDomains, (domain) => {
|
|
3420
3432
|
logger.info(`[ActivationController] Auto-pruning domain "${domain}"`);
|
|
3421
3433
|
});
|
|
3422
3434
|
this.subscribe();
|
|
@@ -3648,10 +3660,27 @@ function handleToolError(toolName, error) {
|
|
|
3648
3660
|
logger.error(`Tool execution failed: ${toolName}`, error);
|
|
3649
3661
|
throw new McpError(ErrorCode.InternalError, `Execution Failed in ${toolName}: ${error instanceof Error ? error.message : String(error)}`);
|
|
3650
3662
|
}
|
|
3663
|
+
function stripParamDescriptions(schema) {
|
|
3664
|
+
const clone = { ...schema };
|
|
3665
|
+
if (clone.properties) {
|
|
3666
|
+
const props = {};
|
|
3667
|
+
for (const [key, val] of Object.entries(clone.properties)) {
|
|
3668
|
+
const { description: _d, ...rest } = val;
|
|
3669
|
+
props[key] = stripParamDescriptions(rest);
|
|
3670
|
+
}
|
|
3671
|
+
clone.properties = props;
|
|
3672
|
+
}
|
|
3673
|
+
if (clone.items && typeof clone.items === "object") {
|
|
3674
|
+
const { description: _d, ...rest } = clone.items;
|
|
3675
|
+
clone.items = stripParamDescriptions(rest);
|
|
3676
|
+
}
|
|
3677
|
+
if (clone.additionalProperties && typeof clone.additionalProperties === "object" && !Array.isArray(clone.additionalProperties)) clone.additionalProperties = stripParamDescriptions(clone.additionalProperties);
|
|
3678
|
+
return clone;
|
|
3679
|
+
}
|
|
3651
3680
|
function registerSingleTool(ctx, toolDef) {
|
|
3652
3681
|
const builtTool = toolDef;
|
|
3653
3682
|
if (builtTool.__autocomplete) ctx.toolAutocompleteHandlers.set(toolDef.name, builtTool.__autocomplete);
|
|
3654
|
-
const rawSchema = toolDef.inputSchema;
|
|
3683
|
+
const rawSchema = MCP_COMPACT_SCHEMA && toolDef.inputSchema ? stripParamDescriptions(toolDef.inputSchema) : toolDef.inputSchema;
|
|
3655
3684
|
const shape = rawSchema && typeof rawSchema === "object" ? buildZodShape(rawSchema) : {};
|
|
3656
3685
|
const description = toolDef.description ?? toolDef.name;
|
|
3657
3686
|
if (Object.keys(shape).length > 0) {
|
|
@@ -3737,7 +3766,7 @@ async function routeToolRequest(request, ctx, searchEngine) {
|
|
|
3737
3766
|
const availableToolNames = getAvailableToolNames(ctx);
|
|
3738
3767
|
const routeMatch = matchWorkflowRoute(task, ctx);
|
|
3739
3768
|
let presetPlannedToolNames = null;
|
|
3740
|
-
const searchResults = await searchEngine.search(task, maxRecommendations * 2, activeNames, visibleDomains);
|
|
3769
|
+
const searchResults = await searchEngine.search(task, maxRecommendations * 2, activeNames, visibleDomains, getBaseTier(ctx));
|
|
3741
3770
|
let finalResults = [];
|
|
3742
3771
|
if (routeMatch?.workflow.route.kind === "preset") {
|
|
3743
3772
|
const presetTools = buildPresetRecommendations(routeMatch, routingState, ctx, availableToolNames);
|
|
@@ -3904,10 +3933,10 @@ async function routeToolRequest(request, ctx, searchEngine) {
|
|
|
3904
3933
|
async function handleSearchTools(ctx, args) {
|
|
3905
3934
|
const query = args.query;
|
|
3906
3935
|
const topK = args.top_k ?? 10;
|
|
3907
|
-
const engine = getSearchEngine(ctx);
|
|
3936
|
+
const engine = await getSearchEngine(ctx);
|
|
3908
3937
|
const activeNames = getActiveToolNames(ctx);
|
|
3909
3938
|
const visibleDomains = getVisibleDomainsForTier(ctx);
|
|
3910
|
-
const results = await engine.search(query, topK, activeNames, visibleDomains);
|
|
3939
|
+
const results = await engine.search(query, topK, activeNames, visibleDomains, getBaseTier(ctx));
|
|
3911
3940
|
const topResult = results[0];
|
|
3912
3941
|
const topTool = topResult ? describeTool(topResult.name, ctx) : null;
|
|
3913
3942
|
const topExampleArgs = topTool ? generateExampleArgs(topTool.inputSchema) : void 0;
|
|
@@ -3934,12 +3963,14 @@ async function handleSearchTools(ctx, args) {
|
|
|
3934
3963
|
exampleArgs: topExampleArgs,
|
|
3935
3964
|
description: `Call ${topResult.name} directly. Use describe_tool("${topResult.name}") only if you need the full schema.`
|
|
3936
3965
|
});
|
|
3966
|
+
const baseHint = "For guided tool discovery with workflow detection, use route_tool instead. Use activate_tools to enable specific tools, activate_domain for entire domains.";
|
|
3967
|
+
const refinementHint = results.length < 3 ? " Few results — try distilling your query to key concepts (e.g. \"hook fetch\" instead of \"how to intercept fetch requests\")." : "";
|
|
3937
3968
|
const response = {
|
|
3938
3969
|
query,
|
|
3939
3970
|
resultCount: results.length,
|
|
3940
3971
|
results,
|
|
3941
3972
|
nextActions: searchNextActions,
|
|
3942
|
-
hint:
|
|
3973
|
+
hint: baseHint + refinementHint
|
|
3943
3974
|
};
|
|
3944
3975
|
return asTextResponse(JSON.stringify(response, null, 2));
|
|
3945
3976
|
}
|
|
@@ -3957,6 +3988,7 @@ async function notifyToolListChanged(ctx, changed) {
|
|
|
3957
3988
|
}
|
|
3958
3989
|
}
|
|
3959
3990
|
async function activateToolNames(ctx, names) {
|
|
3991
|
+
await ensureAllDomainsLoaded();
|
|
3960
3992
|
const activeNames = getActiveToolNames(ctx);
|
|
3961
3993
|
const activated = [];
|
|
3962
3994
|
const alreadyActive = [];
|
|
@@ -3967,7 +3999,7 @@ async function activateToolNames(ctx, names) {
|
|
|
3967
3999
|
alreadyActive.push(name);
|
|
3968
4000
|
continue;
|
|
3969
4001
|
}
|
|
3970
|
-
const toolDef = getToolByName(ctx).get(name);
|
|
4002
|
+
const toolDef = (await getToolByName(ctx)).get(name);
|
|
3971
4003
|
if (!toolDef) {
|
|
3972
4004
|
notFound.push(name);
|
|
3973
4005
|
continue;
|
|
@@ -4067,7 +4099,7 @@ async function handleRouteTool(ctx, args) {
|
|
|
4067
4099
|
success: false,
|
|
4068
4100
|
error: "task must be a non-empty string"
|
|
4069
4101
|
}));
|
|
4070
|
-
const engine = getSearchEngine(ctx);
|
|
4102
|
+
const engine = await getSearchEngine(ctx);
|
|
4071
4103
|
const autoActivate = context?.autoActivate === true;
|
|
4072
4104
|
let response = populateCallCommands(await routeToolRequest({
|
|
4073
4105
|
task,
|
|
@@ -4181,7 +4213,7 @@ async function handleCallTool(ctx, args) {
|
|
|
4181
4213
|
try {
|
|
4182
4214
|
const response = await ctx.executeToolWithTracking(name, toolArgs);
|
|
4183
4215
|
try {
|
|
4184
|
-
getSearchEngine(ctx).recordToolCallFeedback(name, "");
|
|
4216
|
+
(await getSearchEngine(ctx)).recordToolCallFeedback(name, "");
|
|
4185
4217
|
} catch {}
|
|
4186
4218
|
return attachCallToolMetadata(response, callMetadata);
|
|
4187
4219
|
} catch (error) {
|
|
@@ -4206,7 +4238,7 @@ function buildMetaToolDefinitions(ctx) {
|
|
|
4206
4238
|
properties: {
|
|
4207
4239
|
query: {
|
|
4208
4240
|
type: "string",
|
|
4209
|
-
description: "
|
|
4241
|
+
description: "Before calling, distill your intent into 2-5 key concepts: what action, on what target, in which domain. Pass only those distilled keywords — not the original user request."
|
|
4210
4242
|
},
|
|
4211
4243
|
top_k: {
|
|
4212
4244
|
type: "number",
|
|
@@ -4482,7 +4514,164 @@ Generally, you have three options to deploy hooks:
|
|
|
4482
4514
|
}] }));
|
|
4483
4515
|
}
|
|
4484
4516
|
//#endregion
|
|
4517
|
+
//#region src/server/persistence/RuntimeSnapshotScheduler.ts
|
|
4518
|
+
var RuntimeSnapshotScheduler = class {
|
|
4519
|
+
sources = [];
|
|
4520
|
+
debounceTimer = null;
|
|
4521
|
+
periodicTimer = null;
|
|
4522
|
+
debounceMs;
|
|
4523
|
+
periodicMs;
|
|
4524
|
+
disposed = false;
|
|
4525
|
+
started = false;
|
|
4526
|
+
constructor(options) {
|
|
4527
|
+
this.debounceMs = options?.debounceMs ?? 2e3;
|
|
4528
|
+
this.periodicMs = options?.periodicMs ?? 3e4;
|
|
4529
|
+
}
|
|
4530
|
+
register(filePath, source) {
|
|
4531
|
+
const existing = this.sources.find((entry) => entry.filePath === filePath || entry.source === source);
|
|
4532
|
+
if (existing) {
|
|
4533
|
+
if (existing.filePath !== filePath || existing.source !== source) logger.warn(`skipping conflicting snapshot registration for ${filePath}`);
|
|
4534
|
+
return;
|
|
4535
|
+
}
|
|
4536
|
+
const entry = {
|
|
4537
|
+
source,
|
|
4538
|
+
filePath
|
|
4539
|
+
};
|
|
4540
|
+
this.sources.push(entry);
|
|
4541
|
+
if (this.started) this.restoreOne(entry).catch((err) => logger.warn(`snapshot restore failed for ${entry.filePath}:`, err));
|
|
4542
|
+
}
|
|
4543
|
+
async start() {
|
|
4544
|
+
if (this.started || this.disposed) return;
|
|
4545
|
+
this.started = true;
|
|
4546
|
+
await this.restoreAll();
|
|
4547
|
+
if (this.disposed || this.periodicTimer) return;
|
|
4548
|
+
this.periodicTimer = setInterval(() => {
|
|
4549
|
+
this.scheduleFlush().catch((err) => logger.warn("periodic snapshot failed:", err));
|
|
4550
|
+
}, this.periodicMs);
|
|
4551
|
+
}
|
|
4552
|
+
notifyDirty() {
|
|
4553
|
+
if (this.disposed) return;
|
|
4554
|
+
if (this.debounceTimer) clearTimeout(this.debounceTimer);
|
|
4555
|
+
this.debounceTimer = setTimeout(() => {
|
|
4556
|
+
this.scheduleFlush().catch((err) => logger.warn("debounce snapshot failed:", err));
|
|
4557
|
+
}, this.debounceMs);
|
|
4558
|
+
}
|
|
4559
|
+
async flushAll() {
|
|
4560
|
+
if (this.debounceTimer) {
|
|
4561
|
+
clearTimeout(this.debounceTimer);
|
|
4562
|
+
this.debounceTimer = null;
|
|
4563
|
+
}
|
|
4564
|
+
await this.writeDirtySources();
|
|
4565
|
+
}
|
|
4566
|
+
dispose() {
|
|
4567
|
+
this.disposed = true;
|
|
4568
|
+
if (this.debounceTimer) {
|
|
4569
|
+
clearTimeout(this.debounceTimer);
|
|
4570
|
+
this.debounceTimer = null;
|
|
4571
|
+
}
|
|
4572
|
+
if (this.periodicTimer) {
|
|
4573
|
+
clearInterval(this.periodicTimer);
|
|
4574
|
+
this.periodicTimer = null;
|
|
4575
|
+
}
|
|
4576
|
+
}
|
|
4577
|
+
async restoreAll() {
|
|
4578
|
+
for (const entry of this.sources) await this.restoreOne(entry);
|
|
4579
|
+
}
|
|
4580
|
+
async restoreOne(entry) {
|
|
4581
|
+
try {
|
|
4582
|
+
const data = await readFile(entry.filePath, "utf-8");
|
|
4583
|
+
const parsed = JSON.parse(data);
|
|
4584
|
+
entry.source.restoreSnapshot(parsed);
|
|
4585
|
+
logger.info(`restored snapshot from ${entry.filePath}`);
|
|
4586
|
+
} catch {}
|
|
4587
|
+
}
|
|
4588
|
+
async scheduleFlush() {
|
|
4589
|
+
await this.writeDirtySources();
|
|
4590
|
+
}
|
|
4591
|
+
async writeDirtySources() {
|
|
4592
|
+
for (const entry of this.sources) {
|
|
4593
|
+
if (!entry.source.isPersistDirty()) continue;
|
|
4594
|
+
try {
|
|
4595
|
+
await this.writeSnapshot(entry);
|
|
4596
|
+
} catch (err) {
|
|
4597
|
+
logger.warn(`snapshot write failed for ${entry.filePath}:`, err);
|
|
4598
|
+
}
|
|
4599
|
+
}
|
|
4600
|
+
}
|
|
4601
|
+
async writeSnapshot(entry) {
|
|
4602
|
+
await mkdir(dirname(entry.filePath), { recursive: true });
|
|
4603
|
+
const data = JSON.stringify(entry.source.exportSnapshot());
|
|
4604
|
+
const tmpPath = entry.filePath + ".tmp";
|
|
4605
|
+
await writeFile(tmpPath, data, "utf-8");
|
|
4606
|
+
await rename(tmpPath, entry.filePath);
|
|
4607
|
+
entry.source.markPersisted();
|
|
4608
|
+
}
|
|
4609
|
+
};
|
|
4610
|
+
function getStateDir(baseDir) {
|
|
4611
|
+
return resolve(baseDir, ".jshookmcp", "state");
|
|
4612
|
+
}
|
|
4613
|
+
//#endregion
|
|
4485
4614
|
//#region src/server/MCPServer.ts
|
|
4615
|
+
function shouldCollectExecutionMetrics() {
|
|
4616
|
+
return process.env.E2E_COLLECT_PERFORMANCE === "1";
|
|
4617
|
+
}
|
|
4618
|
+
function captureExecutionMetricMemory() {
|
|
4619
|
+
const memory = process.memoryUsage();
|
|
4620
|
+
return {
|
|
4621
|
+
source: "server",
|
|
4622
|
+
rssBytes: memory.rss,
|
|
4623
|
+
privateBytes: null,
|
|
4624
|
+
virtualBytes: null,
|
|
4625
|
+
heapUsedBytes: memory.heapUsed,
|
|
4626
|
+
heapTotalBytes: memory.heapTotal,
|
|
4627
|
+
externalBytes: memory.external,
|
|
4628
|
+
arrayBuffersBytes: memory.arrayBuffers
|
|
4629
|
+
};
|
|
4630
|
+
}
|
|
4631
|
+
function buildExecutionMetrics(startedAt, startTime, timeoutMs, cpuStart, memoryBefore) {
|
|
4632
|
+
const finishedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
4633
|
+
const cpuUsage = process.cpuUsage(cpuStart);
|
|
4634
|
+
const memoryAfter = captureExecutionMetricMemory();
|
|
4635
|
+
return {
|
|
4636
|
+
source: "server",
|
|
4637
|
+
startedAt,
|
|
4638
|
+
finishedAt,
|
|
4639
|
+
elapsedMs: Number((performance.now() - startTime).toFixed(2)),
|
|
4640
|
+
timeoutMs,
|
|
4641
|
+
serverPid: process.pid,
|
|
4642
|
+
cpuUserMicros: cpuUsage.user,
|
|
4643
|
+
cpuSystemMicros: cpuUsage.system,
|
|
4644
|
+
memoryBefore,
|
|
4645
|
+
memoryAfter,
|
|
4646
|
+
memoryDelta: {
|
|
4647
|
+
rssBytes: memoryAfter.rssBytes - memoryBefore.rssBytes,
|
|
4648
|
+
privateBytes: null,
|
|
4649
|
+
virtualBytes: null,
|
|
4650
|
+
heapUsedBytes: memoryAfter.heapUsedBytes - memoryBefore.heapUsedBytes,
|
|
4651
|
+
heapTotalBytes: memoryAfter.heapTotalBytes - memoryBefore.heapTotalBytes,
|
|
4652
|
+
externalBytes: memoryAfter.externalBytes - memoryBefore.externalBytes,
|
|
4653
|
+
arrayBuffersBytes: memoryAfter.arrayBuffersBytes - memoryBefore.arrayBuffersBytes
|
|
4654
|
+
}
|
|
4655
|
+
};
|
|
4656
|
+
}
|
|
4657
|
+
function appendExecutionMetrics(response, metrics) {
|
|
4658
|
+
const content = response.content;
|
|
4659
|
+
if (!Array.isArray(content)) return response;
|
|
4660
|
+
const firstText = content.find((entry) => typeof entry === "object" && entry !== null && entry.type === "text" && typeof entry.text === "string");
|
|
4661
|
+
if (!firstText) return response;
|
|
4662
|
+
try {
|
|
4663
|
+
const parsed = JSON.parse(firstText.text);
|
|
4664
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return response;
|
|
4665
|
+
const record = parsed;
|
|
4666
|
+
if (!("_executionMetrics" in record)) {
|
|
4667
|
+
record._executionMetrics = metrics;
|
|
4668
|
+
firstText.text = JSON.stringify(record);
|
|
4669
|
+
}
|
|
4670
|
+
} catch {
|
|
4671
|
+
return response;
|
|
4672
|
+
}
|
|
4673
|
+
return response;
|
|
4674
|
+
}
|
|
4486
4675
|
var MCPServer = class {
|
|
4487
4676
|
config;
|
|
4488
4677
|
server;
|
|
@@ -4538,12 +4727,32 @@ var MCPServer = class {
|
|
|
4538
4727
|
this.enabledDomains = this.resolveEnabledDomains(this.selectedTools);
|
|
4539
4728
|
const depsEntries = [];
|
|
4540
4729
|
const manifests = getAllManifests();
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4730
|
+
const loadedByDomain = new Map(manifests.map((m) => [m.domain, m]));
|
|
4731
|
+
const allMeta = getLoaderMetadata();
|
|
4732
|
+
if (!Array.isArray(allMeta)) logger.warn("[MCPServer] getLoaderMetadata returned non-array, skipping domain proxy setup");
|
|
4733
|
+
else for (const meta of allMeta) {
|
|
4734
|
+
const loaded = loadedByDomain.get(meta.domain);
|
|
4735
|
+
if (loaded) {
|
|
4736
|
+
depsEntries.push([meta.depKey, createDomainProxy(this, meta.domain, `${meta.domain}:${meta.depKey}`, () => loaded.ensure(this))]);
|
|
4737
|
+
if (loaded.secondaryDepKeys) {
|
|
4738
|
+
for (const key of loaded.secondaryDepKeys) if (!depsEntries.some(([k]) => k === key)) depsEntries.push([key, createDomainProxy(this, meta.domain, `${meta.domain}:${key}`, async () => {
|
|
4739
|
+
await loaded.ensure(this);
|
|
4740
|
+
return this[key];
|
|
4741
|
+
})]);
|
|
4742
|
+
}
|
|
4743
|
+
} else {
|
|
4744
|
+
depsEntries.push([meta.depKey, createDomainProxy(this, meta.domain, `${meta.domain}:${meta.depKey}`, async () => {
|
|
4745
|
+
const manifest = await ensureDomainLoaded(meta.domain);
|
|
4746
|
+
if (!manifest) throw new Error(`Failed to load domain ${meta.domain}`);
|
|
4747
|
+
return manifest.ensure(this);
|
|
4748
|
+
})]);
|
|
4749
|
+
for (const key of meta.secondaryDepKeys) if (!depsEntries.some(([k]) => k === key)) depsEntries.push([key, createDomainProxy(this, meta.domain, `${meta.domain}:${key}`, async () => {
|
|
4750
|
+
const manifest = await ensureDomainLoaded(meta.domain);
|
|
4751
|
+
if (!manifest) throw new Error(`Failed to load domain ${meta.domain}`);
|
|
4752
|
+
await manifest.ensure(this);
|
|
4753
|
+
return this[key];
|
|
4754
|
+
})]);
|
|
4755
|
+
}
|
|
4547
4756
|
}
|
|
4548
4757
|
this.handlerDeps = Object.fromEntries(depsEntries);
|
|
4549
4758
|
const selectedToolNames = new Set(this.selectedTools.map((t) => t.name));
|
|
@@ -4580,6 +4789,11 @@ var MCPServer = class {
|
|
|
4580
4789
|
this.samplingBridge = new LLMSamplingBridge(this.server);
|
|
4581
4790
|
this.elicitationBridge = new ElicitationBridge(this.server);
|
|
4582
4791
|
this.setDomainInstance("activationController", new ActivationController(this.eventBus, this));
|
|
4792
|
+
const stateDir = getStateDir(process.cwd());
|
|
4793
|
+
const snapshotScheduler = new RuntimeSnapshotScheduler();
|
|
4794
|
+
this.setDomainInstance("snapshotScheduler", snapshotScheduler);
|
|
4795
|
+
this.setDomainInstance("snapshotStateDir", stateDir);
|
|
4796
|
+
snapshotScheduler.start().catch((err) => logger.warn("snapshot scheduler start failed:", err));
|
|
4583
4797
|
this.eventBus.on("tool:progress", async (payload) => {
|
|
4584
4798
|
try {
|
|
4585
4799
|
await this.server.server.notification({
|
|
@@ -4658,7 +4872,7 @@ var MCPServer = class {
|
|
|
4658
4872
|
}
|
|
4659
4873
|
this.cacheRegistrationPromise = (async () => {
|
|
4660
4874
|
try {
|
|
4661
|
-
const { createCacheAdapters } = await import("./CacheAdapters-
|
|
4875
|
+
const { createCacheAdapters } = await import("./CacheAdapters-CDe5WPSV.mjs");
|
|
4662
4876
|
const codeCache = this.collector.getCache();
|
|
4663
4877
|
const codeCompressor = this.collector.getCompressor();
|
|
4664
4878
|
const adapters = createCacheAdapters(this.detailedData, codeCache, codeCompressor);
|
|
@@ -4679,6 +4893,12 @@ var MCPServer = class {
|
|
|
4679
4893
|
}
|
|
4680
4894
|
async executeToolWithTracking(name, args) {
|
|
4681
4895
|
let timeoutTimer;
|
|
4896
|
+
const timeoutMs = 3e4;
|
|
4897
|
+
const collectExecutionMetrics = shouldCollectExecutionMetrics();
|
|
4898
|
+
const executionStartedAt = collectExecutionMetrics ? (/* @__PURE__ */ new Date()).toISOString() : null;
|
|
4899
|
+
const executionStartTime = collectExecutionMetrics ? performance.now() : 0;
|
|
4900
|
+
const executionCpuStart = collectExecutionMetrics ? process.cpuUsage() : null;
|
|
4901
|
+
const executionMemoryBefore = collectExecutionMetrics ? captureExecutionMetricMemory() : null;
|
|
4682
4902
|
try {
|
|
4683
4903
|
timeoutTimer = setTimeout(() => {
|
|
4684
4904
|
try {
|
|
@@ -4687,7 +4907,7 @@ var MCPServer = class {
|
|
|
4687
4907
|
} catch {
|
|
4688
4908
|
logger.warn(`Telemetry Alert [ERR-03]: Tool execution hung (>30s) for '${name}'.`);
|
|
4689
4909
|
}
|
|
4690
|
-
},
|
|
4910
|
+
}, timeoutMs);
|
|
4691
4911
|
timeoutTimer.unref();
|
|
4692
4912
|
let response;
|
|
4693
4913
|
try {
|
|
@@ -4696,7 +4916,8 @@ var MCPServer = class {
|
|
|
4696
4916
|
if (timeoutTimer) clearTimeout(timeoutTimer);
|
|
4697
4917
|
}
|
|
4698
4918
|
this.contextGuard.recordCall(name);
|
|
4699
|
-
|
|
4919
|
+
let enriched = this.contextGuard.enrichResponse(name, response);
|
|
4920
|
+
if (collectExecutionMetrics && executionStartedAt && executionCpuStart && executionMemoryBefore) enriched = appendExecutionMetrics(enriched, buildExecutionMetrics(executionStartedAt, executionStartTime, timeoutMs, executionCpuStart, executionMemoryBefore));
|
|
4700
4921
|
try {
|
|
4701
4922
|
this.tokenBudget.recordToolCall(name, args, enriched);
|
|
4702
4923
|
} catch (trackingError) {
|
|
@@ -4910,7 +5131,8 @@ async function main() {
|
|
|
4910
5131
|
if (cleanup.removedFiles > 0) logger.info(`[artifacts] Startup cleanup removed ${cleanup.removedFiles} files (${cleanup.removedBytes} bytes)`);
|
|
4911
5132
|
}
|
|
4912
5133
|
logger.info("Creating MCP server instance...");
|
|
4913
|
-
|
|
5134
|
+
const explicitProfile = (process.env.MCP_TOOL_PROFILE ?? "").trim().toLowerCase();
|
|
5135
|
+
await initRegistry(explicitProfile === "full" || explicitProfile === "workflow" || explicitProfile === "search" ? explicitProfile : "search");
|
|
4914
5136
|
const server = new MCPServer(config);
|
|
4915
5137
|
const stopArtifactRetentionScheduler = startArtifactRetentionScheduler();
|
|
4916
5138
|
const recoveryWindowMs = Math.max(1e3, RUNTIME_ERROR_WINDOW_MS);
|