@@ -220,9 +220,7 @@ func (t *SmartSearchTool) buildResponseMeta(meta searchMetadata, useCompact bool
220220 }
221221
222222 if isFallback {
223- fallbackNote := "⚡ NOTE: These results are from a fast AST-based fallback search (no vector index available yet). " +
224- "Indexing is running in the background — subsequent searches will use semantic vector matching for better accuracy. " +
225- "Current results are based on lexical/structural matching and may miss semantically related code."
223+ fallbackNote := buildFallbackNote (idxProgress )
226224 if response .Warning != "" {
227225 response .Warning += " | " + fallbackNote
228226 } else {
@@ -233,6 +231,50 @@ func (t *SmartSearchTool) buildResponseMeta(meta searchMetadata, useCompact bool
233231 return response
234232}
235233
234+ // buildFallbackNote constructs a dynamic fallback warning that includes
235+ // live indexing progress data (per-language %, elapsed, ready languages).
236+ func buildFallbackNote (progress * IndexingProgressSummary ) string {
237+ var sb strings.Builder
238+ sb .WriteString ("⚡ Fallback results (AST/lexical, not vector). " )
239+
240+ if progress != nil && progress .Elapsed != "" && progress .Elapsed != "0s" {
241+ sb .WriteString (fmt .Sprintf ("Indexing elapsed: %s. " , progress .Elapsed ))
242+ }
243+
244+ // Report per-language progress and collect fully-indexed langs
245+ var readyLangs []string
246+ if progress != nil && len (progress .Languages ) > 0 {
247+ sb .WriteString ("Progress: " )
248+ first := true
249+ for lang , lp := range progress .Languages {
250+ if lp .TotalFiles == 0 {
251+ continue
252+ }
253+ if ! first {
254+ sb .WriteString (" · " )
255+ }
256+ sb .WriteString (fmt .Sprintf ("%s %d%%" , lang , lp .Percent ))
257+ if lp .Percent == 100 {
258+ sb .WriteString (" ✓" )
259+ readyLangs = append (readyLangs , lang )
260+ }
261+ first = false
262+ }
263+ sb .WriteString (". " )
264+ }
265+
266+ // Actionable hint: tell agent which langs can use vector search now
267+ if len (readyLangs ) > 0 {
268+ sb .WriteString (fmt .Sprintf ("Vector search ready for: %s — retry for higher-quality results on those files. " ,
269+ strings .Join (readyLangs , ", " )))
270+ } else {
271+ sb .WriteString ("Indexing in background — retry shortly for semantic vector results. " )
272+ }
273+
274+ sb .WriteString ("Current results may miss semantically related code." )
275+ return sb .String ()
276+ }
277+
236278// ─── Result Serialization ────────────────────────────────────────────────────
237279
238280// resultToMap converts a mergedResult to the output map format.
0 commit comments