feat: obsidian-style graph view for wissens-vault
This commit is contained in:
@@ -3,6 +3,7 @@ Wiki in der Zentrale. Bewusst READ-ONLY — geschrieben wird der Vault nur vom T
|
||||
(und via Auftragsbuch-Entscheidungen); hier wird nur gelesen und navigiert."""
|
||||
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
@@ -90,3 +91,60 @@ def read_file(pfad: str) -> dict:
|
||||
raise
|
||||
except (ValueError, OSError):
|
||||
raise HTTPException(404, "Notiz nicht lesbar.")
|
||||
|
||||
|
||||
@router.get("/wissen/graph")
|
||||
def graph_vault() -> dict:
|
||||
"""Obsidian-artiger Graph des Vaults (Nodes = Dateien, Edges = Wiki-Links)."""
|
||||
if not _available():
|
||||
return {"nodes": [], "edges": []}
|
||||
|
||||
nodes = []
|
||||
edges = []
|
||||
# Für schnelle Link-Auflösung (case-insensitive Name -> relativer Pfad als ID)
|
||||
name_to_id = {}
|
||||
|
||||
# 1. Alle Nodes sammeln
|
||||
for p in VAULT.rglob("*.md"):
|
||||
if ".git" in p.parts:
|
||||
continue
|
||||
rel = p.relative_to(VAULT).as_posix()
|
||||
name_to_id[p.stem.lower()] = rel
|
||||
|
||||
# Kategorie aus dem Ordner ableiten
|
||||
cat = "knowledge"
|
||||
parent = p.parent.name if p.parent != VAULT else ""
|
||||
if parent == "traeume":
|
||||
cat = "events"
|
||||
elif parent == "muster":
|
||||
cat = "rules"
|
||||
elif parent == "skill-kandidaten":
|
||||
cat = "identity"
|
||||
|
||||
nodes.append({
|
||||
"id": rel,
|
||||
"label": p.stem, # stem ist oft kürzer/prägnanter als der Titel
|
||||
"category": cat
|
||||
})
|
||||
|
||||
# 2. Edges extrahieren (Wiki-Links [[Name]])
|
||||
link_rx = re.compile(r"\[\[([^\]]+)\]\]")
|
||||
for n in nodes:
|
||||
try:
|
||||
target = VAULT / n["id"]
|
||||
content = target.read_text(encoding="utf-8", errors="replace")
|
||||
# Set, um mehrfache Links auf dieselbe Datei zu entduplizieren
|
||||
found_links = set(m.group(1).strip().lower() for m in link_rx.finditer(content))
|
||||
|
||||
for link in found_links:
|
||||
target_id = name_to_id.get(link)
|
||||
if target_id and target_id != n["id"]:
|
||||
edges.append({
|
||||
"source": n["id"],
|
||||
"target": target_id,
|
||||
"weight": 1.0
|
||||
})
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
return {"nodes": nodes, "edges": edges}
|
||||
|
||||
Reference in New Issue
Block a user