main
py 90 lines 3.56 KB
Raw
1 from fastapi import APIRouter
2 from fastapi import Depends
3 from fastapi import Security
4 from loguru import logger
5 from sqlalchemy.ext.asyncio import AsyncSession
6 from starlette.responses import StreamingResponse
7
8 from app.auth.utils import AuthHandler
9 from app.connectors.talon.schema.talon import TalonInvestigateRequest
10 from app.connectors.talon.schema.talon import TalonInvestigateResponse
11 from app.connectors.talon.schema.talon import TalonJobResponse
12 from app.connectors.talon.schema.talon import TalonMessageRequest
13 from app.connectors.talon.schema.talon import TalonStatusResponse
14 from app.connectors.talon.schema.talon import TalonTemplatesResponse
15 from app.connectors.talon.services.talon import get_talon_job
16 from app.connectors.talon.services.talon import get_talon_status
17 from app.connectors.talon.services.talon import investigate_alert
18 from app.connectors.talon.services.talon import list_talon_templates
19 from app.connectors.talon.services.talon import stream_talon_message
20 from app.db.db_session import get_db
21
22 talon_router = APIRouter()
23
24
25 @talon_router.post(
26 "/message",
27 response_class=StreamingResponse,
28 description="Send a message to Talon and stream the SSE response",
29 dependencies=[Security(AuthHandler().require_any_scope("admin", "analyst"))],
30 )
31 async def send_message(request: TalonMessageRequest) -> StreamingResponse:
32 """Send a message to Talon and stream the response as SSE."""
33 logger.info(f"Sending message to Talon: {request.message}")
34 return StreamingResponse(
35 stream_talon_message(request),
36 media_type="text/event-stream",
37 headers={
38 "Cache-Control": "no-cache",
39 "Connection": "keep-alive",
40 "X-Accel-Buffering": "no",
41 },
42 )
43
44
45 @talon_router.post(
46 "/investigate",
47 response_model=TalonInvestigateResponse,
48 description="Trigger a Talon investigation for a specific alert",
49 dependencies=[Security(AuthHandler().require_any_scope("admin", "analyst"))],
50 )
51 async def trigger_investigation(request: TalonInvestigateRequest) -> TalonInvestigateResponse:
52 """Trigger an investigation for a specific alert."""
53 logger.info(f"Triggering investigation for alert ID: {request.alert_id}")
54 return await investigate_alert(request)
55
56
57 @talon_router.get(
58 "/status",
59 response_model=TalonStatusResponse,
60 description="Get the current Talon service status",
61 dependencies=[Security(AuthHandler().require_any_scope("admin", "analyst"))],
62 )
63 async def get_status() -> TalonStatusResponse:
64 """Get the current status of the Talon service."""
65 logger.info("Fetching Talon status")
66 return await get_talon_status()
67
68
69 @talon_router.get(
70 "/templates",
71 response_model=TalonTemplatesResponse,
72 description="List the prompt templates available in NanoClaw's CoPilot group (for replay picker)",
73 dependencies=[Security(AuthHandler().require_any_scope("admin", "analyst"))],
74 )
75 async def get_templates() -> TalonTemplatesResponse:
76 """Proxy NanoClaw GET /templates — read-only template metadata, no bodies."""
77 logger.info("Fetching Talon templates list")
78 return await list_talon_templates()
79
80
81 @talon_router.get(
82 "/jobs/{alert_id}",
83 response_model=TalonJobResponse,
84 description="Get the Talon job status and report for a specific alert",
85 dependencies=[Security(AuthHandler().require_any_scope("admin", "analyst"))],
86 )
87 async def get_job(alert_id: int, db: AsyncSession = Depends(get_db)) -> TalonJobResponse:
88 """Get the job status for a specific alert."""
89 logger.info(f"Fetching Talon job for alert ID: {alert_id}")
90 return await get_talon_job(alert_id, db)