lct-hack/frontend/src/features/health/StandStatus.tsx
Ivan Gerasimov 34eb88270e lct-21: make demo, честный README, готовность стенда
make demo поднимает стенд целиком: проверяет модели, базу, миграции,
сценарии, бэкенд с голосом в офлайн-режиме и фронт. Обкатан заранее,
как и требует карточка, — и сразу поймал ошибку: `cd backend && команда &`
уводит в фон всю связку, родительская оболочка остаётся на месте,
и фронт запускался не из репозитория.

Пять диалогов подряд через make demo: без сбоев, ход 965–1210 мс,
первая реплика 78–115 мс. make dev проверен целиком — образ фронта
собирается, страница отдаётся.

README переписан под факт: два шага до стенда и таблица того, что
работает, вместо обещаний. Экран готовности показывает курсанту, почему
звонящий молчит, вместо тишины без объяснений.

В Makefile записано, что make test и make demo нельзя запускать
одновременно: они просят у uv разные группы зависимостей, uv пересобирает
одно окружение, и второй запуск молча ждёт блокировку.
2026-09-17 22:24:48 +03:00

21 lines
1.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Готовность стенда. Модели грузятся несколько секунд на старте, и курсант
// не должен догадываться, почему звонящий молчит (docs/arch/FRONTEND.md).
import { useHealth } from "@/shared/api/http";
export function StandStatus() {
const health = useHealth();
if (health.isError) {
return <div className="stand stand-bad">Сервер не отвечает — занятие не запустить.</div>;
}
if (!health.data) return null;
const troubles: string[] = [];
if (!health.data.models_ready) troubles.push("голосовой контур выключен: звонок будет без звука");
if (!health.data.embeddings_ready) troubles.push("нет модели эмбеддингов: подсказки идут по порядку чек-листа");
if (!health.data.scenarios_loaded) troubles.push("библиотека сценариев пуста");
if (troubles.length === 0) return null;
return <div className="stand stand-warn">Стенд не в полной готовности — {troubles.join("; ")}.</div>;
}