diff --git a/src-tauri/src/knowledge.rs b/src-tauri/src/knowledge.rs index 5d5ff3d..edfb750 100644 --- a/src-tauri/src/knowledge.rs +++ b/src-tauri/src/knowledge.rs @@ -620,23 +620,59 @@ async fn search_knowledge_filtered(search_query: &str, limit: usize, project: &O return Ok(String::new()); } - // Relevanz-Schwelle: Ergebnisse mit zu niedrigem Score rausfiltern. - // MySQL FULLTEXT NATURAL LANGUAGE MODE gibt Scores > 0 zurück, - // aber generische Einzel-Wort-Treffer haben oft Score < 2. + // === Filter-Pipeline: generische Referenz-Einträge raus === + + // 1. Kategorien die als Hints keinen Wert haben (Referenzdaten, Config-Backups) + const EXCLUDED_CATEGORIES: &[&str] = &[ + "setup", "access", "claude-md", "skill", "slash-command", "hook", + ]; + + // 2. Relevanz-Schwelle let min_relevance = 1.5; - let relevant: Vec<_> = results.into_iter() - .filter(|(_, _, _, _, _, _, relevance)| *relevance >= min_relevance) + + // 3. Basis-Filter: Relevanz + Kategorie + let base_filtered: Vec<_> = results.into_iter() + .filter(|(_, category, _, _, _, _, relevance)| { + if *relevance < min_relevance { return false; } + if EXCLUDED_CATEGORIES.contains(&category.as_str()) { return false; } + true + }) .collect(); - if relevant.is_empty() { - println!("🔍 Keine Hints über Relevanz-Schwelle ({:.1})", min_relevance); + if base_filtered.is_empty() { + println!("🔍 Keine Hints über Relevanz-Schwelle ({:.1}) nach Kategorie-Filter", min_relevance); return Ok(String::new()); } + // 4. Projekt-Filter: wenn Projekt erkannt, bevorzuge Einträge mit passendem Tag. + // Fallback auf base_filtered wenn Projekt-Filter alles wegfiltert. + let filtered_results = if let Some(ref proj) = project { + let proj_lower = proj.to_lowercase(); + let proj_filtered: Vec<_> = base_filtered.iter() + .filter(|(_, _, _, _, tags, _, _)| { + if let Some(ref t) = tags { + t.to_lowercase().contains(&proj_lower) + } else { + false + } + }) + .cloned() + .collect(); + if proj_filtered.is_empty() { + println!("🔍 Projekt-Filter '{}' ergab 0 Treffer, Fallback auf {} Basis-Treffer", proj, base_filtered.len()); + base_filtered + } else { + println!("🔍 Projekt-Filter '{}': {} von {} Treffern", proj, proj_filtered.len(), base_filtered.len()); + proj_filtered + } + } else { + base_filtered + }; + // Bereits gezeigte IDs filtern let filtered: Vec<_> = { let topic = SESSION_TOPIC.lock().unwrap(); - relevant.into_iter() + filtered_results.into_iter() .filter(|(id, _, _, _, _, _, _)| !topic.shown_ids.contains(id)) .take(limit) .collect()