UNPKG

mnemos-coder

Version:

CLI-based coding agent with graph-based execution loop and terminal UI

257 lines 9.83 kB
/** * Tool Manager for Expert Subagents * 전문가별 최적화된 도구 세트를 동적으로 로딩하고 관리 */ import { MCPClient } from '../mcp-client.js'; import { GlobalConfig } from '../config/GlobalConfig.js'; import { getLogger } from '../utils/Logger.js'; export class ToolManager { static instance; expertConfigs = new Map(); loadedServers = new Map(); logger = getLogger('ToolManager'); constructor() { this.initializeExpertConfigs(); } static getInstance() { if (!ToolManager.instance) { ToolManager.instance = new ToolManager(); } return ToolManager.instance; } /** * 전문가별 도구 설정 초기화 */ initializeExpertConfigs() { // CodeReviewer 전용 도구 설정 this.expertConfigs.set('code-reviewer', { subagentName: 'code-reviewer', capabilities: { core: ['read_file', 'search_content', 'find_files'], specialized: [ 'vulnerability_scan', // 보안 취약점 스캔 'crypto_analysis', // 암호화 분석 'dependency_audit', // 의존성 취약점 검사 'code_quality_check', // 코드 품질 측정 'lint_security' // 보안 중심 린팅 ], advanced: ['penetration_test', 'threat_model'] }, mcpServers: [ { name: 'security-analysis', serverConfig: { transport: 'stdio', command: 'node', args: ['dist/mcp-servers/security-analysis-server.js'] }, priority: 10 }, { name: 'code-quality', serverConfig: { transport: 'stdio', command: 'node', args: ['dist/mcp-servers/code-quality-server.js'] }, priority: 8 } ] }); // TestWriter 전용 도구 설정 this.expertConfigs.set('test-writer', { subagentName: 'test-writer', capabilities: { core: ['read_file', 'write_file', 'find_files'], specialized: [ 'test_runner', // 테스트 실행 'coverage_analyzer', // 커버리지 분석 'mock_generator', // Mock 생성 'test_data_factory', // 테스트 데이터 생성 'assertion_builder', // Assertion 빌더 ], advanced: ['mutation_tester', 'property_based_tester', 'performance_tester'] }, mcpServers: [ { name: 'test-automation', serverConfig: { transport: 'stdio', command: 'node', args: ['dist/mcp-servers/test-automation-server.js'] }, priority: 10 } ] }); // FileSearcher 전용 도구 설정 (기존 도구 + 고급 검색) this.expertConfigs.set('file-searcher', { subagentName: 'file-searcher', capabilities: { core: ['find_files', 'search_content', 'read_file'], specialized: [ 'ast_search', // AST 기반 구조 검색 'semantic_search', // 의미론적 검색 'dependency_graph', // 의존성 그래프 분석 'code_similarity', // 코드 유사성 분석 'git_history_search' // Git 히스토리 검색 ], advanced: ['call_graph_analyzer', 'dead_code_detector'] }, mcpServers: [ { name: 'advanced-search', serverConfig: { transport: 'stdio', command: 'node', args: ['dist/mcp-servers/advanced-search-server.js'] }, priority: 9 } ] }); // DatabaseOptimizer 전용 도구 설정 this.expertConfigs.set('database-optimizer', { subagentName: 'database-optimizer', capabilities: { core: ['read_file', 'search_content'], specialized: [ 'query_analyzer', // 쿼리 성능 분석 'index_advisor', // 인덱스 최적화 제안 'schema_validator', // 스키마 검증 'database_profiler', // DB 성능 프로파일링 'migration_generator' // 마이그레이션 생성 ], advanced: ['query_optimizer', 'partition_analyzer'] }, mcpServers: [ { name: 'database-tools', serverConfig: { transport: 'stdio', command: 'node', args: ['dist/mcp-servers/database-tools-server.js'] }, priority: 10 } ] }); } /** * 특정 전문가를 위한 도구 세트 로딩 */ async loadToolsForExpert(subagentName) { const config = this.expertConfigs.get(subagentName); if (!config) { this.logger.debug(`No expert tool configuration found for: ${subagentName}`); return []; } const loadedClients = []; // 전용 MCP 서버들 로딩 for (const serverConfig of config.mcpServers) { try { if (!this.loadedServers.has(serverConfig.name)) { this.logger.debug(`[${subagentName}] Loading specialized MCP server: ${serverConfig.name}`); const client = new MCPClient(); await client.startServer(serverConfig.name, serverConfig.serverConfig); this.loadedServers.set(serverConfig.name, client); this.logger.debug(`[${subagentName}] ✅ MCP server ${serverConfig.name} initialized`); } const client = this.loadedServers.get(serverConfig.name); if (client) { loadedClients.push(client); } } catch (error) { this.logger.error(`[${subagentName}] Failed to load MCP server ${serverConfig.name}:`, error); } } // 기본 공유 서버들도 포함 const globalConfig = GlobalConfig.getInstance(); const sharedServers = ['read-files', 'grep-search', 'glob-finder']; for (const serverName of sharedServers) { if (this.loadedServers.has(serverName)) { const client = this.loadedServers.get(serverName); if (client && !loadedClients.includes(client)) { loadedClients.push(client); } } } return loadedClients; } /** * 특정 전문가가 사용할 수 있는 도구 목록 반환 */ getAvailableToolsForExpert(subagentName) { const config = this.expertConfigs.get(subagentName); if (!config) { return []; } return [ ...config.capabilities.core, ...config.capabilities.specialized, ...(config.capabilities.advanced || []) ]; } /** * 도구 우선순위에 따른 정렬 */ getToolsByPriority(subagentName) { const config = this.expertConfigs.get(subagentName); if (!config) { return []; } const prioritizedTools = []; // Core 도구들 (최고 우선순위) config.capabilities.core.forEach(tool => { prioritizedTools.push({ tool, priority: 10 }); }); // Specialized 도구들 (높은 우선순위) config.capabilities.specialized.forEach(tool => { prioritizedTools.push({ tool, priority: 8 }); }); // Advanced 도구들 (중간 우선순위) (config.capabilities.advanced || []).forEach(tool => { prioritizedTools.push({ tool, priority: 6 }); }); return prioritizedTools.sort((a, b) => b.priority - a.priority); } /** * 동적 도구 추가 (런타임에 새로운 전문가 도구 등록) */ registerExpertTools(config) { this.expertConfigs.set(config.subagentName, config); this.logger.debug(`Registered expert tools for: ${config.subagentName}`); } /** * 도구 사용률 통계 (성능 최적화용) */ getToolUsageStats(subagentName) { // 실제 구현에서는 도구 사용 이력을 추적해서 통계 제공 return {}; } /** * 메모리 최적화: 사용하지 않는 서버들 정리 */ async cleanupUnusedServers() { // 비활성 서버들을 감지하고 정리하는 로직 this.logger.debug('Cleaning up unused MCP servers...'); } /** * 서버 상태 모니터링 */ getServerHealth() { const health = {}; for (const [name, client] of this.loadedServers) { try { // 실제로는 서버 핑 등을 통해 상태 확인 health[name] = 'healthy'; } catch (error) { health[name] = 'down'; } } return health; } } //# sourceMappingURL=ToolManager.js.map