mcp-adr-analysis-server 2.1.9 → 2.1.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -8
- package/dist/.tsbuildinfo +1 -1
- package/dist/src/index.d.ts +78 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1793 -577
- package/dist/src/index.js.map +1 -1
- package/dist/src/prompts/index.d.ts.map +1 -1
- package/dist/src/prompts/index.js +23 -6
- package/dist/src/prompts/index.js.map +1 -1
- package/dist/src/prompts/validated-pattern-prompts.d.ts +33 -0
- package/dist/src/prompts/validated-pattern-prompts.d.ts.map +1 -0
- package/dist/src/prompts/validated-pattern-prompts.js +337 -0
- package/dist/src/prompts/validated-pattern-prompts.js.map +1 -0
- package/dist/src/resources/adr-by-id-resource.d.ts +116 -0
- package/dist/src/resources/adr-by-id-resource.d.ts.map +1 -0
- package/dist/src/resources/adr-by-id-resource.js +213 -0
- package/dist/src/resources/adr-by-id-resource.js.map +1 -0
- package/dist/src/resources/code-quality-resource.d.ts +105 -0
- package/dist/src/resources/code-quality-resource.d.ts.map +1 -0
- package/dist/src/resources/code-quality-resource.js +282 -0
- package/dist/src/resources/code-quality-resource.js.map +1 -0
- package/dist/src/resources/deployment-history-resource.d.ts +214 -0
- package/dist/src/resources/deployment-history-resource.d.ts.map +1 -0
- package/dist/src/resources/deployment-history-resource.js +308 -0
- package/dist/src/resources/deployment-history-resource.js.map +1 -0
- package/dist/src/resources/deployment-status-resource.d.ts +256 -0
- package/dist/src/resources/deployment-status-resource.d.ts.map +1 -0
- package/dist/src/resources/deployment-status-resource.js +665 -0
- package/dist/src/resources/deployment-status-resource.js.map +1 -0
- package/dist/src/resources/environment-analysis-resource.d.ts +237 -0
- package/dist/src/resources/environment-analysis-resource.d.ts.map +1 -0
- package/dist/src/resources/environment-analysis-resource.js +646 -0
- package/dist/src/resources/environment-analysis-resource.js.map +1 -0
- package/dist/src/resources/index.d.ts +6 -2
- package/dist/src/resources/index.d.ts.map +1 -1
- package/dist/src/resources/index.js +247 -492
- package/dist/src/resources/index.js.map +1 -1
- package/dist/src/resources/memory-snapshots-resource.d.ts +180 -0
- package/dist/src/resources/memory-snapshots-resource.d.ts.map +1 -0
- package/dist/src/resources/memory-snapshots-resource.js +847 -0
- package/dist/src/resources/memory-snapshots-resource.js.map +1 -0
- package/dist/src/resources/pattern-base-code-by-platform-resource.d.ts +35 -0
- package/dist/src/resources/pattern-base-code-by-platform-resource.d.ts.map +1 -0
- package/dist/src/resources/pattern-base-code-by-platform-resource.js +72 -0
- package/dist/src/resources/pattern-base-code-by-platform-resource.js.map +1 -0
- package/dist/src/resources/pattern-by-name-resource.d.ts +53 -0
- package/dist/src/resources/pattern-by-name-resource.d.ts.map +1 -0
- package/dist/src/resources/pattern-by-name-resource.js +200 -0
- package/dist/src/resources/pattern-by-name-resource.js.map +1 -0
- package/dist/src/resources/pattern-sources-by-platform-resource.d.ts +26 -0
- package/dist/src/resources/pattern-sources-by-platform-resource.d.ts.map +1 -0
- package/dist/src/resources/pattern-sources-by-platform-resource.js +59 -0
- package/dist/src/resources/pattern-sources-by-platform-resource.js.map +1 -0
- package/dist/src/resources/project-metrics-resource.d.ts +180 -0
- package/dist/src/resources/project-metrics-resource.d.ts.map +1 -0
- package/dist/src/resources/project-metrics-resource.js +487 -0
- package/dist/src/resources/project-metrics-resource.js.map +1 -0
- package/dist/src/resources/project-status-resource.d.ts +75 -0
- package/dist/src/resources/project-status-resource.d.ts.map +1 -0
- package/dist/src/resources/project-status-resource.js +189 -0
- package/dist/src/resources/project-status-resource.js.map +1 -0
- package/dist/src/resources/research-by-topic-resource.d.ts +21 -0
- package/dist/src/resources/research-by-topic-resource.d.ts.map +1 -0
- package/dist/src/resources/research-by-topic-resource.js +125 -0
- package/dist/src/resources/research-by-topic-resource.js.map +1 -0
- package/dist/src/resources/research-index-resource.d.ts +100 -0
- package/dist/src/resources/research-index-resource.d.ts.map +1 -0
- package/dist/src/resources/research-index-resource.js +200 -0
- package/dist/src/resources/research-index-resource.js.map +1 -0
- package/dist/src/resources/resource-cache.d.ts +144 -0
- package/dist/src/resources/resource-cache.d.ts.map +1 -0
- package/dist/src/resources/resource-cache.js +316 -0
- package/dist/src/resources/resource-cache.js.map +1 -0
- package/dist/src/resources/resource-router.d.ts +45 -0
- package/dist/src/resources/resource-router.d.ts.map +1 -0
- package/dist/src/resources/resource-router.js +96 -0
- package/dist/src/resources/resource-router.js.map +1 -0
- package/dist/src/resources/rule-by-id-resource.d.ts +38 -0
- package/dist/src/resources/rule-by-id-resource.d.ts.map +1 -0
- package/dist/src/resources/rule-by-id-resource.js +104 -0
- package/dist/src/resources/rule-by-id-resource.js.map +1 -0
- package/dist/src/resources/rule-catalog-resource.d.ts +126 -0
- package/dist/src/resources/rule-catalog-resource.d.ts.map +1 -0
- package/dist/src/resources/rule-catalog-resource.js +224 -0
- package/dist/src/resources/rule-catalog-resource.js.map +1 -0
- package/dist/src/resources/rule-generation-resource.d.ts +80 -0
- package/dist/src/resources/rule-generation-resource.d.ts.map +1 -0
- package/dist/src/resources/rule-generation-resource.js +282 -0
- package/dist/src/resources/rule-generation-resource.js.map +1 -0
- package/dist/src/resources/technology-by-name-resource.d.ts +43 -0
- package/dist/src/resources/technology-by-name-resource.d.ts.map +1 -0
- package/dist/src/resources/technology-by-name-resource.js +176 -0
- package/dist/src/resources/technology-by-name-resource.js.map +1 -0
- package/dist/src/resources/todo-by-id-resource.d.ts +46 -0
- package/dist/src/resources/todo-by-id-resource.d.ts.map +1 -0
- package/dist/src/resources/todo-by-id-resource.js +192 -0
- package/dist/src/resources/todo-by-id-resource.js.map +1 -0
- package/dist/src/resources/todo-list-resource.d.ts +96 -0
- package/dist/src/resources/todo-list-resource.d.ts.map +1 -0
- package/dist/src/resources/todo-list-resource.js +209 -0
- package/dist/src/resources/todo-list-resource.js.map +1 -0
- package/dist/src/resources/validated-pattern-by-platform-resource.d.ts +14 -0
- package/dist/src/resources/validated-pattern-by-platform-resource.d.ts.map +1 -0
- package/dist/src/resources/validated-pattern-by-platform-resource.js +45 -0
- package/dist/src/resources/validated-pattern-by-platform-resource.js.map +1 -0
- package/dist/src/resources/validated-patterns-catalog-resource.d.ts +36 -0
- package/dist/src/resources/validated-patterns-catalog-resource.d.ts.map +1 -0
- package/dist/src/resources/validated-patterns-catalog-resource.js +57 -0
- package/dist/src/resources/validated-patterns-catalog-resource.js.map +1 -0
- package/dist/src/templates/domain-knowledge-templates.d.ts.map +1 -1
- package/dist/src/templates/domain-knowledge-templates.js +49 -49
- package/dist/src/templates/domain-knowledge-templates.js.map +1 -1
- package/dist/src/tools/adr-bootstrap-validation-tool.d.ts.map +1 -1
- package/dist/src/tools/adr-bootstrap-validation-tool.js +214 -4
- package/dist/src/tools/adr-bootstrap-validation-tool.js.map +1 -1
- package/dist/src/tools/adr-suggestion-tool.d.ts +2 -2
- package/dist/src/tools/adr-suggestion-tool.d.ts.map +1 -1
- package/dist/src/tools/adr-suggestion-tool.js +129 -12
- package/dist/src/tools/adr-suggestion-tool.js.map +1 -1
- package/dist/src/tools/adr-validation-tool.d.ts +98 -0
- package/dist/src/tools/adr-validation-tool.d.ts.map +1 -0
- package/dist/src/tools/adr-validation-tool.js +372 -0
- package/dist/src/tools/adr-validation-tool.js.map +1 -0
- package/dist/src/tools/bootstrap-validation-loop-tool.d.ts +262 -0
- package/dist/src/tools/bootstrap-validation-loop-tool.d.ts.map +1 -0
- package/dist/src/tools/bootstrap-validation-loop-tool.js +1934 -0
- package/dist/src/tools/bootstrap-validation-loop-tool.js.map +1 -0
- package/dist/src/tools/conversation-memory-tool.d.ts +48 -0
- package/dist/src/tools/conversation-memory-tool.d.ts.map +1 -0
- package/dist/src/tools/conversation-memory-tool.js +254 -0
- package/dist/src/tools/conversation-memory-tool.js.map +1 -0
- package/dist/src/tools/deployment-analysis-tool.d.ts.map +1 -1
- package/dist/src/tools/deployment-analysis-tool.js +82 -6
- package/dist/src/tools/deployment-analysis-tool.js.map +1 -1
- package/dist/src/tools/deployment-guidance-tool.d.ts.map +1 -1
- package/dist/src/tools/deployment-guidance-tool.js +126 -25
- package/dist/src/tools/deployment-guidance-tool.js.map +1 -1
- package/dist/src/tools/deployment-readiness-tool.d.ts.map +1 -1
- package/dist/src/tools/deployment-readiness-tool.js +166 -5
- package/dist/src/tools/deployment-readiness-tool.js.map +1 -1
- package/dist/src/tools/environment-analysis-tool.d.ts.map +1 -1
- package/dist/src/tools/environment-analysis-tool.js +36 -1
- package/dist/src/tools/environment-analysis-tool.js.map +1 -1
- package/dist/src/tools/expand-analysis-tool.d.ts +23 -0
- package/dist/src/tools/expand-analysis-tool.d.ts.map +1 -0
- package/dist/src/tools/expand-analysis-tool.js +107 -0
- package/dist/src/tools/expand-analysis-tool.js.map +1 -0
- package/dist/src/tools/get-server-context-tool.d.ts +67 -0
- package/dist/src/tools/get-server-context-tool.d.ts.map +1 -0
- package/dist/src/tools/get-server-context-tool.js +75 -0
- package/dist/src/tools/get-server-context-tool.js.map +1 -0
- package/dist/src/tools/interactive-adr-planning-tool.d.ts.map +1 -1
- package/dist/src/tools/interactive-adr-planning-tool.js +82 -9
- package/dist/src/tools/interactive-adr-planning-tool.js.map +1 -1
- package/dist/src/tools/llm-cloud-management-tool.d.ts +62 -0
- package/dist/src/tools/llm-cloud-management-tool.d.ts.map +1 -0
- package/dist/src/tools/llm-cloud-management-tool.js +202 -0
- package/dist/src/tools/llm-cloud-management-tool.js.map +1 -0
- package/dist/src/tools/llm-database-management-tool.d.ts +62 -0
- package/dist/src/tools/llm-database-management-tool.d.ts.map +1 -0
- package/dist/src/tools/llm-database-management-tool.js +203 -0
- package/dist/src/tools/llm-database-management-tool.js.map +1 -0
- package/dist/src/tools/llm-web-search-tool.d.ts +59 -0
- package/dist/src/tools/llm-web-search-tool.d.ts.map +1 -0
- package/dist/src/tools/llm-web-search-tool.js +165 -0
- package/dist/src/tools/llm-web-search-tool.js.map +1 -0
- package/dist/src/tools/mcp-planning-tool.d.ts.map +1 -1
- package/dist/src/tools/mcp-planning-tool.js +10 -3
- package/dist/src/tools/mcp-planning-tool.js.map +1 -1
- package/dist/src/tools/memory-loading-tool.d.ts.map +1 -1
- package/dist/src/tools/memory-loading-tool.js +4 -2
- package/dist/src/tools/memory-loading-tool.js.map +1 -1
- package/dist/src/tools/perform-research-tool.d.ts +61 -0
- package/dist/src/tools/perform-research-tool.d.ts.map +1 -0
- package/dist/src/tools/perform-research-tool.js +324 -0
- package/dist/src/tools/perform-research-tool.js.map +1 -0
- package/dist/src/tools/research-question-tool.d.ts.map +1 -1
- package/dist/src/tools/research-question-tool.js +11 -9
- package/dist/src/tools/research-question-tool.js.map +1 -1
- package/dist/src/tools/review-existing-adrs-tool.d.ts.map +1 -1
- package/dist/src/tools/review-existing-adrs-tool.js +42 -3
- package/dist/src/tools/review-existing-adrs-tool.js.map +1 -1
- package/dist/src/tools/tool-chain-orchestrator.d.ts +15 -94
- package/dist/src/tools/tool-chain-orchestrator.d.ts.map +1 -1
- package/dist/src/tools/tool-chain-orchestrator.js +2 -2
- package/dist/src/tools/tool-chain-orchestrator.js.map +1 -1
- package/dist/src/tools/troubleshoot-guided-workflow-tool.d.ts +25 -120
- package/dist/src/tools/troubleshoot-guided-workflow-tool.d.ts.map +1 -1
- package/dist/src/tools/troubleshoot-guided-workflow-tool.js +91 -2
- package/dist/src/tools/troubleshoot-guided-workflow-tool.js.map +1 -1
- package/dist/src/types/ape-framework.d.ts +50 -283
- package/dist/src/types/ape-framework.d.ts.map +1 -1
- package/dist/src/types/conversation-context.d.ts.map +1 -1
- package/dist/src/types/conversation-context.js +12 -12
- package/dist/src/types/conversation-context.js.map +1 -1
- package/dist/src/types/conversation-memory.d.ts +184 -0
- package/dist/src/types/conversation-memory.d.ts.map +1 -0
- package/dist/src/types/conversation-memory.js +8 -0
- package/dist/src/types/conversation-memory.js.map +1 -0
- package/dist/src/types/index.d.ts +112 -339
- package/dist/src/types/index.d.ts.map +1 -1
- package/dist/src/types/knowledge-generation.d.ts +96 -401
- package/dist/src/types/knowledge-generation.d.ts.map +1 -1
- package/dist/src/types/knowledge-graph-schemas.d.ts +77 -715
- package/dist/src/types/knowledge-graph-schemas.d.ts.map +1 -1
- package/dist/src/types/knowledge-graph-schemas.js +8 -8
- package/dist/src/types/knowledge-graph-schemas.js.map +1 -1
- package/dist/src/types/memory-entities.d.ts +1230 -6164
- package/dist/src/types/memory-entities.d.ts.map +1 -1
- package/dist/src/types/memory-entities.js +8 -8
- package/dist/src/types/memory-entities.js.map +1 -1
- package/dist/src/types/reflexion-framework.d.ts +35 -264
- package/dist/src/types/reflexion-framework.d.ts.map +1 -1
- package/dist/src/types/reflexion-framework.js +1 -1
- package/dist/src/types/reflexion-framework.js.map +1 -1
- package/dist/src/types/state-reinforcement.d.ts +87 -0
- package/dist/src/types/state-reinforcement.d.ts.map +1 -0
- package/dist/src/types/state-reinforcement.js +5 -0
- package/dist/src/types/state-reinforcement.js.map +1 -0
- package/dist/src/types/tiered-response.d.ts +61 -0
- package/dist/src/types/tiered-response.d.ts.map +1 -0
- package/dist/src/types/tiered-response.js +8 -0
- package/dist/src/types/tiered-response.js.map +1 -0
- package/dist/src/types/tool-context.d.ts +50 -0
- package/dist/src/types/tool-context.d.ts.map +1 -0
- package/dist/src/types/tool-context.js +20 -0
- package/dist/src/types/tool-context.js.map +1 -0
- package/dist/src/utils/adr-action-analyzer.d.ts +23 -0
- package/dist/src/utils/adr-action-analyzer.d.ts.map +1 -0
- package/dist/src/utils/adr-action-analyzer.js +323 -0
- package/dist/src/utils/adr-action-analyzer.js.map +1 -0
- package/dist/src/utils/adr-context-detector.d.ts +33 -0
- package/dist/src/utils/adr-context-detector.d.ts.map +1 -0
- package/dist/src/utils/adr-context-detector.js +279 -0
- package/dist/src/utils/adr-context-detector.js.map +1 -0
- package/dist/src/utils/adr-discovery.d.ts +28 -2
- package/dist/src/utils/adr-discovery.d.ts.map +1 -1
- package/dist/src/utils/adr-discovery.js +91 -7
- package/dist/src/utils/adr-discovery.js.map +1 -1
- package/dist/src/utils/adr-knowledge-initializer.d.ts +54 -0
- package/dist/src/utils/adr-knowledge-initializer.d.ts.map +1 -0
- package/dist/src/utils/adr-knowledge-initializer.js +240 -0
- package/dist/src/utils/adr-knowledge-initializer.js.map +1 -0
- package/dist/src/utils/adr-timeline-extractor.d.ts +21 -0
- package/dist/src/utils/adr-timeline-extractor.d.ts.map +1 -0
- package/dist/src/utils/adr-timeline-extractor.js +294 -0
- package/dist/src/utils/adr-timeline-extractor.js.map +1 -0
- package/dist/src/utils/adr-timeline-types.d.ts +234 -0
- package/dist/src/utils/adr-timeline-types.d.ts.map +1 -0
- package/dist/src/utils/adr-timeline-types.js +7 -0
- package/dist/src/utils/adr-timeline-types.js.map +1 -0
- package/dist/src/utils/ai-executor.d.ts +36 -0
- package/dist/src/utils/ai-executor.d.ts.map +1 -1
- package/dist/src/utils/ai-executor.js +39 -3
- package/dist/src/utils/ai-executor.js.map +1 -1
- package/dist/src/utils/apply-cot-enhancement.d.ts.map +1 -1
- package/dist/src/utils/apply-cot-enhancement.js +15 -15
- package/dist/src/utils/apply-cot-enhancement.js.map +1 -1
- package/dist/src/utils/automatic-prompt-engineering.d.ts.map +1 -1
- package/dist/src/utils/automatic-prompt-engineering.js +68 -58
- package/dist/src/utils/automatic-prompt-engineering.js.map +1 -1
- package/dist/src/utils/conditional-request.d.ts +105 -0
- package/dist/src/utils/conditional-request.d.ts.map +1 -0
- package/dist/src/utils/conditional-request.js +186 -0
- package/dist/src/utils/conditional-request.js.map +1 -0
- package/dist/src/utils/config.d.ts +72 -18
- package/dist/src/utils/config.d.ts.map +1 -1
- package/dist/src/utils/config.js +75 -0
- package/dist/src/utils/config.js.map +1 -1
- package/dist/src/utils/context-document-manager.d.ts +112 -0
- package/dist/src/utils/context-document-manager.d.ts.map +1 -0
- package/dist/src/utils/context-document-manager.js +351 -0
- package/dist/src/utils/context-document-manager.js.map +1 -0
- package/dist/src/utils/conversation-memory-manager.d.ts +86 -0
- package/dist/src/utils/conversation-memory-manager.d.ts.map +1 -0
- package/dist/src/utils/conversation-memory-manager.js +443 -0
- package/dist/src/utils/conversation-memory-manager.js.map +1 -0
- package/dist/src/utils/dag-executor.d.ts +106 -0
- package/dist/src/utils/dag-executor.d.ts.map +1 -0
- package/dist/src/utils/dag-executor.js +453 -0
- package/dist/src/utils/dag-executor.js.map +1 -0
- package/dist/src/utils/deployment-analysis.d.ts.map +1 -1
- package/dist/src/utils/deployment-analysis.js +17 -9
- package/dist/src/utils/deployment-analysis.js.map +1 -1
- package/dist/src/utils/deployment-type-registry.d.ts +52 -0
- package/dist/src/utils/deployment-type-registry.d.ts.map +1 -0
- package/dist/src/utils/deployment-type-registry.js +543 -0
- package/dist/src/utils/deployment-type-registry.js.map +1 -0
- package/dist/src/utils/dynamic-deployment-intelligence.d.ts +117 -0
- package/dist/src/utils/dynamic-deployment-intelligence.d.ts.map +1 -0
- package/dist/src/utils/dynamic-deployment-intelligence.js +445 -0
- package/dist/src/utils/dynamic-deployment-intelligence.js.map +1 -0
- package/dist/src/utils/environment-analysis.d.ts.map +1 -1
- package/dist/src/utils/environment-analysis.js +63 -44
- package/dist/src/utils/environment-analysis.js.map +1 -1
- package/dist/src/utils/environment-capability-registry.d.ts +101 -0
- package/dist/src/utils/environment-capability-registry.d.ts.map +1 -0
- package/dist/src/utils/environment-capability-registry.js +489 -0
- package/dist/src/utils/environment-capability-registry.js.map +1 -0
- package/dist/src/utils/index.d.ts +3 -3
- package/dist/src/utils/index.d.ts.map +1 -1
- package/dist/src/utils/index.js +3 -3
- package/dist/src/utils/index.js.map +1 -1
- package/dist/src/utils/knowledge-generation.d.ts.map +1 -1
- package/dist/src/utils/knowledge-generation.js +61 -35
- package/dist/src/utils/knowledge-generation.js.map +1 -1
- package/dist/src/utils/knowledge-graph-manager.d.ts +19 -0
- package/dist/src/utils/knowledge-graph-manager.d.ts.map +1 -1
- package/dist/src/utils/knowledge-graph-manager.js +165 -1
- package/dist/src/utils/knowledge-graph-manager.js.map +1 -1
- package/dist/src/utils/llm-artifact-detector.d.ts.map +1 -1
- package/dist/src/utils/llm-artifact-detector.js +28 -24
- package/dist/src/utils/llm-artifact-detector.js.map +1 -1
- package/dist/src/utils/mermaid-diagrams.d.ts +101 -0
- package/dist/src/utils/mermaid-diagrams.d.ts.map +1 -0
- package/dist/src/utils/mermaid-diagrams.js +445 -0
- package/dist/src/utils/mermaid-diagrams.js.map +1 -0
- package/dist/src/utils/monitoring.d.ts +249 -0
- package/dist/src/utils/monitoring.d.ts.map +1 -0
- package/dist/src/utils/monitoring.js +513 -0
- package/dist/src/utils/monitoring.js.map +1 -0
- package/dist/src/utils/pattern-contribution-helper.d.ts +60 -0
- package/dist/src/utils/pattern-contribution-helper.d.ts.map +1 -0
- package/dist/src/utils/pattern-contribution-helper.js +308 -0
- package/dist/src/utils/pattern-contribution-helper.js.map +1 -0
- package/dist/src/utils/pattern-loader.d.ts +183 -0
- package/dist/src/utils/pattern-loader.d.ts.map +1 -0
- package/dist/src/utils/pattern-loader.js +200 -0
- package/dist/src/utils/pattern-loader.js.map +1 -0
- package/dist/src/utils/pattern-research-utility.d.ts +107 -0
- package/dist/src/utils/pattern-research-utility.d.ts.map +1 -0
- package/dist/src/utils/pattern-research-utility.js +360 -0
- package/dist/src/utils/pattern-research-utility.js.map +1 -0
- package/dist/src/utils/pattern-to-dag-converter.d.ts +62 -0
- package/dist/src/utils/pattern-to-dag-converter.d.ts.map +1 -0
- package/dist/src/utils/pattern-to-dag-converter.js +265 -0
- package/dist/src/utils/pattern-to-dag-converter.js.map +1 -0
- package/dist/src/utils/platform-detector.d.ts +86 -0
- package/dist/src/utils/platform-detector.d.ts.map +1 -0
- package/dist/src/utils/platform-detector.js +509 -0
- package/dist/src/utils/platform-detector.js.map +1 -0
- package/dist/src/utils/prompt-composition.d.ts.map +1 -1
- package/dist/src/utils/prompt-composition.js +1 -4
- package/dist/src/utils/prompt-composition.js.map +1 -1
- package/dist/src/utils/reflexion.d.ts.map +1 -1
- package/dist/src/utils/reflexion.js +51 -42
- package/dist/src/utils/reflexion.js.map +1 -1
- package/dist/src/utils/research-integration.d.ts.map +1 -1
- package/dist/src/utils/research-integration.js +8 -2
- package/dist/src/utils/research-integration.js.map +1 -1
- package/dist/src/utils/research-orchestrator.d.ts +209 -0
- package/dist/src/utils/research-orchestrator.d.ts.map +1 -0
- package/dist/src/utils/research-orchestrator.js +863 -0
- package/dist/src/utils/research-orchestrator.js.map +1 -0
- package/dist/src/utils/research-questions.d.ts.map +1 -1
- package/dist/src/utils/research-questions.js +4 -1
- package/dist/src/utils/research-questions.js.map +1 -1
- package/dist/src/utils/resource-extractor.d.ts +57 -0
- package/dist/src/utils/resource-extractor.d.ts.map +1 -0
- package/dist/src/utils/resource-extractor.js +323 -0
- package/dist/src/utils/resource-extractor.js.map +1 -0
- package/dist/src/utils/resource-versioning.d.ts +124 -0
- package/dist/src/utils/resource-versioning.d.ts.map +1 -0
- package/dist/src/utils/resource-versioning.js +272 -0
- package/dist/src/utils/resource-versioning.js.map +1 -0
- package/dist/src/utils/root-manager.d.ts +118 -0
- package/dist/src/utils/root-manager.d.ts.map +1 -0
- package/dist/src/utils/root-manager.js +154 -0
- package/dist/src/utils/root-manager.js.map +1 -0
- package/dist/src/utils/rule-generation.d.ts.map +1 -1
- package/dist/src/utils/rule-generation.js +4 -1
- package/dist/src/utils/rule-generation.js.map +1 -1
- package/dist/src/utils/server-context-generator.d.ts +47 -0
- package/dist/src/utils/server-context-generator.d.ts.map +1 -0
- package/dist/src/utils/server-context-generator.js +666 -0
- package/dist/src/utils/server-context-generator.js.map +1 -0
- package/dist/src/utils/state-reinforcement-manager.d.ts +60 -0
- package/dist/src/utils/state-reinforcement-manager.d.ts.map +1 -0
- package/dist/src/utils/state-reinforcement-manager.js +200 -0
- package/dist/src/utils/state-reinforcement-manager.js.map +1 -0
- package/dist/src/utils/system-card-manager.d.ts +194 -0
- package/dist/src/utils/system-card-manager.d.ts.map +1 -0
- package/dist/src/utils/system-card-manager.js +336 -0
- package/dist/src/utils/system-card-manager.js.map +1 -0
- package/dist/src/utils/tiered-response-manager.d.ts +40 -0
- package/dist/src/utils/tiered-response-manager.d.ts.map +1 -0
- package/dist/src/utils/tiered-response-manager.js +243 -0
- package/dist/src/utils/tiered-response-manager.js.map +1 -0
- package/dist/src/utils/tree-sitter-analyzer.d.ts.map +1 -1
- package/dist/src/utils/tree-sitter-analyzer.js +83 -11
- package/dist/src/utils/tree-sitter-analyzer.js.map +1 -1
- package/dist/src/utils/validated-pattern-definitions.d.ts +219 -0
- package/dist/src/utils/validated-pattern-definitions.d.ts.map +1 -0
- package/dist/src/utils/validated-pattern-definitions.js +1511 -0
- package/dist/src/utils/validated-pattern-definitions.js.map +1 -0
- package/package.json +22 -13
- package/dist/src/prompts/todo-prompts.d.ts +0 -49
- package/dist/src/prompts/todo-prompts.d.ts.map +0 -1
- package/dist/src/prompts/todo-prompts.js +0 -824
- package/dist/src/prompts/todo-prompts.js.map +0 -1
- package/dist/src/types/todo-json-schemas.d.ts +0 -17
- package/dist/src/types/todo-json-schemas.d.ts.map +0 -1
- package/dist/src/types/todo-json-schemas.js +0 -9
- package/dist/src/types/todo-json-schemas.js.map +0 -1
- package/dist/src/utils/todo-file-watcher.d.ts +0 -14
- package/dist/src/utils/todo-file-watcher.d.ts.map +0 -1
- package/dist/src/utils/todo-file-watcher.js +0 -25
- package/dist/src/utils/todo-file-watcher.js.map +0 -1
|
@@ -0,0 +1,863 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Research Orchestrator
|
|
3
|
+
*
|
|
4
|
+
* Coordinates multi-source research with cascading fallback:
|
|
5
|
+
* 1. Project Files (local, fast, free)
|
|
6
|
+
* 2. Knowledge Graph (in-memory, instant)
|
|
7
|
+
* 3. Environment Resources (live runtime data)
|
|
8
|
+
* 4. Web Search (external, last resort)
|
|
9
|
+
*/
|
|
10
|
+
import { promises as fs } from 'fs';
|
|
11
|
+
import * as path from 'path';
|
|
12
|
+
import crypto from 'crypto';
|
|
13
|
+
import { EnhancedLogger } from './enhanced-logging.js';
|
|
14
|
+
import { KnowledgeGraphManager } from './knowledge-graph-manager.js';
|
|
15
|
+
import { findFiles } from './file-system.js';
|
|
16
|
+
import { scanProjectStructure } from './actual-file-operations.js';
|
|
17
|
+
import { searchWithRipgrep, isRipgrepAvailable } from './ripgrep-wrapper.js';
|
|
18
|
+
import { TreeSitterAnalyzer } from './tree-sitter-analyzer.js';
|
|
19
|
+
// import { FirecrawlApp } from '@mendable/firecrawl-js';
|
|
20
|
+
// import { loadAIConfig } from '../config/ai-config.js';
|
|
21
|
+
import { loadConfig } from './config.js';
|
|
22
|
+
/**
|
|
23
|
+
* Research Orchestrator Class
|
|
24
|
+
*
|
|
25
|
+
* @description Coordinates multi-source research with cascading fallback strategy.
|
|
26
|
+
* Implements a hierarchical approach to answering research questions by querying
|
|
27
|
+
* sources in order of preference: project files → knowledge graph → environment → web search.
|
|
28
|
+
*
|
|
29
|
+
* Features:
|
|
30
|
+
* - Intelligent confidence scoring for each source
|
|
31
|
+
* - Configurable confidence thresholds
|
|
32
|
+
* - Result caching for performance optimization
|
|
33
|
+
* - Firecrawl integration for web search capabilities
|
|
34
|
+
* - Comprehensive error handling and fallback mechanisms
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```typescript
|
|
38
|
+
* const orchestrator = new ResearchOrchestrator('/path/to/project', 'docs/adrs');
|
|
39
|
+
* orchestrator.setConfidenceThreshold(0.8);
|
|
40
|
+
*
|
|
41
|
+
* const result = await orchestrator.answerResearchQuestion(
|
|
42
|
+
* 'What authentication methods are used in this project?'
|
|
43
|
+
* );
|
|
44
|
+
*
|
|
45
|
+
* console.log(`Answer: ${result.answer}`);
|
|
46
|
+
* console.log(`Confidence: ${result.confidence}`);
|
|
47
|
+
* console.log(`Sources: ${result.sources.map(s => s.type).join(', ')}`);
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* @since 2.0.0
|
|
51
|
+
* @category Research
|
|
52
|
+
* @category Orchestration
|
|
53
|
+
*/
|
|
54
|
+
export class ResearchOrchestrator {
|
|
55
|
+
logger;
|
|
56
|
+
projectPath;
|
|
57
|
+
adrDirectory;
|
|
58
|
+
confidenceThreshold = 0.6;
|
|
59
|
+
kgManager;
|
|
60
|
+
cache = new Map();
|
|
61
|
+
cacheTtl = 5 * 60 * 1000; // 5 minutes
|
|
62
|
+
firecrawl; // FirecrawlApp type
|
|
63
|
+
config; // ServerConfig type
|
|
64
|
+
constructor(projectPath, adrDirectory) {
|
|
65
|
+
this.logger = new EnhancedLogger();
|
|
66
|
+
this.projectPath = projectPath || process.cwd();
|
|
67
|
+
this.adrDirectory = adrDirectory || 'docs/adrs';
|
|
68
|
+
this.kgManager = new KnowledgeGraphManager();
|
|
69
|
+
// Load server configuration
|
|
70
|
+
this.config = loadConfig();
|
|
71
|
+
// Initialize Firecrawl if enabled
|
|
72
|
+
if (this.config.firecrawlEnabled) {
|
|
73
|
+
// TODO: Uncomment when @mendable/firecrawl-js is installed
|
|
74
|
+
// this.firecrawl = new FirecrawlApp({
|
|
75
|
+
// apiKey: this.config.firecrawlApiKey,
|
|
76
|
+
// baseUrl: this.config.firecrawlBaseUrl
|
|
77
|
+
// });
|
|
78
|
+
this.firecrawl = null; // Placeholder until Firecrawl is available
|
|
79
|
+
this.logger.info('Firecrawl integration enabled', 'ResearchOrchestrator');
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
this.firecrawl = null;
|
|
83
|
+
this.logger.info('Firecrawl integration disabled', 'ResearchOrchestrator');
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Answer a research question using cascading source hierarchy
|
|
88
|
+
*
|
|
89
|
+
* @description Executes comprehensive research using a cascading approach:
|
|
90
|
+
* 1. Project files search (fastest, most relevant)
|
|
91
|
+
* 2. Knowledge graph query (instant, context-aware)
|
|
92
|
+
* 3. Environment resources query (live data)
|
|
93
|
+
* 4. Web search fallback (external, when confidence is low)
|
|
94
|
+
*
|
|
95
|
+
* Results are cached for 5 minutes to improve performance for repeated queries.
|
|
96
|
+
*
|
|
97
|
+
* @param {string} question - The research question to investigate
|
|
98
|
+
*
|
|
99
|
+
* @returns {Promise<ResearchAnswer>} Comprehensive research results with:
|
|
100
|
+
* - `answer`: Synthesized answer from all sources
|
|
101
|
+
* - `confidence`: Overall confidence score (0-1)
|
|
102
|
+
* - `sources`: Array of source results with individual confidence scores
|
|
103
|
+
* - `needsWebSearch`: Whether web search is recommended
|
|
104
|
+
* - `metadata`: Execution metadata (duration, files analyzed, etc.)
|
|
105
|
+
*
|
|
106
|
+
* @throws {Error} When question is empty or research orchestration fails
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```typescript
|
|
110
|
+
* const result = await orchestrator.answerResearchQuestion(
|
|
111
|
+
* 'How does authentication work in this project?'
|
|
112
|
+
* );
|
|
113
|
+
*
|
|
114
|
+
* if (result.confidence >= 0.8) {
|
|
115
|
+
* console.log('High confidence answer:', result.answer);
|
|
116
|
+
* } else if (result.needsWebSearch) {
|
|
117
|
+
* console.log('Consider web search for more information');
|
|
118
|
+
* }
|
|
119
|
+
*
|
|
120
|
+
* result.sources.forEach(source => {
|
|
121
|
+
* console.log(`${source.type}: ${(source.confidence * 100).toFixed(1)}%`);
|
|
122
|
+
* });
|
|
123
|
+
* ```
|
|
124
|
+
*
|
|
125
|
+
* @since 2.0.0
|
|
126
|
+
* @category Research
|
|
127
|
+
* @category Public API
|
|
128
|
+
*/
|
|
129
|
+
async answerResearchQuestion(question) {
|
|
130
|
+
const startTime = Date.now();
|
|
131
|
+
// Check cache first
|
|
132
|
+
const cacheKey = this.generateCacheKey(question);
|
|
133
|
+
const cached = this.getCachedResult(cacheKey);
|
|
134
|
+
if (cached) {
|
|
135
|
+
this.logger.info(`Cache hit for question: "${question}"`, 'ResearchOrchestrator');
|
|
136
|
+
return cached;
|
|
137
|
+
}
|
|
138
|
+
this.logger.info(`Starting research for question: "${question}"`, 'ResearchOrchestrator');
|
|
139
|
+
const answer = {
|
|
140
|
+
question,
|
|
141
|
+
sources: [],
|
|
142
|
+
confidence: 0,
|
|
143
|
+
needsWebSearch: false,
|
|
144
|
+
metadata: {
|
|
145
|
+
duration: 0,
|
|
146
|
+
sourcesQueried: [],
|
|
147
|
+
filesAnalyzed: 0,
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
try {
|
|
151
|
+
// SOURCE 1: PROJECT FILES
|
|
152
|
+
this.logger.info('📁 Searching project files...', 'ResearchOrchestrator');
|
|
153
|
+
const projectData = await this.searchProjectFiles(question);
|
|
154
|
+
if (projectData.found) {
|
|
155
|
+
answer.sources.push({
|
|
156
|
+
type: 'project_files',
|
|
157
|
+
data: projectData,
|
|
158
|
+
confidence: 0.9,
|
|
159
|
+
timestamp: new Date().toISOString(),
|
|
160
|
+
});
|
|
161
|
+
answer.metadata.sourcesQueried.push('project_files');
|
|
162
|
+
answer.metadata.filesAnalyzed = projectData.files?.length || 0;
|
|
163
|
+
this.logger.info(`Found ${projectData.files?.length || 0} relevant project files`, 'ResearchOrchestrator');
|
|
164
|
+
}
|
|
165
|
+
// SOURCE 2: KNOWLEDGE GRAPH
|
|
166
|
+
this.logger.info('🧠 Querying knowledge graph...', 'ResearchOrchestrator');
|
|
167
|
+
const knowledgeData = await this.queryKnowledgeGraph(question);
|
|
168
|
+
// Always add to sources queried and sources (even if empty)
|
|
169
|
+
answer.metadata.sourcesQueried.push('knowledge_graph');
|
|
170
|
+
answer.sources.push({
|
|
171
|
+
type: 'knowledge_graph',
|
|
172
|
+
found: knowledgeData.found,
|
|
173
|
+
data: knowledgeData,
|
|
174
|
+
confidence: knowledgeData.found ? 0.85 : 0,
|
|
175
|
+
timestamp: new Date().toISOString(),
|
|
176
|
+
});
|
|
177
|
+
if (knowledgeData.found) {
|
|
178
|
+
this.logger.info(`Found ${knowledgeData.nodes?.length || 0} relevant knowledge graph nodes`, 'ResearchOrchestrator');
|
|
179
|
+
}
|
|
180
|
+
// SOURCE 3: ENVIRONMENT RESOURCES
|
|
181
|
+
this.logger.info('🔧 Checking environment resources...', 'ResearchOrchestrator');
|
|
182
|
+
const envData = await this.queryEnvironment(question);
|
|
183
|
+
if (envData.found) {
|
|
184
|
+
answer.sources.push({
|
|
185
|
+
type: 'environment',
|
|
186
|
+
data: envData,
|
|
187
|
+
confidence: 0.95,
|
|
188
|
+
timestamp: new Date().toISOString(),
|
|
189
|
+
});
|
|
190
|
+
answer.metadata.sourcesQueried.push('environment');
|
|
191
|
+
this.logger.info(`Found environment data from ${envData.capabilities?.length || 0} capabilities`, 'ResearchOrchestrator');
|
|
192
|
+
}
|
|
193
|
+
// Calculate overall confidence
|
|
194
|
+
answer.confidence = this.calculateConfidence(answer.sources);
|
|
195
|
+
this.logger.info(`Research confidence: ${(answer.confidence * 100).toFixed(1)}%`, 'ResearchOrchestrator');
|
|
196
|
+
// SOURCE 4: WEB SEARCH (fallback)
|
|
197
|
+
if (answer.confidence < this.confidenceThreshold) {
|
|
198
|
+
this.logger.warn(`Confidence below threshold (${this.confidenceThreshold}), attempting web search`, 'ResearchOrchestrator');
|
|
199
|
+
try {
|
|
200
|
+
const webSearchData = await this.performWebSearch(question);
|
|
201
|
+
if (webSearchData.found) {
|
|
202
|
+
answer.sources.push({
|
|
203
|
+
type: 'web_search',
|
|
204
|
+
data: webSearchData,
|
|
205
|
+
confidence: 0.7, // Web search has lower confidence
|
|
206
|
+
timestamp: new Date().toISOString(),
|
|
207
|
+
});
|
|
208
|
+
answer.metadata.sourcesQueried.push('web_search');
|
|
209
|
+
// Recalculate confidence with web search
|
|
210
|
+
answer.confidence = this.calculateConfidence(answer.sources);
|
|
211
|
+
this.logger.info(`Web search found ${webSearchData.results?.length || 0} results`, 'ResearchOrchestrator');
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
answer.needsWebSearch = true;
|
|
215
|
+
this.logger.warn('Web search failed or returned no results', 'ResearchOrchestrator');
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
catch (error) {
|
|
219
|
+
this.logger.error('Web search failed', 'ResearchOrchestrator', error);
|
|
220
|
+
answer.needsWebSearch = true;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
// Generate synthesized answer
|
|
224
|
+
answer.answer = this.synthesizeAnswer(answer);
|
|
225
|
+
answer.metadata.duration = Date.now() - startTime;
|
|
226
|
+
// Cache the result
|
|
227
|
+
this.setCachedResult(cacheKey, answer);
|
|
228
|
+
this.logger.info(`Research completed in ${answer.metadata.duration}ms`, 'ResearchOrchestrator', { confidence: answer.confidence, sources: answer.metadata.sourcesQueried });
|
|
229
|
+
return answer;
|
|
230
|
+
}
|
|
231
|
+
catch (_error) {
|
|
232
|
+
this.logger.error('Research orchestration failed', 'ResearchOrchestrator', _error);
|
|
233
|
+
throw _error;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* SOURCE 1: Search project files (Enhanced with tree-sitter, ripgrep, and actual file ops)
|
|
238
|
+
*/
|
|
239
|
+
async searchProjectFiles(question) {
|
|
240
|
+
const results = {
|
|
241
|
+
found: false,
|
|
242
|
+
files: [],
|
|
243
|
+
content: {},
|
|
244
|
+
relevance: {},
|
|
245
|
+
parseAnalysis: {},
|
|
246
|
+
};
|
|
247
|
+
try {
|
|
248
|
+
const questionLower = question.toLowerCase();
|
|
249
|
+
const keywords = this.extractKeywords(question);
|
|
250
|
+
this.logger.info(`Searching project files with keywords: ${keywords.join(', ')}`, 'ResearchOrchestrator');
|
|
251
|
+
// PHASE 1: Use actual-file-operations for structured project scan
|
|
252
|
+
const projectStructure = await scanProjectStructure(this.projectPath, {
|
|
253
|
+
readContent: false,
|
|
254
|
+
maxFileSize: 100000,
|
|
255
|
+
includeHidden: false,
|
|
256
|
+
});
|
|
257
|
+
// PHASE 2: Match relevant file categories based on question intent
|
|
258
|
+
const relevantFiles = [];
|
|
259
|
+
if (questionLower.match(/docker|container/i)) {
|
|
260
|
+
relevantFiles.push(...projectStructure.dockerFiles.map(f => f.path));
|
|
261
|
+
}
|
|
262
|
+
if (questionLower.match(/kubernetes|k8s|pod|deployment/i)) {
|
|
263
|
+
relevantFiles.push(...projectStructure.kubernetesFiles.map(f => f.path));
|
|
264
|
+
}
|
|
265
|
+
if (questionLower.match(/dependency|package|library/i)) {
|
|
266
|
+
relevantFiles.push(...projectStructure.packageFiles.map(f => f.path));
|
|
267
|
+
}
|
|
268
|
+
if (questionLower.match(/config|configuration|environment|env/i)) {
|
|
269
|
+
relevantFiles.push(...projectStructure.configFiles.map(f => f.path));
|
|
270
|
+
relevantFiles.push(...projectStructure.environmentFiles.map(f => f.path));
|
|
271
|
+
}
|
|
272
|
+
if (questionLower.match(/build|ci|cd|pipeline/i)) {
|
|
273
|
+
relevantFiles.push(...projectStructure.buildFiles.map(f => f.path));
|
|
274
|
+
relevantFiles.push(...projectStructure.ciFiles.map(f => f.path));
|
|
275
|
+
}
|
|
276
|
+
if (questionLower.match(/test|testing|spec/i)) {
|
|
277
|
+
// Use fast-glob to find test files
|
|
278
|
+
const testResults = await findFiles(this.projectPath, [
|
|
279
|
+
'**/*.test.ts',
|
|
280
|
+
'**/*.spec.ts',
|
|
281
|
+
'**/*.test.js',
|
|
282
|
+
'**/*.spec.js',
|
|
283
|
+
'**/tests/**',
|
|
284
|
+
'**/test/**',
|
|
285
|
+
]);
|
|
286
|
+
relevantFiles.push(...testResults.files.map(f => f.path));
|
|
287
|
+
}
|
|
288
|
+
// PHASE 3: Always include ADRs
|
|
289
|
+
const adrPath = path.join(this.projectPath, this.adrDirectory);
|
|
290
|
+
try {
|
|
291
|
+
const adrResults = await findFiles(adrPath, ['**/*.md']);
|
|
292
|
+
relevantFiles.push(...adrResults.files.map(f => f.path));
|
|
293
|
+
}
|
|
294
|
+
catch {
|
|
295
|
+
this.logger.warn(`ADR directory not found: ${adrPath}`, 'ResearchOrchestrator');
|
|
296
|
+
}
|
|
297
|
+
// PHASE 4: Use ripgrep for keyword search (if available)
|
|
298
|
+
const hasRipgrep = await isRipgrepAvailable();
|
|
299
|
+
if (hasRipgrep && keywords.length > 0) {
|
|
300
|
+
this.logger.info('Using ripgrep for fast keyword search', 'ResearchOrchestrator');
|
|
301
|
+
try {
|
|
302
|
+
const ripgrepFiles = await searchWithRipgrep({
|
|
303
|
+
pattern: keywords.join('|'),
|
|
304
|
+
path: this.projectPath,
|
|
305
|
+
caseInsensitive: true,
|
|
306
|
+
});
|
|
307
|
+
relevantFiles.push(...ripgrepFiles);
|
|
308
|
+
}
|
|
309
|
+
catch {
|
|
310
|
+
this.logger.warn('Ripgrep search failed, continuing with other methods', 'ResearchOrchestrator');
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
// Remove duplicates
|
|
314
|
+
results.files = [...new Set(relevantFiles)];
|
|
315
|
+
if (results.files.length === 0) {
|
|
316
|
+
this.logger.info('No relevant files found', 'ResearchOrchestrator');
|
|
317
|
+
return results;
|
|
318
|
+
}
|
|
319
|
+
results.found = true;
|
|
320
|
+
// PHASE 5: Read and analyze files with tree-sitter
|
|
321
|
+
const analyzer = new TreeSitterAnalyzer();
|
|
322
|
+
for (const file of results.files.slice(0, 50)) {
|
|
323
|
+
// Limit to 50 files for performance
|
|
324
|
+
try {
|
|
325
|
+
const content = await fs.readFile(file, 'utf-8');
|
|
326
|
+
// Calculate text-based relevance
|
|
327
|
+
const relevance = this.calculateRelevanceLegacy(content, question);
|
|
328
|
+
if (relevance > 0.2) {
|
|
329
|
+
// Lower threshold for tree-sitter analysis
|
|
330
|
+
results.content[file] = content;
|
|
331
|
+
results.relevance[file] = relevance;
|
|
332
|
+
// PHASE 6: Use tree-sitter for AST-based analysis
|
|
333
|
+
if (this.shouldParse(file)) {
|
|
334
|
+
try {
|
|
335
|
+
const analysis = await analyzer.analyzeFile(file, content);
|
|
336
|
+
// Enhance relevance based on AST analysis
|
|
337
|
+
let astRelevance = relevance;
|
|
338
|
+
// Check for infrastructure references
|
|
339
|
+
if (analysis.infraStructure && analysis.infraStructure.length > 0) {
|
|
340
|
+
// Extract provider types and resource names from infrastructure analysis
|
|
341
|
+
const infraProviders = analysis.infraStructure.map(i => i.provider);
|
|
342
|
+
const infraResources = analysis.infraStructure.map(i => i.name);
|
|
343
|
+
// Check if question keywords match infrastructure providers or resources
|
|
344
|
+
const matchingProviders = keywords.filter(k => infraProviders.some(p => p.toLowerCase().includes(k.toLowerCase())));
|
|
345
|
+
const matchingResources = keywords.filter(k => infraResources.some(r => r.toLowerCase().includes(k.toLowerCase())));
|
|
346
|
+
const totalMatches = matchingProviders.length + matchingResources.length;
|
|
347
|
+
if (totalMatches > 0) {
|
|
348
|
+
astRelevance += 0.2 * Math.min(totalMatches, 3); // Cap bonus at 0.6
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
// Check for imports/dependencies
|
|
352
|
+
if (analysis.imports && keywords.some(k => k.match(/import|require|dependency/i))) {
|
|
353
|
+
astRelevance += 0.1;
|
|
354
|
+
}
|
|
355
|
+
// Update relevance
|
|
356
|
+
results.relevance[file] = Math.min(astRelevance, 1.0);
|
|
357
|
+
results.parseAnalysis[file] = {
|
|
358
|
+
language: analysis.language,
|
|
359
|
+
hasInfrastructure: !!analysis.infraStructure,
|
|
360
|
+
functionCount: analysis.functions?.length || 0,
|
|
361
|
+
importCount: analysis.imports?.length || 0,
|
|
362
|
+
};
|
|
363
|
+
this.logger.debug(`Tree-sitter analysis for ${file}: ${analysis.language}, relevance: ${results.relevance[file]}`, 'ResearchOrchestrator');
|
|
364
|
+
}
|
|
365
|
+
catch {
|
|
366
|
+
this.logger.debug(`Tree-sitter parsing failed for ${file}, using text-based analysis`, 'ResearchOrchestrator');
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
catch {
|
|
372
|
+
this.logger.warn(`Failed to read file: ${file}`, 'ResearchOrchestrator');
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
// Sort files by relevance
|
|
376
|
+
results.files = results.files
|
|
377
|
+
.filter(f => (results.relevance[f] ?? 0) > 0.2)
|
|
378
|
+
.sort((a, b) => (results.relevance[b] || 0) - (results.relevance[a] || 0))
|
|
379
|
+
.slice(0, 20); // Top 20 most relevant files
|
|
380
|
+
this.logger.info(`Found ${results.files.length} relevant files (analyzed with tree-sitter)`, 'ResearchOrchestrator');
|
|
381
|
+
return results;
|
|
382
|
+
}
|
|
383
|
+
catch (error) {
|
|
384
|
+
this.logger.error('Project file search failed', 'ResearchOrchestrator', error);
|
|
385
|
+
return results;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Check if file should be parsed with tree-sitter
|
|
390
|
+
*/
|
|
391
|
+
shouldParse(filePath) {
|
|
392
|
+
const parsableExtensions = [
|
|
393
|
+
'.ts',
|
|
394
|
+
'.tsx',
|
|
395
|
+
'.js',
|
|
396
|
+
'.jsx',
|
|
397
|
+
'.py',
|
|
398
|
+
'.yaml',
|
|
399
|
+
'.yml',
|
|
400
|
+
'.json',
|
|
401
|
+
'.sh',
|
|
402
|
+
'.bash',
|
|
403
|
+
'.tf',
|
|
404
|
+
'.hcl',
|
|
405
|
+
];
|
|
406
|
+
return parsableExtensions.some(ext => filePath.endsWith(ext));
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* SOURCE 2: Query knowledge graph
|
|
410
|
+
*/
|
|
411
|
+
async queryKnowledgeGraph(question) {
|
|
412
|
+
try {
|
|
413
|
+
this.logger.debug(`Querying knowledge graph for: "${question}"`, 'ResearchOrchestrator');
|
|
414
|
+
// Query knowledge graph using KnowledgeGraphManager
|
|
415
|
+
const results = await this.kgManager.queryKnowledgeGraph(question);
|
|
416
|
+
if (results.found) {
|
|
417
|
+
this.logger.info(`Knowledge graph query found ${results.nodes.length} nodes, ${results.relationships.length} relationships`, 'ResearchOrchestrator', {
|
|
418
|
+
relevantIntents: results.relevantIntents.length,
|
|
419
|
+
relevantDecisions: results.relevantDecisions.length,
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
else {
|
|
423
|
+
this.logger.debug('No relevant knowledge graph data found', 'ResearchOrchestrator');
|
|
424
|
+
}
|
|
425
|
+
return results;
|
|
426
|
+
}
|
|
427
|
+
catch (error) {
|
|
428
|
+
this.logger.error('Knowledge graph query failed', 'ResearchOrchestrator', error);
|
|
429
|
+
return {
|
|
430
|
+
found: false,
|
|
431
|
+
nodes: [],
|
|
432
|
+
relationships: [],
|
|
433
|
+
relevantIntents: [],
|
|
434
|
+
relevantDecisions: [],
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* SOURCE 3: Query environment resources
|
|
440
|
+
*/
|
|
441
|
+
async queryEnvironment(question) {
|
|
442
|
+
try {
|
|
443
|
+
// Import dynamically to avoid circular dependencies
|
|
444
|
+
const { EnvironmentCapabilityRegistry } = await import('./environment-capability-registry.js');
|
|
445
|
+
const envRegistry = new EnvironmentCapabilityRegistry(this.projectPath);
|
|
446
|
+
// Discover available capabilities
|
|
447
|
+
await envRegistry.discoverCapabilities();
|
|
448
|
+
// Query relevant capabilities
|
|
449
|
+
const results = await envRegistry.query(question);
|
|
450
|
+
return {
|
|
451
|
+
found: results.length > 0,
|
|
452
|
+
capabilities: envRegistry.listCapabilities(),
|
|
453
|
+
data: results,
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
catch {
|
|
457
|
+
this.logger.warn('Environment query failed (capability registry not available)', 'ResearchOrchestrator');
|
|
458
|
+
return { found: false, capabilities: [], data: [] };
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* Calculate confidence score from multiple sources
|
|
463
|
+
*/
|
|
464
|
+
calculateConfidence(sources) {
|
|
465
|
+
if (sources.length === 0)
|
|
466
|
+
return 0;
|
|
467
|
+
// Weighted confidence calculation
|
|
468
|
+
const totalConfidence = sources.reduce((sum, s) => sum + s.confidence, 0);
|
|
469
|
+
const avgConfidence = totalConfidence / sources.length;
|
|
470
|
+
// Bonus for multiple sources
|
|
471
|
+
const sourceBonus = Math.min(sources.length * 0.05, 0.15);
|
|
472
|
+
return Math.min(avgConfidence + sourceBonus, 1.0);
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Synthesize answer from multiple sources
|
|
476
|
+
*/
|
|
477
|
+
synthesizeAnswer(research) {
|
|
478
|
+
if (research.sources.length === 0) {
|
|
479
|
+
return 'No relevant information found in project files, knowledge graph, or environment.';
|
|
480
|
+
}
|
|
481
|
+
const parts = [];
|
|
482
|
+
// Add project file findings
|
|
483
|
+
const projectFiles = research.sources.find(s => s.type === 'project_files');
|
|
484
|
+
if (projectFiles && projectFiles.data.files?.length > 0) {
|
|
485
|
+
parts.push(`Found ${projectFiles.data.files.length} relevant project file(s).`);
|
|
486
|
+
}
|
|
487
|
+
// Add knowledge graph findings
|
|
488
|
+
const knowledgeGraph = research.sources.find(s => s.type === 'knowledge_graph');
|
|
489
|
+
if (knowledgeGraph && knowledgeGraph.data.nodes?.length > 0) {
|
|
490
|
+
parts.push(`Identified ${knowledgeGraph.data.nodes.length} related architectural decision(s).`);
|
|
491
|
+
}
|
|
492
|
+
// Add environment findings
|
|
493
|
+
const environment = research.sources.find(s => s.type === 'environment');
|
|
494
|
+
if (environment && environment.data.capabilities?.length > 0) {
|
|
495
|
+
parts.push(`Detected ${environment.data.capabilities.length} environment capability(ies): ${environment.data.capabilities.join(', ')}.`);
|
|
496
|
+
}
|
|
497
|
+
if (research.needsWebSearch) {
|
|
498
|
+
parts.push('Additional web research recommended for comprehensive answer.');
|
|
499
|
+
}
|
|
500
|
+
return parts.join(' ');
|
|
501
|
+
}
|
|
502
|
+
/**
|
|
503
|
+
* Calculate relevance score for content (legacy method - kept for compatibility)
|
|
504
|
+
*/
|
|
505
|
+
calculateRelevanceLegacy(content, question) {
|
|
506
|
+
const contentLower = content.toLowerCase();
|
|
507
|
+
const questionLower = question.toLowerCase();
|
|
508
|
+
// Extract keywords from question
|
|
509
|
+
const keywords = this.extractKeywords(question);
|
|
510
|
+
let score = 0;
|
|
511
|
+
for (const keyword of keywords) {
|
|
512
|
+
if (contentLower.includes(keyword.toLowerCase())) {
|
|
513
|
+
score += 0.2;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
// Bonus for exact question phrases
|
|
517
|
+
const questionWords = questionLower.split(/\s+/).filter(w => w.length > 3);
|
|
518
|
+
for (const word of questionWords) {
|
|
519
|
+
if (contentLower.includes(word)) {
|
|
520
|
+
score += 0.1;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
return Math.min(score, 1.0);
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* Extract keywords from question
|
|
527
|
+
*/
|
|
528
|
+
extractKeywords(question) {
|
|
529
|
+
// Remove common words
|
|
530
|
+
const stopWords = new Set([
|
|
531
|
+
'the',
|
|
532
|
+
'is',
|
|
533
|
+
'are',
|
|
534
|
+
'was',
|
|
535
|
+
'were',
|
|
536
|
+
'what',
|
|
537
|
+
'when',
|
|
538
|
+
'where',
|
|
539
|
+
'why',
|
|
540
|
+
'how',
|
|
541
|
+
'which',
|
|
542
|
+
'who',
|
|
543
|
+
'a',
|
|
544
|
+
'an',
|
|
545
|
+
'and',
|
|
546
|
+
'or',
|
|
547
|
+
'but',
|
|
548
|
+
'in',
|
|
549
|
+
'on',
|
|
550
|
+
'at',
|
|
551
|
+
'to',
|
|
552
|
+
'for',
|
|
553
|
+
'with',
|
|
554
|
+
'about',
|
|
555
|
+
'as',
|
|
556
|
+
'by',
|
|
557
|
+
'from',
|
|
558
|
+
'of',
|
|
559
|
+
'can',
|
|
560
|
+
'could',
|
|
561
|
+
'should',
|
|
562
|
+
'would',
|
|
563
|
+
'do',
|
|
564
|
+
'does',
|
|
565
|
+
'did',
|
|
566
|
+
'have',
|
|
567
|
+
'has',
|
|
568
|
+
'had',
|
|
569
|
+
'we',
|
|
570
|
+
'our',
|
|
571
|
+
'us',
|
|
572
|
+
]);
|
|
573
|
+
const words = question
|
|
574
|
+
.toLowerCase()
|
|
575
|
+
.replace(/[^\w\s-]/g, ' ')
|
|
576
|
+
.split(/\s+/)
|
|
577
|
+
.filter(w => w.length > 2 && !stopWords.has(w));
|
|
578
|
+
return [...new Set(words)];
|
|
579
|
+
}
|
|
580
|
+
/**
|
|
581
|
+
* Set confidence threshold for web search fallback
|
|
582
|
+
*/
|
|
583
|
+
setConfidenceThreshold(threshold) {
|
|
584
|
+
this.confidenceThreshold = Math.max(0, Math.min(1, threshold));
|
|
585
|
+
}
|
|
586
|
+
/**
|
|
587
|
+
* SOURCE 4: Perform web search using Firecrawl (LLM-managed)
|
|
588
|
+
*/
|
|
589
|
+
async performWebSearch(question) {
|
|
590
|
+
try {
|
|
591
|
+
this.logger.debug(`Performing Firecrawl web search for: "${question}"`, 'ResearchOrchestrator');
|
|
592
|
+
// Generate search queries
|
|
593
|
+
const searchQueries = this.generateSearchQueries(question);
|
|
594
|
+
// Use Firecrawl to search and extract content
|
|
595
|
+
const results = await Promise.all(searchQueries.map(async (query) => {
|
|
596
|
+
return await this.searchWithFirecrawl(query);
|
|
597
|
+
}));
|
|
598
|
+
const flattenedResults = results.flat().filter(result => result.found);
|
|
599
|
+
return {
|
|
600
|
+
found: flattenedResults.length > 0,
|
|
601
|
+
results: flattenedResults,
|
|
602
|
+
queries: searchQueries,
|
|
603
|
+
timestamp: new Date().toISOString(),
|
|
604
|
+
provider: 'firecrawl',
|
|
605
|
+
};
|
|
606
|
+
}
|
|
607
|
+
catch (error) {
|
|
608
|
+
this.logger.error('Firecrawl web search failed', 'ResearchOrchestrator', error);
|
|
609
|
+
return {
|
|
610
|
+
found: false,
|
|
611
|
+
results: [],
|
|
612
|
+
queries: [],
|
|
613
|
+
error: error instanceof Error ? error.message : String(error),
|
|
614
|
+
provider: 'firecrawl',
|
|
615
|
+
};
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
/**
|
|
619
|
+
* Search using Firecrawl with LLM-driven query optimization
|
|
620
|
+
*/
|
|
621
|
+
async searchWithFirecrawl(query) {
|
|
622
|
+
try {
|
|
623
|
+
// Check if Firecrawl is available
|
|
624
|
+
if (!this.firecrawl) {
|
|
625
|
+
this.logger.warn('Firecrawl is not available, using fallback search', 'ResearchOrchestrator');
|
|
626
|
+
return this.generateFallbackSearchResults(query);
|
|
627
|
+
}
|
|
628
|
+
// Step 1: Generate search URLs using LLM
|
|
629
|
+
const searchUrls = await this.generateSearchUrls(query);
|
|
630
|
+
// Step 2: Use Firecrawl to extract content from search results
|
|
631
|
+
const results = await Promise.all(searchUrls.map(async (url) => {
|
|
632
|
+
try {
|
|
633
|
+
const crawlResult = await this.firecrawl.scrapeUrl(url, {
|
|
634
|
+
formats: ['markdown', 'html'],
|
|
635
|
+
onlyMainContent: true,
|
|
636
|
+
removeBase64Images: true,
|
|
637
|
+
removeEmojis: true,
|
|
638
|
+
removeLinks: false,
|
|
639
|
+
removeImages: false,
|
|
640
|
+
removeScripts: true,
|
|
641
|
+
removeStyles: true,
|
|
642
|
+
});
|
|
643
|
+
return {
|
|
644
|
+
title: crawlResult.metadata?.title || 'No title',
|
|
645
|
+
url: url,
|
|
646
|
+
content: crawlResult.markdown || crawlResult.html,
|
|
647
|
+
relevance: await this.calculateRelevance(query, crawlResult.markdown || ''),
|
|
648
|
+
timestamp: new Date().toISOString(),
|
|
649
|
+
};
|
|
650
|
+
}
|
|
651
|
+
catch (error) {
|
|
652
|
+
this.logger.debug(`Failed to scrape ${url}`, 'ResearchOrchestrator', error instanceof Error ? error : new Error(String(error)));
|
|
653
|
+
return null;
|
|
654
|
+
}
|
|
655
|
+
}));
|
|
656
|
+
return results.filter(result => result !== null && result.relevance > 0.3);
|
|
657
|
+
}
|
|
658
|
+
catch (error) {
|
|
659
|
+
this.logger.error(`Firecrawl search failed for query: ${query}`, 'ResearchOrchestrator', error);
|
|
660
|
+
return this.generateFallbackSearchResults(query);
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
/**
|
|
664
|
+
* Generate fallback search results when Firecrawl is not available
|
|
665
|
+
*/
|
|
666
|
+
generateFallbackSearchResults(query) {
|
|
667
|
+
const searchQueries = this.generateSearchQueries(query);
|
|
668
|
+
return searchQueries.map((searchQuery, index) => ({
|
|
669
|
+
title: `Search Result ${index + 1} for "${searchQuery}"`,
|
|
670
|
+
url: `https://example.com/search?q=${encodeURIComponent(searchQuery)}`,
|
|
671
|
+
content: `This is a fallback search result for the query: ${searchQuery}. Firecrawl is not available, so this is a placeholder result.`,
|
|
672
|
+
relevance: Math.max(0.3, 0.9 - index * 0.1),
|
|
673
|
+
timestamp: new Date().toISOString(),
|
|
674
|
+
}));
|
|
675
|
+
}
|
|
676
|
+
/**
|
|
677
|
+
* Generate search URLs using LLM
|
|
678
|
+
*/
|
|
679
|
+
async generateSearchUrls(query) {
|
|
680
|
+
// const aiConfig = loadAIConfig();
|
|
681
|
+
// const executor = getAIExecutor();
|
|
682
|
+
// const prompt = `
|
|
683
|
+
// Generate 3-5 relevant search URLs for this query: "${query}"
|
|
684
|
+
//
|
|
685
|
+
// Consider:
|
|
686
|
+
// - Technical documentation sites (docs, GitHub, Stack Overflow)
|
|
687
|
+
// - Official documentation (Red Hat, Ubuntu, macOS)
|
|
688
|
+
// - Community forums and wikis
|
|
689
|
+
// - API documentation
|
|
690
|
+
// - Tutorial and guide sites
|
|
691
|
+
//
|
|
692
|
+
// Return only the URLs, one per line.
|
|
693
|
+
// `;
|
|
694
|
+
// TODO: Implement LLM URL generation when AI executor is available
|
|
695
|
+
// try {
|
|
696
|
+
// const result = await executor.executeStructuredPrompt(prompt, {
|
|
697
|
+
// type: 'object',
|
|
698
|
+
// properties: {
|
|
699
|
+
// urls: {
|
|
700
|
+
// type: 'array',
|
|
701
|
+
// items: { type: 'string' },
|
|
702
|
+
// description: 'List of URLs to search'
|
|
703
|
+
// }
|
|
704
|
+
// }
|
|
705
|
+
// });
|
|
706
|
+
// return result.data.urls || [];
|
|
707
|
+
// } catch (error) {
|
|
708
|
+
// this.logger.warn('LLM search URL generation failed, using fallback', 'ResearchOrchestrator');
|
|
709
|
+
// }
|
|
710
|
+
// Fallback to common search URLs
|
|
711
|
+
return [
|
|
712
|
+
`https://www.google.com/search?q=${encodeURIComponent(query)}`,
|
|
713
|
+
`https://duckduckgo.com/?q=${encodeURIComponent(query)}`,
|
|
714
|
+
`https://www.bing.com/search?q=${encodeURIComponent(query)}`,
|
|
715
|
+
];
|
|
716
|
+
}
|
|
717
|
+
/**
|
|
718
|
+
* Calculate relevance score using LLM
|
|
719
|
+
*/
|
|
720
|
+
async calculateRelevance(query, content) {
|
|
721
|
+
if (!content || content.length < 100)
|
|
722
|
+
return 0;
|
|
723
|
+
// const aiConfig = loadAIConfig();
|
|
724
|
+
// const executor = getAIExecutor();
|
|
725
|
+
// const prompt = `
|
|
726
|
+
// Rate the relevance of this content to the query "${query}" on a scale of 0.0 to 1.0.
|
|
727
|
+
//
|
|
728
|
+
// Content (first 500 chars): ${content.substring(0, 500)}...
|
|
729
|
+
//
|
|
730
|
+
// Consider:
|
|
731
|
+
// - Direct answer to the query
|
|
732
|
+
// - Technical accuracy
|
|
733
|
+
// - Completeness of information
|
|
734
|
+
// - Authority of the source
|
|
735
|
+
//
|
|
736
|
+
// Return only a number between 0.0 and 1.0.
|
|
737
|
+
// `;
|
|
738
|
+
// TODO: Implement LLM relevance calculation when AI executor is available
|
|
739
|
+
// try {
|
|
740
|
+
// const result = await executor.executeStructuredPrompt(prompt, {
|
|
741
|
+
// type: 'object',
|
|
742
|
+
// properties: {
|
|
743
|
+
// relevance: { type: 'number', minimum: 0, maximum: 1 }
|
|
744
|
+
// }
|
|
745
|
+
// });
|
|
746
|
+
// return result.data.relevance || 0;
|
|
747
|
+
// } catch (error) {
|
|
748
|
+
// // Fallback to simple keyword matching
|
|
749
|
+
// }
|
|
750
|
+
// Fallback to simple keyword matching
|
|
751
|
+
const queryWords = query.toLowerCase().split(' ');
|
|
752
|
+
const contentLower = content.toLowerCase();
|
|
753
|
+
const matches = queryWords.filter(word => contentLower.includes(word)).length;
|
|
754
|
+
return Math.min(matches / queryWords.length, 1);
|
|
755
|
+
}
|
|
756
|
+
/**
|
|
757
|
+
* Generate search queries based on research question
|
|
758
|
+
*/
|
|
759
|
+
generateSearchQueries(question) {
|
|
760
|
+
const queries = [question];
|
|
761
|
+
// Add variations
|
|
762
|
+
const questionLower = question.toLowerCase();
|
|
763
|
+
if (questionLower.includes('what')) {
|
|
764
|
+
queries.push(question.replace(/^what/i, 'how to'));
|
|
765
|
+
}
|
|
766
|
+
if (questionLower.includes('how')) {
|
|
767
|
+
queries.push(question.replace(/^how/i, 'best practices for'));
|
|
768
|
+
}
|
|
769
|
+
// Add context-specific queries
|
|
770
|
+
if (questionLower.includes('kubernetes') || questionLower.includes('k8s')) {
|
|
771
|
+
queries.push(`${question} kubernetes best practices`);
|
|
772
|
+
}
|
|
773
|
+
if (questionLower.includes('docker')) {
|
|
774
|
+
queries.push(`${question} docker production`);
|
|
775
|
+
}
|
|
776
|
+
if (questionLower.includes('openshift')) {
|
|
777
|
+
queries.push(`${question} openshift documentation`);
|
|
778
|
+
}
|
|
779
|
+
if (questionLower.includes('ansible')) {
|
|
780
|
+
queries.push(`${question} ansible automation`);
|
|
781
|
+
}
|
|
782
|
+
if (questionLower.includes('deployment')) {
|
|
783
|
+
queries.push(`${question} deployment strategy`);
|
|
784
|
+
}
|
|
785
|
+
if (questionLower.includes('security')) {
|
|
786
|
+
queries.push(`${question} security best practices`);
|
|
787
|
+
}
|
|
788
|
+
return queries.slice(0, 3); // Limit to top 3
|
|
789
|
+
}
|
|
790
|
+
/**
|
|
791
|
+
* Generate cache key for research question
|
|
792
|
+
*/
|
|
793
|
+
generateCacheKey(question) {
|
|
794
|
+
const key = `${this.projectPath}:${this.adrDirectory}:${question}`;
|
|
795
|
+
return crypto.createHash('sha256').update(key).digest('hex').slice(0, 16);
|
|
796
|
+
}
|
|
797
|
+
/**
|
|
798
|
+
* Get cached result if available and not expired
|
|
799
|
+
*/
|
|
800
|
+
getCachedResult(cacheKey) {
|
|
801
|
+
const cached = this.cache.get(cacheKey);
|
|
802
|
+
if (!cached)
|
|
803
|
+
return null;
|
|
804
|
+
if (Date.now() > cached.expiry) {
|
|
805
|
+
this.cache.delete(cacheKey);
|
|
806
|
+
return null;
|
|
807
|
+
}
|
|
808
|
+
// Mark as cached
|
|
809
|
+
const result = { ...cached.result };
|
|
810
|
+
result.metadata = { ...result.metadata, cached: true };
|
|
811
|
+
return result;
|
|
812
|
+
}
|
|
813
|
+
/**
|
|
814
|
+
* Cache a research result
|
|
815
|
+
*/
|
|
816
|
+
setCachedResult(cacheKey, result) {
|
|
817
|
+
const now = Date.now();
|
|
818
|
+
this.cache.set(cacheKey, {
|
|
819
|
+
result: { ...result },
|
|
820
|
+
timestamp: now,
|
|
821
|
+
expiry: now + this.cacheTtl,
|
|
822
|
+
});
|
|
823
|
+
}
|
|
824
|
+
/**
|
|
825
|
+
* Clear expired cache entries
|
|
826
|
+
*/
|
|
827
|
+
cleanupCache() {
|
|
828
|
+
const now = Date.now();
|
|
829
|
+
let cleaned = 0;
|
|
830
|
+
for (const [key, cached] of this.cache.entries()) {
|
|
831
|
+
if (now > cached.expiry) {
|
|
832
|
+
this.cache.delete(key);
|
|
833
|
+
cleaned++;
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
if (cleaned > 0) {
|
|
837
|
+
this.logger.info(`Cleaned ${cleaned} expired cache entries`, 'ResearchOrchestrator');
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
/**
|
|
841
|
+
* Clear all cache entries
|
|
842
|
+
*/
|
|
843
|
+
clearCache() {
|
|
844
|
+
this.cache.clear();
|
|
845
|
+
this.logger.info('Research cache cleared', 'ResearchOrchestrator');
|
|
846
|
+
}
|
|
847
|
+
/**
|
|
848
|
+
* Get cache statistics
|
|
849
|
+
*/
|
|
850
|
+
getCacheStats() {
|
|
851
|
+
const now = Date.now();
|
|
852
|
+
const entries = Array.from(this.cache.entries()).map(([key, cached]) => ({
|
|
853
|
+
key,
|
|
854
|
+
age: now - cached.timestamp,
|
|
855
|
+
expires: cached.expiry - now,
|
|
856
|
+
}));
|
|
857
|
+
return {
|
|
858
|
+
size: this.cache.size,
|
|
859
|
+
entries,
|
|
860
|
+
};
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
//# sourceMappingURL=research-orchestrator.js.map
|