diff --git a/app/frontend/ui.py b/app/frontend/ui.py index d3e714b..adb7cdc 100644 --- a/app/frontend/ui.py +++ b/app/frontend/ui.py @@ -14,6 +14,8 @@ load_dotenv() API_BASE_URL = os.getenv("MINDNET_API_URL", "http://localhost:8002") CHAT_ENDPOINT = f"{API_BASE_URL}/chat" FEEDBACK_ENDPOINT = f"{API_BASE_URL}/feedback" +INGEST_ANALYZE_ENDPOINT = f"{API_BASE_URL}/ingest/analyze" +INGEST_SAVE_ENDPOINT = f"{API_BASE_URL}/ingest/save" HISTORY_FILE = Path("data/logs/search_history.jsonl") # Timeout Strategy @@ -52,10 +54,13 @@ st.markdown(""" font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif; } - .debug-info { - font-size: 0.7rem; - color: #888; - margin-bottom: 5px; + .suggestion-card { + border-left: 3px solid #1a73e8; + background-color: #ffffff; + padding: 10px; + margin-bottom: 8px; + border-radius: 4px; + box-shadow: 0 1px 3px rgba(0,0,0,0.1); } """, unsafe_allow_html=True) @@ -67,20 +72,14 @@ if "user_id" not in st.session_state: st.session_state.user_id = str(uuid.uuid4( # --- HELPER FUNCTIONS --- def normalize_meta_and_body(meta, body): - """ - Sanitizer: Stellt sicher, dass nur erlaubte Felder im Frontmatter bleiben. - Alles andere wird in den Body verschoben (Repair-Strategie). - """ + """Sanitizer: Stellt sicher, dass nur erlaubte Felder im Frontmatter bleiben.""" ALLOWED_KEYS = {"title", "type", "status", "tags", "id", "created", "updated", "aliases", "lang"} - clean_meta = {} extra_content = [] - # 1. Title/Titel Normalisierung if "titel" in meta and "title" not in meta: meta["title"] = meta.pop("titel") - # 2. Tags Normalisierung (Synonyme) tag_candidates = ["tags", "emotionale_keywords", "keywords", "schluesselwoerter"] all_tags = [] for key in tag_candidates: @@ -89,14 +88,12 @@ def normalize_meta_and_body(meta, body): if isinstance(val, list): all_tags.extend(val) elif isinstance(val, str): all_tags.extend([t.strip() for t in val.split(",")]) - # 3. Filterung und Verschiebung for key, val in meta.items(): if key in ALLOWED_KEYS: clean_meta[key] = val elif key in tag_candidates: - pass # Schon oben behandelt + pass else: - # Unerlaubtes Feld (z.B. 'situation') -> Ab in den Body! if val and isinstance(val, str): header = key.replace("_", " ").title() extra_content.append(f"## {header}\n{val}\n") @@ -104,7 +101,6 @@ def normalize_meta_and_body(meta, body): if all_tags: clean_meta["tags"] = list(set(all_tags)) - # 4. Body Zusammenbau if extra_content: new_section = "\n".join(extra_content) final_body = f"{new_section}\n{body}" @@ -114,18 +110,14 @@ def normalize_meta_and_body(meta, body): return clean_meta, final_body def parse_markdown_draft(full_text): - """ - Robustes Parsing + Sanitization. - """ + """Robustes Parsing + Sanitization.""" clean_text = full_text - # Codeblock entfernen pattern_block = r"```(?:markdown|md)?\s*(.*?)\s*```" match_block = re.search(pattern_block, full_text, re.DOTALL | re.IGNORECASE) if match_block: clean_text = match_block.group(1).strip() - # Frontmatter splitten parts = re.split(r"^---+\s*$", clean_text, maxsplit=2, flags=re.MULTILINE) meta = {} @@ -152,7 +144,6 @@ def build_markdown_doc(meta, body): meta["updated"] = datetime.now().strftime("%Y-%m-%d") - # Sortierung für UX ordered_meta = {} prio_keys = ["id", "type", "title", "status", "tags"] for k in prio_keys: @@ -183,6 +174,8 @@ def load_history_from_logs(limit=10): except: pass return queries +# --- API CLIENT --- + def send_chat_message(message: str, top_k: int, explain: bool): try: response = requests.post( @@ -195,6 +188,32 @@ def send_chat_message(message: str, top_k: int, explain: bool): except Exception as e: return {"error": str(e)} +def analyze_draft_text(text: str, n_type: str): + """Ruft den neuen Intelligence-Service (WP-11) auf.""" + try: + response = requests.post( + INGEST_ANALYZE_ENDPOINT, + json={"text": text, "type": n_type}, + timeout=10 + ) + response.raise_for_status() + return response.json() + except Exception as e: + return {"error": str(e)} + +def save_draft_to_vault(markdown_content: str, filename: str = None): + """Ruft den neuen Persistence-Service (WP-11) auf.""" + try: + response = requests.post( + INGEST_SAVE_ENDPOINT, + json={"markdown_content": markdown_content, "filename": filename}, + timeout=30 # Indizierung kann dauern + ) + response.raise_for_status() + return response.json() + except Exception as e: + return {"error": str(e)} + def submit_feedback(query_id, node_id, score, comment=None): try: requests.post(FEEDBACK_ENDPOINT, json={"query_id": query_id, "node_id": node_id, "score": score, "comment": comment}, timeout=2) @@ -230,15 +249,14 @@ def render_draft_editor(msg): st.session_state[f"{key_base}_type"] = meta.get("type", "default") st.session_state[f"{key_base}_title"] = meta.get("title", "") - tags_raw = meta.get("tags", []) st.session_state[f"{key_base}_tags"] = ", ".join(tags_raw) if isinstance(tags_raw, list) else str(tags_raw) - st.session_state[f"{key_base}_body"] = body.strip() st.session_state[f"{key_base}_meta"] = meta + st.session_state[f"{key_base}_suggestions"] = [] st.session_state[f"{key_base}_init"] = True - # 2. UI + # 2. UI Layout st.markdown(f'
{sugg['suggested_markdown']}
+