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:
@@ -89,16 +89,55 @@ def select_persona(container: Any = None) -> dict[str, Any]:
|
||||
where = container or st.sidebar
|
||||
personas, error = _personas(get_api().base_url)
|
||||
if error:
|
||||
where.caption(f"⚠️ персоны из API недоступны ({error}); используется токен из окружения")
|
||||
where.caption(f"⚠️ {error}")
|
||||
tokens = [p["token"] for p in personas]
|
||||
current = st.session_state.get("console_token")
|
||||
index = tokens.index(current) if current in tokens else 0
|
||||
labels = {p["token"]: f"{p.get('display_name') or p['token']} ({p['token']})" for p in personas}
|
||||
token = where.selectbox("Пациент демо", tokens, index=index, format_func=lambda t: labels[t])
|
||||
labels = {p["token"]: f"{p.get('display_name') or p['token']} ({p['token'][:12]})" for p in personas}
|
||||
token = where.selectbox("Пациент демо", tokens, index=index, format_func=lambda t: labels.get(t, t))
|
||||
st.session_state["console_token"] = token
|
||||
return next(p for p in personas if p["token"] == token)
|
||||
|
||||
|
||||
# Synthetic demo hero (docs/product/01_demo_persona.md); the SNILS is fake and used only to derive the token.
|
||||
DEMO_HERO = {
|
||||
"display_name": "Андрей С.",
|
||||
"birth_year": 1992,
|
||||
"sex": "m",
|
||||
"snils": "000-000-017 17",
|
||||
"drug": "сертралин",
|
||||
"dose": "50 мг",
|
||||
"times": ["08:00"],
|
||||
"instructions": "1 раз в сутки утром после еды",
|
||||
"modules": ["veteran", "depression"],
|
||||
}
|
||||
|
||||
|
||||
def _connect_hero() -> None:
|
||||
name = st.session_state.get("console_hero_name") or DEMO_HERO["display_name"]
|
||||
body = {**DEMO_HERO, "doctor_id": doctor_id(), "display_name": name}
|
||||
try:
|
||||
out = get_api().connect(body)
|
||||
except ApiError as exc:
|
||||
hint = " — пациент уже подключён, выберите его в списке" if "409" in str(exc) else ""
|
||||
flash(f"Подключение не выполнено: {exc}{hint}", "warning" if hint else "error")
|
||||
return
|
||||
token = str(out.get("token", ""))
|
||||
st.session_state["console_token"] = token
|
||||
st.session_state[f"console_code:{token}"] = str(out.get("code", ""))
|
||||
_personas.clear()
|
||||
flash(f"Пациент подключён, код {out.get('code', '')}. Нажмите «Начать» в чате.", "success")
|
||||
|
||||
|
||||
def render_connect_hero(container: Any = None) -> None:
|
||||
"""Fallback when the demo seed is missing: connect the synthetic hero through the doctor API."""
|
||||
where = container or st.sidebar
|
||||
with where.expander("Подключить демо-пациента"):
|
||||
st.caption("Если сид демо не загружен: врач подключает Андрея (синтетика) — как на приёме.")
|
||||
st.text_input("Имя", value="Андрей С.", key="console_hero_name")
|
||||
st.button("Подключить", key="console-connect", on_click=_connect_hero)
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------------------------ clock
|
||||
def _drain_quiet(api: ConsoleApi, token: str) -> None:
|
||||
try:
|
||||
@@ -137,6 +176,7 @@ def _reset() -> None:
|
||||
flash(f"Сброс не выполнен: {exc}")
|
||||
return
|
||||
forget_demo_state()
|
||||
_personas.clear() # the seed may be recreated on reset
|
||||
flash("Демо сброшено: часы вернулись к реальному времени, чат и прогресс сценария очищены.", "success")
|
||||
|
||||
|
||||
@@ -263,7 +303,10 @@ def render_chat(token: str, *, height: int = 520, key: str = "chat") -> None:
|
||||
left, right = st.columns([5, 1])
|
||||
left.text_input("Сообщение", key=input_key, label_visibility="collapsed", placeholder="Сообщение пациента…")
|
||||
right.form_submit_button("➤", width="stretch", on_click=_submit_text, args=(token, input_key))
|
||||
with st.expander("Начать диалог / код подключения"):
|
||||
code = st.query_params.get("code") # connect links from the doctor point to the console with ?code=
|
||||
if code and not st.session_state.get(f"console_code:{token}"):
|
||||
st.session_state[f"console_code:{token}"] = code
|
||||
with st.expander("Начать диалог / код подключения", expanded=bool(code)):
|
||||
st.text_input("Код подключения (необязательно)", key=f"console_code:{token}", placeholder="DEMO-0001")
|
||||
c1, c2 = st.columns(2)
|
||||
c1.button("🚀 Начать", key=f"{key}-start", on_click=_send, args=(token, "start"), width="stretch")
|
||||
|
||||
Reference in New Issue
Block a user