import { SQLiteDatabase } from '../storage/sqlite-db.js';
import { SemanticVectorDB } from '../storage/vector-db.js';
import { SemanticEngine } from '../engines/semantic-engine.js';
import { PatternEngine } from '../engines/pattern-engine.js';
import { existsSync, statSync } from 'fs';
import { join } from 'path';
export interface DebugOptions {
verbose: boolean;
checkDatabase: boolean;
checkIntelligence: boolean;
checkFileSystem: boolean;
validateData: boolean;
performance: boolean;
}
export class DebugTools {
private verbose: boolean = false;
constructor(private options: DebugOptions = {
verbose: false,
checkDatabase: true,
checkIntelligence: true,
checkFileSystem: true,
validateData: false,
performance: false
}) {
this.verbose = options.verbose;
}
async runDiagnostics(projectPath: string = process.cwd()): Promise<void> {
console.log('π In Memoria Debug & Diagnostics');
console.log(`π Project: ${projectPath}`);
console.log(`β‘ Verbose: ${this.verbose ? 'ON' : 'OFF'}\n`);
const results = {
passed: 0,
warnings: 0,
errors: 0,
suggestions: [] as string[]
};
// System Information
console.log('π SYSTEM INFORMATION');
console.log('β'.repeat(50));
this.checkSystemInfo();
console.log();
// Database Diagnostics
if (this.options.checkDatabase) {
console.log('ποΈ DATABASE DIAGNOSTICS');
console.log('β'.repeat(50));
const dbResults = await this.checkDatabase(projectPath);
this.mergeResults(results, dbResults);
console.log();
}
// Intelligence Diagnostics
if (this.options.checkIntelligence) {
console.log('π§ INTELLIGENCE DIAGNOSTICS');
console.log('β'.repeat(50));
const intResults = await this.checkIntelligence(projectPath);
this.mergeResults(results, intResults);
console.log();
}
// File System Diagnostics
if (this.options.checkFileSystem) {
console.log('π FILE SYSTEM DIAGNOSTICS');
console.log('β'.repeat(50));
const fsResults = await this.checkFileSystem(projectPath);
this.mergeResults(results, fsResults);
console.log();
}
// Data Validation
if (this.options.validateData) {
console.log('β
DATA VALIDATION');
console.log('β'.repeat(50));
const validationResults = await this.validateIntelligenceData(projectPath);
this.mergeResults(results, validationResults);
console.log();
}
// Performance Analysis
if (this.options.performance) {
console.log('β‘ PERFORMANCE ANALYSIS');
console.log('β'.repeat(50));
const perfResults = await this.analyzePerformance(projectPath);
this.mergeResults(results, perfResults);
console.log();
}
// Summary
this.printSummary(results);
}
private checkSystemInfo(): void {
const nodeVersion = process.version;
const platform = process.platform;
const arch = process.arch;
const memory = process.memoryUsage();
console.log(` Node.js Version: ${nodeVersion}`);
console.log(` Platform: ${platform}-${arch}`);
console.log(` Memory Usage: ${Math.round(memory.rss / 1024 / 1024)}MB RSS, ${Math.round(memory.heapUsed / 1024 / 1024)}MB Heap`);
const majorVersion = parseInt(nodeVersion.substring(1));
if (majorVersion < 18) {
console.log(' β Node.js version is too old. Minimum required: 18');
} else {
console.log(' β
Node.js version is compatible');
}
}
private async checkDatabase(projectPath: string): Promise<any> {
const results = { passed: 0, warnings: 0, errors: 0, suggestions: [] as string[] };
try {
const dbPath = join(projectPath, 'in-memoria.db');
// Check if database exists
if (!existsSync(dbPath)) {
console.log(' β Database file not found');
console.log(` Expected: ${dbPath}`);
results.errors++;
results.suggestions.push('Run `in-memoria init` or `in-memoria setup --interactive` to initialize');
return results;
}
// Check database file size and permissions
const stats = statSync(dbPath);
console.log(` π Database file: ${dbPath}`);
console.log(` πΎ Size: ${Math.round(stats.size / 1024)}KB`);
console.log(` π
Modified: ${stats.mtime.toISOString()}`);
if (stats.size === 0) {
console.log(' β οΈ Database file is empty');
results.warnings++;
} else {
console.log(' β
Database file exists and has content');
results.passed++;
}
// Test database connection
try {
const db = new SQLiteDatabase(dbPath);
console.log(' β
Database connection successful');
// Check migrations
const migrator = db.getMigrator();
const currentVersion = migrator.getCurrentVersion();
const latestVersion = migrator.getLatestVersion();
console.log(` π Schema version: ${currentVersion}/${latestVersion}`);
if (currentVersion < latestVersion) {
console.log(' β οΈ Database schema needs migration');
results.warnings++;
results.suggestions.push('Run database migrations will be applied automatically on next start');
} else {
console.log(' β
Database schema is up-to-date');
results.passed++;
}
// Check table counts
const concepts = db.getSemanticConcepts();
const patterns = db.getDeveloperPatterns();
console.log(` π Stored concepts: ${concepts.length}`);
console.log(` π Stored patterns: ${patterns.length}`);
if (concepts.length === 0 && patterns.length === 0) {
console.log(' β οΈ No intelligence data found');
results.warnings++;
results.suggestions.push('Run `in-memoria learn` to analyze your codebase');
}
db.close();
results.passed++;
} catch (error: unknown) {
console.log(` β Database connection failed: ${error instanceof Error ? error.message : String(error)}`);
results.errors++;
if (this.verbose) {
console.log(` Details: ${error instanceof Error ? error.stack : 'No stack trace available'}`);
}
}
} catch (error: unknown) {
console.log(` β Database check failed: ${error instanceof Error ? error.message : String(error)}`);
results.errors++;
}
return results;
}
private async checkIntelligence(projectPath: string): Promise<any> {
const results = { passed: 0, warnings: 0, errors: 0, suggestions: [] as string[] };
try {
// Check if we can initialize intelligence components
const dbPath = join(projectPath, 'in-memoria.db');
if (!existsSync(dbPath)) {
console.log(' β No database found for intelligence check');
results.errors++;
return results;
}
const database = new SQLiteDatabase(dbPath);
const vectorDB = new SemanticVectorDB(process.env.OPENAI_API_KEY);
const semanticEngine = new SemanticEngine(database, vectorDB);
const patternEngine = new PatternEngine(database);
console.log(' β
Intelligence components initialized successfully');
results.passed++;
// Test basic functionality
try {
const concepts = database.getSemanticConcepts();
const patterns = database.getDeveloperPatterns();
console.log(` π Available concepts: ${concepts.length}`);
console.log(` π Available patterns: ${patterns.length}`);
if (concepts.length === 0) {
console.log(' β οΈ No semantic concepts found');
results.warnings++;
results.suggestions.push('Run learning to build semantic understanding');
}
if (patterns.length === 0) {
console.log(' β οΈ No development patterns found');
results.warnings++;
results.suggestions.push('Run learning to identify coding patterns');
}
// Check OpenAI integration
if (process.env.OPENAI_API_KEY) {
console.log(' π OpenAI API key detected');
console.log(' β
Enhanced embeddings available');
results.passed++;
} else {
console.log(' β οΈ No OpenAI API key found');
console.log(' π Using local embeddings only');
results.warnings++;
results.suggestions.push('Set OPENAI_API_KEY environment variable for enhanced features');
}
} catch (error: unknown) {
console.log(` β Intelligence data access failed: ${error instanceof Error ? error.message : String(error)}`);
results.errors++;
}
database.close();
} catch (error: unknown) {
console.log(` β Intelligence initialization failed: ${error instanceof Error ? error.message : String(error)}`);
results.errors++;
if (this.verbose) {
console.log(` Details: ${error instanceof Error ? error.stack : 'No stack trace available'}`);
}
}
return results;
}
private async checkFileSystem(projectPath: string): Promise<any> {
const results = { passed: 0, warnings: 0, errors: 0, suggestions: [] as string[] };
try {
// Check project directory
if (!existsSync(projectPath)) {
console.log(` β Project directory does not exist: ${projectPath}`);
results.errors++;
return results;
}
console.log(` π Project directory: ${projectPath}`);
console.log(' β
Project directory exists');
results.passed++;
// Check for .in-memoria directory
const configDir = join(projectPath, '.in-memoria');
if (existsSync(configDir)) {
console.log(' π Configuration directory found');
// Check config file
const configFile = join(configDir, 'config.json');
if (existsSync(configFile)) {
console.log(' βοΈ Configuration file exists');
try {
const configContent = await import(`file://${configFile}`);
console.log(' β
Configuration file is valid JSON');
results.passed++;
} catch (error) {
console.log(' β Configuration file is invalid JSON');
results.errors++;
}
} else {
console.log(' β οΈ No configuration file found');
results.warnings++;
results.suggestions.push('Run `in-memoria setup --interactive` to create configuration');
}
} else {
console.log(' β οΈ No .in-memoria configuration directory');
results.warnings++;
results.suggestions.push('Run `in-memoria init` to create basic configuration');
}
// Check for common files
const packageJson = join(projectPath, 'package.json');
const gitDir = join(projectPath, '.git');
if (existsSync(packageJson)) {
console.log(' π¦ Node.js project detected (package.json)');
results.passed++;
}
if (existsSync(gitDir)) {
console.log(' ποΈ Git repository detected');
results.passed++;
}
// Check .gitignore
const gitignore = join(projectPath, '.gitignore');
if (existsSync(gitignore)) {
const fs = await import('fs');
const content = fs.readFileSync(gitignore, 'utf-8');
if (content.includes('in-memoria.db')) {
console.log(' β
In Memoria entries found in .gitignore');
results.passed++;
} else {
console.log(' β οΈ In Memoria not in .gitignore');
results.warnings++;
results.suggestions.push('Add in-memoria.db to .gitignore to avoid committing database');
}
}
} catch (error: unknown) {
console.log(` β File system check failed: ${error instanceof Error ? error.message : String(error)}`);
results.errors++;
}
return results;
}
private async validateIntelligenceData(projectPath: string): Promise<any> {
const results = { passed: 0, warnings: 0, errors: 0, suggestions: [] as string[] };
console.log(' π Validating intelligence data consistency...');
try {
const dbPath = join(projectPath, 'in-memoria.db');
if (!existsSync(dbPath)) {
console.log(' β No database to validate');
results.errors++;
return results;
}
const database = new SQLiteDatabase(dbPath);
const concepts = database.getSemanticConcepts();
const patterns = database.getDeveloperPatterns();
// Validate concepts
let validConcepts = 0;
let invalidConcepts = 0;
for (const concept of concepts) {
if (concept.conceptName && concept.conceptType && concept.confidenceScore >= 0) {
validConcepts++;
} else {
invalidConcepts++;
if (this.verbose) {
console.log(` β οΈ Invalid concept: ${concept.id}`);
}
}
}
console.log(` π Concepts: ${validConcepts} valid, ${invalidConcepts} invalid`);
if (invalidConcepts > 0) {
results.warnings++;
results.suggestions.push('Some concept data may be corrupted - consider re-learning');
} else {
results.passed++;
}
// Validate patterns
let validPatterns = 0;
let invalidPatterns = 0;
for (const pattern of patterns) {
if (pattern.patternType && pattern.frequency >= 0) {
validPatterns++;
} else {
invalidPatterns++;
if (this.verbose) {
console.log(` β οΈ Invalid pattern: ${pattern.patternId}`);
}
}
}
console.log(` π Patterns: ${validPatterns} valid, ${invalidPatterns} invalid`);
if (invalidPatterns > 0) {
results.warnings++;
results.suggestions.push('Some pattern data may be corrupted - consider re-learning');
} else {
results.passed++;
}
database.close();
} catch (error: unknown) {
console.log(` β Validation failed: ${error instanceof Error ? error.message : String(error)}`);
results.errors++;
}
return results;
}
private async analyzePerformance(projectPath: string): Promise<any> {
const results = { passed: 0, warnings: 0, errors: 0, suggestions: [] as string[] };
console.log(' β‘ Analyzing performance characteristics...');
try {
const dbPath = join(projectPath, 'in-memoria.db');
if (!existsSync(dbPath)) {
console.log(' β No database for performance analysis');
results.errors++;
return results;
}
const stats = statSync(dbPath);
const dbSizeMB = stats.size / (1024 * 1024);
console.log(` πΎ Database size: ${dbSizeMB.toFixed(2)}MB`);
if (dbSizeMB > 100) {
console.log(' β οΈ Large database size detected');
results.warnings++;
results.suggestions.push('Consider archiving old intelligence data for better performance');
} else {
console.log(' β
Database size is reasonable');
results.passed++;
}
// Test query performance
const startTime = Date.now();
const database = new SQLiteDatabase(dbPath);
const concepts = database.getSemanticConcepts();
const queryTime = Date.now() - startTime;
console.log(` π Query time: ${queryTime}ms for ${concepts.length} concepts`);
if (queryTime > 1000) {
console.log(' β οΈ Slow query performance detected');
results.warnings++;
results.suggestions.push('Database may benefit from optimization or indexing');
} else {
console.log(' β
Query performance is good');
results.passed++;
}
database.close();
} catch (error: unknown) {
console.log(` β Performance analysis failed: ${error instanceof Error ? error.message : String(error)}`);
results.errors++;
}
return results;
}
private mergeResults(target: any, source: any): void {
target.passed += source.passed;
target.warnings += source.warnings;
target.errors += source.errors;
target.suggestions.push(...source.suggestions);
}
private printSummary(results: any): void {
console.log('π DIAGNOSTIC SUMMARY');
console.log('β'.repeat(50));
console.log(`β
Passed: ${results.passed}`);
console.log(`β οΈ Warnings: ${results.warnings}`);
console.log(`β Errors: ${results.errors}`);
if (results.suggestions.length > 0) {
console.log('\nπ‘ SUGGESTIONS:');
results.suggestions.forEach((suggestion: string, index: number) => {
console.log(`${index + 1}. ${suggestion}`);
});
}
console.log('\nπ― OVERALL STATUS:');
if (results.errors === 0 && results.warnings === 0) {
console.log('π’ All systems operational');
} else if (results.errors === 0) {
console.log('π‘ Functional with minor issues');
} else {
console.log('π΄ Issues detected - intervention required');
}
}
}