erosolar-cli 2.1.249 → 2.1.252
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/agents/general.rules.json +10 -133
- package/agents/general.rules.json.bak +278 -0
- package/agents/general.rules.json.bak2 +306 -0
- package/dist/bin/erosolar.js +9 -5
- package/dist/bin/erosolar.js.map +1 -1
- package/dist/capabilities/bidirectionalAuditCapability.d.ts +26 -0
- package/dist/capabilities/bidirectionalAuditCapability.d.ts.map +1 -0
- package/dist/capabilities/bidirectionalAuditCapability.js +44 -0
- package/dist/capabilities/bidirectionalAuditCapability.js.map +1 -0
- package/dist/capabilities/globCapability.d.ts +3 -6
- package/dist/capabilities/globCapability.d.ts.map +1 -1
- package/dist/capabilities/globCapability.js +6 -10
- package/dist/capabilities/globCapability.js.map +1 -1
- package/dist/capabilities/index.d.ts +1 -18
- package/dist/capabilities/index.d.ts.map +1 -1
- package/dist/capabilities/index.js +1 -18
- package/dist/capabilities/index.js.map +1 -1
- package/dist/capabilities/orchestrationCapability.d.ts +2 -0
- package/dist/capabilities/orchestrationCapability.d.ts.map +1 -1
- package/dist/capabilities/orchestrationCapability.js +980 -2
- package/dist/capabilities/orchestrationCapability.js.map +1 -1
- package/dist/capabilities/searchCapability.d.ts +8 -2
- package/dist/capabilities/searchCapability.d.ts.map +1 -1
- package/dist/capabilities/searchCapability.js +11 -6
- package/dist/capabilities/searchCapability.js.map +1 -1
- package/dist/contracts/tools.schema.json +9 -133
- package/dist/core/aiErrorFixer.d.ts +1 -14
- package/dist/core/aiErrorFixer.d.ts.map +1 -1
- package/dist/core/aiErrorFixer.js +51 -239
- package/dist/core/aiErrorFixer.js.map +1 -1
- package/dist/core/alphaZeroEngine.d.ts +16 -256
- package/dist/core/alphaZeroEngine.d.ts.map +1 -1
- package/dist/core/alphaZeroEngine.js +22 -513
- package/dist/core/alphaZeroEngine.js.map +1 -1
- package/dist/core/completeAttackOrchestrator.d.ts +102 -0
- package/dist/core/completeAttackOrchestrator.d.ts.map +1 -0
- package/dist/core/completeAttackOrchestrator.js +293 -0
- package/dist/core/completeAttackOrchestrator.js.map +1 -0
- package/dist/core/defensiveSecurityToolkit.d.ts +373 -0
- package/dist/core/defensiveSecurityToolkit.d.ts.map +1 -0
- package/dist/core/defensiveSecurityToolkit.js +1304 -0
- package/dist/core/defensiveSecurityToolkit.js.map +1 -0
- package/dist/core/errors/errorTypes.d.ts +30 -57
- package/dist/core/errors/errorTypes.d.ts.map +1 -1
- package/dist/core/errors/errorTypes.js +51 -228
- package/dist/core/errors/errorTypes.js.map +1 -1
- package/dist/core/errors/safetyValidator.d.ts +19 -3
- package/dist/core/errors/safetyValidator.d.ts.map +1 -1
- package/dist/core/errors/safetyValidator.js +33 -71
- package/dist/core/errors/safetyValidator.js.map +1 -1
- package/dist/core/failureRecovery.d.ts +4 -100
- package/dist/core/failureRecovery.d.ts.map +1 -1
- package/dist/core/failureRecovery.js +16 -440
- package/dist/core/failureRecovery.js.map +1 -1
- package/dist/core/intelligentTargetResearcher.d.ts +142 -0
- package/dist/core/intelligentTargetResearcher.d.ts.map +1 -0
- package/dist/core/intelligentTargetResearcher.js +367 -0
- package/dist/core/intelligentTargetResearcher.js.map +1 -0
- package/dist/core/intelligentTestFlows.d.ts +26 -107
- package/dist/core/intelligentTestFlows.d.ts.map +1 -1
- package/dist/core/intelligentTestFlows.js +15 -659
- package/dist/core/intelligentTestFlows.js.map +1 -1
- package/dist/core/learningPersistence.d.ts +45 -132
- package/dist/core/learningPersistence.d.ts.map +1 -1
- package/dist/core/learningPersistence.js +32 -463
- package/dist/core/learningPersistence.js.map +1 -1
- package/dist/core/metricsTracker.d.ts +22 -139
- package/dist/core/metricsTracker.d.ts.map +1 -1
- package/dist/core/metricsTracker.js +51 -241
- package/dist/core/metricsTracker.js.map +1 -1
- package/dist/core/performanceMonitor.d.ts +15 -109
- package/dist/core/performanceMonitor.d.ts.map +1 -1
- package/dist/core/performanceMonitor.js +27 -184
- package/dist/core/performanceMonitor.js.map +1 -1
- package/dist/core/resultVerification.d.ts +6 -100
- package/dist/core/resultVerification.d.ts.map +1 -1
- package/dist/core/resultVerification.js +31 -400
- package/dist/core/resultVerification.js.map +1 -1
- package/dist/core/selfEvolution.d.ts +32 -126
- package/dist/core/selfEvolution.d.ts.map +1 -1
- package/dist/core/selfEvolution.js +24 -967
- package/dist/core/selfEvolution.js.map +1 -1
- package/dist/core/selfImprovement.d.ts +50 -109
- package/dist/core/selfImprovement.d.ts.map +1 -1
- package/dist/core/selfImprovement.js +14 -689
- package/dist/core/selfImprovement.js.map +1 -1
- package/dist/core/sourceCodeManager.d.ts +89 -0
- package/dist/core/sourceCodeManager.d.ts.map +1 -0
- package/dist/core/sourceCodeManager.js +332 -0
- package/dist/core/sourceCodeManager.js.map +1 -0
- package/dist/core/unifiedOrchestrator.d.ts +88 -0
- package/dist/core/unifiedOrchestrator.d.ts.map +1 -0
- package/dist/core/unifiedOrchestrator.js +284 -0
- package/dist/core/unifiedOrchestrator.js.map +1 -0
- package/dist/core/userDefenseOrchestrator.d.ts +202 -0
- package/dist/core/userDefenseOrchestrator.d.ts.map +1 -0
- package/dist/core/userDefenseOrchestrator.js +1006 -0
- package/dist/core/userDefenseOrchestrator.js.map +1 -0
- package/dist/plugins/index.d.ts +1 -1
- package/dist/plugins/index.d.ts.map +1 -1
- package/dist/plugins/index.js +36 -26
- package/dist/plugins/index.js.map +1 -1
- package/dist/plugins/tools/bidirectionalAudit/bidirectionalAuditPlugin.d.ts +8 -0
- package/dist/plugins/tools/bidirectionalAudit/bidirectionalAuditPlugin.d.ts.map +1 -0
- package/dist/plugins/tools/bidirectionalAudit/bidirectionalAuditPlugin.js +17 -0
- package/dist/plugins/tools/bidirectionalAudit/bidirectionalAuditPlugin.js.map +1 -0
- package/dist/plugins/tools/nodeDefaults.d.ts +14 -0
- package/dist/plugins/tools/nodeDefaults.d.ts.map +1 -1
- package/dist/plugins/tools/nodeDefaults.js +17 -54
- package/dist/plugins/tools/nodeDefaults.js.map +1 -1
- package/dist/plugins/tools/orchestration/orchestrationPlugin.d.ts +9 -0
- package/dist/plugins/tools/orchestration/orchestrationPlugin.d.ts.map +1 -0
- package/dist/plugins/tools/orchestration/orchestrationPlugin.js +18 -0
- package/dist/plugins/tools/orchestration/orchestrationPlugin.js.map +1 -0
- package/dist/shell/interactiveShell.d.ts +97 -2
- package/dist/shell/interactiveShell.d.ts.map +1 -1
- package/dist/shell/interactiveShell.js +1001 -6
- package/dist/shell/interactiveShell.js.map +1 -1
- package/dist/tools/appleExposureTools.d.ts +108 -0
- package/dist/tools/appleExposureTools.d.ts.map +1 -0
- package/dist/tools/appleExposureTools.js +850 -0
- package/dist/tools/appleExposureTools.js.map +1 -0
- package/dist/tools/bidirectionalAuditTools.d.ts +104 -0
- package/dist/tools/bidirectionalAuditTools.d.ts.map +1 -0
- package/dist/tools/bidirectionalAuditTools.js +1280 -0
- package/dist/tools/bidirectionalAuditTools.js.map +1 -0
- package/dist/tools/defensiveSecurityTools.d.ts +152 -0
- package/dist/tools/defensiveSecurityTools.d.ts.map +1 -0
- package/dist/tools/defensiveSecurityTools.js +576 -0
- package/dist/tools/defensiveSecurityTools.js.map +1 -0
- package/dist/tools/forwardAttackChainTracer.d.ts +73 -0
- package/dist/tools/forwardAttackChainTracer.d.ts.map +1 -0
- package/dist/tools/forwardAttackChainTracer.js +604 -0
- package/dist/tools/forwardAttackChainTracer.js.map +1 -0
- package/dist/tools/localExplore.d.ts +12 -199
- package/dist/tools/localExplore.d.ts.map +1 -1
- package/dist/tools/localExplore.js +18 -1352
- package/dist/tools/localExplore.js.map +1 -1
- package/dist/tools/offensiveTransparencyTools.d.ts +188 -0
- package/dist/tools/offensiveTransparencyTools.d.ts.map +1 -0
- package/dist/tools/offensiveTransparencyTools.js +890 -0
- package/dist/tools/offensiveTransparencyTools.js.map +1 -0
- package/dist/tools/planningTools.d.ts +8 -17
- package/dist/tools/planningTools.d.ts.map +1 -1
- package/dist/tools/planningTools.js +31 -141
- package/dist/tools/planningTools.js.map +1 -1
- package/dist/tools/searchTools.d.ts +9 -0
- package/dist/tools/searchTools.d.ts.map +1 -1
- package/dist/tools/searchTools.js +305 -189
- package/dist/tools/searchTools.js.map +1 -1
- package/dist/tools/skillTools.d.ts +7 -5
- package/dist/tools/skillTools.d.ts.map +1 -1
- package/dist/tools/skillTools.js +13 -155
- package/dist/tools/skillTools.js.map +1 -1
- package/dist/tools/threatIntelligenceTools.d.ts +128 -0
- package/dist/tools/threatIntelligenceTools.d.ts.map +1 -0
- package/dist/tools/threatIntelligenceTools.js +712 -0
- package/dist/tools/threatIntelligenceTools.js.map +1 -0
- package/dist/ui/PromptController.d.ts +4 -0
- package/dist/ui/PromptController.d.ts.map +1 -1
- package/dist/ui/PromptController.js +32 -11
- package/dist/ui/PromptController.js.map +1 -1
- package/dist/ui/UnifiedUIRenderer.d.ts +20 -0
- package/dist/ui/UnifiedUIRenderer.d.ts.map +1 -1
- package/dist/ui/UnifiedUIRenderer.js +235 -28
- package/dist/ui/UnifiedUIRenderer.js.map +1 -1
- package/dist/ui/animatedStatus.d.ts +2 -0
- package/dist/ui/animatedStatus.d.ts.map +1 -1
- package/dist/ui/animatedStatus.js +36 -2
- package/dist/ui/animatedStatus.js.map +1 -1
- package/dist/ui/orchestration/StatusOrchestrator.d.ts +10 -0
- package/dist/ui/orchestration/StatusOrchestrator.d.ts.map +1 -1
- package/dist/ui/orchestration/StatusOrchestrator.js +36 -4
- package/dist/ui/orchestration/StatusOrchestrator.js.map +1 -1
- package/package.json +1 -1
- package/dist/capabilities/advancedTestGenerationCapability.d.ts +0 -17
- package/dist/capabilities/advancedTestGenerationCapability.d.ts.map +0 -1
- package/dist/capabilities/advancedTestGenerationCapability.js +0 -28
- package/dist/capabilities/advancedTestGenerationCapability.js.map +0 -1
- package/dist/capabilities/browserAutomationCapability.d.ts +0 -37
- package/dist/capabilities/browserAutomationCapability.d.ts.map +0 -1
- package/dist/capabilities/browserAutomationCapability.js +0 -49
- package/dist/capabilities/browserAutomationCapability.js.map +0 -1
- package/dist/capabilities/buildCapability.d.ts +0 -24
- package/dist/capabilities/buildCapability.d.ts.map +0 -1
- package/dist/capabilities/buildCapability.js +0 -25
- package/dist/capabilities/buildCapability.js.map +0 -1
- package/dist/capabilities/cloudCapability.d.ts +0 -13
- package/dist/capabilities/cloudCapability.d.ts.map +0 -1
- package/dist/capabilities/cloudCapability.js +0 -38
- package/dist/capabilities/cloudCapability.js.map +0 -1
- package/dist/capabilities/codeAnalysisCapability.d.ts +0 -13
- package/dist/capabilities/codeAnalysisCapability.d.ts.map +0 -1
- package/dist/capabilities/codeAnalysisCapability.js +0 -24
- package/dist/capabilities/codeAnalysisCapability.js.map +0 -1
- package/dist/capabilities/codeQualityCapability.d.ts +0 -13
- package/dist/capabilities/codeQualityCapability.d.ts.map +0 -1
- package/dist/capabilities/codeQualityCapability.js +0 -25
- package/dist/capabilities/codeQualityCapability.js.map +0 -1
- package/dist/capabilities/dependencySecurityCapability.d.ts +0 -13
- package/dist/capabilities/dependencySecurityCapability.d.ts.map +0 -1
- package/dist/capabilities/dependencySecurityCapability.js +0 -24
- package/dist/capabilities/dependencySecurityCapability.js.map +0 -1
- package/dist/capabilities/devCapability.d.ts +0 -13
- package/dist/capabilities/devCapability.d.ts.map +0 -1
- package/dist/capabilities/devCapability.js +0 -24
- package/dist/capabilities/devCapability.js.map +0 -1
- package/dist/capabilities/emailCapability.d.ts +0 -12
- package/dist/capabilities/emailCapability.d.ts.map +0 -1
- package/dist/capabilities/emailCapability.js +0 -22
- package/dist/capabilities/emailCapability.js.map +0 -1
- package/dist/capabilities/enhancedAnalysisCapability.d.ts +0 -13
- package/dist/capabilities/enhancedAnalysisCapability.d.ts.map +0 -1
- package/dist/capabilities/enhancedAnalysisCapability.js +0 -20
- package/dist/capabilities/enhancedAnalysisCapability.js.map +0 -1
- package/dist/capabilities/enhancedCodeIntelligenceCapability.d.ts +0 -17
- package/dist/capabilities/enhancedCodeIntelligenceCapability.d.ts.map +0 -1
- package/dist/capabilities/enhancedCodeIntelligenceCapability.js +0 -28
- package/dist/capabilities/enhancedCodeIntelligenceCapability.js.map +0 -1
- package/dist/capabilities/enhancedDevWorkflowCapability.d.ts +0 -17
- package/dist/capabilities/enhancedDevWorkflowCapability.d.ts.map +0 -1
- package/dist/capabilities/enhancedDevWorkflowCapability.js +0 -28
- package/dist/capabilities/enhancedDevWorkflowCapability.js.map +0 -1
- package/dist/capabilities/frontendTestingCapability.d.ts +0 -13
- package/dist/capabilities/frontendTestingCapability.d.ts.map +0 -1
- package/dist/capabilities/frontendTestingCapability.js +0 -28
- package/dist/capabilities/frontendTestingCapability.js.map +0 -1
- package/dist/capabilities/interactionCapability.d.ts +0 -12
- package/dist/capabilities/interactionCapability.d.ts.map +0 -1
- package/dist/capabilities/interactionCapability.js +0 -22
- package/dist/capabilities/interactionCapability.js.map +0 -1
- package/dist/capabilities/learnCapability.d.ts +0 -22
- package/dist/capabilities/learnCapability.d.ts.map +0 -1
- package/dist/capabilities/learnCapability.js +0 -37
- package/dist/capabilities/learnCapability.js.map +0 -1
- package/dist/capabilities/notebookCapability.d.ts +0 -17
- package/dist/capabilities/notebookCapability.d.ts.map +0 -1
- package/dist/capabilities/notebookCapability.js +0 -27
- package/dist/capabilities/notebookCapability.js.map +0 -1
- package/dist/capabilities/planningCapability.d.ts +0 -16
- package/dist/capabilities/planningCapability.d.ts.map +0 -1
- package/dist/capabilities/planningCapability.js +0 -26
- package/dist/capabilities/planningCapability.js.map +0 -1
- package/dist/capabilities/refactoringCapability.d.ts +0 -13
- package/dist/capabilities/refactoringCapability.d.ts.map +0 -1
- package/dist/capabilities/refactoringCapability.js +0 -25
- package/dist/capabilities/refactoringCapability.js.map +0 -1
- package/dist/capabilities/repoChecksCapability.d.ts +0 -10
- package/dist/capabilities/repoChecksCapability.d.ts.map +0 -1
- package/dist/capabilities/repoChecksCapability.js +0 -24
- package/dist/capabilities/repoChecksCapability.js.map +0 -1
- package/dist/capabilities/taskManagementCapability.d.ts +0 -12
- package/dist/capabilities/taskManagementCapability.d.ts.map +0 -1
- package/dist/capabilities/taskManagementCapability.js +0 -22
- package/dist/capabilities/taskManagementCapability.js.map +0 -1
- package/dist/capabilities/testingCapability.d.ts +0 -13
- package/dist/capabilities/testingCapability.d.ts.map +0 -1
- package/dist/capabilities/testingCapability.js +0 -25
- package/dist/capabilities/testingCapability.js.map +0 -1
- package/dist/capabilities/validationCapability.d.ts +0 -13
- package/dist/capabilities/validationCapability.d.ts.map +0 -1
- package/dist/capabilities/validationCapability.js +0 -24
- package/dist/capabilities/validationCapability.js.map +0 -1
- package/dist/capabilities/webCapability.d.ts +0 -12
- package/dist/capabilities/webCapability.d.ts.map +0 -1
- package/dist/capabilities/webCapability.js +0 -22
- package/dist/capabilities/webCapability.js.map +0 -1
- package/dist/core/deepBugAnalyzer.d.ts +0 -128
- package/dist/core/deepBugAnalyzer.d.ts.map +0 -1
- package/dist/core/deepBugAnalyzer.js +0 -406
- package/dist/core/deepBugAnalyzer.js.map +0 -1
- package/dist/core/hypothesisEngine.d.ts +0 -113
- package/dist/core/hypothesisEngine.d.ts.map +0 -1
- package/dist/core/hypothesisEngine.js +0 -264
- package/dist/core/hypothesisEngine.js.map +0 -1
- package/dist/core/productTestHarness.d.ts +0 -113
- package/dist/core/productTestHarness.d.ts.map +0 -1
- package/dist/core/productTestHarness.js +0 -351
- package/dist/core/productTestHarness.js.map +0 -1
- package/dist/core/validationRunner.d.ts +0 -106
- package/dist/core/validationRunner.d.ts.map +0 -1
- package/dist/core/validationRunner.js +0 -892
- package/dist/core/validationRunner.js.map +0 -1
- package/dist/plugins/tools/browser/browserAutomationPlugin.d.ts +0 -14
- package/dist/plugins/tools/browser/browserAutomationPlugin.d.ts.map +0 -1
- package/dist/plugins/tools/browser/browserAutomationPlugin.js +0 -26
- package/dist/plugins/tools/browser/browserAutomationPlugin.js.map +0 -1
- package/dist/plugins/tools/checks/localRepoChecksPlugin.d.ts +0 -3
- package/dist/plugins/tools/checks/localRepoChecksPlugin.d.ts.map +0 -1
- package/dist/plugins/tools/checks/localRepoChecksPlugin.js +0 -14
- package/dist/plugins/tools/checks/localRepoChecksPlugin.js.map +0 -1
- package/dist/plugins/tools/cloud/cloudPlugin.d.ts +0 -3
- package/dist/plugins/tools/cloud/cloudPlugin.d.ts.map +0 -1
- package/dist/plugins/tools/cloud/cloudPlugin.js +0 -14
- package/dist/plugins/tools/cloud/cloudPlugin.js.map +0 -1
- package/dist/plugins/tools/codeAnalysis/codeAnalysisPlugin.d.ts +0 -3
- package/dist/plugins/tools/codeAnalysis/codeAnalysisPlugin.d.ts.map +0 -1
- package/dist/plugins/tools/codeAnalysis/codeAnalysisPlugin.js +0 -14
- package/dist/plugins/tools/codeAnalysis/codeAnalysisPlugin.js.map +0 -1
- package/dist/plugins/tools/codeQuality/codeQualityPlugin.d.ts +0 -3
- package/dist/plugins/tools/codeQuality/codeQualityPlugin.d.ts.map +0 -1
- package/dist/plugins/tools/codeQuality/codeQualityPlugin.js +0 -14
- package/dist/plugins/tools/codeQuality/codeQualityPlugin.js.map +0 -1
- package/dist/plugins/tools/dependency/dependencyPlugin.d.ts +0 -3
- package/dist/plugins/tools/dependency/dependencyPlugin.d.ts.map +0 -1
- package/dist/plugins/tools/dependency/dependencyPlugin.js +0 -12
- package/dist/plugins/tools/dependency/dependencyPlugin.js.map +0 -1
- package/dist/plugins/tools/development/devPlugin.d.ts +0 -3
- package/dist/plugins/tools/development/devPlugin.d.ts.map +0 -1
- package/dist/plugins/tools/development/devPlugin.js +0 -14
- package/dist/plugins/tools/development/devPlugin.js.map +0 -1
- package/dist/plugins/tools/email/emailPlugin.d.ts +0 -3
- package/dist/plugins/tools/email/emailPlugin.d.ts.map +0 -1
- package/dist/plugins/tools/email/emailPlugin.js +0 -12
- package/dist/plugins/tools/email/emailPlugin.js.map +0 -1
- package/dist/plugins/tools/enhancedAnalysis/enhancedAnalysisPlugin.d.ts +0 -3
- package/dist/plugins/tools/enhancedAnalysis/enhancedAnalysisPlugin.d.ts.map +0 -1
- package/dist/plugins/tools/enhancedAnalysis/enhancedAnalysisPlugin.js +0 -14
- package/dist/plugins/tools/enhancedAnalysis/enhancedAnalysisPlugin.js.map +0 -1
- package/dist/plugins/tools/enhancedCodeIntelligence/enhancedCodeIntelligencePlugin.d.ts +0 -3
- package/dist/plugins/tools/enhancedCodeIntelligence/enhancedCodeIntelligencePlugin.d.ts.map +0 -1
- package/dist/plugins/tools/enhancedCodeIntelligence/enhancedCodeIntelligencePlugin.js +0 -12
- package/dist/plugins/tools/enhancedCodeIntelligence/enhancedCodeIntelligencePlugin.js.map +0 -1
- package/dist/plugins/tools/enhancedDevWorkflow/enhancedDevWorkflowPlugin.d.ts +0 -3
- package/dist/plugins/tools/enhancedDevWorkflow/enhancedDevWorkflowPlugin.d.ts.map +0 -1
- package/dist/plugins/tools/enhancedDevWorkflow/enhancedDevWorkflowPlugin.js +0 -12
- package/dist/plugins/tools/enhancedDevWorkflow/enhancedDevWorkflowPlugin.js.map +0 -1
- package/dist/plugins/tools/frontendTesting/frontendTestingPlugin.d.ts +0 -3
- package/dist/plugins/tools/frontendTesting/frontendTestingPlugin.d.ts.map +0 -1
- package/dist/plugins/tools/frontendTesting/frontendTestingPlugin.js +0 -14
- package/dist/plugins/tools/frontendTesting/frontendTestingPlugin.js.map +0 -1
- package/dist/plugins/tools/interaction/interactionPlugin.d.ts +0 -3
- package/dist/plugins/tools/interaction/interactionPlugin.d.ts.map +0 -1
- package/dist/plugins/tools/interaction/interactionPlugin.js +0 -12
- package/dist/plugins/tools/interaction/interactionPlugin.js.map +0 -1
- package/dist/plugins/tools/learn/learnPlugin.d.ts +0 -3
- package/dist/plugins/tools/learn/learnPlugin.d.ts.map +0 -1
- package/dist/plugins/tools/learn/learnPlugin.js +0 -14
- package/dist/plugins/tools/learn/learnPlugin.js.map +0 -1
- package/dist/plugins/tools/notebook/notebookPlugin.d.ts +0 -9
- package/dist/plugins/tools/notebook/notebookPlugin.d.ts.map +0 -1
- package/dist/plugins/tools/notebook/notebookPlugin.js +0 -15
- package/dist/plugins/tools/notebook/notebookPlugin.js.map +0 -1
- package/dist/plugins/tools/planning/planningPlugin.d.ts +0 -9
- package/dist/plugins/tools/planning/planningPlugin.d.ts.map +0 -1
- package/dist/plugins/tools/planning/planningPlugin.js +0 -15
- package/dist/plugins/tools/planning/planningPlugin.js.map +0 -1
- package/dist/plugins/tools/refactoring/refactoringPlugin.d.ts +0 -3
- package/dist/plugins/tools/refactoring/refactoringPlugin.d.ts.map +0 -1
- package/dist/plugins/tools/refactoring/refactoringPlugin.js +0 -12
- package/dist/plugins/tools/refactoring/refactoringPlugin.js.map +0 -1
- package/dist/plugins/tools/taskManagement/taskManagementPlugin.d.ts +0 -3
- package/dist/plugins/tools/taskManagement/taskManagementPlugin.d.ts.map +0 -1
- package/dist/plugins/tools/taskManagement/taskManagementPlugin.js +0 -12
- package/dist/plugins/tools/taskManagement/taskManagementPlugin.js.map +0 -1
- package/dist/plugins/tools/testing/testingPlugin.d.ts +0 -3
- package/dist/plugins/tools/testing/testingPlugin.d.ts.map +0 -1
- package/dist/plugins/tools/testing/testingPlugin.js +0 -12
- package/dist/plugins/tools/testing/testingPlugin.js.map +0 -1
- package/dist/plugins/tools/validation/validationPlugin.d.ts +0 -3
- package/dist/plugins/tools/validation/validationPlugin.d.ts.map +0 -1
- package/dist/plugins/tools/validation/validationPlugin.js +0 -14
- package/dist/plugins/tools/validation/validationPlugin.js.map +0 -1
- package/dist/plugins/tools/web/webPlugin.d.ts +0 -3
- package/dist/plugins/tools/web/webPlugin.d.ts.map +0 -1
- package/dist/plugins/tools/web/webPlugin.js +0 -12
- package/dist/plugins/tools/web/webPlugin.js.map +0 -1
- package/dist/tools/advancedTestGenerationTools.d.ts +0 -21
- package/dist/tools/advancedTestGenerationTools.d.ts.map +0 -1
- package/dist/tools/advancedTestGenerationTools.js +0 -304
- package/dist/tools/advancedTestGenerationTools.js.map +0 -1
- package/dist/tools/browserAutomationTools.d.ts +0 -23
- package/dist/tools/browserAutomationTools.d.ts.map +0 -1
- package/dist/tools/browserAutomationTools.js +0 -916
- package/dist/tools/browserAutomationTools.js.map +0 -1
- package/dist/tools/buildTools.d.ts +0 -9
- package/dist/tools/buildTools.d.ts.map +0 -1
- package/dist/tools/buildTools.js +0 -346
- package/dist/tools/buildTools.js.map +0 -1
- package/dist/tools/cloudTools.d.ts +0 -49
- package/dist/tools/cloudTools.d.ts.map +0 -1
- package/dist/tools/cloudTools.js +0 -1258
- package/dist/tools/cloudTools.js.map +0 -1
- package/dist/tools/codeAnalysisTools.d.ts +0 -74
- package/dist/tools/codeAnalysisTools.d.ts.map +0 -1
- package/dist/tools/codeAnalysisTools.js +0 -664
- package/dist/tools/codeAnalysisTools.js.map +0 -1
- package/dist/tools/codeGenerationTools.d.ts +0 -3
- package/dist/tools/codeGenerationTools.d.ts.map +0 -1
- package/dist/tools/codeGenerationTools.js +0 -439
- package/dist/tools/codeGenerationTools.js.map +0 -1
- package/dist/tools/codeQualityTools.d.ts +0 -3
- package/dist/tools/codeQualityTools.d.ts.map +0 -1
- package/dist/tools/codeQualityTools.js +0 -297
- package/dist/tools/codeQualityTools.js.map +0 -1
- package/dist/tools/dependencyTools.d.ts +0 -3
- package/dist/tools/dependencyTools.d.ts.map +0 -1
- package/dist/tools/dependencyTools.js +0 -284
- package/dist/tools/dependencyTools.js.map +0 -1
- package/dist/tools/devTools.d.ts +0 -10
- package/dist/tools/devTools.d.ts.map +0 -1
- package/dist/tools/devTools.js +0 -2126
- package/dist/tools/devTools.js.map +0 -1
- package/dist/tools/emailTools.d.ts +0 -21
- package/dist/tools/emailTools.d.ts.map +0 -1
- package/dist/tools/emailTools.js +0 -449
- package/dist/tools/emailTools.js.map +0 -1
- package/dist/tools/enhancedAnalysisTools.d.ts +0 -9
- package/dist/tools/enhancedAnalysisTools.d.ts.map +0 -1
- package/dist/tools/enhancedAnalysisTools.js +0 -370
- package/dist/tools/enhancedAnalysisTools.js.map +0 -1
- package/dist/tools/enhancedCodeIntelligenceTools.d.ts +0 -7
- package/dist/tools/enhancedCodeIntelligenceTools.d.ts.map +0 -1
- package/dist/tools/enhancedCodeIntelligenceTools.js +0 -540
- package/dist/tools/enhancedCodeIntelligenceTools.js.map +0 -1
- package/dist/tools/enhancedDevWorkflowTools.d.ts +0 -7
- package/dist/tools/enhancedDevWorkflowTools.d.ts.map +0 -1
- package/dist/tools/enhancedDevWorkflowTools.js +0 -432
- package/dist/tools/enhancedDevWorkflowTools.js.map +0 -1
- package/dist/tools/frontendTestingTools.d.ts +0 -35
- package/dist/tools/frontendTestingTools.d.ts.map +0 -1
- package/dist/tools/frontendTestingTools.js +0 -1258
- package/dist/tools/frontendTestingTools.js.map +0 -1
- package/dist/tools/globTools.d.ts +0 -15
- package/dist/tools/globTools.d.ts.map +0 -1
- package/dist/tools/globTools.js +0 -174
- package/dist/tools/globTools.js.map +0 -1
- package/dist/tools/grepTools.d.ts +0 -19
- package/dist/tools/grepTools.d.ts.map +0 -1
- package/dist/tools/grepTools.js +0 -411
- package/dist/tools/grepTools.js.map +0 -1
- package/dist/tools/interactionTools.d.ts +0 -6
- package/dist/tools/interactionTools.d.ts.map +0 -1
- package/dist/tools/interactionTools.js +0 -209
- package/dist/tools/interactionTools.js.map +0 -1
- package/dist/tools/learnTools.d.ts +0 -164
- package/dist/tools/learnTools.d.ts.map +0 -1
- package/dist/tools/learnTools.js +0 -2098
- package/dist/tools/learnTools.js.map +0 -1
- package/dist/tools/notebookEditTools.d.ts +0 -15
- package/dist/tools/notebookEditTools.d.ts.map +0 -1
- package/dist/tools/notebookEditTools.js +0 -197
- package/dist/tools/notebookEditTools.js.map +0 -1
- package/dist/tools/refactoringTools.d.ts +0 -3
- package/dist/tools/refactoringTools.d.ts.map +0 -1
- package/dist/tools/refactoringTools.js +0 -294
- package/dist/tools/refactoringTools.js.map +0 -1
- package/dist/tools/repoChecksTools.d.ts +0 -3
- package/dist/tools/repoChecksTools.d.ts.map +0 -1
- package/dist/tools/repoChecksTools.js +0 -276
- package/dist/tools/repoChecksTools.js.map +0 -1
- package/dist/tools/taskManagementTools.d.ts +0 -10
- package/dist/tools/taskManagementTools.d.ts.map +0 -1
- package/dist/tools/taskManagementTools.js +0 -133
- package/dist/tools/taskManagementTools.js.map +0 -1
- package/dist/tools/testingTools.d.ts +0 -3
- package/dist/tools/testingTools.d.ts.map +0 -1
- package/dist/tools/testingTools.js +0 -237
- package/dist/tools/testingTools.js.map +0 -1
- package/dist/tools/validationTools.d.ts +0 -7
- package/dist/tools/validationTools.d.ts.map +0 -1
- package/dist/tools/validationTools.js +0 -344
- package/dist/tools/validationTools.js.map +0 -1
- package/dist/tools/webTools.d.ts +0 -3
- package/dist/tools/webTools.d.ts.map +0 -1
- package/dist/tools/webTools.js +0 -502
- package/dist/tools/webTools.js.map +0 -1
|
@@ -1,1364 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Local Explore
|
|
3
|
-
*
|
|
4
|
-
* This module implements an exploration system that mimics how Erosolar-CLI's
|
|
5
|
-
* explore agent works. It can work fully offline OR use the active AI model
|
|
6
|
-
* for enhanced query understanding and result summarization.
|
|
7
|
-
*
|
|
8
|
-
* Features:
|
|
9
|
-
* 1. Codebase indexing - Build a searchable index of files, functions, classes, imports
|
|
10
|
-
* 2. Query processing - Parse natural language questions and map to search strategies
|
|
11
|
-
* 3. Smart search - Combine glob, grep, and structure analysis
|
|
12
|
-
* 4. Answer generation - Format results in a Erosolar-CLI-like way
|
|
13
|
-
* 5. Caching - Store the index for fast subsequent queries
|
|
14
|
-
* 6. AI Enhancement (optional) - Use the active model for better query understanding
|
|
15
|
-
*/
|
|
16
|
-
import { readFileSync, existsSync, readdirSync, statSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
17
|
-
import { join, relative, extname, basename, dirname } from 'node:path';
|
|
18
|
-
import { createHash } from 'node:crypto';
|
|
19
|
-
import { homedir } from 'node:os';
|
|
20
|
-
import { reportToolProgress } from '../core/toolRuntime.js';
|
|
21
|
-
import { buildError } from '../core/errors.js';
|
|
22
|
-
// =====================================================
|
|
23
|
-
// Global AI Enhancer Registry
|
|
24
|
-
// =====================================================
|
|
25
|
-
/**
|
|
26
|
-
* Global registry for the AI enhancer.
|
|
27
|
-
* This allows the explore tool to automatically use the active AI model
|
|
28
|
-
* without requiring explicit wiring at tool creation time.
|
|
29
|
-
*
|
|
30
|
-
* Usage:
|
|
31
|
-
* 1. When a session starts, call: setGlobalAIEnhancer(enhancerFn)
|
|
32
|
-
* 2. When the session ends, call: setGlobalAIEnhancer(null)
|
|
33
|
-
* 3. The explore tool will automatically use the registered enhancer
|
|
34
|
-
*/
|
|
35
|
-
let globalAIEnhancer = null;
|
|
36
|
-
/**
|
|
37
|
-
* Register the global AI enhancer function.
|
|
38
|
-
* Call this when an AI session becomes available.
|
|
2
|
+
* Local Explore - Minimal stub for backward compatibility
|
|
39
3
|
*/
|
|
4
|
+
let _globalAIEnhancer = null;
|
|
40
5
|
export function setGlobalAIEnhancer(enhancer) {
|
|
41
|
-
|
|
6
|
+
_globalAIEnhancer = enhancer;
|
|
42
7
|
}
|
|
43
|
-
/**
|
|
44
|
-
* Get the current global AI enhancer.
|
|
45
|
-
*/
|
|
46
8
|
export function getGlobalAIEnhancer() {
|
|
47
|
-
return
|
|
9
|
+
return _globalAIEnhancer;
|
|
48
10
|
}
|
|
49
|
-
|
|
50
|
-
* Check if an AI enhancer is available (globally or in context).
|
|
51
|
-
*/
|
|
52
|
-
function resolveAIEnhancer(context) {
|
|
53
|
-
return context.aiEnhancer ?? globalAIEnhancer ?? undefined;
|
|
54
|
-
}
|
|
55
|
-
// =====================================================
|
|
56
|
-
// Constants
|
|
57
|
-
// =====================================================
|
|
58
|
-
const INDEX_VERSION = 1;
|
|
59
|
-
const CACHE_DIR = join(homedir(), '.erosolar', 'explore-cache');
|
|
60
|
-
const IGNORED_DIRS = new Set([
|
|
61
|
-
'node_modules', '.git', '.svn', '.hg', 'dist', 'build', 'out',
|
|
62
|
-
'.next', '.nuxt', '.output', 'coverage', '.nyc_output', '.cache',
|
|
63
|
-
'.turbo', '.vercel', '.netlify', '__pycache__', '.pytest_cache',
|
|
64
|
-
'.mypy_cache', '.ruff_cache', 'venv', '.venv', 'env', '.env',
|
|
65
|
-
'target', 'vendor', '.idea', '.vscode',
|
|
66
|
-
]);
|
|
67
|
-
const LANGUAGE_MAP = {
|
|
68
|
-
'.ts': 'TypeScript', '.tsx': 'TypeScript React', '.js': 'JavaScript',
|
|
69
|
-
'.jsx': 'JavaScript React', '.mjs': 'JavaScript', '.cjs': 'JavaScript',
|
|
70
|
-
'.py': 'Python', '.rs': 'Rust', '.go': 'Go', '.java': 'Java',
|
|
71
|
-
'.kt': 'Kotlin', '.rb': 'Ruby', '.php': 'PHP', '.cs': 'C#',
|
|
72
|
-
'.cpp': 'C++', '.c': 'C', '.h': 'C/C++ Header', '.swift': 'Swift',
|
|
73
|
-
'.vue': 'Vue', '.svelte': 'Svelte', '.md': 'Markdown',
|
|
74
|
-
'.json': 'JSON', '.yaml': 'YAML', '.yml': 'YAML', '.toml': 'TOML',
|
|
75
|
-
};
|
|
76
|
-
// Query type detection patterns
|
|
77
|
-
const QUERY_PATTERNS = [
|
|
78
|
-
{ pattern: /where\s+(?:is|are|can\s+i\s+find)\s+.*(file|module|component)/i, type: 'find_file' },
|
|
79
|
-
{ pattern: /find\s+(?:the\s+)?(?:file|module|component)/i, type: 'find_file' },
|
|
80
|
-
{ pattern: /which\s+file/i, type: 'find_file' },
|
|
81
|
-
{ pattern: /where\s+(?:is|are)\s+(?:the\s+)?(\w+)\s+(?:defined|declared|implemented)/i, type: 'find_symbol' },
|
|
82
|
-
{ pattern: /find\s+(?:the\s+)?(?:function|class|type|interface)\s+/i, type: 'find_symbol' },
|
|
83
|
-
{ pattern: /definition\s+of/i, type: 'find_symbol' },
|
|
84
|
-
{ pattern: /where\s+(?:is\s+)?(\w+)\s+used/i, type: 'find_usage' },
|
|
85
|
-
{ pattern: /who\s+(?:uses|calls|imports)/i, type: 'find_usage' },
|
|
86
|
-
{ pattern: /usages?\s+of/i, type: 'find_usage' },
|
|
87
|
-
{ pattern: /how\s+(?:does|do|is)/i, type: 'understand' },
|
|
88
|
-
{ pattern: /(what(?:'s)?|what\s+is|explain)\s+(?:in|about)\s+(?:this\s+)?(repo|repository|project|codebase)/i, type: 'architecture' },
|
|
89
|
-
{ pattern: /explain\s+(?:the\s+)?(?:how|what)/i, type: 'explain' },
|
|
90
|
-
{ pattern: /what\s+(?:is|are|does)/i, type: 'explain' },
|
|
91
|
-
{ pattern: /architecture|structure|organization|layout/i, type: 'architecture' },
|
|
92
|
-
{ pattern: /dependencies|imports|relationships/i, type: 'dependencies' },
|
|
93
|
-
{ pattern: /./, type: 'search' }, // Default fallback
|
|
94
|
-
];
|
|
95
|
-
// =====================================================
|
|
96
|
-
// Local Explore Engine
|
|
97
|
-
// =====================================================
|
|
98
|
-
export class LocalExploreEngine {
|
|
99
|
-
workingDir;
|
|
100
|
-
index = null;
|
|
101
|
-
indexPath;
|
|
102
|
-
context;
|
|
103
|
-
constructor(workingDir, context = {}) {
|
|
104
|
-
this.workingDir = workingDir;
|
|
105
|
-
this.context = context;
|
|
106
|
-
const hash = createHash('md5').update(workingDir).digest('hex').slice(0, 12);
|
|
107
|
-
this.indexPath = join(CACHE_DIR, `index-${hash}.json`);
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* Set or update the AI enhancer context.
|
|
111
|
-
* Call this to enable AI-enhanced exploration with the active model.
|
|
112
|
-
*/
|
|
113
|
-
setContext(context) {
|
|
114
|
-
this.context = { ...this.context, ...context };
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* Initialize or load the codebase index.
|
|
118
|
-
* Returns true if a fresh index was built.
|
|
119
|
-
*/
|
|
120
|
-
async initialize(forceRebuild = false) {
|
|
121
|
-
if (!forceRebuild && this.tryLoadCache()) {
|
|
122
|
-
return { rebuilt: false, fileCount: this.index.files.length };
|
|
123
|
-
}
|
|
124
|
-
this.index = await this.buildIndex();
|
|
125
|
-
this.saveCache();
|
|
126
|
-
return { rebuilt: true, fileCount: this.index.files.length };
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* Process a natural language query and return exploration results.
|
|
130
|
-
* Automatically uses the active AI model for better results when available.
|
|
131
|
-
*/
|
|
132
|
-
async explore(query, options) {
|
|
133
|
-
const startTime = Date.now();
|
|
134
|
-
if (!this.index) {
|
|
135
|
-
await this.initialize();
|
|
136
|
-
}
|
|
137
|
-
// Resolve AI enhancer (from context or global registry)
|
|
138
|
-
const useAI = options?.useAI !== false; // Default to true
|
|
139
|
-
const aiEnhancer = useAI ? resolveAIEnhancer(this.context) : undefined;
|
|
140
|
-
// Use AI for query parsing if available and enabled
|
|
141
|
-
let parsedQuery;
|
|
142
|
-
if (aiEnhancer && this.context.aiQueryParsing !== false) {
|
|
143
|
-
parsedQuery = await this.parseQueryWithAI(query, aiEnhancer);
|
|
144
|
-
}
|
|
145
|
-
else {
|
|
146
|
-
parsedQuery = this.parseQuery(query);
|
|
147
|
-
}
|
|
148
|
-
const result = await this.executeQuery(parsedQuery);
|
|
149
|
-
// Use AI for result summarization if available and enabled
|
|
150
|
-
if (aiEnhancer && this.context.aiSummarization !== false && result.files.length + result.symbols.length > 0) {
|
|
151
|
-
result.answer = await this.summarizeWithAI(query, result, aiEnhancer);
|
|
152
|
-
}
|
|
153
|
-
result.timeTaken = Date.now() - startTime;
|
|
154
|
-
return result;
|
|
155
|
-
}
|
|
156
|
-
/**
|
|
157
|
-
* Use AI to parse a natural language query into structured exploration.
|
|
158
|
-
*/
|
|
159
|
-
async parseQueryWithAI(query, aiEnhancer) {
|
|
160
|
-
try {
|
|
161
|
-
const prompt = `You are helping parse a codebase exploration query. Extract the intent and keywords.
|
|
162
|
-
|
|
163
|
-
Query: "${query}"
|
|
164
|
-
|
|
165
|
-
Respond in this exact JSON format (no markdown, just JSON):
|
|
166
|
-
{
|
|
167
|
-
"type": "find_file" | "find_symbol" | "find_usage" | "understand" | "explain" | "search" | "architecture" | "dependencies",
|
|
168
|
-
"keywords": ["keyword1", "keyword2"],
|
|
169
|
-
"symbolKind": "function" | "class" | "type" | "interface" | null,
|
|
170
|
-
"filePattern": "pattern or null"
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
Types:
|
|
174
|
-
- find_file: Looking for specific files
|
|
175
|
-
- find_symbol: Looking for function/class/type definitions
|
|
176
|
-
- find_usage: Finding where something is used/called
|
|
177
|
-
- understand/explain: Understanding how something works
|
|
178
|
-
- architecture: Codebase structure overview
|
|
179
|
-
- dependencies: Import/export relationships
|
|
180
|
-
- search: General keyword search`;
|
|
181
|
-
const response = await aiEnhancer(prompt);
|
|
182
|
-
// Parse the JSON response
|
|
183
|
-
const jsonMatch = response.match(/\{[\s\S]*\}/);
|
|
184
|
-
if (jsonMatch) {
|
|
185
|
-
const parsed = JSON.parse(jsonMatch[0]);
|
|
186
|
-
return {
|
|
187
|
-
type: parsed.type || 'search',
|
|
188
|
-
keywords: Array.isArray(parsed.keywords) ? parsed.keywords : [query],
|
|
189
|
-
filters: {
|
|
190
|
-
symbolKind: parsed.symbolKind || undefined,
|
|
191
|
-
filePattern: parsed.filePattern || undefined,
|
|
192
|
-
limit: 10,
|
|
193
|
-
},
|
|
194
|
-
originalQuery: query,
|
|
195
|
-
};
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
catch {
|
|
199
|
-
// Fall back to rule-based parsing
|
|
200
|
-
}
|
|
201
|
-
return this.parseQuery(query);
|
|
202
|
-
}
|
|
203
|
-
/**
|
|
204
|
-
* Use AI to generate a natural language summary of exploration results.
|
|
205
|
-
*/
|
|
206
|
-
async summarizeWithAI(query, result, aiEnhancer) {
|
|
207
|
-
try {
|
|
208
|
-
const filesInfo = result.files.slice(0, 5).map(f => `- ${f.path}: ${f.reason}`).join('\n');
|
|
209
|
-
const symbolsInfo = result.symbols.slice(0, 5).map(s => `- ${s.name} (${s.kind}) at ${s.file}:${s.line}`).join('\n');
|
|
210
|
-
const prompt = `Summarize these codebase exploration results concisely.
|
|
211
|
-
|
|
212
|
-
User asked: "${query}"
|
|
213
|
-
|
|
214
|
-
Files found (${result.files.length} total):
|
|
215
|
-
${filesInfo || 'None'}
|
|
216
|
-
|
|
217
|
-
Symbols found (${result.symbols.length} total):
|
|
218
|
-
${symbolsInfo || 'None'}
|
|
219
|
-
|
|
220
|
-
Provide a helpful 2-4 sentence summary that directly answers the user's question. Include the most relevant file paths. Be specific and actionable.`;
|
|
221
|
-
const summary = await aiEnhancer(prompt);
|
|
222
|
-
return summary.trim();
|
|
223
|
-
}
|
|
224
|
-
catch {
|
|
225
|
-
return result.answer;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
/**
|
|
229
|
-
* Get a quick overview of the codebase.
|
|
230
|
-
*/
|
|
231
|
-
getOverview() {
|
|
232
|
-
if (!this.index) {
|
|
233
|
-
return 'Index not loaded. Call initialize() first.';
|
|
234
|
-
}
|
|
235
|
-
const idx = this.index;
|
|
236
|
-
const lines = [
|
|
237
|
-
`# Codebase Overview: ${basename(idx.rootDir)}`,
|
|
238
|
-
'',
|
|
239
|
-
`**Files indexed:** ${idx.files.length}`,
|
|
240
|
-
`**Last indexed:** ${idx.createdAt}`,
|
|
241
|
-
'',
|
|
242
|
-
'## Quick Access',
|
|
243
|
-
'',
|
|
244
|
-
];
|
|
245
|
-
if (idx.quickLookup.entryPoints.length) {
|
|
246
|
-
lines.push(`**Entry Points:** ${idx.quickLookup.entryPoints.slice(0, 5).join(', ')}`);
|
|
247
|
-
}
|
|
248
|
-
if (idx.quickLookup.configFiles.length) {
|
|
249
|
-
lines.push(`**Config Files:** ${idx.quickLookup.configFiles.slice(0, 5).join(', ')}`);
|
|
250
|
-
}
|
|
251
|
-
if (idx.quickLookup.testFiles.length) {
|
|
252
|
-
lines.push(`**Test Files:** ${idx.quickLookup.testFiles.length} files`);
|
|
253
|
-
}
|
|
254
|
-
lines.push('', '## Architecture');
|
|
255
|
-
if (idx.patterns.architecture.length) {
|
|
256
|
-
lines.push(`**Detected:** ${idx.patterns.architecture.join(', ')}`);
|
|
257
|
-
}
|
|
258
|
-
if (idx.patterns.designPatterns.length) {
|
|
259
|
-
lines.push(`**Patterns:** ${idx.patterns.designPatterns.slice(0, 5).join(', ')}`);
|
|
260
|
-
}
|
|
261
|
-
return lines.join('\n');
|
|
262
|
-
}
|
|
263
|
-
// =====================================================
|
|
264
|
-
// Private Methods
|
|
265
|
-
// =====================================================
|
|
266
|
-
tryLoadCache() {
|
|
267
|
-
try {
|
|
268
|
-
if (!existsSync(this.indexPath)) {
|
|
269
|
-
return false;
|
|
270
|
-
}
|
|
271
|
-
const content = readFileSync(this.indexPath, 'utf-8');
|
|
272
|
-
const cached = JSON.parse(content);
|
|
273
|
-
// Check version and hash
|
|
274
|
-
if (cached.version !== INDEX_VERSION) {
|
|
275
|
-
return false;
|
|
276
|
-
}
|
|
277
|
-
// Quick validation: check if file count roughly matches
|
|
278
|
-
const currentFileCount = this.countFiles(this.workingDir, 0, 4);
|
|
279
|
-
const cachedFileCount = cached.files.length;
|
|
280
|
-
const drift = Math.abs(currentFileCount - cachedFileCount);
|
|
281
|
-
// Allow 10% drift before rebuilding
|
|
282
|
-
if (drift > cachedFileCount * 0.1 && drift > 10) {
|
|
283
|
-
return false;
|
|
284
|
-
}
|
|
285
|
-
// Restore Map objects from JSON
|
|
286
|
-
this.index = {
|
|
287
|
-
...cached,
|
|
288
|
-
symbols: {
|
|
289
|
-
byName: new Map(Object.entries(cached.symbols.byName || {})),
|
|
290
|
-
byKind: new Map(Object.entries(cached.symbols.byKind || {})),
|
|
291
|
-
byFile: new Map(Object.entries(cached.symbols.byFile || {})),
|
|
292
|
-
},
|
|
293
|
-
imports: {
|
|
294
|
-
imports: new Map(Object.entries(cached.imports.imports || {})),
|
|
295
|
-
importedBy: new Map(Object.entries(cached.imports.importedBy || {})),
|
|
296
|
-
},
|
|
297
|
-
};
|
|
298
|
-
return true;
|
|
299
|
-
}
|
|
300
|
-
catch {
|
|
301
|
-
return false;
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
saveCache() {
|
|
305
|
-
try {
|
|
306
|
-
mkdirSync(CACHE_DIR, { recursive: true });
|
|
307
|
-
// Convert Maps to objects for JSON serialization
|
|
308
|
-
const serializable = {
|
|
309
|
-
...this.index,
|
|
310
|
-
symbols: {
|
|
311
|
-
byName: Object.fromEntries(this.index.symbols.byName),
|
|
312
|
-
byKind: Object.fromEntries(this.index.symbols.byKind),
|
|
313
|
-
byFile: Object.fromEntries(this.index.symbols.byFile),
|
|
314
|
-
},
|
|
315
|
-
imports: {
|
|
316
|
-
imports: Object.fromEntries(this.index.imports.imports),
|
|
317
|
-
importedBy: Object.fromEntries(this.index.imports.importedBy),
|
|
318
|
-
},
|
|
319
|
-
};
|
|
320
|
-
writeFileSync(this.indexPath, JSON.stringify(serializable, null, 2));
|
|
321
|
-
}
|
|
322
|
-
catch {
|
|
323
|
-
// Ignore cache save errors
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
countFiles(dir, depth, maxDepth) {
|
|
327
|
-
if (depth >= maxDepth)
|
|
328
|
-
return 0;
|
|
329
|
-
let count = 0;
|
|
330
|
-
try {
|
|
331
|
-
const entries = readdirSync(dir, { withFileTypes: true });
|
|
332
|
-
for (const entry of entries) {
|
|
333
|
-
if (entry.name.startsWith('.') || IGNORED_DIRS.has(entry.name))
|
|
334
|
-
continue;
|
|
335
|
-
if (entry.isDirectory()) {
|
|
336
|
-
count += this.countFiles(join(dir, entry.name), depth + 1, maxDepth);
|
|
337
|
-
}
|
|
338
|
-
else if (entry.isFile() && LANGUAGE_MAP[extname(entry.name).toLowerCase()]) {
|
|
339
|
-
count++;
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
catch {
|
|
344
|
-
// Ignore errors
|
|
345
|
-
}
|
|
346
|
-
return count;
|
|
347
|
-
}
|
|
348
|
-
async buildIndex() {
|
|
349
|
-
const files = [];
|
|
350
|
-
const symbolsByName = new Map();
|
|
351
|
-
const symbolsByKind = new Map();
|
|
352
|
-
const symbolsByFile = new Map();
|
|
353
|
-
const importsMap = new Map();
|
|
354
|
-
const importedByMap = new Map();
|
|
355
|
-
const quickLookup = {
|
|
356
|
-
entryPoints: [],
|
|
357
|
-
configFiles: [],
|
|
358
|
-
testFiles: [],
|
|
359
|
-
componentFiles: [],
|
|
360
|
-
typeFiles: [],
|
|
361
|
-
utilityFiles: [],
|
|
362
|
-
routeFiles: [],
|
|
363
|
-
modelFiles: [],
|
|
364
|
-
};
|
|
365
|
-
const patterns = {
|
|
366
|
-
architecture: [],
|
|
367
|
-
designPatterns: [],
|
|
368
|
-
namingConventions: [],
|
|
369
|
-
testPatterns: [],
|
|
370
|
-
componentPatterns: [],
|
|
371
|
-
};
|
|
372
|
-
// Collect all files
|
|
373
|
-
const allFiles = this.collectFiles(this.workingDir, 0, 6);
|
|
374
|
-
const totalFiles = allFiles.length;
|
|
375
|
-
let processed = 0;
|
|
376
|
-
let lastProgressAt = 0;
|
|
377
|
-
const sendProgress = (message) => {
|
|
378
|
-
if (totalFiles === 0)
|
|
379
|
-
return;
|
|
380
|
-
const now = Date.now();
|
|
381
|
-
const shouldEmit = processed === totalFiles || now - lastProgressAt > 50;
|
|
382
|
-
if (!shouldEmit)
|
|
383
|
-
return;
|
|
384
|
-
lastProgressAt = now;
|
|
385
|
-
try {
|
|
386
|
-
reportToolProgress({
|
|
387
|
-
current: processed,
|
|
388
|
-
total: totalFiles,
|
|
389
|
-
message,
|
|
390
|
-
});
|
|
391
|
-
}
|
|
392
|
-
catch {
|
|
393
|
-
// Best-effort progress reporting; ignore failures
|
|
394
|
-
}
|
|
395
|
-
};
|
|
396
|
-
// Initial progress update so UI can display total file count
|
|
397
|
-
if (totalFiles > 0) {
|
|
398
|
-
sendProgress();
|
|
399
|
-
}
|
|
400
|
-
// Index each file
|
|
401
|
-
for (const filePath of allFiles) {
|
|
402
|
-
try {
|
|
403
|
-
processed += 1;
|
|
404
|
-
const relPath = relative(this.workingDir, filePath);
|
|
405
|
-
const indexed = this.indexFile(filePath);
|
|
406
|
-
if (indexed) {
|
|
407
|
-
files.push(indexed);
|
|
408
|
-
// Build symbol index
|
|
409
|
-
const relPath = indexed.path;
|
|
410
|
-
const fileSymbols = [];
|
|
411
|
-
for (const sym of [...indexed.symbols.functions, ...indexed.symbols.classes,
|
|
412
|
-
...indexed.symbols.interfaces, ...indexed.symbols.types]) {
|
|
413
|
-
const location = {
|
|
414
|
-
file: relPath,
|
|
415
|
-
line: sym.line,
|
|
416
|
-
kind: sym.kind,
|
|
417
|
-
signature: sym.signature,
|
|
418
|
-
};
|
|
419
|
-
// By name
|
|
420
|
-
const existing = symbolsByName.get(sym.name.toLowerCase()) || [];
|
|
421
|
-
existing.push(location);
|
|
422
|
-
symbolsByName.set(sym.name.toLowerCase(), existing);
|
|
423
|
-
// By kind
|
|
424
|
-
const byKind = symbolsByKind.get(sym.kind) || [];
|
|
425
|
-
byKind.push(location);
|
|
426
|
-
symbolsByKind.set(sym.kind, byKind);
|
|
427
|
-
fileSymbols.push(sym.name);
|
|
428
|
-
}
|
|
429
|
-
symbolsByFile.set(relPath, fileSymbols);
|
|
430
|
-
// Build import graph
|
|
431
|
-
importsMap.set(relPath, indexed.imports);
|
|
432
|
-
for (const imp of indexed.imports) {
|
|
433
|
-
const existing = importedByMap.get(imp) || [];
|
|
434
|
-
existing.push(relPath);
|
|
435
|
-
importedByMap.set(imp, existing);
|
|
436
|
-
}
|
|
437
|
-
// Categorize files
|
|
438
|
-
this.categorizeFile(indexed, quickLookup);
|
|
439
|
-
}
|
|
440
|
-
sendProgress(relPath);
|
|
441
|
-
}
|
|
442
|
-
catch {
|
|
443
|
-
// Skip files we can't index
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
// Detect patterns
|
|
447
|
-
this.detectPatterns(files, patterns);
|
|
448
|
-
// Create hash for cache validation
|
|
449
|
-
const hash = createHash('md5')
|
|
450
|
-
.update(files.map(f => f.path).sort().join('\n'))
|
|
451
|
-
.digest('hex');
|
|
452
|
-
return {
|
|
453
|
-
version: INDEX_VERSION,
|
|
454
|
-
createdAt: new Date().toISOString(),
|
|
455
|
-
rootDir: this.workingDir,
|
|
456
|
-
hash,
|
|
457
|
-
files,
|
|
458
|
-
symbols: {
|
|
459
|
-
byName: symbolsByName,
|
|
460
|
-
byKind: symbolsByKind,
|
|
461
|
-
byFile: symbolsByFile,
|
|
462
|
-
},
|
|
463
|
-
imports: {
|
|
464
|
-
imports: importsMap,
|
|
465
|
-
importedBy: importedByMap,
|
|
466
|
-
},
|
|
467
|
-
patterns,
|
|
468
|
-
quickLookup,
|
|
469
|
-
};
|
|
470
|
-
}
|
|
471
|
-
collectFiles(dir, depth, maxDepth) {
|
|
472
|
-
if (depth >= maxDepth)
|
|
473
|
-
return [];
|
|
474
|
-
const files = [];
|
|
475
|
-
try {
|
|
476
|
-
const entries = readdirSync(dir, { withFileTypes: true });
|
|
477
|
-
for (const entry of entries) {
|
|
478
|
-
if (entry.name.startsWith('.') || IGNORED_DIRS.has(entry.name))
|
|
479
|
-
continue;
|
|
480
|
-
const fullPath = join(dir, entry.name);
|
|
481
|
-
if (entry.isDirectory()) {
|
|
482
|
-
files.push(...this.collectFiles(fullPath, depth + 1, maxDepth));
|
|
483
|
-
}
|
|
484
|
-
else if (entry.isFile()) {
|
|
485
|
-
const ext = extname(entry.name).toLowerCase();
|
|
486
|
-
if (LANGUAGE_MAP[ext]) {
|
|
487
|
-
files.push(fullPath);
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
catch {
|
|
493
|
-
// Ignore errors
|
|
494
|
-
}
|
|
495
|
-
return files;
|
|
496
|
-
}
|
|
497
|
-
indexFile(filePath) {
|
|
498
|
-
try {
|
|
499
|
-
const stat = statSync(filePath);
|
|
500
|
-
if (stat.size > 500000)
|
|
501
|
-
return null; // Skip large files
|
|
502
|
-
const content = readFileSync(filePath, 'utf-8');
|
|
503
|
-
const lines = content.split('\n');
|
|
504
|
-
const ext = extname(filePath).toLowerCase();
|
|
505
|
-
const language = LANGUAGE_MAP[ext] || 'Unknown';
|
|
506
|
-
const relPath = relative(this.workingDir, filePath);
|
|
507
|
-
const symbols = this.extractSymbols(content, ext);
|
|
508
|
-
const imports = this.extractImports(content, ext);
|
|
509
|
-
const exports = this.extractExports(content, ext);
|
|
510
|
-
const purpose = this.inferPurpose(basename(filePath), content, symbols);
|
|
511
|
-
const tags = this.generateTags(relPath, content, symbols, purpose);
|
|
512
|
-
return {
|
|
513
|
-
path: relPath,
|
|
514
|
-
language,
|
|
515
|
-
size: stat.size,
|
|
516
|
-
lineCount: lines.length,
|
|
517
|
-
lastModified: stat.mtimeMs,
|
|
518
|
-
symbols,
|
|
519
|
-
imports,
|
|
520
|
-
exports,
|
|
521
|
-
purpose,
|
|
522
|
-
tags,
|
|
523
|
-
};
|
|
524
|
-
}
|
|
525
|
-
catch {
|
|
526
|
-
return null;
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
extractSymbols(content, ext) {
|
|
530
|
-
const symbols = {
|
|
531
|
-
functions: [],
|
|
532
|
-
classes: [],
|
|
533
|
-
interfaces: [],
|
|
534
|
-
types: [],
|
|
535
|
-
constants: [],
|
|
536
|
-
variables: [],
|
|
537
|
-
};
|
|
538
|
-
if (!['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'].includes(ext)) {
|
|
539
|
-
return symbols; // Only analyze JS/TS for now
|
|
540
|
-
}
|
|
541
|
-
// Extract functions
|
|
542
|
-
const funcRegex = /(?:export\s+)?(?:async\s+)?function\s+(\w+)\s*\(([^)]*)\)/g;
|
|
543
|
-
let match;
|
|
544
|
-
while ((match = funcRegex.exec(content)) !== null) {
|
|
545
|
-
const line = content.substring(0, match.index).split('\n').length;
|
|
546
|
-
symbols.functions.push({
|
|
547
|
-
name: match[1] || '',
|
|
548
|
-
line,
|
|
549
|
-
kind: 'function',
|
|
550
|
-
isExported: content.substring(match.index - 20, match.index).includes('export'),
|
|
551
|
-
signature: `${match[1]}(${match[2]})`,
|
|
552
|
-
});
|
|
553
|
-
}
|
|
554
|
-
// Arrow functions
|
|
555
|
-
const arrowRegex = /(?:export\s+)?(?:const|let)\s+(\w+)\s*=\s*(?:async\s+)?\(?([^)=]*)\)?\s*=>/g;
|
|
556
|
-
while ((match = arrowRegex.exec(content)) !== null) {
|
|
557
|
-
const line = content.substring(0, match.index).split('\n').length;
|
|
558
|
-
symbols.functions.push({
|
|
559
|
-
name: match[1] || '',
|
|
560
|
-
line,
|
|
561
|
-
kind: 'function',
|
|
562
|
-
isExported: content.substring(match.index - 20, match.index).includes('export'),
|
|
563
|
-
signature: `${match[1]}(${match[2] || ''})`,
|
|
564
|
-
});
|
|
565
|
-
}
|
|
566
|
-
// Classes
|
|
567
|
-
const classRegex = /(?:export\s+)?class\s+(\w+)(?:\s+extends\s+(\w+))?/g;
|
|
568
|
-
while ((match = classRegex.exec(content)) !== null) {
|
|
569
|
-
const line = content.substring(0, match.index).split('\n').length;
|
|
570
|
-
symbols.classes.push({
|
|
571
|
-
name: match[1] || '',
|
|
572
|
-
line,
|
|
573
|
-
kind: 'class',
|
|
574
|
-
isExported: content.substring(match.index - 20, match.index).includes('export'),
|
|
575
|
-
signature: match[2] ? `class ${match[1]} extends ${match[2]}` : `class ${match[1]}`,
|
|
576
|
-
});
|
|
577
|
-
}
|
|
578
|
-
// Interfaces
|
|
579
|
-
const interfaceRegex = /(?:export\s+)?interface\s+(\w+)(?:\s+extends\s+([^{]+))?/g;
|
|
580
|
-
while ((match = interfaceRegex.exec(content)) !== null) {
|
|
581
|
-
const line = content.substring(0, match.index).split('\n').length;
|
|
582
|
-
symbols.interfaces.push({
|
|
583
|
-
name: match[1] || '',
|
|
584
|
-
line,
|
|
585
|
-
kind: 'interface',
|
|
586
|
-
isExported: content.substring(match.index - 20, match.index).includes('export'),
|
|
587
|
-
signature: `interface ${match[1]}`,
|
|
588
|
-
});
|
|
589
|
-
}
|
|
590
|
-
// Types
|
|
591
|
-
const typeRegex = /(?:export\s+)?type\s+(\w+)\s*=/g;
|
|
592
|
-
while ((match = typeRegex.exec(content)) !== null) {
|
|
593
|
-
const line = content.substring(0, match.index).split('\n').length;
|
|
594
|
-
symbols.types.push({
|
|
595
|
-
name: match[1] || '',
|
|
596
|
-
line,
|
|
597
|
-
kind: 'type',
|
|
598
|
-
isExported: content.substring(match.index - 20, match.index).includes('export'),
|
|
599
|
-
signature: `type ${match[1]}`,
|
|
600
|
-
});
|
|
601
|
-
}
|
|
602
|
-
// Constants
|
|
603
|
-
const constRegex = /(?:export\s+)?const\s+([A-Z][A-Z_0-9]+)\s*=/g;
|
|
604
|
-
while ((match = constRegex.exec(content)) !== null) {
|
|
605
|
-
const line = content.substring(0, match.index).split('\n').length;
|
|
606
|
-
symbols.constants.push({
|
|
607
|
-
name: match[1] || '',
|
|
608
|
-
line,
|
|
609
|
-
kind: 'const',
|
|
610
|
-
isExported: content.substring(match.index - 20, match.index).includes('export'),
|
|
611
|
-
});
|
|
612
|
-
}
|
|
613
|
-
return symbols;
|
|
614
|
-
}
|
|
615
|
-
extractImports(content, ext) {
|
|
616
|
-
const imports = [];
|
|
617
|
-
if (!['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'].includes(ext)) {
|
|
618
|
-
return imports;
|
|
619
|
-
}
|
|
620
|
-
// ES6 imports
|
|
621
|
-
const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
622
|
-
let match;
|
|
623
|
-
while ((match = importRegex.exec(content)) !== null) {
|
|
624
|
-
const source = match[1] || '';
|
|
625
|
-
if (source.startsWith('.')) {
|
|
626
|
-
// Resolve relative imports
|
|
627
|
-
imports.push(source);
|
|
628
|
-
}
|
|
629
|
-
}
|
|
630
|
-
return imports;
|
|
631
|
-
}
|
|
632
|
-
extractExports(content, ext) {
|
|
633
|
-
const exports = [];
|
|
634
|
-
if (!['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'].includes(ext)) {
|
|
635
|
-
return exports;
|
|
636
|
-
}
|
|
637
|
-
// Named exports
|
|
638
|
-
const namedExportRegex = /export\s+(?:const|let|var|function|class|interface|type|enum)\s+(\w+)/g;
|
|
639
|
-
let match;
|
|
640
|
-
while ((match = namedExportRegex.exec(content)) !== null) {
|
|
641
|
-
if (match[1])
|
|
642
|
-
exports.push(match[1]);
|
|
643
|
-
}
|
|
644
|
-
// Default export
|
|
645
|
-
if (/export\s+default/.test(content)) {
|
|
646
|
-
exports.push('default');
|
|
647
|
-
}
|
|
648
|
-
return exports;
|
|
649
|
-
}
|
|
650
|
-
inferPurpose(filename, content, symbols) {
|
|
651
|
-
const lower = filename.toLowerCase();
|
|
652
|
-
if (lower.includes('test') || lower.includes('spec'))
|
|
653
|
-
return 'Test file';
|
|
654
|
-
if (lower === 'index.ts' || lower === 'index.js')
|
|
655
|
-
return 'Module entry point';
|
|
656
|
-
if (lower.includes('config'))
|
|
657
|
-
return 'Configuration';
|
|
658
|
-
if (lower.includes('type') || lower.includes('interface'))
|
|
659
|
-
return 'Type definitions';
|
|
660
|
-
if (lower.includes('util') || lower.includes('helper'))
|
|
661
|
-
return 'Utilities';
|
|
662
|
-
if (lower.includes('hook'))
|
|
663
|
-
return 'React hooks';
|
|
664
|
-
if (lower.includes('context'))
|
|
665
|
-
return 'Context provider';
|
|
666
|
-
if (lower.includes('store') || lower.includes('reducer'))
|
|
667
|
-
return 'State management';
|
|
668
|
-
if (lower.includes('service'))
|
|
669
|
-
return 'Business logic';
|
|
670
|
-
if (lower.includes('api') || lower.includes('client'))
|
|
671
|
-
return 'API client';
|
|
672
|
-
if (lower.includes('route'))
|
|
673
|
-
return 'Routes';
|
|
674
|
-
if (lower.includes('middleware'))
|
|
675
|
-
return 'Middleware';
|
|
676
|
-
if (lower.includes('model') || lower.includes('entity'))
|
|
677
|
-
return 'Data models';
|
|
678
|
-
if (lower.includes('schema'))
|
|
679
|
-
return 'Schema definitions';
|
|
680
|
-
if (lower.includes('component'))
|
|
681
|
-
return 'UI component';
|
|
682
|
-
if (symbols.classes.length > 0)
|
|
683
|
-
return `Class: ${symbols.classes[0]?.name}`;
|
|
684
|
-
if (symbols.interfaces.length > 0)
|
|
685
|
-
return `Types/Interfaces`;
|
|
686
|
-
if (symbols.functions.length > 0)
|
|
687
|
-
return `Functions: ${symbols.functions.slice(0, 3).map(f => f.name).join(', ')}`;
|
|
688
|
-
return 'General module';
|
|
689
|
-
}
|
|
690
|
-
generateTags(path, content, symbols, purpose) {
|
|
691
|
-
const tags = [];
|
|
692
|
-
// Add purpose-based tags
|
|
693
|
-
tags.push(purpose.toLowerCase().split(':')[0] || '');
|
|
694
|
-
// Add path-based tags
|
|
695
|
-
const parts = path.split('/');
|
|
696
|
-
for (const part of parts.slice(0, -1)) {
|
|
697
|
-
if (part && !part.startsWith('.')) {
|
|
698
|
-
tags.push(part.toLowerCase());
|
|
699
|
-
}
|
|
700
|
-
}
|
|
701
|
-
// Add symbol-based tags
|
|
702
|
-
for (const sym of symbols.functions) {
|
|
703
|
-
if (sym.isExported)
|
|
704
|
-
tags.push(sym.name.toLowerCase());
|
|
705
|
-
}
|
|
706
|
-
for (const sym of symbols.classes) {
|
|
707
|
-
if (sym.isExported)
|
|
708
|
-
tags.push(sym.name.toLowerCase());
|
|
709
|
-
}
|
|
710
|
-
// Add content-based tags
|
|
711
|
-
if (/useEffect|useState|useCallback/.test(content))
|
|
712
|
-
tags.push('react', 'hooks');
|
|
713
|
-
if (/async\s+function|await\s+/.test(content))
|
|
714
|
-
tags.push('async');
|
|
715
|
-
if (/express|fastify|koa/.test(content))
|
|
716
|
-
tags.push('server', 'http');
|
|
717
|
-
if (/import.*prisma|import.*mongoose/.test(content))
|
|
718
|
-
tags.push('database');
|
|
719
|
-
if (/import.*zod|import.*yup|import.*joi/.test(content))
|
|
720
|
-
tags.push('validation');
|
|
721
|
-
if (/describe\s*\(|it\s*\(|test\s*\(/.test(content))
|
|
722
|
-
tags.push('test');
|
|
723
|
-
return [...new Set(tags.filter(Boolean))];
|
|
724
|
-
}
|
|
725
|
-
categorizeFile(file, lookup) {
|
|
726
|
-
const lower = file.path.toLowerCase();
|
|
727
|
-
const name = basename(file.path).toLowerCase();
|
|
728
|
-
// Entry points
|
|
729
|
-
if (['index.ts', 'index.js', 'main.ts', 'main.js', 'app.ts', 'app.js'].includes(name)) {
|
|
730
|
-
lookup.entryPoints.push(file.path);
|
|
731
|
-
}
|
|
732
|
-
// Config files
|
|
733
|
-
if (name.includes('config') || name.includes('settings') || name.includes('.rc')) {
|
|
734
|
-
lookup.configFiles.push(file.path);
|
|
735
|
-
}
|
|
736
|
-
// Test files
|
|
737
|
-
if (lower.includes('test') || lower.includes('spec') || lower.includes('__tests__')) {
|
|
738
|
-
lookup.testFiles.push(file.path);
|
|
739
|
-
}
|
|
740
|
-
// Component files
|
|
741
|
-
if (lower.includes('component') || lower.includes('components/') ||
|
|
742
|
-
file.language.includes('React')) {
|
|
743
|
-
lookup.componentFiles.push(file.path);
|
|
744
|
-
}
|
|
745
|
-
// Type files
|
|
746
|
-
if (lower.includes('type') || lower.includes('interface') || name.endsWith('.d.ts')) {
|
|
747
|
-
lookup.typeFiles.push(file.path);
|
|
748
|
-
}
|
|
749
|
-
// Utility files
|
|
750
|
-
if (lower.includes('util') || lower.includes('helper') || lower.includes('lib/')) {
|
|
751
|
-
lookup.utilityFiles.push(file.path);
|
|
752
|
-
}
|
|
753
|
-
// Route files
|
|
754
|
-
if (lower.includes('route') || lower.includes('api/')) {
|
|
755
|
-
lookup.routeFiles.push(file.path);
|
|
756
|
-
}
|
|
757
|
-
// Model files
|
|
758
|
-
if (lower.includes('model') || lower.includes('entity') || lower.includes('schema')) {
|
|
759
|
-
lookup.modelFiles.push(file.path);
|
|
760
|
-
}
|
|
761
|
-
}
|
|
762
|
-
detectPatterns(files, patterns) {
|
|
763
|
-
const dirs = new Set();
|
|
764
|
-
for (const file of files) {
|
|
765
|
-
const dir = dirname(file.path);
|
|
766
|
-
dirs.add(dir.split('/')[0] || dir);
|
|
767
|
-
}
|
|
768
|
-
// Detect architecture patterns
|
|
769
|
-
if (dirs.has('src') && (dirs.has('components') || dirs.has('views'))) {
|
|
770
|
-
patterns.architecture.push('Component-based');
|
|
771
|
-
}
|
|
772
|
-
if (dirs.has('api') || dirs.has('routes')) {
|
|
773
|
-
patterns.architecture.push('API-driven');
|
|
774
|
-
}
|
|
775
|
-
if (dirs.has('services') && dirs.has('controllers')) {
|
|
776
|
-
patterns.architecture.push('Layered');
|
|
777
|
-
}
|
|
778
|
-
if (dirs.has('domain') || dirs.has('entities')) {
|
|
779
|
-
patterns.architecture.push('Domain-driven');
|
|
780
|
-
}
|
|
781
|
-
// Detect design patterns
|
|
782
|
-
const allContent = files.slice(0, 50).map(f => {
|
|
783
|
-
try {
|
|
784
|
-
return readFileSync(join(this.workingDir, f.path), 'utf-8');
|
|
785
|
-
}
|
|
786
|
-
catch {
|
|
787
|
-
return '';
|
|
788
|
-
}
|
|
789
|
-
}).join('\n');
|
|
790
|
-
if (/singleton|getInstance/i.test(allContent))
|
|
791
|
-
patterns.designPatterns.push('Singleton');
|
|
792
|
-
if (/factory|create\w+/i.test(allContent))
|
|
793
|
-
patterns.designPatterns.push('Factory');
|
|
794
|
-
if (/observer|subscribe|emit/i.test(allContent))
|
|
795
|
-
patterns.designPatterns.push('Observer');
|
|
796
|
-
if (/strategy|\bstrategy\b/i.test(allContent))
|
|
797
|
-
patterns.designPatterns.push('Strategy');
|
|
798
|
-
if (/decorator|@\w+/i.test(allContent))
|
|
799
|
-
patterns.designPatterns.push('Decorator');
|
|
800
|
-
// Detect naming conventions
|
|
801
|
-
const fileNames = files.map(f => basename(f.path, extname(f.path)));
|
|
802
|
-
if (fileNames.some(n => /[a-z]+-[a-z]+/.test(n)))
|
|
803
|
-
patterns.namingConventions.push('kebab-case');
|
|
804
|
-
if (fileNames.some(n => /[a-z]+[A-Z]/.test(n)))
|
|
805
|
-
patterns.namingConventions.push('camelCase');
|
|
806
|
-
if (fileNames.some(n => /^[A-Z][a-z]+[A-Z]/.test(n)))
|
|
807
|
-
patterns.namingConventions.push('PascalCase');
|
|
808
|
-
if (fileNames.some(n => /[a-z]+_[a-z]+/.test(n)))
|
|
809
|
-
patterns.namingConventions.push('snake_case');
|
|
810
|
-
}
|
|
811
|
-
parseQuery(query) {
|
|
812
|
-
const normalized = query.trim().toLowerCase();
|
|
813
|
-
let type = 'search';
|
|
814
|
-
for (const { pattern, type: queryType } of QUERY_PATTERNS) {
|
|
815
|
-
if (pattern.test(query)) {
|
|
816
|
-
type = queryType;
|
|
817
|
-
break;
|
|
818
|
-
}
|
|
819
|
-
}
|
|
820
|
-
// Extract keywords
|
|
821
|
-
const stopWords = new Set(['the', 'a', 'an', 'is', 'are', 'where', 'what', 'how', 'which', 'find', 'show', 'get', 'me', 'i', 'can', 'do', 'does', 'for', 'to', 'in', 'of']);
|
|
822
|
-
const keywords = normalized
|
|
823
|
-
.replace(/[^\w\s]/g, ' ')
|
|
824
|
-
.split(/\s+/)
|
|
825
|
-
.filter(w => w.length > 2 && !stopWords.has(w));
|
|
826
|
-
// Extract filters from query
|
|
827
|
-
const filters = { limit: 10 };
|
|
828
|
-
// File pattern filter
|
|
829
|
-
const fileMatch = query.match(/(?:in|from|file)\s+([^\s]+\.[a-z]+)/i);
|
|
830
|
-
if (fileMatch) {
|
|
831
|
-
filters.filePattern = fileMatch[1];
|
|
832
|
-
}
|
|
833
|
-
// Language filter
|
|
834
|
-
const langMatch = query.match(/(typescript|javascript|python|rust|go)/i);
|
|
835
|
-
if (langMatch) {
|
|
836
|
-
filters.language = langMatch[1];
|
|
837
|
-
}
|
|
838
|
-
// Symbol kind filter
|
|
839
|
-
const kindMatch = query.match(/(function|class|type|interface|constant)/i);
|
|
840
|
-
if (kindMatch && kindMatch[1]) {
|
|
841
|
-
filters.symbolKind = kindMatch[1].toLowerCase();
|
|
842
|
-
}
|
|
843
|
-
return {
|
|
844
|
-
type,
|
|
845
|
-
keywords,
|
|
846
|
-
filters,
|
|
847
|
-
originalQuery: query,
|
|
848
|
-
};
|
|
849
|
-
}
|
|
850
|
-
async executeQuery(query) {
|
|
851
|
-
const result = {
|
|
852
|
-
query: query.originalQuery,
|
|
853
|
-
queryType: query.type,
|
|
854
|
-
files: [],
|
|
855
|
-
symbols: [],
|
|
856
|
-
answer: '',
|
|
857
|
-
suggestions: [],
|
|
858
|
-
timeTaken: 0,
|
|
859
|
-
};
|
|
860
|
-
switch (query.type) {
|
|
861
|
-
case 'find_file':
|
|
862
|
-
this.findFiles(query, result);
|
|
863
|
-
break;
|
|
864
|
-
case 'find_symbol':
|
|
865
|
-
this.findSymbols(query, result);
|
|
866
|
-
break;
|
|
867
|
-
case 'find_usage':
|
|
868
|
-
this.findUsages(query, result);
|
|
869
|
-
break;
|
|
870
|
-
case 'architecture':
|
|
871
|
-
this.explainArchitecture(query, result);
|
|
872
|
-
break;
|
|
873
|
-
case 'dependencies':
|
|
874
|
-
this.showDependencies(query, result);
|
|
875
|
-
break;
|
|
876
|
-
case 'understand':
|
|
877
|
-
case 'explain':
|
|
878
|
-
this.explainConcept(query, result);
|
|
879
|
-
break;
|
|
880
|
-
case 'search':
|
|
881
|
-
default:
|
|
882
|
-
this.generalSearch(query, result);
|
|
883
|
-
break;
|
|
884
|
-
}
|
|
885
|
-
// Generate suggestions
|
|
886
|
-
this.generateSuggestions(query, result);
|
|
887
|
-
return result;
|
|
888
|
-
}
|
|
889
|
-
findFiles(query, result) {
|
|
890
|
-
const matches = [];
|
|
891
|
-
for (const file of this.index.files) {
|
|
892
|
-
let relevance = 0;
|
|
893
|
-
for (const keyword of query.keywords) {
|
|
894
|
-
const keywordLower = keyword.toLowerCase();
|
|
895
|
-
// Match in path
|
|
896
|
-
if (file.path.toLowerCase().includes(keywordLower)) {
|
|
897
|
-
relevance += 10;
|
|
898
|
-
}
|
|
899
|
-
// Match in tags
|
|
900
|
-
if (file.tags.some(t => t.includes(keywordLower))) {
|
|
901
|
-
relevance += 5;
|
|
902
|
-
}
|
|
903
|
-
// Match in purpose
|
|
904
|
-
if (file.purpose.toLowerCase().includes(keywordLower)) {
|
|
905
|
-
relevance += 3;
|
|
906
|
-
}
|
|
907
|
-
// Match symbol names
|
|
908
|
-
const allSymbols = [...file.symbols.functions, ...file.symbols.classes];
|
|
909
|
-
if (allSymbols.some(s => s.name.toLowerCase().includes(keywordLower))) {
|
|
910
|
-
relevance += 7;
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
|
-
// Apply filters
|
|
914
|
-
if (query.filters.filePattern && !file.path.includes(query.filters.filePattern)) {
|
|
915
|
-
relevance = 0;
|
|
916
|
-
}
|
|
917
|
-
if (query.filters.language && !file.language.toLowerCase().includes(query.filters.language.toLowerCase())) {
|
|
918
|
-
relevance = 0;
|
|
919
|
-
}
|
|
920
|
-
if (relevance > 0) {
|
|
921
|
-
matches.push({
|
|
922
|
-
path: file.path,
|
|
923
|
-
relevance,
|
|
924
|
-
reason: file.purpose,
|
|
925
|
-
});
|
|
926
|
-
}
|
|
927
|
-
}
|
|
928
|
-
// Sort by relevance and limit
|
|
929
|
-
matches.sort((a, b) => b.relevance - a.relevance);
|
|
930
|
-
result.files = matches.slice(0, query.filters.limit || 10);
|
|
931
|
-
// Generate answer
|
|
932
|
-
if (result.files.length > 0) {
|
|
933
|
-
const topFiles = result.files.slice(0, 5);
|
|
934
|
-
result.answer = [
|
|
935
|
-
`Found ${result.files.length} relevant file(s) for "${query.keywords.join(' ')}":`,
|
|
936
|
-
'',
|
|
937
|
-
...topFiles.map(f => `• **${f.path}** - ${f.reason}`),
|
|
938
|
-
result.files.length > 5 ? `\n...and ${result.files.length - 5} more files` : '',
|
|
939
|
-
].join('\n');
|
|
940
|
-
}
|
|
941
|
-
else {
|
|
942
|
-
result.answer = `No files found matching "${query.keywords.join(' ')}". Try different keywords or check the spelling.`;
|
|
943
|
-
}
|
|
944
|
-
}
|
|
945
|
-
findSymbols(query, result) {
|
|
946
|
-
const matches = [];
|
|
947
|
-
for (const keyword of query.keywords) {
|
|
948
|
-
const keywordLower = keyword.toLowerCase();
|
|
949
|
-
const locations = this.index.symbols.byName.get(keywordLower) || [];
|
|
950
|
-
for (const loc of locations) {
|
|
951
|
-
// Check kind filter
|
|
952
|
-
if (query.filters.symbolKind && loc.kind !== query.filters.symbolKind) {
|
|
953
|
-
continue;
|
|
954
|
-
}
|
|
955
|
-
matches.push({
|
|
956
|
-
name: keyword,
|
|
957
|
-
file: loc.file,
|
|
958
|
-
line: loc.line,
|
|
959
|
-
kind: loc.kind,
|
|
960
|
-
relevance: 10,
|
|
961
|
-
});
|
|
962
|
-
}
|
|
963
|
-
}
|
|
964
|
-
// Also search partial matches
|
|
965
|
-
for (const [name, locations] of this.index.symbols.byName) {
|
|
966
|
-
for (const keyword of query.keywords) {
|
|
967
|
-
if (name.includes(keyword.toLowerCase()) && !matches.some(m => m.name === name)) {
|
|
968
|
-
for (const loc of locations) {
|
|
969
|
-
if (query.filters.symbolKind && loc.kind !== query.filters.symbolKind)
|
|
970
|
-
continue;
|
|
971
|
-
matches.push({
|
|
972
|
-
name,
|
|
973
|
-
file: loc.file,
|
|
974
|
-
line: loc.line,
|
|
975
|
-
kind: loc.kind,
|
|
976
|
-
relevance: 5,
|
|
977
|
-
});
|
|
978
|
-
}
|
|
979
|
-
}
|
|
980
|
-
}
|
|
981
|
-
}
|
|
982
|
-
matches.sort((a, b) => b.relevance - a.relevance);
|
|
983
|
-
result.symbols = matches.slice(0, query.filters.limit || 10);
|
|
984
|
-
// Generate answer
|
|
985
|
-
if (result.symbols.length > 0) {
|
|
986
|
-
const topSymbols = result.symbols.slice(0, 5);
|
|
987
|
-
result.answer = [
|
|
988
|
-
`Found ${result.symbols.length} symbol(s) matching "${query.keywords.join(' ')}":`,
|
|
989
|
-
'',
|
|
990
|
-
...topSymbols.map(s => `• **${s.name}** (${s.kind}) at ${s.file}:${s.line}`),
|
|
991
|
-
result.symbols.length > 5 ? `\n...and ${result.symbols.length - 5} more symbols` : '',
|
|
992
|
-
].join('\n');
|
|
993
|
-
}
|
|
994
|
-
else {
|
|
995
|
-
result.answer = `No symbols found matching "${query.keywords.join(' ')}".`;
|
|
996
|
-
}
|
|
997
|
-
}
|
|
998
|
-
findUsages(query, result) {
|
|
999
|
-
for (const keyword of query.keywords) {
|
|
1000
|
-
const keywordLower = keyword.toLowerCase();
|
|
1001
|
-
// Find files that import this symbol
|
|
1002
|
-
for (const file of this.index.files) {
|
|
1003
|
-
// Check if file content mentions the keyword
|
|
1004
|
-
const fullPath = join(this.workingDir, file.path);
|
|
1005
|
-
try {
|
|
1006
|
-
const content = readFileSync(fullPath, 'utf-8');
|
|
1007
|
-
if (content.toLowerCase().includes(keywordLower)) {
|
|
1008
|
-
const lines = content.split('\n');
|
|
1009
|
-
const matchingLines = lines
|
|
1010
|
-
.map((line, i) => ({ line, num: i + 1 }))
|
|
1011
|
-
.filter(({ line }) => line.toLowerCase().includes(keywordLower))
|
|
1012
|
-
.slice(0, 3);
|
|
1013
|
-
result.files.push({
|
|
1014
|
-
path: file.path,
|
|
1015
|
-
relevance: matchingLines.length * 3,
|
|
1016
|
-
reason: `Used on line${matchingLines.length > 1 ? 's' : ''} ${matchingLines.map(l => l.num).join(', ')}`,
|
|
1017
|
-
snippets: matchingLines.map(l => l.line.trim()),
|
|
1018
|
-
});
|
|
1019
|
-
}
|
|
1020
|
-
}
|
|
1021
|
-
catch {
|
|
1022
|
-
// Skip unreadable files
|
|
1023
|
-
}
|
|
1024
|
-
}
|
|
1025
|
-
}
|
|
1026
|
-
result.files.sort((a, b) => b.relevance - a.relevance);
|
|
1027
|
-
result.files = result.files.slice(0, query.filters.limit || 10);
|
|
1028
|
-
if (result.files.length > 0) {
|
|
1029
|
-
result.answer = [
|
|
1030
|
-
`Found ${result.files.length} file(s) using "${query.keywords.join(' ')}":`,
|
|
1031
|
-
'',
|
|
1032
|
-
...result.files.slice(0, 5).map(f => `• **${f.path}** - ${f.reason}`),
|
|
1033
|
-
].join('\n');
|
|
1034
|
-
}
|
|
1035
|
-
else {
|
|
1036
|
-
result.answer = `No usages found for "${query.keywords.join(' ')}".`;
|
|
1037
|
-
}
|
|
1038
|
-
}
|
|
1039
|
-
explainArchitecture(_query, result) {
|
|
1040
|
-
const patterns = this.index.patterns;
|
|
1041
|
-
const lookup = this.index.quickLookup;
|
|
1042
|
-
const lines = [
|
|
1043
|
-
'# Architecture Overview',
|
|
1044
|
-
'',
|
|
1045
|
-
];
|
|
1046
|
-
if (patterns.architecture.length) {
|
|
1047
|
-
lines.push(`**Architectural Style:** ${patterns.architecture.join(', ')}`);
|
|
1048
|
-
lines.push('');
|
|
1049
|
-
}
|
|
1050
|
-
if (patterns.designPatterns.length) {
|
|
1051
|
-
lines.push(`**Design Patterns:** ${patterns.designPatterns.join(', ')}`);
|
|
1052
|
-
lines.push('');
|
|
1053
|
-
}
|
|
1054
|
-
lines.push('## Key Areas');
|
|
1055
|
-
lines.push('');
|
|
1056
|
-
if (lookup.entryPoints.length) {
|
|
1057
|
-
lines.push(`**Entry Points:** ${lookup.entryPoints.slice(0, 3).join(', ')}`);
|
|
1058
|
-
}
|
|
1059
|
-
if (lookup.componentFiles.length) {
|
|
1060
|
-
lines.push(`**Components:** ${lookup.componentFiles.length} files`);
|
|
1061
|
-
}
|
|
1062
|
-
if (lookup.routeFiles.length) {
|
|
1063
|
-
lines.push(`**Routes/API:** ${lookup.routeFiles.length} files`);
|
|
1064
|
-
}
|
|
1065
|
-
if (lookup.modelFiles.length) {
|
|
1066
|
-
lines.push(`**Models:** ${lookup.modelFiles.length} files`);
|
|
1067
|
-
}
|
|
1068
|
-
if (lookup.testFiles.length) {
|
|
1069
|
-
lines.push(`**Tests:** ${lookup.testFiles.length} files`);
|
|
1070
|
-
}
|
|
1071
|
-
if (patterns.namingConventions.length) {
|
|
1072
|
-
lines.push('');
|
|
1073
|
-
lines.push(`**Naming Conventions:** ${patterns.namingConventions.join(', ')}`);
|
|
1074
|
-
}
|
|
1075
|
-
result.answer = lines.join('\n');
|
|
1076
|
-
}
|
|
1077
|
-
showDependencies(query, result) {
|
|
1078
|
-
// Find the most relevant file
|
|
1079
|
-
const targetFile = query.keywords.length > 0
|
|
1080
|
-
? this.index.files.find(f => query.keywords.some(k => f.path.toLowerCase().includes(k.toLowerCase())))
|
|
1081
|
-
: this.index.quickLookup.entryPoints[0];
|
|
1082
|
-
if (!targetFile) {
|
|
1083
|
-
result.answer = 'Specify a file to show dependencies for.';
|
|
1084
|
-
return;
|
|
1085
|
-
}
|
|
1086
|
-
const filePath = typeof targetFile === 'string' ? targetFile : targetFile.path;
|
|
1087
|
-
const imports = this.index.imports.imports.get(filePath) || [];
|
|
1088
|
-
const importedBy = this.index.imports.importedBy.get(filePath) || [];
|
|
1089
|
-
const lines = [
|
|
1090
|
-
`# Dependencies for ${filePath}`,
|
|
1091
|
-
'',
|
|
1092
|
-
'## Imports (dependencies)',
|
|
1093
|
-
imports.length ? imports.map(i => `• ${i}`).join('\n') : 'No local imports',
|
|
1094
|
-
'',
|
|
1095
|
-
'## Imported by (dependents)',
|
|
1096
|
-
importedBy.length ? importedBy.map(i => `• ${i}`).join('\n') : 'Not imported by other files',
|
|
1097
|
-
];
|
|
1098
|
-
result.answer = lines.join('\n');
|
|
1099
|
-
}
|
|
1100
|
-
explainConcept(query, result) {
|
|
1101
|
-
// Combine file and symbol search for conceptual queries
|
|
1102
|
-
this.findFiles(query, result);
|
|
1103
|
-
this.findSymbols(query, result);
|
|
1104
|
-
// Enhanced answer
|
|
1105
|
-
const allMatches = result.files.length + result.symbols.length;
|
|
1106
|
-
if (allMatches > 0) {
|
|
1107
|
-
const parts = [
|
|
1108
|
-
`Found ${allMatches} relevant result(s) for "${query.keywords.join(' ')}":`,
|
|
1109
|
-
'',
|
|
1110
|
-
];
|
|
1111
|
-
if (result.symbols.length > 0) {
|
|
1112
|
-
parts.push('**Symbols:**');
|
|
1113
|
-
for (const s of result.symbols.slice(0, 3)) {
|
|
1114
|
-
parts.push(`• ${s.name} (${s.kind}) at ${s.file}:${s.line}`);
|
|
1115
|
-
}
|
|
1116
|
-
parts.push('');
|
|
1117
|
-
}
|
|
1118
|
-
if (result.files.length > 0) {
|
|
1119
|
-
parts.push('**Files:**');
|
|
1120
|
-
for (const f of result.files.slice(0, 3)) {
|
|
1121
|
-
parts.push(`• ${f.path} - ${f.reason}`);
|
|
1122
|
-
}
|
|
1123
|
-
}
|
|
1124
|
-
result.answer = parts.join('\n');
|
|
1125
|
-
}
|
|
1126
|
-
}
|
|
1127
|
-
generalSearch(query, result) {
|
|
1128
|
-
// Combine all search methods
|
|
1129
|
-
this.findFiles(query, result);
|
|
1130
|
-
const fileMatches = [...result.files];
|
|
1131
|
-
result.files = [];
|
|
1132
|
-
this.findSymbols(query, result);
|
|
1133
|
-
const symbolMatches = [...result.symbols];
|
|
1134
|
-
// Merge results
|
|
1135
|
-
result.files = fileMatches;
|
|
1136
|
-
result.symbols = symbolMatches;
|
|
1137
|
-
// Generate combined answer
|
|
1138
|
-
const parts = [];
|
|
1139
|
-
if (symbolMatches.length > 0) {
|
|
1140
|
-
parts.push(`**Symbols (${symbolMatches.length}):**`);
|
|
1141
|
-
for (const s of symbolMatches.slice(0, 5)) {
|
|
1142
|
-
parts.push(` • ${s.name} (${s.kind}) → ${s.file}:${s.line}`);
|
|
1143
|
-
}
|
|
1144
|
-
}
|
|
1145
|
-
if (fileMatches.length > 0) {
|
|
1146
|
-
if (parts.length)
|
|
1147
|
-
parts.push('');
|
|
1148
|
-
parts.push(`**Files (${fileMatches.length}):**`);
|
|
1149
|
-
for (const f of fileMatches.slice(0, 5)) {
|
|
1150
|
-
parts.push(` • ${f.path} - ${f.reason}`);
|
|
1151
|
-
}
|
|
1152
|
-
}
|
|
1153
|
-
if (parts.length === 0) {
|
|
1154
|
-
result.answer = `No results found for "${query.keywords.join(' ')}". Try different terms.`;
|
|
1155
|
-
}
|
|
1156
|
-
else {
|
|
1157
|
-
result.answer = parts.join('\n');
|
|
1158
|
-
}
|
|
1159
|
-
}
|
|
1160
|
-
generateSuggestions(query, result) {
|
|
1161
|
-
result.suggestions = [];
|
|
1162
|
-
if (result.files.length > 0) {
|
|
1163
|
-
result.suggestions.push(`Explore: ${result.files[0]?.path}`);
|
|
1164
|
-
}
|
|
1165
|
-
if (query.type === 'find_file' && result.files.length === 0) {
|
|
1166
|
-
result.suggestions.push('Try broader search terms');
|
|
1167
|
-
result.suggestions.push('Check the architecture overview: "show architecture"');
|
|
1168
|
-
}
|
|
1169
|
-
if (query.type === 'find_symbol') {
|
|
1170
|
-
result.suggestions.push('Find usages: "where is X used"');
|
|
1171
|
-
}
|
|
1172
|
-
// Suggest related queries based on patterns
|
|
1173
|
-
const patterns = this.index.patterns;
|
|
1174
|
-
if (patterns.designPatterns.length > 0) {
|
|
1175
|
-
result.suggestions.push(`Explore pattern: ${patterns.designPatterns[0]}`);
|
|
1176
|
-
}
|
|
1177
|
-
}
|
|
1178
|
-
}
|
|
1179
|
-
export function createLocalExploreTool(workingDir, options) {
|
|
1180
|
-
const context = {
|
|
1181
|
-
aiEnhancer: options?.aiEnhancer,
|
|
1182
|
-
aiQueryParsing: options?.aiQueryParsing,
|
|
1183
|
-
aiSummarization: options?.aiSummarization,
|
|
1184
|
-
};
|
|
1185
|
-
const engine = new LocalExploreEngine(workingDir, context);
|
|
1186
|
-
let initialized = false;
|
|
1187
|
-
// Store reference for dynamic AI enhancer updates
|
|
1188
|
-
const toolState = { engine, context };
|
|
11
|
+
export async function buildCodebaseIndex(_rootDir) {
|
|
1189
12
|
return {
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
- "Explain this project"
|
|
1200
|
-
- "Where is handleSubmit used?"
|
|
1201
|
-
- "What are the entry points?"
|
|
1202
|
-
- "Show dependencies for src/app.ts"
|
|
1203
|
-
|
|
1204
|
-
Returns file locations, symbol definitions, and explanations.`,
|
|
1205
|
-
parameters: {
|
|
1206
|
-
type: 'object',
|
|
1207
|
-
properties: {
|
|
1208
|
-
query: {
|
|
1209
|
-
type: 'string',
|
|
1210
|
-
description: 'Natural language query about the codebase',
|
|
1211
|
-
},
|
|
1212
|
-
rebuild: {
|
|
1213
|
-
type: 'boolean',
|
|
1214
|
-
description: 'Force rebuild of the codebase index (default: false)',
|
|
1215
|
-
},
|
|
1216
|
-
useAI: {
|
|
1217
|
-
type: 'boolean',
|
|
1218
|
-
description: 'Use AI for enhanced results (default: true if AI is available)',
|
|
1219
|
-
},
|
|
1220
|
-
mode: {
|
|
1221
|
-
type: 'string',
|
|
1222
|
-
enum: ['concise', 'detailed'],
|
|
1223
|
-
description: 'Output mode. Concise trims long lists for context safety (default).',
|
|
1224
|
-
},
|
|
1225
|
-
},
|
|
1226
|
-
required: ['query'],
|
|
1227
|
-
additionalProperties: false,
|
|
13
|
+
version: 1,
|
|
14
|
+
createdAt: new Date().toISOString(),
|
|
15
|
+
rootDir: _rootDir,
|
|
16
|
+
hash: '',
|
|
17
|
+
files: [],
|
|
18
|
+
symbols: {
|
|
19
|
+
functions: new Map(),
|
|
20
|
+
classes: new Map(),
|
|
21
|
+
exports: new Map(),
|
|
1228
22
|
},
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
_engine: toolState,
|
|
1232
|
-
handler: async (args) => {
|
|
1233
|
-
try {
|
|
1234
|
-
const query = args['query'];
|
|
1235
|
-
const rebuild = args['rebuild'] === true;
|
|
1236
|
-
const useAI = args['useAI'] !== false; // Default to true - AI is used by default
|
|
1237
|
-
const mode = args['mode'] === 'detailed' ? 'detailed' : 'concise';
|
|
1238
|
-
if (!query || !query.trim()) {
|
|
1239
|
-
return 'Error: query must be a non-empty string';
|
|
1240
|
-
}
|
|
1241
|
-
// Initialize on first use
|
|
1242
|
-
if (!initialized || rebuild) {
|
|
1243
|
-
const { rebuilt, fileCount } = await toolState.engine.initialize(rebuild);
|
|
1244
|
-
initialized = true;
|
|
1245
|
-
if (rebuilt) {
|
|
1246
|
-
const exploreResult = await toolState.engine.explore(query, { useAI });
|
|
1247
|
-
return `Indexed ${fileCount} files. Now exploring: "${query}"\n\n${exploreResult.answer}`;
|
|
1248
|
-
}
|
|
1249
|
-
}
|
|
1250
|
-
// Handle special queries
|
|
1251
|
-
if (query.toLowerCase() === 'overview' || query.toLowerCase() === 'help') {
|
|
1252
|
-
return toolState.engine.getOverview();
|
|
1253
|
-
}
|
|
1254
|
-
// Execute exploration (AI is used by default when available)
|
|
1255
|
-
const result = await toolState.engine.explore(query, { useAI });
|
|
1256
|
-
// Check if AI was actually available and used
|
|
1257
|
-
const aiAvailable = resolveAIEnhancer(toolState.context) !== undefined;
|
|
1258
|
-
return formatExploreOutput(result, {
|
|
1259
|
-
query,
|
|
1260
|
-
mode,
|
|
1261
|
-
aiUsed: aiAvailable && useAI,
|
|
1262
|
-
});
|
|
1263
|
-
}
|
|
1264
|
-
catch (error) {
|
|
1265
|
-
return buildError('exploring codebase', error, { workingDir });
|
|
1266
|
-
}
|
|
1267
|
-
},
|
|
1268
|
-
};
|
|
1269
|
-
}
|
|
1270
|
-
/**
|
|
1271
|
-
* Create all local exploration tools (explore + index management).
|
|
1272
|
-
*/
|
|
1273
|
-
export function createLocalExploreTools(workingDir, options) {
|
|
1274
|
-
return [
|
|
1275
|
-
createLocalExploreTool(workingDir, options),
|
|
1276
|
-
createIndexTool(workingDir, options),
|
|
1277
|
-
];
|
|
1278
|
-
}
|
|
1279
|
-
function createIndexTool(workingDir, options) {
|
|
1280
|
-
const context = {
|
|
1281
|
-
aiEnhancer: options?.aiEnhancer,
|
|
23
|
+
imports: { nodes: [], edges: [] },
|
|
24
|
+
patterns: { frameworks: [], testFrameworks: [], buildTools: [] },
|
|
1282
25
|
};
|
|
1283
|
-
const engine = new LocalExploreEngine(workingDir, context);
|
|
1284
|
-
return {
|
|
1285
|
-
name: 'explore_index',
|
|
1286
|
-
description: 'Manage the codebase index for exploration. Use action "rebuild" to force re-index, "status" to check index state.',
|
|
1287
|
-
parameters: {
|
|
1288
|
-
type: 'object',
|
|
1289
|
-
properties: {
|
|
1290
|
-
action: {
|
|
1291
|
-
type: 'string',
|
|
1292
|
-
enum: ['rebuild', 'status'],
|
|
1293
|
-
description: 'Action to perform on the index',
|
|
1294
|
-
},
|
|
1295
|
-
},
|
|
1296
|
-
required: ['action'],
|
|
1297
|
-
additionalProperties: false,
|
|
1298
|
-
},
|
|
1299
|
-
cacheable: false,
|
|
1300
|
-
handler: async (args) => {
|
|
1301
|
-
try {
|
|
1302
|
-
const action = args['action'];
|
|
1303
|
-
if (action === 'rebuild') {
|
|
1304
|
-
const { fileCount } = await engine.initialize(true);
|
|
1305
|
-
return `✓ Rebuilt codebase index: ${fileCount} files analyzed`;
|
|
1306
|
-
}
|
|
1307
|
-
if (action === 'status') {
|
|
1308
|
-
const { rebuilt, fileCount } = await engine.initialize(false);
|
|
1309
|
-
return rebuilt
|
|
1310
|
-
? `Built new index: ${fileCount} files`
|
|
1311
|
-
: `Using cached index: ${fileCount} files`;
|
|
1312
|
-
}
|
|
1313
|
-
return 'Unknown action. Use "rebuild" or "status".';
|
|
1314
|
-
}
|
|
1315
|
-
catch (error) {
|
|
1316
|
-
return buildError('managing index', error, { workingDir });
|
|
1317
|
-
}
|
|
1318
|
-
},
|
|
1319
|
-
};
|
|
1320
|
-
}
|
|
1321
|
-
function formatExploreOutput(result, options) {
|
|
1322
|
-
const { query, mode, aiUsed } = options;
|
|
1323
|
-
const lines = [];
|
|
1324
|
-
if (mode === 'concise') {
|
|
1325
|
-
const answer = clampText(result.answer, 1200);
|
|
1326
|
-
lines.push(answer);
|
|
1327
|
-
const topFiles = result.files.slice(0, 4);
|
|
1328
|
-
const topSymbols = result.symbols.slice(0, 3);
|
|
1329
|
-
if (topFiles.length || topSymbols.length) {
|
|
1330
|
-
lines.push('');
|
|
1331
|
-
lines.push(`Files: ${result.files.length}${result.files.length > topFiles.length ? ` (showing ${topFiles.length})` : ''}`);
|
|
1332
|
-
for (const f of topFiles) {
|
|
1333
|
-
lines.push(`• ${f.path}${f.reason ? ` — ${f.reason}` : ''}`);
|
|
1334
|
-
}
|
|
1335
|
-
if (topSymbols.length) {
|
|
1336
|
-
lines.push('');
|
|
1337
|
-
lines.push(`Symbols: ${result.symbols.length}${result.symbols.length > topSymbols.length ? ` (showing ${topSymbols.length})` : ''}`);
|
|
1338
|
-
for (const s of topSymbols) {
|
|
1339
|
-
lines.push(`• ${s.name} (${s.kind}) → ${s.file}:${s.line}`);
|
|
1340
|
-
}
|
|
1341
|
-
}
|
|
1342
|
-
}
|
|
1343
|
-
}
|
|
1344
|
-
else {
|
|
1345
|
-
lines.push(result.answer);
|
|
1346
|
-
}
|
|
1347
|
-
if (result.suggestions.length > 0 && (mode === 'detailed' || result.files.length + result.symbols.length < 3)) {
|
|
1348
|
-
lines.push('');
|
|
1349
|
-
lines.push('**Suggestions:**');
|
|
1350
|
-
for (const s of result.suggestions.slice(0, 3)) {
|
|
1351
|
-
lines.push(`• ${s}`);
|
|
1352
|
-
}
|
|
1353
|
-
}
|
|
1354
|
-
lines.push('');
|
|
1355
|
-
lines.push(`_Query: "${query}" | Type: ${result.queryType} | Time: ${result.timeTaken}ms${aiUsed ? ' | AI' : ''}_`);
|
|
1356
|
-
return clampText(lines.join('\n'), mode === 'concise' ? 2200 : 3200);
|
|
1357
26
|
}
|
|
1358
|
-
function
|
|
1359
|
-
|
|
1360
|
-
return text;
|
|
1361
|
-
const slice = text.slice(0, Math.max(0, maxLength - 60));
|
|
1362
|
-
return `${slice}\n... (truncated for brevity)`;
|
|
27
|
+
export async function searchIndex(_index, _query) {
|
|
28
|
+
return [];
|
|
1363
29
|
}
|
|
1364
30
|
//# sourceMappingURL=localExplore.js.map
|