This commit is contained in:
yumoqing 2026-04-24 12:03:27 +08:00
parent 5a4c2e7393
commit 5002a3a4c7
3 changed files with 58 additions and 86 deletions

View File

@ -10,19 +10,18 @@ implement these endpoints by calling the functions provided in this module.
""" """
import json import json
import uuid
import asyncio import asyncio
import aiohttp import aiohttp
from typing import Dict, List, Optional, Tuple from typing import Dict, List, Optional, Tuple
from datetime import datetime from datetime import datetime
# Import sqlor database module # Import sqlor database module
from sqlor.dbpools import DBPools from sqlor.dbpools import get_sor_context
# Import user context helper # Import user context helper
from .user_context import get_current_user_id
# Import ahserver get_user function # Import ahserver get_user function
from ahserver.serverenv import get_user from ahserver.serverenv import get_user
from appPublic.uniqueID import getID
# Import database table definitions and CRUD operations # Import database table definitions and CRUD operations
from .db_tables import TABLE_DEFINITIONS from .db_tables import TABLE_DEFINITIONS
@ -74,20 +73,16 @@ def load_hermes_web_cli():
env.generate_session_id = generate_session_id env.generate_session_id = generate_session_id
# Also register the user context helper if needed # Also register the user context helper if needed
env.get_current_user_id = get_current_user_id
return True return True
# Database operations using sqlor-database-module # Database operations using sqlor-database-module
async def get_all_services() -> List[Dict]: async def get_all_services(userid: str) -> List[Dict]:
"""Get all registered Hermes services for the current user from database.""" """Get all registered Hermes services for the current user from database."""
try: try:
# Get current user ID
user_id = await get_current_user_id()
# Query services table with user_id filter using sqlor-database-module # Query services table with user_id filter using sqlor-database-module
db = DBPools() env = ServerEnv()
async with db.sqlorContext('hermes-web-cli') as sor: async with get_sor_context(env, 'hermes-web-cli') as sor:
sql_template = SERVICES_CRUD['operations']['read_all']['sql_template'] sql_template = SERVICES_CRUD['operations']['read_all']['sql_template']
recs = await sor.sqlExe(sql_template, {'user_id': user_id}) recs = await sor.sqlExe(sql_template, {'user_id': user_id})
@ -111,21 +106,18 @@ async def get_all_services() -> List[Dict]:
print(f"Error getting services: {e}") print(f"Error getting services: {e}")
return [] return []
async def create_service(name: str, url: str, description: str = "", apikey: str = "") -> str: 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.""" """Create a new Hermes service registration for the current user."""
try: try:
# Get current user ID
user_id = await get_current_user_id()
# Validate service URL # Validate service URL
if not await validate_service_url(url): if not await validate_service_url(url):
raise ValueError("Invalid service URL") raise ValueError("Invalid service URL")
service_id = str(uuid.uuid4()) service_id = getID()
# Save to database using sqlor-database-module # Save to database using sqlor-database-module
db = DBPools() env = ServerEnv()
async with db.sqlorContext('hermes-web-cli') as sor: async with get_sor_context(env, 'hermes-web-cli') as sor:
sql_template = SERVICES_CRUD['operations']['create']['sql_template'] sql_template = SERVICES_CRUD['operations']['create']['sql_template']
await sor.sqlExe(sql_template, { await sor.sqlExe(sql_template, {
'id': service_id, 'id': service_id,
@ -142,12 +134,9 @@ async def create_service(name: str, url: str, description: str = "", apikey: str
print(f"Error creating service: {str(e)}") print(f"Error creating service: {str(e)}")
raise raise
async def delete_service(service_id: str) -> bool: async def delete_service(userid: str, service_id: str) -> bool:
"""Delete a Hermes service registration (only if owned by current user).""" """Delete a Hermes service registration (only if owned by current user)."""
try: try:
# Get current user ID
user_id = await get_current_user_id()
# Verify service belongs to current user before deletion # Verify service belongs to current user before deletion
service = await get_service_by_id(service_id) service = await get_service_by_id(service_id)
if not service: if not service:
@ -158,8 +147,8 @@ async def delete_service(service_id: str) -> bool:
return False return False
# Delete from database using sqlor-database-module # Delete from database using sqlor-database-module
db = DBPools() env = ServerEnv()
async with db.sqlorContext('hermes-web-cli') as sor: async with get_sor_context(env, 'hermes-web-cli') as sor:
sql_template = SERVICES_CRUD['operations']['delete']['sql_template'] sql_template = SERVICES_CRUD['operations']['delete']['sql_template']
await sor.sqlExe(sql_template, { await sor.sqlExe(sql_template, {
'service_id': service_id, 'service_id': service_id,
@ -181,15 +170,12 @@ async def delete_service(service_id: str) -> bool:
print(f"Error deleting service: {str(e)}") print(f"Error deleting service: {str(e)}")
return False return False
async def get_service_by_id(service_id: str) -> Optional[Dict]: async def get_service_by_id(userid: str, service_id: str) -> Optional[Dict]:
"""Get service configuration by ID (only if owned by current user).""" """Get service configuration by ID (only if owned by current user)."""
try: try:
# Get current user ID
user_id = await get_current_user_id()
# Query database directly with user_id filter for security # Query database directly with user_id filter for security
db = DBPools() env = ServerEnv()
async with db.sqlorContext('hermes-web-cli') as sor: async with get_sor_context(env, 'hermes-web-cli') as sor:
sql_template = SERVICES_CRUD['operations']['read_by_id']['sql_template'] sql_template = SERVICES_CRUD['operations']['read_by_id']['sql_template']
recs = await sor.sqlExe(sql_template, { recs = await sor.sqlExe(sql_template, {
'service_id': service_id, 'service_id': service_id,
@ -289,8 +275,8 @@ async def create_session(service_id: str, user_id: str, user_message: str = "")
raise ValueError("Remote service did not return a session ID") raise ValueError("Remote service did not return a session ID")
# Create local session record in database # Create local session record in database
db = DBPools() env = ServerEnv()
async with db.sqlorContext('hermes-web-cli') as sor: async with get_sor_context(env, 'hermes-web-cli') as sor:
sql_template = SESSIONS_CRUD['operations']['create']['sql_template'] sql_template = SESSIONS_CRUD['operations']['create']['sql_template']
await sor.sqlExe(sql_template, { await sor.sqlExe(sql_template, {
'session_id': remote_session_id, 'session_id': remote_session_id,
@ -307,18 +293,15 @@ async def create_session(service_id: str, user_id: str, user_message: str = "")
print(f"Error creating session: {str(e)}") print(f"Error creating session: {str(e)}")
raise raise
async def send_message_to_service(service_id: str, session_id: str, message: str) -> Dict: 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).""" """Send a message to a Hermes service and get response (only if session owned by current user)."""
try: try:
# Get current user ID
user_id = await get_current_user_id()
# Verify session belongs to current user before sending message # Verify session belongs to current user before sending message
session = await get_session_by_id(session_id) session = await get_session_by_id(session_id)
if not session: if not session:
raise ValueError(f"Session {session_id} not found or access denied for user {user_id}") raise ValueError(f"Session {session_id} not found or access denied for user {user_id}")
service = await get_service_by_id(service_id) service = await get_service_by_id(userid, service_id)
if not service: if not service:
raise ValueError(f"Service {service_id} not found or access denied for user {user_id}") raise ValueError(f"Service {service_id} not found or access denied for user {user_id}")
@ -351,12 +334,9 @@ async def send_message_to_service(service_id: str, session_id: str, message: str
print(f"Error sending message: {e}") print(f"Error sending message: {e}")
raise raise
async def get_session_messages(session_id: str) -> List[Dict]: 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).""" """Get all messages for a session (only if session owned by current user)."""
try: try:
# Get current user ID
user_id = await get_current_user_id()
# Verify session belongs to current user before getting messages # Verify session belongs to current user before getting messages
session = await get_session_by_id(session_id) session = await get_session_by_id(session_id)
if not session: if not session:
@ -364,7 +344,7 @@ async def get_session_messages(session_id: str) -> List[Dict]:
return [] return []
# Get the associated service # Get the associated service
service = await get_service_by_id(session['service_id']) service = await get_service_by_id(userid, session['service_id'])
if not service: if not service:
print(f"Service for session {session_id} not found or access denied") print(f"Service for session {session_id} not found or access denied")
return [] return []
@ -392,8 +372,8 @@ async def get_session_messages(session_id: str) -> List[Dict]:
messages = await response.json() messages = await response.json()
# Update session last_active timestamp and message count in local database # Update session last_active timestamp and message count in local database
db = DBPools() env = ServerEnv()
async with db.sqlorContext('hermes-web-cli') as sor: async with get_sor_context(env, 'hermes-web-cli') as sor:
await sor.sqlExe(""" await sor.sqlExe("""
UPDATE sessions UPDATE sessions
SET last_active = CURRENT_TIMESTAMP, SET last_active = CURRENT_TIMESTAMP,
@ -412,15 +392,12 @@ async def get_session_messages(session_id: str) -> List[Dict]:
return [] return []
# Active sessions management # Active sessions management
async def get_active_sessions() -> List[Dict]: async def get_active_sessions(userid: str) -> List[Dict]:
"""Get all active sessions for the current user from database.""" """Get all active sessions for the current user from database."""
try: try:
# Get current user ID
user_id = await get_current_user_id()
# Query the sessions table for active sessions belonging to current user using sqlor-database-module # Query the sessions table for active sessions belonging to current user using sqlor-database-module
db = DBPools() env = ServerEnv()
async with db.sqlorContext('hermes-web-cli') as sor: async with get_sor_context(env, 'hermes-web-cli') as sor:
sql_template = SESSIONS_CRUD['operations']['read_active']['sql_template'] sql_template = SESSIONS_CRUD['operations']['read_active']['sql_template']
recs = await sor.sqlExe(sql_template, {'user_id': user_id}) recs = await sor.sqlExe(sql_template, {'user_id': user_id})
@ -440,15 +417,12 @@ async def get_active_sessions() -> List[Dict]:
print(f"Error getting active sessions: {str(e)}") print(f"Error getting active sessions: {str(e)}")
return [] return []
async def get_recent_sessions(limit: int = 5) -> List[Dict]: 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).""" """Get recent sessions for the current user from database, ordered by creation time (most recent first)."""
try: try:
# Get current user ID
user_id = await get_current_user_id()
# Query the sessions table for recent sessions belonging to current user using sqlor-database-module # Query the sessions table for recent sessions belonging to current user using sqlor-database-module
db = DBPools() env = ServerEnv()
async with db.sqlorContext('hermes-web-cli') as sor: async with get_sor_context(env, 'hermes-web-cli') as sor:
sql_template = SESSIONS_CRUD['operations']['read_recent']['sql_template'] sql_template = SESSIONS_CRUD['operations']['read_recent']['sql_template']
recs = await sor.sqlExe(sql_template, {'user_id': user_id, 'limit': limit}) recs = await sor.sqlExe(sql_template, {'user_id': user_id, 'limit': limit})
@ -468,15 +442,12 @@ async def get_recent_sessions(limit: int = 5) -> List[Dict]:
print(f"Error getting recent sessions: {str(e)}") print(f"Error getting recent sessions: {str(e)}")
return [] return []
async def get_session_by_id(session_id: str) -> Optional[Dict]: async def get_session_by_id(userid, session_id: str) -> Optional[Dict]:
"""Get session details by session ID (only if owned by current user).""" """Get session details by session ID (only if owned by current user)."""
try: try:
# Get current user ID
user_id = await get_current_user_id()
# Query database directly with user_id filter for security # Query database directly with user_id filter for security
db = DBPools() env = ServerEnv()
async with db.sqlorContext('hermes-web-cli') as sor: async with get_sor_context(env, 'hermes-web-cli') as sor:
sql_template = SESSIONS_CRUD['operations']['read_by_id']['sql_template'] sql_template = SESSIONS_CRUD['operations']['read_by_id']['sql_template']
recs = await sor.sqlExe(sql_template, { recs = await sor.sqlExe(sql_template, {
'session_id': session_id, 'session_id': session_id,
@ -508,7 +479,7 @@ def validate_service_url(url: str) -> bool:
def generate_session_id() -> str: def generate_session_id() -> str:
"""Generate a unique session ID.""" """Generate a unique session ID."""
return str(uuid.uuid4()) return getID()
# Settings management # Settings management
async def get_setting() -> Dict: async def get_setting() -> Dict:
@ -535,8 +506,8 @@ async def get_setting() -> Dict:
try: try:
# Query user settings from database # Query user settings from database
db = DBPools() env = ServerEnv()
async with db.sqlorContext('hermes-web-cli') as sor: async with get_sor_context(env, 'hermes-web-cli') as sor:
sql_template = SETTINGS_CRUD['operations']['read']['sql_template'] sql_template = SETTINGS_CRUD['operations']['read']['sql_template']
recs = await sor.sqlExe(sql_template, {'user_id': user_id}) recs = await sor.sqlExe(sql_template, {'user_id': user_id})
@ -577,8 +548,8 @@ async def save_setting(section: str, key: str, value) -> bool:
try: try:
# Save to database using sqlor-database-module # Save to database using sqlor-database-module
db = DBPools() env = ServerEnv()
async with db.sqlorContext('hermes-web-cli') as sor: async with get_sor_context(env, 'hermes-web-cli') as sor:
sql_template = SETTINGS_CRUD['operations']['create_or_update']['sql_template'] sql_template = SETTINGS_CRUD['operations']['create_or_update']['sql_template']
await sor.sqlExe(sql_template, { await sor.sqlExe(sql_template, {
'user_id': user_id, 'user_id': user_id,
@ -614,4 +585,4 @@ __all__ = [
'get_current_user_id', 'get_current_user_id',
'MODULE_NAME', 'MODULE_NAME',
'MODULE_VERSION' 'MODULE_VERSION'
] ]

View File

@ -3,7 +3,8 @@
try: try:
# Use the function provided by hermes-web-cli module # Use the function provided by hermes-web-cli module
services = await get_all_services() userid = await get_user()
services = await get_all_services(userid)
# Format for code component (value, text pairs) # Format for code component (value, text pairs)
result = [] result = []

View File

@ -1,18 +1,18 @@
1|# Remove a service by ID # Remove a service by ID
2|# This .dspy file uses functions provided by load_hermes_web_cli() # This .dspy file uses functions provided by load_hermes_web_cli()
3|
4|try: try:
5| service_id = params_kw.get('id') service_id = params_kw.get('id')
6| if not service_id: if not service_id:
7| return {"error": "Service ID is required"} return {"error": "Service ID is required"}
8| userid = await get_user()
9| # Call the function provided by the hermes-web-cli module # Call the function provided by the hermes-web-cli module
10| success = await delete_service(service_id) success = await delete_service(userid, service_id)
11|
12| if success: if success:
13| return {"success": True, "message": "Service removed successfully"} return {"success": True, "message": "Service removed successfully"}
14| else: else:
15| return {"error": "Failed to remove service"} return {"error": "Failed to remove service"}
16|
17|except Exception as e: except Exception as e:
18| return {"error": str(e)} return {"error": str(e)}