from typing import Annotated, Literal from fastapi import APIRouter, Depends, HTTPException, Request from pydantic import BaseModel, ConfigDict, Field, StrictBool from sqlmodel import Session from ..core.api_validation import SensitivePayloadRoute from ..db.session import get_session from ..services import managed_ai from ..services.audit_logger import log_event from ..services.user_access import authorize_request router = APIRouter(prefix="/api/settings/ai", route_class=SensitivePayloadRoute) DatabaseSession = Annotated[Session, Depends(get_session)] class ManagedAiSettings(BaseModel): model_config = ConfigDict(extra="forbid") enabled: StrictBool | None = None gatewayUrl: str | None = Field(default=None, max_length=2048) capability: Literal["assistant.ops@1"] | None = None credential: str | None = Field(default=None, max_length=64) @router.get("") def get_config(request: Request, db: DatabaseSession): authorize_request(request) return managed_ai.get_config(db) @router.get("/status") def get_status(request: Request, db: DatabaseSession): authorize_request(request) return managed_ai.status(db) def _admin(request: Request): user = authorize_request(request) if user.role != "admin": raise HTTPException(403, "Only administrators can configure managed AI") return user @router.patch("") def update_config(payload: ManagedAiSettings, request: Request, db: DatabaseSession): user = _admin(request) try: config = managed_ai.save_config(db, payload.model_dump(exclude_none=True)) except ValueError as error: raise HTTPException(422, str(error)) from None log_event(db, source="manual", identity=user.id, action_id="settings.ai.update", target="modelforge", target_type="settings", risk="low", policy_decision="allowed", reason="Managed AI configuration updated", result="success", redacted_metadata={"enabled": config["enabled"], "capability": config["capability"]}) return config @router.post("/test") def test_inference(request: Request, db: DatabaseSession): _admin(request) try: result = managed_ai.analyze(db, "Beantwoord in één zin: wat is de status volgens deze evidence?", [{"rank": 1, "title": "Verbindingstest", "excerpt": "Dit is synthetische testevidence. De verbindingstest staat op ready; er is geen echte server-health-informatie meegegeven."}]) except managed_ai.ManagedAiError as error: raise HTTPException(503, {"code": error.code, "correlationId": error.correlation_id, "message": "ModelForge-inferentie niet beschikbaar."}) from None return {"success": True, **result}