bobs-workshop 0.3.0 → 0.3.1

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 (34) hide show
  1. package/Claude.md +30 -4
  2. package/README.md +2 -2
  3. package/dist/index.js +4 -4
  4. package/dist/index.js.map +1 -1
  5. package/dist/prompts/architect.js +6 -1
  6. package/dist/prompts/architect.js.map +1 -1
  7. package/dist/prompts/debugger.js +5 -0
  8. package/dist/prompts/debugger.js.map +1 -1
  9. package/dist/prompts/engineer.js +6 -1
  10. package/dist/prompts/engineer.js.map +1 -1
  11. package/dist/prompts/reviewer.js +6 -1
  12. package/dist/prompts/reviewer.js.map +1 -1
  13. package/dist/tools/searchTools.js +55 -2
  14. package/dist/tools/searchTools.js.map +1 -1
  15. package/dist/tools/structural/__tests__/orchestrator.test.js +61 -0
  16. package/dist/tools/structural/__tests__/orchestrator.test.js.map +1 -0
  17. package/dist/tools/structural/cache.js +226 -0
  18. package/dist/tools/structural/cache.js.map +1 -0
  19. package/dist/tools/structural/engines/python/index.js +118 -0
  20. package/dist/tools/structural/engines/python/index.js.map +1 -0
  21. package/dist/tools/structural/engines/typescript/__tests__/typescript-engine.test.js +97 -0
  22. package/dist/tools/structural/engines/typescript/__tests__/typescript-engine.test.js.map +1 -0
  23. package/dist/tools/structural/engines/typescript/analyzer.js +433 -0
  24. package/dist/tools/structural/engines/typescript/analyzer.js.map +1 -0
  25. package/dist/tools/structural/engines/typescript/index.js +381 -0
  26. package/dist/tools/structural/engines/typescript/index.js.map +1 -0
  27. package/dist/tools/structural/engines/typescript/utils.js +279 -0
  28. package/dist/tools/structural/engines/typescript/utils.js.map +1 -0
  29. package/dist/tools/structural/index.js +248 -0
  30. package/dist/tools/structural/index.js.map +1 -0
  31. package/dist/tools/structural/types.js +18 -0
  32. package/dist/tools/structural/types.js.map +1 -0
  33. package/package.json +5 -1
  34. package/public/.well-known/mcp/manifest.json +6 -5
