"""Live progress of the chat agent for streaming channels (web SSE). The SSE endpoint sets a queue in the context; the agent pushes events while it works: status — a tool step in plain Russian («Смотрю вашу карту ЕМИАС…») delta — a chunk of the answer as the model writes it reset — the streamed text so far was a preface before tool calls: clear it Channels without a queue (Telegram, tests) are unaffected. Deltas are the raw model text: the final reply (forbidden-output filter, sources footer) always comes in the closing `done` event and replaces it. """ import asyncio from contextvars import ContextVar from typing import Any STREAM: ContextVar[asyncio.Queue[tuple[str, Any]] | None] = ContextVar("agent_stream", default=None) TOOL_STATUS = { "get_patient_record": "Смотрю вашу карту ЕМИАС…", "check_drug_for_patient": "Проверяю препарат по вашей карте: болезни, непереносимости, другие лекарства…", "get_drug_info": "Открываю инструкцию к препарату (ГРЛС)…", "search_guidelines": "Ищу в клинических рекомендациях Минздрава…", } def active() -> bool: return STREAM.get() is not None def emit(kind: str, payload: Any) -> None: q = STREAM.get() if q is not None: q.put_nowait((kind, payload))