#!/usr/bin/env python3 """ Chat Memory Lookup - Fast local memory queries Queries shared project memory without external calls """ import sqlite3 from pathlib import Path from typing import Dict, List, Optional import time class ChatMemoryLookup: """Query local project memory for chat interface""" MEMORY_DB = Path('/etc/zen-swarm/memory/projects.db') def __init__(self, timeout_ms: int = 150): """Initialize with query timeout""" self.timeout_ms = timeout_ms self.timeout_seconds = timeout_ms / 1000.0 def search_entities(self, query: str, limit: int = 10) -> Dict: """Search for entities by name""" if not self.MEMORY_DB.exists(): return {'error': 'Memory database not found', 'entities': []} try: conn = sqlite3.connect(str(self.MEMORY_DB), timeout=self.timeout_seconds) conn.row_factory = sqlite3.Row cursor = conn.cursor() cursor.execute( "SELECT id, name, type FROM entities WHERE name LIKE ? LIMIT ?", (f'%{query}%', limit) ) entities = [ { 'id': row['id'], 'name': row['name'], 'type': row['type'] } for row in cursor.fetchall() ] conn.close() return {'entities': entities, 'count': len(entities)} except Exception as e: return {'error': str(e), 'entities': []} def get_entity(self, entity_name: str) -> Dict: """Get entity and its relations""" if not self.MEMORY_DB.exists(): return {'error': 'Memory database not found'} try: conn = sqlite3.connect(str(self.MEMORY_DB), timeout=self.timeout_seconds) conn.row_factory = sqlite3.Row cursor = conn.cursor() # Get entity cursor.execute( "SELECT id, name, type FROM entities WHERE name = ?", (entity_name,) ) entity_row = cursor.fetchone() if not entity_row: conn.close() return {'error': f'Entity {entity_name} not found'} entity_id = entity_row['id'] entity = { 'name': entity_row['name'], 'type': entity_row['type'], 'relations': [] } # Get relations (join to get entity names) cursor.execute(""" SELECT e1.name as from_name, e2.name as to_name, r.relation, r.context FROM relations r JOIN entities e1 ON r.source_id = e1.id JOIN entities e2 ON r.target_id = e2.id WHERE r.source_id = ? OR r.target_id = ? LIMIT 20 """, (entity_id, entity_id)) for row in cursor.fetchall(): entity['relations'].append({ 'from': row['from_name'], 'to': row['to_name'], 'type': row['relation'], 'context': row['context'] }) conn.close() return entity except Exception as e: return {'error': str(e)} def get_project_info(self, project_name: str) -> Dict: """Get project-specific information""" if not self.MEMORY_DB.exists(): return {'error': 'Memory database not found'} try: conn = sqlite3.connect(str(self.MEMORY_DB), timeout=self.timeout_seconds) conn.row_factory = sqlite3.Row cursor = conn.cursor() # Get project entity cursor.execute( "SELECT id, name, type FROM entities WHERE name = ? AND type = 'project'", (project_name,) ) project_row = cursor.fetchone() if not project_row: conn.close() return {'error': f'Project {project_name} not found'} project_id = project_row['id'] project = { 'name': project_row['name'], 'type': project_row['type'], 'related_entities': [] } # Get related entities cursor.execute(""" SELECT e.name FROM entities e JOIN relations r ON r.target_id = e.id WHERE r.source_id = ? LIMIT 10 """, (project_id,)) for row in cursor.fetchall(): project['related_entities'].append(row['name']) conn.close() return project except Exception as e: return {'error': str(e)} def list_all_projects(self) -> Dict: """List all projects in memory""" if not self.MEMORY_DB.exists(): return {'error': 'Memory database not found', 'projects': []} try: conn = sqlite3.connect(str(self.MEMORY_DB), timeout=self.timeout_seconds) conn.row_factory = sqlite3.Row cursor = conn.cursor() cursor.execute( "SELECT name, type FROM entities WHERE type = 'project' OR type = 'Project' LIMIT 50" ) projects = [ { 'name': row['name'], 'type': row['type'] } for row in cursor.fetchall() ] conn.close() return {'projects': projects, 'count': len(projects)} except Exception as e: return {'error': str(e), 'projects': []} def memory_statistics(self) -> Dict: """Get memory database statistics""" if not self.MEMORY_DB.exists(): return {'available': False} try: conn = sqlite3.connect(str(self.MEMORY_DB), timeout=self.timeout_seconds) cursor = conn.cursor() cursor.execute("SELECT COUNT(*) FROM entities") entity_count = cursor.fetchone()[0] cursor.execute("SELECT COUNT(*) FROM relations") relation_count = cursor.fetchone()[0] stats = { 'available': True, 'entities': entity_count, 'relations': relation_count } conn.close() return stats except Exception as e: return {'available': False, 'error': str(e)} if __name__ == '__main__': import json lookup = ChatMemoryLookup() print("Memory Statistics:") print(json.dumps(lookup.memory_statistics(), indent=2)) print() print("List Projects:") print(json.dumps(lookup.list_all_projects(), indent=2))