#!/usr/bin/env python3 """ proactive_search.py - Proaktive Websuche für Second Brain. Sucht relevante Themen, speichert Ergebnisse als Engramme. Stoppt wenn neue Aufgaben erkannt werden. """ import sys import json from pathlib import Path from datetime import datetime, timezone, timedelta from typing import List, Dict, Any, Optional sys.path.insert(0, str(Path(__file__).resolve().parent)) from src.store import EngramStore from src.engram import Engram, Grounding from src.retriever import Retriever from src.embedder import encode from src.chroma_store import ChromaStore DB_PATH = Path(__file__).resolve().parent.parent / "data" / "brain.sqlite" CHROMA_PATH = Path(__file__).resolve().parent.parent / "data" / "chroma" # Themen die relevant sind für den Benutzer INTEREST_TOPICS = [ "OpenClaw AI Agent", "Künstliche Intelligenz Trends 2025", "Second Brain Memory System", "Automation DIY Projects", "Smart Home IoT", "Raspberry Pi Projects", "Deutschland Tech News", "AI Agent Frameworks", "Workflow Automation", ] def get_store(): return EngramStore(str(DB_PATH)) def load_state() -> Dict[str, Any]: """Lädt den Such-Zustand.""" state_path = Path(__file__).resolve().parent.parent / "data" / "search_state.json" if state_path.exists(): with open(state_path, "r", encoding="utf-8") as f: return json.load(f) return { "last_search": None, "searched_topics": [], "new_tasks_detected": False, "paused_until": None, } def save_state(state: Dict[str, Any]): state_path = Path(__file__).resolve().parent.parent / "data" / "search_state.json" with open(state_path, "w", encoding="utf-8") as f: json.dump(state, f, ensure_ascii=False) def check_for_new_tasks(store: EngramStore) -> bool: """Prüft ob in letzten 2h neue Aufgaben-Artige Engramme erstellt wurden.""" now = datetime.now(timezone.utc) recent = now - timedelta(hours=2) egs = store.get_all(limit=1000) for eg in egs: created_str = eg.metadata.get("created", "") if not created_str: continue try: eg_time = datetime.fromisoformat(created_str) if eg_time.tzinfo is None: eg_time = eg_time.replace(tzinfo=timezone.utc) if eg_time > recent: tags = eg.metadata.get("tags", []) if "task" in tags or "aufgabe" in tags or "todo" in tags: return True except Exception: pass return False def try_web_search(topic: str) -> Optional[List[Dict[str, str]]]: """Web-Suche via OpenClaw.""" try: import subprocess result = subprocess.run( ["python3", "-c", f""" import sys sys.path.insert(0, '/root/.openclaw/workspace/second-brain/src') from src.retriever import Retriever from src.store import EngramStore store = EngramStore('data/brain.sqlite') ret = Retriever(store) results = ret.retrieve('{topic}') print('FOUND ' + str(len(results))) """], capture_output=True, text=True, timeout=30, cwd="/root/.openclaw/workspace/second-brain", ) # Actually do web search print(f"[search] Would search: {topic}") return None # Placeholder: real search would be here except Exception as e: print(f"[search] Error: {e}") return None def run_proactive_search(): """Haupt-Funktion für proaktive Suche.""" store = get_store() state = load_state() now = datetime.now(timezone.utc) # Check: Neue Aufgaben? if check_for_new_tasks(store): state["new_tasks_detected"] = True state["paused_until"] = (now + timedelta(hours=4)).isoformat() save_state(state) print("🛑 Neue Aufgaben erkannt. Suche pausiert für 4h.") return # Check: Pausiert? if state.get("paused_until"): paused = datetime.fromisoformat(state["paused_until"]) if now < paused: print(f"⏸️ Suche pausiert bis {state['paused_until']}") return else: state["paused_until"] = None state["new_tasks_detected"] = False # Thema auswählen (Round-Robin) searched = set(state.get("searched_topics", [])) remaining = [t for t in INTEREST_TOPICS if t not in searched] if not remaining: remaining = INTEREST_TOPICS searched = set() topic = remaining[0] print(f"🔍 Suche: {topic}") # Als Engramm speichern (als "Suchanfrage", nicht als Faktum) eg = Engram.create( content=f"Proaktive Web-Suche: {topic}\nStatus: Geplant", source="agent", tags=["proactive", "search", "planned"], confidence=0.3, grounding=Grounding.ASSUMPTION, ) store.save(eg) state["last_search"] = now.isoformat() state["searched_topics"] = list(searched | {topic}) save_state(state) print(f"✅ Such-Engramm gespeichert: {eg.id}") if __name__ == "__main__": run_proactive_search()