@compilr-dev/agents-coding-ts 0.1.3 → 0.1.5

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 (51) hide show
  1. package/LICENSE +95 -8
  2. package/README.md +4 -1
  3. package/dist/index.d.ts +8 -5
  4. package/dist/index.js +14 -4
  5. package/dist/parser/index.d.ts +2 -2
  6. package/dist/parser/index.js +1 -1
  7. package/dist/parser/typescript-parser.d.ts +2 -2
  8. package/dist/parser/typescript-parser.js +77 -54
  9. package/dist/skills/code-health.js +5 -5
  10. package/dist/skills/code-structure.js +5 -5
  11. package/dist/skills/dependency-audit.js +5 -5
  12. package/dist/skills/index.d.ts +7 -7
  13. package/dist/skills/index.js +11 -11
  14. package/dist/skills/refactor-impact.js +5 -5
  15. package/dist/skills/type-analysis.js +5 -5
  16. package/dist/tools/find-dead-code.d.ts +2 -2
  17. package/dist/tools/find-dead-code.js +82 -58
  18. package/dist/tools/find-duplicates.d.ts +2 -2
  19. package/dist/tools/find-duplicates.js +41 -38
  20. package/dist/tools/find-implementations.d.ts +2 -2
  21. package/dist/tools/find-implementations.js +44 -36
  22. package/dist/tools/find-patterns.d.ts +2 -2
  23. package/dist/tools/find-patterns.js +154 -148
  24. package/dist/tools/find-references.d.ts +2 -2
  25. package/dist/tools/find-references.js +76 -72
  26. package/dist/tools/find-symbol.d.ts +2 -2
  27. package/dist/tools/find-symbol.js +106 -96
  28. package/dist/tools/get-call-graph.d.ts +2 -2
  29. package/dist/tools/get-call-graph.js +52 -47
  30. package/dist/tools/get-complexity.d.ts +2 -2
  31. package/dist/tools/get-complexity.js +94 -46
  32. package/dist/tools/get-dependency-graph.d.ts +2 -2
  33. package/dist/tools/get-dependency-graph.js +66 -52
  34. package/dist/tools/get-documentation.d.ts +2 -2
  35. package/dist/tools/get-documentation.js +154 -122
  36. package/dist/tools/get-exports.d.ts +2 -2
  37. package/dist/tools/get-exports.js +73 -61
  38. package/dist/tools/get-file-structure.d.ts +2 -2
  39. package/dist/tools/get-file-structure.js +16 -16
  40. package/dist/tools/get-imports.d.ts +2 -2
  41. package/dist/tools/get-imports.js +46 -46
  42. package/dist/tools/get-signature.d.ts +2 -2
  43. package/dist/tools/get-signature.js +168 -124
  44. package/dist/tools/get-type-hierarchy.d.ts +2 -2
  45. package/dist/tools/get-type-hierarchy.js +53 -44
  46. package/dist/tools/index.d.ts +18 -16
  47. package/dist/tools/index.js +17 -15
  48. package/dist/tools/read-symbol.d.ts +62 -0
  49. package/dist/tools/read-symbol.js +464 -0
  50. package/dist/tools/types.d.ts +27 -27
  51. package/package.json +8 -8
@@ -3,13 +3,13 @@
3
3
  *
4
4
  * Specialized skills for code analysis workflows using AST-based tools.
5
5
  */
6
- import type { Skill } from '@compilr-dev/agents';
7
- export { defineSkill, type Skill } from '@compilr-dev/agents';
8
- export { codeStructureSkill } from './code-structure.js';
9
- export { dependencyAuditSkill } from './dependency-audit.js';
10
- export { refactorImpactSkill } from './refactor-impact.js';
11
- export { typeAnalysisSkill } from './type-analysis.js';
12
- export { codeHealthSkill } from './code-health.js';
6
+ import type { Skill } from "@compilr-dev/agents";
7
+ export { defineSkill, type Skill } from "@compilr-dev/agents";
8
+ export { codeStructureSkill } from "./code-structure.js";
9
+ export { dependencyAuditSkill } from "./dependency-audit.js";
10
+ export { refactorImpactSkill } from "./refactor-impact.js";
11
+ export { typeAnalysisSkill } from "./type-analysis.js";
12
+ export { codeHealthSkill } from "./code-health.js";
13
13
  /**
14
14
  * All TypeScript/JavaScript analysis skills
15
15
  */
