trace-mcp 1.7.0 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/cli.js +619 -499
- package/dist/cli.js.map +1 -1
- package/dist/index.js +107 -43
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -4,10 +4,16 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
4
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
5
|
var __getProtoOf = Object.getPrototypeOf;
|
|
6
6
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
8
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
9
|
+
}) : x)(function(x) {
|
|
10
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
11
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
12
|
+
});
|
|
7
13
|
var __esm = (fn, res) => function __init() {
|
|
8
14
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
9
15
|
};
|
|
10
|
-
var __commonJS = (cb, mod) => function
|
|
16
|
+
var __commonJS = (cb, mod) => function __require2() {
|
|
11
17
|
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
12
18
|
};
|
|
13
19
|
var __export = (target, all) => {
|
|
@@ -1106,7 +1112,7 @@ var require_parse = __commonJS({
|
|
|
1106
1112
|
}
|
|
1107
1113
|
return { risky: false };
|
|
1108
1114
|
};
|
|
1109
|
-
var
|
|
1115
|
+
var parse2 = (input, options) => {
|
|
1110
1116
|
if (typeof input !== "string") {
|
|
1111
1117
|
throw new TypeError("Expected a string");
|
|
1112
1118
|
}
|
|
@@ -1276,7 +1282,7 @@ var require_parse = __commonJS({
|
|
|
1276
1282
|
output = token.close = `)$))${extglobStar}`;
|
|
1277
1283
|
}
|
|
1278
1284
|
if (token.inner.includes("*") && (rest = remaining()) && /^\.[^\\/.]+$/.test(rest)) {
|
|
1279
|
-
const expression =
|
|
1285
|
+
const expression = parse2(rest, { ...options, fastpaths: false }).output;
|
|
1280
1286
|
output = token.close = `)${expression})${extglobStar})`;
|
|
1281
1287
|
}
|
|
1282
1288
|
if (token.prev.type === "bos") {
|
|
@@ -1798,7 +1804,7 @@ var require_parse = __commonJS({
|
|
|
1798
1804
|
}
|
|
1799
1805
|
return state;
|
|
1800
1806
|
};
|
|
1801
|
-
|
|
1807
|
+
parse2.fastpaths = (input, options) => {
|
|
1802
1808
|
const opts = { ...options };
|
|
1803
1809
|
const max = typeof opts.maxLength === "number" ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH;
|
|
1804
1810
|
const len = input.length;
|
|
@@ -1863,7 +1869,7 @@ var require_parse = __commonJS({
|
|
|
1863
1869
|
}
|
|
1864
1870
|
return source;
|
|
1865
1871
|
};
|
|
1866
|
-
module.exports =
|
|
1872
|
+
module.exports = parse2;
|
|
1867
1873
|
}
|
|
1868
1874
|
});
|
|
1869
1875
|
|
|
@@ -1872,7 +1878,7 @@ var require_picomatch = __commonJS({
|
|
|
1872
1878
|
"node_modules/picomatch/lib/picomatch.js"(exports, module) {
|
|
1873
1879
|
"use strict";
|
|
1874
1880
|
var scan = require_scan();
|
|
1875
|
-
var
|
|
1881
|
+
var parse2 = require_parse();
|
|
1876
1882
|
var utils = require_utils();
|
|
1877
1883
|
var constants = require_constants();
|
|
1878
1884
|
var isObject = (val) => val && typeof val === "object" && !Array.isArray(val);
|
|
@@ -1960,7 +1966,7 @@ var require_picomatch = __commonJS({
|
|
|
1960
1966
|
picomatch3.isMatch = (str2, patterns, options) => picomatch3(patterns, options)(str2);
|
|
1961
1967
|
picomatch3.parse = (pattern, options) => {
|
|
1962
1968
|
if (Array.isArray(pattern)) return pattern.map((p) => picomatch3.parse(p, options));
|
|
1963
|
-
return
|
|
1969
|
+
return parse2(pattern, { ...options, fastpaths: false });
|
|
1964
1970
|
};
|
|
1965
1971
|
picomatch3.scan = (input, options) => scan(input, options);
|
|
1966
1972
|
picomatch3.compileRe = (state, options, returnOutput = false, returnState = false) => {
|
|
@@ -1986,10 +1992,10 @@ var require_picomatch = __commonJS({
|
|
|
1986
1992
|
}
|
|
1987
1993
|
let parsed = { negated: false, fastpaths: true };
|
|
1988
1994
|
if (options.fastpaths !== false && (input[0] === "." || input[0] === "*")) {
|
|
1989
|
-
parsed.output =
|
|
1995
|
+
parsed.output = parse2.fastpaths(input, options);
|
|
1990
1996
|
}
|
|
1991
1997
|
if (!parsed.output) {
|
|
1992
|
-
parsed =
|
|
1998
|
+
parsed = parse2(input, options);
|
|
1993
1999
|
}
|
|
1994
2000
|
return picomatch3.compileRe(parsed, options, returnOutput, returnState);
|
|
1995
2001
|
};
|
|
@@ -7363,9 +7369,9 @@ var DEFAULT_CONFIG_JSONC = `{
|
|
|
7363
7369
|
"provider": "ollama", // "ollama" | "openai"
|
|
7364
7370
|
// "base_url": "http://localhost:11434", // custom endpoint
|
|
7365
7371
|
// "api_key": "", // required for openai; or set OPENAI_API_KEY env
|
|
7366
|
-
|
|
7367
|
-
|
|
7368
|
-
|
|
7372
|
+
"inference_model": "gemma4-e4b", // ollama: "gemma4-e4b", openai: "gpt-4o-mini"
|
|
7373
|
+
"fast_model": "gemma4-e4b", // ollama: "gemma4-e4b", openai: "gpt-4o-mini"
|
|
7374
|
+
"embedding_model": "qwen3-embedding:0.6b", // ollama: "qwen3-embedding:0.6b", openai: "text-embedding-3-small"
|
|
7369
7375
|
// "embedding_dimensions": 1536, // provider-specific
|
|
7370
7376
|
"summarize_on_index": true,
|
|
7371
7377
|
"summarize_batch_size": 20,
|
|
@@ -9988,10 +9994,34 @@ var DEFAULT_WEIGHTS = { primary: 0.4, dependencies: 0.3, callers: 0.2, typeConte
|
|
|
9988
9994
|
function assembleStructuredContext(request) {
|
|
9989
9995
|
const weights = request.budgetWeights ?? DEFAULT_WEIGHTS;
|
|
9990
9996
|
const budget = request.totalBudget;
|
|
9991
|
-
const
|
|
9992
|
-
const
|
|
9993
|
-
|
|
9994
|
-
|
|
9997
|
+
const categories = ["primary", "dependencies", "callers", "typeContext"];
|
|
9998
|
+
const itemCounts = {
|
|
9999
|
+
primary: request.primary.length,
|
|
10000
|
+
dependencies: request.dependencies.length,
|
|
10001
|
+
callers: request.callers.length,
|
|
10002
|
+
typeContext: request.typeContext.length
|
|
10003
|
+
};
|
|
10004
|
+
let surplusWeight = 0;
|
|
10005
|
+
let activeWeight = 0;
|
|
10006
|
+
for (const cat of categories) {
|
|
10007
|
+
if (itemCounts[cat] === 0) {
|
|
10008
|
+
surplusWeight += weights[cat];
|
|
10009
|
+
} else {
|
|
10010
|
+
activeWeight += weights[cat];
|
|
10011
|
+
}
|
|
10012
|
+
}
|
|
10013
|
+
const effectiveWeights = { primary: 0, dependencies: 0, callers: 0, typeContext: 0 };
|
|
10014
|
+
for (const cat of categories) {
|
|
10015
|
+
if (itemCounts[cat] === 0) {
|
|
10016
|
+
effectiveWeights[cat] = 0;
|
|
10017
|
+
} else if (activeWeight > 0) {
|
|
10018
|
+
effectiveWeights[cat] = weights[cat] + surplusWeight * (weights[cat] / activeWeight);
|
|
10019
|
+
}
|
|
10020
|
+
}
|
|
10021
|
+
const primaryResult = assembleContext(request.primary, Math.floor(budget * effectiveWeights.primary));
|
|
10022
|
+
const depsResult = assembleContext(request.dependencies, Math.floor(budget * effectiveWeights.dependencies));
|
|
10023
|
+
const callersResult = assembleContext(request.callers, Math.floor(budget * effectiveWeights.callers));
|
|
10024
|
+
const typeResult = assembleContext(request.typeContext, Math.floor(budget * effectiveWeights.typeContext));
|
|
9995
10025
|
return {
|
|
9996
10026
|
primary: primaryResult.items,
|
|
9997
10027
|
dependencies: depsResult.items,
|
|
@@ -10034,19 +10064,34 @@ var CALL_EDGES = /* @__PURE__ */ new Set([
|
|
|
10034
10064
|
"nest_injects",
|
|
10035
10065
|
"graphql_resolves"
|
|
10036
10066
|
]);
|
|
10037
|
-
|
|
10038
|
-
|
|
10039
|
-
|
|
10040
|
-
return readByteRange(absPath, sym.byte_start, sym.byte_end, !!file.gitignored) ?? void 0;
|
|
10041
|
-
} catch {
|
|
10042
|
-
return void 0;
|
|
10067
|
+
var FileReadCache = class {
|
|
10068
|
+
constructor(rootPath) {
|
|
10069
|
+
this.rootPath = rootPath;
|
|
10043
10070
|
}
|
|
10044
|
-
|
|
10045
|
-
|
|
10071
|
+
rootPath;
|
|
10072
|
+
cache = /* @__PURE__ */ new Map();
|
|
10073
|
+
readSymbolSource(sym, file) {
|
|
10074
|
+
let buf = this.cache.get(file.id);
|
|
10075
|
+
if (buf === void 0) {
|
|
10076
|
+
try {
|
|
10077
|
+
const absPath = path22.resolve(this.rootPath, file.path);
|
|
10078
|
+
const fs39 = __require("fs");
|
|
10079
|
+
buf = fs39.readFileSync(absPath);
|
|
10080
|
+
} catch {
|
|
10081
|
+
buf = null;
|
|
10082
|
+
}
|
|
10083
|
+
this.cache.set(file.id, buf);
|
|
10084
|
+
}
|
|
10085
|
+
if (!buf || sym.byte_start == null || sym.byte_end == null) return void 0;
|
|
10086
|
+
if (file.gitignored) return "[gitignored]";
|
|
10087
|
+
return buf.subarray(sym.byte_start, sym.byte_end).toString("utf-8");
|
|
10088
|
+
}
|
|
10089
|
+
};
|
|
10090
|
+
function toContextItemCached(sym, file, cache, score, signatureOnly) {
|
|
10046
10091
|
return {
|
|
10047
10092
|
id: sym.symbol_id,
|
|
10048
10093
|
score,
|
|
10049
|
-
source:
|
|
10094
|
+
source: signatureOnly ? void 0 : cache.readSymbolSource(sym, file),
|
|
10050
10095
|
signature: sym.signature ?? void 0,
|
|
10051
10096
|
metadata: `[${sym.kind}] ${sym.fqn ?? sym.name} \u2014 ${file.path}`
|
|
10052
10097
|
};
|
|
@@ -10157,14 +10202,16 @@ function getContextBundle(store, rootPath, opts) {
|
|
|
10157
10202
|
}
|
|
10158
10203
|
}
|
|
10159
10204
|
}
|
|
10205
|
+
const fileCache = new FileReadCache(rootPath);
|
|
10160
10206
|
const primaryItems = primarySymbols.map(
|
|
10161
|
-
(p, i) =>
|
|
10207
|
+
(p, i) => toContextItemCached(p.sym, p.file, fileCache, 1 - i * 0.01, false)
|
|
10162
10208
|
);
|
|
10209
|
+
const MAX_FULL_SOURCE_DEPS = 10;
|
|
10163
10210
|
const depItems = depSymbols.map(
|
|
10164
|
-
(d, i) =>
|
|
10211
|
+
(d, i) => toContextItemCached(d.sym, d.file, fileCache, 0.8 - i * 5e-3, i >= MAX_FULL_SOURCE_DEPS)
|
|
10165
10212
|
);
|
|
10166
10213
|
const callerItems = callerSymbols.map(
|
|
10167
|
-
(c, i) =>
|
|
10214
|
+
(c, i) => toContextItemCached(c.sym, c.file, fileCache, 0.6 - i * 5e-3, i >= MAX_FULL_SOURCE_DEPS)
|
|
10168
10215
|
);
|
|
10169
10216
|
const assembled = assembleStructuredContext({
|
|
10170
10217
|
primary: primaryItems,
|
|
@@ -11628,7 +11675,7 @@ function detectFramework(allFiles) {
|
|
|
11628
11675
|
}
|
|
11629
11676
|
return "unknown";
|
|
11630
11677
|
}
|
|
11631
|
-
function
|
|
11678
|
+
function readSource(rootPath, filePath) {
|
|
11632
11679
|
try {
|
|
11633
11680
|
return fs20.readFileSync(path26.resolve(rootPath, filePath), "utf-8");
|
|
11634
11681
|
} catch {
|
|
@@ -11640,7 +11687,7 @@ function buildExpressChain(store, rootPath, url, allFiles, chain) {
|
|
|
11640
11687
|
const PATH_MW_RE = /(?:app|router)\s*\.\s*use\s*\(\s*['"`]([^'"`]+)['"`]\s*,\s*([A-Za-z][\w.]*)/g;
|
|
11641
11688
|
for (const file of allFiles) {
|
|
11642
11689
|
if (file.framework_role !== "express_router" && file.framework_role !== "express_middleware") continue;
|
|
11643
|
-
const source =
|
|
11690
|
+
const source = readSource(rootPath, file.path);
|
|
11644
11691
|
if (!source) continue;
|
|
11645
11692
|
let match;
|
|
11646
11693
|
const globalRe = new RegExp(GLOBAL_MW_RE.source, "g");
|
|
@@ -11665,7 +11712,7 @@ function buildNestChain(store, rootPath, route, allFiles, chain) {
|
|
|
11665
11712
|
const FILTERS_RE = /@UseFilters\(\s*([^)]+)\s*\)/g;
|
|
11666
11713
|
const controllerFiles = allFiles.filter((f) => f.framework_role === "nest_controller");
|
|
11667
11714
|
for (const file of controllerFiles) {
|
|
11668
|
-
const source =
|
|
11715
|
+
const source = readSource(rootPath, file.path);
|
|
11669
11716
|
if (!source) continue;
|
|
11670
11717
|
const extractDecorators = (regex, scope) => {
|
|
11671
11718
|
const re = new RegExp(regex.source, "g");
|
|
@@ -11718,7 +11765,7 @@ function buildFlaskChain(store, rootPath, url, allFiles, chain) {
|
|
|
11718
11765
|
}
|
|
11719
11766
|
for (const file of allFiles) {
|
|
11720
11767
|
if (file.framework_role !== "flask_routes") continue;
|
|
11721
|
-
const source =
|
|
11768
|
+
const source = readSource(rootPath, file.path);
|
|
11722
11769
|
if (!source) continue;
|
|
11723
11770
|
const decoratorRe = /@([\w.]+)\s*(?:\([^)]*\))?\s*\n\s*(?:@\w[\w.]*\s*(?:\([^)]*\))?\s*\n\s*)*def\s+\w+/g;
|
|
11724
11771
|
let m;
|
|
@@ -11733,7 +11780,7 @@ function buildFlaskChain(store, rootPath, url, allFiles, chain) {
|
|
|
11733
11780
|
function buildFastAPIChain(store, rootPath, url, allFiles, chain) {
|
|
11734
11781
|
for (const file of allFiles) {
|
|
11735
11782
|
if (file.framework_role !== "fastapi_routes" && file.framework_role !== "fastapi_app") continue;
|
|
11736
|
-
const source =
|
|
11783
|
+
const source = readSource(rootPath, file.path);
|
|
11737
11784
|
if (!source) continue;
|
|
11738
11785
|
const addMwRe = /(?:app|router)\s*\.\s*add_middleware\s*\(\s*([\w.]+)/g;
|
|
11739
11786
|
let m;
|
|
@@ -11761,7 +11808,7 @@ function buildFastAPIChain(store, rootPath, url, allFiles, chain) {
|
|
|
11761
11808
|
function buildDjangoChain(store, rootPath, allFiles, chain) {
|
|
11762
11809
|
for (const file of allFiles) {
|
|
11763
11810
|
if (!file.path.endsWith("settings.py") && !file.path.includes("settings/")) continue;
|
|
11764
|
-
const source =
|
|
11811
|
+
const source = readSource(rootPath, file.path);
|
|
11765
11812
|
if (!source) continue;
|
|
11766
11813
|
const mwMatch = source.match(/MIDDLEWARE\s*=\s*\[([\s\S]*?)\]/);
|
|
11767
11814
|
if (!mwMatch) continue;
|
|
@@ -11775,7 +11822,7 @@ function buildDjangoChain(store, rootPath, allFiles, chain) {
|
|
|
11775
11822
|
}
|
|
11776
11823
|
for (const file of allFiles) {
|
|
11777
11824
|
if (file.framework_role !== "view") continue;
|
|
11778
|
-
const source =
|
|
11825
|
+
const source = readSource(rootPath, file.path);
|
|
11779
11826
|
if (!source) continue;
|
|
11780
11827
|
const decoratorRe = /@([\w.]+)\s*(?:\([^)]*\))?\s*\n\s*(?:@\w[\w.]*\s*(?:\([^)]*\))?\s*\n\s*)*(?:def|class)\s+\w+/g;
|
|
11781
11828
|
let m;
|
|
@@ -26828,8 +26875,9 @@ function benchmarkContextBundle(store, symbols, count, rand) {
|
|
|
26828
26875
|
const group = sampled.slice(i * batchSize, (i + 1) * batchSize);
|
|
26829
26876
|
const totalSourceBytes = group.reduce((s, sym) => s + (sym.source_bytes || Math.round(sym.file_byte_length * 0.08)), 0);
|
|
26830
26877
|
const importOverhead = group.length * 200;
|
|
26831
|
-
const
|
|
26832
|
-
const
|
|
26878
|
+
const perCallHintsOverhead = group.length * 120;
|
|
26879
|
+
const bl = estimateTokens3(totalSourceBytes + importOverhead) + perCallHintsOverhead;
|
|
26880
|
+
const tm = estimateTokens3(Math.round((totalSourceBytes + importOverhead) * 0.45));
|
|
26833
26881
|
const names = group.map((g) => g.name).join(", ");
|
|
26834
26882
|
details.push({ query: names, file: group[0].file_path, baseline_tokens: bl, trace_mcp_tokens: tm, reduction_pct: reductionPct(bl, tm) });
|
|
26835
26883
|
}
|
|
@@ -26842,10 +26890,13 @@ function benchmarkBatchOverhead(symbols, files, count, rand) {
|
|
|
26842
26890
|
const details = [];
|
|
26843
26891
|
for (let i = 0; i < batches; i++) {
|
|
26844
26892
|
const group = sampledSymbols.slice(i * batchSize, (i + 1) * batchSize);
|
|
26845
|
-
const
|
|
26893
|
+
const perCallFramingOverhead = 150;
|
|
26894
|
+
const perCallHintsOverhead = 120;
|
|
26895
|
+
const perCallMetadataOverhead = 40;
|
|
26896
|
+
const perCallOverhead = perCallFramingOverhead + perCallHintsOverhead + perCallMetadataOverhead;
|
|
26846
26897
|
const contentTokens = group.reduce((s, sym) => s + estimateTokens3(sym.source_bytes || 200), 0);
|
|
26847
26898
|
const bl = contentTokens + batchSize * perCallOverhead;
|
|
26848
|
-
const tm = contentTokens +
|
|
26899
|
+
const tm = contentTokens + perCallFramingOverhead;
|
|
26849
26900
|
const names = group.map((g) => g.name).join(", ");
|
|
26850
26901
|
details.push({ query: names, file: group[0].file_path, baseline_tokens: bl, trace_mcp_tokens: tm, reduction_pct: reductionPct(bl, tm) });
|
|
26851
26902
|
}
|
|
@@ -28014,7 +28065,14 @@ function registerSessionTools(server, ctx) {
|
|
|
28014
28065
|
const text = response.content?.[0]?.text;
|
|
28015
28066
|
if (text) {
|
|
28016
28067
|
try {
|
|
28017
|
-
|
|
28068
|
+
const parsed = JSON.parse(text);
|
|
28069
|
+
if (parsed && typeof parsed === "object") {
|
|
28070
|
+
delete parsed._hints;
|
|
28071
|
+
delete parsed._optimization_hint;
|
|
28072
|
+
delete parsed._budget_warning;
|
|
28073
|
+
delete parsed._budget_level;
|
|
28074
|
+
}
|
|
28075
|
+
results.push({ tool: call.tool, result: parsed });
|
|
28018
28076
|
} catch {
|
|
28019
28077
|
results.push({ tool: call.tool, result: text });
|
|
28020
28078
|
}
|
|
@@ -28032,7 +28090,7 @@ function registerSessionTools(server, ctx) {
|
|
|
28032
28090
|
}
|
|
28033
28091
|
|
|
28034
28092
|
// src/server/server.ts
|
|
28035
|
-
var PKG_VERSION = true ? "1.
|
|
28093
|
+
var PKG_VERSION = true ? "1.8.0" : "0.0.0-dev";
|
|
28036
28094
|
function j2(value) {
|
|
28037
28095
|
return JSON.stringify(value, (_key, val) => val === null || val === void 0 ? void 0 : val);
|
|
28038
28096
|
}
|
|
@@ -29523,7 +29581,13 @@ var PluginRegistry = class {
|
|
|
29523
29581
|
// src/config.ts
|
|
29524
29582
|
import { cosmiconfig } from "cosmiconfig";
|
|
29525
29583
|
import { z as z13 } from "zod";
|
|
29584
|
+
import fs38 from "fs";
|
|
29585
|
+
|
|
29586
|
+
// src/config-jsonc.ts
|
|
29526
29587
|
import fs37 from "fs";
|
|
29588
|
+
import { modify, applyEdits, parse } from "jsonc-parser";
|
|
29589
|
+
|
|
29590
|
+
// src/config.ts
|
|
29527
29591
|
var SecurityConfigSchema = z13.object({
|
|
29528
29592
|
secret_patterns: z13.array(z13.string()).optional(),
|
|
29529
29593
|
max_file_size_bytes: z13.number().positive().optional(),
|
|
@@ -29726,9 +29790,9 @@ var TraceMcpConfigSchema = z13.object({
|
|
|
29726
29790
|
children: z13.array(z13.string()).optional()
|
|
29727
29791
|
});
|
|
29728
29792
|
function loadGlobalConfigRaw() {
|
|
29729
|
-
if (!
|
|
29793
|
+
if (!fs38.existsSync(GLOBAL_CONFIG_PATH)) return {};
|
|
29730
29794
|
try {
|
|
29731
|
-
return JSON.parse(stripJsonComments(
|
|
29795
|
+
return JSON.parse(stripJsonComments(fs38.readFileSync(GLOBAL_CONFIG_PATH, "utf-8")));
|
|
29732
29796
|
} catch {
|
|
29733
29797
|
return {};
|
|
29734
29798
|
}
|