webrtc-komaroff · source snapshot · 16.09.2026

webrtc-komaroff: путь реплики до карты

От реплики пользователя до результатаОСНОВНОЙ СЦЕНАРИЙСказать или написатьбраузер → CoreВыполнить сценарийAgent → workflow → toolsПоказать результаттекст / аэропорты / маршрутЧТО НУЖНО ПОНЯТЬ РАЗРАБОТЧИКУГраницы процессовmedia / state / inferenceПорядок выполнениязапросы / retries / commitЦена измененияcontracts / tests / delivery

Медиасоединение, состояние диалога и модель разделены. Два последовательных оркестратора — главный кандидат на упрощение.

SOURCE · src_core/main.py · src_agent/service.py · stack/webrtc.drs

webrtc-komaroff · source snapshot · 16.09.2026

Что именно проверено

Границы доказательствСлойФактГраница выводаSource772de4a · remote mainЧистый отдельный worktreeTests25 Ruby + 7 PythonБез GPU и live NATSАрхитектураКод + contracts + DRSНе текущий runtimeНагрузкаBaseline отсутствуетНет обещаний ускорения

Снимок от 16.09.2026. Локальный checkout не переключался; новая документация привязана к указанному commit.

VERIFIED / UNKNOWN · src_langgraph_rb_node/spec · tests/test_llm_routing.py · stack/webrtc.drs

webrtc-komaroff · source snapshot · 16.09.2026

Кому принадлежат компоненты

Границы компонентовДИАЛОГБраузертекст / WebRTCкарта и сообщенияCoreHTTP + mediaживые соединенияAgent → workflowсостояние / сценарииPostgres / LLM / toolsРАСПОЗНАВАНИЕ — СОСЕДНИЙ РЕПОЗИТОРИЙCore / audioPCM → NATSpy_faster_whisperVAD + ASR bridgeВнешний LinTOHTTP inferenceОБРАТНЫЙ ПУТЬAgent / CoreUI-событияNATS WebSocketnats.events.user123Браузертекст / MapLibre

Whisper — отдельный репозиторий. Публичные маршруты его WebUI объявлены здесь; rag-stack остаётся за границей исследования.

SOURCE · stack/webrtc.drs · src_core/processors/whisper_stream_node.py

webrtc-komaroff · source snapshot · 16.09.2026

Как устроен монорепозиторий

Иерархия модулейwebrtc-komaroffservice roots src_*Вход и интерфейсsrc_front / src_coreHTTP + WebRTCTypeScript / aiohttpaiortc / AudioGraphДиалог и сценарииsrc_agent / src_langgraph*Python + два Ruby runtimeruntime_state / eventssrc_shared/contractsРесурсы и поставкаsrc_llm / src_api_gatewayМодель / инструментыsrc_postgres / dockerstack / CI

src_* — корни сервисов, src_front/src — внутренний каталог frontend. Перенос каталогов сам по себе не устраняет legacy.

SOURCE · docker/docker-compose.yml · src_shared/contracts · stack/webrtc.drs

webrtc-komaroff · source snapshot · 16.09.2026

Один текстовый turn

Одна текстовая репликаUICoreAgentWorkflowLLM / toolsPOST /core/messageNATS: turn + runtime identityruntime + textrouting / params / toolsdata / errorsnext_runtime + client_eventscommit → NATS UI eventsHTTP reply через Core

UI получает содержательный результат через события. HTTP-ответ и доставка UI-команды — разные участки пути.

SOURCE · src_core/main.py · src_agent/service.py · src_agent/agent.py

webrtc-komaroff · source snapshot · 16.09.2026

Голос выходит на тот же Agent

Звук до готовой репликиБраузерCoreWhisperLinTOAgentSDP → audio track20 мс PCM framespending + phrase_idWAV → HTTP ASRtextphrase_id + textстабильный turn_idрезультат → UI events

phrase_id связывает распознавание с turn_id. Завершение WebRTC и завершение inference требуют раздельной обработки.

SOURCE · src_core/main.py · src_core/processors/whisper_stream_node.py

webrtc-komaroff · source snapshot · 16.09.2026

Аудиоконтракт между репозиториями

Формат аудиоОДИН ПАКЕТ4 байтадлина JSON · big-endianMetadata JSONtype / seq / session_idPCM bytesint16 little-endianПАРАМЕТРЫ ПОТОКА16 000 Гцmono · sample_width = 220 мс / frame640 байт PCM32 000 байт/сбез metadata и транспорта

Пропускная способность рассчитана по формату. Наличие seq в пакете ещё не доказывает контроль потерь у потребителя.

SOURCE / РАСЧЁТ · src_core/processors/track_source_node.py · src_core/processors/whisper_stream_node.py