@@ -0,0 +1,381 @@
1
+ import { Node, SyntaxKind } from "ts-morph";
2
+ import path from "path";
3
+ import { ErrorCode, AnalysisError } from "../../types.js";
4
+ import { analyzeSourceFile } from "./analyzer.js";
5
+ import { createProject, findProjectRoot, findFiles, nodeToLocation, validatePath } from "./utils.js";
6
+ export class TypeScriptEngine {
7
+ constructor() {
8
+ this.projectCache = new Map();
9
+ }
10
+ /**
11
+ * Find all references to a symbol
12
+ */
13
+ async findReferences(symbolName, scope, options) {
14
+ const results = [];
15
+ try {
16
+ validatePath(scope);
17
+ // Determine if scope is a file or directory
18
+ const isFile = scope.endsWith('.ts') || scope.endsWith('.tsx') || scope.endsWith('.js') || scope.endsWith('.jsx');
19
+ const projectRoot = isFile ? findProjectRoot(scope) : scope;
20
+ const project = this.getOrCreateProject(projectRoot);
21
+ // Load files into project
22
+ const files = isFile ? [scope] : await this.getFilesInScope(scope, 500);
23
+ for (const file of files) {
24
+ try {
25
+ // Check if file is already in project
26
+ if (!project.getSourceFile(file)) {
27
+ project.addSourceFileAtPath(file);
28
+ }
29
+ }
30
+ catch (error) {
31
+ // Skip files that can't be loaded
32
+ }
33
+ }
34
+ // Find the symbol in the scope
35
+ const sourceFiles = isFile ? [project.getSourceFile(scope)] : project.getSourceFiles();
36
+ for (const sourceFile of sourceFiles) {
37
+ if (!sourceFile)
38
+ continue;
39
+ // Search for the symbol in this file
40
+ const symbolNodes = this.findSymbolInFile(sourceFile, symbolName);
41
+ for (const node of symbolNodes) {
42
+ try {
43
+ const identifier = Node.isIdentifier(node)
44
+ ? node
45
+ : node.getFirstDescendantByKind(SyntaxKind.Identifier);
46
+ if (identifier && Node.isIdentifier(identifier)) {
47
+ // Force program compilation before language service operations
48
+ const languageService = project.getLanguageService();
49
+ const refs = identifier.findReferences();
50
+ refs.forEach((ref) => {
51
+ ref.getReferences().forEach((refEntry) => {
52
+ try {
53
+ const refNode = refEntry.getNode();
54
+ const location = nodeToLocation(refNode);
55
+ // Skip if not including definitions and this is a definition
56
+ if (!options?.includeDefinition && refEntry.isDefinition()) {
57
+ return;
58
+ }
59
+ results.push({
60
+ file: location.file,
61
+ line: location.position.line,
62
+ column: location.position.character,
63
+ symbol: symbolName,
64
+ kind: this.getSymbolKindFromNode(refNode),
65
+ context: this.getContext(refNode)
66
+ });
67
+ }
68
+ catch (error) {
69
+ // Skip individual reference that fails
70
+ }
71
+ });
72
+ });
73
+ }
74
+ }
75
+ catch (error) {
76
+ // Skip nodes that fail to find references
77
+ }
78
+ }
79
+ }
80
+ return results.slice(0, options?.maxResults || 100);
81
+ }
82
+ catch (error) {
83
+ throw new AnalysisError({
84
+ code: ErrorCode.PARSE_ERROR,
85
+ message: `Failed to find references: ${error}`,
86
+ details: { symbolName, file: scope }
87
+ });
88
+ }
89
+ }
90
+ /**
91
+ * Find the definition of a symbol
92
+ */
93
+ async findDefinition(symbolName, scope, options) {
94
+ try {
95
+ validatePath(scope);
96
+ const isFile = scope.endsWith('.ts') || scope.endsWith('.tsx') || scope.endsWith('.js') || scope.endsWith('.jsx');
97
+ const projectRoot = isFile ? findProjectRoot(scope) : scope;
98
+ const project = this.getOrCreateProject(projectRoot);
99
+ const files = isFile ? [scope] : await this.getFilesInScope(scope, 500);
100
+ for (const file of files) {
101
+ try {
102
+ const sourceFile = project.addSourceFileAtPath(file);
103
+ const symbolNodes = this.findSymbolInFile(sourceFile, symbolName);
104
+ for (const node of symbolNodes) {
105
+ const symbol = node.getSymbol();
106
+ if (symbol) {
107
+ const declarations = symbol.getDeclarations();
108
+ if (declarations.length > 0) {
109
+ const declaration = declarations[0];
110
+ const location = nodeToLocation(declaration);
111
+ return {
112
+ file: location.file,
113
+ line: location.position.line,
114
+ column: location.position.character,
115
+ symbol: symbolName,
116
+ kind: this.getSymbolKindFromNode(declaration),
117
+ type: node.getType().getText(),
118
+ context: this.getContext(declaration)
119
+ };
120
+ }
121
+ }
122
+ }
123
+ }
124
+ catch (error) {
125
+ // Skip files that can't be loaded
126
+ }
127
+ }
128
+ return null;
129
+ }
130
+ catch (error) {
131
+ throw new AnalysisError({
132
+ code: ErrorCode.PARSE_ERROR,
133
+ message: `Failed to find definition: ${error}`,
134
+ details: { symbolName, file: scope }
135
+ });
136
+ }
137
+ }
138
+ /**
139
+ * Get dependencies of a file or symbol
140
+ */
141
+ async getDependencies(target, options) {
142
+ try {
143
+ validatePath(target);
144
+ const projectRoot = findProjectRoot(target);
145
+ const project = this.getOrCreateProject(projectRoot);
146
+ const sourceFile = project.addSourceFileAtPath(target);
147
+ const analysis = analyzeSourceFile(sourceFile, "dependencies", 2, false, false);
148
+ const results = [];
149
+ analysis.imports.forEach((imp, index) => {
150
+ results.push({
151
+ file: target,
152
+ line: index,
153
+ symbol: imp.moduleSpecifier,
154
+ kind: "module",
155
+ context: `imports: ${imp.symbols.join(", ")}`
156
+ });
157
+ });
158
+ return results.slice(0, options?.maxResults || 100);
159
+ }
160
+ catch (error) {
161
+ throw new AnalysisError({
162
+ code: ErrorCode.PARSE_ERROR,
163
+ message: `Failed to get dependencies: ${error}`,
164
+ details: { file: target }
165
+ });
166
+ }
167
+ }
168
+ /**
169
+ * Get dependency graph (for Architect role)
170
+ */
171
+ async getDependencyGraph(filePath, depth = 2) {
172
+ const visited = new Set();
173
+ const dependencies = [];
174
+ const circular = [];
175
+ const buildGraph = async (file, currentDepth, chain) => {
176
+ if (currentDepth > depth || visited.has(file)) {
177
+ // Check for circular dependency
178
+ if (chain.includes(file)) {
179
+ circular.push([...chain, file]);
180
+ }
181
+ return;
182
+ }
183
+ visited.add(file);
184
+ try {
185
+ const projectRoot = findProjectRoot(file);
186
+ const project = this.getOrCreateProject(projectRoot);
187
+ const sourceFile = project.addSourceFileAtPath(file);
188
+ const analysis = analyzeSourceFile(sourceFile, "dependencies", 1, false, false);
189
+ const imports = analysis.imports.map(imp => imp.moduleSpecifier);
190
+ dependencies.push({
191
+ file,
192
+ imports,
193
+ depth: currentDepth
194
+ });
195
+ // Recursively process imports
196
+ for (const imp of imports) {
197
+ if (imp.startsWith('.')) {
198
+ const resolvedPath = path.resolve(path.dirname(file), imp);
199
+ await buildGraph(resolvedPath, currentDepth + 1, [...chain, file]);
200
+ }
201
+ }
202
+ }
203
+ catch (error) {
204
+ // Skip files that can't be analyzed
205
+ }
206
+ };
207
+ await buildGraph(filePath, 0, []);
208
+ return {
209
+ root: filePath,
210
+ dependencies,
211
+ circular: circular.length > 0 ? circular.map(cycle => ({ cycle })) : undefined
212
+ };
213
+ }
214
+ /**
215
+ * Find architectural issues (for Architect role)
216
+ */
217
+ async findArchitecturalIssues(scope) {
218
+ const issues = [];
219
+ try {
220
+ const files = await this.getFilesInScope(scope, 500);
221
+ for (const file of files) {
222
+ const graph = await this.getDependencyGraph(file, 3);
223
+ // Check for circular dependencies
224
+ if (graph.circular && graph.circular.length > 0) {
225
+ issues.push({
226
+ type: "circular-dependency",
227
+ severity: "error",
228
+ message: `Circular dependency detected: ${graph.circular[0].cycle.join(" -> ")}`,
229
+ location: { file, position: { line: 0 } },
230
+ suggestion: "Consider breaking the circular dependency by introducing an interface or moving shared code to a separate module"
231
+ });
232
+ }
233
+ // Check for high coupling (too many imports)
234
+ const mainDep = graph.dependencies.find(d => d.file === file);
235
+ if (mainDep && mainDep.imports.length > 15) {
236
+ issues.push({
237
+ type: "high-coupling",
238
+ severity: "warning",
239
+ message: `High coupling detected: ${mainDep.imports.length} imports`,
240
+ location: { file, position: { line: 0 } },
241
+ suggestion: "Consider splitting this file into smaller, more focused modules"
242
+ });
243
+ }
244
+ }
245
+ return issues;
246
+ }
247
+ catch (error) {
248
+ return [];
249
+ }
250
+ }
251
+ /**
252
+ * Find unused exports (for Engineer role)
253
+ */
254
+ async findUnusedExports(scope) {
255
+ const unused = [];
256
+ try {
257
+ const files = await this.getFilesInScope(scope, 500);
258
+ const project = this.getOrCreateProject(scope);
259
+ // Load all files
260
+ for (const file of files) {
261
+ try {
262
+ project.addSourceFileAtPath(file);
263
+ }
264
+ catch (error) {
265
+ // Skip
266
+ }
267
+ }
268
+ for (const file of files) {
269
+ try {
270
+ const sourceFile = project.getSourceFile(file);
271
+ if (!sourceFile)
272
+ continue;
273
+ const analysis = analyzeSourceFile(sourceFile, "all", 1, false, false);
274
+ for (const exportName of analysis.exports) {
275
+ // Check if this export is used anywhere
276
+ const refs = await this.findReferences(exportName, scope, { maxResults: 2 });
277
+ if (refs.length === 0) {
278
+ unused.push({
279
+ name: exportName,
280
+ kind: "variable",
281
+ location: { file, position: { line: 0 } },
282
+ exportedFrom: file
283
+ });
284
+ }
285
+ }
286
+ }
287
+ catch (error) {
288
+ // Skip
289
+ }
290
+ }
291
+ return unused;
292
+ }
293
+ catch (error) {
294
+ return [];
295
+ }
296
+ }
297
+ /**
298
+ * Get refactor impact (for Engineer role)
299
+ */
300
+ async getRefactorImpact(symbol, scope) {
301
+ const refs = await this.findReferences(symbol, scope, { maxResults: 1000 });
302
+ const affectedFiles = [...new Set(refs.map(r => r.file))];
303
+ const testFiles = affectedFiles.filter(f => f.includes('test') || f.includes('spec'));
304
+ return {
305
+ symbol,
306
+ referenceCount: refs.length,
307
+ affectedFiles,
308
+ testFiles
309
+ };
310
+ }
311
+ // Private helper methods
312
+ getOrCreateProject(rootPath) {
313
+ if (this.projectCache.has(rootPath)) {
314
+ return this.projectCache.get(rootPath);
315
+ }
316
+ const project = createProject(rootPath, false);
317
+ this.projectCache.set(rootPath, project);
318
+ return project;
319
+ }
320
+ async getFilesInScope(scope, maxFiles = 500) {
321
+ const files = await findFiles("**/*.{ts,tsx,js,jsx}", scope);
322
+ // Sort by modification time (most recent first) for better cache hits
323
+ const filesWithStats = await Promise.all(files.map(async (file) => {
324
+ try {
325
+ const fs = await import('fs/promises');
326
+ const stats = await fs.stat(file);
327
+ return { file, mtime: stats.mtimeMs };
328
+ }
329
+ catch {
330
+ return { file, mtime: 0 };
331
+ }
332
+ }));
333
+ filesWithStats.sort((a, b) => b.mtime - a.mtime);
334
+ return filesWithStats.slice(0, maxFiles).map(f => f.file);
335
+ }
336
+ findSymbolInFile(sourceFile, symbolName) {
337
+ const nodes = [];
338
+ sourceFile.forEachDescendant(node => {
339
+ try {
340
+ if (node.getSymbol()?.getName() === symbolName) {
341
+ nodes.push(node);
342
+ }
343
+ }
344
+ catch (error) {
345
+ // Skip nodes where getSymbol() fails due to incomplete type information
346
+ // This can happen when not all dependencies are loaded in the project
347
+ }
348
+ });
349
+ return nodes;
350
+ }
351
+ getSymbolKindFromNode(node) {
352
+ if (Node.isClassDeclaration(node))
353
+ return "class";
354
+ if (Node.isInterfaceDeclaration(node))
355
+ return "interface";
356
+ if (Node.isEnumDeclaration(node))
357
+ return "enum";
358
+ if (Node.isFunctionDeclaration(node))
359
+ return "function";
360
+ if (Node.isMethodDeclaration(node))
361
+ return "method";
362
+ if (Node.isPropertyDeclaration(node))
363
+ return "property";
364
+ if (Node.isVariableDeclaration(node))
365
+ return "variable";
366
+ if (Node.isTypeAliasDeclaration(node))
367
+ return "type";
368
+ // Check for parameter using getKind()
369
+ if (node.getKind() === SyntaxKind.Parameter)
370
+ return "parameter";
371
+ return "variable";
372
+ }
373
+ getContext(node) {
374
+ const parent = node.getParent();
375
+ if (!parent)
376
+ return node.getText().substring(0, 100);
377
+ const parentText = parent.getText();
378
+ return parentText.substring(0, 100);
379
+ }
380
+ }
381
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/tools/structural/engines/typescript/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,279 @@
1
+ import { Project, SyntaxKind, ts } from "ts-morph";
2
+ import { glob } from "glob";
3
+ import { minimatch } from "minimatch";
4
+ import path from "path";
5
+ import * as fs from "fs";
6
+ import { cacheManager } from "../../cache.js";
7
+ // Re-export for backward compatibility
8
+ export const fileCache = {
9
+ get: (key) => {
10
+ const cached = cacheManager.getCachedFile(key);
11
+ return cached?.then(c => c?.sourceFile);
12
+ },
13
+ set: (key, value) => {
14
+ cacheManager.setCachedFile(key, value);
15
+ },
16
+ clear: () => cacheManager.clearFileCache()
17
+ };
18
+ export const symbolCache = {
19
+ get: (key) => cacheManager.getCachedSymbol(key),
20
+ set: (key, value) => cacheManager.setCachedSymbol(key, value),
21
+ clear: () => cacheManager.clearSymbolCache()
22
+ };
23
+ export const performanceConfig = {
24
+ maxMemoryMB: 2048,
25
+ batchSize: 50,
26
+ cacheStrategy: "memory",
27
+ gcInterval: 100
28
+ };
29
+ export const timeoutLimits = {
30
+ singleFile: 5000,
31
+ symbolSearch: 10000,
32
+ projectAnalysis: 60000,
33
+ impactAnalysis: 30000,
34
+ };
35
+ export const securityConfig = {
36
+ allowedPaths: ["./src", "./tests", "./lib"],
37
+ excludePatterns: ["**/node_modules/**", "**/.git/**", "**/dist/**", "**/build/**"],
38
+ maxFileSize: 5 * 1024 * 1024,
39
+ maxPathDepth: 10,
40
+ };
41
+ export function findProjectRoot(filePath) {
42
+ let currentDir = path.dirname(path.resolve(filePath));
43
+ // First priority: look for tsconfig.json (closest to the file)
44
+ let tsConfigDir = null;
45
+ let tempDir = currentDir;
46
+ while (tempDir !== path.dirname(tempDir)) {
47
+ if (fs.existsSync(path.join(tempDir, 'tsconfig.json'))) {
48
+ tsConfigDir = tempDir;
49
+ break;
50
+ }
51
+ tempDir = path.dirname(tempDir);
52
+ }
53
+ // If we found a tsconfig.json, use it
54
+ if (tsConfigDir) {
55
+ return tsConfigDir;
56
+ }
57
+ // Fallback: look for package.json or .git
58
+ while (currentDir !== path.dirname(currentDir)) {
59
+ if (fs.existsSync(path.join(currentDir, 'package.json')) ||
60
+ fs.existsSync(path.join(currentDir, '.git'))) {
61
+ return currentDir;
62
+ }
63
+ currentDir = path.dirname(currentDir);
64
+ }
65
+ // Final fallback to the directory containing the file
66
+ return path.dirname(path.resolve(filePath));
67
+ }
68
+ export function createProject(rootPath, includeNodeModules = false) {
69
+ const workingDir = rootPath || process.cwd();
70
+ // Check if there's a tsconfig.json file
71
+ const tsConfigPath = path.join(workingDir, 'tsconfig.json');
72
+ const hasTsConfig = fs.existsSync(tsConfigPath);
73
+ // If we have a tsconfig and we're not doing symbol analysis (includeNodeModules), use it
74
+ if (hasTsConfig && !includeNodeModules) {
75
+ try {
76
+ const project = new Project({
77
+ tsConfigFilePath: tsConfigPath,
78
+ skipAddingFilesFromTsConfig: true,
79
+ useInMemoryFileSystem: false,
80
+ skipFileDependencyResolution: false // Enable for language service operations
81
+ });
82
+ return project;
83
+ }
84
+ catch (error) {
85
+ // If tsconfig parsing fails, fall back to default options
86
+ console.error('Failed to parse tsconfig.json, using defaults:', error);
87
+ }
88
+ }
89
+ // Use default compiler options for symbol analysis or when tsconfig is not available
90
+ const baseOptions = {
91
+ target: ts.ScriptTarget.ES2022,
92
+ module: ts.ModuleKind.ESNext,
93
+ moduleResolution: ts.ModuleResolutionKind.Bundler,
94
+ allowJs: true,
95
+ declaration: true,
96
+ esModuleInterop: true,
97
+ allowSyntheticDefaultImports: true,
98
+ strict: false, // Disable strict mode for better compatibility
99
+ skipLibCheck: true,
100
+ noEmit: true,
101
+ resolveJsonModule: true,
102
+ isolatedModules: true,
103
+ allowImportingTsExtensions: false,
104
+ noResolve: false,
105
+ jsx: ts.JsxEmit.ReactJSX,
106
+ };
107
+ if (includeNodeModules) {
108
+ const projectRoot = workingDir;
109
+ baseOptions.typeRoots = [
110
+ path.join(projectRoot, "node_modules/@types"),
111
+ path.join(projectRoot, "node_modules")
112
+ ];
113
+ baseOptions.baseUrl = projectRoot;
114
+ baseOptions.paths = {
115
+ "*": ["node_modules/*", "node_modules/@types/*"]
116
+ };
117
+ }
118
+ const project = new Project({
119
+ compilerOptions: baseOptions,
120
+ skipAddingFilesFromTsConfig: true,
121
+ useInMemoryFileSystem: false,
122
+ skipFileDependencyResolution: false // Enable for language service operations
123
+ });
124
+ return project;
125
+ }
126
+ export function findClosestTsConfig(filePath) {
127
+ let currentDir = path.dirname(path.resolve(filePath));
128
+ // Walk up from the target path looking only for tsconfig.json
129
+ while (currentDir !== path.dirname(currentDir)) {
130
+ const tsConfigPath = path.join(currentDir, 'tsconfig.json');
131
+ if (fs.existsSync(tsConfigPath)) {
132
+ return currentDir;
133
+ }
134
+ currentDir = path.dirname(currentDir);
135
+ }
136
+ return null;
137
+ }
138
+ export function nodeToLocation(node) {
139
+ const sourceFile = node.getSourceFile();
140
+ const start = sourceFile.getLineAndColumnAtPos(node.getStart());
141
+ const end = sourceFile.getLineAndColumnAtPos(node.getEnd());
142
+ return {
143
+ file: sourceFile.getFilePath(),
144
+ position: {
145
+ line: start.line - 1,
146
+ character: start.column - 1
147
+ },
148
+ endPosition: {
149
+ line: end.line - 1,
150
+ character: end.column - 1
151
+ }
152
+ };
153
+ }
154
+ export function positionToOffset(sourceFile, position) {
155
+ const character = position.character ?? 0;
156
+ const pos = sourceFile.compilerNode.getPositionOfLineAndCharacter(position.line, character);
157
+ return pos;
158
+ }
159
+ export function getSymbolKind(node) {
160
+ const kind = node.getKind();
161
+ switch (kind) {
162
+ case SyntaxKind.ClassDeclaration:
163
+ return "class";
164
+ case SyntaxKind.InterfaceDeclaration:
165
+ return "interface";
166
+ case SyntaxKind.EnumDeclaration:
167
+ return "enum";
168
+ case SyntaxKind.FunctionDeclaration:
169
+ case SyntaxKind.FunctionExpression:
170
+ case SyntaxKind.ArrowFunction:
171
+ return "function";
172
+ case SyntaxKind.MethodDeclaration:
173
+ case SyntaxKind.MethodSignature:
174
+ return "method";
175
+ case SyntaxKind.PropertyDeclaration:
176
+ case SyntaxKind.PropertySignature:
177
+ return "property";
178
+ case SyntaxKind.VariableDeclaration:
179
+ return "variable";
180
+ case SyntaxKind.Parameter:
181
+ return "parameter";
182
+ case SyntaxKind.TypeAliasDeclaration:
183
+ return "type";
184
+ case SyntaxKind.ModuleDeclaration:
185
+ return "module";
186
+ case SyntaxKind.NamespaceKeyword:
187
+ return "namespace";
188
+ default:
189
+ return "variable";
190
+ }
191
+ }
192
+ export async function findFiles(pattern, basePath = process.cwd()) {
193
+ const files = await glob(pattern, {
194
+ cwd: basePath,
195
+ absolute: true,
196
+ ignore: securityConfig.excludePatterns,
197
+ });
198
+ return files.filter(file => {
199
+ const relativePath = path.relative(basePath, file);
200
+ const depth = relativePath.split(path.sep).length;
201
+ return depth <= securityConfig.maxPathDepth;
202
+ });
203
+ }
204
+ export function matchesScope(filePath, scope) {
205
+ if (!scope)
206
+ return true;
207
+ if (scope.fileTypes) {
208
+ const ext = path.extname(filePath);
209
+ if (!scope.fileTypes.includes(ext))
210
+ return false;
211
+ }
212
+ if (scope.excludeFiles) {
213
+ for (const pattern of scope.excludeFiles) {
214
+ if (minimatch(filePath, pattern))
215
+ return false;
216
+ }
217
+ }
218
+ if (scope.includeFiles) {
219
+ for (const pattern of scope.includeFiles) {
220
+ if (minimatch(filePath, pattern))
221
+ return true;
222
+ }
223
+ return false;
224
+ }
225
+ return true;
226
+ }
227
+ export function validatePath(filePath, allowNodeModules = false) {
228
+ // Path validation removed - allow analyzing files from any location
229
+ return;
230
+ }
231
+ export function getNodeComplexity(node) {
232
+ let complexity = 1;
233
+ node.forEachDescendant(child => {
234
+ const kind = child.getKind();
235
+ if (kind === SyntaxKind.IfStatement ||
236
+ kind === SyntaxKind.ForStatement ||
237
+ kind === SyntaxKind.ForInStatement ||
238
+ kind === SyntaxKind.ForOfStatement ||
239
+ kind === SyntaxKind.WhileStatement ||
240
+ kind === SyntaxKind.DoStatement ||
241
+ kind === SyntaxKind.ConditionalExpression ||
242
+ kind === SyntaxKind.CatchClause ||
243
+ kind === SyntaxKind.CaseClause ||
244
+ kind === SyntaxKind.BinaryExpression) {
245
+ complexity++;
246
+ }
247
+ });
248
+ return complexity;
249
+ }
250
+ export function getTypeString(type, maxLength = 500) {
251
+ const typeText = type.getText();
252
+ if (typeText.length > maxLength) {
253
+ return typeText.substring(0, maxLength - 3) + "...";
254
+ }
255
+ return typeText;
256
+ }
257
+ export async function checkMemoryUsage() {
258
+ const usage = process.memoryUsage();
259
+ const heapUsedMB = usage.heapUsed / 1024 / 1024;
260
+ const cacheMemoryMB = cacheManager.getMemoryUsage() / 1024 / 1024;
261
+ if (heapUsedMB + cacheMemoryMB > performanceConfig.maxMemoryMB * 0.9) {
262
+ if (global.gc) {
263
+ global.gc();
264
+ }
265
+ await cacheManager.clearAll();
266
+ }
267
+ }
268
+ export class TimeoutError extends Error {
269
+ constructor(operation, limit) {
270
+ super(`Operation '${operation}' timed out after ${limit}ms`);
271
+ }
272
+ }
273
+ export function withTimeout(promise, operation, limit) {
274
+ return Promise.race([
275
+ promise,
276
+ new Promise((_, reject) => setTimeout(() => reject(new TimeoutError(operation, limit)), limit))
277
+ ]);
278
+ }
279
+ //# sourceMappingURL=utils.js.map