@szabadkai/graphite 0.1.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 +427 -0
- package/dist/cli/formatters.d.ts +3 -0
- package/dist/cli/formatters.js +61 -0
- package/dist/cli/formatters.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +186 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/indexer/call-resolver.d.ts +8 -0
- package/dist/indexer/call-resolver.js +161 -0
- package/dist/indexer/call-resolver.js.map +1 -0
- package/dist/indexer/extractors/calls.d.ts +17 -0
- package/dist/indexer/extractors/calls.js +206 -0
- package/dist/indexer/extractors/calls.js.map +1 -0
- package/dist/indexer/extractors/classes.d.ts +35 -0
- package/dist/indexer/extractors/classes.js +209 -0
- package/dist/indexer/extractors/classes.js.map +1 -0
- package/dist/indexer/extractors/exports.d.ts +12 -0
- package/dist/indexer/extractors/exports.js +267 -0
- package/dist/indexer/extractors/exports.js.map +1 -0
- package/dist/indexer/extractors/functions.d.ts +12 -0
- package/dist/indexer/extractors/functions.js +169 -0
- package/dist/indexer/extractors/functions.js.map +1 -0
- package/dist/indexer/extractors/imports.d.ts +12 -0
- package/dist/indexer/extractors/imports.js +195 -0
- package/dist/indexer/extractors/imports.js.map +1 -0
- package/dist/indexer/extractors/index.d.ts +7 -0
- package/dist/indexer/extractors/index.js +24 -0
- package/dist/indexer/extractors/index.js.map +1 -0
- package/dist/indexer/extractors/types.d.ts +12 -0
- package/dist/indexer/extractors/types.js +138 -0
- package/dist/indexer/extractors/types.js.map +1 -0
- package/dist/indexer/extractors/variables.d.ts +10 -0
- package/dist/indexer/extractors/variables.js +134 -0
- package/dist/indexer/extractors/variables.js.map +1 -0
- package/dist/indexer/file-discovery.d.ts +7 -0
- package/dist/indexer/file-discovery.js +92 -0
- package/dist/indexer/file-discovery.js.map +1 -0
- package/dist/indexer/file-indexer.d.ts +2 -0
- package/dist/indexer/file-indexer.js +267 -0
- package/dist/indexer/file-indexer.js.map +1 -0
- package/dist/indexer/graph-contract.d.ts +25 -0
- package/dist/indexer/graph-contract.js +7 -0
- package/dist/indexer/graph-contract.js.map +1 -0
- package/dist/indexer/hasher.d.ts +1 -0
- package/dist/indexer/hasher.js +11 -0
- package/dist/indexer/hasher.js.map +1 -0
- package/dist/indexer/import-resolver.d.ts +11 -0
- package/dist/indexer/import-resolver.js +131 -0
- package/dist/indexer/import-resolver.js.map +1 -0
- package/dist/indexer/index.d.ts +11 -0
- package/dist/indexer/index.js +28 -0
- package/dist/indexer/index.js.map +1 -0
- package/dist/indexer/inheritance-resolver.d.ts +7 -0
- package/dist/indexer/inheritance-resolver.js +119 -0
- package/dist/indexer/inheritance-resolver.js.map +1 -0
- package/dist/indexer/parser.d.ts +5 -0
- package/dist/indexer/parser.js +48 -0
- package/dist/indexer/parser.js.map +1 -0
- package/dist/indexer/path-utils.d.ts +3 -0
- package/dist/indexer/path-utils.js +20 -0
- package/dist/indexer/path-utils.js.map +1 -0
- package/dist/indexer/project-indexer.d.ts +14 -0
- package/dist/indexer/project-indexer.js +167 -0
- package/dist/indexer/project-indexer.js.map +1 -0
- package/dist/indexer/property-parsers.d.ts +20 -0
- package/dist/indexer/property-parsers.js +81 -0
- package/dist/indexer/property-parsers.js.map +1 -0
- package/dist/mcp/index.d.ts +3 -0
- package/dist/mcp/index.js +20 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/response-formatter.d.ts +10 -0
- package/dist/mcp/response-formatter.js +47 -0
- package/dist/mcp/response-formatter.js.map +1 -0
- package/dist/mcp/server.d.ts +10 -0
- package/dist/mcp/server.js +118 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools-list.d.ts +9 -0
- package/dist/mcp/tools-list.js +12 -0
- package/dist/mcp/tools-list.js.map +1 -0
- package/dist/mcp/tools.d.ts +13 -0
- package/dist/mcp/tools.js +163 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/query/analyze-impact.d.ts +18 -0
- package/dist/query/analyze-impact.js +58 -0
- package/dist/query/analyze-impact.js.map +1 -0
- package/dist/query/find-callees.d.ts +12 -0
- package/dist/query/find-callees.js +46 -0
- package/dist/query/find-callees.js.map +1 -0
- package/dist/query/find-callers.d.ts +12 -0
- package/dist/query/find-callers.js +46 -0
- package/dist/query/find-callers.js.map +1 -0
- package/dist/query/find-definition.d.ts +3 -0
- package/dist/query/find-definition.js +41 -0
- package/dist/query/find-definition.js.map +1 -0
- package/dist/query/find-dependency-path.d.ts +2 -0
- package/dist/query/find-dependency-path.js +39 -0
- package/dist/query/find-dependency-path.js.map +1 -0
- package/dist/query/find-implementations.d.ts +10 -0
- package/dist/query/find-implementations.js +34 -0
- package/dist/query/find-implementations.js.map +1 -0
- package/dist/query/get-exports.d.ts +3 -0
- package/dist/query/get-exports.js +82 -0
- package/dist/query/get-exports.js.map +1 -0
- package/dist/query/get-file-structure.d.ts +3 -0
- package/dist/query/get-file-structure.js +58 -0
- package/dist/query/get-file-structure.js.map +1 -0
- package/dist/query/get-graph-stats.d.ts +21 -0
- package/dist/query/get-graph-stats.js +42 -0
- package/dist/query/get-graph-stats.js.map +1 -0
- package/dist/query/index.d.ts +11 -0
- package/dist/query/index.js +28 -0
- package/dist/query/index.js.map +1 -0
- package/dist/query/search-symbols.d.ts +6 -0
- package/dist/query/search-symbols.js +75 -0
- package/dist/query/search-symbols.js.map +1 -0
- package/dist/query/types.d.ts +41 -0
- package/dist/query/types.js +36 -0
- package/dist/query/types.js.map +1 -0
- package/dist/storage/database.d.ts +13 -0
- package/dist/storage/database.js +49 -0
- package/dist/storage/database.js.map +1 -0
- package/dist/storage/index.d.ts +7 -0
- package/dist/storage/index.js +24 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/migrations/001_initial.sql +59 -0
- package/dist/storage/migrations/002_add_name_index.sql +9 -0
- package/dist/storage/migrator.d.ts +9 -0
- package/dist/storage/migrator.js +86 -0
- package/dist/storage/migrator.js.map +1 -0
- package/dist/storage/paths.d.ts +5 -0
- package/dist/storage/paths.js +25 -0
- package/dist/storage/paths.js.map +1 -0
- package/dist/storage/reader.d.ts +10 -0
- package/dist/storage/reader.js +103 -0
- package/dist/storage/reader.js.map +1 -0
- package/dist/storage/schema.d.ts +14 -0
- package/dist/storage/schema.js +18 -0
- package/dist/storage/schema.js.map +1 -0
- package/dist/storage/types.d.ts +42 -0
- package/dist/storage/types.js +3 -0
- package/dist/storage/types.js.map +1 -0
- package/dist/storage/writer.d.ts +13 -0
- package/dist/storage/writer.js +160 -0
- package/dist/storage/writer.js.map +1 -0
- package/package.json +47 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Centralized property parsing utilities for edge and node metadata in the indexer.
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.extractImportBindingsFromIndexedEdges = extractImportBindingsFromIndexedEdges;
|
|
5
|
+
exports.parseBindingsFromStoredImportEdge = parseBindingsFromStoredImportEdge;
|
|
6
|
+
exports.parseBindings = parseBindings;
|
|
7
|
+
exports.parseExportInfo = parseExportInfo;
|
|
8
|
+
exports.parseClassMetadata = parseClassMetadata;
|
|
9
|
+
function extractImportBindingsFromIndexedEdges(edges) {
|
|
10
|
+
const bindings = [];
|
|
11
|
+
for (const edge of edges) {
|
|
12
|
+
if (edge.type !== "IMPORTS" || !edge.properties)
|
|
13
|
+
continue;
|
|
14
|
+
try {
|
|
15
|
+
const parsed = JSON.parse(edge.properties);
|
|
16
|
+
if (!parsed.sourcePath)
|
|
17
|
+
continue;
|
|
18
|
+
bindings.push({
|
|
19
|
+
sourcePath: parsed.sourcePath,
|
|
20
|
+
importedName: parsed.importedName ?? null,
|
|
21
|
+
localName: parsed.localName ?? null,
|
|
22
|
+
isTypeOnly: parsed.isTypeOnly ?? false
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
catch { }
|
|
26
|
+
}
|
|
27
|
+
return bindings;
|
|
28
|
+
}
|
|
29
|
+
function parseBindingsFromStoredImportEdge(properties) {
|
|
30
|
+
if (!properties)
|
|
31
|
+
return [];
|
|
32
|
+
try {
|
|
33
|
+
const parsed = JSON.parse(properties);
|
|
34
|
+
return parsed.bindings ?? [];
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function parseBindings(properties) {
|
|
41
|
+
if (!properties)
|
|
42
|
+
return [];
|
|
43
|
+
try {
|
|
44
|
+
const parsed = JSON.parse(properties);
|
|
45
|
+
if (!parsed.sourcePath)
|
|
46
|
+
return [];
|
|
47
|
+
return [parsed];
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function parseExportInfo(properties) {
|
|
54
|
+
if (!properties)
|
|
55
|
+
return { exportedName: null, reExport: false };
|
|
56
|
+
try {
|
|
57
|
+
const parsed = JSON.parse(properties);
|
|
58
|
+
return {
|
|
59
|
+
exportedName: parsed.exportedName ?? null,
|
|
60
|
+
reExport: parsed.reExport ?? false
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return { exportedName: null, reExport: false };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function parseClassMetadata(properties) {
|
|
68
|
+
if (!properties)
|
|
69
|
+
return { extendsName: null, implementsNames: [] };
|
|
70
|
+
try {
|
|
71
|
+
const parsed = JSON.parse(properties);
|
|
72
|
+
return {
|
|
73
|
+
extendsName: parsed.extendsName ?? null,
|
|
74
|
+
implementsNames: parsed.implementsNames ?? []
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return { extendsName: null, implementsNames: [] };
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=property-parsers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"property-parsers.js","sourceRoot":"","sources":["../../src/indexer/property-parsers.ts"],"names":[],"mappings":";AAAA,oFAAoF;;AASpF,sFAuBC;AAED,8EAQC;AAED,sCASC;AAED,0CAcC;AAED,gDAcC;AA5ED,SAAgB,qCAAqC,CACnD,KAAyD;IAEzD,MAAM,QAAQ,GAAoB,EAAE,CAAC;IACrC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,SAAS;QAC1D,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAKxC,CAAC;YACF,IAAI,CAAC,MAAM,CAAC,UAAU;gBAAE,SAAS;YACjC,QAAQ,CAAC,IAAI,CAAC;gBACZ,UAAU,EAAE,MAAM,CAAC,UAAU;gBAC7B,YAAY,EAAE,MAAM,CAAC,YAAY,IAAI,IAAI;gBACzC,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,IAAI;gBACnC,UAAU,EAAE,MAAM,CAAC,UAAU,IAAI,KAAK;aACvC,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;IACZ,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAgB,iCAAiC,CAAC,UAAyB;IACzE,IAAI,CAAC,UAAU;QAAE,OAAO,EAAE,CAAC;IAC3B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAmC,CAAC;QACxE,OAAO,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,SAAgB,aAAa,CAAC,UAAyB;IACrD,IAAI,CAAC,UAAU;QAAE,OAAO,EAAE,CAAC;IAC3B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAkB,CAAC;QACvD,IAAI,CAAC,MAAM,CAAC,UAAU;YAAE,OAAO,EAAE,CAAC;QAClC,OAAO,CAAC,MAAM,CAAC,CAAC;IAClB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,SAAgB,eAAe,CAAC,UAAyB;IAIvD,IAAI,CAAC,UAAU;QAAE,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAChE,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAyD,CAAC;QAC9F,OAAO;YACL,YAAY,EAAE,MAAM,CAAC,YAAY,IAAI,IAAI;YACzC,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,KAAK;SACnC,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IACjD,CAAC;AACH,CAAC;AAED,SAAgB,kBAAkB,CAAC,UAAyB;IAI1D,IAAI,CAAC,UAAU;QAAE,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,eAAe,EAAE,EAAE,EAAE,CAAC;IACnE,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAgE,CAAC;QACrG,OAAO;YACL,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,IAAI;YACvC,eAAe,EAAE,MAAM,CAAC,eAAe,IAAI,EAAE;SAC9C,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,eAAe,EAAE,EAAE,EAAE,CAAC;IACpD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./server"), exports);
|
|
18
|
+
__exportStar(require("./tools"), exports);
|
|
19
|
+
__exportStar(require("./response-formatter"), exports);
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAyB;AACzB,0CAAwB;AACxB,uDAAqC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatToolResponse = formatToolResponse;
|
|
4
|
+
function truncateText(input, maxChars) {
|
|
5
|
+
if (input.length <= maxChars) {
|
|
6
|
+
return { text: input, truncated: false };
|
|
7
|
+
}
|
|
8
|
+
return {
|
|
9
|
+
text: `${input.slice(0, maxChars)}\n... truncated ...`,
|
|
10
|
+
truncated: true
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function sliceResults(payload, maxResults) {
|
|
14
|
+
if (!Array.isArray(payload)) {
|
|
15
|
+
return {
|
|
16
|
+
normalized: payload,
|
|
17
|
+
total: null,
|
|
18
|
+
shown: null,
|
|
19
|
+
truncated: false
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
const total = payload.length;
|
|
23
|
+
const shown = Math.min(maxResults, total);
|
|
24
|
+
const truncated = shown < total;
|
|
25
|
+
return {
|
|
26
|
+
normalized: payload.slice(0, shown),
|
|
27
|
+
total,
|
|
28
|
+
shown,
|
|
29
|
+
truncated
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function formatToolResponse(options) {
|
|
33
|
+
const maxResults = options.maxResults ?? 50;
|
|
34
|
+
const maxChars = options.maxChars ?? 8000;
|
|
35
|
+
const sliced = sliceResults(options.payload, maxResults);
|
|
36
|
+
const serialized = JSON.stringify(sliced.normalized, null, 2);
|
|
37
|
+
const textBlock = `# ${options.title}\n${serialized}`;
|
|
38
|
+
const trunc = truncateText(textBlock, maxChars);
|
|
39
|
+
const truncationSummary = sliced.truncated
|
|
40
|
+
? `\nShowing ${sliced.shown} of ${sliced.total} results. Use max_results to see more.`
|
|
41
|
+
: "";
|
|
42
|
+
return {
|
|
43
|
+
text: `${trunc.text}${truncationSummary}`,
|
|
44
|
+
truncated: trunc.truncated || sliced.truncated
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=response-formatter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response-formatter.js","sourceRoot":"","sources":["../../src/mcp/response-formatter.ts"],"names":[],"mappings":";;AA6CA,gDAoBC;AA1DD,SAAS,YAAY,CAAC,KAAa,EAAE,QAAgB;IACnD,IAAI,KAAK,CAAC,MAAM,IAAI,QAAQ,EAAE,CAAC;QAC7B,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IAC3C,CAAC;IAED,OAAO;QACL,IAAI,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,qBAAqB;QACtD,SAAS,EAAE,IAAI;KAChB,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,OAAgB,EAAE,UAAkB;IAMxD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,OAAO;YACL,UAAU,EAAE,OAAO;YACnB,KAAK,EAAE,IAAI;YACX,KAAK,EAAE,IAAI;YACX,SAAS,EAAE,KAAK;SACjB,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC;IAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IAC1C,MAAM,SAAS,GAAG,KAAK,GAAG,KAAK,CAAC;IAEhC,OAAO;QACL,UAAU,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC;QACnC,KAAK;QACL,KAAK;QACL,SAAS;KACV,CAAC;AACJ,CAAC;AAED,SAAgB,kBAAkB,CAAC,OAA4B;IAI7D,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,EAAE,CAAC;IAC5C,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,IAAI,CAAC;IAE1C,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IACzD,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC9D,MAAM,SAAS,GAAG,KAAK,OAAO,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;IACtD,MAAM,KAAK,GAAG,YAAY,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAEhD,MAAM,iBAAiB,GAAG,MAAM,CAAC,SAAS;QACxC,CAAC,CAAC,aAAa,MAAM,CAAC,KAAK,OAAO,MAAM,CAAC,KAAK,wCAAwC;QACtF,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO;QACL,IAAI,EAAE,GAAG,KAAK,CAAC,IAAI,GAAG,iBAAiB,EAAE;QACzC,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,MAAM,CAAC,SAAS;KAC/C,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface GraphiteMcpServerOptions {
|
|
2
|
+
projectRoot: string;
|
|
3
|
+
maxResults?: number;
|
|
4
|
+
maxChars?: number;
|
|
5
|
+
}
|
|
6
|
+
export interface GraphiteMcpServer {
|
|
7
|
+
start: () => Promise<void>;
|
|
8
|
+
stop: () => Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
export declare function createGraphiteMcpServer(options: GraphiteMcpServerOptions): GraphiteMcpServer;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createGraphiteMcpServer = createGraphiteMcpServer;
|
|
7
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
|
+
const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
|
|
9
|
+
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
10
|
+
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
11
|
+
const storage_1 = require("../storage");
|
|
12
|
+
const indexer_1 = require("../indexer");
|
|
13
|
+
const response_formatter_1 = require("./response-formatter");
|
|
14
|
+
const tools_1 = require("./tools");
|
|
15
|
+
function createGraphiteMcpServer(options) {
|
|
16
|
+
const dbPath = (0, storage_1.resolveDatabasePath)(options.projectRoot);
|
|
17
|
+
const indexExistedBeforeOpen = node_fs_1.default.existsSync(dbPath);
|
|
18
|
+
const databaseManager = (0, storage_1.connectDatabase)({ projectRoot: options.projectRoot });
|
|
19
|
+
const server = new index_js_1.Server({
|
|
20
|
+
name: "graphite",
|
|
21
|
+
version: "0.1.0"
|
|
22
|
+
}, {
|
|
23
|
+
capabilities: {
|
|
24
|
+
tools: {}
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
let lastIndexTime = 0;
|
|
28
|
+
// H10: Re-index if more than 5 minutes have elapsed since the last index
|
|
29
|
+
const STALE_THRESHOLD_MS = 5 * 60 * 1000;
|
|
30
|
+
const ensureIndexed = () => {
|
|
31
|
+
const now = Date.now();
|
|
32
|
+
const isStale = lastIndexTime > 0 && (now - lastIndexTime) > STALE_THRESHOLD_MS;
|
|
33
|
+
if (lastIndexTime > 0 && !isStale) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const fileCount = databaseManager.db.prepare("SELECT COUNT(*) as count FROM files").get().count;
|
|
37
|
+
if (!indexExistedBeforeOpen || fileCount === 0 || isStale) {
|
|
38
|
+
(0, indexer_1.indexProject)({
|
|
39
|
+
projectRoot: options.projectRoot,
|
|
40
|
+
db: databaseManager.db
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
lastIndexTime = Date.now();
|
|
44
|
+
};
|
|
45
|
+
server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => {
|
|
46
|
+
return {
|
|
47
|
+
tools: tools_1.MCP_TOOLS.map((tool) => ({
|
|
48
|
+
name: tool.name,
|
|
49
|
+
description: tool.description,
|
|
50
|
+
inputSchema: tool.inputSchema
|
|
51
|
+
}))
|
|
52
|
+
};
|
|
53
|
+
});
|
|
54
|
+
server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
55
|
+
try {
|
|
56
|
+
ensureIndexed();
|
|
57
|
+
const tool = (0, tools_1.getToolByName)(request.params.name);
|
|
58
|
+
if (!tool) {
|
|
59
|
+
return {
|
|
60
|
+
isError: true,
|
|
61
|
+
content: [
|
|
62
|
+
{
|
|
63
|
+
type: "text",
|
|
64
|
+
text: `Unknown tool: ${request.params.name}`
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
const args = request.params.arguments ?? {};
|
|
70
|
+
const result = tool.execute(databaseManager.db, args);
|
|
71
|
+
const formatted = (0, response_formatter_1.formatToolResponse)({
|
|
72
|
+
title: tool.name,
|
|
73
|
+
payload: result,
|
|
74
|
+
maxResults: options.maxResults,
|
|
75
|
+
maxChars: options.maxChars
|
|
76
|
+
});
|
|
77
|
+
return {
|
|
78
|
+
content: [
|
|
79
|
+
{
|
|
80
|
+
type: "text",
|
|
81
|
+
text: formatted.text
|
|
82
|
+
}
|
|
83
|
+
]
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
const message = error instanceof Error ? error.message : "Unknown tool error";
|
|
88
|
+
return {
|
|
89
|
+
isError: true,
|
|
90
|
+
content: [
|
|
91
|
+
{
|
|
92
|
+
type: "text",
|
|
93
|
+
text: message
|
|
94
|
+
}
|
|
95
|
+
]
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
const transport = new stdio_js_1.StdioServerTransport();
|
|
100
|
+
const stop = async () => {
|
|
101
|
+
databaseManager.close();
|
|
102
|
+
await server.close();
|
|
103
|
+
};
|
|
104
|
+
const start = async () => {
|
|
105
|
+
await server.connect(transport);
|
|
106
|
+
const shutdown = async () => {
|
|
107
|
+
await stop();
|
|
108
|
+
process.exit(0);
|
|
109
|
+
};
|
|
110
|
+
process.on("SIGINT", shutdown);
|
|
111
|
+
process.on("SIGTERM", shutdown);
|
|
112
|
+
};
|
|
113
|
+
return {
|
|
114
|
+
start,
|
|
115
|
+
stop
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.listMcpTools = listMcpTools;
|
|
4
|
+
const tools_1 = require("./tools");
|
|
5
|
+
function listMcpTools() {
|
|
6
|
+
return tools_1.MCP_TOOLS.map((tool) => ({
|
|
7
|
+
name: tool.name,
|
|
8
|
+
description: tool.description,
|
|
9
|
+
inputSchema: tool.inputSchema
|
|
10
|
+
}));
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=tools-list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools-list.js","sourceRoot":"","sources":["../../src/mcp/tools-list.ts"],"names":[],"mappings":";;AAEA,oCAcC;AAhBD,mCAAoC;AAEpC,SAAgB,YAAY;IAS1B,OAAO,iBAAS,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC9B,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,WAAW,EAAE,IAAI,CAAC,WAAW;KAC9B,CAAC,CAAC,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type Database from "better-sqlite3";
|
|
2
|
+
export interface McpToolDefinition {
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
inputSchema: {
|
|
6
|
+
type: "object";
|
|
7
|
+
properties?: Record<string, unknown>;
|
|
8
|
+
required?: string[];
|
|
9
|
+
};
|
|
10
|
+
execute: (db: Database.Database, args: Record<string, unknown>) => unknown;
|
|
11
|
+
}
|
|
12
|
+
export declare const MCP_TOOLS: McpToolDefinition[];
|
|
13
|
+
export declare function getToolByName(name: string): McpToolDefinition | undefined;
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MCP_TOOLS = void 0;
|
|
4
|
+
exports.getToolByName = getToolByName;
|
|
5
|
+
const index_1 = require("../index");
|
|
6
|
+
function requireString(args, key) {
|
|
7
|
+
const value = args[key];
|
|
8
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
9
|
+
throw new Error(`Missing required argument '${key}'.`);
|
|
10
|
+
}
|
|
11
|
+
return value;
|
|
12
|
+
}
|
|
13
|
+
function optionalString(args, key) {
|
|
14
|
+
const value = args[key];
|
|
15
|
+
return typeof value === "string" && value.trim().length > 0 ? value : undefined;
|
|
16
|
+
}
|
|
17
|
+
function optionalNumber(args, key) {
|
|
18
|
+
const value = args[key];
|
|
19
|
+
return typeof value === "number" ? value : undefined;
|
|
20
|
+
}
|
|
21
|
+
exports.MCP_TOOLS = [
|
|
22
|
+
{
|
|
23
|
+
name: "find_definition",
|
|
24
|
+
description: "Find definition(s) for a symbol by exact name. Returns file path, line numbers, type, and signature for each match. Use this to locate where a function, class, variable, or type is defined.",
|
|
25
|
+
inputSchema: {
|
|
26
|
+
type: "object",
|
|
27
|
+
properties: {
|
|
28
|
+
symbol: { type: "string", description: "Exact name of the symbol to find (e.g. 'UserService', 'handleClick')." },
|
|
29
|
+
type: { type: "string", description: "Optional node type filter: Function, Class, Method, Interface, TypeAlias, Enum, Variable." }
|
|
30
|
+
},
|
|
31
|
+
required: ["symbol"]
|
|
32
|
+
},
|
|
33
|
+
execute: (db, args) => (0, index_1.findDefinition)(db, requireString(args, "symbol"), optionalString(args, "type"))
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
name: "search_symbols",
|
|
37
|
+
description: "Search symbols using prefix matching. Returns ranked results with file paths and signatures. Use this when you only know part of a symbol name or want to explore what symbols exist.",
|
|
38
|
+
inputSchema: {
|
|
39
|
+
type: "object",
|
|
40
|
+
properties: {
|
|
41
|
+
query: { type: "string", description: "Search query — prefix-matched against symbol names (e.g. 'handle' finds handleClick, handleSubmit)." },
|
|
42
|
+
type: { type: "string", description: "Optional node type filter: Function, Class, Method, Interface, TypeAlias, Enum, Variable." },
|
|
43
|
+
max_results: { type: "integer", description: "Maximum number of results to return (default: 20, max: 100)." }
|
|
44
|
+
},
|
|
45
|
+
required: ["query"]
|
|
46
|
+
},
|
|
47
|
+
execute: (db, args) => (0, index_1.searchSymbols)(db, requireString(args, "query"), {
|
|
48
|
+
type: optionalString(args, "type"),
|
|
49
|
+
maxResults: optionalNumber(args, "max_results")
|
|
50
|
+
})
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: "get_file_structure",
|
|
54
|
+
description: "Get all symbols defined in a file, organized by type (functions, classes with members, interfaces, types, enums, variables). Use this to understand a file's API surface.",
|
|
55
|
+
inputSchema: {
|
|
56
|
+
type: "object",
|
|
57
|
+
properties: {
|
|
58
|
+
file_path: { type: "string", description: "Relative file path from project root (e.g. 'src/services/auth.ts')." }
|
|
59
|
+
},
|
|
60
|
+
required: ["file_path"]
|
|
61
|
+
},
|
|
62
|
+
execute: (db, args) => (0, index_1.getFileStructure)(db, requireString(args, "file_path"))
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: "get_exports",
|
|
66
|
+
description: "Get all exports for a file or module. Returns exported names, types, source locations, and whether each is a re-export. Use this to understand a module's public API.",
|
|
67
|
+
inputSchema: {
|
|
68
|
+
type: "object",
|
|
69
|
+
properties: {
|
|
70
|
+
file_or_module: { type: "string", description: "File path (e.g. 'src/utils.ts') or module name (e.g. 'utils') to look up exports for." }
|
|
71
|
+
},
|
|
72
|
+
required: ["file_or_module"]
|
|
73
|
+
},
|
|
74
|
+
execute: (db, args) => (0, index_1.getExports)(db, requireString(args, "file_or_module"))
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: "find_callers",
|
|
78
|
+
description: "Find all functions/methods that call a given symbol, with multi-hop traversal. Use this to understand who depends on a function and trace call chains upward.",
|
|
79
|
+
inputSchema: {
|
|
80
|
+
type: "object",
|
|
81
|
+
properties: {
|
|
82
|
+
symbol: { type: "string", description: "Name of the function or method to find callers of." },
|
|
83
|
+
depth: { type: "integer", description: "How many hops to traverse up the call chain (default: 1, max: practical limit ~10)." },
|
|
84
|
+
max_results: { type: "integer", description: "Maximum results to return (default: 50, max: 500)." }
|
|
85
|
+
},
|
|
86
|
+
required: ["symbol"]
|
|
87
|
+
},
|
|
88
|
+
execute: (db, args) => (0, index_1.findCallers)(db, requireString(args, "symbol"), {
|
|
89
|
+
depth: optionalNumber(args, "depth"),
|
|
90
|
+
maxResults: optionalNumber(args, "max_results")
|
|
91
|
+
})
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
name: "find_callees",
|
|
95
|
+
description: "Find all functions/methods called by a given symbol, with multi-hop traversal. Use this to understand what a function depends on and trace call chains downward.",
|
|
96
|
+
inputSchema: {
|
|
97
|
+
type: "object",
|
|
98
|
+
properties: {
|
|
99
|
+
symbol: { type: "string", description: "Name of the function or method to find callees of." },
|
|
100
|
+
depth: { type: "integer", description: "How many hops to traverse down the call chain (default: 1, max: practical limit ~10)." },
|
|
101
|
+
max_results: { type: "integer", description: "Maximum results to return (default: 50, max: 500)." }
|
|
102
|
+
},
|
|
103
|
+
required: ["symbol"]
|
|
104
|
+
},
|
|
105
|
+
execute: (db, args) => (0, index_1.findCallees)(db, requireString(args, "symbol"), {
|
|
106
|
+
depth: optionalNumber(args, "depth"),
|
|
107
|
+
maxResults: optionalNumber(args, "max_results")
|
|
108
|
+
})
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
name: "get_graph_stats",
|
|
112
|
+
description: "Get summary statistics about the indexed code graph: total files, node counts by type, edge counts by type, index freshness, and most-connected symbols.",
|
|
113
|
+
inputSchema: {
|
|
114
|
+
type: "object",
|
|
115
|
+
properties: {}
|
|
116
|
+
},
|
|
117
|
+
execute: (db) => (0, index_1.getGraphStats)(db)
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
name: "find_implementations",
|
|
121
|
+
description: "Find classes that implement an interface or extend a base class. Use this to find concrete implementations of abstract types.",
|
|
122
|
+
inputSchema: {
|
|
123
|
+
type: "object",
|
|
124
|
+
properties: {
|
|
125
|
+
symbol: { type: "string", description: "Name of the interface or base class to find implementations/subclasses of." }
|
|
126
|
+
},
|
|
127
|
+
required: ["symbol"]
|
|
128
|
+
},
|
|
129
|
+
execute: (db, args) => (0, index_1.findImplementations)(db, requireString(args, "symbol"))
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
name: "analyze_impact",
|
|
133
|
+
description: "Analyze the reverse dependency graph around a symbol. Returns all files and symbols that would be affected if the target symbol changes, grouped by file with depth information.",
|
|
134
|
+
inputSchema: {
|
|
135
|
+
type: "object",
|
|
136
|
+
properties: {
|
|
137
|
+
symbol: { type: "string", description: "Name of the symbol to analyze impact for." },
|
|
138
|
+
max_depth: { type: "integer", description: "Maximum depth of reverse traversal (default: 5, higher = wider blast radius)." }
|
|
139
|
+
},
|
|
140
|
+
required: ["symbol"]
|
|
141
|
+
},
|
|
142
|
+
execute: (db, args) => (0, index_1.analyzeImpact)(db, requireString(args, "symbol"), {
|
|
143
|
+
maxDepth: optionalNumber(args, "max_depth")
|
|
144
|
+
})
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
name: "find_dependency_path",
|
|
148
|
+
description: "Find the shortest import path between two files. Returns the chain of files connected by IMPORTS edges. Use this to understand how two files are connected.",
|
|
149
|
+
inputSchema: {
|
|
150
|
+
type: "object",
|
|
151
|
+
properties: {
|
|
152
|
+
source_file: { type: "string", description: "Relative path of the starting file (e.g. 'src/app.ts')." },
|
|
153
|
+
target_file: { type: "string", description: "Relative path of the target file (e.g. 'src/db/client.ts')." }
|
|
154
|
+
},
|
|
155
|
+
required: ["source_file", "target_file"]
|
|
156
|
+
},
|
|
157
|
+
execute: (db, args) => (0, index_1.findDependencyPath)(db, requireString(args, "source_file"), requireString(args, "target_file"))
|
|
158
|
+
}
|
|
159
|
+
];
|
|
160
|
+
function getToolByName(name) {
|
|
161
|
+
return exports.MCP_TOOLS.find((tool) => tool.name === name);
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/mcp/tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type Database from "better-sqlite3";
|
|
2
|
+
export interface ImpactResult {
|
|
3
|
+
filePath: string;
|
|
4
|
+
symbolCount: number;
|
|
5
|
+
symbols: Array<{
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
type: string;
|
|
9
|
+
depth: number;
|
|
10
|
+
}>;
|
|
11
|
+
}
|
|
12
|
+
export declare function analyzeImpact(db: Database.Database, symbolName: string, options?: {
|
|
13
|
+
maxDepth?: number;
|
|
14
|
+
}): {
|
|
15
|
+
affectedFileCount: number;
|
|
16
|
+
affectedSymbolCount: number;
|
|
17
|
+
files: ImpactResult[];
|
|
18
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.analyzeImpact = analyzeImpact;
|
|
4
|
+
function analyzeImpact(db, symbolName, options) {
|
|
5
|
+
// L4: Default maxDepth=5 per PRD
|
|
6
|
+
const maxDepth = Math.max(1, options?.maxDepth ?? 5);
|
|
7
|
+
const rows = db
|
|
8
|
+
.prepare(`
|
|
9
|
+
WITH RECURSIVE seeds AS (
|
|
10
|
+
SELECT id, 0 as depth FROM nodes WHERE name = ?
|
|
11
|
+
),
|
|
12
|
+
walk(node_id, depth) AS (
|
|
13
|
+
SELECT id, depth FROM seeds
|
|
14
|
+
UNION
|
|
15
|
+
SELECT edges.source_id, walk.depth + 1
|
|
16
|
+
FROM edges
|
|
17
|
+
JOIN walk ON walk.node_id = edges.target_id
|
|
18
|
+
WHERE edges.type IN ('CALLS', 'IMPORTS', 'EXTENDS', 'IMPLEMENTS') AND walk.depth < ?
|
|
19
|
+
)
|
|
20
|
+
SELECT DISTINCT
|
|
21
|
+
nodes.id,
|
|
22
|
+
nodes.name,
|
|
23
|
+
nodes.type,
|
|
24
|
+
nodes.file_path,
|
|
25
|
+
walk.depth
|
|
26
|
+
FROM walk
|
|
27
|
+
JOIN nodes ON nodes.id = walk.node_id
|
|
28
|
+
ORDER BY walk.depth ASC, nodes.file_path ASC, nodes.start_line ASC
|
|
29
|
+
`)
|
|
30
|
+
.all(symbolName, maxDepth);
|
|
31
|
+
const grouped = new Map();
|
|
32
|
+
for (const row of rows) {
|
|
33
|
+
// L4: Exclude the seed symbol itself (depth 0) from impact results
|
|
34
|
+
if (row.depth === 0) {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
const entry = grouped.get(row.file_path) ?? {
|
|
38
|
+
filePath: row.file_path,
|
|
39
|
+
symbolCount: 0,
|
|
40
|
+
symbols: []
|
|
41
|
+
};
|
|
42
|
+
entry.symbols.push({
|
|
43
|
+
id: row.id,
|
|
44
|
+
name: row.name,
|
|
45
|
+
type: row.type,
|
|
46
|
+
depth: row.depth
|
|
47
|
+
});
|
|
48
|
+
entry.symbolCount = entry.symbols.length;
|
|
49
|
+
grouped.set(row.file_path, entry);
|
|
50
|
+
}
|
|
51
|
+
const files = [...grouped.values()];
|
|
52
|
+
return {
|
|
53
|
+
affectedFileCount: files.length,
|
|
54
|
+
affectedSymbolCount: rows.length,
|
|
55
|
+
files
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=analyze-impact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze-impact.js","sourceRoot":"","sources":["../../src/query/analyze-impact.ts"],"names":[],"mappings":";;AAQA,sCA6EC;AA7ED,SAAgB,aAAa,CAC3B,EAAqB,EACrB,UAAkB,EAClB,OAA+B;IAM/B,iCAAiC;IACjC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,QAAQ,IAAI,CAAC,CAAC,CAAC;IAErD,MAAM,IAAI,GAAG,EAAE;SACZ,OAAO,CACN;;;;;;;;;;;;;;;;;;;;;KAqBD,CACA;SACA,GAAG,CAAC,UAAU,EAAE,QAAQ,CAMzB,CAAC;IAEH,MAAM,OAAO,GAAG,IAAI,GAAG,EAAwB,CAAC;IAEhD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,mEAAmE;QACnE,IAAI,GAAG,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;YACpB,SAAS;QACX,CAAC;QAED,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI;YAC1C,QAAQ,EAAE,GAAG,CAAC,SAAS;YACvB,WAAW,EAAE,CAAC;YACd,OAAO,EAAE,EAAE;SACZ,CAAC;QAEF,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;YACjB,EAAE,EAAE,GAAG,CAAC,EAAE;YACV,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,KAAK,EAAE,GAAG,CAAC,KAAK;SACjB,CAAC,CAAC;QAEH,KAAK,CAAC,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IACpC,CAAC;IAED,MAAM,KAAK,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAEpC,OAAO;QACL,iBAAiB,EAAE,KAAK,CAAC,MAAM;QAC/B,mBAAmB,EAAE,IAAI,CAAC,MAAM;QAChC,KAAK;KACN,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type Database from "better-sqlite3";
|
|
2
|
+
export interface CalleeResult {
|
|
3
|
+
calleeId: string;
|
|
4
|
+
calleeName: string;
|
|
5
|
+
filePath: string;
|
|
6
|
+
line: number;
|
|
7
|
+
depth: number;
|
|
8
|
+
}
|
|
9
|
+
export declare function findCallees(db: Database.Database, symbolName: string, options?: {
|
|
10
|
+
depth?: number;
|
|
11
|
+
maxResults?: number;
|
|
12
|
+
}): CalleeResult[];
|