UNPKG

mcp-adr-analysis-server

Version:

MCP server for analyzing Architectural Decision Records and project architecture

295 lines 9.79 kB
/** * Research Orchestrator * * Coordinates multi-source research with cascading fallback: * 1. Project Files (local, fast, free) * 2. Knowledge Graph (in-memory, instant) * 3. Environment Resources (live runtime data) * 4. Web Search (external, last resort) */ import { type ResearchPlan, type ResearchTaskTracker, type CreateResearchTaskOptions } from './research-task-integration.js'; export interface ResearchSource { type: 'project_files' | 'knowledge_graph' | 'environment' | 'web_search'; found?: boolean; data: any; confidence: number; timestamp: string; } export interface ResearchAnswer { question: string; sources: ResearchSource[]; confidence: number; needsWebSearch: boolean; answer?: string; metadata: { duration: number; sourcesQueried: string[]; filesAnalyzed: number; cached?: boolean; }; } /** * Research Orchestrator Class * * @deprecated This class is deprecated as of v2.2.0 and will be removed in v4.0.0. * Use atomic tools instead per ADR-018 (Atomic Tools Architecture): * - For codebase search: Use `searchCodebase` from `tools/search-codebase-tool.ts` * - For external research: Use `llm-web-search-tool.ts` (if needed) * * **Deprecation Rationale** (see ADR-018): * - Sequential execution blocking (2-8 seconds per call) * - 5,000-6,000 tokens overhead per session * - Causes 37+ test timeout failures due to complex ESM mocking * - 850+ second test suite execution time * - Conflicts with CE-MCP directive-based architecture (ADR-014) * * **Migration Guide**: * ```typescript * // OLD: Using ResearchOrchestrator * const orchestrator = new ResearchOrchestrator('/path/to/project', 'docs/adrs'); * const result = await orchestrator.answerResearchQuestion('Docker configuration'); * * // NEW: Using atomic searchCodebase tool * import { searchCodebase } from './tools/search-codebase-tool.js'; * const result = await searchCodebase({ * query: 'Docker configuration', * projectPath: '/path/to/project' * }); * ``` * * @description Coordinates multi-source research with cascading fallback strategy. * Implements a hierarchical approach to answering research questions by querying * sources in order of preference: project files → knowledge graph → environment → web search. * * Features: * - Intelligent confidence scoring for each source * - Configurable confidence thresholds * - Result caching for performance optimization * - Firecrawl integration for web search capabilities * - Comprehensive error handling and fallback mechanisms * * @example * ```typescript * const orchestrator = new ResearchOrchestrator('/path/to/project', 'docs/adrs'); * orchestrator.setConfidenceThreshold(0.8); * * const result = await orchestrator.answerResearchQuestion( * 'What authentication methods are used in this project?' * ); * * console.log(`Answer: ${result.answer}`); * console.log(`Confidence: ${result.confidence}`); * console.log(`Sources: ${result.sources.map(s => s.type).join(', ')}`); * ``` * * @since 2.0.0 * @category Research * @category Orchestration */ export declare class ResearchOrchestrator { private logger; private projectPath; private adrDirectory; private confidenceThreshold; private kgManager; private cache; private cacheTtl; private firecrawl; private config; constructor(projectPath?: string, adrDirectory?: string); /** * Answer a research question using cascading source hierarchy * * @deprecated Use atomic searchCodebase() tool instead. See class-level @deprecated tag for details. * * @description Executes comprehensive research using a cascading approach: * 1. Project files search (fastest, most relevant) * 2. Knowledge graph query (instant, context-aware) * 3. Environment resources query (live data) * 4. Web search fallback (external, when confidence is low) * * Results are cached for 5 minutes to improve performance for repeated queries. * * @param {string} question - The research question to investigate * * @returns {Promise<ResearchAnswer>} Comprehensive research results with: * - `answer`: Synthesized answer from all sources * - `confidence`: Overall confidence score (0-1) * - `sources`: Array of source results with individual confidence scores * - `needsWebSearch`: Whether web search is recommended * - `metadata`: Execution metadata (duration, files analyzed, etc.) * * @throws {Error} When question is empty or research orchestration fails * * @example * ```typescript * const result = await orchestrator.answerResearchQuestion( * 'How does authentication work in this project?' * ); * * if (result.confidence >= 0.8) { * console.log('High confidence answer:', result.answer); * } else if (result.needsWebSearch) { * console.log('Consider web search for more information'); * } * * result.sources.forEach(source => { * console.log(`${source.type}: ${(source.confidence * 100).toFixed(1)}%`); * }); * ``` * * @since 2.0.0 * @category Research * @category Public API */ answerResearchQuestion(question: string): Promise<ResearchAnswer>; /** * SOURCE 1: Search project files (Enhanced with tree-sitter and file ops) */ private searchProjectFiles; /** * Check if file should be parsed with tree-sitter */ private shouldParse; /** * SOURCE 2: Query knowledge graph */ private queryKnowledgeGraph; /** * SOURCE 3: Query environment resources */ private queryEnvironment; /** * Calculate confidence score from multiple sources */ private calculateConfidence; /** * Synthesize answer from multiple sources */ private synthesizeAnswer; /** * Calculate relevance score for content (legacy method - kept for compatibility) */ private calculateRelevanceLegacy; /** * Extract keywords from question */ private extractKeywords; /** * Set confidence threshold for web search fallback */ setConfidenceThreshold(threshold: number): void; /** * SOURCE 4: Perform web search using Firecrawl (LLM-managed) */ private performWebSearch; /** * Search using Firecrawl with LLM-driven query optimization */ private searchWithFirecrawl; /** * Generate fallback search results when Firecrawl is not available */ private generateFallbackSearchResults; /** * Generate search URLs using LLM */ private generateSearchUrls; /** * Calculate relevance score using LLM */ private calculateRelevance; /** * Generate search queries based on research question */ private generateSearchQueries; /** * Generate cache key for research question */ private generateCacheKey; /** * Get cached result if available and not expired */ private getCachedResult; /** * Cache a research result */ private setCachedResult; /** * Clear expired cache entries */ cleanupCache(): void; /** * Clear all cache entries */ clearCache(): void; /** * Get cache statistics */ getCacheStats(): { size: number; entries: Array<{ key: string; age: number; expires: number; }>; }; /** * Create a research plan for LLM delegation (non-blocking) * * This is the recommended method for new code. Instead of executing research * internally (which blocks for 2-8 seconds), this returns a research plan * that the calling LLM should execute using atomic tools. * * Benefits: * - Non-blocking: Returns immediately with a plan * - LLM-controlled: The calling LLM decides execution order * - MCP Tasks: Integrated with MCP Tasks for progress tracking * - Cancellable: Can be cancelled between phases * * @param question - The research question to investigate * @param options - Optional configuration * @returns Task ID, research plan, and tracker for progress updates * * @example * ```typescript * const orchestrator = new ResearchOrchestrator('/path/to/project'); * const { taskId, plan, tracker } = await orchestrator.createResearchPlan( * 'How does authentication work in this codebase?' * ); * * // LLM receives the plan and executes each phase: * for (const phase of plan.phases) { * await tracker.startPhase(phase.phase); * const result = await executeToolCall(phase.tool, phase.params); * await tracker.storeResult(phase.phase, result); * await tracker.completePhase(phase.phase); * } * * // Finally, synthesize and complete * const answer = synthesize(results); * await tracker.storeSynthesizedAnswer(answer, confidence); * await tracker.complete({ success: true, data: { answer, confidence } }); * ``` * * @since 3.1.0 */ createResearchPlan(question: string, options?: { includeWebSearch?: boolean; confidenceThreshold?: number; }): Promise<{ taskId: string; plan: ResearchPlan; tracker: ResearchTaskTracker; }>; /** * Get the project path used by this orchestrator */ getProjectPath(): string; /** * Get the ADR directory used by this orchestrator */ getAdrDirectory(): string; } export type { ResearchPlan, ResearchTaskTracker, CreateResearchTaskOptions }; //# sourceMappingURL=research-orchestrator.d.ts.map