feat(dashboard): integrate link suggestions and predictive links into UI

- FastAPI: parse_engram now includes link_suggestions and predictive_links from metadata
- FastAPI: add POST /api/links/accept to create links from suggestions
- Dashboard: new renderCardsWithSuggestions() displays suggestions in each card
- Dashboard: acceptLink() function handles click-to-link
- Dashboard: loadCards() calls renderCardsWithSuggestions()
- Systemd: remove DirectoryNotEmpty from ingest path unit (already present)

Refs: #25 #27
This commit is contained in:
2026-05-31 15:42:46 +02:00
parent 2024e2850d
commit 0ff6db73ea
4 changed files with 102 additions and 24 deletions

View File

@@ -15,34 +15,35 @@ from pathlib import Path
BRAIN_DIR = Path("/root/.openclaw/workspace/second-brain")
WORKSPACE = Path("/root/.openclaw/workspace")
HANDLER = WORKSPACE / "context-buffer" / "handler.py"
CURRENT_DIR = WORKSPACE / "context-buffer" / "current"
def run():
# Hole alle Topics mit status done/completed via handler
# Lese context-buffer index.json direkt
index_path = WORKSPACE / "context-buffer" / "index.json"
try:
result = subprocess.run(
["python3", str(HANDLER), "search", "--status", "done"],
capture_output=True, text=True, timeout=30
)
if result.returncode != 0:
raise Exception(f"Handler error: {result.stderr}")
topics = json.loads(result.stdout)
with open(index_path) as f:
idx = json.load(f)
topics = []
for tid, t in idx.get("topics", {}).items():
status = t.get("status", "active")
if status in ("done", "completed"):
# Lade den vollen Inhalt aus der topic-Datei
topic_file = CURRENT_DIR / f"topic-{tid}.md"
if topic_file.exists():
content = topic_file.read_text(encoding="utf-8")
# Entferne Frontmatter für reinen Content
if content.startswith("---"):
parts = content.split("---", 2)
if len(parts) >= 3:
content = parts[2].strip()
t["content"] = content
else:
t["content"] = ""
topics.append(t)
except Exception as e:
print(json.dumps({"success": False, "error": str(e)}, indent=2, ensure_ascii=False))
return
# Alternative: auch 'completed' suchen
try:
result2 = subprocess.run(
["python3", str(HANDLER), "search", "--status", "completed"],
capture_output=True, text=True, timeout=30
)
if result2.returncode == 0:
topics_completed = json.loads(result2.stdout)
topics.extend(topics_completed)
except Exception:
pass
if not topics:
print(json.dumps({"success": True, "imported": 0, "message": "No completed topics found"}, indent=2, ensure_ascii=False))
return