hikma-engine
Version:
Code Knowledge Graph Indexer - A sophisticated TypeScript-based indexer that transforms Git repositories into multi-dimensional knowledge stores for AI agents
263 lines (257 loc) • 11 kB
JavaScript
/**
* @file Main entry point for the hikma-engine application.
* Initializes configuration, logging, and delegates to the core indexer.
*/
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.HikmaEngineCLI = exports.SearchService = exports.EnhancedSearchService = exports.Indexer = void 0;
// Load environment variables from .env file
require("dotenv/config");
// Add global error handlers
process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled Rejection at:', promise, 'reason:', reason);
process.exit(1);
});
process.on('uncaughtException', (error) => {
console.error('Uncaught Exception:', error);
process.exit(1);
});
const path = __importStar(require("path"));
const indexer_1 = require("./core/indexer");
const config_1 = require("./config");
const logger_1 = require("./utils/logger");
const error_handling_1 = require("./utils/error-handling");
/**
* Command line interface for the hikma-engine.
*/
class HikmaEngineCLI {
constructor(projectRoot) {
this.projectRoot = path.resolve(projectRoot);
}
/**
* Parses command line arguments and returns indexing options.
*/
parseArguments() {
const args = process.argv.slice(2);
const options = {};
for (let i = 0; i < args.length; i++) {
const arg = args[i];
switch (arg) {
case '--force-full':
case '-f':
options.forceFullIndex = true;
break;
case '--skip-ai-summary':
options.skipAISummary = true;
break;
case '--skip-embeddings':
options.skipEmbeddings = true;
break;
case '--dry-run':
options.dryRun = true;
break;
case '--phases':
if (i + 1 < args.length) {
options.runPhases = args[++i].split(',').map(Number);
}
break;
case '--from-phase':
if (i + 1 < args.length) {
options.fromPhase = Number(args[++i]);
}
break;
case '--force-phases':
if (i + 1 < args.length) {
options.forcePhases = args[++i].split(',').map(Number);
}
break;
case '--inspect-phase':
if (i + 1 < args.length) {
options.inspectPhase = Number(args[++i]);
}
break;
case '--status':
options.showStatus = true;
break;
case '--help':
case '-h':
this.printHelp();
process.exit(0);
break;
default:
// Skip unknown arguments or treat as project path
if (!arg.startsWith('-') && i === 0) {
this.projectRoot = path.resolve(arg);
}
break;
}
}
return options;
}
/**
* Prints help information.
*/
printHelp() {
console.log(`
hikma-engine - Code Knowledge Graph Indexer
Usage: npm start [project-path] [options]
Arguments:
project-path Path to the project to index (default: current directory)
Basic Options:
-f, --force-full Force full indexing (ignore incremental updates)
--skip-ai-summary Skip AI summary generation
--skip-embeddings Skip vector embedding generation
--dry-run Perform indexing without persisting data
-h, --help Show this help message
Phase Control Options:
--phases 1,2,3 Run only specific phases (comma-separated)
--from-phase 2 Start from specific phase (runs 2,3,4)
--force-phases 1,3 Force re-run specific phases
--inspect-phase 1 Show phase 1 data and exit
--status Show status of all phases
Examples:
npm start # Index current directory (all phases)
npm start /path/to/project # Index specific project
npm start --force-full # Force full re-indexing
npm start --dry-run # Test run without persistence
npm start --phases 1,2 # Only run discovery and parsing
npm start --from-phase 3 # Start from AI enrichment
npm start --force-phases 2 # Re-run structure extraction
npm start --inspect-phase 1 # Show discovered files
npm start --status # Show phase completion status
`);
}
/**
* Runs the hikma-engine with the provided options.
*/
async run() {
try {
const options = this.parseArguments();
// Initialize configuration
const config = (0, config_1.initializeConfig)(this.projectRoot);
// Initialize logging
const loggingConfig = config.getLoggingConfig();
(0, logger_1.initializeLogger)({
level: loggingConfig.level,
enableConsole: loggingConfig.enableConsole,
enableFile: loggingConfig.enableFile,
logFilePath: loggingConfig.logFilePath,
});
const logger = (0, logger_1.getLogger)('CLI');
console.log('✓ Logger initialized');
logger.info('Starting hikma-engine', {
projectRoot: this.projectRoot,
options,
version: require('../package.json').version
});
// Create and run the indexer
console.log('✓ Creating indexer...');
const indexer = new indexer_1.Indexer(this.projectRoot, config);
console.log('✓ Indexer created, starting run...');
const result = await indexer.run(options);
console.log('✓ Indexing completed');
// Log results
const resultForLogging = {
...result,
phases: result.phases.map(({ data, ...phase }) => phase),
};
logger.info('Indexing completed successfully', resultForLogging);
console.log('\n=== Indexing Results ===');
console.log(`Project: ${this.projectRoot}`);
console.log(`Mode: ${result.isIncremental ? 'Incremental' : 'Full'}`);
console.log(`Files processed: ${result.processedFiles}`);
console.log(`Nodes created: ${result.totalNodes}`);
console.log(`Edges created: ${result.totalEdges}`);
console.log(`Duration: ${result.duration}ms`);
if (result.errors.length > 0) {
console.log(`Errors: ${result.errors.length}`);
result.errors.forEach(error => console.log(` - ${error}`));
}
if (options.dryRun) {
console.log('\n(Dry run mode - no data was persisted)');
}
}
catch (error) {
const logger = (0, logger_1.getLogger)('CLI');
(0, error_handling_1.logError)(logger, 'Application failed', error);
console.error('\n=== Error ===');
console.error(`Failed to index project: ${(0, error_handling_1.getErrorMessage)(error)}`);
if (process.env.NODE_ENV === 'development') {
const stack = (0, error_handling_1.getErrorStack)(error);
if (stack) {
console.error('\nStack trace:');
console.error(stack);
}
}
process.exit(1);
}
}
}
exports.HikmaEngineCLI = HikmaEngineCLI;
// Main execution
async function main() {
const projectPath = process.argv.find(arg => !arg.startsWith('-') && arg !== process.argv[0] && arg !== process.argv[1]) || process.cwd();
const cli = new HikmaEngineCLI(projectPath);
await cli.run();
}
// Handle unhandled promise rejections
process.on('unhandledRejection', (reason, promise) => {
const logger = (0, logger_1.getLogger)('Process');
logger.error('Unhandled promise rejection', { reason, promise });
process.exit(1);
});
// Handle uncaught exceptions
process.on('uncaughtException', (error) => {
const logger = (0, logger_1.getLogger)('Process');
logger.error('Uncaught exception', { error: (0, error_handling_1.getErrorMessage)(error), stack: (0, error_handling_1.getErrorStack)(error) });
process.exit(1);
});
// Run the application
if (require.main === module) {
main();
}
// Export main classes and interfaces for library usage
var indexer_2 = require("./core/indexer");
Object.defineProperty(exports, "Indexer", { enumerable: true, get: function () { return indexer_2.Indexer; } });
var enhanced_search_service_1 = require("./modules/enhanced-search-service");
Object.defineProperty(exports, "EnhancedSearchService", { enumerable: true, get: function () { return enhanced_search_service_1.EnhancedSearchService; } });
var search_service_1 = require("./modules/search-service");
Object.defineProperty(exports, "SearchService", { enumerable: true, get: function () { return search_service_1.SearchService; } });
__exportStar(require("./types"), exports);
__exportStar(require("./config"), exports);
;