@@ -30,7 +30,7 @@ func NewTagSearchStrategy(repo ToolRepository, descriptionWeight float64) *TagSe
3030// SearchTools returns tools ordered by relevance to the query, using explicit tags and description keywords.
3131func (s * TagSearchStrategy ) SearchTools (ctx context.Context , query string , limit int ) ([]Tool , error ) {
3232 // Normalize query
33- queryLower := strings .ToLower (query )
33+ queryLower := strings .ToLower (strings . TrimSpace ( query ) )
3434 words := s .wordRegex .FindAllString (queryLower , - 1 )
3535 queryWordSet := make (map [string ]struct {}, len (words ))
3636 for _ , w := range words {
@@ -43,57 +43,74 @@ func (s *TagSearchStrategy) SearchTools(ctx context.Context, query string, limit
4343 return nil , err
4444 }
4545
46- // SUTCP each tool
47- type sUTCPdTool struct {
48- t Tool
49- sUTCP float64
46+ // Compute SUTCP score for each tool
47+ type scoredTool struct {
48+ tool Tool
49+ score float64
5050 }
51- var sUTCPd []sUTCPdTool
51+ var scored []scoredTool
52+
5253 for _ , t := range tools {
53- var sUTCP float64
54+ var score float64
5455
55- // SUTCP from tags
56+ // Match against tags
5657 for _ , tag := range t .Tags {
5758 tagLower := strings .ToLower (tag )
59+
60+ // Direct substring match
5861 if strings .Contains (queryLower , tagLower ) {
59- sUTCP += 1.0
62+ score += 1.0
6063 }
61- // Partial matches on tag words
64+
65+ // Word-level overlap
6266 tagWords := s .wordRegex .FindAllString (tagLower , - 1 )
6367 for _ , w := range tagWords {
6468 if _ , ok := queryWordSet [w ]; ok {
65- sUTCP += s .descriptionWeight
69+ score += s .descriptionWeight
6670 }
6771 }
6872 }
6973
70- // SUTCP from description
74+ // Match against description
7175 if t .Description != "" {
7276 descWords := s .wordRegex .FindAllString (strings .ToLower (t .Description ), - 1 )
7377 for _ , w := range descWords {
7478 if len (w ) > 2 {
7579 if _ , ok := queryWordSet [w ]; ok {
76- sUTCP += s .descriptionWeight
80+ score += s .descriptionWeight
7781 }
7882 }
7983 }
8084 }
8185
82- sUTCPd = append (sUTCPd , sUTCPdTool { t : t , sUTCP : sUTCP })
86+ scored = append (scored , scoredTool { tool : t , score : score })
8387 }
8488
85- // Sort by descending sUTCP
86- sort .Slice (sUTCPd , func (i , j int ) bool {
87- return sUTCPd [i ].sUTCP > sUTCPd [j ].sUTCP
89+ // Sort descending by score
90+ sort .Slice (scored , func (i , j int ) bool {
91+ return scored [i ].score > scored [j ].score
8892 })
8993
90- // Return up to limit
94+ // Collect only positive matches
9195 var result []Tool
92- for i , st := range sUTCPd {
93- if i >= limit {
94- break
96+ for _ , st := range scored {
97+ if st .score > 0 {
98+ result = append (result , st .tool )
99+ if len (result ) >= limit {
100+ break
101+ }
95102 }
96- result = append (result , st .t )
97103 }
104+
105+ // If no matches, fallback to top N (for discoverability)
106+ if len (result ) == 0 && len (scored ) > 0 {
107+ for i , st := range scored {
108+ if i >= limit {
109+ break
110+ }
111+ result = append (result , st .tool )
112+ }
113+ }
114+
98115 return result , nil
99116}
0 commit comments