Files
gitmost/docs/backlog/streaming-dictation-feature-toggle.md
claude_code ee25d52965 docs(backlog): gate streaming dictation behind a feature toggle (default off)
Design entry: hide the silence-cut streaming dictation path behind a per-
workspace settings.ai.dictationStreaming flag, default false, with batch
dictation as the default and fallback. Reuses the existing STT model and
/ai-chat/transcribe — no new provider/model/endpoint fields. Lists the server
+ client touch points, acceptance criteria, and edge cases.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 23:40:53 +03:00

6.9 KiB

Стриминговая (по тишине) диктовка под фиче-тогглом, по умолчанию ВЫКЛ

Статус: открыто.

Контекст

Стриминговая диктовка (нарезка по тишине через Silero VAD, @ricky0123/vad-web) уже в develop и сейчас жёстко включена: MicButton получает проп streaming литералом true в двух местах — редактор (dictation-group.tsx) и чат (chat-input.tsx). Фича экспериментальная:

  • тяжёлые ассеты (ONNX-модель + ORT-wasm, 13–26 МБ, грузятся в браузер при первом использовании);
  • задержка инициализации модели на первом клике (компиляция wasm + подъём inference-сессии — повторяется на каждую загрузку страницы);
  • много мелких запросов на /ai-chat/transcribe (по одному на сегмент речи) вместо одного на запись.

Её нужно сделать opt-in на воркспейс, по умолчанию выключенной, с обычной батч-диктовкой как дефолтом и фолбэком.

Цель

Спрятать стриминговый путь за булевым флагом воркспейса settings.ai.dictationStreaming (default false). Выкл → текущая стабильная батч-диктовка. Вкл → стриминговая.

Минимализм (явно): один булев флаг, переиспользуем существующую STT-модель и эндпоинт /ai-chat/transcribe, без новых полей провайдера / модели / эндпоинта / секретов — осознанное требование после претензий к realtime-PR (#118) за лишние поля настроек.

Дизайн

Сервер

  • В типе AI-настроек (integrations/ai/ai.types.ts) и в dto/update-ai-settings.dto.ts добавить dictationStreaming?: boolean рядом с уже существующим флагом dictation. Проверить, валидируется ли апдейт настроек по whitelist (ai-settings.service.ts) — если да, внести ключ; иначе passthrough.
  • Это только клиентский поведенческий флаг: эндпоинт транскрипции и STT-модель не меняются (стриминг переиспользует /ai-chat/transcribe). Флаг просто отдаётся в составе settings.ai, который клиент уже читает.

Клиент

  • Тип features/workspace/types/workspace.types.ts (settings.ai, рядом с dictation?: boolean): добавить dictationStreaming?: boolean.
  • UI ai-provider-settings.tsx: добавить Switch «Streaming dictation (cut on pauses)» внутри/рядом с тумблером «Voice dictation» — активен только когда dictation включена (это под-режим диктовки). Оптимистичный апдейт по образцу dictation (см. handleDictationToggle и запись ai: { ...ai, dictation: value }), пишет settings.ai.dictationStreaming. Default off. Новый i18n-ключ.
  • Гейтинг: в dictation-group.tsx и chat-input.tsx заменить жёсткий streaming (литерал true) на streaming={settings.ai.dictationStreaming === true}. Проп streaming у MicButton уже выбирает хук (useStreamingDictation vs useDictation) — там менять ничего не нужно.

Критерии приёмки

  • Свежий воркспейс (флага нет) → mic-кнопка использует батч-диктовку; ассеты VAD (ONNX/wasm) не грузятся (ленивый import() в useStreamingDictation.start() срабатывает только при streaming и клике, которого при выкл не будет — оба хука инертны до start()).
  • Тоггл вкл → стриминговая диктовка работает и в редакторе, и в чате.
  • Тоггл выкл → возврат к батчу; стриминговые ассеты не подгружаются.
  • Нет новых полей модели / эндпоинта / секрета — переиспользуется диктовочная STT-модель и /ai-chat/transcribe.
  • Флаг персистится на воркспейс и гейтится как прочие settings.ai.*.

Затрагиваемые файлы (указатели)

  • Сервер: integrations/ai/ai.types.ts, integrations/ai/dto/update-ai-settings.dto.ts, integrations/ai/ai-settings.service.ts (если есть нормализация/whitelist).
  • Клиент: features/workspace/types/workspace.types.ts, features/workspace/components/settings/components/ai-provider-settings.tsx (Switch + i18n), features/editor/components/fixed-toolbar/groups/dictation-group.tsx, features/ai-chat/components/chat-input.tsx.

Заметки / краевые случаи

  • Батч-диктовка остаётся дефолтом и фолбэком (в т.ч. если стриминговая инициализация падает).
  • Подтвердить, что выкл-состояние не тянет ни одного VAD-байта: MicButton хоть и вызывает оба хука безусловно (правило хуков), оба инертны до start(), поэтому при streaming=false модель/wasm не запрашиваются.
  • Не добавлять отдельные модель/эндпоинт под стриминг — переиспользовать диктовочные (явное требование после realtime-PR).

Вне scope

  • Preload / мгновенный старт и латентность инициализации модели — отдельный follow-up.
  • Realtime-websocket путь (PR #118, streaming-dictation-plan.md) — не мержится.