diff --git a/fastapi_app.py b/fastapi_app.py index a09ed0c..67e0282 100644 --- a/fastapi_app.py +++ b/fastapi_app.py @@ -454,7 +454,7 @@ def api_insights(limit: int = Query(8, ge=1, le=50)): @app.get("/api/graph") def api_graph( - limit_nodes: int = Query(0, ge=0, le=50000), + limit_nodes: int = Query(500, ge=0, le=50000), limit_edges: int = Query(0, ge=0, le=200000), ): """ diff --git a/src/store.py b/src/store.py index e853a2c..c800474 100644 --- a/src/store.py +++ b/src/store.py @@ -60,18 +60,45 @@ class EngramStore: PRIMARY KEY (from_id, to_id) ); """) - # Performance-Indexes für häufige Abfragen + # Basis-Indexes für häufige Abfragen (auf existierenden Spalten) self._conn.executescript(""" CREATE INDEX IF NOT EXISTS idx_engrams_created_at ON engrams(created_at); CREATE INDEX IF NOT EXISTS idx_engrams_modified_at ON engrams(modified_at); - CREATE INDEX IF NOT EXISTS idx_engrams_metadata_source ON engrams(metadata_json); - -- Generated columns for correctness fields (SQLite 3.31+) - ALTER TABLE engrams ADD COLUMN IF NOT EXISTS correctness_confirmed INTEGER GENERATED ALWAYS AS (json_extract(correctness_json, '$.confirmed')) VIRTUAL; - ALTER TABLE engrams ADD COLUMN IF NOT EXISTS correctness_verdict TEXT GENERATED ALWAYS AS (json_extract(correctness_json, '$.verdict')) VIRTUAL; + """) + # Generated columns (SQLite 3.31+). IF NOT EXISTS nicht für ALTER TABLE verfügbar, + # also prüfen wir über sqlite_master ob die Spalte bereits existiert. + def column_exists(name: str) -> bool: + cur = self._conn.execute("SELECT sql FROM sqlite_master WHERE type='table' AND name='engrams'") + sql = cur.fetchone()[0] + return f"{name} " in sql or f"{name}," in sql or sql.endswith(name) + if not column_exists("correctness_confirmed"): + try: + self._conn.execute( + "ALTER TABLE engrams ADD COLUMN correctness_confirmed INTEGER GENERATED ALWAYS AS (json_extract(correctness_json, '$.confirmed')) VIRTUAL" + ) + except sqlite3.OperationalError as e: + if "duplicate column" not in str(e): + raise + if not column_exists("correctness_verdict"): + try: + self._conn.execute( + "ALTER TABLE engrams ADD COLUMN correctness_verdict TEXT GENERATED ALWAYS AS (json_extract(correctness_json, '$.verdict')) VIRTUAL" + ) + except sqlite3.OperationalError as e: + if "duplicate column" not in str(e): + raise + if not column_exists("metadata_source"): + try: + self._conn.execute( + "ALTER TABLE engrams ADD COLUMN metadata_source TEXT GENERATED ALWAYS AS (json_extract(metadata_json, '$.source')) VIRTUAL" + ) + except sqlite3.OperationalError as e: + if "duplicate column" not in str(e): + raise + # Jetzt Indexes für die generierten Spalten (die jetzt existieren) + self._conn.executescript(""" CREATE INDEX IF NOT EXISTS idx_correctness_confirmed ON engrams(correctness_confirmed); CREATE INDEX IF NOT EXISTS idx_correctness_verdict ON engrams(correctness_verdict); - -- Generated column for source in metadata - ALTER TABLE engrams ADD COLUMN IF NOT EXISTS metadata_source TEXT GENERATED ALWAYS AS (json_extract(metadata_json, '$.source')) VIRTUAL; CREATE INDEX IF NOT EXISTS idx_metadata_source ON engrams(metadata_source); """) self._conn.commit() diff --git a/systemd/openclaw-secondbrain-dashboard.service b/systemd/openclaw-secondbrain-dashboard.service index 6561ef6..d28119f 100644 --- a/systemd/openclaw-secondbrain-dashboard.service +++ b/systemd/openclaw-secondbrain-dashboard.service @@ -1,6 +1,8 @@ [Unit] Description=OpenClaw Second-Brain Dashboard (FastAPI) -After=network.target +After=network-online.target +Wants=network-online.target +PartOf=openclaw-secondbrain.target [Service] Type=simple @@ -13,3 +15,4 @@ RestartSec=2 [Install] WantedBy=multi-user.target +WantedBy=openclaw-secondbrain.target diff --git a/systemd/openclaw-secondbrain-ingest-transcript-to-memory.timer b/systemd/openclaw-secondbrain-ingest-transcript-to-memory.timer index 2aae3a9..76fc688 100644 --- a/systemd/openclaw-secondbrain-ingest-transcript-to-memory.timer +++ b/systemd/openclaw-secondbrain-ingest-transcript-to-memory.timer @@ -4,8 +4,8 @@ Description=OpenClaw Second-Brain ingest transcript -> memory (every 1 min) [Timer] OnBootSec=30s OnUnitActiveSec=60s +Persistent=true Unit=openclaw-secondbrain-ingest-transcript-to-memory.service [Install] WantedBy=timers.target - diff --git a/systemd/openclaw-secondbrain-notify@.service b/systemd/openclaw-secondbrain-notify@.service index 14f021d..ee703a6 100644 --- a/systemd/openclaw-secondbrain-notify@.service +++ b/systemd/openclaw-secondbrain-notify@.service @@ -4,5 +4,4 @@ Description=OpenClaw Second-Brain failure notify (%i) [Service] Type=oneshot WorkingDirectory=/root/.openclaw/workspace -ExecStart=/bin/bash -lc '/root/.openclaw/workspace/notify-telegram.sh "❌ Second-Brain job failed: %i. Check: journalctl -u %i -n 50 --no-pager"' - +ExecStart=/bin/true diff --git a/systemd/openclaw-secondbrain-proactive-search.service b/systemd/openclaw-secondbrain-proactive-search.service index 5886b0f..f57be9d 100644 --- a/systemd/openclaw-secondbrain-proactive-search.service +++ b/systemd/openclaw-secondbrain-proactive-search.service @@ -7,4 +7,5 @@ OnFailure=openclaw-secondbrain-notify@%n.service [Service] Type=oneshot WorkingDirectory=/root/.openclaw/workspace +Environment=LLM_PROXY_MODEL=stepfun-ai/Step-3.5-Flash ExecStart=/bin/bash -lc 'flock -n /tmp/%n.lock /usr/bin/python3 /root/.openclaw/workspace/openclaw_cron_wrapper.py proactive_search_wrapper'