@compilr-dev/agents-coding-python 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/LICENSE +21 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/parser/index.d.ts +6 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/index.js +5 -0
- package/dist/parser/node-types.d.ts +119 -0
- package/dist/parser/node-types.d.ts.map +1 -0
- package/dist/parser/node-types.js +4 -0
- package/dist/parser/python-parser.d.ts +85 -0
- package/dist/parser/python-parser.d.ts.map +1 -0
- package/dist/parser/python-parser.js +477 -0
- package/dist/skills/index.d.ts +26 -0
- package/dist/skills/index.d.ts.map +1 -0
- package/dist/skills/index.js +36 -0
- package/dist/skills/python-best-practices.d.ts +7 -0
- package/dist/skills/python-best-practices.d.ts.map +1 -0
- package/dist/skills/python-best-practices.js +78 -0
- package/dist/skills/python-code-health.d.ts +7 -0
- package/dist/skills/python-code-health.d.ts.map +1 -0
- package/dist/skills/python-code-health.js +209 -0
- package/dist/skills/python-code-structure.d.ts +7 -0
- package/dist/skills/python-code-structure.d.ts.map +1 -0
- package/dist/skills/python-code-structure.js +155 -0
- package/dist/skills/python-dependency-audit.d.ts +7 -0
- package/dist/skills/python-dependency-audit.d.ts.map +1 -0
- package/dist/skills/python-dependency-audit.js +246 -0
- package/dist/skills/python-refactor-impact.d.ts +7 -0
- package/dist/skills/python-refactor-impact.d.ts.map +1 -0
- package/dist/skills/python-refactor-impact.js +232 -0
- package/dist/tools/extract-docstrings.d.ts +70 -0
- package/dist/tools/extract-docstrings.d.ts.map +1 -0
- package/dist/tools/extract-docstrings.js +575 -0
- package/dist/tools/find-dead-code.d.ts +62 -0
- package/dist/tools/find-dead-code.d.ts.map +1 -0
- package/dist/tools/find-dead-code.js +422 -0
- package/dist/tools/find-duplicates.d.ts +65 -0
- package/dist/tools/find-duplicates.d.ts.map +1 -0
- package/dist/tools/find-duplicates.js +289 -0
- package/dist/tools/find-implementations.d.ts +71 -0
- package/dist/tools/find-implementations.d.ts.map +1 -0
- package/dist/tools/find-implementations.js +342 -0
- package/dist/tools/find-patterns.d.ts +71 -0
- package/dist/tools/find-patterns.d.ts.map +1 -0
- package/dist/tools/find-patterns.js +477 -0
- package/dist/tools/find-references.d.ts +66 -0
- package/dist/tools/find-references.d.ts.map +1 -0
- package/dist/tools/find-references.js +306 -0
- package/dist/tools/find-symbol.d.ts +86 -0
- package/dist/tools/find-symbol.d.ts.map +1 -0
- package/dist/tools/find-symbol.js +414 -0
- package/dist/tools/get-call-graph.d.ts +89 -0
- package/dist/tools/get-call-graph.d.ts.map +1 -0
- package/dist/tools/get-call-graph.js +431 -0
- package/dist/tools/get-class-hierarchy.d.ts +38 -0
- package/dist/tools/get-class-hierarchy.d.ts.map +1 -0
- package/dist/tools/get-class-hierarchy.js +289 -0
- package/dist/tools/get-complexity.d.ts +61 -0
- package/dist/tools/get-complexity.d.ts.map +1 -0
- package/dist/tools/get-complexity.js +384 -0
- package/dist/tools/get-dependency-graph.d.ts +85 -0
- package/dist/tools/get-dependency-graph.d.ts.map +1 -0
- package/dist/tools/get-dependency-graph.js +387 -0
- package/dist/tools/get-exports.d.ts +78 -0
- package/dist/tools/get-exports.d.ts.map +1 -0
- package/dist/tools/get-exports.js +437 -0
- package/dist/tools/get-file-structure.d.ts +28 -0
- package/dist/tools/get-file-structure.d.ts.map +1 -0
- package/dist/tools/get-file-structure.js +186 -0
- package/dist/tools/get-imports.d.ts +34 -0
- package/dist/tools/get-imports.d.ts.map +1 -0
- package/dist/tools/get-imports.js +455 -0
- package/dist/tools/get-signature.d.ts +100 -0
- package/dist/tools/get-signature.d.ts.map +1 -0
- package/dist/tools/get-signature.js +800 -0
- package/dist/tools/index.d.ts +55 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +75 -0
- package/dist/tools/types.d.ts +378 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +4 -0
- package/package.json +85 -0
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* findSymbol Tool
|
|
3
|
+
*
|
|
4
|
+
* Find the definition location of a symbol across Python codebases.
|
|
5
|
+
* Uses Tree-sitter for AST analysis.
|
|
6
|
+
*/
|
|
7
|
+
import * as fs from "node:fs/promises";
|
|
8
|
+
import * as path from "node:path";
|
|
9
|
+
import { defineTool, createSuccessResult, createErrorResult, } from "@compilr-dev/agents";
|
|
10
|
+
import { parseFile, parseClass, parseFunction, parseVariable, parseDecorators, } from "../parser/python-parser.js";
|
|
11
|
+
// Supported file extensions for searching
|
|
12
|
+
const SUPPORTED_EXTENSIONS = new Set([".py", ".pyi"]);
|
|
13
|
+
// Tool description
|
|
14
|
+
const TOOL_DESCRIPTION = `Find the definition location of a symbol by name across Python codebases.
|
|
15
|
+
Returns structured JSON with file path, line number, symbol kind, and other metadata.
|
|
16
|
+
Use this to locate where functions, classes, variables, etc. are defined.`;
|
|
17
|
+
// Tool input schema
|
|
18
|
+
const TOOL_INPUT_SCHEMA = {
|
|
19
|
+
type: "object",
|
|
20
|
+
properties: {
|
|
21
|
+
symbol: {
|
|
22
|
+
type: "string",
|
|
23
|
+
description: "Symbol name to find",
|
|
24
|
+
},
|
|
25
|
+
scope: {
|
|
26
|
+
type: "string",
|
|
27
|
+
description: "Scope the search to a specific file or directory",
|
|
28
|
+
},
|
|
29
|
+
kind: {
|
|
30
|
+
type: "string",
|
|
31
|
+
enum: ["function", "class", "method", "variable", "constant", "any"],
|
|
32
|
+
description: "Filter by symbol kind (default: any)",
|
|
33
|
+
default: "any",
|
|
34
|
+
},
|
|
35
|
+
limit: {
|
|
36
|
+
type: "number",
|
|
37
|
+
description: "Maximum results to return (default: 10)",
|
|
38
|
+
default: 10,
|
|
39
|
+
},
|
|
40
|
+
includeVenv: {
|
|
41
|
+
type: "boolean",
|
|
42
|
+
description: "Include symbols from virtual environments/site-packages (default: false)",
|
|
43
|
+
default: false,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
required: ["symbol"],
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* findSymbol tool - Find symbol definitions in Python
|
|
50
|
+
*/
|
|
51
|
+
export const findSymbolTool = defineTool({
|
|
52
|
+
name: "find_symbol_python",
|
|
53
|
+
description: TOOL_DESCRIPTION,
|
|
54
|
+
inputSchema: TOOL_INPUT_SCHEMA,
|
|
55
|
+
execute: executeFindSymbol,
|
|
56
|
+
});
|
|
57
|
+
/**
|
|
58
|
+
* Execute the findSymbol tool
|
|
59
|
+
*/
|
|
60
|
+
async function executeFindSymbol(input) {
|
|
61
|
+
const { symbol, scope, kind = "any", limit = 10, includeVenv = false, } = input;
|
|
62
|
+
// Validate input
|
|
63
|
+
if (!symbol || symbol.trim().length === 0) {
|
|
64
|
+
return createErrorResult("Symbol name is required");
|
|
65
|
+
}
|
|
66
|
+
const startTime = Date.now();
|
|
67
|
+
const definitions = [];
|
|
68
|
+
let filesSearched = 0;
|
|
69
|
+
try {
|
|
70
|
+
// Determine search path
|
|
71
|
+
const searchPath = scope || process.cwd();
|
|
72
|
+
// Check if path exists
|
|
73
|
+
try {
|
|
74
|
+
await fs.access(searchPath);
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return createErrorResult(`Path not found: ${searchPath}`);
|
|
78
|
+
}
|
|
79
|
+
const stats = await fs.stat(searchPath);
|
|
80
|
+
if (stats.isFile()) {
|
|
81
|
+
// Search single file
|
|
82
|
+
if (isPythonFile(searchPath)) {
|
|
83
|
+
filesSearched = 1;
|
|
84
|
+
const fileDefinitions = await searchFileForSymbol(searchPath, symbol, kind);
|
|
85
|
+
definitions.push(...fileDefinitions);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
else if (stats.isDirectory()) {
|
|
89
|
+
// Search directory recursively
|
|
90
|
+
const files = await collectFiles(searchPath, includeVenv);
|
|
91
|
+
filesSearched = files.length;
|
|
92
|
+
for (const filePath of files) {
|
|
93
|
+
if (definitions.length >= limit)
|
|
94
|
+
break;
|
|
95
|
+
const fileDefinitions = await searchFileForSymbol(filePath, symbol, kind);
|
|
96
|
+
const remaining = limit - definitions.length;
|
|
97
|
+
definitions.push(...fileDefinitions.slice(0, remaining));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
return createErrorResult(`Path is neither a file nor directory: ${searchPath}`);
|
|
102
|
+
}
|
|
103
|
+
const endTime = Date.now();
|
|
104
|
+
const result = {
|
|
105
|
+
query: symbol,
|
|
106
|
+
definitions: definitions.slice(0, limit),
|
|
107
|
+
stats: {
|
|
108
|
+
filesSearched,
|
|
109
|
+
timeMs: endTime - startTime,
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
return createSuccessResult(result);
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
116
|
+
return createErrorResult(`Failed to search for symbol: ${message}`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Check if a file is a Python file
|
|
121
|
+
*/
|
|
122
|
+
function isPythonFile(filePath) {
|
|
123
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
124
|
+
return SUPPORTED_EXTENSIONS.has(ext);
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Collect all Python files in a directory recursively
|
|
128
|
+
*/
|
|
129
|
+
async function collectFiles(dir, includeVenv) {
|
|
130
|
+
const files = [];
|
|
131
|
+
async function walk(currentDir) {
|
|
132
|
+
const entries = await fs.readdir(currentDir, { withFileTypes: true });
|
|
133
|
+
for (const entry of entries) {
|
|
134
|
+
const fullPath = path.join(currentDir, entry.name);
|
|
135
|
+
if (entry.isDirectory()) {
|
|
136
|
+
// Skip virtual environments unless explicitly included
|
|
137
|
+
if (!includeVenv &&
|
|
138
|
+
(entry.name === "venv" ||
|
|
139
|
+
entry.name === ".venv" ||
|
|
140
|
+
entry.name === "env" ||
|
|
141
|
+
entry.name === ".env" ||
|
|
142
|
+
entry.name === "site-packages" ||
|
|
143
|
+
entry.name === "__pycache__")) {
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
// Skip common non-source directories
|
|
147
|
+
if (entry.name.startsWith(".") ||
|
|
148
|
+
entry.name === "dist" ||
|
|
149
|
+
entry.name === "build" ||
|
|
150
|
+
entry.name === "eggs" ||
|
|
151
|
+
entry.name === "*.egg-info") {
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
await walk(fullPath);
|
|
155
|
+
}
|
|
156
|
+
else if (entry.isFile()) {
|
|
157
|
+
if (isPythonFile(fullPath)) {
|
|
158
|
+
files.push(fullPath);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
await walk(dir);
|
|
164
|
+
return files;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Search a single file for symbol definitions
|
|
168
|
+
*/
|
|
169
|
+
async function searchFileForSymbol(filePath, symbolName, kindFilter) {
|
|
170
|
+
const definitions = [];
|
|
171
|
+
try {
|
|
172
|
+
const parseResult = await parseFile(filePath);
|
|
173
|
+
const { tree, source } = parseResult;
|
|
174
|
+
const rootNode = tree.rootNode;
|
|
175
|
+
// Search for symbols in the AST
|
|
176
|
+
for (const child of rootNode.children) {
|
|
177
|
+
// Function definitions
|
|
178
|
+
if (child.type === "function_definition" ||
|
|
179
|
+
child.type === "async_function_definition") {
|
|
180
|
+
const funcInfo = parseFunction(child, source);
|
|
181
|
+
if (funcInfo.name === symbolName) {
|
|
182
|
+
if (kindFilter === "any" || kindFilter === "function") {
|
|
183
|
+
definitions.push({
|
|
184
|
+
name: funcInfo.name,
|
|
185
|
+
path: filePath,
|
|
186
|
+
line: funcInfo.line,
|
|
187
|
+
column: funcInfo.column + 1,
|
|
188
|
+
kind: "function",
|
|
189
|
+
isPublic: !funcInfo.name.startsWith("_"),
|
|
190
|
+
signature: buildFunctionSignature(funcInfo),
|
|
191
|
+
docSummary: funcInfo.docstring?.split("\n")[0],
|
|
192
|
+
confidence: 1.0,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
// Decorated definitions
|
|
198
|
+
if (child.type === "decorated_definition") {
|
|
199
|
+
const decorators = parseDecorators(child, source);
|
|
200
|
+
const funcNode = child.children.find((c) => c.type === "function_definition" ||
|
|
201
|
+
c.type === "async_function_definition");
|
|
202
|
+
const classNode = child.children.find((c) => c.type === "class_definition");
|
|
203
|
+
if (funcNode) {
|
|
204
|
+
const funcInfo = parseFunction(funcNode, source, decorators);
|
|
205
|
+
if (funcInfo.name === symbolName) {
|
|
206
|
+
if (kindFilter === "any" || kindFilter === "function") {
|
|
207
|
+
definitions.push({
|
|
208
|
+
name: funcInfo.name,
|
|
209
|
+
path: filePath,
|
|
210
|
+
line: funcInfo.line,
|
|
211
|
+
column: funcInfo.column + 1,
|
|
212
|
+
kind: "function",
|
|
213
|
+
isPublic: !funcInfo.name.startsWith("_"),
|
|
214
|
+
signature: buildFunctionSignature(funcInfo),
|
|
215
|
+
docSummary: funcInfo.docstring?.split("\n")[0],
|
|
216
|
+
confidence: 1.0,
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
if (classNode) {
|
|
222
|
+
const classInfo = parseClass(classNode, source, decorators);
|
|
223
|
+
if (classInfo.name === symbolName) {
|
|
224
|
+
if (kindFilter === "any" || kindFilter === "class") {
|
|
225
|
+
definitions.push({
|
|
226
|
+
name: classInfo.name,
|
|
227
|
+
path: filePath,
|
|
228
|
+
line: classInfo.line,
|
|
229
|
+
column: classInfo.column + 1,
|
|
230
|
+
kind: "class",
|
|
231
|
+
isPublic: !classInfo.name.startsWith("_"),
|
|
232
|
+
signature: buildClassSignature(classInfo),
|
|
233
|
+
docSummary: classInfo.docstring?.split("\n")[0],
|
|
234
|
+
confidence: 1.0,
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
// Search methods inside the class
|
|
239
|
+
if (kindFilter === "any" || kindFilter === "method") {
|
|
240
|
+
for (const method of classInfo.methods) {
|
|
241
|
+
if (method.name === symbolName) {
|
|
242
|
+
definitions.push({
|
|
243
|
+
name: method.name,
|
|
244
|
+
path: filePath,
|
|
245
|
+
line: method.line,
|
|
246
|
+
column: method.column + 1,
|
|
247
|
+
kind: "method",
|
|
248
|
+
container: classInfo.name,
|
|
249
|
+
isPublic: !method.name.startsWith("_"),
|
|
250
|
+
signature: buildMethodSignature(method, classInfo.name),
|
|
251
|
+
docSummary: method.docstring?.split("\n")[0],
|
|
252
|
+
confidence: 1.0,
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
// Class definitions (non-decorated)
|
|
260
|
+
if (child.type === "class_definition") {
|
|
261
|
+
const classInfo = parseClass(child, source);
|
|
262
|
+
if (classInfo.name === symbolName) {
|
|
263
|
+
if (kindFilter === "any" || kindFilter === "class") {
|
|
264
|
+
definitions.push({
|
|
265
|
+
name: classInfo.name,
|
|
266
|
+
path: filePath,
|
|
267
|
+
line: classInfo.line,
|
|
268
|
+
column: classInfo.column + 1,
|
|
269
|
+
kind: "class",
|
|
270
|
+
isPublic: !classInfo.name.startsWith("_"),
|
|
271
|
+
signature: buildClassSignature(classInfo),
|
|
272
|
+
docSummary: classInfo.docstring?.split("\n")[0],
|
|
273
|
+
confidence: 1.0,
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
// Search methods inside the class
|
|
278
|
+
if (kindFilter === "any" || kindFilter === "method") {
|
|
279
|
+
for (const method of classInfo.methods) {
|
|
280
|
+
if (method.name === symbolName) {
|
|
281
|
+
definitions.push({
|
|
282
|
+
name: method.name,
|
|
283
|
+
path: filePath,
|
|
284
|
+
line: method.line,
|
|
285
|
+
column: method.column + 1,
|
|
286
|
+
kind: "method",
|
|
287
|
+
container: classInfo.name,
|
|
288
|
+
isPublic: !method.name.startsWith("_"),
|
|
289
|
+
signature: buildMethodSignature(method, classInfo.name),
|
|
290
|
+
docSummary: method.docstring?.split("\n")[0],
|
|
291
|
+
confidence: 1.0,
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
// Variable assignments at module level
|
|
298
|
+
if (child.type === "expression_statement") {
|
|
299
|
+
const expr = child.firstChild;
|
|
300
|
+
if (expr &&
|
|
301
|
+
(expr.type === "assignment" || expr.type === "annotated_assignment")) {
|
|
302
|
+
const varInfo = parseVariable(expr, source);
|
|
303
|
+
if (varInfo && varInfo.name === symbolName) {
|
|
304
|
+
const varKind = varInfo.isConstant
|
|
305
|
+
? "constant"
|
|
306
|
+
: "variable";
|
|
307
|
+
if (kindFilter === "any" ||
|
|
308
|
+
kindFilter === varKind ||
|
|
309
|
+
(kindFilter === "variable" && varKind === "constant")) {
|
|
310
|
+
definitions.push({
|
|
311
|
+
name: varInfo.name,
|
|
312
|
+
path: filePath,
|
|
313
|
+
line: varInfo.line,
|
|
314
|
+
column: varInfo.column + 1,
|
|
315
|
+
kind: varKind,
|
|
316
|
+
isPublic: !varInfo.name.startsWith("_"),
|
|
317
|
+
signature: buildVariableSignature(varInfo),
|
|
318
|
+
confidence: 1.0,
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
catch {
|
|
327
|
+
// Silently skip files that can't be parsed
|
|
328
|
+
}
|
|
329
|
+
return definitions;
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Build a function signature string
|
|
333
|
+
*/
|
|
334
|
+
function buildFunctionSignature(func) {
|
|
335
|
+
const asyncPrefix = func.isAsync ? "async " : "";
|
|
336
|
+
const params = func.parameters
|
|
337
|
+
.map((p) => {
|
|
338
|
+
let param = p.name;
|
|
339
|
+
if (p.type)
|
|
340
|
+
param += `: ${p.type}`;
|
|
341
|
+
if (p.default)
|
|
342
|
+
param += ` = ${p.default}`;
|
|
343
|
+
return param;
|
|
344
|
+
})
|
|
345
|
+
.join(", ");
|
|
346
|
+
const returnType = func.returnType ? ` -> ${func.returnType}` : "";
|
|
347
|
+
return `${asyncPrefix}def ${func.name}(${params})${returnType}`;
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Build a method signature string
|
|
351
|
+
*/
|
|
352
|
+
function buildMethodSignature(method, className) {
|
|
353
|
+
const prefix = method.isStaticMethod
|
|
354
|
+
? "@staticmethod "
|
|
355
|
+
: method.isClassMethod
|
|
356
|
+
? "@classmethod "
|
|
357
|
+
: method.isProperty
|
|
358
|
+
? "@property "
|
|
359
|
+
: "";
|
|
360
|
+
const asyncPrefix = method.isAsync ? "async " : "";
|
|
361
|
+
const params = method.parameters
|
|
362
|
+
.map((p) => {
|
|
363
|
+
let param = p.name;
|
|
364
|
+
if (p.type)
|
|
365
|
+
param += `: ${p.type}`;
|
|
366
|
+
if (p.default)
|
|
367
|
+
param += ` = ${p.default}`;
|
|
368
|
+
return param;
|
|
369
|
+
})
|
|
370
|
+
.join(", ");
|
|
371
|
+
const returnType = method.returnType ? ` -> ${method.returnType}` : "";
|
|
372
|
+
return `${prefix}${asyncPrefix}def ${className}.${method.name}(${params})${returnType}`;
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Build a class signature string
|
|
376
|
+
*/
|
|
377
|
+
function buildClassSignature(classInfo) {
|
|
378
|
+
const dataclassPrefix = classInfo.isDataclass ? "@dataclass " : "";
|
|
379
|
+
const bases = classInfo.bases.length > 0 ? `(${classInfo.bases.join(", ")})` : "";
|
|
380
|
+
return `${dataclassPrefix}class ${classInfo.name}${bases}`;
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Build a variable signature string
|
|
384
|
+
*/
|
|
385
|
+
function buildVariableSignature(varInfo) {
|
|
386
|
+
let sig = varInfo.name;
|
|
387
|
+
if (varInfo.type)
|
|
388
|
+
sig += `: ${varInfo.type}`;
|
|
389
|
+
if (varInfo.value) {
|
|
390
|
+
const valuePreview = varInfo.value.length > 50
|
|
391
|
+
? varInfo.value.substring(0, 47) + "..."
|
|
392
|
+
: varInfo.value;
|
|
393
|
+
sig += ` = ${valuePreview}`;
|
|
394
|
+
}
|
|
395
|
+
return sig;
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* Factory function to create a customized findSymbol tool
|
|
399
|
+
*/
|
|
400
|
+
export function createFindSymbolTool(options) {
|
|
401
|
+
const { defaultLimit = 10, defaultIncludeVenv = false } = options ?? {};
|
|
402
|
+
return defineTool({
|
|
403
|
+
name: "find_symbol_python",
|
|
404
|
+
description: TOOL_DESCRIPTION,
|
|
405
|
+
inputSchema: TOOL_INPUT_SCHEMA,
|
|
406
|
+
execute: async (input) => {
|
|
407
|
+
return executeFindSymbol({
|
|
408
|
+
...input,
|
|
409
|
+
limit: input.limit ?? defaultLimit,
|
|
410
|
+
includeVenv: input.includeVenv ?? defaultIncludeVenv,
|
|
411
|
+
});
|
|
412
|
+
},
|
|
413
|
+
});
|
|
414
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* getCallGraph Tool
|
|
3
|
+
*
|
|
4
|
+
* Analyze function call relationships in Python code.
|
|
5
|
+
* Returns a call graph showing what functions call what.
|
|
6
|
+
*/
|
|
7
|
+
import type { Tool } from "@compilr-dev/agents";
|
|
8
|
+
/**
|
|
9
|
+
* Direction for call graph traversal
|
|
10
|
+
*/
|
|
11
|
+
export type CallGraphDirection = "callers" | "callees" | "both";
|
|
12
|
+
/**
|
|
13
|
+
* Call type
|
|
14
|
+
*/
|
|
15
|
+
export type CallType = "direct" | "method" | "constructor" | "decorator";
|
|
16
|
+
/**
|
|
17
|
+
* Function node in the call graph
|
|
18
|
+
*/
|
|
19
|
+
export interface FunctionNode {
|
|
20
|
+
name: string;
|
|
21
|
+
path: string;
|
|
22
|
+
line: number;
|
|
23
|
+
column?: number;
|
|
24
|
+
className?: string;
|
|
25
|
+
async?: boolean;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Call info
|
|
29
|
+
*/
|
|
30
|
+
export interface CallInfo {
|
|
31
|
+
function: FunctionNode;
|
|
32
|
+
callLine: number;
|
|
33
|
+
callColumn?: number;
|
|
34
|
+
type: CallType;
|
|
35
|
+
count: number;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Call graph node
|
|
39
|
+
*/
|
|
40
|
+
export interface CallGraphNode {
|
|
41
|
+
function: FunctionNode;
|
|
42
|
+
calls: CallInfo[];
|
|
43
|
+
calledBy: CallInfo[];
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Call graph stats
|
|
47
|
+
*/
|
|
48
|
+
export interface CallGraphStats {
|
|
49
|
+
totalFunctions: number;
|
|
50
|
+
totalCalls: number;
|
|
51
|
+
maxDepthReached: number;
|
|
52
|
+
externalCalls?: number;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Input for getCallGraph tool
|
|
56
|
+
*/
|
|
57
|
+
export interface GetCallGraphInput {
|
|
58
|
+
/** File to analyze */
|
|
59
|
+
path: string;
|
|
60
|
+
/** Specific function to analyze (optional) */
|
|
61
|
+
functionName?: string;
|
|
62
|
+
/** Direction: 'callers' | 'callees' | 'both' (default: 'both') */
|
|
63
|
+
direction?: CallGraphDirection;
|
|
64
|
+
/** Maximum depth to traverse (default: 2) */
|
|
65
|
+
maxDepth?: number;
|
|
66
|
+
/** Include external package calls (default: false) */
|
|
67
|
+
includeExternal?: boolean;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Result of getCallGraph
|
|
71
|
+
*/
|
|
72
|
+
export interface GetCallGraphResult {
|
|
73
|
+
root?: FunctionNode;
|
|
74
|
+
graph: CallGraphNode[];
|
|
75
|
+
stats: CallGraphStats;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* getCallGraph tool
|
|
79
|
+
*/
|
|
80
|
+
export declare const getCallGraphTool: Tool<GetCallGraphInput>;
|
|
81
|
+
/**
|
|
82
|
+
* Factory function to create a customized getCallGraph tool
|
|
83
|
+
*/
|
|
84
|
+
export declare function createGetCallGraphTool(options?: {
|
|
85
|
+
defaultDirection?: CallGraphDirection;
|
|
86
|
+
defaultMaxDepth?: number;
|
|
87
|
+
defaultIncludeExternal?: boolean;
|
|
88
|
+
}): Tool<GetCallGraphInput>;
|
|
89
|
+
//# sourceMappingURL=get-call-graph.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-call-graph.d.ts","sourceRoot":"","sources":["../../src/tools/get-call-graph.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,OAAO,KAAK,EAAE,IAAI,EAAuB,MAAM,qBAAqB,CAAC;AAQrE;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,CAAC;AAEhE;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,aAAa,GAAG,WAAW,CAAC;AAEzE;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,YAAY,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,YAAY,CAAC;IACvB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,QAAQ,EAAE,QAAQ,EAAE,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,sBAAsB;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,8CAA8C;IAC9C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kEAAkE;IAClE,SAAS,CAAC,EAAE,kBAAkB,CAAC;IAC/B,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,KAAK,EAAE,cAAc,CAAC;CACvB;AA+CD;;GAEG;AACH,eAAO,MAAM,gBAAgB,yBAK3B,CAAC;AA6dH;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,CAAC,EAAE;IAC/C,gBAAgB,CAAC,EAAE,kBAAkB,CAAC;IACtC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC,GAAG,IAAI,CAAC,iBAAiB,CAAC,CAoB1B"}
|