@@ -3,18 +3,18 @@
3
3
  *
4
4
  * Specialized skills for code analysis workflows using AST-based tools.
5
5
  */
6
- export { defineSkill } from '@compilr-dev/agents';
7
- export { codeStructureSkill } from './code-structure.js';
8
- export { dependencyAuditSkill } from './dependency-audit.js';
9
- export { refactorImpactSkill } from './refactor-impact.js';
10
- export { typeAnalysisSkill } from './type-analysis.js';
11
- export { codeHealthSkill } from './code-health.js';
6
+ export { defineSkill } from "@compilr-dev/agents";
7
+ export { codeStructureSkill } from "./code-structure.js";
8
+ export { dependencyAuditSkill } from "./dependency-audit.js";
9
+ export { refactorImpactSkill } from "./refactor-impact.js";
10
+ export { typeAnalysisSkill } from "./type-analysis.js";
11
+ export { codeHealthSkill } from "./code-health.js";
12
12
  // Import for collection
13
- import { codeStructureSkill } from './code-structure.js';
14
- import { dependencyAuditSkill } from './dependency-audit.js';
15
- import { refactorImpactSkill } from './refactor-impact.js';
16
- import { typeAnalysisSkill } from './type-analysis.js';
17
- import { codeHealthSkill } from './code-health.js';
13
+ import { codeStructureSkill } from "./code-structure.js";
14
+ import { dependencyAuditSkill } from "./dependency-audit.js";
15
+ import { refactorImpactSkill } from "./refactor-impact.js";
16
+ import { typeAnalysisSkill } from "./type-analysis.js";
17
+ import { codeHealthSkill } from "./code-health.js";
18
18
  /**
19
19
  * All TypeScript/JavaScript analysis skills
20
20
  */
@@ -3,13 +3,13 @@
3
3
  *
4
4
  * Analyze the impact of refactoring a symbol across the codebase.
5
5
  */
6
- import { defineSkill } from '@compilr-dev/agents';
6
+ import { defineSkill } from "@compilr-dev/agents";
7
7
  /**
8
8
  * Refactor impact skill - Analyze impact of refactoring a symbol
9
9
  */
10
10
  export const refactorImpactSkill = defineSkill({
11
- name: 'refactor-impact',
12
- description: 'Analyze the impact of refactoring a symbol across the codebase',
11
+ name: "refactor-impact",
12
+ description: "Analyze the impact of refactoring a symbol across the codebase",
13
13
  prompt: `You are in REFACTOR IMPACT ANALYSIS mode. Analyze what would be affected by refactoring a symbol.
14
14
 
15
15
  ## When to Use
@@ -141,6 +141,6 @@ get_type_hierarchy({
141
141
  - Quantify the impact (number of files, usages)
142
142
  - Provide actionable checklist
143
143
  - Highlight breaking changes for exported/public symbols`,
144
- tags: ['refactoring', 'analysis', 'impact', 'planning'],
145
- version: '1.0.0',
144
+ tags: ["refactoring", "analysis", "impact", "planning"],
145
+ version: "1.0.0",
146
146
  });
@@ -3,13 +3,13 @@
3
3
  *
4
4
  * Analyze type hierarchies, interfaces, and their implementations.
5
5
  */
6
- import { defineSkill } from '@compilr-dev/agents';
6
+ import { defineSkill } from "@compilr-dev/agents";
7
7
  /**
8
8
  * Type analysis skill - Analyze type hierarchies and implementations
9
9
  */
