saap-plattform / backend /api /openrouter_endpoints.py
Hwandji's picture
feat: initial HuggingFace Space deployment
4343907
"""
OpenRouter Chat Endpoints for SAAP Frontend
Separate endpoints for OpenRouter-specific chat functionality
"""
from fastapi import APIRouter, HTTPException, Depends
from typing import Dict, Any
import logging
import os
from datetime import datetime
from services.agent_manager import AgentManagerService
from agents.openrouter_saap_agent import OpenRouterSAAPAgent
logger = logging.getLogger(__name__)
# Create router for OpenRouter endpoints
openrouter_router = APIRouter(prefix="/api/v1/agents", tags=["OpenRouter"])
def get_agent_manager() -> AgentManagerService:
"""Dependency injection for agent manager"""
from main import saap_app
if not saap_app.agent_manager:
raise HTTPException(status_code=503, detail="Agent Manager not initialized")
return saap_app.agent_manager
@openrouter_router.post("/{agent_id}/chat/openrouter")
async def chat_with_agent_via_openrouter(
agent_id: str,
message_data: Dict[str, Any],
agent_manager: AgentManagerService = Depends(get_agent_manager)
):
"""
πŸš€ NEW: Chat with agent using OpenRouter (Fast, Cost-efficient)
Endpoint: POST /api/v1/agents/{agent_id}/chat/openrouter
"""
try:
message = message_data.get("message", "")
if not message:
raise HTTPException(status_code=400, detail="Message content required")
logger.info(f"🌐 OpenRouter Chat request: {agent_id} - {message[:50]}...")
# Get agent from manager
agent = agent_manager.get_agent(agent_id)
if not agent:
raise HTTPException(status_code=404, detail=f"Agent '{agent_id}' not found")
# Get OpenRouter API key from environment
api_key = os.getenv("OPENROUTER_API_KEY")
if not api_key:
raise HTTPException(
status_code=500,
detail="OpenRouter API key not configured"
)
# Create OpenRouter agent
openrouter_agent = OpenRouterSAAPAgent(
agent_id,
agent.type.value if agent.type else "Assistant",
api_key
)
# Get agent-specific model configuration
model_map = {
"jane_alesi": os.getenv("JANE_ALESI_MODEL", "openai/gpt-4o-mini"),
"john_alesi": os.getenv("JOHN_ALESI_MODEL", "deepseek/deepseek-coder"),
"lara_alesi": os.getenv("LARA_ALESI_MODEL", "anthropic/claude-3-haiku")
}
preferred_model = model_map.get(agent_id, "openai/gpt-4o-mini")
openrouter_agent.model_name = preferred_model
# Send request to OpenRouter
response = await openrouter_agent.send_request_to_openrouter(
message,
max_tokens=1000
)
if response.get("success"):
logger.info(f"βœ… OpenRouter chat successful: {agent_id}")
return {
"success": True,
"agent_id": agent_id,
"provider": "OpenRouter",
"model": preferred_model,
"message": message,
"response": {
"content": response.get("response", ""),
"provider": f"OpenRouter ({preferred_model})",
"response_time": response.get("response_time", 0),
"tokens_used": response.get("token_count", 0),
"cost_estimate": response.get("cost_estimate", 0.0)
},
"timestamp": datetime.utcnow().isoformat()
}
else:
logger.error(f"❌ OpenRouter chat failed: {response.get('error')}")
return {
"success": False,
"agent_id": agent_id,
"provider": "OpenRouter",
"error": response.get("error", "Unknown OpenRouter error"),
"timestamp": datetime.utcnow().isoformat()
}
except HTTPException:
raise
except Exception as e:
logger.error(f"❌ OpenRouter endpoint error: {e}")
return {
"success": False,
"agent_id": agent_id,
"provider": "OpenRouter",
"error": f"OpenRouter endpoint error: {str(e)}",
"timestamp": datetime.utcnow().isoformat()
}
@openrouter_router.post("/{agent_id}/chat/compare")
async def compare_providers(
agent_id: str,
message_data: Dict[str, Any],
agent_manager: AgentManagerService = Depends(get_agent_manager)
):
"""
πŸ†š Compare colossus vs OpenRouter performance side-by-side
"""
try:
message = message_data.get("message", "")
if not message:
raise HTTPException(status_code=400, detail="Message content required")
logger.info(f"πŸ†š Provider comparison request: {agent_id}")
# Send to both providers concurrently
import asyncio
# Colossus request
async def colossus_request():
try:
return await agent_manager.send_message_to_agent(agent_id, message)
except Exception as e:
return {"error": f"colossus error: {str(e)}", "provider": "colossus"}
# OpenRouter request
async def openrouter_request():
try:
agent = agent_manager.get_agent(agent_id)
if not agent:
return {"error": "Agent not found", "provider": "OpenRouter"}
api_key = os.getenv("OPENROUTER_API_KEY")
if not api_key:
return {"error": "API key not configured", "provider": "OpenRouter"}
openrouter_agent = OpenRouterSAAPAgent(agent_id, "Assistant", api_key)
response = await openrouter_agent.send_request_to_openrouter(message)
return {
"provider": "OpenRouter",
"content": response.get("response", ""),
"response_time": response.get("response_time", 0),
"success": response.get("success", False),
"error": response.get("error") if not response.get("success") else None
}
except Exception as e:
return {"error": f"OpenRouter error: {str(e)}", "provider": "OpenRouter"}
# Run both concurrently with timeout
colossus_result, openrouter_result = await asyncio.gather(
colossus_request(),
openrouter_request(),
return_exceptions=True
)
return {
"success": True,
"comparison": {
"colossus": colossus_result,
"openrouter": openrouter_result,
"performance_winner": (
"OpenRouter" if (
openrouter_result.get("response_time", float('inf')) <
colossus_result.get("response_time", float('inf'))
) else "colossus"
)
},
"timestamp": datetime.utcnow().isoformat()
}
except Exception as e:
logger.error(f"❌ Provider comparison error: {e}")
raise HTTPException(status_code=500, detail=f"Comparison failed: {str(e)}")
@openrouter_router.get("/{agent_id}/openrouter/status")
async def openrouter_status(agent_id: str):
"""
ℹ️ Get OpenRouter availability status for specific agent
"""
try:
api_key = os.getenv("OPENROUTER_API_KEY")
if not api_key:
return {
"available": False,
"error": "OpenRouter API key not configured",
"timestamp": datetime.utcnow().isoformat()
}
# Test OpenRouter connection
test_agent = OpenRouterSAAPAgent(agent_id, "Test", api_key)
health = await test_agent.health_check()
return {
"available": health["status"] == "healthy",
"model": test_agent.model_name,
"response_time": health.get("response_time"),
"error": health.get("error"),
"timestamp": datetime.utcnow().isoformat()
}
except Exception as e:
return {
"available": False,
"error": str(e),
"timestamp": datetime.utcnow().isoformat()
}