## Что сделано - `src/types.ts`: добавлены поля `endpoint: string` и `temperature: number` в интерфейс `AppConfig`. - `src/config.ts`: - `DEFAULTS.endpoint = "https://api.groq.com/openai/v1/audio/transcriptions"` (обратная совместимость). - `DEFAULTS.temperature = 0` (детерминированный вывод). - `DEFAULTS.whisperPrompt` сокращён с ~270 до 107 символов — термины через запятую, без предложений. - `getConfig()` читает новые поля через `GM_getValue` с fallback на `DEFAULTS`. - Добавлены 2 меню-команды: «Set STT Endpoint» и «Set Temperature» в `registerMenuCommands` (параметры `onSetEndpoint`, `onSetTemperature`). - `src/index.ts`: реализованы `promptForEndpoint` (fallback на дефолт при пустом вводе) и `promptForTemperature` (clamp к `[0, 1]`, NaN-валидация, сохранение текущего значения при cancel), зарегистрированы в `registerMenuCommands`. - `src/transcribe.ts`: удалён хардкод `GROQ_API_URL`, используется `config.endpoint`; в `buildFormData` добавлено `formData.append("temperature", String(config.temperature))`. - `vite.config.ts`: `@connect api.groq.com` → `@connect *` (разрешает `GM_xmlhttpRequest` к любому домену). - `README.md`: добавлены разделы «Custom STT Endpoint» (EN+RU) с примером nginx `proxy_pass` и «Temperature». - `tests/`: обновлены `mockConfig` (новые поля), ассерты на `temperature` в FormData, тест на длину `whisperPrompt < 120`, `registerMenuCommands` теперь ожидает 7 команд. ## Почему Groq периодически блокирует прямые IP-запросы к `api.groq.com` — нужен обход через пользовательский nginx-прокси (свой endpoint). Whisper галлюцинирует на тишине/шуме — `temperature=0` снижает галлюцинации. Длинный `whisperPrompt` с целыми предложениями мог «утекать» в вывод транскрипции — сокращён до списка терминов через запятую (~107 символов). Хардкод `GROQ_API_URL` и `@connect api.groq.com` блокировали использование кастомных доменов. ## Watch out - `@connect *` в метаблоке расширяет поверхность запросов userscript-а на любой домен — юзер должен доверять установленному endpoint. Это намеренный trade-off для поддержки произвольных прокси. - Существующие юзеры со старым `whisperPrompt` в `GM_getValue` сохраняют своё значение (новый короткий default применяется только если ключ не задан) — обратная совместимость сохранена. - Кламп температуры: ввод `NaN` → toast «Invalid temperature» (значение не меняется); ввод `5` → `1`; ввод `-0.3` → `0`. - Пустой endpoint (юзер ввёл пробелы) → fallback на `DEFAULTS.endpoint` (`api.groq.com`), не пустая строка. - Cancel в prompt (Esc) по endpoint/temperature → значение не меняется (поведение `null`-check). - Error-сообщения `transcribe.ts` всё ещё упоминают «Groq API» — оставлено намеренно, т.к. дефолтный endpoint = Groq и большинство юзеров используют его. ## Pending - Обновить `@version` в `vite.config.ts` при релизе (сейчас `1.0.3` — не тронуто, решает релиз-процесс). - Trim тишины (RMS-based) — явно вне scope этого issue (отдельный PR если `temperature=0` не поможет). Closes #42 Closes #42 --------- Co-authored-by: opencode-agent <agent@opencode.local>
120 lines
No EOL
5.8 KiB
Markdown
120 lines
No EOL
5.8 KiB
Markdown
# 🚀 opencode-voice-dictation
|
||

