From 4df2f72758307b479184e146154d9e65f06a417f Mon Sep 17 00:00:00 2001 From: yumoqing Date: Sat, 25 Apr 2026 22:10:38 +0800 Subject: [PATCH] fix(init): remove leftover conflict markers and duplicate code Cleaned up 426 lines of dead code and unresolved conflict markers (<<<<<<< HEAD, =======, >>>>>>>) left over from rebase. File reduced from 1102 to 676 lines. --- hermes_web_cli/init.py | 426 ----------------------------------------- 1 file changed, 426 deletions(-) diff --git a/hermes_web_cli/init.py b/hermes_web_cli/init.py index 3beab4a..8e58d6f 100644 --- a/hermes_web_cli/init.py +++ b/hermes_web_cli/init.py @@ -18,437 +18,11 @@ from datetime import datetime # Import sqlor database module from sqlor.dbpools import get_sor_context ->>>>>>> f741c58 (feat(hermes-web-cli): refactor user context, settings, services and sessions management) # Import database table definitions and CRUD operations from .db_tables import TABLE_DEFINITIONS from .crud_ops import SERVICES_CRUD, SESSIONS_CRUD, SETTINGS_CRUD def load_hermes_web_cli(): -<<<<<<< HEAD - """Initialize and load the hermes-web-cli module. - - This function is called by Sage system during module loading. - It registers all module functions with the ServerEnv instance - so they can be called directly from .ui and .dspy files. - """ - from ahserver.serverenv import ServerEnv - - # Get the ServerEnv instance - env = ServerEnv() - - # Register all module functions with ServerEnv - env.get_setting = get_setting - env.save_setting = save_setting - env.get_all_services = get_all_services - env.create_service = create_service - env.delete_service = delete_service - env.get_service_by_id = get_service_by_id - env.test_service_connection = test_service_connection - env.create_session = create_session - env.send_message_to_service = send_message_to_service - env.get_session_messages = get_session_messages - env.get_active_sessions = get_active_sessions - env.get_recent_sessions = get_recent_sessions - env.get_session_by_id = get_session_by_id - env.validate_service_url = validate_service_url - env.generate_session_id = generate_session_id - - return True - -# Database operations using sqlor-database-module -async def get_all_services_old(userid: str) -> List[Dict]: - """Get all registered Hermes services for the current user from database.""" - try: - # Query services table with user_id filter using sqlor-database-module - env = ServerEnv() - async with get_sor_context(env, 'hermes-web-cli') as sor: - sql_template = SERVICES_CRUD['operations']['read_all']['sql_template'] - recs = await sor.sqlExe(sql_template, {'user_id': user_id}) - - # Convert datetime objects to ISO format strings for JSON serialization - result = [] - for rec in recs: - service_dict = dict(rec) - if 'created_at' in service_dict and service_dict['created_at']: - service_dict['created_at'] = service_dict['created_at'].isoformat() - if 'updated_at' in service_dict and service_dict['updated_at']: - service_dict['updated_at'] = service_dict['updated_at'].isoformat() - result.append(service_dict) - - return result - - except Exception as e: - print(f"Error getting services: {str(e)}") - # Return empty list on error - return [] - except Exception as e: - print(f"Error getting services: {e}") - return [] - -async def create_service(userid: str, name: str, url: str, description: str = "", apikey: str = "") -> str: - """Create a new Hermes service registration for the current user.""" - try: - # Validate service URL - if not await validate_service_url(url): - raise ValueError("Invalid service URL") - - service_id = getID() - - # Save to database using sqlor-database-module - env = ServerEnv() - async with get_sor_context(env, 'hermes-web-cli') as sor: - sql_template = SERVICES_CRUD['operations']['create']['sql_template'] - await sor.sqlExe(sql_template, { - 'id': service_id, - 'user_id': user_id, - 'name': name, - 'service_url': url, - 'description': description, - 'status': 'active' - }) - - return service_id - - except Exception as e: - print(f"Error creating service: {str(e)}") - raise - -async def delete_service(userid: str, service_id: str) -> bool: - """Delete a Hermes service registration (only if owned by current user).""" - try: - # Verify service belongs to current user before deletion - service = await get_service_by_id(service_id) - if not service: - return False - - if service.get("user_id") != user_id: - print(f"Permission denied: Service {service_id} does not belong to user {user_id}") - return False - - # Delete from database using sqlor-database-module - env = ServerEnv() - async with get_sor_context(env, 'hermes-web-cli') as sor: - sql_template = SERVICES_CRUD['operations']['delete']['sql_template'] - await sor.sqlExe(sql_template, { - 'service_id': service_id, - 'user_id': user_id - }) - - # Also delete associated sessions - env = ServerEnv() - dbname = env.get_module_dbname() - async with db.sqlorContext(dbname) as sor: - await sor.sqlExe(""" - DELETE FROM sessions - WHERE service_id = ${service_id}$ AND user_id = ${user_id}$ - """, { - 'service_id': service_id, - 'user_id': user_id - }) - - return True - except Exception as e: - print(f"Error deleting service: {str(e)}") - return False - -async def get_service_by_id(userid: str, service_id: str) -> Optional[Dict]: - """Get service configuration by ID (only if owned by current user).""" - try: - # Query database directly with user_id filter for security - env = ServerEnv() - async with get_sor_context(env, 'hermes-web-cli') as sor: - sql_template = SERVICES_CRUD['operations']['read_by_id']['sql_template'] - recs = await sor.sqlExe(sql_template, { - 'service_id': service_id, - 'user_id': user_id - }) - - if len(recs) > 0: - service_dict = dict(recs[0]) - if 'created_at' in service_dict and service_dict['created_at']: - service_dict['created_at'] = service_dict['created_at'].isoformat() - if 'updated_at' in service_dict and service_dict['updated_at']: - service_dict['updated_at'] = service_dict['updated_at'].isoformat() - return service_dict - - return None - - except Exception as e: - print(f"Error getting service: {str(e)}") - return None -# Service connection testing -async def test_service_connection(service_id: str) -> Tuple[bool, str]: - """Test connection to a Hermes service endpoint. - - Args: - service_id: The ID of the service to test - - Returns: - Tuple[bool, str]: (is_connected, status_message) - """ - try: - # Get service configuration (verify it belongs to current user) - service = await get_service_by_id(service_id) - if not service: - return False, "Service not found or access denied" - - url = service["service_url"] - apikey = service.get("apikey", "") - - # Prepare headers - headers = {} - if apikey: - headers["Authorization"] = f"Bearer {apikey}" - - # Test the /health endpoint or similar - timeout = aiohttp.ClientTimeout(total=10) - async with aiohttp.ClientSession(timeout=timeout) as session: - async with session.get(f"{url.rstrip('/')}/health", headers=headers) as response: - if response.status == 200: - return True, "Connected" - else: - return False, f"HTTP {response.status}" - except asyncio.TimeoutError: - return False, "Connection timeout" - except aiohttp.ClientConnectorError: - return False, "Connection refused" - except Exception as e: - return False, f"Error: {str(e)}" - -# Session management -async def create_session(service_id: str, user_id: str, user_message: str = "") -> str: - """Create a new session with a Hermes service.""" - try: - # Get service configuration (verify it belongs to current user) - service = await get_service_by_id(service_id) - if not service: - raise ValueError(f"Service {service_id} not found or access denied") - - service_url = service["service_url"] - apikey = service.get("apikey", "") - - # Prepare headers - headers = { - "Content-Type": "application/json" - } - - # Add Authorization header if API key is provided - if apikey: - headers["Authorization"] = f"Bearer {apikey}" - - # Call remote service API to create session - timeout = aiohttp.ClientTimeout(total=30) - async with aiohttp.ClientSession(timeout=timeout) as session: - async with session.post( - f"{service_url.rstrip('/')}/api/v1/sessions", - json={ - "user_id": user_id, - "initial_message": user_message if user_message else None - }, - headers=headers - ) as response: - response.raise_for_status() - result = await response.json() - - # Get the session ID from the remote service - remote_session_id = result.get("session_id", "") - if not remote_session_id: - raise ValueError("Remote service did not return a session ID") - - # Create local session record in database - env = ServerEnv() - async with get_sor_context(env, 'hermes-web-cli') as sor: - sql_template = SESSIONS_CRUD['operations']['create']['sql_template'] - await sor.sqlExe(sql_template, { - 'session_id': remote_session_id, - 'user_id': user_id, - 'service_id': service_id, - 'session_name': None, - 'service_name': service.get("name", "Unknown Service") - }) - - # Return the session ID from the remote service - return remote_session_id - - except Exception as e: - print(f"Error creating session: {str(e)}") - raise - -async def send_message_to_service(userid: str, service_id: str, session_id: str, message: str) -> Dict: - """Send a message to a Hermes service and get response (only if session owned by current user).""" - try: - # Verify session belongs to current user before sending message - session = await get_session_by_id(session_id) - if not session: - raise ValueError(f"Session {session_id} not found or access denied for user {user_id}") - - service = await get_service_by_id(userid, service_id) - if not service: - raise ValueError(f"Service {service_id} not found or access denied for user {user_id}") - - service_url = service["service_url"] - apikey = service.get("apikey", "") - - # Prepare headers - headers = { - "Content-Type": "application/json" - } - - # Add Authorization header if API key is provided - if apikey: - headers["Authorization"] = f"Bearer {apikey}" - - # Call remote service API - timeout = aiohttp.ClientTimeout(total=30) - async with aiohttp.ClientSession(timeout=timeout) as session: - async with session.post( - f"{service_url.rstrip('/')}/api/chat", - json={ - "session_id": session_id, - "message": message - }, - headers=headers - ) as response: - response.raise_for_status() - return await response.json() - except Exception as e: - print(f"Error sending message: {e}") - raise - -async def get_session_messages(userid: str, session_id: str) -> List[Dict]: - """Get all messages for a session (only if session owned by current user).""" - try: - # Verify session belongs to current user before getting messages - session = await get_session_by_id(session_id) - if not session: - print(f"Session {session_id} not found or access denied for user {user_id}") - return [] - - # Get the associated service - service = await get_service_by_id(userid, session['service_id']) - if not service: - print(f"Service for session {session_id} not found or access denied") - return [] - - service_url = service["service_url"] - apikey = service.get("apikey", "") - - # Prepare headers - headers = { - "Content-Type": "application/json" - } - - # Add Authorization header if API key is provided - if apikey: - headers["Authorization"] = f"Bearer {apikey}" - - # Call remote service API to get messages - timeout = aiohttp.ClientTimeout(total=30) - async with aiohttp.ClientSession(timeout=timeout) as session: - async with session.get( - f"{service_url.rstrip('/')}/api/v1/sessions/{session_id}/messages", - headers=headers - ) as response: - response.raise_for_status() - messages = await response.json() - - # Update session last_active timestamp and message count in local database - env = ServerEnv() - async with get_sor_context(env, 'hermes-web-cli') as sor: - await sor.sqlExe(""" - UPDATE sessions - SET last_active = CURRENT_TIMESTAMP, - message_count = ${message_count}$ - WHERE session_id = ${session_id}$ AND user_id = ${user_id}$ - """, { - 'session_id': session_id, - 'user_id': user_id, - 'message_count': len(messages) - }) - - return messages - - except Exception as e: - print(f"Error getting session messages: {str(e)}") - return [] - -# Active sessions management -async def get_active_sessions(userid: str) -> List[Dict]: - """Get all active sessions for the current user from database.""" - try: - # Query the sessions table for active sessions belonging to current user using sqlor-database-module - env = ServerEnv() - async with get_sor_context(env, 'hermes-web-cli') as sor: - sql_template = SESSIONS_CRUD['operations']['read_active']['sql_template'] - recs = await sor.sqlExe(sql_template, {'user_id': user_id}) - - # Convert datetime objects to ISO format strings for JSON serialization - result = [] - for rec in recs: - session_dict = dict(rec) - if 'created_at' in session_dict and session_dict['created_at']: - session_dict['created_at'] = session_dict['created_at'].isoformat() - if 'last_active' in session_dict and session_dict['last_active']: - session_dict['last_active'] = session_dict['last_active'].isoformat() - result.append(session_dict) - - return result - - except Exception as e: - print(f"Error getting active sessions: {str(e)}") - return [] - -async def get_recent_sessions(userid: str, limit: int = 5) -> List[Dict]: - """Get recent sessions for the current user from database, ordered by creation time (most recent first).""" - try: - # Query the sessions table for recent sessions belonging to current user using sqlor-database-module - env = ServerEnv() - async with get_sor_context(env, 'hermes-web-cli') as sor: - sql_template = SESSIONS_CRUD['operations']['read_recent']['sql_template'] - recs = await sor.sqlExe(sql_template, {'user_id': user_id, 'limit': limit}) - - # Convert datetime objects to ISO format strings for JSON serialization - result = [] - for rec in recs: - session_dict = dict(rec) - if 'created_at' in session_dict and session_dict['created_at']: - session_dict['created_at'] = session_dict['created_at'].isoformat() - if 'last_active' in session_dict and session_dict['last_active']: - session_dict['last_active'] = session_dict['last_active'].isoformat() - result.append(session_dict) - - return result - - except Exception as e: - print(f"Error getting recent sessions: {str(e)}") - return [] - -async def get_session_by_id(userid, session_id: str) -> Optional[Dict]: - """Get session details by session ID (only if owned by current user).""" - try: - # Query database directly with user_id filter for security - env = ServerEnv() - async with get_sor_context(env, 'hermes-web-cli') as sor: - sql_template = SESSIONS_CRUD['operations']['read_by_id']['sql_template'] - recs = await sor.sqlExe(sql_template, { - 'session_id': session_id, - 'user_id': user_id - }) - - if len(recs) > 0: - session_dict = dict(recs[0]) - if 'created_at' in session_dict and session_dict['created_at']: - session_dict['created_at'] = session_dict['created_at'].isoformat() - if 'last_active' in session_dict and session_dict['last_active']: - session_dict['last_active'] = session_dict['last_active'].isoformat() - return session_dict - - return None - - except Exception as e: - print(f"Error getting session by ID: {str(e)}") - return None -======= """Initialize and load the hermes-web-cli module. This function is called by Sage system during module loading.