erosolar-cli 2.1.249 → 2.1.253
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/reliabilityPrompt.d.ts.map +1 -1
- package/dist/core/reliabilityPrompt.js +14 -0
- package/dist/core/reliabilityPrompt.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
package/dist/tools/learnTools.js
DELETED
|
@@ -1,2098 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Learn Tools - Codebase exploration and learning tools for understanding codebases.
|
|
3
|
-
*
|
|
4
|
-
* These tools enable deep codebase exploration without requiring external API calls
|
|
5
|
-
* for the core analysis. The AI can use these tools to build a comprehensive
|
|
6
|
-
* understanding of any codebase's architecture, patterns, and conventions.
|
|
7
|
-
*
|
|
8
|
-
* Features:
|
|
9
|
-
* - Codebase structure analysis
|
|
10
|
-
* - Pattern detection and learning
|
|
11
|
-
* - Architecture understanding
|
|
12
|
-
* - File relationship mapping
|
|
13
|
-
* - Topic-based exploration
|
|
14
|
-
*/
|
|
15
|
-
import { createHash } from 'node:crypto';
|
|
16
|
-
import { readFileSync, existsSync, readdirSync, statSync } from 'node:fs';
|
|
17
|
-
import { homedir } from 'node:os';
|
|
18
|
-
import { join, relative, extname, basename } from 'node:path';
|
|
19
|
-
import { buildError } from '../core/errors.js';
|
|
20
|
-
// =====================================================
|
|
21
|
-
// Constants
|
|
22
|
-
// =====================================================
|
|
23
|
-
const IGNORED_DIRS = new Set([
|
|
24
|
-
'node_modules',
|
|
25
|
-
'.git',
|
|
26
|
-
'.svn',
|
|
27
|
-
'.hg',
|
|
28
|
-
'dist',
|
|
29
|
-
'build',
|
|
30
|
-
'out',
|
|
31
|
-
'.next',
|
|
32
|
-
'.nuxt',
|
|
33
|
-
'.output',
|
|
34
|
-
'coverage',
|
|
35
|
-
'.nyc_output',
|
|
36
|
-
'.cache',
|
|
37
|
-
'.turbo',
|
|
38
|
-
'.vercel',
|
|
39
|
-
'.netlify',
|
|
40
|
-
'__pycache__',
|
|
41
|
-
'.pytest_cache',
|
|
42
|
-
'.mypy_cache',
|
|
43
|
-
'.ruff_cache',
|
|
44
|
-
'venv',
|
|
45
|
-
'.venv',
|
|
46
|
-
'env',
|
|
47
|
-
'.env',
|
|
48
|
-
'target',
|
|
49
|
-
'vendor',
|
|
50
|
-
'.idea',
|
|
51
|
-
'.vscode',
|
|
52
|
-
]);
|
|
53
|
-
const LANGUAGE_MAP = {
|
|
54
|
-
'.ts': 'TypeScript',
|
|
55
|
-
'.tsx': 'TypeScript React',
|
|
56
|
-
'.js': 'JavaScript',
|
|
57
|
-
'.jsx': 'JavaScript React',
|
|
58
|
-
'.mjs': 'JavaScript (ESM)',
|
|
59
|
-
'.cjs': 'JavaScript (CJS)',
|
|
60
|
-
'.py': 'Python',
|
|
61
|
-
'.pyw': 'Python',
|
|
62
|
-
'.pyi': 'Python Stub',
|
|
63
|
-
'.rs': 'Rust',
|
|
64
|
-
'.go': 'Go',
|
|
65
|
-
'.java': 'Java',
|
|
66
|
-
'.kt': 'Kotlin',
|
|
67
|
-
'.kts': 'Kotlin Script',
|
|
68
|
-
'.scala': 'Scala',
|
|
69
|
-
'.rb': 'Ruby',
|
|
70
|
-
'.php': 'PHP',
|
|
71
|
-
'.cs': 'C#',
|
|
72
|
-
'.fs': 'F#',
|
|
73
|
-
'.cpp': 'C++',
|
|
74
|
-
'.cc': 'C++',
|
|
75
|
-
'.cxx': 'C++',
|
|
76
|
-
'.c': 'C',
|
|
77
|
-
'.h': 'C/C++ Header',
|
|
78
|
-
'.hpp': 'C++ Header',
|
|
79
|
-
'.swift': 'Swift',
|
|
80
|
-
'.m': 'Objective-C',
|
|
81
|
-
'.mm': 'Objective-C++',
|
|
82
|
-
'.vue': 'Vue',
|
|
83
|
-
'.svelte': 'Svelte',
|
|
84
|
-
'.elm': 'Elm',
|
|
85
|
-
'.ex': 'Elixir',
|
|
86
|
-
'.exs': 'Elixir Script',
|
|
87
|
-
'.erl': 'Erlang',
|
|
88
|
-
'.hs': 'Haskell',
|
|
89
|
-
'.ml': 'OCaml',
|
|
90
|
-
'.mli': 'OCaml Interface',
|
|
91
|
-
'.lua': 'Lua',
|
|
92
|
-
'.pl': 'Perl',
|
|
93
|
-
'.pm': 'Perl Module',
|
|
94
|
-
'.sh': 'Shell',
|
|
95
|
-
'.bash': 'Bash',
|
|
96
|
-
'.zsh': 'Zsh',
|
|
97
|
-
'.fish': 'Fish',
|
|
98
|
-
'.ps1': 'PowerShell',
|
|
99
|
-
'.sql': 'SQL',
|
|
100
|
-
'.json': 'JSON',
|
|
101
|
-
'.yaml': 'YAML',
|
|
102
|
-
'.yml': 'YAML',
|
|
103
|
-
'.toml': 'TOML',
|
|
104
|
-
'.xml': 'XML',
|
|
105
|
-
'.md': 'Markdown',
|
|
106
|
-
'.mdx': 'MDX',
|
|
107
|
-
'.html': 'HTML',
|
|
108
|
-
'.htm': 'HTML',
|
|
109
|
-
'.css': 'CSS',
|
|
110
|
-
'.scss': 'SCSS',
|
|
111
|
-
'.sass': 'Sass',
|
|
112
|
-
'.less': 'Less',
|
|
113
|
-
'.styl': 'Stylus',
|
|
114
|
-
};
|
|
115
|
-
const CONFIG_FILES = {
|
|
116
|
-
'package.json': { type: 'npm', purpose: 'Node.js package configuration and dependencies' },
|
|
117
|
-
'tsconfig.json': { type: 'typescript', purpose: 'TypeScript compiler configuration' },
|
|
118
|
-
'pyproject.toml': { type: 'python', purpose: 'Python project configuration (PEP 517/518)' },
|
|
119
|
-
'setup.py': { type: 'python', purpose: 'Python package setup (legacy)' },
|
|
120
|
-
'requirements.txt': { type: 'python', purpose: 'Python dependencies' },
|
|
121
|
-
'Cargo.toml': { type: 'rust', purpose: 'Rust package manifest' },
|
|
122
|
-
'go.mod': { type: 'go', purpose: 'Go module definition' },
|
|
123
|
-
'pom.xml': { type: 'maven', purpose: 'Maven project configuration' },
|
|
124
|
-
'build.gradle': { type: 'gradle', purpose: 'Gradle build configuration' },
|
|
125
|
-
'build.gradle.kts': { type: 'gradle', purpose: 'Gradle Kotlin build configuration' },
|
|
126
|
-
'Gemfile': { type: 'ruby', purpose: 'Ruby dependencies (Bundler)' },
|
|
127
|
-
'composer.json': { type: 'php', purpose: 'PHP Composer dependencies' },
|
|
128
|
-
'.eslintrc.json': { type: 'linting', purpose: 'ESLint configuration' },
|
|
129
|
-
'.eslintrc.js': { type: 'linting', purpose: 'ESLint configuration' },
|
|
130
|
-
'.prettierrc': { type: 'formatting', purpose: 'Prettier configuration' },
|
|
131
|
-
'prettier.config.js': { type: 'formatting', purpose: 'Prettier configuration' },
|
|
132
|
-
'.gitignore': { type: 'git', purpose: 'Git ignore patterns' },
|
|
133
|
-
'.dockerignore': { type: 'docker', purpose: 'Docker ignore patterns' },
|
|
134
|
-
'Dockerfile': { type: 'docker', purpose: 'Docker image definition' },
|
|
135
|
-
'docker-compose.yml': { type: 'docker', purpose: 'Docker Compose services' },
|
|
136
|
-
'docker-compose.yaml': { type: 'docker', purpose: 'Docker Compose services' },
|
|
137
|
-
'Makefile': { type: 'build', purpose: 'Make build automation' },
|
|
138
|
-
'.env.example': { type: 'config', purpose: 'Environment variable template' },
|
|
139
|
-
'jest.config.js': { type: 'testing', purpose: 'Jest test configuration' },
|
|
140
|
-
'vitest.config.ts': { type: 'testing', purpose: 'Vitest test configuration' },
|
|
141
|
-
'webpack.config.js': { type: 'bundler', purpose: 'Webpack bundler configuration' },
|
|
142
|
-
'vite.config.ts': { type: 'bundler', purpose: 'Vite build tool configuration' },
|
|
143
|
-
'rollup.config.js': { type: 'bundler', purpose: 'Rollup bundler configuration' },
|
|
144
|
-
'next.config.js': { type: 'framework', purpose: 'Next.js configuration' },
|
|
145
|
-
'nuxt.config.ts': { type: 'framework', purpose: 'Nuxt.js configuration' },
|
|
146
|
-
'tailwind.config.js': { type: 'css', purpose: 'Tailwind CSS configuration' },
|
|
147
|
-
'.github/workflows': { type: 'ci', purpose: 'GitHub Actions workflows' },
|
|
148
|
-
'.gitlab-ci.yml': { type: 'ci', purpose: 'GitLab CI/CD configuration' },
|
|
149
|
-
'Jenkinsfile': { type: 'ci', purpose: 'Jenkins pipeline definition' },
|
|
150
|
-
};
|
|
151
|
-
const ARCHITECTURE_PATTERNS = [
|
|
152
|
-
{
|
|
153
|
-
name: 'MVC (Model-View-Controller)',
|
|
154
|
-
indicators: ['models', 'views', 'controllers', 'routes'],
|
|
155
|
-
type: 'architectural',
|
|
156
|
-
},
|
|
157
|
-
{
|
|
158
|
-
name: 'Clean Architecture',
|
|
159
|
-
indicators: ['domain', 'application', 'infrastructure', 'presentation', 'entities', 'use-cases', 'usecases'],
|
|
160
|
-
type: 'architectural',
|
|
161
|
-
},
|
|
162
|
-
{
|
|
163
|
-
name: 'Hexagonal Architecture',
|
|
164
|
-
indicators: ['ports', 'adapters', 'domain', 'application'],
|
|
165
|
-
type: 'architectural',
|
|
166
|
-
},
|
|
167
|
-
{
|
|
168
|
-
name: 'Feature-based Structure',
|
|
169
|
-
indicators: ['features', 'modules'],
|
|
170
|
-
type: 'structural',
|
|
171
|
-
},
|
|
172
|
-
{
|
|
173
|
-
name: 'Component-based',
|
|
174
|
-
indicators: ['components', 'shared', 'common'],
|
|
175
|
-
type: 'structural',
|
|
176
|
-
},
|
|
177
|
-
{
|
|
178
|
-
name: 'Layered Architecture',
|
|
179
|
-
indicators: ['api', 'services', 'repositories', 'data', 'business'],
|
|
180
|
-
type: 'architectural',
|
|
181
|
-
},
|
|
182
|
-
{
|
|
183
|
-
name: 'Microservices',
|
|
184
|
-
indicators: ['services', 'gateway', 'docker-compose'],
|
|
185
|
-
type: 'architectural',
|
|
186
|
-
},
|
|
187
|
-
{
|
|
188
|
-
name: 'Monorepo',
|
|
189
|
-
indicators: ['packages', 'apps', 'libs', 'workspace'],
|
|
190
|
-
type: 'structural',
|
|
191
|
-
},
|
|
192
|
-
{
|
|
193
|
-
name: 'Plugin Architecture',
|
|
194
|
-
indicators: ['plugins', 'extensions', 'addons'],
|
|
195
|
-
type: 'architectural',
|
|
196
|
-
},
|
|
197
|
-
{
|
|
198
|
-
name: 'Event-Driven',
|
|
199
|
-
indicators: ['events', 'handlers', 'listeners', 'subscribers', 'publishers'],
|
|
200
|
-
type: 'architectural',
|
|
201
|
-
},
|
|
202
|
-
];
|
|
203
|
-
// =====================================================
|
|
204
|
-
// Tool Creation
|
|
205
|
-
// =====================================================
|
|
206
|
-
export function createLearnTools(workingDir) {
|
|
207
|
-
return [
|
|
208
|
-
createLearnCodebaseTool(workingDir),
|
|
209
|
-
createLearnFileTool(workingDir),
|
|
210
|
-
createLearnTopicTool(workingDir),
|
|
211
|
-
createLearnSummaryTool(workingDir),
|
|
212
|
-
];
|
|
213
|
-
}
|
|
214
|
-
// =====================================================
|
|
215
|
-
// learn_codebase Tool
|
|
216
|
-
// =====================================================
|
|
217
|
-
function createLearnCodebaseTool(workingDir) {
|
|
218
|
-
return {
|
|
219
|
-
name: 'learn_codebase',
|
|
220
|
-
description: `Deprecated: use the explore tool for repo-wide or architectural deep dives.
|
|
221
|
-
This legacy deep dive remains available for compatibility; prefer explore (or explore_index) first. Detailed mode is opt-in and heavier.`,
|
|
222
|
-
parameters: {
|
|
223
|
-
type: 'object',
|
|
224
|
-
properties: {
|
|
225
|
-
depth: {
|
|
226
|
-
type: 'number',
|
|
227
|
-
description: 'Maximum directory depth to analyze (default: 5)',
|
|
228
|
-
},
|
|
229
|
-
includeHidden: {
|
|
230
|
-
type: 'boolean',
|
|
231
|
-
description: 'Include hidden files/directories in analysis (default: false)',
|
|
232
|
-
},
|
|
233
|
-
focusPath: {
|
|
234
|
-
type: 'string',
|
|
235
|
-
description: 'Focus analysis on a specific subdirectory',
|
|
236
|
-
},
|
|
237
|
-
mode: {
|
|
238
|
-
type: 'string',
|
|
239
|
-
enum: ['concise', 'detailed'],
|
|
240
|
-
description: 'Output mode: concise (default, context-safe) or detailed (full report)',
|
|
241
|
-
},
|
|
242
|
-
},
|
|
243
|
-
additionalProperties: false,
|
|
244
|
-
},
|
|
245
|
-
cacheable: true,
|
|
246
|
-
handler: async (args) => {
|
|
247
|
-
try {
|
|
248
|
-
const requestedDepth = typeof args['depth'] === 'number' ? args['depth'] : 5;
|
|
249
|
-
const includeHidden = args['includeHidden'] === true;
|
|
250
|
-
const focusPath = args['focusPath'];
|
|
251
|
-
const mode = args['mode'] === 'detailed' ? 'detailed' : 'concise';
|
|
252
|
-
const guardrails = createAnalysisGuardrails(requestedDepth, includeHidden, mode);
|
|
253
|
-
const deprecatedNote = '⚠️ Deprecated: prefer the explore tool for deep repo discovery. This legacy deep-learn flow remains for compatibility.';
|
|
254
|
-
const targetDir = focusPath ? resolveFilePath(workingDir, focusPath) : workingDir;
|
|
255
|
-
if (!existsSync(targetDir)) {
|
|
256
|
-
return `Error: Directory not found: ${targetDir}`;
|
|
257
|
-
}
|
|
258
|
-
const indexSnapshot = getRecentExploreIndexSnapshot(workingDir);
|
|
259
|
-
if (mode === 'concise' && !focusPath && indexSnapshot?.fresh) {
|
|
260
|
-
return `${deprecatedNote}\n\n${formatIndexPreflight(indexSnapshot)}`;
|
|
261
|
-
}
|
|
262
|
-
// Deep analysis with progressive output (concise by default to protect context)
|
|
263
|
-
const analysis = await analyzeCodebaseDeep(targetDir, workingDir, guardrails.maxDepth, guardrails.includeHidden, guardrails);
|
|
264
|
-
const body = mode === 'detailed'
|
|
265
|
-
? formatCodebaseAnalysis(analysis)
|
|
266
|
-
: formatConciseCodebaseAnalysis(analysis);
|
|
267
|
-
return `${deprecatedNote}\n\n${body}`;
|
|
268
|
-
}
|
|
269
|
-
catch (error) {
|
|
270
|
-
return buildError('analyzing codebase', error, { workingDir });
|
|
271
|
-
}
|
|
272
|
-
},
|
|
273
|
-
};
|
|
274
|
-
}
|
|
275
|
-
// =====================================================
|
|
276
|
-
// learn_file Tool
|
|
277
|
-
// =====================================================
|
|
278
|
-
function createLearnFileTool(workingDir) {
|
|
279
|
-
return {
|
|
280
|
-
name: 'learn_file',
|
|
281
|
-
description: `Deep-learn a specific file's purpose, structure, patterns, and relationships.
|
|
282
|
-
This tool provides detailed analysis of a single file including:
|
|
283
|
-
- File purpose and responsibilities
|
|
284
|
-
- Imports and dependencies
|
|
285
|
-
- Exports and public interface
|
|
286
|
-
- Functions and classes with their purposes
|
|
287
|
-
- Complexity metrics
|
|
288
|
-
- Relationships to other files`,
|
|
289
|
-
parameters: {
|
|
290
|
-
type: 'object',
|
|
291
|
-
properties: {
|
|
292
|
-
path: {
|
|
293
|
-
type: 'string',
|
|
294
|
-
description: 'Path to the file to analyze',
|
|
295
|
-
},
|
|
296
|
-
includeRelationships: {
|
|
297
|
-
type: 'boolean',
|
|
298
|
-
description: 'Analyze relationships to other files (default: true)',
|
|
299
|
-
},
|
|
300
|
-
},
|
|
301
|
-
required: ['path'],
|
|
302
|
-
additionalProperties: false,
|
|
303
|
-
},
|
|
304
|
-
cacheable: true,
|
|
305
|
-
handler: async (args) => {
|
|
306
|
-
try {
|
|
307
|
-
const filePath = resolveFilePath(workingDir, args['path']);
|
|
308
|
-
const includeRelationships = args['includeRelationships'] !== false;
|
|
309
|
-
if (!existsSync(filePath)) {
|
|
310
|
-
return `Error: File not found: ${filePath}`;
|
|
311
|
-
}
|
|
312
|
-
const stat = statSync(filePath);
|
|
313
|
-
if (stat.isDirectory()) {
|
|
314
|
-
return `Error: Path is a directory, not a file: ${filePath}`;
|
|
315
|
-
}
|
|
316
|
-
const analysis = analyzeFile(filePath, workingDir, includeRelationships);
|
|
317
|
-
return formatFileAnalysis(analysis);
|
|
318
|
-
}
|
|
319
|
-
catch (error) {
|
|
320
|
-
return buildError('analyzing file', error, { path: String(args['path']) });
|
|
321
|
-
}
|
|
322
|
-
},
|
|
323
|
-
};
|
|
324
|
-
}
|
|
325
|
-
// =====================================================
|
|
326
|
-
// learn_topic Tool
|
|
327
|
-
// =====================================================
|
|
328
|
-
function createLearnTopicTool(workingDir) {
|
|
329
|
-
return {
|
|
330
|
-
name: 'learn_topic',
|
|
331
|
-
description: `Learn about a specific topic, pattern, or concept within the codebase.
|
|
332
|
-
Use this to understand how specific patterns are implemented, such as:
|
|
333
|
-
- Authentication/authorization patterns
|
|
334
|
-
- Error handling conventions
|
|
335
|
-
- Data validation approaches
|
|
336
|
-
- API design patterns
|
|
337
|
-
- State management
|
|
338
|
-
- Testing patterns
|
|
339
|
-
- Any custom pattern or convention`,
|
|
340
|
-
parameters: {
|
|
341
|
-
type: 'object',
|
|
342
|
-
properties: {
|
|
343
|
-
topic: {
|
|
344
|
-
type: 'string',
|
|
345
|
-
description: 'The topic or pattern to learn about (e.g., "authentication", "error handling", "api routes")',
|
|
346
|
-
},
|
|
347
|
-
maxFiles: {
|
|
348
|
-
type: 'number',
|
|
349
|
-
description: 'Maximum number of relevant files to analyze (default: 10)',
|
|
350
|
-
},
|
|
351
|
-
maxExamples: {
|
|
352
|
-
type: 'number',
|
|
353
|
-
description: 'Maximum number of code examples to include (default: 5)',
|
|
354
|
-
},
|
|
355
|
-
},
|
|
356
|
-
required: ['topic'],
|
|
357
|
-
additionalProperties: false,
|
|
358
|
-
},
|
|
359
|
-
cacheable: true,
|
|
360
|
-
handler: async (args) => {
|
|
361
|
-
try {
|
|
362
|
-
const topic = args['topic'];
|
|
363
|
-
const maxFiles = typeof args['maxFiles'] === 'number' ? args['maxFiles'] : 10;
|
|
364
|
-
const maxExamples = typeof args['maxExamples'] === 'number' ? args['maxExamples'] : 5;
|
|
365
|
-
if (!topic || !topic.trim()) {
|
|
366
|
-
return 'Error: topic must be a non-empty string';
|
|
367
|
-
}
|
|
368
|
-
const analysis = analyzeTopic(workingDir, topic.trim(), maxFiles, maxExamples);
|
|
369
|
-
return formatTopicAnalysis(analysis);
|
|
370
|
-
}
|
|
371
|
-
catch (error) {
|
|
372
|
-
return buildError('analyzing topic', error, { topic: String(args['topic']) });
|
|
373
|
-
}
|
|
374
|
-
},
|
|
375
|
-
};
|
|
376
|
-
}
|
|
377
|
-
// =====================================================
|
|
378
|
-
// learn_summary Tool
|
|
379
|
-
// =====================================================
|
|
380
|
-
function createLearnSummaryTool(workingDir) {
|
|
381
|
-
return {
|
|
382
|
-
name: 'learn_summary',
|
|
383
|
-
description: `Generate a learning summary for the codebase suitable for onboarding.
|
|
384
|
-
This creates a comprehensive summary including:
|
|
385
|
-
- Quick start guide
|
|
386
|
-
- Key concepts and terminology
|
|
387
|
-
- Architecture overview
|
|
388
|
-
- Important files and their purposes
|
|
389
|
-
- Common patterns and conventions
|
|
390
|
-
- Development workflow suggestions`,
|
|
391
|
-
parameters: {
|
|
392
|
-
type: 'object',
|
|
393
|
-
properties: {
|
|
394
|
-
format: {
|
|
395
|
-
type: 'string',
|
|
396
|
-
description: 'Output format: "markdown" (default) or "text"',
|
|
397
|
-
enum: ['markdown', 'text'],
|
|
398
|
-
},
|
|
399
|
-
focus: {
|
|
400
|
-
type: 'string',
|
|
401
|
-
description: 'Focus area for the summary (e.g., "frontend", "backend", "api")',
|
|
402
|
-
},
|
|
403
|
-
},
|
|
404
|
-
additionalProperties: false,
|
|
405
|
-
},
|
|
406
|
-
cacheable: true,
|
|
407
|
-
handler: async (args) => {
|
|
408
|
-
try {
|
|
409
|
-
const format = args['format'] || 'markdown';
|
|
410
|
-
const focus = args['focus'];
|
|
411
|
-
const analysis = analyzeCodebase(workingDir, workingDir, 4, false);
|
|
412
|
-
return formatLearningSummary(analysis, format, focus);
|
|
413
|
-
}
|
|
414
|
-
catch (error) {
|
|
415
|
-
return buildError('generating learning summary', error, { workingDir });
|
|
416
|
-
}
|
|
417
|
-
},
|
|
418
|
-
};
|
|
419
|
-
}
|
|
420
|
-
// =====================================================
|
|
421
|
-
// Analysis Functions
|
|
422
|
-
// =====================================================
|
|
423
|
-
/**
|
|
424
|
-
* Deep codebase analysis with thorough exploration.
|
|
425
|
-
* Does actual file content analysis for better insights.
|
|
426
|
-
*/
|
|
427
|
-
async function analyzeCodebaseDeep(targetDir, workingDir, maxDepth, includeHidden, guardrails) {
|
|
428
|
-
const files = [];
|
|
429
|
-
const directories = [];
|
|
430
|
-
const configFiles = [];
|
|
431
|
-
const limits = guardrails ?? createAnalysisGuardrails(maxDepth, includeHidden, 'detailed');
|
|
432
|
-
// Phase 1: Directory structure traversal
|
|
433
|
-
const structure = buildDirectoryTree(targetDir, workingDir, 0, limits.maxDepth, limits.includeHidden, files, directories, configFiles, limits);
|
|
434
|
-
// Phase 2: File type detection and language breakdown
|
|
435
|
-
const languageCounts = new Map();
|
|
436
|
-
for (const file of files) {
|
|
437
|
-
const lang = LANGUAGE_MAP[file.ext] || 'Other';
|
|
438
|
-
const existing = languageCounts.get(lang) || { ext: file.ext, count: 0 };
|
|
439
|
-
existing.count++;
|
|
440
|
-
languageCounts.set(lang, existing);
|
|
441
|
-
}
|
|
442
|
-
const totalFiles = files.length;
|
|
443
|
-
const languages = Array.from(languageCounts.entries())
|
|
444
|
-
.map(([language, data]) => ({
|
|
445
|
-
language,
|
|
446
|
-
extension: data.ext,
|
|
447
|
-
fileCount: data.count,
|
|
448
|
-
percentage: totalFiles > 0 ? (data.count / totalFiles) * 100 : 0,
|
|
449
|
-
}))
|
|
450
|
-
.sort((a, b) => b.fileCount - a.fileCount);
|
|
451
|
-
// Phase 3: Architecture pattern detection
|
|
452
|
-
const dirNames = directories.map((d) => basename(d).toLowerCase());
|
|
453
|
-
const patterns = detectPatterns(dirNames, files.map((f) => f.path));
|
|
454
|
-
// Phase 4: Configuration file analysis with deep inspection
|
|
455
|
-
const configDetails = analyzeConfigFilesDeep(configFiles, targetDir);
|
|
456
|
-
// Phase 5: Dependency analysis
|
|
457
|
-
const dependencies = analyzeDependencies(targetDir);
|
|
458
|
-
// Phase 6: Entry point identification
|
|
459
|
-
const entryPoints = findEntryPoints(files.map((f) => f.path), configFiles);
|
|
460
|
-
// Phase 7: Component and layer mapping
|
|
461
|
-
const architecture = buildArchitectureInsights(patterns, dirNames, targetDir, workingDir);
|
|
462
|
-
// Phase 8: Deep source file analysis for patterns and complexity
|
|
463
|
-
const keyFiles = files
|
|
464
|
-
.filter(f => LANGUAGE_MAP[f.ext] && f.size < 100000)
|
|
465
|
-
.slice(0, 50);
|
|
466
|
-
const codePatterns = new Map();
|
|
467
|
-
for (const file of keyFiles) {
|
|
468
|
-
try {
|
|
469
|
-
const fullPath = join(workingDir, file.path);
|
|
470
|
-
const content = readFileSync(fullPath, 'utf-8');
|
|
471
|
-
const filePatterns = detectCodePatterns(content, file.ext);
|
|
472
|
-
// Accumulate pattern counts
|
|
473
|
-
for (const pattern of filePatterns) {
|
|
474
|
-
codePatterns.set(pattern, (codePatterns.get(pattern) || 0) + 1);
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
catch {
|
|
478
|
-
// Skip unreadable files
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
// Add detected code patterns to the patterns list
|
|
482
|
-
for (const [patternName, count] of codePatterns.entries()) {
|
|
483
|
-
if (count >= 3) { // Only include patterns found in multiple files
|
|
484
|
-
patterns.push({
|
|
485
|
-
name: patternName,
|
|
486
|
-
type: 'design',
|
|
487
|
-
description: `Found ${patternName} pattern in ${count} files`,
|
|
488
|
-
evidence: [`Detected in ${count} source files`],
|
|
489
|
-
confidence: count >= 10 ? 'high' : count >= 5 ? 'medium' : 'low',
|
|
490
|
-
});
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
return {
|
|
494
|
-
rootDir: relative(workingDir, targetDir) || '.',
|
|
495
|
-
totalFiles,
|
|
496
|
-
totalDirectories: directories.length,
|
|
497
|
-
languages,
|
|
498
|
-
structure,
|
|
499
|
-
patterns,
|
|
500
|
-
architecture,
|
|
501
|
-
entryPoints,
|
|
502
|
-
configFiles: configDetails,
|
|
503
|
-
dependencies,
|
|
504
|
-
guardrails: limits,
|
|
505
|
-
};
|
|
506
|
-
}
|
|
507
|
-
function analyzeConfigFilesDeep(configs, targetDir) {
|
|
508
|
-
// Enhance config info with actual content analysis where useful
|
|
509
|
-
return configs.map(config => {
|
|
510
|
-
try {
|
|
511
|
-
const fullPath = join(targetDir, config.path);
|
|
512
|
-
if (config.name === 'package.json' && existsSync(fullPath)) {
|
|
513
|
-
const content = JSON.parse(readFileSync(fullPath, 'utf-8'));
|
|
514
|
-
const scripts = Object.keys(content.scripts || {}).slice(0, 5);
|
|
515
|
-
if (scripts.length > 0) {
|
|
516
|
-
return {
|
|
517
|
-
...config,
|
|
518
|
-
purpose: `${config.purpose} (scripts: ${scripts.join(', ')})`,
|
|
519
|
-
};
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
catch {
|
|
524
|
-
// Keep original
|
|
525
|
-
}
|
|
526
|
-
return config;
|
|
527
|
-
});
|
|
528
|
-
}
|
|
529
|
-
function analyzeCodebase(targetDir, workingDir, maxDepth, includeHidden, guardrails) {
|
|
530
|
-
const files = [];
|
|
531
|
-
const directories = [];
|
|
532
|
-
const configFiles = [];
|
|
533
|
-
const limits = guardrails ?? createAnalysisGuardrails(maxDepth, includeHidden, 'concise');
|
|
534
|
-
// Build directory tree and collect files
|
|
535
|
-
const structure = buildDirectoryTree(targetDir, workingDir, 0, limits.maxDepth, limits.includeHidden, files, directories, configFiles, limits);
|
|
536
|
-
// Calculate language breakdown
|
|
537
|
-
const languageCounts = new Map();
|
|
538
|
-
for (const file of files) {
|
|
539
|
-
const lang = LANGUAGE_MAP[file.ext] || 'Other';
|
|
540
|
-
const existing = languageCounts.get(lang) || { ext: file.ext, count: 0 };
|
|
541
|
-
existing.count++;
|
|
542
|
-
languageCounts.set(lang, existing);
|
|
543
|
-
}
|
|
544
|
-
const totalFiles = files.length;
|
|
545
|
-
const languages = Array.from(languageCounts.entries())
|
|
546
|
-
.map(([language, data]) => ({
|
|
547
|
-
language,
|
|
548
|
-
extension: data.ext,
|
|
549
|
-
fileCount: data.count,
|
|
550
|
-
percentage: totalFiles > 0 ? (data.count / totalFiles) * 100 : 0,
|
|
551
|
-
}))
|
|
552
|
-
.sort((a, b) => b.fileCount - a.fileCount);
|
|
553
|
-
// Detect architecture patterns
|
|
554
|
-
const dirNames = directories.map((d) => basename(d).toLowerCase());
|
|
555
|
-
const patterns = detectPatterns(dirNames, files.map((f) => f.path));
|
|
556
|
-
// Build architecture insights
|
|
557
|
-
const architecture = buildArchitectureInsights(patterns, dirNames, targetDir, workingDir);
|
|
558
|
-
// Find entry points
|
|
559
|
-
const entryPoints = findEntryPoints(files.map((f) => f.path), configFiles);
|
|
560
|
-
// Analyze dependencies
|
|
561
|
-
const dependencies = analyzeDependencies(targetDir);
|
|
562
|
-
return {
|
|
563
|
-
rootDir: relative(workingDir, targetDir) || '.',
|
|
564
|
-
totalFiles,
|
|
565
|
-
totalDirectories: directories.length,
|
|
566
|
-
languages,
|
|
567
|
-
structure,
|
|
568
|
-
patterns,
|
|
569
|
-
architecture,
|
|
570
|
-
entryPoints,
|
|
571
|
-
configFiles,
|
|
572
|
-
dependencies,
|
|
573
|
-
guardrails: limits,
|
|
574
|
-
};
|
|
575
|
-
}
|
|
576
|
-
function buildDirectoryTree(dir, workingDir, depth, maxDepth, includeHidden, files, directories, configFiles, guardrails) {
|
|
577
|
-
const name = basename(dir) || dir;
|
|
578
|
-
const relPath = relative(workingDir, dir) || '.';
|
|
579
|
-
const node = {
|
|
580
|
-
name,
|
|
581
|
-
path: relPath,
|
|
582
|
-
type: 'directory',
|
|
583
|
-
children: [],
|
|
584
|
-
};
|
|
585
|
-
if (depth >= maxDepth) {
|
|
586
|
-
return node;
|
|
587
|
-
}
|
|
588
|
-
try {
|
|
589
|
-
const entries = readdirSync(dir, { withFileTypes: true });
|
|
590
|
-
for (const entry of entries) {
|
|
591
|
-
if (guardrails.truncated) {
|
|
592
|
-
break;
|
|
593
|
-
}
|
|
594
|
-
// Skip hidden files/dirs if not requested
|
|
595
|
-
if (!includeHidden && entry.name.startsWith('.')) {
|
|
596
|
-
continue;
|
|
597
|
-
}
|
|
598
|
-
// Skip ignored directories
|
|
599
|
-
if (IGNORED_DIRS.has(entry.name)) {
|
|
600
|
-
continue;
|
|
601
|
-
}
|
|
602
|
-
const fullPath = join(dir, entry.name);
|
|
603
|
-
const entryRelPath = relative(workingDir, fullPath);
|
|
604
|
-
if (entry.isDirectory()) {
|
|
605
|
-
if (!consumeGuardrailSlot(guardrails, 'node_limit'))
|
|
606
|
-
break;
|
|
607
|
-
directories.push(fullPath);
|
|
608
|
-
const childNode = buildDirectoryTree(fullPath, workingDir, depth + 1, maxDepth, includeHidden, files, directories, configFiles, guardrails);
|
|
609
|
-
node.children.push(childNode);
|
|
610
|
-
}
|
|
611
|
-
else if (entry.isFile()) {
|
|
612
|
-
if (!consumeGuardrailSlot(guardrails, 'node_limit'))
|
|
613
|
-
break;
|
|
614
|
-
try {
|
|
615
|
-
const stat = statSync(fullPath);
|
|
616
|
-
const ext = extname(entry.name).toLowerCase();
|
|
617
|
-
const language = LANGUAGE_MAP[ext];
|
|
618
|
-
files.push({ path: entryRelPath, ext, size: stat.size });
|
|
619
|
-
// Check if it's a config file
|
|
620
|
-
const configInfo = CONFIG_FILES[entry.name];
|
|
621
|
-
if (configInfo) {
|
|
622
|
-
configFiles.push({
|
|
623
|
-
name: entry.name,
|
|
624
|
-
path: entryRelPath,
|
|
625
|
-
type: configInfo.type,
|
|
626
|
-
purpose: configInfo.purpose,
|
|
627
|
-
});
|
|
628
|
-
}
|
|
629
|
-
node.children.push({
|
|
630
|
-
name: entry.name,
|
|
631
|
-
path: entryRelPath,
|
|
632
|
-
type: 'file',
|
|
633
|
-
size: stat.size,
|
|
634
|
-
language,
|
|
635
|
-
});
|
|
636
|
-
}
|
|
637
|
-
catch {
|
|
638
|
-
// Skip files we can't stat
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
}
|
|
642
|
-
}
|
|
643
|
-
catch {
|
|
644
|
-
// Skip directories we can't read
|
|
645
|
-
}
|
|
646
|
-
return node;
|
|
647
|
-
}
|
|
648
|
-
function consumeGuardrailSlot(guardrails, reason) {
|
|
649
|
-
if (guardrails.nodeCount >= guardrails.nodeLimit) {
|
|
650
|
-
guardrails.truncated = true;
|
|
651
|
-
guardrails.truncatedReason = guardrails.truncatedReason ?? reason;
|
|
652
|
-
return false;
|
|
653
|
-
}
|
|
654
|
-
guardrails.nodeCount += 1;
|
|
655
|
-
return true;
|
|
656
|
-
}
|
|
657
|
-
function detectPatterns(dirNames, filePaths) {
|
|
658
|
-
const patterns = [];
|
|
659
|
-
const dirNameSet = new Set(dirNames);
|
|
660
|
-
const filePathsLower = filePaths.map((p) => p.toLowerCase());
|
|
661
|
-
for (const pattern of ARCHITECTURE_PATTERNS) {
|
|
662
|
-
const matches = pattern.indicators.filter((ind) => dirNameSet.has(ind));
|
|
663
|
-
if (matches.length >= 2 || (matches.length >= 1 && pattern.indicators.length <= 2)) {
|
|
664
|
-
const confidence = matches.length >= 3 ? 'high' : matches.length >= 2 ? 'medium' : 'low';
|
|
665
|
-
patterns.push({
|
|
666
|
-
name: pattern.name,
|
|
667
|
-
type: pattern.type,
|
|
668
|
-
description: `Detected ${pattern.name} pattern based on directory structure`,
|
|
669
|
-
evidence: matches.map((m) => `Found "${m}" directory`),
|
|
670
|
-
confidence,
|
|
671
|
-
});
|
|
672
|
-
}
|
|
673
|
-
}
|
|
674
|
-
// Detect naming conventions
|
|
675
|
-
const hasKebabCase = filePathsLower.some((p) => /[a-z]+-[a-z]+/.test(basename(p)));
|
|
676
|
-
const hasCamelCase = filePaths.some((p) => /[a-z]+[A-Z][a-z]+/.test(basename(p)));
|
|
677
|
-
const hasPascalCase = filePaths.some((p) => /^[A-Z][a-z]+[A-Z]/.test(basename(p)));
|
|
678
|
-
const hasSnakeCase = filePathsLower.some((p) => /[a-z]+_[a-z]+/.test(basename(p)));
|
|
679
|
-
const namingConventions = [];
|
|
680
|
-
if (hasKebabCase)
|
|
681
|
-
namingConventions.push('kebab-case');
|
|
682
|
-
if (hasCamelCase)
|
|
683
|
-
namingConventions.push('camelCase');
|
|
684
|
-
if (hasPascalCase)
|
|
685
|
-
namingConventions.push('PascalCase');
|
|
686
|
-
if (hasSnakeCase)
|
|
687
|
-
namingConventions.push('snake_case');
|
|
688
|
-
if (namingConventions.length > 0) {
|
|
689
|
-
patterns.push({
|
|
690
|
-
name: 'File Naming Convention',
|
|
691
|
-
type: 'naming',
|
|
692
|
-
description: `Uses ${namingConventions.join(', ')} naming convention(s)`,
|
|
693
|
-
evidence: namingConventions.map((n) => `Detected ${n} pattern in filenames`),
|
|
694
|
-
confidence: 'medium',
|
|
695
|
-
});
|
|
696
|
-
}
|
|
697
|
-
// Detect test patterns
|
|
698
|
-
const hasTestDir = dirNameSet.has('test') || dirNameSet.has('tests') || dirNameSet.has('__tests__');
|
|
699
|
-
const hasSpecFiles = filePathsLower.some((p) => p.includes('.spec.') || p.includes('.test.'));
|
|
700
|
-
if (hasTestDir || hasSpecFiles) {
|
|
701
|
-
patterns.push({
|
|
702
|
-
name: 'Testing Structure',
|
|
703
|
-
type: 'structural',
|
|
704
|
-
description: hasTestDir
|
|
705
|
-
? 'Uses dedicated test directory'
|
|
706
|
-
: 'Uses co-located test files (.spec/.test)',
|
|
707
|
-
evidence: hasTestDir
|
|
708
|
-
? ['Found test/tests/__tests__ directory']
|
|
709
|
-
: ['Found .spec or .test files alongside source'],
|
|
710
|
-
confidence: 'high',
|
|
711
|
-
});
|
|
712
|
-
}
|
|
713
|
-
return patterns;
|
|
714
|
-
}
|
|
715
|
-
function buildArchitectureInsights(patterns, dirNames, targetDir, workingDir) {
|
|
716
|
-
const archPattern = patterns.find((p) => p.type === 'architectural');
|
|
717
|
-
const type = archPattern?.name || 'Custom/Unknown';
|
|
718
|
-
const layers = [];
|
|
719
|
-
const components = [];
|
|
720
|
-
// Identify layers based on common directory names
|
|
721
|
-
const layerDirs = ['api', 'routes', 'controllers', 'services', 'models', 'views', 'components', 'utils', 'lib', 'core'];
|
|
722
|
-
for (const layer of layerDirs) {
|
|
723
|
-
if (dirNames.includes(layer)) {
|
|
724
|
-
layers.push(layer);
|
|
725
|
-
}
|
|
726
|
-
}
|
|
727
|
-
// Build component info from top-level directories
|
|
728
|
-
try {
|
|
729
|
-
const entries = readdirSync(targetDir, { withFileTypes: true });
|
|
730
|
-
for (const entry of entries) {
|
|
731
|
-
if (entry.isDirectory() && !IGNORED_DIRS.has(entry.name) && !entry.name.startsWith('.')) {
|
|
732
|
-
const componentPath = relative(workingDir, join(targetDir, entry.name));
|
|
733
|
-
components.push({
|
|
734
|
-
name: entry.name,
|
|
735
|
-
type: inferComponentType(entry.name),
|
|
736
|
-
path: componentPath,
|
|
737
|
-
responsibilities: inferResponsibilities(entry.name),
|
|
738
|
-
});
|
|
739
|
-
}
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
catch {
|
|
743
|
-
// Ignore errors
|
|
744
|
-
}
|
|
745
|
-
const dataFlow = inferDataFlow(layers, type);
|
|
746
|
-
return {
|
|
747
|
-
type,
|
|
748
|
-
layers,
|
|
749
|
-
components,
|
|
750
|
-
dataFlow,
|
|
751
|
-
};
|
|
752
|
-
}
|
|
753
|
-
function inferComponentType(name) {
|
|
754
|
-
const lower = name.toLowerCase();
|
|
755
|
-
if (['api', 'routes', 'controllers', 'handlers'].includes(lower))
|
|
756
|
-
return 'API Layer';
|
|
757
|
-
if (['services', 'business', 'domain'].includes(lower))
|
|
758
|
-
return 'Business Logic';
|
|
759
|
-
if (['models', 'entities', 'schemas'].includes(lower))
|
|
760
|
-
return 'Data Models';
|
|
761
|
-
if (['views', 'pages', 'screens'].includes(lower))
|
|
762
|
-
return 'Presentation';
|
|
763
|
-
if (['components', 'ui'].includes(lower))
|
|
764
|
-
return 'UI Components';
|
|
765
|
-
if (['utils', 'helpers', 'lib', 'common', 'shared'].includes(lower))
|
|
766
|
-
return 'Utilities';
|
|
767
|
-
if (['config', 'configs', 'settings'].includes(lower))
|
|
768
|
-
return 'Configuration';
|
|
769
|
-
if (['test', 'tests', '__tests__', 'spec'].includes(lower))
|
|
770
|
-
return 'Testing';
|
|
771
|
-
if (['types', 'interfaces', 'contracts'].includes(lower))
|
|
772
|
-
return 'Type Definitions';
|
|
773
|
-
if (['middleware', 'middlewares'].includes(lower))
|
|
774
|
-
return 'Middleware';
|
|
775
|
-
if (['plugins', 'extensions', 'addons'].includes(lower))
|
|
776
|
-
return 'Extensions';
|
|
777
|
-
return 'Module';
|
|
778
|
-
}
|
|
779
|
-
function inferResponsibilities(name) {
|
|
780
|
-
const lower = name.toLowerCase();
|
|
781
|
-
const responsibilities = [];
|
|
782
|
-
if (['api', 'routes'].includes(lower)) {
|
|
783
|
-
responsibilities.push('HTTP request handling', 'Route definitions', 'Request/response processing');
|
|
784
|
-
}
|
|
785
|
-
else if (lower === 'controllers') {
|
|
786
|
-
responsibilities.push('Request handling', 'Input validation', 'Response formatting');
|
|
787
|
-
}
|
|
788
|
-
else if (lower === 'services') {
|
|
789
|
-
responsibilities.push('Business logic', 'Data orchestration', 'External integrations');
|
|
790
|
-
}
|
|
791
|
-
else if (lower === 'models') {
|
|
792
|
-
responsibilities.push('Data structures', 'Database schemas', 'Data validation');
|
|
793
|
-
}
|
|
794
|
-
else if (['views', 'pages'].includes(lower)) {
|
|
795
|
-
responsibilities.push('UI rendering', 'Page composition', 'Layout management');
|
|
796
|
-
}
|
|
797
|
-
else if (lower === 'components') {
|
|
798
|
-
responsibilities.push('Reusable UI elements', 'Component logic', 'State management');
|
|
799
|
-
}
|
|
800
|
-
else if (['utils', 'helpers'].includes(lower)) {
|
|
801
|
-
responsibilities.push('Utility functions', 'Common helpers', 'Shared logic');
|
|
802
|
-
}
|
|
803
|
-
return responsibilities.length > 0 ? responsibilities : ['Module functionality'];
|
|
804
|
-
}
|
|
805
|
-
function inferDataFlow(layers, archType) {
|
|
806
|
-
if (archType.includes('MVC')) {
|
|
807
|
-
return ['Request → Controller → Model → View → Response'];
|
|
808
|
-
}
|
|
809
|
-
if (archType.includes('Clean')) {
|
|
810
|
-
return [
|
|
811
|
-
'External → Controllers → Use Cases → Entities',
|
|
812
|
-
'Entities → Use Cases → Presenters → External',
|
|
813
|
-
];
|
|
814
|
-
}
|
|
815
|
-
if (archType.includes('Layered')) {
|
|
816
|
-
return ['API → Services → Repositories → Database'];
|
|
817
|
-
}
|
|
818
|
-
if (layers.length > 0) {
|
|
819
|
-
return [`Request → ${layers.join(' → ')} → Response`];
|
|
820
|
-
}
|
|
821
|
-
return ['Standard request/response flow'];
|
|
822
|
-
}
|
|
823
|
-
function findEntryPoints(filePaths, configFiles) {
|
|
824
|
-
const entryPoints = [];
|
|
825
|
-
// Check for common entry point patterns
|
|
826
|
-
const entryPatterns = [
|
|
827
|
-
'index.ts',
|
|
828
|
-
'index.js',
|
|
829
|
-
'main.ts',
|
|
830
|
-
'main.js',
|
|
831
|
-
'app.ts',
|
|
832
|
-
'app.js',
|
|
833
|
-
'server.ts',
|
|
834
|
-
'server.js',
|
|
835
|
-
'cli.ts',
|
|
836
|
-
'cli.js',
|
|
837
|
-
'__main__.py',
|
|
838
|
-
'main.py',
|
|
839
|
-
'app.py',
|
|
840
|
-
'manage.py',
|
|
841
|
-
'main.go',
|
|
842
|
-
'main.rs',
|
|
843
|
-
'lib.rs',
|
|
844
|
-
];
|
|
845
|
-
for (const pattern of entryPatterns) {
|
|
846
|
-
const match = filePaths.find((p) => basename(p) === pattern || p.endsWith(`/src/${pattern}`) || p.endsWith(`/bin/${pattern}`));
|
|
847
|
-
if (match) {
|
|
848
|
-
entryPoints.push(match);
|
|
849
|
-
}
|
|
850
|
-
}
|
|
851
|
-
// Check package.json for main/bin
|
|
852
|
-
const pkgJson = configFiles.find((c) => c.name === 'package.json');
|
|
853
|
-
if (pkgJson) {
|
|
854
|
-
entryPoints.push(`${pkgJson.path} (see "main" or "bin" fields)`);
|
|
855
|
-
}
|
|
856
|
-
return [...new Set(entryPoints)];
|
|
857
|
-
}
|
|
858
|
-
function analyzeDependencies(dir) {
|
|
859
|
-
const result = {
|
|
860
|
-
dependencies: [],
|
|
861
|
-
devDependencies: [],
|
|
862
|
-
hasDependencyFile: false,
|
|
863
|
-
};
|
|
864
|
-
// Check package.json
|
|
865
|
-
const pkgPath = join(dir, 'package.json');
|
|
866
|
-
if (existsSync(pkgPath)) {
|
|
867
|
-
try {
|
|
868
|
-
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
869
|
-
result.packageManager = 'npm';
|
|
870
|
-
result.hasDependencyFile = true;
|
|
871
|
-
result.dependencies = Object.keys(pkg.dependencies || {}).slice(0, 20);
|
|
872
|
-
result.devDependencies = Object.keys(pkg.devDependencies || {}).slice(0, 20);
|
|
873
|
-
}
|
|
874
|
-
catch {
|
|
875
|
-
// Ignore parse errors
|
|
876
|
-
}
|
|
877
|
-
}
|
|
878
|
-
// Check pyproject.toml
|
|
879
|
-
const pyprojectPath = join(dir, 'pyproject.toml');
|
|
880
|
-
if (existsSync(pyprojectPath)) {
|
|
881
|
-
result.packageManager = result.packageManager || 'pip';
|
|
882
|
-
result.hasDependencyFile = true;
|
|
883
|
-
// Basic TOML parsing for dependencies
|
|
884
|
-
try {
|
|
885
|
-
const content = readFileSync(pyprojectPath, 'utf-8');
|
|
886
|
-
const depMatch = content.match(/dependencies\s*=\s*\[([\s\S]*?)\]/);
|
|
887
|
-
if (depMatch && depMatch[1]) {
|
|
888
|
-
const deps = depMatch[1].match(/"([^"]+)"/g) || [];
|
|
889
|
-
result.dependencies = deps.map((d) => d.replace(/"/g, '').split(/[<>=!]/)[0]?.trim() ?? '').slice(0, 20);
|
|
890
|
-
}
|
|
891
|
-
}
|
|
892
|
-
catch {
|
|
893
|
-
// Ignore parse errors
|
|
894
|
-
}
|
|
895
|
-
}
|
|
896
|
-
// Check Cargo.toml
|
|
897
|
-
const cargoPath = join(dir, 'Cargo.toml');
|
|
898
|
-
if (existsSync(cargoPath)) {
|
|
899
|
-
result.packageManager = 'cargo';
|
|
900
|
-
result.hasDependencyFile = true;
|
|
901
|
-
}
|
|
902
|
-
// Check go.mod
|
|
903
|
-
const goModPath = join(dir, 'go.mod');
|
|
904
|
-
if (existsSync(goModPath)) {
|
|
905
|
-
result.packageManager = 'go modules';
|
|
906
|
-
result.hasDependencyFile = true;
|
|
907
|
-
}
|
|
908
|
-
return result;
|
|
909
|
-
}
|
|
910
|
-
function analyzeFile(filePath, workingDir, includeRelationships) {
|
|
911
|
-
const content = readFileSync(filePath, 'utf-8');
|
|
912
|
-
const lines = content.split('\n');
|
|
913
|
-
const ext = extname(filePath).toLowerCase();
|
|
914
|
-
const language = LANGUAGE_MAP[ext] || 'Unknown';
|
|
915
|
-
const relPath = relative(workingDir, filePath);
|
|
916
|
-
const imports = extractImports(content, ext);
|
|
917
|
-
const exports = extractExports(content, ext);
|
|
918
|
-
const functions = extractFunctions(content, ext);
|
|
919
|
-
const classes = extractClasses(content, ext);
|
|
920
|
-
const patterns = detectCodePatterns(content, ext);
|
|
921
|
-
const complexity = calculateComplexity(content);
|
|
922
|
-
const purpose = inferFilePurpose(basename(filePath), content, imports, exports, functions, classes);
|
|
923
|
-
const relationships = [];
|
|
924
|
-
if (includeRelationships) {
|
|
925
|
-
// Build relationships from imports
|
|
926
|
-
for (const imp of imports) {
|
|
927
|
-
if (imp.isRelative) {
|
|
928
|
-
relationships.push({
|
|
929
|
-
targetFile: imp.resolvedPath || imp.source,
|
|
930
|
-
type: 'imports',
|
|
931
|
-
symbols: imp.specifiers,
|
|
932
|
-
});
|
|
933
|
-
}
|
|
934
|
-
}
|
|
935
|
-
}
|
|
936
|
-
return {
|
|
937
|
-
path: relPath,
|
|
938
|
-
language,
|
|
939
|
-
size: content.length,
|
|
940
|
-
lineCount: lines.length,
|
|
941
|
-
purpose,
|
|
942
|
-
imports,
|
|
943
|
-
exports,
|
|
944
|
-
functions,
|
|
945
|
-
classes,
|
|
946
|
-
patterns,
|
|
947
|
-
relationships,
|
|
948
|
-
complexity,
|
|
949
|
-
};
|
|
950
|
-
}
|
|
951
|
-
function extractImports(content, ext) {
|
|
952
|
-
const imports = [];
|
|
953
|
-
if (['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'].includes(ext)) {
|
|
954
|
-
// ES6 imports
|
|
955
|
-
const importRegex = /import\s+(?:(\*\s+as\s+\w+)|(\{[^}]+\})|(\w+)(?:\s*,\s*\{([^}]+)\})?)\s+from\s+['"]([^'"]+)['"]/g;
|
|
956
|
-
let match;
|
|
957
|
-
while ((match = importRegex.exec(content)) !== null) {
|
|
958
|
-
const source = match[5] || '';
|
|
959
|
-
let specifiers = [];
|
|
960
|
-
if (match[1]) {
|
|
961
|
-
// namespace import
|
|
962
|
-
specifiers = [match[1].trim()];
|
|
963
|
-
}
|
|
964
|
-
else if (match[2]) {
|
|
965
|
-
// named imports
|
|
966
|
-
specifiers = match[2]
|
|
967
|
-
.replace(/[{}]/g, '')
|
|
968
|
-
.split(',')
|
|
969
|
-
.map((s) => s.trim())
|
|
970
|
-
.filter(Boolean);
|
|
971
|
-
}
|
|
972
|
-
else if (match[3]) {
|
|
973
|
-
// default import
|
|
974
|
-
specifiers = [match[3]];
|
|
975
|
-
if (match[4]) {
|
|
976
|
-
// additional named imports
|
|
977
|
-
specifiers.push(...match[4]
|
|
978
|
-
.split(',')
|
|
979
|
-
.map((s) => s.trim())
|
|
980
|
-
.filter(Boolean));
|
|
981
|
-
}
|
|
982
|
-
}
|
|
983
|
-
imports.push({
|
|
984
|
-
source,
|
|
985
|
-
specifiers,
|
|
986
|
-
isRelative: source.startsWith('.') || source.startsWith('/'),
|
|
987
|
-
});
|
|
988
|
-
}
|
|
989
|
-
// CommonJS requires
|
|
990
|
-
const requireRegex = /(?:const|let|var)\s+(?:(\{[^}]+\})|(\w+))\s*=\s*require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
991
|
-
while ((match = requireRegex.exec(content)) !== null) {
|
|
992
|
-
const source = match[3] || '';
|
|
993
|
-
let specifiers = [];
|
|
994
|
-
if (match[1]) {
|
|
995
|
-
specifiers = match[1]
|
|
996
|
-
.replace(/[{}]/g, '')
|
|
997
|
-
.split(',')
|
|
998
|
-
.map((s) => s.trim())
|
|
999
|
-
.filter(Boolean);
|
|
1000
|
-
}
|
|
1001
|
-
else if (match[2]) {
|
|
1002
|
-
specifiers = [match[2]];
|
|
1003
|
-
}
|
|
1004
|
-
imports.push({
|
|
1005
|
-
source,
|
|
1006
|
-
specifiers,
|
|
1007
|
-
isRelative: source.startsWith('.') || source.startsWith('/'),
|
|
1008
|
-
});
|
|
1009
|
-
}
|
|
1010
|
-
}
|
|
1011
|
-
else if (ext === '.py') {
|
|
1012
|
-
// Python imports
|
|
1013
|
-
const fromImportRegex = /from\s+([^\s]+)\s+import\s+(.+)/g;
|
|
1014
|
-
let match;
|
|
1015
|
-
while ((match = fromImportRegex.exec(content)) !== null) {
|
|
1016
|
-
const source = match[1] ?? '';
|
|
1017
|
-
const specifiers = (match[2] ?? '')
|
|
1018
|
-
.split(',')
|
|
1019
|
-
.map((s) => s.trim().split(' as ')[0]?.trim() ?? '')
|
|
1020
|
-
.filter(Boolean);
|
|
1021
|
-
imports.push({
|
|
1022
|
-
source,
|
|
1023
|
-
specifiers,
|
|
1024
|
-
isRelative: source.startsWith('.'),
|
|
1025
|
-
});
|
|
1026
|
-
}
|
|
1027
|
-
const importRegex = /^import\s+([^\s,]+(?:\s*,\s*[^\s,]+)*)/gm;
|
|
1028
|
-
while ((match = importRegex.exec(content)) !== null) {
|
|
1029
|
-
const modules = (match[1] ?? '').split(',').map((s) => s.trim().split(' as ')[0]?.trim() ?? '');
|
|
1030
|
-
for (const mod of modules) {
|
|
1031
|
-
if (mod) {
|
|
1032
|
-
imports.push({
|
|
1033
|
-
source: mod,
|
|
1034
|
-
specifiers: [mod],
|
|
1035
|
-
isRelative: mod.startsWith('.'),
|
|
1036
|
-
});
|
|
1037
|
-
}
|
|
1038
|
-
}
|
|
1039
|
-
}
|
|
1040
|
-
}
|
|
1041
|
-
return imports;
|
|
1042
|
-
}
|
|
1043
|
-
function extractExports(content, ext) {
|
|
1044
|
-
const exports = [];
|
|
1045
|
-
if (['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'].includes(ext)) {
|
|
1046
|
-
// Export default
|
|
1047
|
-
const defaultMatch = content.match(/export\s+default\s+(?:class|function)?\s*(\w+)?/);
|
|
1048
|
-
if (defaultMatch) {
|
|
1049
|
-
exports.push({
|
|
1050
|
-
name: defaultMatch[1] || 'default',
|
|
1051
|
-
type: 'default',
|
|
1052
|
-
});
|
|
1053
|
-
}
|
|
1054
|
-
// Named exports
|
|
1055
|
-
const namedExportRegex = /export\s+(?:const|let|var|function|class|interface|type|enum)\s+(\w+)/g;
|
|
1056
|
-
let match;
|
|
1057
|
-
while ((match = namedExportRegex.exec(content)) !== null) {
|
|
1058
|
-
const name = match[1] || '';
|
|
1059
|
-
const line = content.substring(0, match.index).split('\n').length;
|
|
1060
|
-
const lineContent = content.split('\n')[line - 1] || '';
|
|
1061
|
-
let type = 'named';
|
|
1062
|
-
if (lineContent.includes('interface'))
|
|
1063
|
-
type = 'interface';
|
|
1064
|
-
else if (lineContent.includes('type'))
|
|
1065
|
-
type = 'type';
|
|
1066
|
-
else if (lineContent.includes('class'))
|
|
1067
|
-
type = 'class';
|
|
1068
|
-
else if (lineContent.includes('function'))
|
|
1069
|
-
type = 'function';
|
|
1070
|
-
exports.push({ name, type });
|
|
1071
|
-
}
|
|
1072
|
-
// Re-exports
|
|
1073
|
-
const reExportRegex = /export\s+\{([^}]+)\}\s+from/g;
|
|
1074
|
-
while ((match = reExportRegex.exec(content)) !== null) {
|
|
1075
|
-
const names = (match[1] ?? '').split(',').map((s) => s.trim().split(' as ')[0]?.trim() ?? '');
|
|
1076
|
-
for (const name of names) {
|
|
1077
|
-
if (name) {
|
|
1078
|
-
exports.push({ name, type: 'named' });
|
|
1079
|
-
}
|
|
1080
|
-
}
|
|
1081
|
-
}
|
|
1082
|
-
}
|
|
1083
|
-
else if (ext === '.py') {
|
|
1084
|
-
// Python __all__
|
|
1085
|
-
const allMatch = content.match(/__all__\s*=\s*\[([\s\S]*?)\]/);
|
|
1086
|
-
if (allMatch && allMatch[1]) {
|
|
1087
|
-
const names = (allMatch[1].match(/['"]([^'"]+)['"]/g) || []).map((s) => s.replace(/['"]/g, ''));
|
|
1088
|
-
for (const name of names) {
|
|
1089
|
-
exports.push({ name, type: 'named' });
|
|
1090
|
-
}
|
|
1091
|
-
}
|
|
1092
|
-
// Public functions/classes (not starting with _)
|
|
1093
|
-
const defRegex = /^(?:def|class)\s+([a-zA-Z][a-zA-Z0-9_]*)/gm;
|
|
1094
|
-
let match;
|
|
1095
|
-
while ((match = defRegex.exec(content)) !== null) {
|
|
1096
|
-
const name = match[1] || '';
|
|
1097
|
-
if (!name.startsWith('_')) {
|
|
1098
|
-
const lineContent = content.split('\n')[content.substring(0, match.index).split('\n').length - 1] || '';
|
|
1099
|
-
exports.push({
|
|
1100
|
-
name,
|
|
1101
|
-
type: lineContent.startsWith('class') ? 'class' : 'function',
|
|
1102
|
-
});
|
|
1103
|
-
}
|
|
1104
|
-
}
|
|
1105
|
-
}
|
|
1106
|
-
return exports;
|
|
1107
|
-
}
|
|
1108
|
-
function extractFunctions(content, ext) {
|
|
1109
|
-
const functions = [];
|
|
1110
|
-
if (['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'].includes(ext)) {
|
|
1111
|
-
// Regular functions
|
|
1112
|
-
const funcRegex = /(?:export\s+)?(?:async\s+)?function\s+(\w+)\s*\(([^)]*)\)(?:\s*:\s*([^{]+))?\s*\{/g;
|
|
1113
|
-
let match;
|
|
1114
|
-
while ((match = funcRegex.exec(content)) !== null) {
|
|
1115
|
-
const name = match[1] || '';
|
|
1116
|
-
const params = (match[2] || '').split(',').map((p) => p.trim().split(':')[0]?.trim() ?? '').filter(Boolean);
|
|
1117
|
-
const returnType = (match[3] || '').trim() || undefined;
|
|
1118
|
-
const line = content.substring(0, match.index).split('\n').length;
|
|
1119
|
-
const isAsync = content.substring(match.index - 20, match.index).includes('async');
|
|
1120
|
-
const isExported = content.substring(match.index - 20, match.index).includes('export');
|
|
1121
|
-
functions.push({
|
|
1122
|
-
name,
|
|
1123
|
-
line,
|
|
1124
|
-
parameters: params,
|
|
1125
|
-
returnType,
|
|
1126
|
-
isAsync,
|
|
1127
|
-
isExported,
|
|
1128
|
-
complexity: 1,
|
|
1129
|
-
});
|
|
1130
|
-
}
|
|
1131
|
-
// Arrow functions
|
|
1132
|
-
const arrowRegex = /(?:export\s+)?(?:const|let|var)\s+(\w+)\s*=\s*(?:async\s+)?\(?([^)=]*)\)?\s*(?::\s*([^=]+))?\s*=>/g;
|
|
1133
|
-
while ((match = arrowRegex.exec(content)) !== null) {
|
|
1134
|
-
const name = match[1] || '';
|
|
1135
|
-
const params = (match[2] || '').split(',').map((p) => p.trim().split(':')[0]?.trim() ?? '').filter(Boolean);
|
|
1136
|
-
const returnType = (match[3] || '').trim() || undefined;
|
|
1137
|
-
const line = content.substring(0, match.index).split('\n').length;
|
|
1138
|
-
const isAsync = content.substring(match.index, match.index + 50).includes('async');
|
|
1139
|
-
const isExported = content.substring(match.index - 20, match.index).includes('export');
|
|
1140
|
-
functions.push({
|
|
1141
|
-
name,
|
|
1142
|
-
line,
|
|
1143
|
-
parameters: params,
|
|
1144
|
-
returnType,
|
|
1145
|
-
isAsync,
|
|
1146
|
-
isExported,
|
|
1147
|
-
complexity: 1,
|
|
1148
|
-
});
|
|
1149
|
-
}
|
|
1150
|
-
}
|
|
1151
|
-
else if (ext === '.py') {
|
|
1152
|
-
const defRegex = /(?:async\s+)?def\s+(\w+)\s*\(([^)]*)\)(?:\s*->\s*([^:]+))?\s*:/g;
|
|
1153
|
-
let match;
|
|
1154
|
-
while ((match = defRegex.exec(content)) !== null) {
|
|
1155
|
-
const name = match[1] ?? '';
|
|
1156
|
-
const params = (match[2] ?? '')
|
|
1157
|
-
.split(',')
|
|
1158
|
-
.map((p) => (p.trim().split(':')[0]?.split('=')[0]?.trim()) ?? '')
|
|
1159
|
-
.filter((p) => p && p !== 'self' && p !== 'cls');
|
|
1160
|
-
const returnType = (match[3] || '').trim() || undefined;
|
|
1161
|
-
const line = content.substring(0, match.index).split('\n').length;
|
|
1162
|
-
const isAsync = content.substring(match.index - 10, match.index).includes('async');
|
|
1163
|
-
functions.push({
|
|
1164
|
-
name,
|
|
1165
|
-
line,
|
|
1166
|
-
parameters: params,
|
|
1167
|
-
returnType,
|
|
1168
|
-
isAsync,
|
|
1169
|
-
isExported: !name.startsWith('_'),
|
|
1170
|
-
complexity: 1,
|
|
1171
|
-
});
|
|
1172
|
-
}
|
|
1173
|
-
}
|
|
1174
|
-
return functions;
|
|
1175
|
-
}
|
|
1176
|
-
function extractClasses(content, ext) {
|
|
1177
|
-
const classes = [];
|
|
1178
|
-
if (['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'].includes(ext)) {
|
|
1179
|
-
const classRegex = /(?:export\s+)?class\s+(\w+)(?:\s+extends\s+(\w+))?(?:\s+implements\s+([^{]+))?\s*\{/g;
|
|
1180
|
-
let match;
|
|
1181
|
-
while ((match = classRegex.exec(content)) !== null) {
|
|
1182
|
-
const name = match[1] || '';
|
|
1183
|
-
const line = content.substring(0, match.index).split('\n').length;
|
|
1184
|
-
const extendsClass = match[2];
|
|
1185
|
-
const implementsList = match[3]
|
|
1186
|
-
? match[3]
|
|
1187
|
-
.split(',')
|
|
1188
|
-
.map((s) => s.trim())
|
|
1189
|
-
.filter(Boolean)
|
|
1190
|
-
: undefined;
|
|
1191
|
-
const isExported = content.substring(match.index - 20, match.index).includes('export');
|
|
1192
|
-
// Find class body and extract methods/properties
|
|
1193
|
-
const classStart = match.index + match[0].length;
|
|
1194
|
-
let braceCount = 1;
|
|
1195
|
-
let classEnd = classStart;
|
|
1196
|
-
for (let i = classStart; i < content.length && braceCount > 0; i++) {
|
|
1197
|
-
if (content[i] === '{')
|
|
1198
|
-
braceCount++;
|
|
1199
|
-
if (content[i] === '}')
|
|
1200
|
-
braceCount--;
|
|
1201
|
-
classEnd = i;
|
|
1202
|
-
}
|
|
1203
|
-
const classBody = content.substring(classStart, classEnd);
|
|
1204
|
-
const methods = [];
|
|
1205
|
-
const properties = [];
|
|
1206
|
-
// Extract methods
|
|
1207
|
-
const methodRegex = /(?:async\s+)?(?:public|private|protected)?\s*(\w+)\s*\([^)]*\)/g;
|
|
1208
|
-
let methodMatch;
|
|
1209
|
-
while ((methodMatch = methodRegex.exec(classBody)) !== null) {
|
|
1210
|
-
if (methodMatch[1] && methodMatch[1] !== 'constructor') {
|
|
1211
|
-
methods.push(methodMatch[1]);
|
|
1212
|
-
}
|
|
1213
|
-
}
|
|
1214
|
-
// Extract properties
|
|
1215
|
-
const propRegex = /(?:public|private|protected|readonly)?\s+(\w+)\s*[:=]/g;
|
|
1216
|
-
let propMatch;
|
|
1217
|
-
while ((propMatch = propRegex.exec(classBody)) !== null) {
|
|
1218
|
-
if (propMatch[1]) {
|
|
1219
|
-
properties.push(propMatch[1]);
|
|
1220
|
-
}
|
|
1221
|
-
}
|
|
1222
|
-
classes.push({
|
|
1223
|
-
name,
|
|
1224
|
-
line,
|
|
1225
|
-
methods,
|
|
1226
|
-
properties,
|
|
1227
|
-
extends: extendsClass,
|
|
1228
|
-
implements: implementsList,
|
|
1229
|
-
isExported,
|
|
1230
|
-
});
|
|
1231
|
-
}
|
|
1232
|
-
}
|
|
1233
|
-
else if (ext === '.py') {
|
|
1234
|
-
const classRegex = /class\s+(\w+)(?:\s*\(([^)]*)\))?\s*:/g;
|
|
1235
|
-
let match;
|
|
1236
|
-
while ((match = classRegex.exec(content)) !== null) {
|
|
1237
|
-
const name = match[1] || '';
|
|
1238
|
-
const line = content.substring(0, match.index).split('\n').length;
|
|
1239
|
-
const parentClasses = match[2]
|
|
1240
|
-
? match[2]
|
|
1241
|
-
.split(',')
|
|
1242
|
-
.map((s) => s.trim())
|
|
1243
|
-
.filter(Boolean)
|
|
1244
|
-
: [];
|
|
1245
|
-
classes.push({
|
|
1246
|
-
name,
|
|
1247
|
-
line,
|
|
1248
|
-
methods: [],
|
|
1249
|
-
properties: [],
|
|
1250
|
-
extends: parentClasses[0],
|
|
1251
|
-
implements: parentClasses.slice(1),
|
|
1252
|
-
isExported: !name.startsWith('_'),
|
|
1253
|
-
});
|
|
1254
|
-
}
|
|
1255
|
-
}
|
|
1256
|
-
return classes;
|
|
1257
|
-
}
|
|
1258
|
-
function detectCodePatterns(content, _ext) {
|
|
1259
|
-
const patterns = [];
|
|
1260
|
-
// Common patterns detection
|
|
1261
|
-
if (/async\s+function|async\s+\(|await\s+/.test(content)) {
|
|
1262
|
-
patterns.push('Async/Await');
|
|
1263
|
-
}
|
|
1264
|
-
if (/Promise\.all|Promise\.race|Promise\.allSettled/.test(content)) {
|
|
1265
|
-
patterns.push('Promise Combinators');
|
|
1266
|
-
}
|
|
1267
|
-
if (/try\s*\{[\s\S]*?\}\s*catch/.test(content)) {
|
|
1268
|
-
patterns.push('Try-Catch Error Handling');
|
|
1269
|
-
}
|
|
1270
|
-
if (/\.map\s*\(|\.filter\s*\(|\.reduce\s*\(/.test(content)) {
|
|
1271
|
-
patterns.push('Functional Array Methods');
|
|
1272
|
-
}
|
|
1273
|
-
if (/Object\.freeze|Object\.seal|readonly\s+/.test(content)) {
|
|
1274
|
-
patterns.push('Immutability');
|
|
1275
|
-
}
|
|
1276
|
-
if (/interface\s+\w+|type\s+\w+\s*=/.test(content)) {
|
|
1277
|
-
patterns.push('TypeScript Types');
|
|
1278
|
-
}
|
|
1279
|
-
if (/\bclass\s+\w+/.test(content)) {
|
|
1280
|
-
patterns.push('Object-Oriented');
|
|
1281
|
-
}
|
|
1282
|
-
if (/export\s+default|export\s+\{|module\.exports/.test(content)) {
|
|
1283
|
-
patterns.push('Module Pattern');
|
|
1284
|
-
}
|
|
1285
|
-
if (/\.test\(|\.spec\.|describe\s*\(|it\s*\(|expect\s*\(/.test(content)) {
|
|
1286
|
-
patterns.push('Testing');
|
|
1287
|
-
}
|
|
1288
|
-
if (/console\.(log|error|warn|debug)/.test(content)) {
|
|
1289
|
-
patterns.push('Console Logging');
|
|
1290
|
-
}
|
|
1291
|
-
if (/@decorator|@\w+\s*\(|@\w+\s*\n/.test(content)) {
|
|
1292
|
-
patterns.push('Decorators');
|
|
1293
|
-
}
|
|
1294
|
-
if (/useEffect|useState|useCallback|useMemo/.test(content)) {
|
|
1295
|
-
patterns.push('React Hooks');
|
|
1296
|
-
}
|
|
1297
|
-
if (/createSlice|createReducer|createAction/.test(content)) {
|
|
1298
|
-
patterns.push('Redux Toolkit');
|
|
1299
|
-
}
|
|
1300
|
-
return patterns;
|
|
1301
|
-
}
|
|
1302
|
-
function calculateComplexity(content) {
|
|
1303
|
-
const lines = content.split('\n');
|
|
1304
|
-
const linesOfCode = lines.filter((l) => l.trim() && !l.trim().startsWith('//')).length;
|
|
1305
|
-
const linesOfComments = lines.filter((l) => l.trim().startsWith('//')).length;
|
|
1306
|
-
// Simple cyclomatic complexity estimation
|
|
1307
|
-
let cyclomaticComplexity = 1;
|
|
1308
|
-
const controlFlowPatterns = /\bif\b|\belse\b|\bfor\b|\bwhile\b|\bcase\b|\bcatch\b|\b\?\s*:/g;
|
|
1309
|
-
const matches = content.match(controlFlowPatterns);
|
|
1310
|
-
if (matches) {
|
|
1311
|
-
cyclomaticComplexity += matches.length;
|
|
1312
|
-
}
|
|
1313
|
-
// Cognitive complexity (simplified)
|
|
1314
|
-
let cognitiveComplexity = cyclomaticComplexity;
|
|
1315
|
-
const nestedPatterns = /\{\s*\{|\bif\b.*\bif\b/g;
|
|
1316
|
-
const nestedMatches = content.match(nestedPatterns);
|
|
1317
|
-
if (nestedMatches) {
|
|
1318
|
-
cognitiveComplexity += nestedMatches.length * 2;
|
|
1319
|
-
}
|
|
1320
|
-
// Maintainability index (simplified, 0-100 scale)
|
|
1321
|
-
const maintainabilityIndex = Math.max(0, Math.min(100, 171 - 5.2 * Math.log(linesOfCode + 1) - 0.23 * cyclomaticComplexity - 16.2 * Math.log(linesOfCode / (linesOfComments + 1) + 1)));
|
|
1322
|
-
return {
|
|
1323
|
-
cyclomaticComplexity,
|
|
1324
|
-
cognitiveComplexity,
|
|
1325
|
-
maintainabilityIndex: Math.round(maintainabilityIndex),
|
|
1326
|
-
linesOfCode,
|
|
1327
|
-
linesOfComments,
|
|
1328
|
-
};
|
|
1329
|
-
}
|
|
1330
|
-
function inferFilePurpose(filename, _content, _imports, exports, functions, classes) {
|
|
1331
|
-
const lower = filename.toLowerCase();
|
|
1332
|
-
// Check filename patterns
|
|
1333
|
-
if (lower.includes('test') || lower.includes('spec')) {
|
|
1334
|
-
return 'Test file for unit/integration testing';
|
|
1335
|
-
}
|
|
1336
|
-
if (lower === 'index.ts' || lower === 'index.js') {
|
|
1337
|
-
return 'Module entry point and public API exports';
|
|
1338
|
-
}
|
|
1339
|
-
if (lower.includes('config')) {
|
|
1340
|
-
return 'Configuration settings and constants';
|
|
1341
|
-
}
|
|
1342
|
-
if (lower.includes('type') || lower.includes('interface')) {
|
|
1343
|
-
return 'Type definitions and interfaces';
|
|
1344
|
-
}
|
|
1345
|
-
if (lower.includes('util') || lower.includes('helper')) {
|
|
1346
|
-
return 'Utility functions and helpers';
|
|
1347
|
-
}
|
|
1348
|
-
if (lower.includes('hook')) {
|
|
1349
|
-
return 'Custom React hooks';
|
|
1350
|
-
}
|
|
1351
|
-
if (lower.includes('context')) {
|
|
1352
|
-
return 'React context provider';
|
|
1353
|
-
}
|
|
1354
|
-
if (lower.includes('store') || lower.includes('reducer')) {
|
|
1355
|
-
return 'State management';
|
|
1356
|
-
}
|
|
1357
|
-
if (lower.includes('service')) {
|
|
1358
|
-
return 'Business logic and service layer';
|
|
1359
|
-
}
|
|
1360
|
-
if (lower.includes('api') || lower.includes('client')) {
|
|
1361
|
-
return 'API client and HTTP requests';
|
|
1362
|
-
}
|
|
1363
|
-
if (lower.includes('route')) {
|
|
1364
|
-
return 'Route definitions and handlers';
|
|
1365
|
-
}
|
|
1366
|
-
if (lower.includes('middleware')) {
|
|
1367
|
-
return 'Middleware functions';
|
|
1368
|
-
}
|
|
1369
|
-
if (lower.includes('model') || lower.includes('entity')) {
|
|
1370
|
-
return 'Data models and entities';
|
|
1371
|
-
}
|
|
1372
|
-
if (lower.includes('schema')) {
|
|
1373
|
-
return 'Schema definitions and validation';
|
|
1374
|
-
}
|
|
1375
|
-
if (lower.includes('component')) {
|
|
1376
|
-
return 'UI component';
|
|
1377
|
-
}
|
|
1378
|
-
// Infer from content
|
|
1379
|
-
if (classes.length > 0 && functions.length === 0) {
|
|
1380
|
-
return `Class definitions: ${classes.map((c) => c.name).join(', ')}`;
|
|
1381
|
-
}
|
|
1382
|
-
if (functions.length > 0 && classes.length === 0) {
|
|
1383
|
-
const exportedFuncs = functions.filter((f) => f.isExported);
|
|
1384
|
-
if (exportedFuncs.length > 0) {
|
|
1385
|
-
return `Function library: ${exportedFuncs.map((f) => f.name).slice(0, 3).join(', ')}${exportedFuncs.length > 3 ? '...' : ''}`;
|
|
1386
|
-
}
|
|
1387
|
-
}
|
|
1388
|
-
if (exports.length > 0) {
|
|
1389
|
-
return `Module exporting: ${exports.map((e) => e.name).slice(0, 3).join(', ')}${exports.length > 3 ? '...' : ''}`;
|
|
1390
|
-
}
|
|
1391
|
-
return 'General module';
|
|
1392
|
-
}
|
|
1393
|
-
function analyzeTopic(workingDir, topic, maxFiles, maxExamples) {
|
|
1394
|
-
const topicLower = topic.toLowerCase();
|
|
1395
|
-
const relevantFiles = [];
|
|
1396
|
-
const patterns = new Map();
|
|
1397
|
-
const examples = [];
|
|
1398
|
-
// Keywords to search for based on topic
|
|
1399
|
-
const keywords = generateTopicKeywords(topicLower);
|
|
1400
|
-
// Search through files
|
|
1401
|
-
const allFiles = collectAllFiles(workingDir, 4);
|
|
1402
|
-
for (const filePath of allFiles) {
|
|
1403
|
-
try {
|
|
1404
|
-
const content = readFileSync(filePath, 'utf-8');
|
|
1405
|
-
const lines = content.split('\n');
|
|
1406
|
-
const relPath = relative(workingDir, filePath);
|
|
1407
|
-
// Calculate relevance score
|
|
1408
|
-
let relevance = 0;
|
|
1409
|
-
const snippets = [];
|
|
1410
|
-
for (const keyword of keywords) {
|
|
1411
|
-
const regex = new RegExp(keyword, 'gi');
|
|
1412
|
-
const matches = content.match(regex);
|
|
1413
|
-
if (matches) {
|
|
1414
|
-
relevance += matches.length;
|
|
1415
|
-
// Find snippets containing the keyword
|
|
1416
|
-
for (let i = 0; i < lines.length && snippets.length < 3; i++) {
|
|
1417
|
-
if (lines[i]?.toLowerCase().includes(keyword)) {
|
|
1418
|
-
const snippet = lines.slice(Math.max(0, i - 1), Math.min(lines.length, i + 3)).join('\n');
|
|
1419
|
-
if (!snippets.includes(snippet)) {
|
|
1420
|
-
snippets.push(snippet);
|
|
1421
|
-
// Add to patterns
|
|
1422
|
-
const patternName = identifyPattern(lines[i] ?? '', keyword);
|
|
1423
|
-
if (patternName) {
|
|
1424
|
-
const existing = patterns.get(patternName) || { count: 0, locations: [] };
|
|
1425
|
-
existing.count++;
|
|
1426
|
-
if (!existing.locations.includes(relPath)) {
|
|
1427
|
-
existing.locations.push(relPath);
|
|
1428
|
-
}
|
|
1429
|
-
patterns.set(patternName, existing);
|
|
1430
|
-
}
|
|
1431
|
-
// Add to examples
|
|
1432
|
-
if (examples.length < maxExamples) {
|
|
1433
|
-
examples.push({
|
|
1434
|
-
file: relPath,
|
|
1435
|
-
line: i + 1,
|
|
1436
|
-
code: snippet,
|
|
1437
|
-
explanation: `Example of ${topic} usage`,
|
|
1438
|
-
});
|
|
1439
|
-
}
|
|
1440
|
-
}
|
|
1441
|
-
}
|
|
1442
|
-
}
|
|
1443
|
-
}
|
|
1444
|
-
}
|
|
1445
|
-
if (relevance > 0) {
|
|
1446
|
-
relevantFiles.push({
|
|
1447
|
-
path: relPath,
|
|
1448
|
-
relevance,
|
|
1449
|
-
snippets,
|
|
1450
|
-
});
|
|
1451
|
-
}
|
|
1452
|
-
}
|
|
1453
|
-
catch {
|
|
1454
|
-
// Skip files we can't read
|
|
1455
|
-
}
|
|
1456
|
-
}
|
|
1457
|
-
// Sort by relevance and limit
|
|
1458
|
-
relevantFiles.sort((a, b) => b.relevance - a.relevance);
|
|
1459
|
-
const topFiles = relevantFiles.slice(0, maxFiles);
|
|
1460
|
-
// Convert patterns map to array
|
|
1461
|
-
const topicPatterns = Array.from(patterns.entries())
|
|
1462
|
-
.map(([name, data]) => ({
|
|
1463
|
-
name,
|
|
1464
|
-
occurrences: data.count,
|
|
1465
|
-
locations: data.locations,
|
|
1466
|
-
}))
|
|
1467
|
-
.sort((a, b) => b.occurrences - a.occurrences);
|
|
1468
|
-
// Generate summary
|
|
1469
|
-
const summary = generateTopicSummary(topic, topFiles, topicPatterns, examples);
|
|
1470
|
-
return {
|
|
1471
|
-
topic,
|
|
1472
|
-
relevantFiles: topFiles,
|
|
1473
|
-
patterns: topicPatterns,
|
|
1474
|
-
examples: examples.slice(0, maxExamples),
|
|
1475
|
-
summary,
|
|
1476
|
-
};
|
|
1477
|
-
}
|
|
1478
|
-
function generateTopicKeywords(topic) {
|
|
1479
|
-
const keywords = [topic];
|
|
1480
|
-
// Add related keywords
|
|
1481
|
-
const relatedKeywords = {
|
|
1482
|
-
auth: ['authentication', 'authorize', 'login', 'logout', 'session', 'token', 'jwt', 'oauth', 'passport'],
|
|
1483
|
-
error: ['error', 'exception', 'catch', 'throw', 'try', 'finally', 'fail', 'handle'],
|
|
1484
|
-
api: ['api', 'route', 'endpoint', 'handler', 'request', 'response', 'http', 'rest', 'graphql'],
|
|
1485
|
-
test: ['test', 'spec', 'describe', 'it', 'expect', 'mock', 'jest', 'vitest', 'pytest'],
|
|
1486
|
-
database: ['database', 'db', 'sql', 'query', 'model', 'schema', 'migration', 'orm', 'prisma', 'mongoose'],
|
|
1487
|
-
validation: ['validate', 'validation', 'schema', 'zod', 'yup', 'joi', 'check', 'verify'],
|
|
1488
|
-
state: ['state', 'store', 'reducer', 'action', 'dispatch', 'context', 'redux', 'zustand', 'recoil'],
|
|
1489
|
-
cache: ['cache', 'memoize', 'memo', 'redis', 'memcached', 'ttl', 'invalidate'],
|
|
1490
|
-
logging: ['log', 'logger', 'logging', 'debug', 'trace', 'info', 'warn', 'error', 'console'],
|
|
1491
|
-
config: ['config', 'configuration', 'settings', 'env', 'environment', 'options'],
|
|
1492
|
-
};
|
|
1493
|
-
for (const [key, related] of Object.entries(relatedKeywords)) {
|
|
1494
|
-
if (topic.includes(key)) {
|
|
1495
|
-
keywords.push(...related);
|
|
1496
|
-
}
|
|
1497
|
-
}
|
|
1498
|
-
return [...new Set(keywords)];
|
|
1499
|
-
}
|
|
1500
|
-
function identifyPattern(line, _keyword) {
|
|
1501
|
-
const lower = line.toLowerCase();
|
|
1502
|
-
if (lower.includes('try') && lower.includes('catch'))
|
|
1503
|
-
return 'Try-Catch Pattern';
|
|
1504
|
-
if (lower.includes('async') && lower.includes('await'))
|
|
1505
|
-
return 'Async/Await Pattern';
|
|
1506
|
-
if (lower.includes('export') && lower.includes('default'))
|
|
1507
|
-
return 'Default Export';
|
|
1508
|
-
if (lower.includes('import') && lower.includes('from'))
|
|
1509
|
-
return 'ES6 Import';
|
|
1510
|
-
if (lower.includes('class') && lower.includes('extends'))
|
|
1511
|
-
return 'Class Inheritance';
|
|
1512
|
-
if (lower.includes('interface') || lower.includes('type'))
|
|
1513
|
-
return 'Type Definition';
|
|
1514
|
-
if (/\.(map|filter|reduce)\s*\(/.test(lower))
|
|
1515
|
-
return 'Functional Methods';
|
|
1516
|
-
if (lower.includes('usestate') || lower.includes('useeffect'))
|
|
1517
|
-
return 'React Hooks';
|
|
1518
|
-
if (lower.includes('describe') && lower.includes('it'))
|
|
1519
|
-
return 'Test Structure';
|
|
1520
|
-
return null;
|
|
1521
|
-
}
|
|
1522
|
-
function generateTopicSummary(topic, files, patterns, examples) {
|
|
1523
|
-
const parts = [];
|
|
1524
|
-
parts.push(`Analysis of "${topic}" in this codebase:\n`);
|
|
1525
|
-
if (files.length === 0) {
|
|
1526
|
-
parts.push(`No files found directly related to "${topic}". Consider searching for related terms.`);
|
|
1527
|
-
}
|
|
1528
|
-
else {
|
|
1529
|
-
parts.push(`Found ${files.length} relevant file(s).`);
|
|
1530
|
-
if (patterns.length > 0) {
|
|
1531
|
-
parts.push(`\nDetected patterns:`);
|
|
1532
|
-
for (const pattern of patterns.slice(0, 5)) {
|
|
1533
|
-
parts.push(`- ${pattern.name}: ${pattern.occurrences} occurrence(s)`);
|
|
1534
|
-
}
|
|
1535
|
-
}
|
|
1536
|
-
if (examples.length > 0) {
|
|
1537
|
-
parts.push(`\n${examples.length} code example(s) available.`);
|
|
1538
|
-
}
|
|
1539
|
-
parts.push(`\nMost relevant files:`);
|
|
1540
|
-
for (const file of files.slice(0, 5)) {
|
|
1541
|
-
parts.push(`- ${file.path} (relevance: ${file.relevance})`);
|
|
1542
|
-
}
|
|
1543
|
-
}
|
|
1544
|
-
return parts.join('\n');
|
|
1545
|
-
}
|
|
1546
|
-
function collectAllFiles(dir, maxDepth, depth = 0) {
|
|
1547
|
-
const files = [];
|
|
1548
|
-
if (depth >= maxDepth)
|
|
1549
|
-
return files;
|
|
1550
|
-
try {
|
|
1551
|
-
const entries = readdirSync(dir, { withFileTypes: true });
|
|
1552
|
-
for (const entry of entries) {
|
|
1553
|
-
if (entry.name.startsWith('.') || IGNORED_DIRS.has(entry.name)) {
|
|
1554
|
-
continue;
|
|
1555
|
-
}
|
|
1556
|
-
const fullPath = join(dir, entry.name);
|
|
1557
|
-
if (entry.isDirectory()) {
|
|
1558
|
-
files.push(...collectAllFiles(fullPath, maxDepth, depth + 1));
|
|
1559
|
-
}
|
|
1560
|
-
else if (entry.isFile()) {
|
|
1561
|
-
const ext = extname(entry.name).toLowerCase();
|
|
1562
|
-
if (LANGUAGE_MAP[ext]) {
|
|
1563
|
-
files.push(fullPath);
|
|
1564
|
-
}
|
|
1565
|
-
}
|
|
1566
|
-
}
|
|
1567
|
-
}
|
|
1568
|
-
catch {
|
|
1569
|
-
// Skip directories we can't read
|
|
1570
|
-
}
|
|
1571
|
-
return files;
|
|
1572
|
-
}
|
|
1573
|
-
function createAnalysisGuardrails(requestedDepth, includeHidden, mode) {
|
|
1574
|
-
const normalizedDepth = Number.isFinite(requestedDepth) ? requestedDepth : 5;
|
|
1575
|
-
const maxDepth = Math.min(8, Math.max(1, Math.floor(normalizedDepth)));
|
|
1576
|
-
const allowHidden = mode === 'detailed' && includeHidden;
|
|
1577
|
-
return {
|
|
1578
|
-
maxDepth,
|
|
1579
|
-
requestedDepth: normalizedDepth,
|
|
1580
|
-
includeHidden: allowHidden,
|
|
1581
|
-
hiddenRequestBlocked: includeHidden && !allowHidden,
|
|
1582
|
-
nodeLimit: mode === 'detailed' ? 12000 : 6000,
|
|
1583
|
-
nodeCount: 0,
|
|
1584
|
-
truncated: false,
|
|
1585
|
-
};
|
|
1586
|
-
}
|
|
1587
|
-
function getRecentExploreIndexSnapshot(workingDir) {
|
|
1588
|
-
try {
|
|
1589
|
-
const hash = createHash('md5').update(workingDir).digest('hex').slice(0, 12);
|
|
1590
|
-
const indexPath = join(homedir(), '.erosolar', 'explore-cache', `index-${hash}.json`);
|
|
1591
|
-
const stats = statSync(indexPath);
|
|
1592
|
-
const ageMs = Date.now() - stats.mtimeMs;
|
|
1593
|
-
const ageMinutes = Math.max(1, Math.round(ageMs / 60000));
|
|
1594
|
-
const payload = JSON.parse(readFileSync(indexPath, 'utf-8'));
|
|
1595
|
-
const fileCount = Array.isArray(payload?.files) ? payload.files.length : undefined;
|
|
1596
|
-
const freshnessWindowMs = 6 * 60 * 60 * 1000;
|
|
1597
|
-
return {
|
|
1598
|
-
fileCount,
|
|
1599
|
-
fresh: ageMs <= freshnessWindowMs,
|
|
1600
|
-
ageMinutes,
|
|
1601
|
-
};
|
|
1602
|
-
}
|
|
1603
|
-
catch {
|
|
1604
|
-
return null;
|
|
1605
|
-
}
|
|
1606
|
-
}
|
|
1607
|
-
function formatIndexPreflight(snapshot) {
|
|
1608
|
-
const lines = [];
|
|
1609
|
-
lines.push('# learn_codebase guardrail');
|
|
1610
|
-
lines.push(`Recent explore index detected${snapshot.fileCount ? ` (${snapshot.fileCount} files)` : ''}, ~${snapshot.ageMinutes}m old.`);
|
|
1611
|
-
lines.push('Reuse it via `explore` / `explore_index status` before running a fresh deep dive.');
|
|
1612
|
-
lines.push('If you truly need a scan, rerun with mode "detailed" or set a focused path to narrow scope.');
|
|
1613
|
-
return lines.join('\n');
|
|
1614
|
-
}
|
|
1615
|
-
function formatGuardrailSummary(guardrails) {
|
|
1616
|
-
if (!guardrails)
|
|
1617
|
-
return [];
|
|
1618
|
-
const parts = [
|
|
1619
|
-
`depth<=${guardrails.maxDepth}${guardrails.maxDepth < guardrails.requestedDepth ? ` (was ${guardrails.requestedDepth})` : ''}`,
|
|
1620
|
-
`hidden:${guardrails.includeHidden ? 'on' : 'off'}`,
|
|
1621
|
-
`node cap:${guardrails.nodeLimit}`,
|
|
1622
|
-
];
|
|
1623
|
-
const lines = [`Guardrails: ${parts.join(' | ')}`];
|
|
1624
|
-
if (guardrails.hiddenRequestBlocked) {
|
|
1625
|
-
lines.push('Hidden files scan disabled in concise mode; rerun in detailed mode to include them.');
|
|
1626
|
-
}
|
|
1627
|
-
if (guardrails.truncated) {
|
|
1628
|
-
lines.push(`Traversal stopped early after ${guardrails.nodeCount} items${guardrails.truncatedReason ? ` (${guardrails.truncatedReason})` : ''}.`);
|
|
1629
|
-
}
|
|
1630
|
-
return lines;
|
|
1631
|
-
}
|
|
1632
|
-
// =====================================================
|
|
1633
|
-
// Formatting Functions
|
|
1634
|
-
// =====================================================
|
|
1635
|
-
function formatConciseCodebaseAnalysis(analysis) {
|
|
1636
|
-
const lines = [];
|
|
1637
|
-
const topLanguages = analysis.languages.slice(0, 3).map((lang) => `${lang.language} (${lang.fileCount} files)`);
|
|
1638
|
-
const topPatterns = analysis.patterns.slice(0, 5).map((pattern) => `${pattern.name} (${pattern.confidence})`);
|
|
1639
|
-
const keyComponents = analysis.architecture.components.slice(0, 5).map((comp) => `${comp.name} - ${comp.path}`);
|
|
1640
|
-
const keyDirs = (analysis.structure.children ?? [])
|
|
1641
|
-
.filter((child) => child.type === 'directory')
|
|
1642
|
-
.slice(0, 5)
|
|
1643
|
-
.map((child) => `${child.name}/`);
|
|
1644
|
-
const keyConfigs = analysis.configFiles.slice(0, 5).map((config) => `${config.name}: ${config.purpose}`);
|
|
1645
|
-
const keyDependencies = analysis.dependencies.dependencies.slice(0, 8);
|
|
1646
|
-
const keyDevDependencies = analysis.dependencies.devDependencies.slice(0, 5);
|
|
1647
|
-
lines.push(`# Context-safe repo deep-learn: ${analysis.rootDir}`);
|
|
1648
|
-
lines.push('Use only when targeted explore/grep tools are insufficient.');
|
|
1649
|
-
const guardrailLines = formatGuardrailSummary(analysis.guardrails);
|
|
1650
|
-
if (guardrailLines.length > 0) {
|
|
1651
|
-
lines.push(...guardrailLines);
|
|
1652
|
-
}
|
|
1653
|
-
lines.push('');
|
|
1654
|
-
lines.push('## Overview');
|
|
1655
|
-
lines.push(`- Files: ${analysis.totalFiles} • Directories: ${analysis.totalDirectories}`);
|
|
1656
|
-
lines.push(`- Primary languages: ${topLanguages.length ? topLanguages.join('; ') : 'Unknown'}`);
|
|
1657
|
-
lines.push(`- Architecture: ${analysis.architecture.type || 'Unknown'}`);
|
|
1658
|
-
if (analysis.entryPoints.length > 0) {
|
|
1659
|
-
lines.push(`- Entry points: ${analysis.entryPoints.slice(0, 5).join(', ')}`);
|
|
1660
|
-
}
|
|
1661
|
-
lines.push('');
|
|
1662
|
-
if (topPatterns.length > 0) {
|
|
1663
|
-
lines.push('## Patterns & conventions');
|
|
1664
|
-
lines.push(`- ${topPatterns.join('; ')}`);
|
|
1665
|
-
lines.push('');
|
|
1666
|
-
}
|
|
1667
|
-
if (keyComponents.length > 0 || keyDirs.length > 0) {
|
|
1668
|
-
lines.push('## Key areas to inspect next');
|
|
1669
|
-
if (keyComponents.length > 0) {
|
|
1670
|
-
lines.push(`- Components: ${keyComponents.join('; ')}`);
|
|
1671
|
-
}
|
|
1672
|
-
if (keyDirs.length > 0) {
|
|
1673
|
-
lines.push(`- Important directories: ${keyDirs.join(', ')}`);
|
|
1674
|
-
}
|
|
1675
|
-
lines.push('');
|
|
1676
|
-
}
|
|
1677
|
-
if (keyConfigs.length > 0) {
|
|
1678
|
-
lines.push('## Configuration');
|
|
1679
|
-
lines.push(`- ${keyConfigs.join('; ')}`);
|
|
1680
|
-
lines.push('');
|
|
1681
|
-
}
|
|
1682
|
-
if (analysis.dependencies.hasDependencyFile && (keyDependencies.length > 0 || keyDevDependencies.length > 0)) {
|
|
1683
|
-
lines.push('## Dependencies snapshot');
|
|
1684
|
-
if (keyDependencies.length > 0) {
|
|
1685
|
-
lines.push(`- Dependencies: ${keyDependencies.join(', ')}${analysis.dependencies.dependencies.length > keyDependencies.length ? ' ...' : ''}`);
|
|
1686
|
-
}
|
|
1687
|
-
if (keyDevDependencies.length > 0) {
|
|
1688
|
-
lines.push(`- Dev dependencies: ${keyDevDependencies.join(', ')}${analysis.dependencies.devDependencies.length > keyDevDependencies.length ? ' ...' : ''}`);
|
|
1689
|
-
}
|
|
1690
|
-
lines.push('');
|
|
1691
|
-
}
|
|
1692
|
-
if (analysis.entryPoints.length > 0) {
|
|
1693
|
-
lines.push('## Suggested probes');
|
|
1694
|
-
const entryProbe = analysis.entryPoints.slice(0, 2).map((entry) => `- Check routing/boot flow around ${entry}`);
|
|
1695
|
-
lines.push(...entryProbe);
|
|
1696
|
-
}
|
|
1697
|
-
lines.push('- Run `explore_index status` to reuse the cached index, or `explore_index rebuild` after large file changes.');
|
|
1698
|
-
lines.push('- Use `explore` queries or `Grep` with `head_limit` to target follow-up investigations.');
|
|
1699
|
-
lines.push('');
|
|
1700
|
-
lines.push('Context guard: concise mode trims output to keep the session responsive. Use learn_codebase as a last resort; set mode to "detailed" only if you truly need the full tree and metrics.');
|
|
1701
|
-
return lines.join('\n');
|
|
1702
|
-
}
|
|
1703
|
-
function formatCodebaseAnalysis(analysis) {
|
|
1704
|
-
const output = [];
|
|
1705
|
-
// Show analysis phases completed
|
|
1706
|
-
output.push(`# Codebase Analysis: ${analysis.rootDir}`);
|
|
1707
|
-
output.push('Use only when targeted explore/grep tools are insufficient.');
|
|
1708
|
-
const guardrailLines = formatGuardrailSummary(analysis.guardrails);
|
|
1709
|
-
if (guardrailLines.length > 0) {
|
|
1710
|
-
output.push(...guardrailLines);
|
|
1711
|
-
}
|
|
1712
|
-
output.push('');
|
|
1713
|
-
output.push('## Analysis Phases Completed');
|
|
1714
|
-
output.push('✓ Directory structure traversal');
|
|
1715
|
-
output.push('✓ File type detection and language breakdown');
|
|
1716
|
-
output.push('✓ Architecture pattern detection');
|
|
1717
|
-
output.push('✓ Configuration file analysis');
|
|
1718
|
-
output.push('✓ Dependency analysis');
|
|
1719
|
-
output.push('✓ Entry point identification');
|
|
1720
|
-
output.push('✓ Component and layer mapping');
|
|
1721
|
-
output.push('');
|
|
1722
|
-
// Overview
|
|
1723
|
-
output.push('## Overview');
|
|
1724
|
-
output.push(`- Total files analyzed: ${analysis.totalFiles}`);
|
|
1725
|
-
output.push(`- Total directories scanned: ${analysis.totalDirectories}`);
|
|
1726
|
-
output.push(`- Patterns detected: ${analysis.patterns.length}`);
|
|
1727
|
-
output.push(`- Config files found: ${analysis.configFiles.length}`);
|
|
1728
|
-
output.push('');
|
|
1729
|
-
// Languages
|
|
1730
|
-
output.push('## Languages');
|
|
1731
|
-
for (const lang of analysis.languages.slice(0, 10)) {
|
|
1732
|
-
output.push(`- ${lang.language}: ${lang.fileCount} files (${lang.percentage.toFixed(1)}%)`);
|
|
1733
|
-
}
|
|
1734
|
-
output.push('');
|
|
1735
|
-
// Architecture
|
|
1736
|
-
output.push('## Architecture');
|
|
1737
|
-
output.push(`- Type: ${analysis.architecture.type}`);
|
|
1738
|
-
if (analysis.architecture.layers.length > 0) {
|
|
1739
|
-
output.push(`- Layers: ${analysis.architecture.layers.join(', ')}`);
|
|
1740
|
-
}
|
|
1741
|
-
if (analysis.architecture.dataFlow.length > 0) {
|
|
1742
|
-
output.push('- Data Flow:');
|
|
1743
|
-
for (const flow of analysis.architecture.dataFlow) {
|
|
1744
|
-
output.push(` - ${flow}`);
|
|
1745
|
-
}
|
|
1746
|
-
}
|
|
1747
|
-
output.push('');
|
|
1748
|
-
// Detected Patterns
|
|
1749
|
-
if (analysis.patterns.length > 0) {
|
|
1750
|
-
output.push('## Detected Patterns');
|
|
1751
|
-
for (const pattern of analysis.patterns) {
|
|
1752
|
-
output.push(`- **${pattern.name}** (${pattern.confidence} confidence)`);
|
|
1753
|
-
output.push(` ${pattern.description}`);
|
|
1754
|
-
}
|
|
1755
|
-
output.push('');
|
|
1756
|
-
}
|
|
1757
|
-
// Key Components
|
|
1758
|
-
if (analysis.architecture.components.length > 0) {
|
|
1759
|
-
output.push('## Key Components');
|
|
1760
|
-
for (const comp of analysis.architecture.components.slice(0, 15)) {
|
|
1761
|
-
output.push(`- **${comp.name}** (${comp.type}): ${comp.path}`);
|
|
1762
|
-
if (comp.responsibilities.length > 0) {
|
|
1763
|
-
output.push(` Responsibilities: ${comp.responsibilities.join(', ')}`);
|
|
1764
|
-
}
|
|
1765
|
-
}
|
|
1766
|
-
output.push('');
|
|
1767
|
-
}
|
|
1768
|
-
// Entry Points
|
|
1769
|
-
if (analysis.entryPoints.length > 0) {
|
|
1770
|
-
output.push('## Entry Points');
|
|
1771
|
-
for (const entry of analysis.entryPoints) {
|
|
1772
|
-
output.push(`- ${entry}`);
|
|
1773
|
-
}
|
|
1774
|
-
output.push('');
|
|
1775
|
-
}
|
|
1776
|
-
// Configuration Files
|
|
1777
|
-
if (analysis.configFiles.length > 0) {
|
|
1778
|
-
output.push('## Configuration Files');
|
|
1779
|
-
for (const config of analysis.configFiles.slice(0, 10)) {
|
|
1780
|
-
output.push(`- **${config.name}** (${config.type}): ${config.purpose}`);
|
|
1781
|
-
}
|
|
1782
|
-
output.push('');
|
|
1783
|
-
}
|
|
1784
|
-
// Dependencies
|
|
1785
|
-
if (analysis.dependencies.hasDependencyFile) {
|
|
1786
|
-
output.push('## Dependencies');
|
|
1787
|
-
output.push(`- Package Manager: ${analysis.dependencies.packageManager || 'Unknown'}`);
|
|
1788
|
-
if (analysis.dependencies.dependencies.length > 0) {
|
|
1789
|
-
output.push(`- Dependencies: ${analysis.dependencies.dependencies.slice(0, 10).join(', ')}${analysis.dependencies.dependencies.length > 10 ? '...' : ''}`);
|
|
1790
|
-
}
|
|
1791
|
-
if (analysis.dependencies.devDependencies.length > 0) {
|
|
1792
|
-
output.push(`- Dev Dependencies: ${analysis.dependencies.devDependencies.slice(0, 10).join(', ')}${analysis.dependencies.devDependencies.length > 10 ? '...' : ''}`);
|
|
1793
|
-
}
|
|
1794
|
-
output.push('');
|
|
1795
|
-
}
|
|
1796
|
-
// Directory Structure (simplified)
|
|
1797
|
-
output.push('## Directory Structure');
|
|
1798
|
-
output.push(formatDirectoryTree(analysis.structure, 0, 3));
|
|
1799
|
-
return output.join('\n');
|
|
1800
|
-
}
|
|
1801
|
-
function formatDirectoryTree(node, depth, maxDepth) {
|
|
1802
|
-
const indent = ' '.repeat(depth);
|
|
1803
|
-
const lines = [];
|
|
1804
|
-
if (node.type === 'directory') {
|
|
1805
|
-
lines.push(`${indent}${node.name}/`);
|
|
1806
|
-
if (node.children && depth < maxDepth) {
|
|
1807
|
-
for (const child of node.children.slice(0, 15)) {
|
|
1808
|
-
lines.push(formatDirectoryTree(child, depth + 1, maxDepth));
|
|
1809
|
-
}
|
|
1810
|
-
if (node.children.length > 15) {
|
|
1811
|
-
lines.push(`${indent} ... (${node.children.length - 15} more)`);
|
|
1812
|
-
}
|
|
1813
|
-
}
|
|
1814
|
-
}
|
|
1815
|
-
else {
|
|
1816
|
-
const langSuffix = node.language ? ` [${node.language}]` : '';
|
|
1817
|
-
lines.push(`${indent}${node.name}${langSuffix}`);
|
|
1818
|
-
}
|
|
1819
|
-
return lines.join('\n');
|
|
1820
|
-
}
|
|
1821
|
-
function formatFileAnalysis(analysis) {
|
|
1822
|
-
const output = [];
|
|
1823
|
-
output.push(`# File Analysis: ${analysis.path}`);
|
|
1824
|
-
output.push('');
|
|
1825
|
-
// Overview
|
|
1826
|
-
output.push('## Overview');
|
|
1827
|
-
output.push(`- Language: ${analysis.language}`);
|
|
1828
|
-
output.push(`- Lines: ${analysis.lineCount}`);
|
|
1829
|
-
output.push(`- Size: ${(analysis.size / 1024).toFixed(2)} KB`);
|
|
1830
|
-
output.push(`- Purpose: ${analysis.purpose}`);
|
|
1831
|
-
output.push('');
|
|
1832
|
-
// Complexity
|
|
1833
|
-
output.push('## Complexity Metrics');
|
|
1834
|
-
output.push(`- Cyclomatic Complexity: ${analysis.complexity.cyclomaticComplexity}`);
|
|
1835
|
-
output.push(`- Cognitive Complexity: ${analysis.complexity.cognitiveComplexity}`);
|
|
1836
|
-
output.push(`- Maintainability Index: ${analysis.complexity.maintainabilityIndex}/100`);
|
|
1837
|
-
output.push(`- Lines of Code: ${analysis.complexity.linesOfCode}`);
|
|
1838
|
-
output.push(`- Lines of Comments: ${analysis.complexity.linesOfComments}`);
|
|
1839
|
-
output.push('');
|
|
1840
|
-
// Imports
|
|
1841
|
-
if (analysis.imports.length > 0) {
|
|
1842
|
-
output.push('## Imports');
|
|
1843
|
-
for (const imp of analysis.imports.slice(0, 15)) {
|
|
1844
|
-
const type = imp.isRelative ? '(relative)' : '(external)';
|
|
1845
|
-
output.push(`- ${imp.source} ${type}`);
|
|
1846
|
-
if (imp.specifiers.length > 0) {
|
|
1847
|
-
output.push(` Imports: ${imp.specifiers.join(', ')}`);
|
|
1848
|
-
}
|
|
1849
|
-
}
|
|
1850
|
-
if (analysis.imports.length > 15) {
|
|
1851
|
-
output.push(`- ... and ${analysis.imports.length - 15} more imports`);
|
|
1852
|
-
}
|
|
1853
|
-
output.push('');
|
|
1854
|
-
}
|
|
1855
|
-
// Exports
|
|
1856
|
-
if (analysis.exports.length > 0) {
|
|
1857
|
-
output.push('## Exports');
|
|
1858
|
-
for (const exp of analysis.exports) {
|
|
1859
|
-
output.push(`- ${exp.name} (${exp.type})`);
|
|
1860
|
-
}
|
|
1861
|
-
output.push('');
|
|
1862
|
-
}
|
|
1863
|
-
// Functions
|
|
1864
|
-
if (analysis.functions.length > 0) {
|
|
1865
|
-
output.push('## Functions');
|
|
1866
|
-
for (const func of analysis.functions.slice(0, 20)) {
|
|
1867
|
-
const async = func.isAsync ? 'async ' : '';
|
|
1868
|
-
const exported = func.isExported ? 'export ' : '';
|
|
1869
|
-
const params = func.parameters.join(', ');
|
|
1870
|
-
const ret = func.returnType ? `: ${func.returnType}` : '';
|
|
1871
|
-
output.push(`- Line ${func.line}: ${exported}${async}${func.name}(${params})${ret}`);
|
|
1872
|
-
}
|
|
1873
|
-
if (analysis.functions.length > 20) {
|
|
1874
|
-
output.push(`- ... and ${analysis.functions.length - 20} more functions`);
|
|
1875
|
-
}
|
|
1876
|
-
output.push('');
|
|
1877
|
-
}
|
|
1878
|
-
// Classes
|
|
1879
|
-
if (analysis.classes.length > 0) {
|
|
1880
|
-
output.push('## Classes');
|
|
1881
|
-
for (const cls of analysis.classes) {
|
|
1882
|
-
const exported = cls.isExported ? 'export ' : '';
|
|
1883
|
-
const ext = cls.extends ? ` extends ${cls.extends}` : '';
|
|
1884
|
-
const impl = cls.implements?.length ? ` implements ${cls.implements.join(', ')}` : '';
|
|
1885
|
-
output.push(`- Line ${cls.line}: ${exported}class ${cls.name}${ext}${impl}`);
|
|
1886
|
-
if (cls.methods.length > 0) {
|
|
1887
|
-
output.push(` Methods: ${cls.methods.join(', ')}`);
|
|
1888
|
-
}
|
|
1889
|
-
if (cls.properties.length > 0) {
|
|
1890
|
-
output.push(` Properties: ${cls.properties.join(', ')}`);
|
|
1891
|
-
}
|
|
1892
|
-
}
|
|
1893
|
-
output.push('');
|
|
1894
|
-
}
|
|
1895
|
-
// Patterns
|
|
1896
|
-
if (analysis.patterns.length > 0) {
|
|
1897
|
-
output.push('## Detected Patterns');
|
|
1898
|
-
output.push(analysis.patterns.join(', '));
|
|
1899
|
-
output.push('');
|
|
1900
|
-
}
|
|
1901
|
-
// Relationships
|
|
1902
|
-
if (analysis.relationships.length > 0) {
|
|
1903
|
-
output.push('## File Relationships');
|
|
1904
|
-
for (const rel of analysis.relationships) {
|
|
1905
|
-
output.push(`- ${rel.type}: ${rel.targetFile}`);
|
|
1906
|
-
if (rel.symbols.length > 0) {
|
|
1907
|
-
output.push(` Symbols: ${rel.symbols.join(', ')}`);
|
|
1908
|
-
}
|
|
1909
|
-
}
|
|
1910
|
-
output.push('');
|
|
1911
|
-
}
|
|
1912
|
-
return output.join('\n');
|
|
1913
|
-
}
|
|
1914
|
-
function formatTopicAnalysis(analysis) {
|
|
1915
|
-
const output = [];
|
|
1916
|
-
output.push(`# Topic Analysis: "${analysis.topic}"`);
|
|
1917
|
-
output.push('');
|
|
1918
|
-
output.push(analysis.summary);
|
|
1919
|
-
output.push('');
|
|
1920
|
-
// Patterns
|
|
1921
|
-
if (analysis.patterns.length > 0) {
|
|
1922
|
-
output.push('## Patterns Found');
|
|
1923
|
-
for (const pattern of analysis.patterns) {
|
|
1924
|
-
output.push(`### ${pattern.name}`);
|
|
1925
|
-
output.push(`- Occurrences: ${pattern.occurrences}`);
|
|
1926
|
-
output.push(`- Found in: ${pattern.locations.slice(0, 5).join(', ')}${pattern.locations.length > 5 ? '...' : ''}`);
|
|
1927
|
-
output.push('');
|
|
1928
|
-
}
|
|
1929
|
-
}
|
|
1930
|
-
// Relevant Files
|
|
1931
|
-
if (analysis.relevantFiles.length > 0) {
|
|
1932
|
-
output.push('## Relevant Files');
|
|
1933
|
-
for (const file of analysis.relevantFiles) {
|
|
1934
|
-
output.push(`### ${file.path}`);
|
|
1935
|
-
output.push(`Relevance Score: ${file.relevance}`);
|
|
1936
|
-
if (file.snippets.length > 0) {
|
|
1937
|
-
output.push('');
|
|
1938
|
-
output.push('Relevant snippets:');
|
|
1939
|
-
for (const snippet of file.snippets.slice(0, 2)) {
|
|
1940
|
-
output.push('```');
|
|
1941
|
-
output.push(snippet);
|
|
1942
|
-
output.push('```');
|
|
1943
|
-
}
|
|
1944
|
-
}
|
|
1945
|
-
output.push('');
|
|
1946
|
-
}
|
|
1947
|
-
}
|
|
1948
|
-
// Code Examples
|
|
1949
|
-
if (analysis.examples.length > 0) {
|
|
1950
|
-
output.push('## Code Examples');
|
|
1951
|
-
for (const example of analysis.examples) {
|
|
1952
|
-
output.push(`### ${example.file}:${example.line}`);
|
|
1953
|
-
output.push(example.explanation);
|
|
1954
|
-
output.push('```');
|
|
1955
|
-
output.push(example.code);
|
|
1956
|
-
output.push('```');
|
|
1957
|
-
output.push('');
|
|
1958
|
-
}
|
|
1959
|
-
}
|
|
1960
|
-
return output.join('\n');
|
|
1961
|
-
}
|
|
1962
|
-
function formatLearningSummary(analysis, format, _focus) {
|
|
1963
|
-
const output = [];
|
|
1964
|
-
const isMarkdown = format === 'markdown';
|
|
1965
|
-
const h1 = (text) => (isMarkdown ? `# ${text}` : text.toUpperCase());
|
|
1966
|
-
const h2 = (text) => (isMarkdown ? `## ${text}` : `\n${text}`);
|
|
1967
|
-
const bullet = isMarkdown ? '-' : '*';
|
|
1968
|
-
output.push(h1('Codebase Learning Summary'));
|
|
1969
|
-
output.push('');
|
|
1970
|
-
// Quick Start
|
|
1971
|
-
output.push(h2('Quick Start'));
|
|
1972
|
-
output.push('');
|
|
1973
|
-
const mainLang = analysis.languages[0];
|
|
1974
|
-
if (mainLang) {
|
|
1975
|
-
output.push(`This is primarily a **${mainLang.language}** project.`);
|
|
1976
|
-
}
|
|
1977
|
-
if (analysis.dependencies.packageManager) {
|
|
1978
|
-
output.push(`Package manager: **${analysis.dependencies.packageManager}**`);
|
|
1979
|
-
}
|
|
1980
|
-
if (analysis.entryPoints.length > 0) {
|
|
1981
|
-
output.push(`Main entry point: \`${analysis.entryPoints[0]}\``);
|
|
1982
|
-
}
|
|
1983
|
-
output.push('');
|
|
1984
|
-
// Architecture Overview
|
|
1985
|
-
output.push(h2('Architecture Overview'));
|
|
1986
|
-
output.push('');
|
|
1987
|
-
output.push(`Architecture Type: **${analysis.architecture.type}**`);
|
|
1988
|
-
if (analysis.architecture.layers.length > 0) {
|
|
1989
|
-
output.push(`Layers: ${analysis.architecture.layers.join(' → ')}`);
|
|
1990
|
-
}
|
|
1991
|
-
for (const flow of analysis.architecture.dataFlow) {
|
|
1992
|
-
output.push(`${bullet} ${flow}`);
|
|
1993
|
-
}
|
|
1994
|
-
output.push('');
|
|
1995
|
-
// Key Concepts
|
|
1996
|
-
output.push(h2('Key Concepts'));
|
|
1997
|
-
output.push('');
|
|
1998
|
-
for (const pattern of analysis.patterns.slice(0, 5)) {
|
|
1999
|
-
output.push(`${bullet} **${pattern.name}**: ${pattern.description}`);
|
|
2000
|
-
}
|
|
2001
|
-
output.push('');
|
|
2002
|
-
// Important Files
|
|
2003
|
-
output.push(h2('Important Files'));
|
|
2004
|
-
output.push('');
|
|
2005
|
-
for (const config of analysis.configFiles.slice(0, 5)) {
|
|
2006
|
-
output.push(`${bullet} \`${config.path}\`: ${config.purpose}`);
|
|
2007
|
-
}
|
|
2008
|
-
if (analysis.entryPoints.length > 0) {
|
|
2009
|
-
output.push('');
|
|
2010
|
-
output.push('Entry points:');
|
|
2011
|
-
for (const entry of analysis.entryPoints) {
|
|
2012
|
-
output.push(`${bullet} \`${entry}\``);
|
|
2013
|
-
}
|
|
2014
|
-
}
|
|
2015
|
-
output.push('');
|
|
2016
|
-
// Directory Guide
|
|
2017
|
-
output.push(h2('Directory Guide'));
|
|
2018
|
-
output.push('');
|
|
2019
|
-
for (const comp of analysis.architecture.components.slice(0, 10)) {
|
|
2020
|
-
output.push(`${bullet} **${comp.name}/** (${comp.type})`);
|
|
2021
|
-
if (comp.responsibilities.length > 0) {
|
|
2022
|
-
output.push(` ${comp.responsibilities.slice(0, 2).join(', ')}`);
|
|
2023
|
-
}
|
|
2024
|
-
}
|
|
2025
|
-
output.push('');
|
|
2026
|
-
// Common Patterns
|
|
2027
|
-
if (analysis.patterns.length > 0) {
|
|
2028
|
-
output.push(h2('Common Patterns'));
|
|
2029
|
-
output.push('');
|
|
2030
|
-
for (const pattern of analysis.patterns.filter((p) => p.confidence === 'high').slice(0, 5)) {
|
|
2031
|
-
output.push(`${bullet} **${pattern.name}**`);
|
|
2032
|
-
for (const evidence of pattern.evidence.slice(0, 2)) {
|
|
2033
|
-
output.push(` ${bullet} ${evidence}`);
|
|
2034
|
-
}
|
|
2035
|
-
}
|
|
2036
|
-
output.push('');
|
|
2037
|
-
}
|
|
2038
|
-
// Development Workflow
|
|
2039
|
-
output.push(h2('Development Workflow'));
|
|
2040
|
-
output.push('');
|
|
2041
|
-
const hasTest = analysis.configFiles.some((c) => c.type === 'testing');
|
|
2042
|
-
const hasLint = analysis.configFiles.some((c) => c.type === 'linting');
|
|
2043
|
-
const hasBundler = analysis.configFiles.some((c) => c.type === 'bundler');
|
|
2044
|
-
if (analysis.dependencies.packageManager === 'npm') {
|
|
2045
|
-
output.push('```bash');
|
|
2046
|
-
output.push('# Install dependencies');
|
|
2047
|
-
output.push('npm install');
|
|
2048
|
-
output.push('');
|
|
2049
|
-
if (hasBundler) {
|
|
2050
|
-
output.push('# Build project');
|
|
2051
|
-
output.push('npm run build');
|
|
2052
|
-
output.push('');
|
|
2053
|
-
}
|
|
2054
|
-
if (hasTest) {
|
|
2055
|
-
output.push('# Run tests');
|
|
2056
|
-
output.push('npm test');
|
|
2057
|
-
output.push('');
|
|
2058
|
-
}
|
|
2059
|
-
if (hasLint) {
|
|
2060
|
-
output.push('# Lint code');
|
|
2061
|
-
output.push('npm run lint');
|
|
2062
|
-
}
|
|
2063
|
-
output.push('```');
|
|
2064
|
-
}
|
|
2065
|
-
else if (analysis.dependencies.packageManager === 'pip') {
|
|
2066
|
-
output.push('```bash');
|
|
2067
|
-
output.push('# Install dependencies');
|
|
2068
|
-
output.push('pip install -e .');
|
|
2069
|
-
output.push('');
|
|
2070
|
-
if (hasTest) {
|
|
2071
|
-
output.push('# Run tests');
|
|
2072
|
-
output.push('pytest');
|
|
2073
|
-
}
|
|
2074
|
-
output.push('```');
|
|
2075
|
-
}
|
|
2076
|
-
output.push('');
|
|
2077
|
-
// Next Steps
|
|
2078
|
-
output.push(h2('Suggested Next Steps'));
|
|
2079
|
-
output.push('');
|
|
2080
|
-
output.push(`1. Read the entry point: \`${analysis.entryPoints[0] || 'index file'}\``);
|
|
2081
|
-
if (analysis.configFiles.some((c) => c.name === 'package.json')) {
|
|
2082
|
-
output.push('2. Review `package.json` for available scripts');
|
|
2083
|
-
}
|
|
2084
|
-
output.push('3. Explore the main directories to understand the structure');
|
|
2085
|
-
if (hasTest) {
|
|
2086
|
-
output.push('4. Run the test suite to verify setup');
|
|
2087
|
-
}
|
|
2088
|
-
output.push('5. Use `learn_topic` to explore specific features');
|
|
2089
|
-
return output.join('\n');
|
|
2090
|
-
}
|
|
2091
|
-
// =====================================================
|
|
2092
|
-
// Utilities
|
|
2093
|
-
// =====================================================
|
|
2094
|
-
function resolveFilePath(workingDir, path) {
|
|
2095
|
-
const normalized = path.trim();
|
|
2096
|
-
return normalized.startsWith('/') ? normalized : join(workingDir, normalized);
|
|
2097
|
-
}
|
|
2098
|
-
//# sourceMappingURL=learnTools.js.map
|