@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.
Files changed (83) hide show
  1. package/LICENSE +21 -0
  2. package/dist/index.d.ts +40 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +27 -0
  5. package/dist/parser/index.d.ts +6 -0
  6. package/dist/parser/index.d.ts.map +1 -0
  7. package/dist/parser/index.js +5 -0
  8. package/dist/parser/node-types.d.ts +119 -0
  9. package/dist/parser/node-types.d.ts.map +1 -0
  10. package/dist/parser/node-types.js +4 -0
  11. package/dist/parser/python-parser.d.ts +85 -0
  12. package/dist/parser/python-parser.d.ts.map +1 -0
  13. package/dist/parser/python-parser.js +477 -0
  14. package/dist/skills/index.d.ts +26 -0
  15. package/dist/skills/index.d.ts.map +1 -0
  16. package/dist/skills/index.js +36 -0
  17. package/dist/skills/python-best-practices.d.ts +7 -0
  18. package/dist/skills/python-best-practices.d.ts.map +1 -0
  19. package/dist/skills/python-best-practices.js +78 -0
  20. package/dist/skills/python-code-health.d.ts +7 -0
  21. package/dist/skills/python-code-health.d.ts.map +1 -0
  22. package/dist/skills/python-code-health.js +209 -0
  23. package/dist/skills/python-code-structure.d.ts +7 -0
  24. package/dist/skills/python-code-structure.d.ts.map +1 -0
  25. package/dist/skills/python-code-structure.js +155 -0
  26. package/dist/skills/python-dependency-audit.d.ts +7 -0
  27. package/dist/skills/python-dependency-audit.d.ts.map +1 -0
  28. package/dist/skills/python-dependency-audit.js +246 -0
  29. package/dist/skills/python-refactor-impact.d.ts +7 -0
  30. package/dist/skills/python-refactor-impact.d.ts.map +1 -0
  31. package/dist/skills/python-refactor-impact.js +232 -0
  32. package/dist/tools/extract-docstrings.d.ts +70 -0
  33. package/dist/tools/extract-docstrings.d.ts.map +1 -0
  34. package/dist/tools/extract-docstrings.js +575 -0
  35. package/dist/tools/find-dead-code.d.ts +62 -0
  36. package/dist/tools/find-dead-code.d.ts.map +1 -0
  37. package/dist/tools/find-dead-code.js +422 -0
  38. package/dist/tools/find-duplicates.d.ts +65 -0
  39. package/dist/tools/find-duplicates.d.ts.map +1 -0
  40. package/dist/tools/find-duplicates.js +289 -0
  41. package/dist/tools/find-implementations.d.ts +71 -0
  42. package/dist/tools/find-implementations.d.ts.map +1 -0
  43. package/dist/tools/find-implementations.js +342 -0
  44. package/dist/tools/find-patterns.d.ts +71 -0
  45. package/dist/tools/find-patterns.d.ts.map +1 -0
  46. package/dist/tools/find-patterns.js +477 -0
  47. package/dist/tools/find-references.d.ts +66 -0
  48. package/dist/tools/find-references.d.ts.map +1 -0
  49. package/dist/tools/find-references.js +306 -0
  50. package/dist/tools/find-symbol.d.ts +86 -0
  51. package/dist/tools/find-symbol.d.ts.map +1 -0
  52. package/dist/tools/find-symbol.js +414 -0
  53. package/dist/tools/get-call-graph.d.ts +89 -0
  54. package/dist/tools/get-call-graph.d.ts.map +1 -0
  55. package/dist/tools/get-call-graph.js +431 -0
  56. package/dist/tools/get-class-hierarchy.d.ts +38 -0
  57. package/dist/tools/get-class-hierarchy.d.ts.map +1 -0
  58. package/dist/tools/get-class-hierarchy.js +289 -0
  59. package/dist/tools/get-complexity.d.ts +61 -0
  60. package/dist/tools/get-complexity.d.ts.map +1 -0
  61. package/dist/tools/get-complexity.js +384 -0
  62. package/dist/tools/get-dependency-graph.d.ts +85 -0
  63. package/dist/tools/get-dependency-graph.d.ts.map +1 -0
  64. package/dist/tools/get-dependency-graph.js +387 -0
  65. package/dist/tools/get-exports.d.ts +78 -0
  66. package/dist/tools/get-exports.d.ts.map +1 -0
  67. package/dist/tools/get-exports.js +437 -0
  68. package/dist/tools/get-file-structure.d.ts +28 -0
  69. package/dist/tools/get-file-structure.d.ts.map +1 -0
  70. package/dist/tools/get-file-structure.js +186 -0
  71. package/dist/tools/get-imports.d.ts +34 -0
  72. package/dist/tools/get-imports.d.ts.map +1 -0
  73. package/dist/tools/get-imports.js +455 -0
  74. package/dist/tools/get-signature.d.ts +100 -0
  75. package/dist/tools/get-signature.d.ts.map +1 -0
  76. package/dist/tools/get-signature.js +800 -0
  77. package/dist/tools/index.d.ts +55 -0
  78. package/dist/tools/index.d.ts.map +1 -0
  79. package/dist/tools/index.js +75 -0
  80. package/dist/tools/types.d.ts +378 -0
  81. package/dist/tools/types.d.ts.map +1 -0
  82. package/dist/tools/types.js +4 -0
  83. package/package.json +85 -0