10
10
  export const typeAnalysisSkill = defineSkill({
11
- name: 'type-analysis',
12
- description: 'Analyze type hierarchies, interfaces, and their implementations',
11
+ name: "type-analysis",
12
+ description: "Analyze type hierarchies, interfaces, and their implementations",
13
13
  prompt: `You are in TYPE ANALYSIS mode. Analyze type relationships in the codebase.
14
14
 
15
15
  ## When to Use
@@ -156,6 +156,6 @@ TypeName
156
156
  - Highlight incomplete implementations
157
157
  - Note generic type parameters when present
158
158
  - Keep diagrams simple - expand on request`,
159
- tags: ['types', 'analysis', 'inheritance', 'interfaces', 'architecture'],
160
- version: '1.0.0',
159
+ tags: ["types", "analysis", "inheritance", "interfaces", "architecture"],
160
+ version: "1.0.0",
161
161
  });
@@ -4,8 +4,8 @@
4
4
  * Find potentially unused exports, functions, and variables across a codebase.
5
5
  * Uses static analysis to identify code that may be dead.
6
6
  */
7
- import type { Tool } from '@compilr-dev/agents';
8
- import type { FindDeadCodeInput } from './types.js';
7
+ import type { Tool } from "@compilr-dev/agents";
8
+ import type { FindDeadCodeInput } from "./types.js";
9
9
  /**
10
10
  * findDeadCode tool
11
11
  */
@@ -4,59 +4,59 @@
4
4
  * Find potentially unused exports, functions, and variables across a codebase.
5
5
  * Uses static analysis to identify code that may be dead.
6
6
  */
7
- import * as fs from 'node:fs/promises';
8
- import * as path from 'node:path';
9
- import * as ts from 'typescript';
10
- import { defineTool, createSuccessResult, createErrorResult } from '@compilr-dev/agents';
11
- import { detectLanguage, isLanguageSupported } from '../parser/typescript-parser.js';
7
+ import * as fs from "node:fs/promises";
8
+ import * as path from "node:path";
9
+ import * as ts from "typescript";
10
+ import { defineTool, createSuccessResult, createErrorResult, } from "@compilr-dev/agents";
11
+ import { detectLanguage, isLanguageSupported, } from "../parser/typescript-parser.js";
12
12
  // Tool description
13
13
  const TOOL_DESCRIPTION = `Find potentially unused exports, functions, and variables.
14
14
  Analyzes the codebase to identify code that may be dead (never used).
15
15
  Useful for cleanup and reducing bundle size.`;
16
16
  // Tool input schema
17
17
  const TOOL_INPUT_SCHEMA = {
18
- type: 'object',
18
+ type: "object",
19
19
  properties: {
20
20
  path: {
21
- type: 'string',
22
- description: 'Directory to analyze',
21
+ type: "string",
22
+ description: "Directory to analyze",
23
23
  },
24
24
  includeTests: {
25
- type: 'boolean',
26
- description: 'Include test files in analysis (default: false)',
25
+ type: "boolean",
26
+ description: "Include test files in analysis (default: false)",
27
27
  default: false,
28
28
  },
29
29
  checkExports: {
30
- type: 'boolean',
31
- description: 'Check for unused exports (default: true)',
30
+ type: "boolean",
31
+ description: "Check for unused exports (default: true)",
32
32
  default: true,
33
33
  },
34
34
  checkFunctions: {
35
- type: 'boolean',
36
- description: 'Check for unused functions (default: true)',
35
+ type: "boolean",
36
+ description: "Check for unused functions (default: true)",
37
37
  default: true,
38
38
  },
39
39
  checkVariables: {
40
- type: 'boolean',
41
- description: 'Check for unused variables (default: false)',
40
+ type: "boolean",
41
+ description: "Check for unused variables (default: false)",
42
42
  default: false,
43
43
  },
44
44
  maxFiles: {
45
- type: 'number',
46
- description: 'Maximum files to analyze (default: 100)',
45
+ type: "number",
46
+ description: "Maximum files to analyze (default: 100)",
47
47
  default: 100,
48
48
  },
49
49
  },
50
- required: ['path'],
50
+ required: ["path"],
51
51
  };
