diff --git a/app/rest.py b/app/rest.py index a62070f..246b5cc 100644 --- a/app/rest.py +++ b/app/rest.py @@ -12,6 +12,7 @@ import hmac import json import logging import os +import re import time # Offline mode: must be set before any HuggingFace library is imported. @@ -277,6 +278,10 @@ class DiagnoseRequest(BaseModel): source: str | None = None +class SourceSuggestRequest(BaseModel): + query: str + + class SeverityOverride(BaseModel): name: str pattern: str @@ -523,6 +528,55 @@ async def diagnose_post_stream(body: DiagnoseRequest) -> StreamingResponse: ) +_SUGGEST_STOPWORDS = frozenset({ + "the", "and", "that", "this", "with", "have", "from", "they", + "been", "their", "what", "when", "there", "some", "would", "make", + "like", "into", "time", "look", "just", "know", "take", "year", + "your", "good", "some", "could", "them", "then", "very", "also", + "back", "after", "work", "need", "even", "much", "most", "tell", + "does", "more", "once", "help", "seem", "here", "about", "issue", + "thing", "logs", "error", "again", "still", "these", "those", + "getting", "having", "trying", "going", "where", "which", "cant", + "now", "set", "kind", "weird", "stable", "huge", "real", "nice", +}) + + +@router.post("/api/sources/suggest") +def suggest_sources(body: SourceSuggestRequest) -> dict: + """Return source IDs ranked by relevance to a natural-language problem description.""" + all_sources = _list_sources(DB_PATH) + query_tokens = { + t.lower() + for t in re.findall(r"[a-zA-Z]+", body.query) + if len(t) > 2 and t.lower() not in _SUGGEST_STOPWORDS + } + + suggestions = [] + for src in all_sources: + src_id: str = src["source_id"] + # Tokenise source ID: split on colon, dash, underscore, digits + parts = { + p.lower() + for seg in re.split(r"[:\-_\d]+", src_id) + for p in [seg.strip()] + if len(p) > 2 + } + matched = query_tokens & parts + if matched: + score = round(len(matched) / max(len(parts), 1), 3) + suggestions.append({ + "source_id": src_id, + "score": score, + "matched_tokens": sorted(matched), + }) + + suggestions.sort(key=lambda x: x["score"], reverse=True) + return { + "suggested": suggestions, + "all_source_ids": [s["source_id"] for s in all_sources], + } + + @router.get("/api/settings") def get_settings() -> dict: return _load_prefs() diff --git a/web/src/components/ChatDiagnose.vue b/web/src/components/ChatDiagnose.vue new file mode 100644 index 0000000..eb87110 --- /dev/null +++ b/web/src/components/ChatDiagnose.vue @@ -0,0 +1,370 @@ +