@goodandready/dsh-voice 0.9.31 → 0.9.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.ru.md CHANGED
@@ -1,251 +1,254 @@
1
- # 📦 @goodandready/dsh-voice
2
-
3
- <div align="center">
4
-
5
- <h3>Потоковая диктовка без задержек и мультиязычный голосовой ввод для DeepSeek Harness</h3>
6
-
7
- <p align="center">
8
- <a href="https://www.npmjs.com/package/@goodandready/dsh-voice"><img src="https://img.shields.io/npm/v/@goodandready/dsh-voice.svg?style=for-the-badge&color=6366f1&labelColor=1e1b4b" alt="npm version"></a>
9
- <a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-10b981.svg?style=for-the-badge&color=10b981&labelColor=064e3b" alt="license"></a>
10
- <a href="https://github.com/topics/dsh-plugin"><img src="https://img.shields.io/badge/DSH-Plugin-8b5cf6.svg?style=for-the-badge&labelColor=2e1065" alt="DSH Plugin"></a>
11
- <a href="https://nodejs.org"><img src="https://img.shields.io/badge/Node-20%2B-f59e0b.svg?style=for-the-badge&labelColor=451a03" alt="Node version"></a>
12
- </p>
13
-
14
- <p align="center">
15
- <a href="https://goodandready.app/"><img src="https://img.shields.io/badge/Все_проекты_автора-goodandready.app-ff4500.svg?style=for-the-badge&logo=rocket&logoColor=white&labelColor=1a1a2e" alt="Все проекты автора"></a>
16
- </p>
17
-
18
- <p align="center">
19
- <a href="README.md"><b>🇬🇧 English</b></a> •
20
- <a href="README.ru.md"><b>🇷🇺 Русский</b></a> •
21
- <a href="README.zh.md"><b>🇨🇳 中文说明</b></a>
22
- </p>
23
-
24
- <table align="center">
25
- <tr>
26
- <td align="center">
27
- ⭐ <strong>Если вам нравится этот плагин, поставьте ему звезду на GitHub</strong> — это покажет мне, что плагин вам полезен, и будет мотивировать меня развивать его дальше.
28
- <br><br>
29
- 🐛 <strong>Если вы нашли баг или хотите предложить новый функционал</strong>, создайте issue на GitHub на любом языке — я рассмотрю ваше предложение и реализую полезные идеи в одной из следующих версий плагина.
30
- </td>
31
- </tr>
32
- </table>
33
-
34
- </div>
35
-
36
- ---
37
-
38
- ## Требования
39
- ### Доступ к микрофону и Secure Context\nСовременные веб-браузеры требуют безопасный контекст (**Secure Context**: `https://` или `http://localhost` / `http://127.0.0.1`) для захвата аудио с микрофона (`navigator.mediaDevices.getUserMedia`). При открытии DSH в локальной сети по обычному HTTP (например, `http://192.168.1.x:3080` через `dsh-lanmode`) браузер блокирует микрофон. Для работы в LAN настройте HTTPS (через reverse proxy, например caddy/nginx) либо укажите адрес в настройках браузера (`chrome://flags/#unsafely-treat-insecure-origin-as-secure`).\n
40
-
41
- ## ⚡ Обзор
42
-
43
- **`dsh-voice`** добавляет полноценные голосовые возможности в веб-интерфейс **DeepSeek Harness**. Будь то непрерывная диктовка с нарезкой фраз по естественным паузам или голосовые сообщения с удобными жестами Push-to-Talk (мышь и клавиатура) — `dsh-voice` гарантирует сохранность каждой записи благодаря **автоматическим цепочкам отказоустойчивости**.
44
-
45
- ```mermaid
46
- graph LR
47
- subgraph Client [Браузер Web UI]
48
- Mic[🎙️ Микрофон диктовки] -->|Нарезка фраз VAD| Stream[Аудио-чанки]
49
- Wave[🌊 Голосовое сообщение] -->|Зажатие / Отпускание| PTT[Push-to-Talk]
50
- end
51
-
52
- subgraph Host [Бэкенд DSH Host]
53
- Stream --> FFMPEG[Транскодер ffmpeg 16кГц]
54
- PTT --> FFMPEG
55
- FFMPEG --> Chain{Цепочка фолбеков}
56
-
57
- Chain -->|1-й приоритет| P1[Deepgram / Nova-2]
58
- Chain -.->|При лимитах / 429| P2[Groq / Whisper Turbo]
59
- Chain -.->|При сбое| P3[Локальный whisper.cpp]
60
- end
61
-
62
- subgraph Output [Результат]
63
- P1 --> Composer[💬 Строка ввода чата]
64
- P2 --> Composer
65
- P3 --> Composer
66
- end
67
-
68
- style Client fill:#1e1e2e,stroke:#89b4fa,stroke-width:2px,color:#cdd6f4
69
- style Host fill:#181825,stroke:#cba6f7,stroke-width:2px,color:#cdd6f4
70
- style Output fill:#11111b,stroke:#a6e3a1,stroke-width:2px,color:#cdd6f4
71
- ```
72
-
73
- ---
74
-
75
- ## ✨ Ключевые возможности
76
-
77
- * 🎙️ **Потоковая диктовка с VAD**: аудиопоток режется по естественным паузам речи (`vadSilenceMs`, по умолчанию 700 мс) и мгновенно печатается в поле ввода.
78
- * 🌊 **Голосовые заметки с окном отмены**: запишите законченную мысль — сообщение автоматически уйдёт агенту по истечении таймера (`autoSendMs`, по умолчанию 4000 мс).
79
- * 🎮 **Тактильный Push-to-Talk**:
80
- * **Мышь**: зажмите кнопку волны — запись идёт пока кнопка зажата; отпускание отправляет, увод курсора отменяет запись.
81
- * **Клавиатура**: зажмите <kbd>Ctrl</kbd> для записи без мыши; нажмите <kbd>Esc</kbd> для отмены.
82
- * ⚡ **Субтитры браузера в реальном времени (`browser`)**: распознавание Web Speech API с плавающими субтитрами в реальном времени (Внимание: стандартный браузерный движок в Chrome отправляет аудио на серверы Google; для полностью локальной приватной работы без внешних вызовов используйте локальный `whisper` или `sensevoice`).
83
- * 🛡️ **Надёжные цепочки фолбеков**: при исчерпании квоты или ошибке 429 плагин мгновенно обращается к следующему провайдеру в списке.
84
- * 🧠 **Контекстный словарь (Context Glossary)**: автоматическое извлечение переменных и технических терминов из черновика композера для точного распознавания редких слов и кода.
85
- * 🎵 **Встроенный аудиоплеер**: предпросмотр и воспроизведение записанного голосового сообщения в чате и доке перед отправкой или для переслушивания.
86
- * 🔇 **Аппаратное шумоподавление**: переключатель в настройках для включения/выключения браузерного шумоподавления, эхоподавления и АРУ.
87
- * 📊 **Дашборд задержки и здоровья провайдеров**: мониторинг скорости ответа (мс), процента успешных транскрипций и ошибок в реальном времени.
88
- * 🔒 **Безопасность API-ключей**: ключи читаются на сервере через `ctx.credentials` и никогда не попадают в браузер клиента.
89
- * 🖥️ **Автозапуск локального whisper.cpp**: управление жизненным циклом `whisper-server` с авто-конвертацией через `ffmpeg`.
90
- * ⚡ **SenseVoice-ONNX / Sherpa-ONNX** *(0.8.11, обновлено 0.8.32)*: сверхбыстрый (~50–100мс) неавторегрессивный локальный STT с установкой модели SenseVoice-Small в 1 клик в `~/.dsh/models/sensevoice`.
91
- * 🎙️ **Gated Turn-Taking и защита от эха** *(0.8.32)*: автоматическое выключение микрофона во время ответа ассистента (`dsh:tts:start`/`stop`) и поддержка прерывания речи (Barge-In).
92
- * 👻 **Живой предпросмотр (Ghost Interim Preview)** *(0.8.32)*: визуальное отображение распознаваемых слов в реальном времени до фиксации фрагмента.
93
- * ⏱️ **Кольцевой таймер тишины (SVG Silence Ring)** *(0.8.32)*: круговая анимация обратного отсчёта до авто-отправки в полоске композера.
94
- * 🗣️ **Голосовые команды управления (Hands-free Actions)** *(0.8.32)*: фразы «отправь», «отмена», «очисти», «с новой строки» выполняют действия напрямую, не попадая в текст сообщения.
95
- * 🧩 **Голосовой выбор в интерактивах (Structured Prompts)** *(0.8.32)*: произнесение вариантов ответов нажимает соответствующие кнопки в активных модальных окнах ассистента.
96
- * 📖 **Словарь IT-жаргона и сленга разработчиков** *(0.8.32)*: фонетическое исправление сленга (гитхаб -> GitHub, кубер -> Kubernetes, пнпм -> pnpm) с возможностью добавления своих правил в настройках.
97
- * 🌊 **Анимированные визуализаторы Liquid Wave и Dynamic Orb** *(0.8.12)*: живая интерактивная анимация звуковой волны в полоске записи с откликом на громкость микрофона. Выбор стиля: текучая волна, пульсирующая сфера, классические столбики или выключен.
98
-
99
- ---
100
-
101
- ## 📝 Что нового в 0.8.32
102
-
103
- Пакет из 10 улучшений и установка SenseVoice в 1 клик (Issue #129):
104
-
105
- | Область | Функция | Описание |
106
- |---------|---------|----------|
107
- | Локальный STT | **Установка SenseVoice в 1 клик** | Автоматическая загрузка и распаковка `model.int8.onnx` и `tokens.txt` в `~/.dsh/models/sensevoice` через защищённый loopback-маршрут. |
108
- | Координация речи | **Gated Turn-Taking** | Микрофон глушится при воспроизведении ответа ассистента (`dsh:tts:start`) и включается обратно при `dsh:tts:stop`, исключая эхо и зацикливание. |
109
- | Прерывание | **Barge-In** | Начало речи пользователя мгновенно прерывает воспроизведение ответа синтезатора речи. |
110
- | Обратная связь | **Ghost-предпросмотр** | Полупрозрачный текст живого распознавания прямо в пилюле композера до окончания фразы. |
111
- | Обратный отсчёт | **SVG Silence Ring** | Круговой векторный индикатор оставшегося времени до автоматической отправки сообщения. |
112
- | Управление | **Голосовые действия** | Команды «отправь», «отмена», «очисти» выполняют команды UI без вставки текста в поле ввода. |
113
- | Интерактивы | **Структурированные промпты** | Голосовой выбор вариантов ответов во всплывающих вопросах ассистента. |
114
- | Словарь | **Коррекция IT-жаргона** | Автоматическая замена сленга программистов на правильное написание с редактором правил в настройках. |
115
- | Конфигурация | **Индивидуальные переключатели** | Каждая функция отдельно включается и выключается в карточке настроек. |
116
-
117
- ---
118
-
119
- ## 📝 Что нового в 0.8.19
120
-
121
- Quality-батч после ревью v0.8.18 (Gitea #79–#87, PR #88):
122
-
123
- | Область | Изменение |
124
- |---------|-----------|
125
- | Подсказки в настройках | Хинты моделей/путей резолвятся через locale **в момент рендера** — без «замёрзших» i18n-ключей (#79) |
126
- | Поля моделей | `whisperModel` / `sensevoiceModel` показывают подсказку пути к модели, а не к бинарю (#82) |
127
- | Визуализатор | Liquid wave / dynamic orb читают **токены темы DSH**, без жёстких hex-цветов (#80) |
128
- | Изоляция стилей | CSS-теги несут `data-dsh-plugin="dsh-voice"` — соседний HMR не снимет стили (#81) |
129
- | Язык исходников | Комментарии, ошибки и тесты — английские; добавлены EN-фразы edit-команд. Устные RU-паттерны для STT сохранены (#86) |
130
- | Локали | **Изменение:** полный inline-словарь `ru` удалён. В комплекте только English. Для русского UI ставьте translation-плагин (#85) |
131
- | Исходники клиента | Браузерный клиент собирается из `lib/client-src/*.js` через `npm run build:client` (#87) |
132
- | Документация процесса | Добавлены `docs/design/DESIGN.md`, `index.md`, `AGENTS.md`, `docs/testing/unit.md` (#83) |
133
-
134
- > [!IMPORTANT]
135
- > **Поведение локалей в v0.8.19:** без translation-плагина интерфейс Web UI остаётся английским. Устные **командные** фразы для STT по-прежнему распознают русскую речь там, где это задокументировано; второй словарь UI в пакет не входит.
136
-
137
- ---
138
-
139
- ## 🎮 4 способа голосового ввода
140
-
141
- | Режим | Жест / Активация | Поведение |
142
- |---|---|---|
143
- | **Диктовка** | Клик <kbd>🎙️ Микрофон</kbd> | Речь режется по паузам (`vadSilenceMs`) и вставляется прямо в строку ввода |
144
- | **Голосовое сообщение** | Клик <kbd>🌊 Волна</kbd> | Запись до нажатия стоп, затем отправка с окном отмены (`autoSendMs`) |
145
- | **PTT Мышью** | Зажатие <kbd>🌊 Волна</kbd> | Запись пока зажата кнопка; отпускание отправляет, увод мыши сбрасывает |
146
- | **PTT Клавиатурой** | Зажатие <kbd>Ctrl</kbd> | Запись без мыши; отпускание отправляет, нажатие <kbd>Esc</kbd> отменяет |
147
-
148
- > [!TIP]
149
- > Клавиатурную клавишу можно легко переопределить в настройках (`hotkey`: `Control`, `Alt`, `Shift` или любой код клавиши).
150
-
151
- ---
152
-
153
- ## 🛠️ Матрица поддерживаемых провайдеров
154
-
155
- | Ключ | Сервис | Модель по умолчанию | Переменная секрета | Особенности |
156
- |---|---|---|---|---|
157
- | `browser-webgpu` | WebGPU/WASM Whisper в браузере | `onnx-community/whisper-tiny` | *Не требуется* | 100% приватное офлайн распознавание на GPU клиента; авто-фоллбек на серверную цепочку |
158
- | `browser` | Web Speech API | Нативная в браузере | *Не требуется* | Нулевая задержка, живые субтитры в Chrome (обработка на серверах вендора; не является офлайн) |
159
- | `deepgram` | Deepgram API | `nova-2` | `DEEPGRAM_API_KEY` | Сверхбыстрая облачная транскрипция |
160
- | `groq` | Groq Whisper | `whisper-large-v3-turbo` | `GROQ_API_KEY` | Мгновенная скорость генерации |
161
- | `hf` | HuggingFace Inference | `openai/whisper-large-v3` | `HF_TOKEN` | Высокоточный облачный Whisper |
162
- | `local-whisper` | Локальный whisper.cpp | из параметров сервера | *Не требуется* | 100% приватность, оффлайн, без интернета |
163
- | `sensevoice` | SenseVoice-ONNX / Sherpa-ONNX | `SenseVoiceSmall` | *Не требуется* | Сверхбыстрый (~50мс) локальный STT; ускорение на Rockchip RK3588 NPU (rknpu), OpenVINO, CUDA |
164
-
165
- ### 🚀 Готовые пресеты (Plug & Play)
166
-
167
- Достаточно указать имя в цепочке и добавить API-ключ:
168
- * `openai` (`whisper-1`) → `OPENAI_API_KEY`
169
- * `siliconflow` (`SenseVoiceSmall`) → `SILICONFLOW_API_KEY`
170
- * `mistral` (`voxtral-mini-latest`) → `MISTRAL_API_KEY`
171
- * `openrouter` (`google/gemini-2.5-flash`) → `OPENROUTER_API_KEY`
172
- * `deepinfra` (`whisper-large-v3-turbo`) → `DEEPINFRA_API_KEY`
173
- * `fireworks` (`whisper-v3-turbo`) → `FIREWORKS_API_KEY`
174
-
175
- ---
176
-
177
- ## 📦 Быстрая установка
178
-
179
- ```bash
180
- dsh plugin --profile web add @goodandready/dsh-voice
181
- ```
182
-
183
- > [!IMPORTANT]
184
- > Перезапустите Web UI после установки (`systemctl --user restart dsh-web`) и обновите страницу в браузере.
185
-
186
- ---
187
-
188
- ## ⚙️ Настройка конфигурации
189
-
190
- Откройте **Настройки → Плагины → Настройки плагинов → Голос** в Web UI:
191
-
192
- ```yaml
193
- - id: dsh-voice
194
- config:
195
- dictation:
196
- language: "" # автоопределение по умолчанию; или укажите "ru", "en", "zh" и др.
197
- vadSilenceMs: 700
198
- chain:
199
- - provider: deepgram
200
- - provider: groq
201
- - provider: local-whisper
202
- message:
203
- language: "" # автоопределение по умолчанию; или укажите "ru", "en", "zh" и др.
204
- autoSendMs: 4000
205
- chain:
206
- - provider: openai
207
- - provider: local-whisper
208
- hotkey: Control
209
- autoStart: true
210
- whisperModel: /models/ggml-medium-q8_0.bin
211
- ```
212
-
213
- > **Примечание по языку**: Значение `language: ""` (по умолчанию) включает автоопределение языка провайдером. Нормализация числительных словами в цифры и стандартный словарь технического сленга применяются адаптивно только при распознавании русской речи, исключая искажение англоязычного текста.
214
-
215
- ---
216
-
217
- ## 🤖 Инструмент агента и HTTP API
218
-
219
- ### Инструмент агента (`transcribe_audio`)
220
- Регистрирует `transcribe_audio(file_path, language?)` в `ctx.tools` (с проверкой границ разрешённых каталогов `allowedAudioDirs` / `~/.dsh` / `tmpdir` / `cwd`, защитой от симлинков и валидацией сигнатур аудиофайлов), позволяя агентам распознавать аудиофайлы, интервью и записи с диска.
221
-
222
- ### Внутренние HTTP эндпоинты
223
- * `POST /dsh-voice/transcribe` — `{ dataBase64, mimeType, mode }` → `{ ok, text, provider, tookMs }`
224
- * `POST /dsh-voice/polish` — `{ text }` → `{ ok, text }`
225
- * `GET /dsh-voice/status` — состояние демонов, цепочки, конфигурация SenseVoice, реалтайма и effectiveSensevoiceProvider.
226
- * `GET/PUT /dsh-voice/config` — получение и сохранение конфигурации плагина.
227
- * `GET/POST /dsh-voice/sensevoice-installer` — статус и установка модели SenseVoice в 1 клик.
228
- * `POST /api/dsh-voice/update` — запуск обновления плагина до актуальной версии из npm (с проверкой прав и блокировки профиля).
229
- * `GET /api/dsh-voice/update` — проверка наличия обновлений.
230
-
231
- ### 🔒 Политика блокировок профиля и контролируемое восстановление оператором
232
- При установке и обновлении плагинов DeepSeek Harness синхронизирует параллельные процессы через `<profile-dir>/package.json.lock` (например, `~/.dsh/profiles/<profile>/package.json.lock`).
233
- * **Канонический принцип претендента**: Процесс-претендент никогда не удаляет чужой lock-файл. Автоматическое удаление чужих блокировок претендентом запрещено для исключения TOCTOU-гонок и повреждения состояния профиля.
234
- * **Диагностика**: При наличии lock-файла запрос на обновление возвращает `409 Conflict` с подробной информацией:
235
- - Если блокировка удерживается активным процессом, выводится его PID.
236
- - При ошибках файловой системы (`EACCES`, `EIO`) операция завершается безопасно (fail-closed) с сохранением кода ошибки. Ошибки ФС требуют проверки прав доступа, состояния диска или опций монтирования — **не удаляйте** lock-файл при ошибках `EACCES`/`EIO`.
237
- * **Регламент контролируемого восстановления оператором**:
238
- Если предыдущий процесс установки аварийно оборвался (например, OOM или сбой питания) и оставил зависший lock-файл, снятие блокировки выполняет оператор по следующему регламенту:
239
- 1. **Обеспечение эксклюзивного окна обслуживания**: Убедитесь, что никакие параллельные процессы, команды CLI (`dsh plugin add`), веб-интерфейс или фоновые апдейтеры не выполняют установку и не могут запуститься для данного профиля.
240
- 2. **Проверка отсутствия живого владельца (quiescence)**: Проверьте с помощью `pgrep`, `ps`, `fuser` или `lsof`, что в каталоге профиля действительно нет активных процессов-установщиков. Сам по себе возраст файла или нераспарсенный PID **не являются** достаточным основанием для удаления lock-файла, пока не исключён параллельный запуск другого процесса. Если состояние покоя не подтверждено, удаление запрещено.
241
- 3. **Удаление только подтверждённого осиротевшего lock-файла**: Только после подтверждения статуса сироты удалите конкретный файл блокировки без рекурсивных и force-флагов:
242
- ```bash
243
- rm ~/.dsh/profiles/<profile>/package.json.lock
244
- ```
245
- 4. **Возобновление работы**: Разрешите запуск процессов установки и повторите обновление плагина.
246
-
247
- ---
248
-
249
- ## 📄 Лицензия
250
-
251
- MIT © [GooDAnDReaDY](https://github.com/GooDAnDReaDY)
1
+ # 📦 @goodandready/dsh-voice
2
+
3
+ <div align="center">
4
+
5
+ <h3>Потоковая диктовка без задержек и мультиязычный голосовой ввод для DeepSeek Harness</h3>
6
+
7
+ <p align="center">
8
+ <a href="https://www.npmjs.com/package/@goodandready/dsh-voice"><img src="https://img.shields.io/npm/v/@goodandready/dsh-voice.svg?style=for-the-badge&color=6366f1&labelColor=1e1b4b" alt="npm version"></a>
9
+ <a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-10b981.svg?style=for-the-badge&color=10b981&labelColor=064e3b" alt="license"></a>
10
+ <a href="https://github.com/topics/dsh-plugin"><img src="https://img.shields.io/badge/DSH-Plugin-8b5cf6.svg?style=for-the-badge&labelColor=2e1065" alt="DSH Plugin"></a>
11
+ <a href="https://nodejs.org"><img src="https://img.shields.io/badge/Node-20%2B-f59e0b.svg?style=for-the-badge&labelColor=451a03" alt="Node version"></a>
12
+ </p>
13
+
14
+ <p align="center">
15
+ <a href="https://goodandready.app/"><img src="https://img.shields.io/badge/Все_проекты_автора-goodandready.app-ff4500.svg?style=for-the-badge&logo=rocket&logoColor=white&labelColor=1a1a2e" alt="Все проекты автора"></a>
16
+ </p>
17
+
18
+ <p align="center">
19
+ <a href="README.md"><b>🇬🇧 English</b></a> •
20
+ <a href="README.ru.md"><b>🇷🇺 Русский</b></a> •
21
+ <a href="README.zh.md"><b>🇨🇳 中文说明</b></a>
22
+ </p>
23
+
24
+ <table align="center">
25
+ <tr>
26
+ <td align="center">
27
+ ⭐ <strong>Если вам нравится этот плагин, поставьте ему звезду на GitHub</strong> — это покажет мне, что плагин вам полезен, и будет мотивировать меня развивать его дальше.
28
+ <br><br>
29
+ 🐛 <strong>Если вы нашли баг или хотите предложить новый функционал</strong>, создайте issue на GitHub на любом языке — я рассмотрю ваше предложение и реализую полезные идеи в одной из следующих версий плагина.
30
+ </td>
31
+ </tr>
32
+ </table>
33
+
34
+ </div>
35
+
36
+ ---
37
+
38
+ ## Требования
39
+ ### Доступ к микрофону и Secure Context\nСовременные веб-браузеры требуют безопасный контекст (**Secure Context**: `https://` или `http://localhost` / `http://127.0.0.1`) для захвата аудио с микрофона (`navigator.mediaDevices.getUserMedia`). При открытии DSH в локальной сети по обычному HTTP (например, `http://192.168.1.x:3080` через `dsh-lanmode`) браузер блокирует микрофон. Для работы в LAN настройте HTTPS (через reverse proxy, например caddy/nginx) либо укажите адрес в настройках браузера (`chrome://flags/#unsafely-treat-insecure-origin-as-secure`).\n
40
+
41
+ ## ⚡ Обзор
42
+
43
+ **`dsh-voice`** добавляет полноценные голосовые возможности в веб-интерфейс **DeepSeek Harness**. Будь то непрерывная диктовка с нарезкой фраз по естественным паузам или голосовые сообщения с удобными жестами Push-to-Talk (мышь и клавиатура) — `dsh-voice` гарантирует сохранность каждой записи благодаря **автоматическим цепочкам отказоустойчивости**.
44
+
45
+ ```mermaid
46
+ graph LR
47
+ subgraph Client [Браузер Web UI]
48
+ Mic[🎙️ Микрофон диктовки] -->|Нарезка фраз VAD| Stream[Аудио-чанки]
49
+ Wave[🌊 Голосовое сообщение] -->|Зажатие / Отпускание| PTT[Push-to-Talk]
50
+ end
51
+
52
+ subgraph Host [Бэкенд DSH Host]
53
+ Stream --> FFMPEG[Транскодер ffmpeg 16кГц]
54
+ PTT --> FFMPEG
55
+ FFMPEG --> Chain{Цепочка фолбеков}
56
+
57
+ Chain -->|1-й приоритет| P1[Deepgram / Nova-2]
58
+ Chain -.->|При лимитах / 429| P2[Groq / Whisper Turbo]
59
+ Chain -.->|При сбое| P3[Локальный whisper.cpp]
60
+ end
61
+
62
+ subgraph Output [Результат]
63
+ P1 --> Composer[💬 Строка ввода чата]
64
+ P2 --> Composer
65
+ P3 --> Composer
66
+ end
67
+
68
+ style Client fill:#1e1e2e,stroke:#89b4fa,stroke-width:2px,color:#cdd6f4
69
+ style Host fill:#181825,stroke:#cba6f7,stroke-width:2px,color:#cdd6f4
70
+ style Output fill:#11111b,stroke:#a6e3a1,stroke-width:2px,color:#cdd6f4
71
+ ```
72
+
73
+ ---
74
+
75
+ ## ✨ Ключевые возможности
76
+ - 🎙️ **4 режима диктовки (#264)**: «Дословно» (0 вызовов LLM, чистый STT), «Чистый текст» (пунктуация и удаление мусорных слов без искажения фактов), «Задача агенту» (структурированная формулировка проблемы, целей и критериев приёмки), «Заметка» (ключевые мысли и задачи). Настраиваемые шаблоны с кнопкой сброса к стандартам.
77
+ - ⚡ **Контекстный бустинг лексикона (#167)**: сбор терминов и идентификаторов из активного черновика, последних сообщений чата и блоков кода в DOM, с передачей в Deepgram (`&keywords`), Groq (`prompt`), local-whisper и SenseVoice.
78
+ - 🎯 **Голосовые макросы (#167)**: настраиваемые шаблоны голосовых действий («сделай ревью», «запусти тесты»), автоматически раскрывающиеся в структурированные промпты с подстановкой `{text}`.
79
+
80
+ * 🎙️ **Потоковая диктовка с VAD**: аудиопоток режется по естественным паузам речи (`vadSilenceMs`, по умолчанию 700 мс) и мгновенно печатается в поле ввода.
81
+ * 🌊 **Голосовые заметки с окном отмены**: запишите законченную мысль — сообщение автоматически уйдёт агенту по истечении таймера (`autoSendMs`, по умолчанию 4000 мс).
82
+ * 🎮 **Тактильный Push-to-Talk**:
83
+ * **Мышь**: зажмите кнопку волны — запись идёт пока кнопка зажата; отпускание отправляет, увод курсора отменяет запись.
84
+ * **Клавиатура**: зажмите <kbd>Ctrl</kbd> для записи без мыши; нажмите <kbd>Esc</kbd> для отмены.
85
+ * ⚡ **Субтитры браузера в реальном времени (`browser`)**: распознавание Web Speech API с плавающими субтитрами в реальном времени (Внимание: стандартный браузерный движок в Chrome отправляет аудио на серверы Google; для полностью локальной приватной работы без внешних вызовов используйте локальный `whisper` или `sensevoice`).
86
+ * 🛡️ **Надёжные цепочки фолбеков**: при исчерпании квоты или ошибке 429 плагин мгновенно обращается к следующему провайдеру в списке.
87
+ * 🧠 **Контекстный словарь (Context Glossary)**: автоматическое извлечение переменных и технических терминов из черновика композера для точного распознавания редких слов и кода.
88
+ * 🎵 **Встроенный аудиоплеер**: предпросмотр и воспроизведение записанного голосового сообщения в чате и доке перед отправкой или для переслушивания.
89
+ * 🔇 **Аппаратное шумоподавление**: переключатель в настройках для включения/выключения браузерного шумоподавления, эхоподавления и АРУ.
90
+ * 📊 **Дашборд задержки и здоровья провайдеров**: мониторинг скорости ответа (мс), процента успешных транскрипций и ошибок в реальном времени.
91
+ * 🔒 **Безопасность API-ключей**: ключи читаются на сервере через `ctx.credentials` и никогда не попадают в браузер клиента.
92
+ * 🖥️ **Автозапуск локального whisper.cpp**: управление жизненным циклом `whisper-server` с авто-конвертацией через `ffmpeg`.
93
+ * ⚡ **SenseVoice-ONNX / Sherpa-ONNX** *(0.8.11, обновлено 0.8.32)*: сверхбыстрый (~50–100мс) неавторегрессивный локальный STT с установкой модели SenseVoice-Small в 1 клик в `~/.dsh/models/sensevoice`.
94
+ * 🎙️ **Gated Turn-Taking и защита от эха** *(0.8.32)*: автоматическое выключение микрофона во время ответа ассистента (`dsh:tts:start`/`stop`) и поддержка прерывания речи (Barge-In).
95
+ * 👻 **Живой предпросмотр (Ghost Interim Preview)** *(0.8.32)*: визуальное отображение распознаваемых слов в реальном времени до фиксации фрагмента.
96
+ * ⏱️ **Кольцевой таймер тишины (SVG Silence Ring)** *(0.8.32)*: круговая анимация обратного отсчёта до авто-отправки в полоске композера.
97
+ * 🗣️ **Голосовые команды управления (Hands-free Actions)** *(0.8.32)*: фразы «отправь», «отмена», «очисти», «с новой строки» выполняют действия напрямую, не попадая в текст сообщения.
98
+ * 🧩 **Голосовой выбор в интерактивах (Structured Prompts)** *(0.8.32)*: произнесение вариантов ответов нажимает соответствующие кнопки в активных модальных окнах ассистента.
99
+ * 📖 **Словарь IT-жаргона и сленга разработчиков** *(0.8.32)*: фонетическое исправление сленга (гитхаб -> GitHub, кубер -> Kubernetes, пнпм -> pnpm) с возможностью добавления своих правил в настройках.
100
+ * 🌊 **Анимированные визуализаторы Liquid Wave и Dynamic Orb** *(0.8.12)*: живая интерактивная анимация звуковой волны в полоске записи с откликом на громкость микрофона. Выбор стиля: текучая волна, пульсирующая сфера, классические столбики или выключен.
101
+
102
+ ---
103
+
104
+ ## 📝 Что нового в 0.8.32
105
+
106
+ Пакет из 10 улучшений и установка SenseVoice в 1 клик (Issue #129):
107
+
108
+ | Область | Функция | Описание |
109
+ |---------|---------|----------|
110
+ | Локальный STT | **Установка SenseVoice в 1 клик** | Автоматическая загрузка и распаковка `model.int8.onnx` и `tokens.txt` в `~/.dsh/models/sensevoice` через защищённый loopback-маршрут. |
111
+ | Координация речи | **Gated Turn-Taking** | Микрофон глушится при воспроизведении ответа ассистента (`dsh:tts:start`) и включается обратно при `dsh:tts:stop`, исключая эхо и зацикливание. |
112
+ | Прерывание | **Barge-In** | Начало речи пользователя мгновенно прерывает воспроизведение ответа синтезатора речи. |
113
+ | Обратная связь | **Ghost-предпросмотр** | Полупрозрачный текст живого распознавания прямо в пилюле композера до окончания фразы. |
114
+ | Обратный отсчёт | **SVG Silence Ring** | Круговой векторный индикатор оставшегося времени до автоматической отправки сообщения. |
115
+ | Управление | **Голосовые действия** | Команды «отправь», «отмена», «очисти» выполняют команды UI без вставки текста в поле ввода. |
116
+ | Интерактивы | **Структурированные промпты** | Голосовой выбор вариантов ответов во всплывающих вопросах ассистента. |
117
+ | Словарь | **Коррекция IT-жаргона** | Автоматическая замена сленга программистов на правильное написание с редактором правил в настройках. |
118
+ | Конфигурация | **Индивидуальные переключатели** | Каждая функция отдельно включается и выключается в карточке настроек. |
119
+
120
+ ---
121
+
122
+ ## 📝 Что нового в 0.8.19
123
+
124
+ Quality-батч после ревью v0.8.18 (Gitea #79–#87, PR #88):
125
+
126
+ | Область | Изменение |
127
+ |---------|-----------|
128
+ | Подсказки в настройках | Хинты моделей/путей резолвятся через locale **в момент рендера** — без «замёрзших» i18n-ключей (#79) |
129
+ | Поля моделей | `whisperModel` / `sensevoiceModel` показывают подсказку пути к модели, а не к бинарю (#82) |
130
+ | Визуализатор | Liquid wave / dynamic orb читают **токены темы DSH**, без жёстких hex-цветов (#80) |
131
+ | Изоляция стилей | CSS-теги несут `data-dsh-plugin="dsh-voice"` — соседний HMR не снимет стили (#81) |
132
+ | Язык исходников | Комментарии, ошибки и тесты — английские; добавлены EN-фразы edit-команд. Устные RU-паттерны для STT сохранены (#86) |
133
+ | Локали | **Изменение:** полный inline-словарь `ru` удалён. В комплекте только English. Для русского UI ставьте translation-плагин (#85) |
134
+ | Исходники клиента | Браузерный клиент собирается из `lib/client-src/*.js` через `npm run build:client` (#87) |
135
+ | Документация процесса | Добавлены `docs/design/DESIGN.md`, `index.md`, `AGENTS.md`, `docs/testing/unit.md` (#83) |
136
+
137
+ > [!IMPORTANT]
138
+ > **Поведение локалей в v0.8.19:** без translation-плагина интерфейс Web UI остаётся английским. Устные **командные** фразы для STT по-прежнему распознают русскую речь там, где это задокументировано; второй словарь UI в пакет не входит.
139
+
140
+ ---
141
+
142
+ ## 🎮 4 способа голосового ввода
143
+
144
+ | Режим | Жест / Активация | Поведение |
145
+ |---|---|---|
146
+ | **Диктовка** | Клик <kbd>🎙️ Микрофон</kbd> | Речь режется по паузам (`vadSilenceMs`) и вставляется прямо в строку ввода |
147
+ | **Голосовое сообщение** | Клик <kbd>🌊 Волна</kbd> | Запись до нажатия стоп, затем отправка с окном отмены (`autoSendMs`) |
148
+ | **PTT Мышью** | Зажатие <kbd>🌊 Волна</kbd> | Запись пока зажата кнопка; отпускание отправляет, увод мыши сбрасывает |
149
+ | **PTT Клавиатурой** | Зажатие <kbd>Ctrl</kbd> | Запись без мыши; отпускание отправляет, нажатие <kbd>Esc</kbd> отменяет |
150
+
151
+ > [!TIP]
152
+ > Клавиатурную клавишу можно легко переопределить в настройках (`hotkey`: `Control`, `Alt`, `Shift` или любой код клавиши).
153
+
154
+ ---
155
+
156
+ ## 🛠️ Матрица поддерживаемых провайдеров
157
+
158
+ | Ключ | Сервис | Модель по умолчанию | Переменная секрета | Особенности |
159
+ |---|---|---|---|---|
160
+ | `browser-webgpu` | WebGPU/WASM Whisper в браузере | `onnx-community/whisper-tiny` | *Не требуется* | 100% приватное офлайн распознавание на GPU клиента; авто-фоллбек на серверную цепочку |
161
+ | `browser` | Web Speech API | Нативная в браузере | *Не требуется* | Нулевая задержка, живые субтитры в Chrome (обработка на серверах вендора; не является офлайн) |
162
+ | `deepgram` | Deepgram API | `nova-2` | `DEEPGRAM_API_KEY` | Сверхбыстрая облачная транскрипция |
163
+ | `groq` | Groq Whisper | `whisper-large-v3-turbo` | `GROQ_API_KEY` | Мгновенная скорость генерации |
164
+ | `hf` | HuggingFace Inference | `openai/whisper-large-v3` | `HF_TOKEN` | Высокоточный облачный Whisper |
165
+ | `local-whisper` | Локальный whisper.cpp | из параметров сервера | *Не требуется* | 100% приватность, оффлайн, без интернета |
166
+ | `sensevoice` | SenseVoice-ONNX / Sherpa-ONNX | `SenseVoiceSmall` | *Не требуется* | Сверхбыстрый (~50мс) локальный STT; ускорение на Rockchip RK3588 NPU (rknpu), OpenVINO, CUDA |
167
+
168
+ ### 🚀 Готовые пресеты (Plug & Play)
169
+
170
+ Достаточно указать имя в цепочке и добавить API-ключ:
171
+ * `openai` (`whisper-1`) → `OPENAI_API_KEY`
172
+ * `siliconflow` (`SenseVoiceSmall`) → `SILICONFLOW_API_KEY`
173
+ * `mistral` (`voxtral-mini-latest`) → `MISTRAL_API_KEY`
174
+ * `openrouter` (`google/gemini-2.5-flash`) → `OPENROUTER_API_KEY`
175
+ * `deepinfra` (`whisper-large-v3-turbo`) → `DEEPINFRA_API_KEY`
176
+ * `fireworks` (`whisper-v3-turbo`) → `FIREWORKS_API_KEY`
177
+
178
+ ---
179
+
180
+ ## 📦 Быстрая установка
181
+
182
+ ```bash
183
+ dsh plugin --profile web add @goodandready/dsh-voice
184
+ ```
185
+
186
+ > [!IMPORTANT]
187
+ > Перезапустите Web UI после установки (`systemctl --user restart dsh-web`) и обновите страницу в браузере.
188
+
189
+ ---
190
+
191
+ ## ⚙️ Настройка конфигурации
192
+
193
+ Откройте **Настройки → Плагины → Настройки плагинов → Голос** в Web UI:
194
+
195
+ ```yaml
196
+ - id: dsh-voice
197
+ config:
198
+ dictation:
199
+ language: "" # автоопределение по умолчанию; или укажите "ru", "en", "zh" и др.
200
+ vadSilenceMs: 700
201
+ chain:
202
+ - provider: deepgram
203
+ - provider: groq
204
+ - provider: local-whisper
205
+ message:
206
+ language: "" # автоопределение по умолчанию; или укажите "ru", "en", "zh" и др.
207
+ autoSendMs: 4000
208
+ chain:
209
+ - provider: openai
210
+ - provider: local-whisper
211
+ hotkey: Control
212
+ autoStart: true
213
+ whisperModel: /models/ggml-medium-q8_0.bin
214
+ ```
215
+
216
+ > **Примечание по языку**: Значение `language: ""` (по умолчанию) включает автоопределение языка провайдером. Нормализация числительных словами в цифры и стандартный словарь технического сленга применяются адаптивно только при распознавании русской речи, исключая искажение англоязычного текста.
217
+
218
+ ---
219
+
220
+ ## 🤖 Инструмент агента и HTTP API
221
+
222
+ ### Инструмент агента (`transcribe_audio`)
223
+ Регистрирует `transcribe_audio(file_path, language?)` в `ctx.tools` (с проверкой границ разрешённых каталогов `allowedAudioDirs` / `~/.dsh` / `tmpdir` / `cwd`, защитой от симлинков и валидацией сигнатур аудиофайлов), позволяя агентам распознавать аудиофайлы, интервью и записи с диска.
224
+
225
+ ### Внутренние HTTP эндпоинты
226
+ * `POST /dsh-voice/transcribe` — `{ dataBase64, mimeType, mode }` → `{ ok, text, provider, tookMs }`
227
+ * `POST /dsh-voice/polish` — `{ text }` → `{ ok, text }`
228
+ * `GET /dsh-voice/status` — состояние демонов, цепочки, конфигурация SenseVoice, реалтайма и effectiveSensevoiceProvider.
229
+ * `GET/PUT /dsh-voice/config` — получение и сохранение конфигурации плагина.
230
+ * `GET/POST /dsh-voice/sensevoice-installer` — статус и установка модели SenseVoice в 1 клик.
231
+ * `POST /api/dsh-voice/update` — запуск обновления плагина до актуальной версии из npm (с проверкой прав и блокировки профиля).
232
+ * `GET /api/dsh-voice/update` — проверка наличия обновлений.
233
+
234
+ ### 🔒 Политика блокировок профиля и контролируемое восстановление оператором
235
+ При установке и обновлении плагинов DeepSeek Harness синхронизирует параллельные процессы через `<profile-dir>/package.json.lock` (например, `~/.dsh/profiles/<profile>/package.json.lock`).
236
+ * **Канонический принцип претендента**: Процесс-претендент никогда не удаляет чужой lock-файл. Автоматическое удаление чужих блокировок претендентом запрещено для исключения TOCTOU-гонок и повреждения состояния профиля.
237
+ * **Диагностика**: При наличии lock-файла запрос на обновление возвращает `409 Conflict` с подробной информацией:
238
+ - Если блокировка удерживается активным процессом, выводится его PID.
239
+ - При ошибках файловой системы (`EACCES`, `EIO`) операция завершается безопасно (fail-closed) с сохранением кода ошибки. Ошибки ФС требуют проверки прав доступа, состояния диска или опций монтирования — **не удаляйте** lock-файл при ошибках `EACCES`/`EIO`.
240
+ * **Регламент контролируемого восстановления оператором**:
241
+ Если предыдущий процесс установки аварийно оборвался (например, OOM или сбой питания) и оставил зависший lock-файл, снятие блокировки выполняет оператор по следующему регламенту:
242
+ 1. **Обеспечение эксклюзивного окна обслуживания**: Убедитесь, что никакие параллельные процессы, команды CLI (`dsh plugin add`), веб-интерфейс или фоновые апдейтеры не выполняют установку и не могут запуститься для данного профиля.
243
+ 2. **Проверка отсутствия живого владельца (quiescence)**: Проверьте с помощью `pgrep`, `ps`, `fuser` или `lsof`, что в каталоге профиля действительно нет активных процессов-установщиков. Сам по себе возраст файла или нераспарсенный PID **не являются** достаточным основанием для удаления lock-файла, пока не исключён параллельный запуск другого процесса. Если состояние покоя не подтверждено, удаление запрещено.
244
+ 3. **Удаление только подтверждённого осиротевшего lock-файла**: Только после подтверждения статуса сироты удалите конкретный файл блокировки без рекурсивных и force-флагов:
245
+ ```bash
246
+ rm ~/.dsh/profiles/<profile>/package.json.lock
247
+ ```
248
+ 4. **Возобновление работы**: Разрешите запуск процессов установки и повторите обновление плагина.
249
+
250
+ ---
251
+
252
+ ## 📄 Лицензия
253
+
254
+ MIT © [GooDAnDReaDY](https://github.com/GooDAnDReaDY)