653 lines
19 KiB
Go
653 lines
19 KiB
Go
package intelligence
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"path/filepath"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
|
|
slurpContext "chorus/pkg/slurp/context"
|
|
"chorus/pkg/ucxl"
|
|
)
|
|
|
|
// AnalyzeFile analyzes a single file and generates contextual understanding
|
|
func (e *DefaultIntelligenceEngine) AnalyzeFile(ctx context.Context, filePath string, role string) (*slurpContext.ContextNode, error) {
|
|
start := time.Now()
|
|
defer func() {
|
|
e.updateStats("file_analysis", time.Since(start), true)
|
|
}()
|
|
|
|
// Check cache first
|
|
cacheKey := fmt.Sprintf("file:%s:%s", filePath, role)
|
|
if cached, ok := e.cache.Load(cacheKey); ok {
|
|
if entry, ok := cached.(*CacheEntry); ok && time.Now().Before(entry.ExpiresAt) {
|
|
e.mu.Lock()
|
|
e.stats.CacheHitRate = (e.stats.CacheHitRate*float64(e.stats.TotalAnalyses) + 1) / float64(e.stats.TotalAnalyses+1)
|
|
e.mu.Unlock()
|
|
return entry.ContextNode, nil
|
|
}
|
|
}
|
|
|
|
// Read file content
|
|
content, err := e.readFileContent(filePath)
|
|
if err != nil {
|
|
e.updateStats("file_analysis", time.Since(start), false)
|
|
return nil, fmt.Errorf("failed to read file %s: %w", filePath, err)
|
|
}
|
|
|
|
// Skip files that are too large
|
|
if int64(len(content)) > e.config.MaxFileSize {
|
|
e.updateStats("file_analysis", time.Since(start), false)
|
|
return nil, fmt.Errorf("file %s too large (%d bytes > %d bytes)", filePath, len(content), e.config.MaxFileSize)
|
|
}
|
|
|
|
// Perform file analysis
|
|
analysis, err := e.fileAnalyzer.AnalyzeContent(ctx, filePath, content)
|
|
if err != nil {
|
|
e.updateStats("file_analysis", time.Since(start), false)
|
|
return nil, fmt.Errorf("failed to analyze file content: %w", err)
|
|
}
|
|
|
|
// Generate UCXL address for the file
|
|
ucxlAddr, err := e.generateUCXLAddress(filePath)
|
|
if err != nil {
|
|
e.updateStats("file_analysis", time.Since(start), false)
|
|
return nil, fmt.Errorf("failed to generate UCXL address: %w", err)
|
|
}
|
|
|
|
// Extract purpose and summary
|
|
purpose, purposeConf, err := e.fileAnalyzer.IdentifyPurpose(ctx, analysis)
|
|
if err != nil {
|
|
purpose = "Unknown purpose"
|
|
purposeConf = 0.0
|
|
}
|
|
|
|
summary, err := e.fileAnalyzer.GenerateSummary(ctx, analysis)
|
|
if err != nil {
|
|
summary = "File analysis summary unavailable"
|
|
}
|
|
|
|
// Extract technologies
|
|
technologies, err := e.fileAnalyzer.ExtractTechnologies(ctx, analysis)
|
|
if err != nil {
|
|
technologies = []string{}
|
|
}
|
|
|
|
// Generate basic tags
|
|
tags := e.generateFileTags(analysis, filePath)
|
|
|
|
// Generate role-specific insights
|
|
insights, err := e.GenerateRoleInsights(ctx, nil, role)
|
|
if err != nil {
|
|
insights = []string{}
|
|
}
|
|
|
|
// Enhance with RAG if enabled
|
|
ragConfidence := 0.0
|
|
if e.config.RAGEnabled {
|
|
// This would be enhanced in a real implementation
|
|
ragConfidence = 0.7
|
|
}
|
|
|
|
// Create context node
|
|
contextNode := &slurpContext.ContextNode{
|
|
Path: filePath,
|
|
UCXLAddress: *ucxlAddr,
|
|
Summary: summary,
|
|
Purpose: purpose,
|
|
Technologies: technologies,
|
|
Tags: tags,
|
|
Insights: insights,
|
|
OverridesParent: false,
|
|
ContextSpecificity: e.calculateSpecificity(analysis),
|
|
AppliesToChildren: false,
|
|
GeneratedAt: time.Now(),
|
|
RAGConfidence: ragConfidence,
|
|
EncryptedFor: e.determineEncryptionRoles(role, purposeConf),
|
|
AccessLevel: e.determineAccessLevel(analysis, role),
|
|
Metadata: make(map[string]interface{}),
|
|
}
|
|
|
|
// Add analysis metadata
|
|
contextNode.Metadata["analysis"] = analysis
|
|
contextNode.Metadata["purpose_confidence"] = purposeConf
|
|
contextNode.Metadata["role"] = role
|
|
|
|
// Cache the result
|
|
cacheEntry := &CacheEntry{
|
|
ContextNode: contextNode,
|
|
CreatedAt: time.Now(),
|
|
ExpiresAt: time.Now().Add(e.config.CacheTTL),
|
|
}
|
|
e.cache.Store(cacheKey, cacheEntry)
|
|
|
|
return contextNode, nil
|
|
}
|
|
|
|
// AnalyzeDirectory analyzes directory structure for hierarchical patterns
|
|
func (e *DefaultIntelligenceEngine) AnalyzeDirectory(ctx context.Context, dirPath string) ([]*slurpContext.ContextNode, error) {
|
|
start := time.Now()
|
|
defer func() {
|
|
e.updateStats("directory_analysis", time.Since(start), true)
|
|
}()
|
|
|
|
// Analyze directory structure
|
|
if _, err := e.directoryAnalyzer.AnalyzeStructure(ctx, dirPath); err != nil {
|
|
e.updateStats("directory_analysis", time.Since(start), false)
|
|
return nil, fmt.Errorf("failed to analyze directory structure: %w", err)
|
|
}
|
|
|
|
// Generate hierarchy with bounded depth
|
|
hierarchy, err := e.directoryAnalyzer.GenerateHierarchy(ctx, dirPath, 5) // Max 5 levels deep
|
|
if err != nil {
|
|
e.updateStats("directory_analysis", time.Since(start), false)
|
|
return nil, fmt.Errorf("failed to generate hierarchy: %w", err)
|
|
}
|
|
|
|
return hierarchy, nil
|
|
}
|
|
|
|
// GenerateRoleInsights generates role-specific insights for existing context
|
|
func (e *DefaultIntelligenceEngine) GenerateRoleInsights(ctx context.Context, baseContext *slurpContext.ContextNode, role string) ([]string, error) {
|
|
insights := []string{}
|
|
|
|
// Get role profile
|
|
profile, exists := e.roleProfiles[role]
|
|
if !exists {
|
|
// Generate generic insights
|
|
insights = append(insights, "Generic insight: Consider code quality and maintainability")
|
|
return insights, nil
|
|
}
|
|
|
|
// Generate role-specific insights based on profile
|
|
for _, insightType := range profile.InsightTypes {
|
|
switch insightType {
|
|
case "security":
|
|
insights = append(insights, "Security: Review for potential vulnerabilities and secure coding practices")
|
|
case "performance":
|
|
insights = append(insights, "Performance: Analyze for optimization opportunities and bottlenecks")
|
|
case "architecture":
|
|
insights = append(insights, "Architecture: Ensure alignment with system design patterns")
|
|
case "testing":
|
|
insights = append(insights, "Testing: Consider test coverage and quality assurance requirements")
|
|
case "ui_ux":
|
|
insights = append(insights, "UI/UX: Focus on user experience and interface design principles")
|
|
case "api_design":
|
|
insights = append(insights, "API Design: Ensure RESTful principles and proper error handling")
|
|
case "database":
|
|
insights = append(insights, "Database: Consider data modeling and query optimization")
|
|
case "deployment":
|
|
insights = append(insights, "Deployment: Plan for scalability and infrastructure requirements")
|
|
}
|
|
}
|
|
|
|
// Add context-specific insights if baseContext is provided
|
|
if baseContext != nil {
|
|
contextInsights := e.generateContextSpecificInsights(baseContext, role)
|
|
insights = append(insights, contextInsights...)
|
|
}
|
|
|
|
return insights, nil
|
|
}
|
|
|
|
// AssessGoalAlignment assesses how well context aligns with project goals
|
|
func (e *DefaultIntelligenceEngine) AssessGoalAlignment(ctx context.Context, node *slurpContext.ContextNode) (float64, error) {
|
|
if len(e.projectGoals) == 0 {
|
|
return 0.5, nil // Default alignment score when no goals defined
|
|
}
|
|
|
|
totalAlignment := 0.0
|
|
totalWeight := 0.0
|
|
|
|
for _, goal := range e.projectGoals {
|
|
alignment := e.calculateGoalAlignment(node, goal)
|
|
weight := float64(10 - goal.Priority) // Higher priority = higher weight
|
|
totalAlignment += alignment * weight
|
|
totalWeight += weight
|
|
}
|
|
|
|
if totalWeight == 0 {
|
|
return 0.5, nil
|
|
}
|
|
|
|
return totalAlignment / totalWeight, nil
|
|
}
|
|
|
|
// AnalyzeBatch processes multiple files efficiently in parallel
|
|
func (e *DefaultIntelligenceEngine) AnalyzeBatch(ctx context.Context, filePaths []string, role string) (map[string]*slurpContext.ContextNode, error) {
|
|
results := make(map[string]*slurpContext.ContextNode)
|
|
mu := sync.Mutex{}
|
|
wg := sync.WaitGroup{}
|
|
errorCh := make(chan error, len(filePaths))
|
|
|
|
// Limit concurrency
|
|
semaphore := make(chan struct{}, e.config.MaxConcurrentAnalysis)
|
|
|
|
for _, filePath := range filePaths {
|
|
wg.Add(1)
|
|
go func(path string) {
|
|
defer wg.Done()
|
|
semaphore <- struct{}{} // Acquire semaphore
|
|
defer func() { <-semaphore }() // Release semaphore
|
|
|
|
ctxNode, err := e.AnalyzeFile(ctx, path, role)
|
|
if err != nil {
|
|
errorCh <- fmt.Errorf("failed to analyze %s: %w", path, err)
|
|
return
|
|
}
|
|
|
|
mu.Lock()
|
|
results[path] = ctxNode
|
|
mu.Unlock()
|
|
}(filePath)
|
|
}
|
|
|
|
wg.Wait()
|
|
close(errorCh)
|
|
|
|
// Collect any errors
|
|
var errs []error
|
|
for err := range errorCh {
|
|
errs = append(errs, err)
|
|
}
|
|
|
|
if len(errs) > 0 {
|
|
return results, fmt.Errorf("batch analysis errors: %v", errs)
|
|
}
|
|
|
|
return results, nil
|
|
}
|
|
|
|
// DetectPatterns identifies recurring patterns across multiple contexts
|
|
func (e *DefaultIntelligenceEngine) DetectPatterns(ctx context.Context, contexts []*slurpContext.ContextNode) ([]*Pattern, error) {
|
|
patterns := []*Pattern{}
|
|
|
|
// Use pattern detector to find code patterns
|
|
for _, context := range contexts {
|
|
if context.Metadata["analysis"] != nil {
|
|
if analysis, ok := context.Metadata["analysis"].(*FileAnalysis); ok {
|
|
codePatterns, err := e.patternDetector.DetectCodePatterns(ctx, context.Path, []byte(analysis.FilePath))
|
|
if err == nil {
|
|
for _, cp := range codePatterns {
|
|
patterns = append(patterns, &cp.Pattern)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Detect naming patterns
|
|
namingPatterns, err := e.patternDetector.DetectNamingPatterns(ctx, contexts)
|
|
if err == nil {
|
|
for _, np := range namingPatterns {
|
|
patterns = append(patterns, &np.Pattern)
|
|
}
|
|
}
|
|
|
|
return patterns, nil
|
|
}
|
|
|
|
// EnhanceWithRAG enhances context using RAG system knowledge
|
|
func (e *DefaultIntelligenceEngine) EnhanceWithRAG(ctx context.Context, node *slurpContext.ContextNode) (*slurpContext.ContextNode, error) {
|
|
if !e.config.RAGEnabled {
|
|
return node, nil // Return unchanged if RAG is disabled
|
|
}
|
|
|
|
// Create query for RAG system
|
|
query := fmt.Sprintf("Provide insights for %s: %s", node.Purpose, node.Summary)
|
|
queryContext := map[string]interface{}{
|
|
"file_path": node.Path,
|
|
"technologies": node.Technologies,
|
|
"tags": node.Tags,
|
|
}
|
|
|
|
// Query RAG system
|
|
ragResponse, err := e.ragIntegration.Query(ctx, query, queryContext)
|
|
if err != nil {
|
|
return node, fmt.Errorf("RAG query failed: %w", err)
|
|
}
|
|
|
|
// Enhance context with RAG insights
|
|
enhanced := node.Clone()
|
|
if ragResponse.Confidence >= e.config.MinConfidenceThreshold {
|
|
enhanced.Insights = append(enhanced.Insights, fmt.Sprintf("RAG: %s", ragResponse.Answer))
|
|
enhanced.RAGConfidence = ragResponse.Confidence
|
|
|
|
// Add source information to metadata
|
|
if len(ragResponse.Sources) > 0 {
|
|
sources := make([]string, len(ragResponse.Sources))
|
|
for i, source := range ragResponse.Sources {
|
|
sources[i] = source.Title
|
|
}
|
|
enhanced.Metadata["rag_sources"] = sources
|
|
}
|
|
}
|
|
|
|
return enhanced, nil
|
|
}
|
|
|
|
// ValidateContext validates generated context quality and consistency
|
|
func (e *DefaultIntelligenceEngine) ValidateContext(ctx context.Context, node *slurpContext.ContextNode) (*ValidationResult, error) {
|
|
result := &ValidationResult{
|
|
Valid: true,
|
|
ConfidenceScore: 1.0,
|
|
QualityScore: 1.0,
|
|
Issues: []*ValidationIssue{},
|
|
Suggestions: []*Suggestion{},
|
|
ValidatedAt: time.Now(),
|
|
}
|
|
|
|
// Validate basic structure
|
|
if err := node.Validate(); err != nil {
|
|
result.Valid = false
|
|
result.Issues = append(result.Issues, &ValidationIssue{
|
|
Type: "structure",
|
|
Severity: "error",
|
|
Message: err.Error(),
|
|
Field: "context_node",
|
|
Suggestion: "Fix validation errors in context structure",
|
|
Impact: 0.8,
|
|
})
|
|
}
|
|
|
|
// Check quality thresholds
|
|
if node.RAGConfidence < e.config.MinConfidenceThreshold {
|
|
result.QualityScore *= 0.8
|
|
result.Suggestions = append(result.Suggestions, &Suggestion{
|
|
Type: "quality",
|
|
Title: "Low RAG confidence",
|
|
Description: "Consider enhancing context with additional analysis",
|
|
Confidence: 0.7,
|
|
Priority: 2,
|
|
Action: "re_analyze",
|
|
Impact: "medium",
|
|
})
|
|
}
|
|
|
|
// Validate content quality
|
|
if len(node.Summary) < 10 {
|
|
result.QualityScore *= 0.9
|
|
result.Issues = append(result.Issues, &ValidationIssue{
|
|
Type: "content",
|
|
Severity: "warning",
|
|
Message: "Summary too short",
|
|
Field: "summary",
|
|
Suggestion: "Provide more detailed summary",
|
|
Impact: 0.1,
|
|
})
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
// GetEngineStats returns engine performance and operational statistics
|
|
func (e *DefaultIntelligenceEngine) GetEngineStats() (*EngineStatistics, error) {
|
|
e.mu.RLock()
|
|
defer e.mu.RUnlock()
|
|
|
|
// Calculate cache hit rate
|
|
cacheSize := 0
|
|
e.cache.Range(func(key, value interface{}) bool {
|
|
cacheSize++
|
|
return true
|
|
})
|
|
|
|
stats := *e.stats // Copy current stats
|
|
stats.CacheHitRate = e.calculateCacheHitRate()
|
|
|
|
return &stats, nil
|
|
}
|
|
|
|
// SetConfiguration updates engine configuration
|
|
func (e *DefaultIntelligenceEngine) SetConfiguration(config *EngineConfig) error {
|
|
e.mu.Lock()
|
|
defer e.mu.Unlock()
|
|
|
|
if config == nil {
|
|
return fmt.Errorf("configuration cannot be nil")
|
|
}
|
|
|
|
e.config = config
|
|
e.projectGoals = config.ProjectGoals
|
|
e.roleProfiles = config.RoleProfiles
|
|
|
|
return nil
|
|
}
|
|
|
|
// Helper methods
|
|
|
|
// readFileContent reads and returns file content
|
|
func (e *DefaultIntelligenceEngine) readFileContent(filePath string) ([]byte, error) {
|
|
return ioutil.ReadFile(filePath)
|
|
}
|
|
|
|
// generateUCXLAddress generates a UCXL address for a file path
|
|
func (e *DefaultIntelligenceEngine) generateUCXLAddress(filePath string) (*ucxl.Address, error) {
|
|
// Simple implementation - in reality this would be more sophisticated
|
|
cleanPath := filepath.Clean(filePath)
|
|
addr, err := ucxl.Parse(fmt.Sprintf("file://%s", cleanPath))
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to generate UCXL address: %w", err)
|
|
}
|
|
return addr, nil
|
|
}
|
|
|
|
// generateFileTags generates tags based on file analysis and path
|
|
func (e *DefaultIntelligenceEngine) generateFileTags(analysis *FileAnalysis, filePath string) []string {
|
|
tags := []string{}
|
|
|
|
// Add language tag
|
|
if analysis.Language != "" {
|
|
tags = append(tags, analysis.Language)
|
|
}
|
|
|
|
// Add file type tag
|
|
if analysis.FileType != "" {
|
|
tags = append(tags, analysis.FileType)
|
|
}
|
|
|
|
// Add directory-based tags
|
|
dir := filepath.Dir(filePath)
|
|
dirName := filepath.Base(dir)
|
|
if dirName != "." && dirName != "/" {
|
|
tags = append(tags, "dir:"+dirName)
|
|
}
|
|
|
|
// Add complexity tag
|
|
if analysis.Complexity > 10 {
|
|
tags = append(tags, "high-complexity")
|
|
} else if analysis.Complexity > 5 {
|
|
tags = append(tags, "medium-complexity")
|
|
} else {
|
|
tags = append(tags, "low-complexity")
|
|
}
|
|
|
|
return tags
|
|
}
|
|
|
|
// calculateSpecificity calculates context specificity based on analysis
|
|
func (e *DefaultIntelligenceEngine) calculateSpecificity(analysis *FileAnalysis) int {
|
|
specificity := 1
|
|
|
|
// More specific if it has many functions/classes
|
|
if len(analysis.Functions) > 5 || len(analysis.Classes) > 3 {
|
|
specificity += 2
|
|
}
|
|
|
|
// More specific if it has dependencies
|
|
if len(analysis.Dependencies) > 0 {
|
|
specificity += 1
|
|
}
|
|
|
|
// More specific if it's complex
|
|
if analysis.Complexity > 10 {
|
|
specificity += 1
|
|
}
|
|
|
|
return specificity
|
|
}
|
|
|
|
// determineEncryptionRoles determines which roles can access this context
|
|
func (e *DefaultIntelligenceEngine) determineEncryptionRoles(role string, confidence float64) []string {
|
|
roles := []string{role}
|
|
|
|
// Add senior roles that can access everything
|
|
seniorRoles := []string{"senior_architect", "project_manager"}
|
|
for _, senior := range seniorRoles {
|
|
if senior != role {
|
|
roles = append(roles, senior)
|
|
}
|
|
}
|
|
|
|
// If high confidence, allow broader access
|
|
if confidence > 0.8 {
|
|
roles = append(roles, "*")
|
|
}
|
|
|
|
return roles
|
|
}
|
|
|
|
// determineAccessLevel determines the required access level for context
|
|
func (e *DefaultIntelligenceEngine) determineAccessLevel(analysis *FileAnalysis, role string) slurpContext.RoleAccessLevel {
|
|
// Default to low access
|
|
level := slurpContext.AccessLow
|
|
|
|
// Increase level based on content sensitivity
|
|
sensitive := false
|
|
for _, comment := range analysis.Comments {
|
|
if strings.Contains(strings.ToLower(comment), "password") ||
|
|
strings.Contains(strings.ToLower(comment), "secret") ||
|
|
strings.Contains(strings.ToLower(comment), "private") {
|
|
sensitive = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if sensitive {
|
|
level = slurpContext.AccessHigh
|
|
} else if len(analysis.Dependencies) > 5 {
|
|
level = slurpContext.AccessMedium
|
|
}
|
|
|
|
return level
|
|
}
|
|
|
|
// generateContextSpecificInsights generates insights specific to the provided context
|
|
func (e *DefaultIntelligenceEngine) generateContextSpecificInsights(context *slurpContext.ContextNode, role string) []string {
|
|
insights := []string{}
|
|
|
|
// Technology-specific insights
|
|
for _, tech := range context.Technologies {
|
|
switch strings.ToLower(tech) {
|
|
case "react", "vue", "angular":
|
|
insights = append(insights, fmt.Sprintf("Frontend: %s component requires testing for accessibility and responsiveness", tech))
|
|
case "go", "python", "java":
|
|
insights = append(insights, fmt.Sprintf("Backend: %s code should follow language-specific best practices", tech))
|
|
case "docker", "kubernetes":
|
|
insights = append(insights, fmt.Sprintf("Infrastructure: %s configuration needs security review", tech))
|
|
}
|
|
}
|
|
|
|
// Purpose-specific insights
|
|
if strings.Contains(strings.ToLower(context.Purpose), "api") {
|
|
insights = append(insights, "API: Consider rate limiting, authentication, and proper error responses")
|
|
}
|
|
if strings.Contains(strings.ToLower(context.Purpose), "database") {
|
|
insights = append(insights, "Database: Review for proper indexing and query optimization")
|
|
}
|
|
|
|
return insights
|
|
}
|
|
|
|
// calculateGoalAlignment calculates alignment score between context and goal
|
|
func (e *DefaultIntelligenceEngine) calculateGoalAlignment(node *slurpContext.ContextNode, goal *ProjectGoal) float64 {
|
|
score := 0.0
|
|
checks := 0.0
|
|
|
|
// Check keyword overlap
|
|
nodeText := strings.ToLower(node.Summary + " " + node.Purpose + " " + strings.Join(node.Technologies, " "))
|
|
for _, keyword := range goal.Keywords {
|
|
checks += 1.0
|
|
if strings.Contains(nodeText, strings.ToLower(keyword)) {
|
|
score += 1.0
|
|
}
|
|
}
|
|
|
|
// Check tag overlap
|
|
for _, tag := range node.Tags {
|
|
checks += 1.0
|
|
for _, keyword := range goal.Keywords {
|
|
if strings.Contains(strings.ToLower(tag), strings.ToLower(keyword)) {
|
|
score += 0.5
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
if checks == 0 {
|
|
return 0.5 // Default score when no keywords to check
|
|
}
|
|
|
|
return score / checks
|
|
}
|
|
|
|
// updateStats updates engine statistics
|
|
func (e *DefaultIntelligenceEngine) updateStats(operation string, duration time.Duration, success bool) {
|
|
e.mu.Lock()
|
|
defer e.mu.Unlock()
|
|
|
|
e.stats.TotalAnalyses++
|
|
if success {
|
|
e.stats.SuccessfulAnalyses++
|
|
} else {
|
|
e.stats.FailedAnalyses++
|
|
}
|
|
|
|
// Update average analysis time
|
|
if e.stats.TotalAnalyses == 1 {
|
|
e.stats.AverageAnalysisTime = duration
|
|
} else {
|
|
e.stats.AverageAnalysisTime = time.Duration(
|
|
(int64(e.stats.AverageAnalysisTime)*(e.stats.TotalAnalyses-1) + int64(duration)) / e.stats.TotalAnalyses,
|
|
)
|
|
}
|
|
|
|
// Update operation-specific stats
|
|
switch operation {
|
|
case "file_analysis":
|
|
e.stats.FilesAnalyzed++
|
|
case "directory_analysis":
|
|
e.stats.DirectoriesAnalyzed++
|
|
}
|
|
}
|
|
|
|
// calculateCacheHitRate calculates the current cache hit rate
|
|
func (e *DefaultIntelligenceEngine) calculateCacheHitRate() float64 {
|
|
return e.stats.CacheHitRate // This would be calculated from cache access stats in a real implementation
|
|
}
|
|
|
|
// DefaultEngineConfig returns default configuration for the intelligence engine
|
|
func DefaultEngineConfig() *EngineConfig {
|
|
return &EngineConfig{
|
|
MaxConcurrentAnalysis: 4,
|
|
AnalysisTimeout: 30 * time.Second,
|
|
MaxFileSize: 10 * 1024 * 1024, // 10MB
|
|
RAGEndpoint: "",
|
|
RAGTimeout: 10 * time.Second,
|
|
RAGEnabled: false,
|
|
EnableRAG: false,
|
|
EnableGoalAlignment: false,
|
|
EnablePatternDetection: false,
|
|
EnableRoleAware: false,
|
|
MinConfidenceThreshold: 0.6,
|
|
RequireValidation: true,
|
|
CacheEnabled: true,
|
|
CacheTTL: 1 * time.Hour,
|
|
RoleProfiles: make(map[string]*RoleProfile),
|
|
ProjectGoals: []*ProjectGoal{},
|
|
}
|
|
}
|