mcp-codebase-intelligence 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.
Files changed (84) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +166 -0
  3. package/dist/graph/code-graph.d.ts +119 -0
  4. package/dist/graph/code-graph.js +279 -0
  5. package/dist/graph/code-graph.js.map +1 -0
  6. package/dist/graph/schema.d.ts +2 -0
  7. package/dist/graph/schema.js +62 -0
  8. package/dist/graph/schema.js.map +1 -0
  9. package/dist/index.d.ts +5 -0
  10. package/dist/index.js +171 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/indexer/file-watcher.d.ts +13 -0
  13. package/dist/indexer/file-watcher.js +106 -0
  14. package/dist/indexer/file-watcher.js.map +1 -0
  15. package/dist/indexer/lang-go.d.ts +2 -0
  16. package/dist/indexer/lang-go.js +246 -0
  17. package/dist/indexer/lang-go.js.map +1 -0
  18. package/dist/indexer/lang-java.d.ts +2 -0
  19. package/dist/indexer/lang-java.js +307 -0
  20. package/dist/indexer/lang-java.js.map +1 -0
  21. package/dist/indexer/lang-python.d.ts +2 -0
  22. package/dist/indexer/lang-python.js +232 -0
  23. package/dist/indexer/lang-python.js.map +1 -0
  24. package/dist/indexer/lang-rust.d.ts +2 -0
  25. package/dist/indexer/lang-rust.js +323 -0
  26. package/dist/indexer/lang-rust.js.map +1 -0
  27. package/dist/indexer/language-plugin.d.ts +22 -0
  28. package/dist/indexer/language-plugin.js +22 -0
  29. package/dist/indexer/language-plugin.js.map +1 -0
  30. package/dist/indexer/tree-sitter-indexer.d.ts +12 -0
  31. package/dist/indexer/tree-sitter-indexer.js +618 -0
  32. package/dist/indexer/tree-sitter-indexer.js.map +1 -0
  33. package/dist/lsp/lsp-client.d.ts +45 -0
  34. package/dist/lsp/lsp-client.js +315 -0
  35. package/dist/lsp/lsp-client.js.map +1 -0
  36. package/dist/lsp/lsp-manager.d.ts +13 -0
  37. package/dist/lsp/lsp-manager.js +96 -0
  38. package/dist/lsp/lsp-manager.js.map +1 -0
  39. package/dist/tools/analyze-impact.d.ts +38 -0
  40. package/dist/tools/analyze-impact.js +126 -0
  41. package/dist/tools/analyze-impact.js.map +1 -0
  42. package/dist/tools/architecture-diagram.d.ts +33 -0
  43. package/dist/tools/architecture-diagram.js +216 -0
  44. package/dist/tools/architecture-diagram.js.map +1 -0
  45. package/dist/tools/find-implementations.d.ts +33 -0
  46. package/dist/tools/find-implementations.js +68 -0
  47. package/dist/tools/find-implementations.js.map +1 -0
  48. package/dist/tools/find-symbol.d.ts +39 -0
  49. package/dist/tools/find-symbol.js +52 -0
  50. package/dist/tools/find-symbol.js.map +1 -0
  51. package/dist/tools/get-call-graph.d.ts +40 -0
  52. package/dist/tools/get-call-graph.js +174 -0
  53. package/dist/tools/get-call-graph.js.map +1 -0
  54. package/dist/tools/get-dependencies.d.ts +28 -0
  55. package/dist/tools/get-dependencies.js +68 -0
  56. package/dist/tools/get-dependencies.js.map +1 -0
  57. package/dist/tools/get-exports.d.ts +23 -0
  58. package/dist/tools/get-exports.js +40 -0
  59. package/dist/tools/get-exports.js.map +1 -0
  60. package/dist/tools/get-references.d.ts +28 -0
  61. package/dist/tools/get-references.js +53 -0
  62. package/dist/tools/get-references.js.map +1 -0
  63. package/dist/tools/get-stats.d.ts +15 -0
  64. package/dist/tools/get-stats.js +23 -0
  65. package/dist/tools/get-stats.js.map +1 -0
  66. package/dist/tools/get-type-info.d.ts +33 -0
  67. package/dist/tools/get-type-info.js +69 -0
  68. package/dist/tools/get-type-info.js.map +1 -0
  69. package/dist/tools/goto-definition.d.ts +33 -0
  70. package/dist/tools/goto-definition.js +77 -0
  71. package/dist/tools/goto-definition.js.map +1 -0
  72. package/dist/tools/natural-language-query.d.ts +23 -0
  73. package/dist/tools/natural-language-query.js +426 -0
  74. package/dist/tools/natural-language-query.js.map +1 -0
  75. package/dist/tools/reindex.d.ts +15 -0
  76. package/dist/tools/reindex.js +20 -0
  77. package/dist/tools/reindex.js.map +1 -0
  78. package/dist/tools/semantic-diff.d.ts +32 -0
  79. package/dist/tools/semantic-diff.js +407 -0
  80. package/dist/tools/semantic-diff.js.map +1 -0
  81. package/dist/utils/logger.d.ts +6 -0
  82. package/dist/utils/logger.js +15 -0
  83. package/dist/utils/logger.js.map +1 -0
  84. package/package.json +68 -0
