Skip to content

Commit 3f60866

Browse files
author
razvan
committed
feat(search): dynamic fallback message with live indexing progress (#3)
Replace static fallback warning with buildFallbackNote() that includes: - Elapsed indexing time - Per-language progress (go 100% ✓ · python 12%) - Actionable hint: which languages have vector search ready to retry
1 parent 771a034 commit 3f60866

1 file changed

Lines changed: 45 additions & 3 deletions

File tree

internal/service/tools/smart_search_pipeline.go

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)