@aaswe/codebase-ai
Version:
AI-Assisted Software Engineering (AASWE) - Rich codebase context for IDE LLMs
643 lines (638 loc) • 30.5 kB
JavaScript
#!/usr/bin/env node
"use strict";
/**
* AASWE CLI - Command Line Interface
*
* Provides easy commands to start, configure, and manage the AASWE system.
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const commander_1 = require("commander");
const dotenv_1 = require("dotenv");
const path_1 = require("path");
const fs_1 = require("fs");
const promises_1 = require("fs/promises");
const logger_1 = __importDefault(require("../utils/logger"));
const mcp_server_1 = require("../services/mcp-server");
// Load environment variables from .env.aaswe
(0, dotenv_1.config)({ path: '.env.aaswe' });
// Also try loading from .env as fallback
(0, dotenv_1.config)();
const program = new commander_1.Command();
program
.name('codebase-ai')
.alias('aaswe')
.description('AI-Assisted Software Engineering (AASWE) - Rich codebase context for IDE LLMs')
.version('1.0.0');
/**
* Start command - Launch AASWE server
*/
program
.command('start')
.description('Start the AASWE MCP server')
.option('-m, --mode <mode>', 'Deployment mode: context-only or full', 'context-only')
.option('-p, --port <port>', 'Server port', '3001')
.option('-c, --config <path>', 'Configuration file path')
.option('--project-path <path>', 'Custom project path', process.cwd())
.option('--no-watch', 'Disable TTL file watching')
.option('--debug', 'Enable debug logging')
.action(async (options) => {
try {
if (options.debug) {
process.env.LOG_LEVEL = 'debug';
}
// Set project path
const projectPath = options.projectPath || process.cwd();
process.env.PROJECT_PATH = projectPath;
logger_1.default.info('🚀 Starting AASWE System', {
mode: options.mode,
port: options.port,
projectPath: projectPath,
version: '1.0.0'
});
// Load configuration
const config = options.config ?
require((0, path_1.join)(projectPath, options.config)) :
(0, mcp_server_1.createDefaultMCPConfig)();
config.server.port = parseInt(options.port);
config.ttl.watchEnabled = options.watch;
config.projectPath = projectPath;
// Initialize services based on mode
let layer3Service = null;
let hybridStorage = null;
if (options.mode === 'full') {
logger_1.default.info('🧠 Full mode enabled - Layer 3 AI services available');
logger_1.default.info('💡 Note: Full mode requires proper API keys and Neo4j setup');
// For now, use enhanced mock services that indicate full mode capabilities
// TODO: Implement full Layer 3 initialization when needed
layer3Service = {
query: async (req) => ({
query: req.query,
type: req.type === 'auto' ? 'rag' : req.type,
response: `[Full Mode] Enhanced AI analysis: ${req.query}`,
confidence: 0.9,
sources: ['Layer 3 AI Services'],
executionTime: 100,
metadata: { mode: 'full', enhanced: true }
}),
initialize: async () => { logger_1.default.info('Layer 3 services initialized (mock)'); },
shutdown: async () => { logger_1.default.info('Layer 3 services shutdown (mock)'); },
getStatus: () => ({
overall: 'healthy',
services: {
rag: { name: 'rag', enabled: true, healthy: true, lastCheck: new Date(), metrics: { totalQueries: 0, successRate: 1, averageResponseTime: 100 } },
graphCypher: { name: 'graphCypher', enabled: true, healthy: true, lastCheck: new Date(), metrics: { totalQueries: 0, successRate: 1, averageResponseTime: 100 } },
sparql: { name: 'sparql', enabled: true, healthy: true, lastCheck: new Date(), metrics: { totalQueries: 0, successRate: 1, averageResponseTime: 100 } }
},
lastUpdated: new Date()
}),
getMetrics: () => ({
overall: { totalQueries: 0, successfulQueries: 0, failedQueries: 0, averageResponseTime: 100, queriesPerSecond: 0 },
services: {
rag: { queries: 0, successRate: 1, averageResponseTime: 100, cacheHitRate: 0 },
graphCypher: { queries: 0, successRate: 1, averageResponseTime: 100, averageConfidence: 0.9 },
sparql: { queries: 0, successRate: 1, averageResponseTime: 100, averageConfidence: 0.9 }
},
routing: { autoDetected: 0, manuallySpecified: 0, routingAccuracy: 1, fallbackUsed: 0 },
performance: { memoryUsage: 0, cpuUsage: 0, cacheSize: 0, activeConnections: 0 }
})
};
hybridStorage = {
initialize: async () => { logger_1.default.info('Hybrid storage initialized (mock)'); },
shutdown: async () => { logger_1.default.info('Hybrid storage shutdown (mock)'); },
query: async () => ({ data: [], source: 'cache', executionTime: 50, cached: false, timestamp: new Date() }),
create: async () => ({ data: {}, source: 'cache', executionTime: 50, cached: false, timestamp: new Date() }),
update: async () => ({ data: {}, source: 'cache', executionTime: 50, cached: false, timestamp: new Date() }),
delete: async () => ({ data: true, source: 'cache', executionTime: 50, cached: false, timestamp: new Date() }),
getStatus: () => ({ status: 'running' })
};
await layer3Service.initialize();
await hybridStorage.initialize();
}
else {
logger_1.default.info('📄 Running in context-only mode (recommended)');
// Create minimal mock services for context-only mode
layer3Service = {
query: async () => ({ query: '', type: 'rag', answer: '', confidence: 0, sources: [], explanation: '', metadata: { processingTime: 0, service: 'rag', cached: false, queryId: '', timestamp: Date.now() } }),
initialize: async () => { },
shutdown: async () => { },
getStatus: () => ({ overall: 'healthy', services: { rag: { name: 'rag', enabled: false, healthy: true, lastCheck: new Date() }, graphCypher: { name: 'graphCypher', enabled: false, healthy: true, lastCheck: new Date() }, sparql: { name: 'sparql', enabled: false, healthy: true, lastCheck: new Date() } }, lastUpdated: new Date() }),
getMetrics: () => ({ overall: { totalQueries: 0, successfulQueries: 0, failedQueries: 0, averageResponseTime: 0, queriesPerSecond: 0 }, services: { rag: { queries: 0, successRate: 0, averageResponseTime: 0, cacheHitRate: 0 }, graphCypher: { queries: 0, successRate: 0, averageResponseTime: 0, averageConfidence: 0 }, sparql: { queries: 0, successRate: 0, averageResponseTime: 0, averageConfidence: 0 } }, routing: { autoDetected: 0, manuallySpecified: 0, routingAccuracy: 0, fallbackUsed: 0 }, performance: { memoryUsage: 0, cpuUsage: 0, cacheSize: 0, activeConnections: 0 } })
};
hybridStorage = {
initialize: async () => { },
shutdown: async () => { },
query: async () => ({ data: [], source: 'cache', executionTime: 0, cached: false, timestamp: new Date() }),
create: async () => ({ data: {}, source: 'cache', executionTime: 0, cached: false, timestamp: new Date() }),
update: async () => ({ data: {}, source: 'cache', executionTime: 0, cached: false, timestamp: new Date() }),
delete: async () => ({ data: true, source: 'cache', executionTime: 0, cached: false, timestamp: new Date() }),
getStatus: () => ({ status: 'running' })
};
}
// Start MCP Server
const mcpServer = new mcp_server_1.MCPServer(config, layer3Service, hybridStorage);
await mcpServer.start();
logger_1.default.info('✅ AASWE System Started Successfully!', {
mode: options.mode,
port: config.server.port,
mcpUrl: `ws://localhost:${config.server.port}`
});
logger_1.default.info('🔗 Configure your IDE to connect to:', {
websocket: `ws://localhost:${config.server.port}`,
protocol: 'Model Context Protocol (MCP)'
});
if (options.mode === 'context-only') {
logger_1.default.info('💡 Running in context-only mode - your existing IDE LLM will get enhanced context!');
}
else {
logger_1.default.info('🧠 Running in full mode - advanced AI analysis available!');
}
// Handle graceful shutdown
process.on('SIGINT', async () => {
logger_1.default.info('🛑 Shutting down AASWE System...');
await mcpServer.stop();
if (layer3Service && typeof layer3Service.shutdown === 'function') {
await layer3Service.shutdown();
}
if (hybridStorage && typeof hybridStorage.shutdown === 'function') {
await hybridStorage.shutdown();
}
logger_1.default.info('✅ AASWE System stopped gracefully');
process.exit(0);
});
}
catch (error) {
logger_1.default.error('❌ Failed to start AASWE System', { error });
process.exit(1);
}
});
/**
* Full-start command - Start complete system with all containers
*/
program
.command('full-start')
.description('Start complete AASWE system with all containers (Neo4j + MCP Server + Redis)')
.option('--project-path <path>', 'Custom project path for analysis (not docker-compose location)', process.cwd())
.option('--detach', 'Run containers in background')
.option('--build', 'Rebuild containers before starting')
.action(async (options) => {
try {
// The project path is for analysis, but docker-compose should run from AASWE package directory
const analysisProjectPath = options.projectPath || process.cwd();
// Find the AASWE package directory (where docker-compose.yml is located)
const path = require('path');
const fs = require('fs');
// Get the directory where this CLI script is installed
const cliScriptPath = require.resolve('@aaswe/codebase-ai/dist/cli/index.js');
const packageRoot = path.dirname(path.dirname(path.dirname(cliScriptPath))); // Go up from dist/cli to package root
const dockerComposePath = path.join(packageRoot, 'docker-compose.yml');
// Verify docker-compose.yml exists in package
if (!fs.existsSync(dockerComposePath)) {
logger_1.default.error('❌ AASWE docker-compose.yml not found in package');
logger_1.default.error(`Expected at: ${dockerComposePath}`);
logger_1.default.info('💡 Try reinstalling: npm install -g @aaswe/codebase-ai');
process.exit(1);
}
logger_1.default.info('🚀 Starting Complete AASWE System with All Containers...');
logger_1.default.info('📦 This includes: Neo4j Database + MCP Server + Redis Cache');
logger_1.default.info(`🎯 Analysis will target: ${analysisProjectPath}`);
logger_1.default.info(`🐳 Using docker-compose from: ${packageRoot}`);
// Check if Docker is available
const { spawn } = require('child_process');
// Check Docker availability
const dockerCheck = spawn('docker', ['--version'], { stdio: 'pipe' });
dockerCheck.on('error', () => {
logger_1.default.error('❌ Docker is not installed or not available');
logger_1.default.info('💡 Please install Docker Desktop: https://www.docker.com/products/docker-desktop');
process.exit(1);
});
dockerCheck.on('close', async (code) => {
if (code !== 0) {
logger_1.default.error('❌ Docker is not running');
logger_1.default.info('💡 Please start Docker Desktop and try again');
process.exit(1);
}
// Docker is available, proceed with startup
logger_1.default.info('✅ Docker detected - proceeding with container startup');
// Build Docker Compose arguments
const args = ['compose', 'up'];
if (options.detach)
args.push('-d');
if (options.build)
args.push('--build');
// Set environment variable for the analysis project path
const env = { ...process.env, ANALYSIS_PROJECT_PATH: analysisProjectPath };
logger_1.default.info('🐳 Starting all AASWE containers...');
logger_1.default.info('📊 Services starting:');
logger_1.default.info(' - Neo4j Database (Graph storage with source code)');
logger_1.default.info(' - Redis Cache (Performance optimization)');
logger_1.default.info(' - AASWE MCP Server (LLM integration)');
const child = spawn('docker', args, {
stdio: 'inherit',
cwd: packageRoot, // Use AASWE package root, not current directory
env: env
});
child.on('close', (code) => {
if (code === 0) {
logger_1.default.info('');
logger_1.default.info('🎉 Complete AASWE System Started Successfully!');
logger_1.default.info('');
logger_1.default.info('🔗 Access Points:');
logger_1.default.info(' 📡 MCP Server: ws://localhost:3001 (for IDE integration)');
logger_1.default.info(' 🗄️ Neo4j Browser: http://localhost:7474 (neo4j/aaswe-password)');
logger_1.default.info(' ⚡ Redis Cache: localhost:6379');
logger_1.default.info('');
logger_1.default.info('🎯 Next Steps:');
logger_1.default.info(' 1. Configure your IDE to connect to: ws://localhost:3001');
logger_1.default.info(' 2. Run: codebase-ai analyze (to populate the knowledge graph)');
logger_1.default.info(' 3. Visit http://localhost:7474 to explore the Neo4j graph database');
logger_1.default.info('');
logger_1.default.info('💡 To stop all services: codebase-ai docker down');
}
else {
logger_1.default.error('❌ Failed to start complete AASWE system');
logger_1.default.info('💡 Try: codebase-ai docker down && codebase-ai full-start --build');
process.exit(code);
}
});
});
}
catch (error) {
logger_1.default.error('❌ Failed to start complete AASWE system', { error });
process.exit(1);
}
});
/**
* Init command - Initialize AASWE in current project
*/
program
.command('init')
.description('Initialize AASWE in the current project')
.option('-f, --force', 'Overwrite existing configuration')
.option('-m, --mode <mode>', 'Initialize for specific mode: context-only or full', 'context-only')
.action(async (options) => {
try {
const configPath = (0, path_1.join)(process.cwd(), 'aaswe.config.js');
const envPath = (0, path_1.join)(process.cwd(), '.env.aaswe');
if ((0, fs_1.existsSync)(configPath) && !options.force) {
logger_1.default.warn('AASWE already initialized. Use --force to overwrite.');
return;
}
logger_1.default.info(`🔧 Initializing AASWE in current project for ${options.mode} mode...`);
// Create configuration file with mode-specific settings
const configContent = `
// AASWE Configuration - ${options.mode} mode
module.exports = {
mode: '${options.mode}',
server: {
name: 'AASWE-MCP-Server',
version: '1.0.0',
port: ${options.mode === 'full' ? '8000' : '3001'},
host: 'localhost'
},
context: {
maxTokens: 8000,
maxFiles: 10,
relevanceThreshold: 0.3,
cacheEnabled: true,
cacheTtl: 300000
},
ttl: {
watchEnabled: true,
watchDebounce: 1000,
maxFileSize: 1024 * 1024,
encoding: 'utf-8'
}${options.mode === 'full' ? `,
docker: {
enabled: true,
composeFile: 'docker-compose.local.yml'
}` : ''}
};
`;
// Create environment file with mode-specific content
const envContent = `
# AASWE Environment Configuration - ${options.mode} mode
# Uncomment and configure as needed
${options.mode === 'full' ? `# Full Mode Configuration
# OpenAI Configuration
# OPENAI_API_KEY=your_openai_api_key_here
# Anthropic Configuration
# ANTHROPIC_API_KEY=your_anthropic_api_key_here
# Neo4j Configuration
# NEO4J_URI=bolt://localhost:7687
# NEO4J_USERNAME=neo4j
# NEO4J_PASSWORD=password
# Redis Configuration
# REDIS_URL=redis://localhost:6379` : `# Context-Only Mode Configuration
# No additional API keys required - uses your existing IDE LLM`}
# Logging
LOG_LEVEL=info
`;
await (0, promises_1.writeFile)(configPath, configContent.trim());
await (0, promises_1.writeFile)(envPath, envContent.trim());
logger_1.default.info('✅ AASWE initialized successfully!');
logger_1.default.info('📝 Configuration files created:');
logger_1.default.info(` - ${configPath}`);
logger_1.default.info(` - ${envPath}`);
logger_1.default.info('');
logger_1.default.info('🚀 Next steps:');
if (options.mode === 'context-only') {
logger_1.default.info(' 1. Run: codebase-ai start --mode=context-only');
logger_1.default.info(' 2. Configure your IDE to connect to: ws://localhost:3001');
logger_1.default.info(' 3. Your IDE LLM will now have rich codebase context!');
}
else {
logger_1.default.info(' 1. Set up API keys in .env.aaswe (if needed)');
logger_1.default.info(' 2. Run: codebase-ai full-start');
logger_1.default.info(' 3. Access services:');
logger_1.default.info(' - MCP Server: ws://localhost:3001');
logger_1.default.info(' - Neo4j Browser: http://localhost:7474');
logger_1.default.info('');
logger_1.default.info('💡 Or use: codebase-ai docker up (for advanced users)');
}
}
catch (error) {
logger_1.default.error('❌ Failed to initialize AASWE', { error });
process.exit(1);
}
});
/**
* Status command - Check AASWE server status
*/
program
.command('status')
.description('Check AASWE server status')
.option('-p, --port <port>', 'Server port', '3001')
.action(async (options) => {
try {
// Simple health check
const response = await fetch(`http://localhost:${options.port}/health`).catch(() => null);
if (response && response.ok) {
logger_1.default.info('✅ AASWE Server is running', {
port: options.port,
url: `ws://localhost:${options.port}`
});
}
else {
logger_1.default.warn('❌ AASWE Server is not running', {
port: options.port
});
logger_1.default.info('💡 Start with: codebase-ai start (lightweight) or codebase-ai full-start (complete)');
}
}
catch (error) {
logger_1.default.error('❌ Failed to check server status', { error });
}
});
/**
* Analyze command - Analyze current project and generate TTL files
*/
program
.command('analyze')
.description('Analyze current project and generate TTL knowledge files')
.option('-o, --output <dir>', 'Output directory for TTL files', './knowledge')
.option('--languages <langs>', 'Comma-separated list of languages to analyze', 'typescript,javascript,python,java')
.option('--debug', 'Enable debug logging')
.action(async (options) => {
if (options.debug) {
process.env.LOG_LEVEL = 'debug';
}
try {
logger_1.default.info('🔍 Starting automatic project analysis...');
const outputDir = (0, path_1.join)(process.cwd(), options.output);
await (0, promises_1.mkdir)(outputDir, { recursive: true });
// Import and run the AutoAnalysisWorkflow
const { AutoAnalysisWorkflow } = await Promise.resolve().then(() => __importStar(require('../services/project-analysis/AutoAnalysisWorkflow')));
const workflow = new AutoAnalysisWorkflow({
projectRoot: process.cwd(),
outputDirectory: outputDir,
languages: options.languages.split(',').map((lang) => lang.trim()),
preserveBusinessContext: true,
enableKnowledgeGraphPopulation: true, // Enable Neo4j if available
enableMCPContextLoading: false // CLI mode doesn't need MCP server
});
logger_1.default.info('🚀 Running comprehensive analysis workflow...');
const result = await workflow.executeComprehensiveAnalysis();
logger_1.default.info('✅ Project analysis completed successfully!', {
filesAnalyzed: result.summary.analyzedFiles,
ttlFilesGenerated: result.summary.ttlFilesGenerated,
executionTime: `${result.duration}ms`
});
logger_1.default.info(`📁 TTL knowledge files generated in: ${outputDir}`);
logger_1.default.info('🔗 Files can now be used by MCP servers for enhanced IDE context');
}
catch (error) {
console.error('Full error details:', error);
logger_1.default.error('❌ Failed to analyze project', {
error: error instanceof Error ? error.message : error,
stack: error instanceof Error ? error.stack : undefined
});
process.exit(1);
}
});
/**
* Docker commands
*/
const dockerCmd = program
.command('docker')
.description('Docker-related commands');
dockerCmd
.command('up')
.description('Start AASWE with Docker Compose')
.option('-d, --detach', 'Run in detached mode')
.action(async (options) => {
try {
const { spawn } = require('child_process');
const args = ['compose', 'up'];
if (options.detach)
args.push('-d');
logger_1.default.info('🐳 Starting AASWE with Docker Compose...');
const child = spawn('docker', args, { stdio: 'inherit' });
child.on('close', (code) => {
if (code === 0) {
logger_1.default.info('✅ AASWE Docker services started successfully!');
}
else {
logger_1.default.error('❌ Failed to start Docker services');
process.exit(code);
}
});
}
catch (error) {
logger_1.default.error('❌ Failed to start Docker services', { error });
process.exit(1);
}
});
dockerCmd
.command('down')
.description('Stop AASWE Docker services')
.action(async () => {
try {
const { spawn } = require('child_process');
logger_1.default.info('🐳 Stopping AASWE Docker services...');
const child = spawn('docker', ['compose', 'down'], { stdio: 'inherit' });
child.on('close', (code) => {
if (code === 0) {
logger_1.default.info('✅ AASWE Docker services stopped successfully!');
}
else {
logger_1.default.error('❌ Failed to stop Docker services');
process.exit(code);
}
});
}
catch (error) {
logger_1.default.error('❌ Failed to stop Docker services', { error });
process.exit(1);
}
});
dockerCmd
.command('logs [service]')
.description('View logs for AASWE Docker services')
.option('-f, --follow', 'Follow log output')
.action(async (service, options) => {
try {
const { spawn } = require('child_process');
const args = ['compose', 'logs'];
if (options.follow)
args.push('-f');
if (service)
args.push(service);
logger_1.default.info(`🐳 Viewing logs for ${service || 'all services'}...`);
const child = spawn('docker', args, { stdio: 'inherit' });
child.on('close', (code) => {
if (code !== 0) {
logger_1.default.error('❌ Failed to view Docker logs');
process.exit(code);
}
});
}
catch (error) {
logger_1.default.error('❌ Failed to view Docker logs', { error });
process.exit(1);
}
});
/**
* Git hooks command - Manage Git hooks for TTL file versioning
*/
const gitCmd = program
.command('git')
.description('Git integration and hooks management');
gitCmd
.command('install-hooks')
.description('Install Git hooks for TTL file versioning')
.option('--pre-commit', 'Install pre-commit hook for TTL validation', true)
.option('--post-commit', 'Install post-commit hook for re-analysis', true)
.option('--post-merge', 'Install post-merge hook for conflict resolution', true)
.option('--auto-reanalyze', 'Enable automatic re-analysis on TTL changes', true)
.action(async (options) => {
try {
logger_1.default.info('🔧 Installing Git hooks for TTL file versioning...');
const { GitHooksManager } = await Promise.resolve().then(() => __importStar(require('../services/git-integration/GitHooksManager')));
const manager = new GitHooksManager({
projectRoot: process.cwd(),
ttlDirectories: ['./knowledge', './clean-knowledge', './.aaswe/knowledge'],
ttlPatterns: ['**/*.ttl', '**/*.module-knowledge.ttl'],
enablePreCommitHook: options.preCommit,
enablePostCommitHook: options.postCommit,
enablePostMergeHook: options.postMerge,
autoReanalyzeOnTTLChange: options.autoReanalyze
});
await manager.initialize();
logger_1.default.info('✅ Git hooks installed successfully!');
logger_1.default.info('💡 TTL files will now be automatically validated and re-analyzed');
}
catch (error) {
logger_1.default.error('❌ Failed to install Git hooks', { error });
process.exit(1);
}
});
gitCmd
.command('status')
.description('Check Git hooks status')
.action(async () => {
try {
const { GitHooksManager } = await Promise.resolve().then(() => __importStar(require('../services/git-integration/GitHooksManager')));
const manager = new GitHooksManager({
projectRoot: process.cwd(),
ttlDirectories: ['./knowledge', './clean-knowledge', './.aaswe/knowledge'],
ttlPatterns: ['**/*.ttl', '**/*.module-knowledge.ttl'],
enablePreCommitHook: true,
enablePostCommitHook: true,
enablePostMergeHook: true,
autoReanalyzeOnTTLChange: true
});
const status = await manager.getStatus();
logger_1.default.info('📊 Git Hooks Status:', {
gitRepository: status.isGitRepo ? '✅ Yes' : '❌ No',
preCommitHook: status.hooksInstalled['pre-commit']?.isAASWE ? '✅ Installed' : '❌ Not installed',
postCommitHook: status.hooksInstalled['post-commit']?.isAASWE ? '✅ Installed' : '❌ Not installed',
postMergeHook: status.hooksInstalled['post-merge']?.isAASWE ? '✅ Installed' : '❌ Not installed'
});
}
catch (error) {
logger_1.default.error('❌ Failed to check Git hooks status', { error });
}
});
gitCmd
.command('uninstall-hooks')
.description('Uninstall AASWE Git hooks')
.action(async () => {
try {
logger_1.default.info('🗑️ Uninstalling AASWE Git hooks...');
const { GitHooksManager } = await Promise.resolve().then(() => __importStar(require('../services/git-integration/GitHooksManager')));
const manager = new GitHooksManager({
projectRoot: process.cwd(),
ttlDirectories: ['./knowledge', './clean-knowledge', './.aaswe/knowledge'],
ttlPatterns: ['**/*.ttl', '**/*.module-knowledge.ttl'],
enablePreCommitHook: false,
enablePostCommitHook: false,
enablePostMergeHook: false,
autoReanalyzeOnTTLChange: false
});
await manager.uninstall();
logger_1.default.info('✅ Git hooks uninstalled successfully');
}
catch (error) {
logger_1.default.error('❌ Failed to uninstall Git hooks', { error });
process.exit(1);
}
});
// Parse command line arguments
program.parse();
//# sourceMappingURL=index.js.map