webrtc-komaroff · source snapshot · 16.09.2026

Куда ведёт вызов из Core

Дерево вызовов Agentmessage_handler → handle_transcriptionCore handlers → NATS → AgentRunner.run_run_with_optimistic_locksrc_agent/agent.pyWorkflow requestNATS → Engine.runGraphRunner.runRequestExecutor → LLM / toolsave_runtime_stateruntime_state.pyUPDATE с проверкой versionотдельная операцияpersist_chat_turnutils/db.pyтранзакция сообщенийпосле runtime UPDATE

Дерево выборочное: показаны границы, где появляются внешние вызовы и постоянные записи.

SOURCE · src_core/handlers/handle_transcription.py · src_agent/agent.py · src_langgraph_rb_node/lib/src_langgraph_rb_node/runtime/engine.rb

webrtc-komaroff · source snapshot · 16.09.2026

Состояние диалога: два commit вместо одного

Точки фиксации turnТЕКУЩАЯ ПОСЛЕДОВАТЕЛЬНОСТЬПрочитать versionruntime_stateВызвать workflowвнешние эффектыUPDATE runtimeWHERE version = expectedЗаписать историюpersist_chat_turnВЛАДЕНИЕ ДАННЫМИsessionssession → userruntime_stateversion / pending / contexteventsunique(session, turn)РИСК ПРИ СБОЕ ПОСЛЕ UPDATERuntime уже записанистория ещё нетОбщий retryснова вызывает workflowЛишние внешние вызовыINFERRED; частота неизвестна

Уникальный ключ истории защищает строку, но не запрещает повторно вызвать модель или инструмент.

SOURCE · src_agent/agent.py · src_agent/repositories/runtime_state.py · src_agent/utils/db.py

webrtc-komaroff · source snapshot · 16.09.2026

Три workflow runtime — одна продуктовая роль

Сравнение workflowRuntimeМеханизмТекущая границаPythonLangGraphcompile без checkpointerRubyСобственный DSLАльтернативные сценарииRuby nodeAsyncGraph 0.1.2Ruby; не Node.jsВыборWORKFLOW_RUNTIMEdefault ruby_node; без fallback

Сначала нужен общий корпус parity. Неиспользование движка в одном DRS не доказывает отсутствие других consumers.

SOURCE · src_langgraph/main.py · src_langgraph_rb · src_langgraph_rb_node · stack/webrtc.drs

webrtc-komaroff · source snapshot · 16.09.2026

Аэропорты: где действительно нужны LLM-вызовы

Вызовы сценария аэропортовНОВЫЙ НЕЗАКРЕПЛЁННЫЙ СЦЕНАРИЙrouting_decisionLLM № 1get_current_positiontooltool_paramsLLM № 2search_airports_nearbytoolТОЛЬКО ПРИ ЯВНОМ ЗАПРОСЕ МАРШРУТАКоординаты аэропортаданные tool responsebuild_routeещё один toolФинальная фразадетерминированный текст

Лишний LLM для маршрута и финального ответа уже удалён. Предложение — объединить route + params, сохранив качество и валидацию.

SOURCE · src_langgraph_rb_node/spec/scenarios/find_nearest_airport_spec.rb · src_langgraph_rb_node/lib

webrtc-komaroff · source snapshot · 16.09.2026

Инструменты пока демонстрационные

Ограничения инструментовИнструментРеализацияЧего не доказываетПозицияФиксированные координатыНе геолокация пользователяАэропортыЛокальный каталогНе актуальность справочникаРейсы / погодаFixtures / mockНе live-данныеМаршрутДуга большого кругаНе дорожный маршрут / ETA

Это стенд голосового интерфейса и сценарной оркестрации. Реальные источники должны иметь provenance, freshness и явные ошибки.

SOURCE · src_api_gateway/main.py

webrtc-komaroff · source snapshot · 16.09.2026

Очередь начинается раньше семафора

Накопление ожидающей работыСЕЙЧАСВходящие кадрыкаждые 20 мсcreate_taskpending tasks растутSemaphore(3)ограничено исполнениеПРЕДЛОЖЕНИЕAdmission budgetбайты / сессии / deadlineBounded queueзаданный maxsizeWorkersявная overload policy

Семафор не ограничивает количество уже созданных задач. Нужны p95 queue wait, oldest age, RSS и тест медленного downstream.

SOURCE → ПРЕДЛОЖЕНИЕ 03 · src_core/processors/whisper_stream_node.py · src_llm

webrtc-komaroff · source snapshot · 16.09.2026

Реплики требуют не только количества

Распределение запросовRUBY WORKFLOW СЕЙЧАСNATS subjectодин requestОбычные subscribersкаждая реплика получаетВнешние effectsвозможное повторениеЦЕЛЕВОЙ КОНТРАКТQueue groupодин выбранный workerTurn identityидемпотентностьSession orderingотдельная гарантия