@@ -0,0 +1,477 @@
1
+ /**
2
+ * Python Parser using Tree-sitter
3
+ *
4
+ * Provides AST parsing and traversal for Python source files.
5
+ */
6
+ import Parser from "tree-sitter";
7
+ import Python from "tree-sitter-python";
8
+ import { readFile } from "node:fs/promises";
9
+ // Initialize parser
10
+ const parser = new Parser();
11
+ // Cast to any to work around tree-sitter type mismatches between versions
12
+ parser.setLanguage(Python);
13
+ /**
14
+ * Parse Python source code
15
+ */
16
+ export function parseSource(source) {
17
+ const tree = parser.parse(source);
18
+ const errors = [];
19
+ // Find error nodes
20
+ const findErrors = (node) => {
21
+ if (node.type === "ERROR" || node.isMissing) {
22
+ errors.push({
23
+ message: node.isMissing ? `Missing: ${node.type}` : "Syntax error",
24
+ line: node.startPosition.row + 1,
25
+ column: node.startPosition.column,
26
+ });
27
+ }
28
+ for (const child of node.children) {
29
+ findErrors(child);
30
+ }
31
+ };
32
+ findErrors(tree.rootNode);
33
+ return {
34
+ tree,
35
+ source,
36
+ hasErrors: errors.length > 0,
37
+ errors,
38
+ };
39
+ }
40
+ /**
41
+ * Parse Python file
42
+ */
43
+ export async function parseFile(path) {
44
+ const source = await readFile(path, "utf-8");
45
+ return parseSource(source);
46
+ }
47
+ /**
48
+ * Get text from a node
49
+ */
50
+ export function getNodeText(node, source) {
51
+ return source.slice(node.startIndex, node.endIndex);
52
+ }
53
+ /**
54
+ * Extract docstring from a block
55
+ */
56
+ export function extractDocstring(node, source) {
57
+ // Look for the first expression_statement containing a string
58
+ const block = node.childForFieldName("body");
59
+ if (!block)
60
+ return undefined;
61
+ const firstChild = block.firstChild;
62
+ if (!firstChild)
63
+ return undefined;
64
+ if (firstChild.type === "expression_statement") {
65
+ const expr = firstChild.firstChild;
66
+ if (expr && expr.type === "string") {
67
+ const text = getNodeText(expr, source);
68
+ // Remove quotes (single, double, triple)
69
+ return text.replace(/^['"]{1,3}|['"]{1,3}$/g, "").trim();
70
+ }
71
+ }
72
+ return undefined;
73
+ }
74
+ /**
75
+ * Parse decorators from a decorated_definition
76
+ */
77
+ export function parseDecorators(node, source) {
78
+ const decorators = [];
79
+ for (const child of node.children) {
80
+ if (child.type === "decorator") {
81
+ let nameNode;
82
+ let argsNode;
83
+ // Check if decorator is a call (e.g., @lru_cache(maxsize=100))
84
+ const callNode = child.children.find((c) => c.type === "call");
85
+ if (callNode) {
86
+ // Get the function name from the call
87
+ nameNode = callNode.children.find((c) => c.type === "identifier" || c.type === "attribute");
88
+ // Get arguments from the call's argument_list
89
+ argsNode = callNode.children.find((c) => c.type === "argument_list");
90
+ }
91
+ else {
92
+ // Simple decorator (e.g., @property)
93
+ nameNode = child.children.find((c) => c.type === "identifier" || c.type === "attribute");
94
+ }
95
+ if (nameNode) {
96
+ const decorator = {
97
+ name: getNodeText(nameNode, source),
98
+ line: child.startPosition.row + 1,
99
+ };
100
+ // Parse arguments if present
101
+ if (argsNode) {
102
+ decorator.arguments = [];
103
+ for (const arg of argsNode.children) {
104
+ if (arg.type !== "(" && arg.type !== ")" && arg.type !== ",") {
105
+ decorator.arguments.push(getNodeText(arg, source));
106
+ }
107
+ }
108
+ }
109
+ decorators.push(decorator);
110
+ }
111
+ }
112
+ }
113
+ return decorators;
114
+ }
115
+ /**
116
+ * Parse function parameters
117
+ */
118
+ export function parseParameters(node, source) {
119
+ const params = [];
120
+ let seenSlash = false;
121
+ let seenStar = false;
122
+ const paramsNode = node.childForFieldName("parameters");
123
+ if (!paramsNode)
124
+ return params;
125
+ for (const child of paramsNode.children) {
126
+ if (child.type === "/" || getNodeText(child, source) === "/") {
127
+ seenSlash = true;
128
+ continue;
129
+ }
130
+ if (child.type === "*" && !child.firstChild) {
131
+ seenStar = true;
132
+ continue;
133
+ }
134
+ if (child.type === "identifier" ||
135
+ child.type === "typed_parameter" ||
136
+ child.type === "default_parameter" ||
137
+ child.type === "typed_default_parameter" ||
138
+ child.type === "list_splat_pattern" ||
139
+ child.type === "dictionary_splat_pattern") {
140
+ const param = {
141
+ name: "",
142
+ isArgs: child.type === "list_splat_pattern",
143
+ isKwargs: child.type === "dictionary_splat_pattern",
144
+ isPositionalOnly: !seenSlash,
145
+ isKeywordOnly: seenStar && !child.type.includes("splat"),
146
+ };
147
+ // Update positional only after we've seen /
148
+ if (seenSlash) {
149
+ param.isPositionalOnly = false;
150
+ }
151
+ // Get name - find the first identifier child
152
+ if (child.type === "identifier") {
153
+ param.name = getNodeText(child, source);
154
+ }
155
+ else {
156
+ // For typed_parameter, default_parameter, etc., find the identifier child
157
+ const nameNode = child.children.find((c) => c.type === "identifier");
158
+ if (nameNode) {
159
+ param.name = getNodeText(nameNode, source);
160
+ }
161
+ }
162
+ // Skip 'self' and 'cls'
163
+ if (param.name === "self" || param.name === "cls") {
164
+ continue;
165
+ }
166
+ // Get type annotation
167
+ const typeNode = child.childForFieldName("type");
168
+ if (typeNode) {
169
+ param.type = getNodeText(typeNode, source);
170
+ }
171
+ // Get default value
172
+ const valueNode = child.childForFieldName("value");
173
+ if (valueNode) {
174
+ param.default = getNodeText(valueNode, source);
175
+ }
176
+ if (param.name) {
177
+ params.push(param);
178
+ }
179
+ }
180
+ }
181
+ return params;
182
+ }
183
+ /**
184
+ * Parse a function definition
185
+ */
186
+ export function parseFunction(node, source, decorators = []) {
187
+ const nameNode = node.childForFieldName("name");
188
+ const returnTypeNode = node.childForFieldName("return_type");
189
+ // Check for async - either the node type or has an 'async' child
190
+ const isAsync = node.type === "async_function_definition" ||
191
+ node.parent?.type === "async_function_definition" ||
192
+ node.children.some((c) => c.type === "async");
193
+ // Check if generator (contains yield)
194
+ let isGenerator = false;
195
+ const checkYield = (n) => {
196
+ if (n.type === "yield")
197
+ return true;
198
+ for (const child of n.children) {
199
+ if (checkYield(child))
200
+ return true;
201
+ }
202
+ return false;
203
+ };
204
+ isGenerator = checkYield(node);
205
+ return {
206
+ name: nameNode ? getNodeText(nameNode, source) : "",
207
+ line: node.startPosition.row + 1,
208
+ endLine: node.endPosition.row + 1,
209
+ column: node.startPosition.column,
210
+ parameters: parseParameters(node, source),
211
+ returnType: returnTypeNode
212
+ ? getNodeText(returnTypeNode, source)
213
+ : undefined,
214
+ decorators,
215
+ isAsync,
216
+ isGenerator,
217
+ docstring: extractDocstring(node, source),
218
+ };
219
+ }
220
+ /**
221
+ * Parse a method (function inside a class)
222
+ */
223
+ export function parseMethod(node, source, decorators = []) {
224
+ const func = parseFunction(node, source, decorators);
225
+ const decoratorNames = decorators.map((d) => d.name);
226
+ return {
227
+ ...func,
228
+ isClassMethod: decoratorNames.includes("classmethod"),
229
+ isStaticMethod: decoratorNames.includes("staticmethod"),
230
+ isProperty: decoratorNames.includes("property"),
231
+ isAbstract: decoratorNames.includes("abstractmethod"),
232
+ };
233
+ }
234
+ /**
235
+ * Parse a class definition
236
+ */
237
+ export function parseClass(node, source, decorators = []) {
238
+ const nameNode = node.childForFieldName("name");
239
+ const basesNode = node.childForFieldName("superclasses");
240
+ const bases = [];
241
+ if (basesNode) {
242
+ for (const child of basesNode.children) {
243
+ if (child.type === "identifier" || child.type === "attribute") {
244
+ bases.push(getNodeText(child, source));
245
+ }
246
+ }
247
+ }
248
+ const methods = [];
249
+ const attributes = [];
250
+ // Parse body
251
+ const body = node.childForFieldName("body");
252
+ if (body) {
253
+ for (const child of body.children) {
254
+ if (child.type === "function_definition" ||
255
+ child.type === "async_function_definition") {
256
+ methods.push(parseMethod(child, source));
257
+ }
258
+ else if (child.type === "decorated_definition") {
259
+ const decs = parseDecorators(child, source);
260
+ const funcNode = child.children.find((c) => c.type === "function_definition" ||
261
+ c.type === "async_function_definition");
262
+ if (funcNode) {
263
+ methods.push(parseMethod(funcNode, source, decs));
264
+ }
265
+ }
266
+ else if (child.type === "expression_statement") {
267
+ // Class-level assignments
268
+ const expr = child.firstChild;
269
+ if (expr &&
270
+ (expr.type === "assignment" || expr.type === "annotated_assignment")) {
271
+ const leftNode = expr.childForFieldName("left") || expr.firstChild;
272
+ if (leftNode && leftNode.type === "identifier") {
273
+ const attr = {
274
+ name: getNodeText(leftNode, source),
275
+ line: child.startPosition.row + 1,
276
+ isClassAttribute: true,
277
+ };
278
+ // Get type annotation
279
+ const typeNode = expr.childForFieldName("type");
280
+ if (typeNode) {
281
+ attr.type = getNodeText(typeNode, source);
282
+ }
283
+ // Get value
284
+ const valueNode = expr.childForFieldName("right") ||
285
+ expr.childForFieldName("value");
286
+ if (valueNode) {
287
+ attr.default = getNodeText(valueNode, source);
288
+ }
289
+ attributes.push(attr);
290
+ }
291
+ }
292
+ }
293
+ }
294
+ }
295
+ const decoratorNames = decorators.map((d) => d.name);
296
+ const isAbstract = bases.some((b) => b === "ABC" || b.endsWith(".ABC") || b === "ABCMeta");
297
+ const isDataclass = decoratorNames.includes("dataclass");
298
+ return {
299
+ name: nameNode ? getNodeText(nameNode, source) : "",
300
+ line: node.startPosition.row + 1,
301
+ endLine: node.endPosition.row + 1,
302
+ column: node.startPosition.column,
303
+ bases,
304
+ decorators,
305
+ methods,
306
+ attributes,
307
+ docstring: extractDocstring(node, source),
308
+ isAbstract,
309
+ isDataclass,
310
+ };
311
+ }
312
+ /**
313
+ * Parse import statement
314
+ */
315
+ export function parseImport(node, source) {
316
+ if (node.type === "import_statement") {
317
+ const names = [];
318
+ let mainModule = "";
319
+ for (const child of node.children) {
320
+ if (child.type === "dotted_name") {
321
+ mainModule = getNodeText(child, source);
322
+ names.push({ name: mainModule });
323
+ }
324
+ else if (child.type === "aliased_import") {
325
+ const nameNode = child.childForFieldName("name");
326
+ const aliasNode = child.childForFieldName("alias");
327
+ if (nameNode) {
328
+ const entry = {
329
+ name: getNodeText(nameNode, source),
330
+ };
331
+ if (aliasNode) {
332
+ entry.alias = getNodeText(aliasNode, source);
333
+ }
334
+ names.push(entry);
335
+ }
336
+ }
337
+ }
338
+ return {
339
+ module: mainModule || (names[0]?.name ?? ""),
340
+ names,
341
+ line: node.startPosition.row + 1,
342
+ isFromImport: false,
343
+ isRelative: false,
344
+ relativeDots: 0,
345
+ };
346
+ }
347
+ // import_from_statement
348
+ const moduleNode = node.childForFieldName("module_name");
349
+ const moduleName = moduleNode ? getNodeText(moduleNode, source) : "";
350
+ // Count relative dots
351
+ let relativeDots = 0;
352
+ for (const child of node.children) {
353
+ if (getNodeText(child, source) === ".") {
354
+ relativeDots++;
355
+ }
356
+ }
357
+ const names = [];
358
+ // Check for wildcard import
359
+ const wildcardNode = node.children.find((c) => getNodeText(c, source) === "*");
360
+ if (wildcardNode) {
361
+ names.push({ name: "*" });
362
+ }
363
+ else {
364
+ // Parse imported names
365
+ for (const child of node.children) {
366
+ if (child.type === "dotted_name" && child !== moduleNode) {
367
+ names.push({ name: getNodeText(child, source) });
368
+ }
369
+ else if (child.type === "aliased_import") {
370
+ const nameNode = child.childForFieldName("name");
371
+ const aliasNode = child.childForFieldName("alias");
372
+ if (nameNode) {
373
+ const entry = {
374
+ name: getNodeText(nameNode, source),
375
+ };
376
+ if (aliasNode) {
377
+ entry.alias = getNodeText(aliasNode, source);
378
+ }
379
+ names.push(entry);
380
+ }
381
+ }
382
+ }
383
+ }
384
+ return {
385
+ module: moduleName,
386
+ names,
387
+ line: node.startPosition.row + 1,
388
+ isFromImport: true,
389
+ isRelative: relativeDots > 0,
390
+ relativeDots,
391
+ };
392
+ }
393
+ /**
394
+ * Parse variable assignment
395
+ */
396
+ export function parseVariable(node, source) {
397
+ let nameNode = null;
398
+ let typeNode = null;
399
+ let valueNode = null;
400
+ if (node.type === "assignment") {
401
+ nameNode = node.childForFieldName("left");
402
+ valueNode = node.childForFieldName("right");
403
+ }
404
+ else if (node.type === "annotated_assignment") {
405
+ nameNode = node.childForFieldName("left") || node.firstChild;
406
+ typeNode = node.childForFieldName("type");
407
+ valueNode = node.childForFieldName("value");
408
+ }
409
+ if (!nameNode || nameNode.type !== "identifier") {
410
+ return null;
411
+ }
412
+ const name = getNodeText(nameNode, source);
413
+ // Check if constant (all uppercase)
414
+ const isConstant = /^[A-Z][A-Z0-9_]*$/.test(name);
415
+ return {
416
+ name,
417
+ type: typeNode ? getNodeText(typeNode, source) : undefined,
418
+ value: valueNode ? getNodeText(valueNode, source) : undefined,
419
+ line: node.startPosition.row + 1,
420
+ column: node.startPosition.column,
421
+ isConstant,
422
+ };
423
+ }
424
+ /**
425
+ * Walk the AST and collect all nodes of given types
426
+ */
427
+ export function* walkTree(node, types) {
428
+ if (!types || types.includes(node.type)) {
429
+ yield node;
430
+ }
431
+ for (const child of node.children) {
432
+ yield* walkTree(child, types);
433
+ }
434
+ }
435
+ /**
436
+ * Find all nodes matching a predicate
437
+ */
438
+ export function findNodes(node, predicate) {
439
+ const results = [];
440
+ const walk = (n) => {
441
+ if (predicate(n)) {
442
+ results.push(n);
443
+ }
444
+ for (const child of n.children) {
445
+ walk(child);
446
+ }
447
+ };
448
+ walk(node);
449
+ return results;
450
+ }
451
+ /**
452
+ * Get the containing scope for a node (function or class)
453
+ */
454
+ export function getContainingScope(node) {
455
+ let current = node.parent;
456
+ while (current) {
457
+ if (current.type === "function_definition" ||
458
+ current.type === "async_function_definition") {
459
+ const nameNode = current.childForFieldName("name");
460
+ return {
461
+ type: "function",
462
+ name: nameNode?.text ?? "",
463
+ node: current,
464
+ };
465
+ }
466
+ if (current.type === "class_definition") {
467
+ const nameNode = current.childForFieldName("name");
468
+ return {
469
+ type: "class",
470
+ name: nameNode?.text ?? "",
471
+ node: current,
472
+ };
473
+ }
474
+ current = current.parent;
475
+ }
476
+ return null;
477
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Python Skills
3
+ *
4
+ * Skills for Python code analysis, best practices, and workflows.
5
+ */
6
+ export { pythonBestPracticesSkill } from "./python-best-practices.js";
7
+ export { pythonCodeHealthSkill } from "./python-code-health.js";
8
+ export { pythonCodeStructureSkill } from "./python-code-structure.js";
9
+ export { pythonDependencyAuditSkill } from "./python-dependency-audit.js";
10
+ export { pythonRefactorImpactSkill } from "./python-refactor-impact.js";
11
+ import type { Skill } from "@compilr-dev/agents";
12
+ /**
13
+ * All Python skills
14
+ */
15
+ export declare const pythonSkills: Skill[];
16
+ /**
17
+ * Python skills by name for selective use
18
+ */
19
+ export declare const pythonSkillsMap: {
20
+ readonly bestPractices: Skill;
21
+ readonly codeHealth: Skill;
22
+ readonly codeStructure: Skill;
23
+ readonly dependencyAudit: Skill;
24
+ readonly refactorImpact: Skill;
25
+ };
26
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/skills/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AAOxE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAEjD;;GAEG;AACH,eAAO,MAAM,YAAY,EAAE,KAAK,EAM/B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe;;;;;;CAMlB,CAAC"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Python Skills
3
+ *
4
+ * Skills for Python code analysis, best practices, and workflows.
5
+ */
6
+ // Individual skill exports
7
+ export { pythonBestPracticesSkill } from "./python-best-practices.js";
8
+ export { pythonCodeHealthSkill } from "./python-code-health.js";
9
+ export { pythonCodeStructureSkill } from "./python-code-structure.js";
10
+ export { pythonDependencyAuditSkill } from "./python-dependency-audit.js";
11
+ export { pythonRefactorImpactSkill } from "./python-refactor-impact.js";
12
+ import { pythonBestPracticesSkill } from "./python-best-practices.js";
13
+ import { pythonCodeHealthSkill } from "./python-code-health.js";
14
+ import { pythonCodeStructureSkill } from "./python-code-structure.js";
15
+ import { pythonDependencyAuditSkill } from "./python-dependency-audit.js";
16
+ import { pythonRefactorImpactSkill } from "./python-refactor-impact.js";
17
+ /**
18
+ * All Python skills
19
+ */
20
+ export const pythonSkills = [
21
+ pythonBestPracticesSkill,
22
+ pythonCodeHealthSkill,
23
+ pythonCodeStructureSkill,
24
+ pythonDependencyAuditSkill,
25
+ pythonRefactorImpactSkill,
26
+ ];
27
+ /**
28
+ * Python skills by name for selective use
29
+ */
30
+ export const pythonSkillsMap = {
31
+ bestPractices: pythonBestPracticesSkill,
32
+ codeHealth: pythonCodeHealthSkill,
33
+ codeStructure: pythonCodeStructureSkill,
34
+ dependencyAudit: pythonDependencyAuditSkill,
35
+ refactorImpact: pythonRefactorImpactSkill,
36
+ };
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Python Best Practices Skill
3
+ *
4
+ * Provides guidance for Python-specific coding patterns and analysis.
5
+ */
6
+ export declare const pythonBestPracticesSkill: import("@compilr-dev/agents").Skill;
7
+ //# sourceMappingURL=python-best-practices.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"python-best-practices.d.ts","sourceRoot":"","sources":["../../src/skills/python-best-practices.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,eAAO,MAAM,wBAAwB,qCAuEnC,CAAC"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Python Best Practices Skill
3
+ *
4
+ * Provides guidance for Python-specific coding patterns and analysis.
5
+ */
6
+ import { defineSkill } from "@compilr-dev/agents";
7
+ export const pythonBestPracticesSkill = defineSkill({
8
+ name: "python-best-practices",
9
+ description: "Python-specific coding guidance and analysis workflow",
10
+ version: "1.0.0",
11
+ tags: ["python", "best-practices", "analysis"],
12
+ prompt: `You are in Python analysis mode. Use these tools for comprehensive code understanding:
13
+
14
+ ## Code Structure Analysis
15
+ - **getFileStructure**: Get overview of classes, functions, imports, variables
16
+ - Use to understand file organization
17
+ - Identify public API surface
18
+ - See class hierarchies and method signatures
19
+
20
+ ## Python-Specific Guidance
21
+
22
+ ### Naming Conventions (PEP 8)
23
+ - \`snake_case\` for functions, variables, modules
24
+ - \`PascalCase\` for classes
25
+ - \`UPPER_CASE\` for constants
26
+ - \`_private\` for internal use
27
+ - \`__dunder__\` for special methods
28
+
29
+ ### Type Hints (PEP 484, 585)
30
+ - Always add type hints to function signatures
31
+ - Use \`Optional[T]\` for nullable values
32
+ - Use \`Union[A, B]\` for multiple types
33
+ - Prefer \`list[T]\` over \`List[T]\` (Python 3.9+)
34
+
35
+ ### Docstrings (PEP 257)
36
+ - Use triple quotes for all docstrings
37
+ - First line is a summary
38
+ - Blank line before detailed description
39
+ - Document parameters, returns, raises
40
+
41
+ ### Best Practices
42
+ - Use dataclasses or attrs for data containers
43
+ - Prefer pathlib over os.path
44
+ - Use f-strings over .format()
45
+ - Use context managers for resources
46
+ - Avoid mutable default arguments: \`def foo(x=None)\` not \`def foo(x=[])\`
47
+ - Use \`__all__\` to define public API
48
+
49
+ ### Anti-Patterns to Avoid
50
+ - Bare \`except:\` clauses (catch specific exceptions)
51
+ - \`from module import *\` (explicit imports only)
52
+ - Global variables
53
+ - Deeply nested code (refactor to smaller functions)
54
+ - Magic numbers (use named constants)
55
+
56
+ ## Analysis Workflow
57
+
58
+ 1. **Understand Structure**
59
+ \`\`\`
60
+ getFileStructure for overview
61
+ \`\`\`
62
+
63
+ 2. **Review Complexity**
64
+ - Look for functions with many parameters
65
+ - Check for deeply nested code
66
+ - Identify god classes
67
+
68
+ 3. **Check Code Quality**
69
+ - Look for missing type hints
70
+ - Check docstring coverage
71
+ - Find TODO/FIXME comments
72
+
73
+ 4. **Suggest Improvements**
74
+ - Recommend refactoring for complex code
75
+ - Suggest type hints where missing
76
+ - Propose better naming when unclear
77
+ `,
78
+ });
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Python Code Health Skill
3
+ *
4
+ * Orchestrates code quality analysis using complexity, dead code, duplicates, patterns, and other tools.
5
+ */
6
+ export declare const pythonCodeHealthSkill: import("@compilr-dev/agents").Skill;
7
+ //# sourceMappingURL=python-code-health.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"python-code-health.d.ts","sourceRoot":"","sources":["../../src/skills/python-code-health.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,eAAO,MAAM,qBAAqB,qCA0MhC,CAAC"}