chore: align slurp config and scaffolding
This commit is contained in:
@@ -227,7 +227,7 @@ func (cau *ContentAnalysisUtils) extractGenericIdentifiers(content string) (func
|
||||
// CalculateComplexity calculates code complexity based on various metrics
|
||||
func (cau *ContentAnalysisUtils) CalculateComplexity(content, language string) float64 {
|
||||
complexity := 0.0
|
||||
|
||||
|
||||
// Lines of code (basic metric)
|
||||
lines := strings.Split(content, "\n")
|
||||
nonEmptyLines := 0
|
||||
@@ -236,26 +236,26 @@ func (cau *ContentAnalysisUtils) CalculateComplexity(content, language string) f
|
||||
nonEmptyLines++
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Base complexity from lines of code
|
||||
complexity += float64(nonEmptyLines) * 0.1
|
||||
|
||||
|
||||
// Control flow complexity (if, for, while, switch, etc.)
|
||||
controlFlowPatterns := []*regexp.Regexp{
|
||||
regexp.MustCompile(`\b(?:if|for|while|switch|case)\b`),
|
||||
regexp.MustCompile(`\b(?:try|catch|finally)\b`),
|
||||
regexp.MustCompile(`\?\s*.*\s*:`), // ternary operator
|
||||
}
|
||||
|
||||
|
||||
for _, pattern := range controlFlowPatterns {
|
||||
matches := pattern.FindAllString(content, -1)
|
||||
complexity += float64(len(matches)) * 0.5
|
||||
}
|
||||
|
||||
|
||||
// Function complexity
|
||||
functions, _, _ := cau.ExtractIdentifiers(content, language)
|
||||
complexity += float64(len(functions)) * 0.3
|
||||
|
||||
|
||||
// Nesting level (simple approximation)
|
||||
maxNesting := 0
|
||||
currentNesting := 0
|
||||
@@ -269,7 +269,7 @@ func (cau *ContentAnalysisUtils) CalculateComplexity(content, language string) f
|
||||
}
|
||||
}
|
||||
complexity += float64(maxNesting) * 0.2
|
||||
|
||||
|
||||
// Normalize to 0-10 scale
|
||||
return math.Min(10.0, complexity/10.0)
|
||||
}
|
||||
@@ -279,66 +279,66 @@ func (cau *ContentAnalysisUtils) DetectTechnologies(content, filename string) []
|
||||
technologies := []string{}
|
||||
lowerContent := strings.ToLower(content)
|
||||
ext := strings.ToLower(filepath.Ext(filename))
|
||||
|
||||
|
||||
// Language detection
|
||||
languageMap := map[string][]string{
|
||||
".go": {"go", "golang"},
|
||||
".py": {"python"},
|
||||
".js": {"javascript", "node.js"},
|
||||
".jsx": {"javascript", "react", "jsx"},
|
||||
".ts": {"typescript"},
|
||||
".tsx": {"typescript", "react", "jsx"},
|
||||
".java": {"java"},
|
||||
".kt": {"kotlin"},
|
||||
".rs": {"rust"},
|
||||
".cpp": {"c++"},
|
||||
".c": {"c"},
|
||||
".cs": {"c#", ".net"},
|
||||
".php": {"php"},
|
||||
".rb": {"ruby"},
|
||||
".go": {"go", "golang"},
|
||||
".py": {"python"},
|
||||
".js": {"javascript", "node.js"},
|
||||
".jsx": {"javascript", "react", "jsx"},
|
||||
".ts": {"typescript"},
|
||||
".tsx": {"typescript", "react", "jsx"},
|
||||
".java": {"java"},
|
||||
".kt": {"kotlin"},
|
||||
".rs": {"rust"},
|
||||
".cpp": {"c++"},
|
||||
".c": {"c"},
|
||||
".cs": {"c#", ".net"},
|
||||
".php": {"php"},
|
||||
".rb": {"ruby"},
|
||||
".swift": {"swift"},
|
||||
".scala": {"scala"},
|
||||
".clj": {"clojure"},
|
||||
".hs": {"haskell"},
|
||||
".ml": {"ocaml"},
|
||||
".clj": {"clojure"},
|
||||
".hs": {"haskell"},
|
||||
".ml": {"ocaml"},
|
||||
}
|
||||
|
||||
|
||||
if langs, exists := languageMap[ext]; exists {
|
||||
technologies = append(technologies, langs...)
|
||||
}
|
||||
|
||||
|
||||
// Framework and library detection
|
||||
frameworkPatterns := map[string][]string{
|
||||
"react": {"import.*react", "from [\"']react[\"']", "<.*/>", "jsx"},
|
||||
"vue": {"import.*vue", "from [\"']vue[\"']", "<template>", "vue"},
|
||||
"angular": {"import.*@angular", "from [\"']@angular", "ngmodule", "component"},
|
||||
"express": {"import.*express", "require.*express", "app.get", "app.post"},
|
||||
"django": {"from django", "import django", "django.db", "models.model"},
|
||||
"flask": {"from flask", "import flask", "@app.route", "flask.request"},
|
||||
"spring": {"@springboot", "@controller", "@service", "@repository"},
|
||||
"hibernate": {"@entity", "@table", "@column", "hibernate"},
|
||||
"jquery": {"$\\(", "jquery"},
|
||||
"bootstrap": {"bootstrap", "btn-", "col-", "row"},
|
||||
"docker": {"dockerfile", "docker-compose", "from.*:", "run.*"},
|
||||
"kubernetes": {"apiversion:", "kind:", "metadata:", "spec:"},
|
||||
"terraform": {"\\.tf$", "resource \"", "provider \"", "terraform"},
|
||||
"ansible": {"\\.yml$", "hosts:", "tasks:", "playbook"},
|
||||
"jenkins": {"jenkinsfile", "pipeline", "stage", "steps"},
|
||||
"git": {"\\.git", "git add", "git commit", "git push"},
|
||||
"mysql": {"mysql", "select.*from", "insert into", "create table"},
|
||||
"postgresql": {"postgresql", "postgres", "psql"},
|
||||
"mongodb": {"mongodb", "mongo", "find\\(", "insert\\("},
|
||||
"redis": {"redis", "set.*", "get.*", "rpush"},
|
||||
"elasticsearch": {"elasticsearch", "elastic", "query.*", "search.*"},
|
||||
"graphql": {"graphql", "query.*{", "mutation.*{", "subscription.*{"},
|
||||
"grpc": {"grpc", "proto", "service.*rpc", "\\.proto$"},
|
||||
"websocket": {"websocket", "ws://", "wss://", "socket.io"},
|
||||
"jwt": {"jwt", "jsonwebtoken", "bearer.*token"},
|
||||
"oauth": {"oauth", "oauth2", "client_id", "client_secret"},
|
||||
"ssl": {"ssl", "tls", "https", "certificate"},
|
||||
"encryption": {"encrypt", "decrypt", "bcrypt", "sha256"},
|
||||
"react": {"import.*react", "from [\"']react[\"']", "<.*/>", "jsx"},
|
||||
"vue": {"import.*vue", "from [\"']vue[\"']", "<template>", "vue"},
|
||||
"angular": {"import.*@angular", "from [\"']@angular", "ngmodule", "component"},
|
||||
"express": {"import.*express", "require.*express", "app.get", "app.post"},
|
||||
"django": {"from django", "import django", "django.db", "models.model"},
|
||||
"flask": {"from flask", "import flask", "@app.route", "flask.request"},
|
||||
"spring": {"@springboot", "@controller", "@service", "@repository"},
|
||||
"hibernate": {"@entity", "@table", "@column", "hibernate"},
|
||||
"jquery": {"$\\(", "jquery"},
|
||||
"bootstrap": {"bootstrap", "btn-", "col-", "row"},
|
||||
"docker": {"dockerfile", "docker-compose", "from.*:", "run.*"},
|
||||
"kubernetes": {"apiversion:", "kind:", "metadata:", "spec:"},
|
||||
"terraform": {"\\.tf$", "resource \"", "provider \"", "terraform"},
|
||||
"ansible": {"\\.yml$", "hosts:", "tasks:", "playbook"},
|
||||
"jenkins": {"jenkinsfile", "pipeline", "stage", "steps"},
|
||||
"git": {"\\.git", "git add", "git commit", "git push"},
|
||||
"mysql": {"mysql", "select.*from", "insert into", "create table"},
|
||||
"postgresql": {"postgresql", "postgres", "psql"},
|
||||
"mongodb": {"mongodb", "mongo", "find\\(", "insert\\("},
|
||||
"redis": {"redis", "set.*", "get.*", "rpush"},
|
||||
"elasticsearch": {"elasticsearch", "elastic", "query.*", "search.*"},
|
||||
"graphql": {"graphql", "query.*{", "mutation.*{", "subscription.*{"},
|
||||
"grpc": {"grpc", "proto", "service.*rpc", "\\.proto$"},
|
||||
"websocket": {"websocket", "ws://", "wss://", "socket.io"},
|
||||
"jwt": {"jwt", "jsonwebtoken", "bearer.*token"},
|
||||
"oauth": {"oauth", "oauth2", "client_id", "client_secret"},
|
||||
"ssl": {"ssl", "tls", "https", "certificate"},
|
||||
"encryption": {"encrypt", "decrypt", "bcrypt", "sha256"},
|
||||
}
|
||||
|
||||
|
||||
for tech, patterns := range frameworkPatterns {
|
||||
for _, pattern := range patterns {
|
||||
if matched, _ := regexp.MatchString(pattern, lowerContent); matched {
|
||||
@@ -347,7 +347,7 @@ func (cau *ContentAnalysisUtils) DetectTechnologies(content, filename string) []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return removeDuplicates(technologies)
|
||||
}
|
||||
|
||||
@@ -371,7 +371,7 @@ func (su *ScoreUtils) NormalizeScore(score, min, max float64) float64 {
|
||||
func (su *ScoreUtils) CalculateWeightedScore(scores map[string]float64, weights map[string]float64) float64 {
|
||||
totalWeight := 0.0
|
||||
weightedSum := 0.0
|
||||
|
||||
|
||||
for dimension, score := range scores {
|
||||
weight := weights[dimension]
|
||||
if weight == 0 {
|
||||
@@ -380,11 +380,11 @@ func (su *ScoreUtils) CalculateWeightedScore(scores map[string]float64, weights
|
||||
weightedSum += score * weight
|
||||
totalWeight += weight
|
||||
}
|
||||
|
||||
|
||||
if totalWeight == 0 {
|
||||
return 0.0
|
||||
}
|
||||
|
||||
|
||||
return weightedSum / totalWeight
|
||||
}
|
||||
|
||||
@@ -393,31 +393,31 @@ func (su *ScoreUtils) CalculatePercentile(values []float64, percentile int) floa
|
||||
if len(values) == 0 {
|
||||
return 0.0
|
||||
}
|
||||
|
||||
|
||||
sorted := make([]float64, len(values))
|
||||
copy(sorted, values)
|
||||
sort.Float64s(sorted)
|
||||
|
||||
|
||||
if percentile <= 0 {
|
||||
return sorted[0]
|
||||
}
|
||||
if percentile >= 100 {
|
||||
return sorted[len(sorted)-1]
|
||||
}
|
||||
|
||||
|
||||
index := float64(percentile) / 100.0 * float64(len(sorted)-1)
|
||||
lower := int(math.Floor(index))
|
||||
upper := int(math.Ceil(index))
|
||||
|
||||
|
||||
if lower == upper {
|
||||
return sorted[lower]
|
||||
}
|
||||
|
||||
|
||||
// Linear interpolation
|
||||
lowerValue := sorted[lower]
|
||||
upperValue := sorted[upper]
|
||||
weight := index - float64(lower)
|
||||
|
||||
|
||||
return lowerValue + weight*(upperValue-lowerValue)
|
||||
}
|
||||
|
||||
@@ -426,14 +426,14 @@ func (su *ScoreUtils) CalculateStandardDeviation(values []float64) float64 {
|
||||
if len(values) <= 1 {
|
||||
return 0.0
|
||||
}
|
||||
|
||||
|
||||
// Calculate mean
|
||||
sum := 0.0
|
||||
for _, value := range values {
|
||||
sum += value
|
||||
}
|
||||
mean := sum / float64(len(values))
|
||||
|
||||
|
||||
// Calculate variance
|
||||
variance := 0.0
|
||||
for _, value := range values {
|
||||
@@ -441,7 +441,7 @@ func (su *ScoreUtils) CalculateStandardDeviation(values []float64) float64 {
|
||||
variance += diff * diff
|
||||
}
|
||||
variance /= float64(len(values) - 1)
|
||||
|
||||
|
||||
return math.Sqrt(variance)
|
||||
}
|
||||
|
||||
@@ -510,41 +510,41 @@ func (su *StringUtils) Similarity(s1, s2 string) float64 {
|
||||
if s1 == s2 {
|
||||
return 1.0
|
||||
}
|
||||
|
||||
|
||||
words1 := strings.Fields(strings.ToLower(s1))
|
||||
words2 := strings.Fields(strings.ToLower(s2))
|
||||
|
||||
|
||||
if len(words1) == 0 && len(words2) == 0 {
|
||||
return 1.0
|
||||
}
|
||||
|
||||
|
||||
if len(words1) == 0 || len(words2) == 0 {
|
||||
return 0.0
|
||||
}
|
||||
|
||||
|
||||
set1 := make(map[string]bool)
|
||||
set2 := make(map[string]bool)
|
||||
|
||||
|
||||
for _, word := range words1 {
|
||||
set1[word] = true
|
||||
}
|
||||
for _, word := range words2 {
|
||||
set2[word] = true
|
||||
}
|
||||
|
||||
|
||||
intersection := 0
|
||||
for word := range set1 {
|
||||
if set2[word] {
|
||||
intersection++
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
union := len(set1) + len(set2) - intersection
|
||||
|
||||
|
||||
if union == 0 {
|
||||
return 1.0
|
||||
}
|
||||
|
||||
|
||||
return float64(intersection) / float64(union)
|
||||
}
|
||||
|
||||
@@ -565,35 +565,35 @@ func (su *StringUtils) ExtractKeywords(text string, minLength int) []string {
|
||||
"so": true, "than": true, "too": true, "very": true, "can": true, "could": true,
|
||||
"should": true, "would": true, "use": true, "used": true, "using": true,
|
||||
}
|
||||
|
||||
|
||||
// Extract words
|
||||
wordRegex := regexp.MustCompile(`\b[a-zA-Z]+\b`)
|
||||
words := wordRegex.FindAllString(strings.ToLower(text), -1)
|
||||
|
||||
|
||||
keywords := []string{}
|
||||
wordFreq := make(map[string]int)
|
||||
|
||||
|
||||
for _, word := range words {
|
||||
if len(word) >= minLength && !stopWords[word] {
|
||||
wordFreq[word]++
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Sort by frequency and return top keywords
|
||||
type wordCount struct {
|
||||
word string
|
||||
count int
|
||||
}
|
||||
|
||||
|
||||
var sortedWords []wordCount
|
||||
for word, count := range wordFreq {
|
||||
sortedWords = append(sortedWords, wordCount{word, count})
|
||||
}
|
||||
|
||||
|
||||
sort.Slice(sortedWords, func(i, j int) bool {
|
||||
return sortedWords[i].count > sortedWords[j].count
|
||||
})
|
||||
|
||||
|
||||
maxKeywords := 20
|
||||
for i, wc := range sortedWords {
|
||||
if i >= maxKeywords {
|
||||
@@ -601,7 +601,7 @@ func (su *StringUtils) ExtractKeywords(text string, minLength int) []string {
|
||||
}
|
||||
keywords = append(keywords, wc.word)
|
||||
}
|
||||
|
||||
|
||||
return keywords
|
||||
}
|
||||
|
||||
@@ -741,30 +741,58 @@ func CloneContextNode(node *slurpContext.ContextNode) *slurpContext.ContextNode
|
||||
}
|
||||
|
||||
clone := &slurpContext.ContextNode{
|
||||
Path: node.Path,
|
||||
Summary: node.Summary,
|
||||
Purpose: node.Purpose,
|
||||
Technologies: make([]string, len(node.Technologies)),
|
||||
Tags: make([]string, len(node.Tags)),
|
||||
Insights: make([]string, len(node.Insights)),
|
||||
CreatedAt: node.CreatedAt,
|
||||
UpdatedAt: node.UpdatedAt,
|
||||
ContextSpecificity: node.ContextSpecificity,
|
||||
RAGConfidence: node.RAGConfidence,
|
||||
ProcessedForRole: node.ProcessedForRole,
|
||||
Path: node.Path,
|
||||
UCXLAddress: node.UCXLAddress,
|
||||
Summary: node.Summary,
|
||||
Purpose: node.Purpose,
|
||||
Technologies: make([]string, len(node.Technologies)),
|
||||
Tags: make([]string, len(node.Tags)),
|
||||
Insights: make([]string, len(node.Insights)),
|
||||
OverridesParent: node.OverridesParent,
|
||||
ContextSpecificity: node.ContextSpecificity,
|
||||
AppliesToChildren: node.AppliesToChildren,
|
||||
AppliesTo: node.AppliesTo,
|
||||
GeneratedAt: node.GeneratedAt,
|
||||
UpdatedAt: node.UpdatedAt,
|
||||
CreatedBy: node.CreatedBy,
|
||||
WhoUpdated: node.WhoUpdated,
|
||||
RAGConfidence: node.RAGConfidence,
|
||||
EncryptedFor: make([]string, len(node.EncryptedFor)),
|
||||
AccessLevel: node.AccessLevel,
|
||||
}
|
||||
|
||||
copy(clone.Technologies, node.Technologies)
|
||||
copy(clone.Tags, node.Tags)
|
||||
copy(clone.Insights, node.Insights)
|
||||
copy(clone.EncryptedFor, node.EncryptedFor)
|
||||
|
||||
if node.RoleSpecificInsights != nil {
|
||||
clone.RoleSpecificInsights = make([]*RoleSpecificInsight, len(node.RoleSpecificInsights))
|
||||
copy(clone.RoleSpecificInsights, node.RoleSpecificInsights)
|
||||
if node.Parent != nil {
|
||||
parent := *node.Parent
|
||||
clone.Parent = &parent
|
||||
}
|
||||
if len(node.Children) > 0 {
|
||||
clone.Children = make([]string, len(node.Children))
|
||||
copy(clone.Children, node.Children)
|
||||
}
|
||||
if node.Language != nil {
|
||||
language := *node.Language
|
||||
clone.Language = &language
|
||||
}
|
||||
if node.Size != nil {
|
||||
sz := *node.Size
|
||||
clone.Size = &sz
|
||||
}
|
||||
if node.LastModified != nil {
|
||||
lm := *node.LastModified
|
||||
clone.LastModified = &lm
|
||||
}
|
||||
if node.ContentHash != nil {
|
||||
hash := *node.ContentHash
|
||||
clone.ContentHash = &hash
|
||||
}
|
||||
|
||||
if node.Metadata != nil {
|
||||
clone.Metadata = make(map[string]interface{})
|
||||
clone.Metadata = make(map[string]interface{}, len(node.Metadata))
|
||||
for k, v := range node.Metadata {
|
||||
clone.Metadata[k] = v
|
||||
}
|
||||
@@ -783,7 +811,7 @@ func MergeContextNodes(nodes ...*slurpContext.ContextNode) *slurpContext.Context
|
||||
}
|
||||
|
||||
merged := CloneContextNode(nodes[0])
|
||||
|
||||
|
||||
for i := 1; i < len(nodes); i++ {
|
||||
node := nodes[i]
|
||||
if node == nil {
|
||||
@@ -792,27 +820,29 @@ func MergeContextNodes(nodes ...*slurpContext.ContextNode) *slurpContext.Context
|
||||
|
||||
// Merge technologies
|
||||
merged.Technologies = mergeStringSlices(merged.Technologies, node.Technologies)
|
||||
|
||||
|
||||
// Merge tags
|
||||
merged.Tags = mergeStringSlices(merged.Tags, node.Tags)
|
||||
|
||||
|
||||
// Merge insights
|
||||
merged.Insights = mergeStringSlices(merged.Insights, node.Insights)
|
||||
|
||||
// Use most recent timestamps
|
||||
if node.CreatedAt.Before(merged.CreatedAt) {
|
||||
merged.CreatedAt = node.CreatedAt
|
||||
|
||||
// Use most relevant timestamps
|
||||
if merged.GeneratedAt.IsZero() {
|
||||
merged.GeneratedAt = node.GeneratedAt
|
||||
} else if !node.GeneratedAt.IsZero() && node.GeneratedAt.Before(merged.GeneratedAt) {
|
||||
merged.GeneratedAt = node.GeneratedAt
|
||||
}
|
||||
if node.UpdatedAt.After(merged.UpdatedAt) {
|
||||
merged.UpdatedAt = node.UpdatedAt
|
||||
}
|
||||
|
||||
|
||||
// Average context specificity
|
||||
merged.ContextSpecificity = (merged.ContextSpecificity + node.ContextSpecificity) / 2
|
||||
|
||||
|
||||
// Average RAG confidence
|
||||
merged.RAGConfidence = (merged.RAGConfidence + node.RAGConfidence) / 2
|
||||
|
||||
|
||||
// Merge metadata
|
||||
if node.Metadata != nil {
|
||||
if merged.Metadata == nil {
|
||||
@@ -844,7 +874,7 @@ func removeDuplicates(slice []string) []string {
|
||||
func mergeStringSlices(slice1, slice2 []string) []string {
|
||||
merged := make([]string, len(slice1))
|
||||
copy(merged, slice1)
|
||||
|
||||
|
||||
for _, item := range slice2 {
|
||||
found := false
|
||||
for _, existing := range merged {
|
||||
@@ -857,7 +887,7 @@ func mergeStringSlices(slice1, slice2 []string) []string {
|
||||
merged = append(merged, item)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return merged
|
||||
}
|
||||
|
||||
@@ -1034,4 +1064,4 @@ func (bu *ByteUtils) ReadFileWithLimit(filename string, maxSize int64) ([]byte,
|
||||
}
|
||||
|
||||
return io.ReadAll(file)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user