""" VERITAS Integrated Memory System ================================== CogniVault (RAG) + Aluna Memory (LTM) — unified HuggingFace Space Rob "The Sounds Guy" Barenbrug | Built by VERITAS Stack: Python 3.11 + Gradio 5.15.0 """ import os, json, sqlite3, hashlib, datetime, re, logging from pathlib import Path import gradio as gr logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s") log = logging.getLogger("veritas") # ─── STORAGE ───────────────────────────────────────────────────────────────── DB_PATH = Path("/data/veritas.db") if Path("/data").exists() else Path("veritas.db") DATA_DIR = Path("/data/uploads") if Path("/data").exists() else Path("uploads") DATA_DIR.mkdir(parents=True, exist_ok=True) def init_db(): with sqlite3.connect(str(DB_PATH)) as conn: conn.executescript(""" CREATE TABLE IF NOT EXISTS memories ( id TEXT PRIMARY KEY, content TEXT NOT NULL, category TEXT DEFAULT 'general', importance INTEGER DEFAULT 5, source TEXT DEFAULT 'manual', created_at TEXT DEFAULT (datetime('now')), updated_at TEXT DEFAULT (datetime('now')), access_count INTEGER DEFAULT 0 ); CREATE TABLE IF NOT EXISTS knowledge ( id TEXT PRIMARY KEY, title TEXT, content TEXT NOT NULL, source TEXT DEFAULT 'manual', tags TEXT DEFAULT '[]', doc_type TEXT DEFAULT 'text', chunk_index INTEGER DEFAULT 0, parent_id TEXT, created_at TEXT DEFAULT (datetime('now')) ); CREATE INDEX IF NOT EXISTS idx_mem_cat ON memories(category); CREATE INDEX IF NOT EXISTS idx_mem_imp ON memories(importance DESC); CREATE INDEX IF NOT EXISTS idx_know_src ON knowledge(source); """) init_db() def make_id(s: str) -> str: return hashlib.sha256((s + datetime.datetime.utcnow().isoformat()).encode()).hexdigest()[:20] # ─── MEMORY OPS ────────────────────────────────────────────────────────────── def store_memory(content, category="general", importance=5, source="manual"): if not str(content).strip(): return {"error": "Content cannot be empty"} with sqlite3.connect(str(DB_PATH)) as conn: row = conn.execute("SELECT id FROM memories WHERE content=?", (content,)).fetchone() if row: conn.execute("UPDATE memories SET access_count=access_count+1, updated_at=datetime('now') WHERE id=?", (row[0],)) return {"id": row[0], "status": "deduplicated", "message": "Already stored — access count bumped"} mid = make_id(content) conn.execute("INSERT INTO memories (id, content, category, importance, source) VALUES (?,?,?,?,?)", (mid, content, category, int(importance), source)) return {"id": mid, "status": "stored", "category": category, "importance": importance} def search_memories(query, category=None, limit=20): q = f"%{query.lower()}%" with sqlite3.connect(str(DB_PATH)) as conn: if category and category != "all": rows = conn.execute( "SELECT id,content,category,importance,created_at,access_count FROM memories " "WHERE lower(content) LIKE ? AND category=? ORDER BY importance DESC,access_count DESC LIMIT ?", (q, category, limit)).fetchall() else: rows = conn.execute( "SELECT id,content,category,importance,created_at,access_count FROM memories " "WHERE lower(content) LIKE ? ORDER BY importance DESC,access_count DESC LIMIT ?", (q, limit)).fetchall() ids = [r[0] for r in rows] if ids: conn.execute(f"UPDATE memories SET access_count=access_count+1 WHERE id IN ({','.join('?'*len(ids))})", ids) return [{"id":r[0],"content":r[1],"category":r[2],"importance":r[3],"created_at":r[4],"access_count":r[5]} for r in rows] def get_all_memories(limit=100): with sqlite3.connect(str(DB_PATH)) as conn: rows = conn.execute( "SELECT id,content,category,importance,created_at,access_count FROM memories " "ORDER BY importance DESC,updated_at DESC LIMIT ?", (limit,)).fetchall() return [{"id":r[0],"content":r[1],"category":r[2],"importance":r[3],"created_at":r[4],"access_count":r[5]} for r in rows] # ─── KNOWLEDGE OPS ─────────────────────────────────────────────────────────── def chunk_text(text, size=800, overlap=100): paras = [p.strip() for p in re.split(r'\n\n+', text) if p.strip()] chunks, cur = [], "" for p in paras: if len(cur) + len(p) + 2 < size: cur = (cur + "\n\n" + p).strip() if cur else p else: if cur: chunks.append(cur) cur = p if cur: chunks.append(cur) final = [] for c in chunks: if len(c) > size * 1.5: for i in range(0, len(c), size - overlap): piece = c[i:i+size] if piece.strip(): final.append(piece) else: final.append(c) return final or [text] def ingest_text(title, content, source="manual", tags_str="", doc_type="text"): if not str(content).strip(): return {"error": "Content is empty"} tags = [t.strip() for t in str(tags_str).split(",") if t.strip()] chunks = chunk_text(str(content)) parent_id = make_id(str(title) + str(content)[:80]) with sqlite3.connect(str(DB_PATH)) as conn: for i, chunk in enumerate(chunks): kid = make_id(chunk + str(i)) conn.execute( "INSERT OR REPLACE INTO knowledge (id,title,content,source,tags,doc_type,chunk_index,parent_id) VALUES (?,?,?,?,?,?,?,?)", (kid, str(title), chunk, source, json.dumps(tags), doc_type, i, parent_id)) return {"parent_id": parent_id, "title": str(title), "chunks": len(chunks), "chars": len(str(content)), "source": source, "tags": tags, "status": "ingested"} def ingest_file(file_obj, source="upload"): if file_obj is None: return {"error": "No file provided"} # Gradio 5 returns filepath string or dict if isinstance(file_obj, dict): filepath = file_obj.get("name", file_obj.get("path", "")) filename = file_obj.get("orig_name", Path(filepath).name) else: filepath = str(file_obj) filename = Path(filepath).name ext = Path(filename).suffix.lower() if ext not in [".txt", ".md"]: return {"error": f"Unsupported: {ext}. Use .txt or .md"} try: with open(filepath, "r", encoding="utf-8", errors="replace") as f: content = f.read() return ingest_text(filename, content, source=source, tags_str=f"{ext.strip('.')},{source}", doc_type=ext.strip(".")) except Exception as e: return {"error": str(e)} def search_knowledge(query, limit=20): q = f"%{query.lower()}%" with sqlite3.connect(str(DB_PATH)) as conn: rows = conn.execute( "SELECT id,title,content,source,tags,doc_type,created_at FROM knowledge " "WHERE lower(content) LIKE ? OR lower(title) LIKE ? ORDER BY created_at DESC LIMIT ?", (q, q, limit)).fetchall() return [{"id":r[0],"title":r[1],"content":r[2],"source":r[3],"tags":json.loads(r[4]),"doc_type":r[5],"created_at":r[6]} for r in rows] def rag_query(question): if not str(question).strip(): return "Enter a question above." know = search_knowledge(question, 6) mems = search_memories(question, limit=4) if not know and not mems: return "❌ No context found. Add documents via 📚 Knowledge or memories via 🧠 Memory tab." parts = [] if know: parts.append("## Knowledge Base\n") for r in know[:5]: parts.append(f"**[{r['title']}]** (source: {r['source']})\n{r['content'][:500]}\n---") if mems: parts.append("\n## Memory Context\n") for m in mems[:3]: parts.append(f"**[{m['category']} | importance {m['importance']}]**\n{m['content'][:300]}\n---") return "\n".join(parts) def get_stats(): with sqlite3.connect(str(DB_PATH)) as conn: mc = conn.execute("SELECT COUNT(*) FROM memories").fetchone()[0] kc = conn.execute("SELECT COUNT(*) FROM knowledge").fetchone()[0] cats = dict(conn.execute("SELECT category,COUNT(*) FROM memories GROUP BY category").fetchall()) srcs = dict(conn.execute("SELECT source,COUNT(*) FROM knowledge GROUP BY source").fetchall()) top = conn.execute("SELECT content,importance,access_count FROM memories ORDER BY importance DESC,access_count DESC LIMIT 5").fetchall() return {"total_memories": mc, "total_knowledge_chunks": kc, "categories": cats, "knowledge_sources": srcs, "top_memories": [{"content": r[0][:120], "importance": r[1], "access_count": r[2]} for r in top]} # ─── MCP JSON API ───────────────────────────────────────────────────────────── def mcp_api(request_json): try: req = json.loads(request_json) except: return json.dumps({"error": "Invalid JSON"}, indent=2) tool = req.get("tool", "") params = req.get("params", {}) if tool == "store_memory": result = store_memory(params.get("content",""), params.get("category","general"), int(params.get("importance",5)), params.get("source","claude")) elif tool == "search_memories": result = search_memories(params.get("query",""), params.get("category"), int(params.get("limit",20))) elif tool == "store_knowledge": result = ingest_text(params.get("title","Untitled"), params.get("content",""), params.get("source","claude"), params.get("tags",""), params.get("doc_type","text")) elif tool == "search_knowledge": result = search_knowledge(params.get("query",""), int(params.get("limit",20))) elif tool == "rag_query": result = {"context": rag_query(params.get("question",""))} elif tool == "get_session_context": result = {"user":"Rob 'The Sounds Guy' Barenbrug","location":"Durban, South Africa", "device":"Huawei Pura 80 Pro (Termux)","vps":"veritas.alunaafrica.cloud", "constraint":"CANNOT manually code — click-and-run only", "philosophy":"Live in truth, never in comfort", "stats": get_stats(), "recent_memories": get_all_memories(10)} elif tool == "status": result = get_stats() result.update({"system":"VERITAS Integrated Memory","version":"1.0.0","status":"OPERATIONAL","stack":"Python 3.11 + Gradio 5.15.0"}) else: result = {"error": f"Unknown tool: '{tool}'", "available": ["store_memory","search_memories","store_knowledge","search_knowledge","rag_query","get_session_context","status"]} return json.dumps(result, indent=2, default=str) # ─── UI ─────────────────────────────────────────────────────────────────────── CATS = ["general","project","technical","personal","rib-rage","bytebot","cognivault","aluna","android","audio","business","mene-portal"] with gr.Blocks(title="VERITAS Memory", theme=gr.themes.Base(primary_hue="blue", neutral_hue="slate"), css="footer{display:none!important}.header{text-align:center;padding:16px 0 6px}") as demo: gr.HTML("""
CogniVault RAG + Aluna Memory LTM — Unified
Rob "The Sounds Guy" Barenbrug | Live in truth, never in comfort