282 lines
9.0 KiB
Python
282 lines
9.0 KiB
Python
from uuid import uuid4
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, Request, Response
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.core.security import get_current_user
|
|
from app.db.session import get_db
|
|
from app.models.user import User
|
|
from app.schemas.ai import (
|
|
AIProviderStatusResponse,
|
|
AlertBriefRequest,
|
|
AlertBriefResponse,
|
|
BGPBriefRequest,
|
|
BGPBriefRecordResponse,
|
|
BGPBriefRecordSummary,
|
|
PlaygroundMessageActionResponse,
|
|
PlaygroundMessageCreateRequest,
|
|
PlaygroundMessageEditRequest,
|
|
PlaygroundMessageResendRequest,
|
|
PlaygroundMessageStopRequest,
|
|
PlaygroundSessionResponse,
|
|
PlaygroundSessionUpsertRequest,
|
|
PlaygroundThreadResponse,
|
|
SituationalAlertBriefRequest,
|
|
SituationalAlertBriefResponse,
|
|
SituationalAnalysisRequest,
|
|
SituationalAnalysisResponse,
|
|
)
|
|
from app.services.alert_ai_brief import build_alert_brief_request
|
|
from app.services.ai_client import AIProviderClient, get_ai_provider_client
|
|
from app.services.bgp_ai_brief import build_bgp_brief_request
|
|
from app.services.bgp_ai_brief_store import (
|
|
get_bgp_brief_record,
|
|
get_latest_bgp_brief_record,
|
|
list_bgp_brief_records,
|
|
save_bgp_brief_record,
|
|
)
|
|
from app.services.playground_session_store import (
|
|
get_playground_session,
|
|
upsert_playground_session,
|
|
)
|
|
from app.services.playground_chat_service import (
|
|
create_turn,
|
|
edit_user_message,
|
|
get_thread,
|
|
resend_turn,
|
|
stop_message,
|
|
)
|
|
from app.services.situational_alert_ai_brief import build_situational_alert_brief_request
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.get("/provider/status", response_model=AIProviderStatusResponse)
|
|
async def get_ai_provider_status(
|
|
request: Request,
|
|
response: Response,
|
|
current_user: User = Depends(get_current_user),
|
|
provider_client: AIProviderClient = Depends(get_ai_provider_client),
|
|
):
|
|
request_id = request.headers.get("X-Request-ID") or str(uuid4())
|
|
response.headers["X-Request-ID"] = request_id
|
|
return await provider_client.get_status(request_id=request_id)
|
|
|
|
|
|
@router.post("/situational-awareness/analyze", response_model=SituationalAnalysisResponse)
|
|
async def analyze_situational_awareness(
|
|
payload: SituationalAnalysisRequest,
|
|
request: Request,
|
|
response: Response,
|
|
current_user: User = Depends(get_current_user),
|
|
provider_client: AIProviderClient = Depends(get_ai_provider_client),
|
|
):
|
|
request_id = request.headers.get("X-Request-ID") or str(uuid4())
|
|
response.headers["X-Request-ID"] = request_id
|
|
return await provider_client.analyze(payload, request_id=request_id)
|
|
|
|
|
|
@router.get("/playground/thread", response_model=PlaygroundThreadResponse | None)
|
|
async def get_playground_thread(
|
|
session_key: str = "default",
|
|
current_user: User = Depends(get_current_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
return await get_thread(
|
|
db,
|
|
user_id=current_user.id,
|
|
session_key=session_key,
|
|
)
|
|
|
|
|
|
@router.get("/playground/session", response_model=PlaygroundSessionResponse | None)
|
|
async def get_saved_playground_session(
|
|
session_key: str = "default",
|
|
current_user: User = Depends(get_current_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
return await get_playground_session(
|
|
db,
|
|
user_id=current_user.id,
|
|
session_key=session_key,
|
|
)
|
|
|
|
|
|
@router.put("/playground/session", response_model=PlaygroundSessionResponse)
|
|
async def save_playground_session(
|
|
payload: PlaygroundSessionUpsertRequest,
|
|
current_user: User = Depends(get_current_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
return await upsert_playground_session(
|
|
db,
|
|
user_id=current_user.id,
|
|
payload=payload,
|
|
)
|
|
|
|
|
|
@router.post("/playground/messages", response_model=PlaygroundMessageActionResponse)
|
|
async def create_playground_message(
|
|
payload: PlaygroundMessageCreateRequest,
|
|
current_user: User = Depends(get_current_user),
|
|
provider_client: AIProviderClient = Depends(get_ai_provider_client),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
return await create_turn(
|
|
db,
|
|
user_id=current_user.id,
|
|
payload=payload,
|
|
provider_client=provider_client,
|
|
)
|
|
|
|
|
|
@router.post("/playground/messages/stop", response_model=PlaygroundMessageActionResponse)
|
|
async def stop_playground_message(
|
|
payload: PlaygroundMessageStopRequest,
|
|
current_user: User = Depends(get_current_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
return await stop_message(
|
|
db,
|
|
user_id=current_user.id,
|
|
payload=payload,
|
|
)
|
|
|
|
|
|
@router.post("/playground/messages/resend", response_model=PlaygroundMessageActionResponse)
|
|
async def resend_playground_message(
|
|
payload: PlaygroundMessageResendRequest,
|
|
current_user: User = Depends(get_current_user),
|
|
provider_client: AIProviderClient = Depends(get_ai_provider_client),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
return await resend_turn(
|
|
db,
|
|
user_id=current_user.id,
|
|
payload=payload,
|
|
provider_client=provider_client,
|
|
)
|
|
|
|
|
|
@router.post("/playground/messages/edit", response_model=PlaygroundMessageActionResponse)
|
|
async def edit_playground_message(
|
|
payload: PlaygroundMessageEditRequest,
|
|
current_user: User = Depends(get_current_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
return await edit_user_message(
|
|
db,
|
|
user_id=current_user.id,
|
|
payload=payload,
|
|
)
|
|
|
|
|
|
@router.get("/bgp/briefs", response_model=list[BGPBriefRecordSummary])
|
|
async def list_saved_bgp_briefs(
|
|
current_user: User = Depends(get_current_user),
|
|
):
|
|
return list_bgp_brief_records()
|
|
|
|
|
|
@router.get("/bgp/briefs/latest", response_model=BGPBriefRecordResponse | None)
|
|
async def get_latest_saved_bgp_brief(
|
|
current_user: User = Depends(get_current_user),
|
|
):
|
|
return get_latest_bgp_brief_record()
|
|
|
|
|
|
@router.get("/bgp/briefs/{brief_id}", response_model=BGPBriefRecordResponse)
|
|
async def get_saved_bgp_brief(
|
|
brief_id: str,
|
|
current_user: User = Depends(get_current_user),
|
|
):
|
|
record = get_bgp_brief_record(brief_id)
|
|
if record is None:
|
|
raise HTTPException(status_code=404, detail="BGP brief not found")
|
|
return record
|
|
|
|
|
|
@router.post("/bgp/brief", response_model=BGPBriefRecordResponse)
|
|
async def analyze_bgp_brief(
|
|
payload: BGPBriefRequest,
|
|
request: Request,
|
|
response: Response,
|
|
current_user: User = Depends(get_current_user),
|
|
provider_client: AIProviderClient = Depends(get_ai_provider_client),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
request_id = request.headers.get("X-Request-ID") or str(uuid4())
|
|
response.headers["X-Request-ID"] = request_id
|
|
|
|
brief_request, facts, context = await build_bgp_brief_request(
|
|
db,
|
|
incident_limit=payload.incident_limit,
|
|
anomaly_limit=payload.anomaly_limit,
|
|
collector_limit=payload.collector_limit,
|
|
)
|
|
brief_request.preferred_model = payload.preferred_model
|
|
brief_request.thinking = payload.thinking
|
|
|
|
analysis = await provider_client.analyze(brief_request, request_id=request_id)
|
|
return save_bgp_brief_record(
|
|
analysis,
|
|
request_id=request_id,
|
|
facts=facts,
|
|
context=context,
|
|
)
|
|
|
|
|
|
@router.post("/alerts/brief", response_model=AlertBriefResponse)
|
|
async def analyze_alert_brief(
|
|
payload: AlertBriefRequest,
|
|
request: Request,
|
|
response: Response,
|
|
current_user: User = Depends(get_current_user),
|
|
provider_client: AIProviderClient = Depends(get_ai_provider_client),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
request_id = request.headers.get("X-Request-ID") or str(uuid4())
|
|
response.headers["X-Request-ID"] = request_id
|
|
|
|
brief_request, facts, context = await build_alert_brief_request(
|
|
db,
|
|
alert_limit=payload.alert_limit,
|
|
)
|
|
brief_request.preferred_model = payload.preferred_model
|
|
brief_request.thinking = payload.thinking
|
|
|
|
analysis = await provider_client.analyze(brief_request, request_id=request_id)
|
|
return AlertBriefResponse(
|
|
**analysis.model_dump(),
|
|
title=brief_request.title,
|
|
objective=brief_request.objective,
|
|
facts=facts,
|
|
context=context,
|
|
)
|
|
|
|
|
|
@router.post("/situational-alerts/brief", response_model=SituationalAlertBriefResponse)
|
|
async def analyze_situational_alert_brief(
|
|
payload: SituationalAlertBriefRequest,
|
|
request: Request,
|
|
response: Response,
|
|
current_user: User = Depends(get_current_user),
|
|
provider_client: AIProviderClient = Depends(get_ai_provider_client),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
request_id = request.headers.get("X-Request-ID") or str(uuid4())
|
|
response.headers["X-Request-ID"] = request_id
|
|
|
|
brief_request, facts, context = await build_situational_alert_brief_request(db)
|
|
brief_request.preferred_model = payload.preferred_model
|
|
brief_request.thinking = payload.thinking
|
|
|
|
analysis = await provider_client.analyze(brief_request, request_id=request_id)
|
|
return SituationalAlertBriefResponse(
|
|
**analysis.model_dump(),
|
|
title=brief_request.title,
|
|
objective=brief_request.objective,
|
|
facts=facts,
|
|
context=context,
|
|
)
|