feat(dashboard): console fallbacks for the real API (#12)
CI / ruff · pytest (pull_request) Successful in 1m37s
CI / ruff · pytest (pull_request) Successful in 1m37s
- personas degrade: /demo/personas → doctor's patients (hero first) → env token - scenario file guessed from the transliterated first name (andrey.jsonl), like the backend - «Подключить демо-пациента»: connects the synthetic hero via /patients/connect when no seed - connect code prefilled from ?code= of the console link Refs #17 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -135,24 +135,51 @@ class ConsoleApi:
|
||||
params = {"since_id": since_id, "open_only": str(open_only).lower()}
|
||||
return list(self._request("GET", f"/api/v1/doctors/{doctor}/alerts", params=params))
|
||||
|
||||
def connect(self, body: dict[str, Any]) -> dict[str, Any]:
|
||||
"""`POST /patients/connect` (ConnectPatientIn) → {token, code, deep_link}."""
|
||||
return dict(self._request("POST", "/api/v1/patients/connect", json=body, timeout=30))
|
||||
|
||||
def ack(self, alert_id: int, doctor: str) -> dict[str, Any]:
|
||||
return dict(self._request("POST", f"/api/v1/alerts/{alert_id}/ack", json={"doctor_id": doctor}))
|
||||
|
||||
|
||||
def personas_or_fallback(api: ConsoleApi) -> tuple[list[dict[str, Any]], str | None]:
|
||||
"""Demo personas from the API; on failure a single fallback persona (env token) and the error text."""
|
||||
"""Demo personas for the selector, degrading step by step so the console always has someone to talk as.
|
||||
|
||||
1. `GET /demo/personas` (patients with a scenario file);
|
||||
2. the demo doctor's patient list (real tokens; no scenario file yet, e.g. before #18 lands);
|
||||
3. a single persona with the token from `DEMO_PERSONA_TOKEN` (fixtures use `tok-andrey`).
|
||||
Returns the personas and a note for the presenter when a fallback was used.
|
||||
"""
|
||||
try:
|
||||
personas = [p for p in api.personas() if isinstance(p, dict) and p.get("token")]
|
||||
if personas:
|
||||
return personas, None
|
||||
error = "API вернул пустой список персон"
|
||||
error = "API не вернул персон со сценарием"
|
||||
except ApiError as exc:
|
||||
error = str(exc)
|
||||
try:
|
||||
patients = [p for p in api.patients(doctor_id()) if isinstance(p, dict) and p.get("token")]
|
||||
except ApiError:
|
||||
patients = []
|
||||
if patients:
|
||||
# The demo hero first: the scenario file is guessed from the name later (`default_scenario_path`).
|
||||
patients.sort(key=lambda p: not str(p.get("display_name", "")).startswith("Андрей"))
|
||||
personas = [
|
||||
{
|
||||
"token": p["token"],
|
||||
"display_name": p.get("display_name") or p["token"],
|
||||
"therapy_day": p.get("therapy_day", 0),
|
||||
"scenario": None,
|
||||
}
|
||||
for p in patients
|
||||
]
|
||||
return personas, f"{error}; показаны пациенты врача"
|
||||
token = fallback_token()
|
||||
fallback = {
|
||||
"token": token,
|
||||
"display_name": "Андрей С." if token == DEFAULT_TOKEN else token,
|
||||
"therapy_day": 0,
|
||||
"scenario": "data/synthetic/andrey.jsonl" if token == DEFAULT_TOKEN else None,
|
||||
"scenario": None,
|
||||
}
|
||||
return [fallback], error
|
||||
return [fallback], f"{error}; используется токен из окружения"
|
||||
|
||||
Reference in New Issue
Block a user