repositories
loading repo index
repositories
loading repo index
repository
loading code, commits, and activity
public Clawd ADK gateway launch mirror
stars
latest
clone command
git clone gitlawb://did:key:z6Mkq5mY...iFZ5/my-project-publ...git clone gitlawb://did:key:z6Mkq5mY.../my-project-publ...2fa351d6docs: add automaton and perps launch sources15d ago| #1 | """ |
| #2 | Mnemosyne Diagnostics |
| #3 | ===================== |
| #4 | PII-safe debug logging for troubleshooting installation and runtime issues. |
| #5 | |
| #6 | Logs to ~/.hermes/mnemosyne/logs/diagnose_YYYY-MM-DD_HHMMSS.jsonl |
| #7 | Never includes memory content, user queries, or API keys. |
| #8 | """ |
| #9 | |
| #10 | import json |
| #11 | import os |
| #12 | import sys |
| #13 | import platform |
| #14 | from datetime import datetime |
| #15 | from pathlib import Path |
| #16 | from typing import Dict, List |
| #17 | |
| #18 | LOG_DIR = Path.home() / ".hermes" / "mnemosyne" / "logs" |
| #19 | |
| #20 | |
| #21 | def _ensure_log_dir(): |
| #22 | LOG_DIR.mkdir(parents=True, exist_ok=True) |
| #23 | |
| #24 | |
| #25 | def _log_path() -> Path: |
| #26 | _ensure_log_dir() |
| #27 | ts = datetime.now().strftime("%Y-%m-%d_%H%M%S") |
| #28 | return LOG_DIR / f"diagnose_{ts}.jsonl" |
| #29 | |
| #30 | |
| #31 | def _safe_env(name: str) -> str: |
| #32 | """Return env var presence indicator, never the value.""" |
| #33 | val = os.environ.get(name, "") |
| #34 | return "set" if val else "unset" |
| #35 | |
| #36 | |
| #37 | def run_diagnostics() -> Dict: |
| #38 | """ |
| #39 | Run full diagnostic scan and write PII-safe log. |
| #40 | Returns summary dict for display. |
| #41 | """ |
| #42 | log_path = _log_path() |
| #43 | entries: List[Dict] = [] |
| #44 | |
| #45 | def log(category: str, check: str, status: str, detail: str = ""): |
| #46 | entry = { |
| #47 | "ts": datetime.now().isoformat(), |
| #48 | "category": category, |
| #49 | "check": check, |
| #50 | "status": status, |
| #51 | "detail": detail |
| #52 | } |
| #53 | entries.append(entry) |
| #54 | return entry |
| #55 | |
| #56 | # --- Python environment --- |
| #57 | log("env", "python_version", sys.version.split()[0]) |
| #58 | log("env", "platform", platform.platform()) |
| #59 | log("env", "python_executable", sys.executable) |
| #60 | |
| #61 | # --- Mnemosyne package --- |
| #62 | try: |
| #63 | import mnemosyne |
| #64 | log("package", "mnemosyne_version", mnemosyne.__version__) |
| #65 | except Exception as e: |
| #66 | log("package", "mnemosyne_version", "ERROR", str(e)) |
| #67 | |
| #68 | # --- Core dependencies --- |
| #69 | deps = { |
| #70 | "fastembed": "fastembed", |
| #71 | "sqlite_vec": "sqlite_vec", |
| #72 | "numpy": "numpy", |
| #73 | "ctransformers": "ctransformers", |
| #74 | "huggingface_hub": "huggingface_hub", |
| #75 | } |
| #76 | for name, module in deps.items(): |
| #77 | try: |
| #78 | mod = __import__(module) |
| #79 | ver = getattr(mod, "__version__", "unknown") |
| #80 | log("deps", name, "OK", f"version={ver}") |
| #81 | except ImportError: |
| #82 | log("deps", name, "MISSING") |
| #83 | except Exception as e: |
| #84 | log("deps", name, "ERROR", str(e)) |
| #85 | |
| #86 | # --- Mnemosyne core components --- |
| #87 | try: |
| #88 | from mnemosyne.core import embeddings as _embeddings |
| #89 | log("core", "embeddings_available", "YES" if _embeddings.available() else "NO") |
| #90 | log("core", "embeddings_model", _embeddings._DEFAULT_MODEL) |
| #91 | except Exception as e: |
| #92 | log("core", "embeddings", "ERROR", str(e)) |
| #93 | |
| #94 | try: |
| #95 | from mnemosyne.core.beam import _SQLITE_VEC_AVAILABLE |
| #96 | log("core", "sqlite_vec_available", "YES" if _SQLITE_VEC_AVAILABLE else "NO") |
| #97 | except Exception as e: |
| #98 | log("core", "sqlite_vec", "ERROR", str(e)) |
| #99 | |
| #100 | # --- Database state --- |
| #101 | try: |
| #102 | from mnemosyne.core.memory import Mnemosyne |
| #103 | mem = Mnemosyne() |
| #104 | stats = mem.get_stats() |
| #105 | |
| #106 | # PII-safe: counts and config only, never content |
| #107 | log("db", "legacy_total", str(stats.get("total_memories", 0))) |
| #108 | log("db", "total_sessions", str(stats.get("total_sessions", 0))) |
| #109 | |
| #110 | beam = stats.get("beam", {}) |
| #111 | wm = beam.get("working_memory", {}) |
| #112 | ep = beam.get("episodic_memory", {}) |
| #113 | |
| #114 | log("db", "working_total", str(wm.get("total", 0))) |
| #115 | log("db", "episodic_total", str(ep.get("total", 0))) |
| #116 | log("db", "episodic_vectors", str(ep.get("vectors", 0))) |
| #117 | log("db", "episodic_vec_type", ep.get("vec_type", "none")) |
| #118 | log("db", "db_path", stats.get("database", "unknown")) |
| #119 | except Exception as e: |
| #120 | log("db", "stats", "ERROR", str(e)) |
| #121 | |
| #122 | # --- Environment variables (presence only, never values) --- |
| #123 | env_vars = [ |
| #124 | "MNEMOSYNE_DATA_DIR", |
| #125 | "MNEMOSYNE_LLM_ENABLED", |
| #126 | "MNEMOSYNE_LLM_BASE_URL", |
| #127 | "MNEMOSYNE_VEC_TYPE", |
| #128 | "MNEMOSYNE_WM_MAX_ITEMS", |
| #129 | "HERMES_HOME", |
| #130 | ] |
| #131 | for var in env_vars: |
| #132 | log("env", var, _safe_env(var)) |
| #133 | |
| #134 | # --- Write log file --- |
| #135 | with open(log_path, "w", encoding="utf-8") as f: |
| #136 | for entry in entries: |
| #137 | f.write(json.dumps(entry) + "\n") |
| #138 | |
| #139 | # --- Build summary --- |
| #140 | summary = { |
| #141 | "log_path": str(log_path), |
| #142 | "checks_total": len(entries), |
| #143 | "checks_passed": sum(1 for e in entries if e["status"] in ("OK", "YES", "set")), |
| #144 | "checks_failed": sum(1 for e in entries if e["status"] in ("MISSING", "NO", "ERROR")), |
| #145 | "key_findings": [] |
| #146 | } |
| #147 | |
| #148 | # Auto-detect common problems |
| #149 | embed_ok = any(e["check"] == "embeddings_available" and e["status"] == "YES" for e in entries) |
| #150 | vec_ok = any(e["check"] == "sqlite_vec_available" and e["status"] == "YES" for e in entries) |
| #151 | ep_vec = next((e for e in entries if e["check"] == "episodic_vectors"), None) |
| #152 | |
| #153 | if not embed_ok: |
| #154 | summary["key_findings"].append("fastembed not available — install with: pip install mnemosyne-memory[embeddings]") |
| #155 | if not vec_ok: |
| #156 | summary["key_findings"].append("sqlite-vec not available — install with: pip install sqlite-vec") |
| #157 | if embed_ok and vec_ok and ep_vec and ep_vec["status"] == "0": |
| #158 | summary["key_findings"].append("Both fastembed and sqlite-vec are available but episodic vectors=0 — memories may not have been consolidated yet. Run: hermes mnemosyne sleep") |
| #159 | if embed_ok and vec_ok and ep_vec and int(ep_vec["status"]) > 0: |
| #160 | summary["key_findings"].append("Semantic search is active with " + ep_vec["status"] + " vectors in episodic memory") |
| #161 | |
| #162 | return summary |
| #163 | |
| #164 | |
| #165 | if __name__ == "__main__": |
| #166 | result = run_diagnostics() |
| #167 | print(json.dumps(result, indent=2)) |
| #168 |