52
52
  // Default exclusions
53
- const DEFAULT_EXCLUDE = ['node_modules', 'dist', 'build', '.git', 'coverage'];
54
- const TEST_PATTERNS = ['.test.', '.spec.', '__tests__', '__mocks__'];
53
+ const DEFAULT_EXCLUDE = ["node_modules", "dist", "build", ".git", "coverage"];
54
+ const TEST_PATTERNS = [".test.", ".spec.", "__tests__", "__mocks__"];
55
55
  /**
56
56
  * findDeadCode tool
57
57
  */
58
58
  export const findDeadCodeTool = defineTool({
59
- name: 'find_dead_code',
59
+ name: "find_dead_code",
60
60
  description: TOOL_DESCRIPTION,
61
61
  inputSchema: TOOL_INPUT_SCHEMA,
62
62
  execute: executeFindDeadCode,
@@ -77,7 +77,7 @@ async function executeFindDeadCode(input) {
77
77
  }
78
78
  const stats = await fs.stat(resolvedPath);
79
79
  if (!stats.isDirectory()) {
80
- return createErrorResult('findDeadCode requires a directory path');
80
+ return createErrorResult("findDeadCode requires a directory path");
81
81
  }
82
82
  // Collect files
83
83
  const files = [];
@@ -101,7 +101,7 @@ async function executeFindDeadCode(input) {
101
101
  let unusedVariables = 0;
102
102
  for (const def of definitions) {
103
103
  // Skip index files (re-exports)
104
- if (def.path.endsWith('index.ts') || def.path.endsWith('index.js')) {
104
+ if (def.path.endsWith("index.ts") || def.path.endsWith("index.js")) {
105
105
  continue;
106
106
  }
107
107
  const isUsed = usages.has(def.name) || importedSymbols.has(def.name);
@@ -117,16 +117,16 @@ async function executeFindDeadCode(input) {
117
117
  name: def.name,
118
118
  path: def.path,
119
119
  line: def.line,
120
- kind: 'export',
120
+ kind: "export",
121
121
  exported: true,
122
- confidence: 'medium',
123
- reason: 'Export is not imported anywhere in the codebase',
122
+ confidence: "medium",
123
+ reason: "Export is not imported anywhere in the codebase",
124
124
  });
125
125
  }
126
126
  }
127
127
  }
128
128
  // Check functions
129
- if (def.kind === 'function' && checkFunctions) {
129
+ if (def.kind === "function" && checkFunctions) {
130
130
  totalFunctions++;
131
131
  if (!isUsed && !def.exported) {
132
132
  unusedFunctions++;
@@ -134,15 +134,15 @@ async function executeFindDeadCode(input) {
134
134
  name: def.name,
135
135
  path: def.path,
136
136
  line: def.line,
137
- kind: 'function',
137
+ kind: "function",
138
138
  exported: false,
139
- confidence: 'high',
140
- reason: 'Function is not called anywhere in the file',
139
+ confidence: "high",
140
+ reason: "Function is not called anywhere in the file",
141
141
  });
142
142
  }
143
143
  }
144
144
  // Check variables
145
- if (def.kind === 'variable' && checkVariables) {
145
+ if (def.kind === "variable" && checkVariables) {
146
146
  totalVariables++;
147
147
  if (!isUsed && !def.exported) {
148
148
  unusedVariables++;
@@ -150,10 +150,10 @@ async function executeFindDeadCode(input) {
150
150
  name: def.name,
151
151
  path: def.path,
152
152
  line: def.line,
153
- kind: 'variable',
153
+ kind: "variable",
154
154
  exported: false,
155
- confidence: 'medium',
156
- reason: 'Variable is not referenced after declaration',
155
+ confidence: "medium",
156
+ reason: "Variable is not referenced after declaration",
157
157
  });
158
158
  }
159
159
  }
@@ -193,15 +193,17 @@ async function collectFiles(dirPath, files, includeTests, maxFiles, currentDepth
193
193
  if (entry.isDirectory()) {
194
194
  if (DEFAULT_EXCLUDE.includes(entry.name))
195
195
  continue;
196
- if (!includeTests && entry.name === '__tests__')
196
+ if (!includeTests && entry.name === "__tests__")
197
197
  continue;
198
198
  await collectFiles(fullPath, files, includeTests, maxFiles, currentDepth + 1);
199
199
  }
200
200
  else if (entry.isFile()) {
201
201
  // Only include TypeScript/JavaScript files
202
- if (/\.(ts|tsx|js|jsx)$/.test(entry.name) && !entry.name.endsWith('.d.ts')) {
202
+ if (/\.(ts|tsx|js|jsx)$/.test(entry.name) &&
203
+ !entry.name.endsWith(".d.ts")) {
203
204
  // Skip test files if not including tests
204
- if (!includeTests && TEST_PATTERNS.some((p) => fullPath.includes(p))) {
205
+ if (!includeTests &&
206
+ TEST_PATTERNS.some((p) => fullPath.includes(p))) {
205
207
  continue;
206
208
  }
207
209
  files.push(fullPath);
@@ -218,47 +220,51 @@ async function collectFiles(dirPath, files, includeTests, maxFiles, currentDepth
218
220
  */
219
221
  async function analyzeFile(filePath, definitions, usages, importedSymbols) {
220
222
  try {
221
- const content = await fs.readFile(filePath, 'utf-8');
223
+ const content = await fs.readFile(filePath, "utf-8");
222
224
  const detection = detectLanguage(filePath);
223
225
  if (!detection.language || !isLanguageSupported(detection.language)) {
224
226
  return;
225
227
  }
226
- const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true, filePath.endsWith('.tsx') ? ts.ScriptKind.TSX : ts.ScriptKind.TS);
228
+ const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true, filePath.endsWith(".tsx") ? ts.ScriptKind.TSX : ts.ScriptKind.TS);
227
229
  // Collect definitions
228
230
  const visit = (node) => {
229
231
  const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
230
232
  // Function declarations
231
233
  if (ts.isFunctionDeclaration(node) && node.name) {
232
- const isExported = node.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword) ?? false;
234
+ const isExported = node.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword) ??
235
+ false;
233
236
  definitions.push({
234
237
  name: node.name.text,
235
238
  path: filePath,
236
239
  line: line + 1,
237
- kind: 'function',
240
+ kind: "function",
238
241
  exported: isExported,
239
242
  });
240
243
  }
241
244
  // Class declarations
242
245
  if (ts.isClassDeclaration(node) && node.name) {
243
- const isExported = node.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword) ?? false;
246
+ const isExported = node.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword) ??
247
+ false;
244
248
  definitions.push({
245
249
  name: node.name.text,
246
250
  path: filePath,
247
251
  line: line + 1,
248
- kind: 'class',
252
+ kind: "class",
249
253
  exported: isExported,
250
254
  });
251
255
  }
252
256
  // Variable declarations (const, let, var)
253
257
  if (ts.isVariableStatement(node)) {
254
- const isExported = node.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword) ?? false;
258
+ const isExported = node.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword) ??
259
+ false;
255
260
  for (const decl of node.declarationList.declarations) {
256
261
  if (ts.isIdentifier(decl.name)) {
257
262
  // Check if it's a function expression
258
263
  const kind = decl.initializer &&
259
- (ts.isFunctionExpression(decl.initializer) || ts.isArrowFunction(decl.initializer))
260
- ? 'function'
261
- : 'variable';
264
+ (ts.isFunctionExpression(decl.initializer) ||
265
+ ts.isArrowFunction(decl.initializer))
266
+ ? "function"
267
+ : "variable";
262
268
  definitions.push({
263
269
  name: decl.name.text,
264
270
  path: filePath,
@@ -271,41 +277,45 @@ async function analyzeFile(filePath, definitions, usages, importedSymbols) {
271
277
  }
272
278
  // Interface declarations
273
279
  if (ts.isInterfaceDeclaration(node)) {
274
- const isExported = node.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword) ?? false;
280
+ const isExported = node.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword) ??
281
+ false;
275
282
  definitions.push({
276
283
  name: node.name.text,
277
284
  path: filePath,
278
285
  line: line + 1,
279
- kind: 'interface',
286
+ kind: "interface",
280
287
  exported: isExported,
281
288
  });
282
289
  }
283
290
  // Type alias declarations
284
291
  if (ts.isTypeAliasDeclaration(node)) {
285
- const isExported = node.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword) ?? false;
292
+ const isExported = node.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword) ??
293
+ false;
286
294
  definitions.push({
287
295
  name: node.name.text,
288
296
  path: filePath,
289
297
  line: line + 1,
290
- kind: 'type',
298
+ kind: "type",
291
299
  exported: isExported,
292
300
  });
293
301
  }
294
302
  // Enum declarations
295
303
  if (ts.isEnumDeclaration(node)) {
296
- const isExported = node.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword) ?? false;
304
+ const isExported = node.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword) ??
305
+ false;
297
306
  definitions.push({
298
307
  name: node.name.text,
299
308
  path: filePath,
300
309
  line: line + 1,
301
- kind: 'enum',
310
+ kind: "enum",
302
311
  exported: isExported,
303
312
  });
304
313
  }
305
314
  // Import declarations - track what's imported
306
315
  if (ts.isImportDeclaration(node) && node.importClause) {
307
316
  // Named imports
308
- if (node.importClause.namedBindings && ts.isNamedImports(node.importClause.namedBindings)) {
317
+ if (node.importClause.namedBindings &&
318
+ ts.isNamedImports(node.importClause.namedBindings)) {
309
319
  for (const specifier of node.importClause.namedBindings.elements) {
310
320
  importedSymbols.add(specifier.name.text);
311
321
  }
@@ -344,13 +354,27 @@ async function analyzeFile(filePath, definitions, usages, importedSymbols) {
344
354
  */
345
355
  function isLikelyEntryPoint(filePath, symbolName) {
346
356
  // Main entry files
347
- const entryPatterns = ['index.ts', 'index.js', 'main.ts', 'main.js', 'app.ts', 'app.js'];
357
+ const entryPatterns = [
358
+ "index.ts",
359
+ "index.js",
360
+ "main.ts",
361
+ "main.js",
362
+ "app.ts",
363
+ "app.js",
364
+ ];
348
365
  const fileName = path.basename(filePath);
349
366
  if (entryPatterns.includes(fileName)) {
350
367
  return true;
351
368
  }
352
369
  // Common exported names that are likely entry points
353
- const entrySymbols = ['default', 'main', 'app', 'handler', 'server', 'client'];
370
+ const entrySymbols = [
371
+ "default",
372
+ "main",
373
+ "app",
374
+ "handler",
375
+ "server",
376
+ "client",
377
+ ];
354
378
  if (entrySymbols.includes(symbolName.toLowerCase())) {
355
379
  return true;
356
380
  }
@@ -361,7 +385,7 @@ function isLikelyEntryPoint(filePath, symbolName) {
361
385
  */
362
386
  export function createFindDeadCodeTool(options) {
363
387
  return defineTool({
364
- name: options?.name ?? 'find_dead_code',
388
+ name: options?.name ?? "find_dead_code",
365
389
  description: options?.description ?? TOOL_DESCRIPTION,
366
390
  inputSchema: TOOL_INPUT_SCHEMA,
367
391
  execute: async (input) => {
@@ -4,8 +4,8 @@
4
4
  * Detect duplicate code blocks across the codebase using content hashing.
5
5
  * Helps identify opportunities for refactoring and code reuse.
6
6
  */
7
- import type { Tool } from '@compilr-dev/agents';
8
- import type { FindDuplicatesInput } from './types.js';
7
+ import type { Tool } from "@compilr-dev/agents";
8
+ import type { FindDuplicatesInput } from "./types.js";
9
9
  /**
10
10
  * findDuplicates tool
11
11
  */