Queue group устраняет fan-out одной подписки, но не даёт порядка сессии, durable delivery или exactly-once.

SOURCE → ПРЕДЛОЖЕНИЕ 04 · src_langgraph_rb_node/lib/src_langgraph_rb_node/runtime/service.rb · src_langgraph_rb/lib/src_langgraph_rb/runtime/service.rb · docs.nats.io

webrtc-komaroff · source snapshot · 16.09.2026

Браузеру нужен поток своей сессии

Session scoped eventsСЕЙЧАСAgent / Coreclient_eventsnats.events.user123фиксированный subjectБраузерприменяет событияПРЕДЛОЖЕНИЕПроверенная identityserver-side ACLsession event streamcursor + sequenceSnapshot + reconnectдедупликация результата

Общее имя subject не является изоляцией. Многопользовательский режим требует проверки чужих подписок и восстановления после disconnect.

SOURCE → ПРЕДЛОЖЕНИЕ 06 · src_front/src · src_agent/service.py · docs.nats.io

webrtc-komaroff · source snapshot · 16.09.2026

Поставка не равна live-проверке

Слои доказательства поставкиИССЛЕДОВАНОSourceremote main 772de4aTests25 Ruby + 7 PythonDesired stackstack/webrtc.drsНЕ ПРОВЕРЯЛОСЬ ЗАНОВОRunning imagedigest / replicas ?Health / update staterollout ?Live acceptanceголос / карта ?ВАЖНО ДЛЯ РЕВЬЮCItests job закомментированаDRSобъявлены три runtimeWORKFLOW_RUNTIMEdefault: ruby_node

Зелёная сборка не подтверждает работающий голосовой путь. В этом исследовании runtime не менялся и live smoke не выполнялся.

VERIFIED / UNKNOWN · .gitlab-ci.yml · docker/docker-compose.yml · stack/webrtc.drs

webrtc-komaroff · source snapshot · 16.09.2026

Как сокращать legacy без потери поведения

Переход к одному workflowСНАЧАЛАКорпус сценариевrouting / edit / pendingПрогоны трёх runtimeодинаковые fixturesУчёт consumerssubjects / DRS / jobsПОСЛЕ PARITYОдин production runtimeвыбор по результатамУдаление альтернативкод + image + configКонтрактные тестыUI / tools / history

Удалять можно доказанно неиспользуемый путь. Размер исходников — показатель сопровождения, а не доказательство производительности.

ПРЕДЛОЖЕНИЕ 05 · src_langgraph · src_langgraph_rb · src_langgraph_rb_node

webrtc-komaroff · source snapshot · 16.09.2026

Более крупный шаг: один сервис диалога

Консолидация orchestrationСЕЙЧАСCoreHTTP / mediaAgentstate + retryWorkflowscenario graphLLM / toolsресурсные сервисыКАНДИДАТCoreграница сохраняетсяDialogue serviceAgent + один workflowLLM / toolsграницы сохраняются

Исчезает один request/reply boundary. Выигрыш latency нужно измерить; разделение media и GPU сохраняет смысл.

ПРЕДЛОЖЕНИЕ 07 · src_agent/agent.py · src_langgraph_rb_node/lib/src_langgraph_rb_node/runtime/service.rb

webrtc-komaroff · source snapshot · 16.09.2026

Полная замена нужна при требованиях к recovery

Durable orchestration candidateПРИЁМCommand APIidempotency keyPostgresjob + outboxDispatchповторяемая доставкаИСПОЛНЕНИЕWorkerlease / step identityCheckpoint + effectsсохранённый прогрессResult streamcursor / replay

Это самый дорогой вариант. Принимать его следует по crash matrix и допустимой потере заданий, а не по моде на фреймворк.

ПРЕДЛОЖЕНИЕ 08 · src_agent/agent.py · docs.nats.io · docs.langchain.com

webrtc-komaroff · source snapshot · 16.09.2026

Приоритет: корректность, меньше вызовов, проще схема

План решенийШагИзмерениеУсловие перехода04 + 03Дубли / queue age / RSSRetries и overload контролируются01 + 02HTTP / LLM calls; p95Качество не ухудшилось05 + 06Parity / чужие событияОдин runtime; session isolation07 → 08Boundary cost / recoveryПрототип подтверждает пользу

Для каждого изменения есть отдельный Markdown: доказательства, схема, метрики, риски и возврат на прежний путь.

ПЛАН ПРОВЕРКИ · src_agent/agent.py · src_core/main.py · opentelemetry.io

1 / 2

Служебные вложения доступны в исходном архиве.