- 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
104 lines
3.2 KiB
Python
104 lines
3.2 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Importiert abgeschlossene Topics aus context-buffer/ als Engramme.
|
|
Ein Topic gilt als abgeschlossen, wenn es den Status 'done' oder 'completed' hat.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import sqlite3
|
|
import subprocess
|
|
import sys
|
|
from datetime import datetime, timezone
|
|
from pathlib import Path
|
|
|
|
BRAIN_DIR = Path("/root/.openclaw/workspace/second-brain")
|
|
WORKSPACE = Path("/root/.openclaw/workspace")
|
|
CURRENT_DIR = WORKSPACE / "context-buffer" / "current"
|
|
|
|
def run():
|
|
# Lese context-buffer index.json direkt
|
|
index_path = WORKSPACE / "context-buffer" / "index.json"
|
|
try:
|
|
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
|
|
|
|
if not topics:
|
|
print(json.dumps({"success": True, "imported": 0, "message": "No completed topics found"}, indent=2, ensure_ascii=False))
|
|
return
|
|
|
|
# Import in Second Brain
|
|
DB_PATH = BRAIN_DIR / "data" / "brain.sqlite"
|
|
conn = sqlite3.connect(str(DB_PATH))
|
|
conn.row_factory = sqlite3.Row
|
|
c = conn.cursor()
|
|
|
|
sys.path.insert(0, str(BRAIN_DIR))
|
|
from src.store import EngramStore
|
|
from src.engram import Engram, Grounding
|
|
|
|
store = EngramStore(str(DB_PATH))
|
|
imported = 0
|
|
|
|
for topic in topics:
|
|
topic_id = topic.get("id")
|
|
title = topic.get("title", "Untitled Topic")
|
|
content = topic.get("content", "")
|
|
if not content.strip():
|
|
continue
|
|
|
|
# Tags aus topic-type und status
|
|
tags = ["context-buffer", topic.get("status", "unknown")]
|
|
if topic.get("type"):
|
|
tags.append(topic["type"])
|
|
|
|
eg = Engram.create(
|
|
content=content,
|
|
source="context-buffer",
|
|
tags=tags,
|
|
grounding=Grounding.ASSUMPTION,
|
|
)
|
|
eg.metadata.update({
|
|
"title": title,
|
|
"context_buffer_id": topic_id,
|
|
"imported_from": "context-buffer",
|
|
"original_status": topic.get("status"),
|
|
})
|
|
store.save(eg)
|
|
imported += 1
|
|
|
|
conn.close()
|
|
|
|
print(json.dumps({
|
|
"success": True,
|
|
"time": datetime.now(timezone.utc).isoformat(),
|
|
"topics_found": len(topics),
|
|
"imported": imported,
|
|
}, indent=2, ensure_ascii=False))
|
|
|
|
if __name__ == "__main__":
|
|
import sys
|
|
sys.path.insert(0, str(BRAIN_DIR))
|
|
run()
|