|
||
<!-- tagline-en:start -->
|
||
> Voice dictation for OpenCode web — mic button via Whisper (Groq API)
|
||
<!-- tagline-en:end -->
|
||
<!-- tagline-ru:start -->
|
||
> Голосовой ввод для OpenCode web — кнопка микрофона через Whisper (Groq API)
|
||
<!-- tagline-ru:end -->
|
||
|
||
[English](#-english) | [Русский](#-русский)
|
||
|
||
---
|
||
|
||
## 🇺🇸 English
|
||
|
||
<!-- summary-en:start -->
|
||
### ❓ Why
|
||
Needed a way to dictate to agents from a phone. Stock Android voice input doesn't cut it. OpenCode web had no built-in voice.
|
||
|
||
### ✅ What
|
||
A Tampermonkey/Violentmonkey userscript — a mic button in the OpenCode web UI. Language selection, auto-submit after dictation. Whisper via Groq API (requires your own key).
|
||
<!-- summary-en:end -->
|
||
|
||
<!-- features-en:start -->
|
||
### Features
|
||
|
||
| Feature | Description |
|
||
|---------|-------------|
|
||
| 🎤 Mic button | Click 🎤 in the input area, speak — text inserts into the prompt |
|
||
| 🌍 Language | `ru`, `en`, or auto-detect |
|
||
| ⚡ Auto-submit | Sends transcription to the agent after dictation (toggleable) |
|
||
| 🧠 Whisper (Groq) | `whisper-large-v3` / `whisper-large-v3-turbo` via Groq API |
|
||
| 📱 Mobile via Firefox | Firefox supports extensions; mobile Chrome doesn't |
|
||
| ✅ Tested on 1.18.8 | Older versions via fallback selectors; needs "New UI" toggle |
|
||
| 🔄 Auto-update | Updates itself via `@updateURL` — no manual reinstall |
|
||
| ⌨️ Ctrl+Space | Desktop hotkey to start/stop recording |
|
||
<!-- features-en:end -->
|
||
|
||
### ⚡ Quick Start
|
||
|
||
1. Install [Tampermonkey](https://www.tampermonkey.net/)
|
||
2. Get a key at [console.groq.com/keys](https://console.groq.com/keys)
|
||
3. Open the [script install link](https://raw.githubusercontent.com/slaid098/opencode-voice-dictation/dist/opencode-voice-dictation.user.js) — it installs into Tampermonkey
|
||
4. Tampermonkey menu → **Set Groq API Key** → paste `gsk_...`
|
||
|
||
### 🌐 Custom STT Endpoint
|
||
|
||
Groq may block direct requests from some networks. Point the script at your own nginx proxy:
|
||
|
||
1. Deploy an nginx reverse proxy that forwards to `api.groq.com`:
|
||
```nginx
|
||
location /groq/ {
|
||
proxy_pass https://api.groq.com/;
|
||
proxy_set_header Host api.groq.com;
|
||
}
|
||
```
|
||
2. Tampermonkey menu → **Set STT Endpoint** → paste `https://your-domain.com/groq/openai/v1/audio/transcriptions`
|
||
3. Requests now go through your proxy. The userscript metadata uses `@connect *`, so any domain is allowed.
|
||
|
||
### 🌡️ Temperature
|
||
|
||
Whisper may hallucinate on silence/noise. **Set Temperature** (default `0` = deterministic, range `0`–`1`) reduces hallucinations.
|
||
|
||
---
|
||
|
||
## 🇷🇺 Русский
|
||
|
||
<!-- summary-ru:start -->
|
||
### ❓ Зачем
|
||
Нужен был способ диктовать агентам с телефона. Стандартный Android-ввод не удовлетворяет. Встроенного голоса в OpenCode web не было.
|
||
|
||
### ✅ Что
|
||
Скрипт для Tampermonkey/Violentmonkey — кнопка микрофона в веб-интерфейсе OpenCode. Выбор языка, автоотправка после диктовки. Whisper через Groq API (нужен свой ключ).
|
||
<!-- summary-ru:end -->
|
||
|
||
<!-- features-ru:start -->
|
||
### Фичи
|
||
|
||
| Фича | Описание |
|
||
|------|----------|
|
||
| 🎤 Микрофон | Нажми 🎤 в поле ввода, говори — текст вставится в промт |
|
||
| 🌍 Язык | `ru`, `en` или автоопределение |
|
||
| ⚡ Автоотправка | Отправляет транскрипцию агенту после диктовки (опционально) |
|
||
| 🧠 Whisper (Groq) | `whisper-large-v3` / `whisper-large-v3-turbo` через Groq API |
|
||
| 📱 Мобайл через Firefox | Firefox поддерживает расширения; mobile Chrome — нет |
|
||
| ✅ Проверено на 1.18.8 | Старые версии через fallback-селекторы; нужен «New UI» |
|
||
| 🔄 Автообновление | Обновляется сам через `@updateURL` — без ручной переустановки |
|
||
| ⌨️ Ctrl+Space | Горячая клавиша на десктопе |
|
||
<!-- features-ru:end -->
|
||
|
||
### ⚡ Быстрый старт
|
||
|
||
1. Установи [Tampermonkey](https://www.tampermonkey.net/)
|
||
2. Получи ключ на [console.groq.com/keys](https://console.groq.com/keys)
|
||
3. Открой [ссылку установки скрипта](https://raw.githubusercontent.com/slaid098/opencode-voice-dictation/dist/opencode-voice-dictation.user.js) — скрипт установится в Tampermonkey
|
||
4. Меню Tampermonkey → **Set Groq API Key** → вставь `gsk_...`
|
||
|
||
### 🌐 Кастомный STT endpoint
|
||
|
||
Groq может блокировать прямые запросы из некоторых сетей. Направь скрипт на свой nginx-прокси:
|
||
|
||
1. Разверни nginx reverse proxy, который форвардит на `api.groq.com`:
|
||
```nginx
|
||
location /groq/ {
|
||
proxy_pass https://api.groq.com/;
|
||
proxy_set_header Host api.groq.com;
|
||
}
|
||
```
|
||
2. Меню Tampermonkey → **Set STT Endpoint** → вставь `https://your-domain.com/groq/openai/v1/audio/transcriptions`
|
||
3. Запросы пойдут через твой прокси. Метаблок юзерскрипта использует `@connect *`, поэтому разрешён любой домен.
|
||
|
||
### 🌡️ Temperature
|
||
|
||
Whisper может галлюцинировать на тишине/шуме. **Set Temperature** (по умолчанию `0` = детерминированный вывод, диапазон `0`–`1`) снижает галлюцинации.
|
||
|
||
---
|
||
|
||
## 💬 Support and contacts / Поддержка и контакты
|
||
|
||
👉 **[slaid098.dev/support](https://slaid098.dev/support)** |