@@ -0,0 +1,45 @@
1
+ export declare class LspClient {
2
+ private rootPath;
3
+ private serverCommand;
4
+ private serverArgs;
5
+ private process;
6
+ private nextId;
7
+ private pending;
8
+ private buffer;
9
+ private contentLength;
10
+ private ready;
11
+ private initPromise;
12
+ private openedFiles;
13
+ constructor(rootPath: string, serverCommand: string, serverArgs: string[]);
14
+ start(): Promise<void>;
15
+ private _start;
16
+ stop(): Promise<void>;
17
+ isReady(): boolean;
18
+ private ensureFileOpen;
19
+ getDefinition(filePath: string, line: number, character: number): Promise<Array<{
20
+ uri: string;
21
+ line: number;
22
+ character: number;
23
+ }>>;
24
+ getReferences(filePath: string, line: number, character: number, includeDeclaration?: boolean): Promise<Array<{
25
+ uri: string;
26
+ line: number;
27
+ character: number;
28
+ }>>;
29
+ getHover(filePath: string, line: number, character: number): Promise<string | null>;
30
+ getTypeDefinition(filePath: string, line: number, character: number): Promise<Array<{
31
+ uri: string;
32
+ line: number;
33
+ character: number;
34
+ }>>;
35
+ getImplementations(filePath: string, line: number, character: number): Promise<Array<{
36
+ uri: string;
37
+ line: number;
38
+ character: number;
39
+ }>>;
40
+ private normalizeLocations;
41
+ private sendRequest;
42
+ private sendNotification;
43
+ private writeMessage;
44
+ private handleData;
45
+ }
@@ -0,0 +1,315 @@
1
+ import { spawn } from "child_process";
2
+ import { readFileSync } from "fs";
3
+ import { logger } from "../utils/logger.js";
4
+ export class LspClient {
5
+ rootPath;
6
+ serverCommand;
7
+ serverArgs;
8
+ process = null;
9
+ nextId = 1;
10
+ pending = new Map();
11
+ buffer = "";
12
+ contentLength = -1;
13
+ ready = false;
14
+ initPromise = null;
15
+ openedFiles = new Set();
16
+ constructor(rootPath, serverCommand, serverArgs) {
17
+ this.rootPath = rootPath;
18
+ this.serverCommand = serverCommand;
19
+ this.serverArgs = serverArgs;
20
+ }
21
+ async start() {
22
+ if (this.initPromise)
23
+ return this.initPromise;
24
+ this.initPromise = this._start();
25
+ return this.initPromise;
26
+ }
27
+ async _start() {
28
+ logger.info(`Starting LSP server: ${this.serverCommand} ${this.serverArgs.join(" ")}`);
29
+ this.process = spawn(this.serverCommand, this.serverArgs, {
30
+ stdio: ["pipe", "pipe", "pipe"],
31
+ cwd: this.rootPath,
32
+ });
33
+ this.process.stdout.on("data", (data) => this.handleData(data));
34
+ this.process.stderr.on("data", (data) => {
35
+ // tsserver logs to stderr — ignore or log at debug level
36
+ logger.debug(`LSP stderr: ${data.toString().trim()}`);
37
+ });
38
+ this.process.on("exit", (code) => {
39
+ logger.warn(`LSP server exited with code ${code}`);
40
+ this.ready = false;
41
+ this.process = null;
42
+ });
43
+ // Send initialize
44
+ const initParams = {
45
+ processId: process.pid,
46
+ rootUri: `file://${this.rootPath}`,
47
+ capabilities: {
48
+ textDocument: {
49
+ definition: { dynamicRegistration: false },
50
+ references: { dynamicRegistration: false },
51
+ hover: { contentFormat: ["plaintext", "markdown"] },
52
+ typeDefinition: { dynamicRegistration: false },
53
+ implementation: { dynamicRegistration: false },
54
+ },
55
+ },
56
+ workspaceFolders: [
57
+ {
58
+ uri: `file://${this.rootPath}`,
59
+ name: "root",
60
+ },
61
+ ],
62
+ };
63
+ const result = (await this.sendRequest("initialize", initParams));
64
+ logger.info(`LSP initialized: ${result.capabilities ? "OK" : "no capabilities"}`);
65
+ // Send initialized notification
66
+ this.sendNotification("initialized", {});
67
+ this.ready = true;
68
+ }
69
+ async stop() {
70
+ if (this.process) {
71
+ try {
72
+ await this.sendRequest("shutdown", null);
73
+ this.sendNotification("exit", null);
74
+ }
75
+ catch {
76
+ // ignore errors during shutdown
77
+ }
78
+ this.process.kill();
79
+ this.process = null;
80
+ this.ready = false;
81
+ }
82
+ }
83
+ isReady() {
84
+ return this.ready;
85
+ }
86
+ async ensureFileOpen(filePath) {
87
+ if (this.openedFiles.has(filePath))
88
+ return;
89
+ try {
90
+ const content = readFileSync(filePath, "utf-8");
91
+ const uri = `file://${filePath}`;
92
+ // Determine language ID
93
+ let languageId = "typescript";
94
+ if (filePath.endsWith(".js") || filePath.endsWith(".mjs") || filePath.endsWith(".cjs")) {
95
+ languageId = "javascript";
96
+ }
97
+ else if (filePath.endsWith(".tsx")) {
98
+ languageId = "typescriptreact";
99
+ }
100
+ else if (filePath.endsWith(".jsx")) {
101
+ languageId = "javascriptreact";
102
+ }
103
+ const params = {
104
+ textDocument: {
105
+ uri,
106
+ languageId,
107
+ version: 1,
108
+ text: content,
109
+ },
110
+ };
111
+ this.sendNotification("textDocument/didOpen", params);
112
+ this.openedFiles.add(filePath);
113
+ }
114
+ catch (err) {
115
+ logger.debug(`Failed to open file in LSP: ${filePath}`, err);
116
+ }
117
+ }
118
+ async getDefinition(filePath, line, character) {
119
+ if (!this.ready)
120
+ return [];
121
+ await this.ensureFileOpen(filePath);
122
+ const params = {
123
+ textDocument: { uri: `file://${filePath}` },
124
+ position: { line: line - 1, character }, // LSP is 0-based
125
+ };
126
+ try {
127
+ const result = await this.sendRequest("textDocument/definition", params);
128
+ return this.normalizeLocations(result);
129
+ }
130
+ catch (err) {
131
+ logger.debug(`Definition request failed for ${filePath}:${line}:${character}`, err);
132
+ return [];
133
+ }
134
+ }
135
+ async getReferences(filePath, line, character, includeDeclaration = false) {
136
+ if (!this.ready)
137
+ return [];
138
+ await this.ensureFileOpen(filePath);
139
+ const params = {
140
+ textDocument: { uri: `file://${filePath}` },
141
+ position: { line: line - 1, character },
142
+ context: { includeDeclaration },
143
+ };
144
+ try {
145
+ const result = await this.sendRequest("textDocument/references", params);
146
+ return this.normalizeLocations(result);
147
+ }
148
+ catch (err) {
149
+ logger.debug(`References request failed for ${filePath}:${line}:${character}`, err);
150
+ return [];
151
+ }
152
+ }
153
+ async getHover(filePath, line, character) {
154
+ if (!this.ready)
155
+ return null;
156
+ await this.ensureFileOpen(filePath);
157
+ const params = {
158
+ textDocument: { uri: `file://${filePath}` },
159
+ position: { line: line - 1, character },
160
+ };
161
+ try {
162
+ const result = (await this.sendRequest("textDocument/hover", params));
163
+ if (!result || !result.contents)
164
+ return null;
165
+ if (typeof result.contents === "string")
166
+ return result.contents;
167
+ if ("value" in result.contents)
168
+ return result.contents.value;
169
+ if (Array.isArray(result.contents)) {
170
+ return result.contents
171
+ .map((c) => (typeof c === "string" ? c : c.value))
172
+ .join("\n");
173
+ }
174
+ return null;
175
+ }
176
+ catch (err) {
177
+ logger.debug(`Hover request failed for ${filePath}:${line}:${character}`, err);
178
+ return null;
179
+ }
180
+ }
181
+ async getTypeDefinition(filePath, line, character) {
182
+ if (!this.ready)
183
+ return [];
184
+ await this.ensureFileOpen(filePath);
185
+ const params = {
186
+ textDocument: { uri: `file://${filePath}` },
187
+ position: { line: line - 1, character },
188
+ };
189
+ try {
190
+ const result = await this.sendRequest("textDocument/typeDefinition", params);
191
+ return this.normalizeLocations(result);
192
+ }
193
+ catch (err) {
194
+ logger.debug(`Type definition request failed for ${filePath}:${line}:${character}`, err);
195
+ return [];
196
+ }
197
+ }
198
+ async getImplementations(filePath, line, character) {
199
+ if (!this.ready)
200
+ return [];
201
+ await this.ensureFileOpen(filePath);
202
+ try {
203
+ const result = await this.sendRequest("textDocument/implementation", {
204
+ textDocument: { uri: `file://${filePath}` },
205
+ position: { line: line - 1, character },
206
+ });
207
+ return this.normalizeLocations(result);
208
+ }
209
+ catch (err) {
210
+ logger.debug(`Implementation request failed for ${filePath}:${line}:${character}`, err);
211
+ return [];
212
+ }
213
+ }
214
+ // --- Protocol internals ---
215
+ normalizeLocations(result) {
216
+ if (!result)
217
+ return [];
218
+ const locations = [];
219
+ if (Array.isArray(result)) {
220
+ for (const item of result) {
221
+ if ("uri" in item && "range" in item) {
222
+ // Location
223
+ locations.push({
224
+ uri: item.uri,
225
+ line: item.range.start.line + 1,
226
+ character: item.range.start.character,
227
+ });
228
+ }
229
+ else if ("targetUri" in item) {
230
+ // LocationLink
231
+ locations.push({
232
+ uri: item.targetUri,
233
+ line: item.targetRange.start.line + 1,
234
+ character: item.targetRange.start.character,
235
+ });
236
+ }
237
+ }
238
+ }
239
+ else if (result && typeof result === "object" && "uri" in result) {
240
+ const loc = result;
241
+ locations.push({
242
+ uri: loc.uri,
243
+ line: loc.range.start.line + 1,
244
+ character: loc.range.start.character,
245
+ });
246
+ }
247
+ return locations;
248
+ }
249
+ sendRequest(method, params) {
250
+ return new Promise((resolve, reject) => {
251
+ const id = this.nextId++;
252
+ this.pending.set(id, { resolve, reject });
253
+ const message = JSON.stringify({ jsonrpc: "2.0", id, method, params });
254
+ this.writeMessage(message);
255
+ // Timeout after 30s
256
+ setTimeout(() => {
257
+ if (this.pending.has(id)) {
258
+ this.pending.delete(id);
259
+ reject(new Error(`LSP request timed out: ${method}`));
260
+ }
261
+ }, 30000);
262
+ });
263
+ }
264
+ sendNotification(method, params) {
265
+ const message = JSON.stringify({ jsonrpc: "2.0", method, params });
266
+ this.writeMessage(message);
267
+ }
268
+ writeMessage(body) {
269
+ if (!this.process?.stdin?.writable)
270
+ return;
271
+ const header = `Content-Length: ${Buffer.byteLength(body)}\r\n\r\n`;
272
+ this.process.stdin.write(header + body);
273
+ }
274
+ handleData(data) {
275
+ this.buffer += data.toString();
276
+ while (true) {
277
+ if (this.contentLength === -1) {
278
+ const headerEnd = this.buffer.indexOf("\r\n\r\n");
279
+ if (headerEnd === -1)
280
+ return;
281
+ const header = this.buffer.substring(0, headerEnd);
282
+ const match = header.match(/Content-Length:\s*(\d+)/i);
283
+ if (!match) {
284
+ this.buffer = this.buffer.substring(headerEnd + 4);
285
+ continue;
286
+ }
287
+ this.contentLength = parseInt(match[1], 10);
288
+ this.buffer = this.buffer.substring(headerEnd + 4);
289
+ }
290
+ if (Buffer.byteLength(this.buffer) < this.contentLength)
291
+ return;
292
+ const body = this.buffer.substring(0, this.contentLength);
293
+ this.buffer = this.buffer.substring(this.contentLength);
294
+ this.contentLength = -1;
295
+ try {
296
+ const msg = JSON.parse(body);
297
+ if ("id" in msg && this.pending.has(msg.id)) {
298
+ const pending = this.pending.get(msg.id);
299
+ this.pending.delete(msg.id);
300
+ if (msg.error) {
301
+ pending.reject(new Error(msg.error.message));
302
+ }
303
+ else {
304
+ pending.resolve(msg.result);
305
+ }
306
+ }
307
+ // Ignore notifications and server-initiated requests
308
+ }
309
+ catch {
310
+ logger.debug("Failed to parse LSP message");
311
+ }
312
+ }
313
+ }
314
+ }
315
+ //# sourceMappingURL=lsp-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lsp-client.js","sourceRoot":"","sources":["../../src/lsp/lsp-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { LspClient } from "./lsp-client.js";
2
+ export declare class LspManager {
3
+ private rootPath;
4
+ private clients;
5
+ private extMap;
6
+ constructor(rootPath: string);
7
+ start(): Promise<void>;
8
+ getClientForFile(filePath: string): LspClient | undefined;
9
+ hasAnyClient(): boolean;
10
+ getActiveServers(): string[];
11
+ stop(): Promise<void>;
12
+ private isCommandAvailable;
13
+ }
@@ -0,0 +1,96 @@
1
+ import { existsSync } from "fs";
2
+ import { execFile } from "child_process";
3
+ import path from "path";
4
+ import { LspClient } from "./lsp-client.js";
5
+ import { logger } from "../utils/logger.js";
6
+ const KNOWN_SERVERS = [
7
+ {
8
+ id: "typescript",
9
+ command: "typescript-language-server",
10
+ args: ["--stdio"],
11
+ extensions: [".ts", ".tsx", ".js", ".jsx", ".mts", ".cts", ".mjs", ".cjs"],
12
+ detect: (root) => existsSync(path.join(root, "tsconfig.json")) ||
13
+ existsSync(path.join(root, "jsconfig.json")) ||
14
+ existsSync(path.join(root, "package.json")),
15
+ },
16
+ ];
17
+ export class LspManager {
18
+ rootPath;
19
+ clients = new Map();
20
+ extMap = new Map(); // extension -> server id
21
+ constructor(rootPath) {
22
+ this.rootPath = rootPath;
23
+ }
24
+ async start() {
25
+ for (const config of KNOWN_SERVERS) {
26
+ if (!config.detect(this.rootPath)) {
27
+ logger.debug(`LSP ${config.id}: skipped (no project markers found)`);
28
+ continue;
29
+ }
30
+ // Check if the server binary is available (direct or via npx)
31
+ let command = config.command;
32
+ let args = config.args;
33
+ const available = await this.isCommandAvailable(config.command);
34
+ if (!available) {
35
+ // Try via npx
36
+ const npxAvailable = await this.isCommandAvailable("npx");
37
+ if (npxAvailable) {
38
+ command = "npx";
39
+ args = [config.command, ...config.args];
40
+ logger.info(`LSP ${config.id}: using npx to run ${config.command}`);
41
+ }
42
+ else {
43
+ logger.info(`LSP ${config.id}: ${config.command} not found, skipping`);
44
+ continue;
45
+ }
46
+ }
47
+ try {
48
+ const client = new LspClient(this.rootPath, command, args);
49
+ await client.start();
50
+ this.clients.set(config.id, client);
51
+ for (const ext of config.extensions) {
52
+ this.extMap.set(ext, config.id);
53
+ }
54
+ logger.info(`LSP ${config.id}: started`);
55
+ }
56
+ catch (err) {
57
+ const msg = err instanceof Error ? err.message : String(err);
58
+ logger.warn(`LSP ${config.id}: failed to start — ${msg}`);
59
+ }
60
+ }
61
+ }
62
+ getClientForFile(filePath) {
63
+ for (const [ext, serverId] of this.extMap) {
64
+ if (filePath.endsWith(ext)) {
65
+ return this.clients.get(serverId);
66
+ }
67
+ }
68
+ return undefined;
69
+ }
70
+ hasAnyClient() {
71
+ return this.clients.size > 0;
72
+ }
73
+ getActiveServers() {
74
+ return Array.from(this.clients.keys());
75
+ }
76
+ async stop() {
77
+ for (const [id, client] of this.clients) {
78
+ try {
79
+ await client.stop();
80
+ logger.info(`LSP ${id}: stopped`);
81
+ }
82
+ catch (err) {
83
+ logger.debug(`LSP ${id}: error during stop`, err);
84
+ }
85
+ }
86
+ this.clients.clear();
87
+ }
88
+ isCommandAvailable(command) {
89
+ return new Promise((resolve) => {
90
+ execFile("which", [command], (err) => {
91
+ resolve(!err);
92
+ });
93
+ });
94
+ }
95
+ }
96
+ //# sourceMappingURL=lsp-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lsp-manager.js","sourceRoot":"","sources":["../../src/lsp/lsp-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import { CodeGraph } from "../graph/code-graph.js";
2
+ export declare const analyzeChangeImpactTool: {
3
+ name: string;
4
+ description: string;
5
+ inputSchema: {
6
+ type: "object";
7
+ properties: {
8
+ file_path: {
9
+ type: string;
10
+ description: string;
11
+ };
12
+ line_start: {
13
+ type: string;
14
+ description: string;
15
+ };
16
+ line_end: {
17
+ type: string;
18
+ description: string;
19
+ };
20
+ depth: {
21
+ type: string;
22
+ description: string;
23
+ };
24
+ };
25
+ required: string[];
26
+ };
27
+ };
28
+ export declare function handleAnalyzeChangeImpact(graph: CodeGraph, args: {
29
+ file_path: string;
30
+ line_start: number;
31
+ line_end: number;
32
+ depth?: number;
33
+ }): {
34
+ content: {
35
+ type: "text";
36
+ text: string;
37
+ }[];
38
+ };
@@ -0,0 +1,126 @@
1
+ export const analyzeChangeImpactTool = {
2
+ name: "analyze_change_impact",
3
+ description: "Analyze the impact of changing lines in a file. Returns all symbols affected by the change and their dependents (callers/users) at configurable depth.",
4
+ inputSchema: {
5
+ type: "object",
6
+ properties: {
7
+ file_path: {
8
+ type: "string",
9
+ description: "Absolute path to the file being modified",
10
+ },
11
+ line_start: {
12
+ type: "number",
13
+ description: "Starting line number of the change (inclusive)",
14
+ },
15
+ line_end: {
16
+ type: "number",
17
+ description: "Ending line number of the change (inclusive)",
18
+ },
19
+ depth: {
20
+ type: "number",
21
+ description: "How many levels of transitive dependents to follow (1 = direct only, default: 2, max: 10)",
22
+ },
23
+ },
24
+ required: ["file_path", "line_start", "line_end"],
25
+ },
26
+ };
27
+ export function handleAnalyzeChangeImpact(graph, args) {
28
+ const depth = args.depth ?? 2;
29
+ const clampedDepth = Math.min(Math.max(depth, 1), 10);
30
+ // Find all symbols in the file that overlap with the line range
31
+ const affectedSymbols = findSymbolsInRange(graph, args.file_path, args.line_start, args.line_end);
32
+ if (affectedSymbols.length === 0) {
33
+ return {
34
+ content: [
35
+ {
36
+ type: "text",
37
+ text: `No symbols found in ${args.file_path} at lines ${args.line_start}-${args.line_end}\n\nThe change may affect code outside of symbol definitions (e.g., module-level code, imports).`,
38
+ },
39
+ ],
40
+ };
41
+ }
42
+ // For each affected symbol, get its references (dependents)
43
+ const impactReport = [];
44
+ for (const sym of affectedSymbols) {
45
+ const refs = graph.getReferences(sym.name, clampedDepth);
46
+ const directRefs = refs.filter((r) => r.depth === 1);
47
+ impactReport.push({
48
+ symbol: sym.name,
49
+ kind: sym.kind,
50
+ lines: `${sym.lineStart}-${sym.lineEnd}`,
51
+ signature: sym.signature,
52
+ directDependents: directRefs.length,
53
+ totalDependents: refs.length,
54
+ references: refs,
55
+ });
56
+ }
57
+ // Build the report
58
+ const sections = [];
59
+ // Summary section
60
+ const totalDirect = impactReport.reduce((sum, r) => sum + r.directDependents, 0);
61
+ const totalAll = impactReport.reduce((sum, r) => sum + r.totalDependents, 0);
62
+ sections.push(`IMPACT ANALYSIS: ${args.file_path} lines ${args.line_start}-${args.line_end}\n` +
63
+ `\nAffected symbols: ${affectedSymbols.length}` +
64
+ `\nDirect dependents: ${totalDirect}` +
65
+ `\nTotal dependents (depth ${clampedDepth}): ${totalAll}`);
66
+ // Affected symbols section
67
+ const affectedList = affectedSymbols.map((s) => {
68
+ const sig = s.signature ? `\n Signature: ${s.signature}` : "";
69
+ return ` ${s.kind} ${s.name} (lines ${s.lineStart}-${s.lineEnd})${sig}`;
70
+ });
71
+ sections.push(`\nAFFECTED SYMBOLS:\n${affectedList.join("\n")}`);
72
+ // Dependents breakdown
73
+ if (totalAll > 0) {
74
+ const dependentSections = [];
75
+ for (const impact of impactReport) {
76
+ if (impact.references.length === 0) {
77
+ continue;
78
+ }
79
+ const header = `\n${impact.kind} ${impact.symbol}:`;
80
+ const byDepth = new Map();
81
+ for (const ref of impact.references) {
82
+ const list = byDepth.get(ref.depth) ?? [];
83
+ list.push(ref);
84
+ byDepth.set(ref.depth, list);
85
+ }
86
+ const depthSections = [];
87
+ for (const [d, depthRefs] of byDepth) {
88
+ const label = d === 1 ? " Direct callers/users" : ` Depth ${d} (transitive)`;
89
+ const lines = depthRefs.map((r) => ` ${r.fromKind} ${r.fromSymbol} (${r.fromFile}:${r.fromLine}) --[${r.refKind}]--> line ${r.refLine}`);
90
+ depthSections.push(`${label}:\n${lines.join("\n")}`);
91
+ }
92
+ dependentSections.push(header + "\n" + depthSections.join("\n"));
93
+ }
94
+ sections.push(`\nDEPENDENTS:${dependentSections.join("\n")}`);
95
+ }
96
+ else {
97
+ sections.push(`\nDEPENDENTS:\nNo references found. The affected symbols are not used elsewhere in the indexed codebase.`);
98
+ }
99
+ return {
100
+ content: [
101
+ {
102
+ type: "text",
103
+ text: sections.join("\n"),
104
+ },
105
+ ],
106
+ };
107
+ }
108
+ // Helper function to find symbols that overlap with a line range
109
+ function findSymbolsInRange(graph, filePath, lineStart, lineEnd) {
110
+ // Query the database directly for symbols in the file that overlap with the range
111
+ const fileId = graph.getFileId(filePath);
112
+ if (!fileId) {
113
+ return [];
114
+ }
115
+ const sql = `
116
+ SELECT s.name, s.kind, s.line_start as lineStart, s.line_end as lineEnd, s.signature
117
+ FROM symbols s
118
+ WHERE s.file_id = ?
119
+ AND s.line_start <= ?
120
+ AND s.line_end >= ?
121
+ ORDER BY s.line_start
122
+ `;
123
+ const db = graph.getDb();
124
+ return db.prepare(sql).all(fileId, lineEnd, lineStart);
125
+ }
126
+ //# sourceMappingURL=analyze-impact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze-impact.js","sourceRoot":"","sources":["../../src/tools/analyze-impact.ts"],"names":[],"mappings":"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"}