Stabilize runtime auth and E2E coverage
This commit is contained in:
parent
6a3e3b541c
commit
188e899394
133 changed files with 55987 additions and 6775 deletions
66
apps/api/app/routes/personas.py
Normal file
66
apps/api/app/routes/personas.py
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
"""Persona catalog routes."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter, HTTPException, Response, status
|
||||
from pydantic import BaseModel
|
||||
|
||||
from ..deps import CurrentPrincipal
|
||||
from ..persona_repository import CatalogPersona, list_catalog_personas
|
||||
|
||||
router = APIRouter(prefix="/personas", tags=["personas"])
|
||||
|
||||
|
||||
class PersonaSummary(BaseModel):
|
||||
code: str
|
||||
display_name: str
|
||||
difficulty: str
|
||||
theory_target: list[str]
|
||||
demographics: dict[str, Any]
|
||||
presenting_summary: str
|
||||
voice_preset: str | None = None
|
||||
source: str = "database"
|
||||
degraded: bool = False
|
||||
|
||||
|
||||
def _first_text_value(data: dict[str, Any]) -> str:
|
||||
for value in data.values():
|
||||
if isinstance(value, str) and value.strip():
|
||||
return value.strip()
|
||||
return ""
|
||||
|
||||
|
||||
def _summary(entry: CatalogPersona) -> PersonaSummary:
|
||||
card = entry.card
|
||||
return PersonaSummary(
|
||||
code=card.code,
|
||||
display_name=card.display_name,
|
||||
difficulty=card.difficulty,
|
||||
theory_target=card.theory_target,
|
||||
demographics=card.demographics,
|
||||
presenting_summary=_first_text_value(card.presenting),
|
||||
source=entry.source,
|
||||
degraded=entry.degraded,
|
||||
)
|
||||
|
||||
|
||||
@router.get("", response_model=list[PersonaSummary])
|
||||
async def list_personas(response: Response, _principal: CurrentPrincipal) -> list[PersonaSummary]:
|
||||
"""Return latest approved personas from app.persona_card."""
|
||||
try:
|
||||
personas = await list_catalog_personas()
|
||||
except Exception as exc:
|
||||
raise HTTPException(
|
||||
status.HTTP_503_SERVICE_UNAVAILABLE,
|
||||
detail="persona catalog database unavailable",
|
||||
) from exc
|
||||
|
||||
if any(entry.degraded for entry in personas):
|
||||
response.headers["X-Vignette-Degraded"] = "true"
|
||||
response.headers["X-Vignette-Catalog-Source"] = "seed_fallback"
|
||||
else:
|
||||
response.headers["X-Vignette-Catalog-Source"] = "database"
|
||||
|
||||
return [_summary(entry) for entry in personas]
|
||||
Loading…
Add table
Add a link
Reference in a new issue