feat(dashboard): console fallbacks for the real API (#12)
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:
2026-10-04 12:50:42 +03:00
co-authored by Claude Opus 5.5
parent 260422138a
commit 8d12aa3d08
5 changed files with 130 additions and 13 deletions
+21 -4
View File
@@ -151,13 +151,30 @@ def load_scenario(path: str | Path, root: Path = REPO_ROOT) -> Scenario:
return parse_scenario(text)
def default_scenario_path(persona: dict[str, Any]) -> str | None:
"""Scenario path from the persona, or `data/synthetic/<name>.jsonl` guessed from a `tok-<name>` token."""
_TRANSLIT = {
"а": "a", "б": "b", "в": "v", "г": "g", "д": "d", "е": "e", "ё": "e", "ж": "zh", "з": "z", "и": "i",
"й": "y", "к": "k", "л": "l", "м": "m", "н": "n", "о": "o", "п": "p", "р": "r", "с": "s", "т": "t",
"у": "u", "ф": "f", "х": "kh", "ц": "ts", "ч": "ch", "ш": "sh", "щ": "shch", "ъ": "", "ы": "y", "ь": "",
"э": "e", "ю": "yu", "я": "ya",
} # fmt: skip
def persona_slug(display_name: str) -> str:
"""'Андрей С.' → 'andrey': the backend names scenario files by the transliterated first name (#12)."""
first = (display_name.split() or [""])[0].lower()
return "".join(_TRANSLIT.get(ch, ch if ch.isascii() and ch.isalnum() else "") for ch in first)
def default_scenario_path(persona: dict[str, Any], root: Path = REPO_ROOT) -> str | None:
"""Scenario path from the persona, else `data/synthetic/<slug>.jsonl` guessed from the name or `tok-<slug>`."""
if persona.get("scenario"):
return str(persona["scenario"])
token = str(persona.get("token", ""))
slugs = [persona_slug(str(persona.get("display_name", "")))]
if token.startswith("tok-"):
guess = f"data/synthetic/{token.removeprefix('tok-')}.jsonl"
if resolve_path(guess).exists():
slugs.append(token.removeprefix("tok-"))
for slug in filter(None, slugs):
guess = f"data/synthetic/{slug}.jsonl"
if resolve_path(guess, root).exists():
return guess
return None