mnemos-coder
Version:
CLI-based coding agent with graph-based execution loop and terminal UI
257 lines • 9.83 kB
JavaScript
/**
* 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