code-auditor-mcp 1.1.0 → 1.2.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/dist/mcp.js CHANGED
@@ -9,8 +9,7 @@ import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprot
9
9
  console.error(chalk.blue('[INFO]'), 'MCP SDK loaded');
10
10
  import { createAuditRunner } from './auditRunner.js';
11
11
  console.error(chalk.blue('[INFO]'), 'Audit runner loaded');
12
- import { registerFunctions, searchFunctions, getIndexStats, findDefinition, clearIndex, syncFileIndex } from './codeIndexService.js';
13
- import { scanFunctionsInFile, scanFunctionsInDirectory } from './functionScanner.js';
12
+ import { searchFunctions, findDefinition, syncFileIndex } from './codeIndexService.js';
14
13
  import { ConfigGeneratorFactory } from './generators/ConfigGeneratorFactory.js';
15
14
  import { DEFAULT_SERVER_URL } from './constants.js';
16
15
  console.error(chalk.blue('[INFO]'), 'Code index service loaded');
@@ -19,19 +18,20 @@ import fs from 'node:fs/promises';
19
18
  import { CodeIndexDB } from './codeIndexDB.js';
20
19
  console.error(chalk.blue('[INFO]'), 'All modules loaded successfully');
21
20
  const tools = [
21
+ // Core Audit Tools
22
22
  {
23
- name: 'audit_run',
24
- description: 'Run a comprehensive code audit on the specified codebase',
23
+ name: 'audit',
24
+ description: 'Run a comprehensive code audit on files or directories',
25
25
  parameters: [
26
26
  {
27
27
  name: 'path',
28
28
  type: 'string',
29
29
  required: false,
30
- description: 'The directory path to audit (defaults to current directory)',
30
+ description: 'The file or directory path to audit (defaults to current directory)',
31
31
  default: process.cwd(),
32
32
  },
33
33
  {
34
- name: 'enabledAnalyzers',
34
+ name: 'analyzers',
35
35
  type: 'array',
36
36
  required: false,
37
37
  description: 'List of analyzers to run (solid, dry, security, component, data-access)',
@@ -45,29 +45,17 @@ const tools = [
45
45
  default: 'warning',
46
46
  enum: ['info', 'warning', 'critical'],
47
47
  },
48
- ],
49
- },
50
- {
51
- name: 'audit_analyze_file',
52
- description: 'Analyze a specific file for code quality issues',
53
- parameters: [
54
48
  {
55
- name: 'filePath',
56
- type: 'string',
57
- required: true,
58
- description: 'The file path to analyze',
59
- },
60
- {
61
- name: 'analyzers',
62
- type: 'array',
49
+ name: 'indexFunctions',
50
+ type: 'boolean',
63
51
  required: false,
64
- description: 'Specific analyzers to run on this file',
65
- default: ['solid', 'dry', 'security'],
52
+ description: 'Automatically index functions during audit',
53
+ default: true,
66
54
  },
67
55
  ],
68
56
  },
69
57
  {
70
- name: 'audit_check_health',
58
+ name: 'audit_health',
71
59
  description: 'Quick health check of a codebase with key metrics',
72
60
  parameters: [
73
61
  {
@@ -84,41 +72,25 @@ const tools = [
84
72
  description: 'Health score threshold (0-100) for pass/fail',
85
73
  default: 70,
86
74
  },
87
- ],
88
- },
89
- {
90
- name: 'audit_list_analyzers',
91
- description: 'List all available code analyzers and their capabilities',
92
- parameters: [],
93
- },
94
- {
95
- name: 'register_functions',
96
- description: 'Register functions with metadata for code indexing',
97
- parameters: [
98
75
  {
99
- name: 'functions',
100
- type: 'array',
101
- required: true,
102
- description: 'Array of function objects with metadata',
103
- },
104
- {
105
- name: 'overwrite',
76
+ name: 'indexFunctions',
106
77
  type: 'boolean',
107
78
  required: false,
108
- description: 'Whether to overwrite existing entries',
109
- default: false,
79
+ description: 'Automatically index functions during health check',
80
+ default: true,
110
81
  },
111
82
  ],
112
83
  },
84
+ // Code Index Tools
113
85
  {
114
- name: 'search_functions',
115
- description: 'Search registered functions by various criteria',
86
+ name: 'search_code',
87
+ description: 'Search indexed functions with natural language queries',
116
88
  parameters: [
117
89
  {
118
90
  name: 'query',
119
91
  type: 'string',
120
92
  required: true,
121
- description: 'Search query (supports full-text search)',
93
+ description: 'Search query (supports natural language)',
122
94
  },
123
95
  {
124
96
  name: 'filters',
@@ -142,41 +114,15 @@ const tools = [
142
114
  },
143
115
  ],
144
116
  },
145
- {
146
- name: 'index_functions',
147
- description: 'Index functions from TypeScript/JavaScript files',
148
- parameters: [
149
- {
150
- name: 'path',
151
- type: 'string',
152
- required: true,
153
- description: 'File or directory path to index',
154
- },
155
- {
156
- name: 'recursive',
157
- type: 'boolean',
158
- required: false,
159
- description: 'Recursively index directories',
160
- default: true,
161
- },
162
- {
163
- name: 'fileTypes',
164
- type: 'array',
165
- required: false,
166
- description: 'File extensions to process',
167
- default: ['.ts', '.tsx', '.js', '.jsx'],
168
- },
169
- ],
170
- },
171
117
  {
172
118
  name: 'find_definition',
173
- description: 'Find the definition of a specific function',
119
+ description: 'Find the exact definition of a specific function',
174
120
  parameters: [
175
121
  {
176
122
  name: 'name',
177
123
  type: 'string',
178
124
  required: true,
179
- description: 'Function name to search for',
125
+ description: 'Function name to find',
180
126
  },
181
127
  {
182
128
  name: 'filePath',
@@ -187,39 +133,35 @@ const tools = [
187
133
  ],
188
134
  },
189
135
  {
190
- name: 'get_index_stats',
191
- description: 'Get statistics about the code index',
192
- parameters: [],
193
- },
194
- {
195
- name: 'clear_index',
196
- description: 'Clear all indexed functions',
136
+ name: 'sync_index',
137
+ description: 'Synchronize, cleanup, or reset the code index',
197
138
  parameters: [
198
139
  {
199
- name: 'confirm',
200
- type: 'boolean',
140
+ name: 'mode',
141
+ type: 'string',
201
142
  required: false,
202
- description: 'Confirm clearing the index',
203
- default: false,
143
+ description: 'Operation mode: sync (update), cleanup (remove stale), or reset (clear all)',
144
+ default: 'sync',
145
+ enum: ['sync', 'cleanup', 'reset'],
146
+ },
147
+ {
148
+ name: 'path',
149
+ type: 'string',
150
+ required: false,
151
+ description: 'Optional specific path to sync',
204
152
  },
205
153
  ],
206
154
  },
155
+ // AI Configuration Tool
207
156
  {
208
- name: 'generate_ai_configs',
157
+ name: 'generate_ai_config',
209
158
  description: 'Generate configuration files for AI coding assistants',
210
159
  parameters: [
211
160
  {
212
161
  name: 'tools',
213
162
  type: 'array',
214
163
  required: true,
215
- description: 'AI tools to generate configs for (cursor, continue, copilot, claude, etc.)',
216
- },
217
- {
218
- name: 'serverUrl',
219
- type: 'string',
220
- required: false,
221
- description: 'MCP server URL',
222
- default: DEFAULT_SERVER_URL,
164
+ description: 'AI tools to configure (cursor, continue, copilot, claude, zed, windsurf, cody, aider, cline, pearai)',
223
165
  },
224
166
  {
225
167
  name: 'outputDir',
@@ -228,60 +170,8 @@ const tools = [
228
170
  description: 'Output directory for configuration files',
229
171
  default: '.',
230
172
  },
231
- {
232
- name: 'overwrite',
233
- type: 'boolean',
234
- required: false,
235
- description: 'Overwrite existing files',
236
- default: false,
237
- },
238
- ],
239
- },
240
- {
241
- name: 'list_ai_tools',
242
- description: 'List all supported AI tools for configuration generation',
243
- parameters: [],
244
- },
245
- {
246
- name: 'get_ai_tool_info',
247
- description: 'Get detailed information about a specific AI tool',
248
- parameters: [
249
- {
250
- name: 'tool',
251
- type: 'string',
252
- required: true,
253
- description: 'AI tool name (cursor, continue, copilot, etc.)',
254
- },
255
173
  ],
256
174
  },
257
- {
258
- name: 'validate_ai_config',
259
- description: 'Validate a generated AI tool configuration',
260
- parameters: [
261
- {
262
- name: 'tool',
263
- type: 'string',
264
- required: true,
265
- description: 'AI tool name',
266
- },
267
- {
268
- name: 'config',
269
- type: 'object',
270
- required: true,
271
- description: 'Configuration object to validate',
272
- },
273
- ],
274
- },
275
- {
276
- name: 'bulk_cleanup',
277
- description: 'Remove index entries for deleted files',
278
- parameters: [],
279
- },
280
- {
281
- name: 'deep_sync',
282
- description: 'Deep synchronize all indexed files to update signatures and remove stale entries',
283
- parameters: [],
284
- },
285
175
  ];
286
176
  async function startMcpServer() {
287
177
  console.error(chalk.blue('[INFO]'), 'Starting Code Auditor MCP Server...');
@@ -326,16 +216,46 @@ async function startMcpServer() {
326
216
  try {
327
217
  let result;
328
218
  switch (name) {
329
- case 'audit_run': {
219
+ case 'audit': {
330
220
  const auditPath = path.resolve(args.path || process.cwd());
221
+ const indexFunctions = args.indexFunctions !== false; // Default true
222
+ // Check if path is a file or directory
223
+ const stats = await fs.stat(auditPath).catch(() => null);
224
+ const isFile = stats?.isFile() || false;
331
225
  const options = {
332
- projectRoot: auditPath,
333
- enabledAnalyzers: args.enabledAnalyzers || ['solid', 'dry', 'security'],
226
+ projectRoot: isFile ? path.dirname(auditPath) : auditPath,
227
+ enabledAnalyzers: args.analyzers || ['solid', 'dry', 'security'],
334
228
  minSeverity: (args.minSeverity || 'warning'),
335
229
  verbose: false,
230
+ indexFunctions,
231
+ ...(isFile && { includePaths: [auditPath] }),
336
232
  };
337
233
  const runner = createAuditRunner(options);
338
234
  const auditResult = await runner.run();
235
+ // Handle function indexing if enabled and functions were collected
236
+ let indexingResult = null;
237
+ if (indexFunctions && auditResult.metadata.fileToFunctionsMap) {
238
+ try {
239
+ const syncStats = { added: 0, updated: 0, removed: 0 };
240
+ // Sync each file's functions to handle additions, updates, and removals
241
+ for (const [filePath, functions] of Object.entries(auditResult.metadata.fileToFunctionsMap)) {
242
+ const fileStats = await syncFileIndex(filePath, functions);
243
+ syncStats.added += fileStats.added;
244
+ syncStats.updated += fileStats.updated;
245
+ syncStats.removed += fileStats.removed;
246
+ }
247
+ indexingResult = {
248
+ success: true,
249
+ registered: syncStats.added + syncStats.updated,
250
+ failed: 0,
251
+ syncStats
252
+ };
253
+ console.error(chalk.blue('[INFO]'), `Synced functions: ${syncStats.added} added, ${syncStats.updated} updated, ${syncStats.removed} removed`);
254
+ }
255
+ catch (error) {
256
+ console.error(chalk.yellow('[WARN]'), 'Failed to sync functions:', error);
257
+ }
258
+ }
339
259
  // Format for MCP
340
260
  result = {
341
261
  summary: {
@@ -349,46 +269,47 @@ async function startMcpServer() {
349
269
  },
350
270
  violations: getAllViolations(auditResult).slice(0, 100), // Limit to first 100
351
271
  recommendations: auditResult.recommendations,
272
+ ...(indexingResult && { functionIndexing: indexingResult }),
352
273
  };
353
274
  break;
354
275
  }
355
- case 'audit_analyze_file': {
356
- const absolutePath = path.resolve(args.filePath);
357
- await fs.access(absolutePath); // Check file exists
358
- const options = {
359
- projectRoot: path.dirname(absolutePath),
360
- enabledAnalyzers: args.analyzers || ['solid', 'dry', 'security'],
361
- includePaths: [absolutePath],
362
- verbose: false,
363
- };
364
- const runner = createAuditRunner(options);
365
- const auditResult = await runner.run();
366
- const fileViolations = getAllViolations(auditResult).filter(v => v.file === absolutePath);
367
- result = {
368
- file: absolutePath,
369
- violations: fileViolations,
370
- summary: {
371
- total: fileViolations.length,
372
- bySeverity: fileViolations
373
- .reduce((acc, v) => {
374
- acc[v.severity] = (acc[v.severity] || 0) + 1;
375
- return acc;
376
- }, {}),
377
- },
378
- };
379
- break;
380
- }
381
- case 'audit_check_health': {
276
+ case 'audit_health': {
382
277
  const auditPath = path.resolve(args.path || process.cwd());
383
278
  const threshold = args.threshold || 70;
279
+ const indexFunctions = args.indexFunctions !== false; // Default true
384
280
  const runner = createAuditRunner({
385
281
  projectRoot: auditPath,
386
282
  enabledAnalyzers: ['solid', 'dry', 'security'],
387
283
  minSeverity: 'warning',
388
284
  verbose: false,
285
+ indexFunctions, // Pass the flag to the runner
389
286
  });
390
287
  const auditResult = await runner.run();
391
288
  const healthScore = calculateHealthScore(auditResult);
289
+ // Handle function indexing if enabled and functions were collected
290
+ let indexingResult = null;
291
+ if (indexFunctions && auditResult.metadata.fileToFunctionsMap) {
292
+ try {
293
+ const syncStats = { added: 0, updated: 0, removed: 0 };
294
+ // Sync each file's functions to handle additions, updates, and removals
295
+ for (const [filePath, functions] of Object.entries(auditResult.metadata.fileToFunctionsMap)) {
296
+ const fileStats = await syncFileIndex(filePath, functions);
297
+ syncStats.added += fileStats.added;
298
+ syncStats.updated += fileStats.updated;
299
+ syncStats.removed += fileStats.removed;
300
+ }
301
+ indexingResult = {
302
+ success: true,
303
+ registered: syncStats.added + syncStats.updated,
304
+ failed: 0,
305
+ syncStats
306
+ };
307
+ console.error(chalk.blue('[INFO]'), `Synced functions: ${syncStats.added} added, ${syncStats.updated} updated, ${syncStats.removed} removed`);
308
+ }
309
+ catch (error) {
310
+ console.error(chalk.yellow('[WARN]'), 'Failed to sync functions:', error);
311
+ }
312
+ }
392
313
  result = {
393
314
  healthScore,
394
315
  threshold,
@@ -401,82 +322,11 @@ async function startMcpServer() {
401
322
  warningViolations: auditResult.summary.warnings,
402
323
  },
403
324
  recommendation: getHealthRecommendation(healthScore, auditResult),
325
+ ...(indexingResult && { functionIndexing: indexingResult }),
404
326
  };
405
327
  break;
406
328
  }
407
- case 'audit_list_analyzers': {
408
- result = {
409
- analyzers: [
410
- {
411
- id: 'solid',
412
- name: 'SOLID Analyzer',
413
- description: 'Checks adherence to SOLID principles',
414
- checks: [
415
- 'Single Responsibility violations',
416
- 'Open/Closed violations',
417
- 'Liskov Substitution issues',
418
- 'Interface Segregation problems',
419
- 'Dependency Inversion violations',
420
- ],
421
- },
422
- {
423
- id: 'dry',
424
- name: 'DRY Analyzer',
425
- description: 'Identifies code duplication',
426
- checks: [
427
- 'Exact code duplicates',
428
- 'Similar code patterns',
429
- 'Duplicate imports',
430
- 'Repeated string literals',
431
- ],
432
- },
433
- {
434
- id: 'security',
435
- name: 'Security Analyzer',
436
- description: 'Verifies security patterns',
437
- checks: [
438
- 'Missing authentication',
439
- 'Authorization issues',
440
- 'SQL injection risks',
441
- 'Unvalidated inputs',
442
- ],
443
- },
444
- {
445
- id: 'component',
446
- name: 'Component Analyzer',
447
- description: 'Analyzes UI components',
448
- checks: [
449
- 'Missing error boundaries',
450
- 'Complex render methods',
451
- 'Deep nesting',
452
- 'Performance issues',
453
- ],
454
- },
455
- {
456
- id: 'data-access',
457
- name: 'Data Access Analyzer',
458
- description: 'Reviews database patterns',
459
- checks: [
460
- 'N+1 queries',
461
- 'Missing transactions',
462
- 'Direct DB access in UI',
463
- 'Performance issues',
464
- ],
465
- },
466
- ],
467
- };
468
- break;
469
- }
470
- case 'register_functions': {
471
- const functions = args.functions;
472
- const overwrite = args.overwrite || false;
473
- if (!Array.isArray(functions)) {
474
- throw new Error('functions must be an array');
475
- }
476
- result = await registerFunctions(functions, { overwrite });
477
- break;
478
- }
479
- case 'search_functions': {
329
+ case 'search_code': {
480
330
  const query = args.query;
481
331
  const filters = args.filters;
482
332
  const limit = args.limit || 50;
@@ -493,36 +343,6 @@ async function startMcpServer() {
493
343
  });
494
344
  break;
495
345
  }
496
- case 'index_functions': {
497
- const targetPath = path.resolve(args.path);
498
- const recursive = args.recursive !== false;
499
- const fileTypes = args.fileTypes || ['.ts', '.tsx', '.js', '.jsx'];
500
- const stats = await fs.stat(targetPath);
501
- if (stats.isFile()) {
502
- // For single files, use sync to handle additions/updates/removals
503
- const functions = await scanFunctionsInFile(targetPath);
504
- const syncResult = await syncFileIndex(targetPath, functions);
505
- result = {
506
- success: true,
507
- registered: syncResult.added + syncResult.updated,
508
- failed: 0,
509
- path: targetPath,
510
- totalScanned: functions.length,
511
- syncStats: syncResult
512
- };
513
- }
514
- else {
515
- // For directories, use regular registration (could be improved later)
516
- const functions = await scanFunctionsInDirectory(targetPath, { recursive, fileTypes });
517
- const registerResult = await registerFunctions(functions);
518
- result = {
519
- ...registerResult,
520
- path: targetPath,
521
- totalScanned: functions.length,
522
- };
523
- }
524
- break;
525
- }
526
346
  case 'find_definition': {
527
347
  const name = args.name;
528
348
  const filePath = args.filePath;
@@ -533,20 +353,7 @@ async function startMcpServer() {
533
353
  result = definition || { error: 'Function not found' };
534
354
  break;
535
355
  }
536
- case 'get_index_stats': {
537
- result = await getIndexStats();
538
- break;
539
- }
540
- case 'clear_index': {
541
- const confirm = args.confirm;
542
- if (!confirm) {
543
- throw new Error('Please set confirm: true to clear the index');
544
- }
545
- await clearIndex();
546
- result = { message: 'Index cleared successfully' };
547
- break;
548
- }
549
- case 'generate_ai_configs': {
356
+ case 'generate_ai_config': {
550
357
  const tools = args.tools;
551
358
  const serverUrl = args.serverUrl || DEFAULT_SERVER_URL;
552
359
  const outputDir = args.outputDir || '.';
@@ -607,121 +414,63 @@ async function startMcpServer() {
607
414
  };
608
415
  break;
609
416
  }
610
- case 'list_ai_tools': {
611
- const factory = new ConfigGeneratorFactory();
612
- const toolInfo = factory.getToolInfo();
613
- result = {
614
- tools: toolInfo,
615
- totalCount: toolInfo.length,
616
- categories: {
617
- native_mcp: toolInfo.filter(t => !t.requiresAuth).map(t => t.name),
618
- api_based: toolInfo.filter(t => t.requiresAuth).map(t => t.name)
417
+ case 'sync_index': {
418
+ const mode = args.mode || 'sync';
419
+ const targetPath = args.path;
420
+ const db = CodeIndexDB.getInstance();
421
+ await db.initialize();
422
+ switch (mode) {
423
+ case 'cleanup': {
424
+ const cleanupResult = await db.bulkCleanup();
425
+ result = {
426
+ mode: 'cleanup',
427
+ success: true,
428
+ scannedFiles: cleanupResult.scannedCount,
429
+ removedEntries: cleanupResult.removedCount,
430
+ removedFiles: cleanupResult.removedFiles,
431
+ errors: cleanupResult.errors,
432
+ message: `Cleaned up ${cleanupResult.removedCount} entries from ${cleanupResult.removedFiles.length} deleted files`
433
+ };
434
+ break;
619
435
  }
620
- };
621
- break;
622
- }
623
- case 'get_ai_tool_info': {
624
- const toolName = args.tool;
625
- if (!toolName) {
626
- throw new Error('tool parameter is required');
627
- }
628
- const factory = new ConfigGeneratorFactory();
629
- const generator = factory.createGenerator(toolName);
630
- if (!generator) {
631
- throw new Error(`Unknown tool: ${toolName}`);
632
- }
633
- const config = generator.generateConfig();
634
- result = {
635
- name: toolName,
636
- displayName: generator.getToolName(),
637
- requiresAuth: generator.requiresAuth(),
638
- defaultApiKey: generator.getDefaultApiKey(),
639
- configFilename: generator.getFilename(),
640
- instructions: generator.getInstructions(),
641
- sampleConfig: JSON.parse(config.content)
642
- };
643
- break;
644
- }
645
- case 'validate_ai_config': {
646
- const toolName = args.tool;
647
- const config = args.config;
648
- if (!toolName) {
649
- throw new Error('tool parameter is required');
650
- }
651
- if (!config) {
652
- throw new Error('config parameter is required');
653
- }
654
- const factory = new ConfigGeneratorFactory();
655
- const generator = factory.createGenerator(toolName);
656
- if (!generator) {
657
- throw new Error(`Unknown tool: ${toolName}`);
658
- }
659
- // Generate reference config to compare structure
660
- const referenceConfig = generator.generateConfig();
661
- const reference = JSON.parse(referenceConfig.content);
662
- // Basic validation - check if main structure matches
663
- const errors = [];
664
- const validateObject = (ref, actual, path = '') => {
665
- for (const key in ref) {
666
- const currentPath = path ? `${path}.${key}` : key;
667
- if (!(key in actual)) {
668
- errors.push(`Missing required field: ${currentPath}`);
436
+ case 'reset': {
437
+ await db.clearIndex();
438
+ result = {
439
+ mode: 'reset',
440
+ success: true,
441
+ message: 'Index cleared successfully'
442
+ };
443
+ break;
444
+ }
445
+ case 'sync':
446
+ default: {
447
+ if (targetPath) {
448
+ // Sync specific file
449
+ const syncResult = await db.synchronizeFile(path.resolve(targetPath));
450
+ result = {
451
+ mode: 'sync',
452
+ success: true,
453
+ path: targetPath,
454
+ ...(syncResult || { message: 'File not found' })
455
+ };
669
456
  }
670
- else if (typeof ref[key] === 'object' && ref[key] !== null && !Array.isArray(ref[key])) {
671
- if (typeof actual[key] === 'object' && actual[key] !== null) {
672
- validateObject(ref[key], actual[key], currentPath);
673
- }
674
- else {
675
- errors.push(`Field ${currentPath} should be an object`);
676
- }
457
+ else {
458
+ // Deep sync all files
459
+ const syncResult = await db.deepSync();
460
+ result = {
461
+ mode: 'sync',
462
+ success: true,
463
+ syncedFiles: syncResult.syncedFiles,
464
+ addedFunctions: syncResult.addedFunctions,
465
+ updatedFunctions: syncResult.updatedFunctions,
466
+ removedFunctions: syncResult.removedFunctions,
467
+ errors: syncResult.errors,
468
+ message: `Synced ${syncResult.syncedFiles} files: ${syncResult.addedFunctions} added, ${syncResult.updatedFunctions} updated, ${syncResult.removedFunctions} removed`
469
+ };
677
470
  }
471
+ break;
678
472
  }
679
- };
680
- validateObject(reference, config);
681
- result = {
682
- valid: errors.length === 0,
683
- tool: toolName,
684
- errors: errors.length > 0 ? errors : undefined,
685
- warnings: [] // Could add warnings for extra fields, deprecated settings, etc.
686
- };
687
- break;
688
- }
689
- case 'bulk_cleanup': {
690
- const db = CodeIndexDB.getInstance();
691
- await db.initialize();
692
- const cleanupResult = await db.bulkCleanup();
693
- result = {
694
- success: true,
695
- scannedFiles: cleanupResult.scannedCount,
696
- removedEntries: cleanupResult.removedCount,
697
- removedFiles: cleanupResult.removedFiles,
698
- errors: cleanupResult.errors,
699
- message: `Cleaned up ${cleanupResult.removedCount} entries from ${cleanupResult.removedFiles.length} deleted files`
700
- };
701
- break;
702
- }
703
- case 'deep_sync': {
704
- const db = CodeIndexDB.getInstance();
705
- await db.initialize();
706
- // Progress tracking
707
- const progressUpdates = [];
708
- const syncResult = await db.deepSync((progress) => {
709
- progressUpdates.push({
710
- current: progress.current,
711
- total: progress.total,
712
- file: progress.file,
713
- percentage: Math.round((progress.current / progress.total) * 100)
714
- });
715
- });
716
- result = {
717
- success: true,
718
- syncedFiles: syncResult.syncedFiles,
719
- addedFunctions: syncResult.addedFunctions,
720
- updatedFunctions: syncResult.updatedFunctions,
721
- removedFunctions: syncResult.removedFunctions,
722
- errors: syncResult.errors,
723
- message: `Synced ${syncResult.syncedFiles} files: ${syncResult.addedFunctions} added, ${syncResult.updatedFunctions} updated, ${syncResult.removedFunctions} removed`
724
- };
473
+ }
725
474
  break;
726
475
  }
727
476
  default: