87 lines
2.6 KiB
Python
87 lines
2.6 KiB
Python
# services/event_router.py
|
|
import asyncio
|
|
import logging
|
|
from typing import Any, Dict, Optional
|
|
|
|
from services.ai_orchestrator import AIOrchestrator
|
|
from services.telegram_templates import alert
|
|
from database.manager import get_session
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
async def _handle_l1(event: Dict[str, Any], session_id: str) -> Dict[str, Any]:
|
|
"""
|
|
L1: semantic translation + reason analysis (provided by Hermes).
|
|
"""
|
|
orchestrator = AIOrchestrator()
|
|
return await orchestrator.handle_l1(event, session_id)
|
|
|
|
|
|
async def _handle_l2(event: Dict[str, Any], session_id: str) -> Dict[str, Any]:
|
|
"""
|
|
L2: planning + review gate.
|
|
Produces an ActionPlan awaiting approval (handled via Telegram callback).
|
|
"""
|
|
orchestrator = AIOrchestrator()
|
|
return await orchestrator.handle_l2(event, session_id)
|
|
|
|
|
|
async def _handle_l0(event: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""L0: return raw event (for compatibility/monitoring)."""
|
|
return {"status": "ok", "echo": event.get("event_type")}
|
|
|
|
|
|
async def dispatch(event: Dict[str, Any], admin_chat_ids: Optional[list] = None) -> Dict[str, Any]:
|
|
"""
|
|
Main event routing entry (compatible with routes/bot_api_routes).
|
|
Output format matches dispatch_v1 for smooth migration.
|
|
"""
|
|
tier = _classify(event)
|
|
session_id = f"evt:{event.get('event_type')}:{event.get('source', 'unknown')}"
|
|
|
|
try:
|
|
if tier == "L0":
|
|
result = await _handle_l0(event)
|
|
elif tier == "L1":
|
|
result = await _handle_l1(event, session_id)
|
|
elif tier == "L2":
|
|
result = await _handle_l2(event, session_id)
|
|
else:
|
|
result = await _handle_l0(event)
|
|
|
|
# preserve legacy output format
|
|
return {
|
|
"tier": tier,
|
|
"sent": 1,
|
|
"errors": [],
|
|
"latency_ms": 0,
|
|
"payload": result,
|
|
}
|
|
except Exception as e:
|
|
logger.exception(f"[EventRouter] dispatch failed: {e}")
|
|
return {
|
|
"tier": tier,
|
|
"sent": 0,
|
|
"errors": [str(e)],
|
|
"latency_ms": 0,
|
|
"payload": None,
|
|
}
|
|
|
|
|
|
def _classify(event: Dict[str, Any]) -> str:
|
|
sev = event.get("severity", "info")
|
|
has_trace = bool(event.get("trace"))
|
|
event_type = event.get("event_type", "")
|
|
|
|
if sev in ("info", "success"):
|
|
return "L0"
|
|
if sev == "warning":
|
|
return "L1" if has_trace else "L0"
|
|
if sev == "alert":
|
|
if event_type in {"price_threat", "db_connection_error", "crawler_timeout",
|
|
"nim_quota_exhausted", "embedding_failure"}:
|
|
return "L2"
|
|
return "L1"
|
|
return "L0"
|