opencode voice dictation
Find a file
Sergey c074dfd777
feat(transcription): custom endpoint and temperature (#43)
## Что сделано

- `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>
2026-08-04 12:32:39 +03:00
.github refactor(repo): remove GitHub releases, add icon, standardize README (#37) 2026-07-30 03:39:20 +03:00
assets feat(cover): add lime cover image and readme reference (#41) 2026-08-01 06:39:36 +03:00
docs docs(readme): align README with updated create-readme checker (#39) 2026-07-30 20:04:05 +03:00
src feat(transcription): custom endpoint and temperature (#43) 2026-08-04 12:32:39 +03:00
tests feat(transcription): custom endpoint and temperature (#43) 2026-08-04 12:32:39 +03:00
.gitignore feat: initial implementation of OpenCode Voice Dictation 2026-07-08 05:37:17 +00:00
.nvmrc feat: initial implementation of OpenCode Voice Dictation 2026-07-08 05:37:17 +00:00
biome.json feat: initial implementation of OpenCode Voice Dictation 2026-07-08 05:37:17 +00:00
knip.json feat: initial implementation of OpenCode Voice Dictation 2026-07-08 05:37:17 +00:00
LICENSE feat: initial implementation of OpenCode Voice Dictation 2026-07-08 05:37:17 +00:00
package-lock.json build(deps-dev): bump @types/node from 22.20.0 to 26.1.1 (#16) 2026-07-09 08:19:28 +03:00
package.json fix(ui): skip composer injection in child session (#33) 2026-07-26 17:18:08 +03:00
README.md feat(transcription): custom endpoint and temperature (#43) 2026-08-04 12:32:39 +03:00
tsconfig.json feat: initial implementation of OpenCode Voice Dictation 2026-07-08 05:37:17 +00:00
vite-env.d.ts feat: initial implementation of OpenCode Voice Dictation 2026-07-08 05:37:17 +00:00
vite.config.ts feat(transcription): custom endpoint and temperature (#43) 2026-08-04 12:32:39 +03:00
vitest.config.ts feat: initial implementation of OpenCode Voice Dictation 2026-07-08 05:37:17 +00:00

🚀 opencode-voice-dictation

Cover

Voice dictation for OpenCode web — mic button via Whisper (Groq API)

Голосовой ввод для OpenCode web — кнопка микрофона через Whisper (Groq API)

English | Русский


🇺🇸 English

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).

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

Quick Start

  1. Install Tampermonkey
  2. Get a key at console.groq.com/keys
  3. Open the script install link — 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:
    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 01) reduces hallucinations.


🇷🇺 Русский

Зачем

Нужен был способ диктовать агентам с телефона. Стандартный Android-ввод не удовлетворяет. Встроенного голоса в OpenCode web не было.

Что

Скрипт для Tampermonkey/Violentmonkey — кнопка микрофона в веб-интерфейсе OpenCode. Выбор языка, автоотправка после диктовки. Whisper через Groq API (нужен свой ключ).

Фичи

Фича Описание
🎤 Микрофон Нажми 🎤 в поле ввода, говори — текст вставится в промт
🌍 Язык 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 Горячая клавиша на десктопе

Быстрый старт

  1. Установи Tampermonkey
  2. Получи ключ на console.groq.com/keys
  3. Открой ссылку установки скрипта — скрипт установится в Tampermonkey
  4. Меню Tampermonkey → Set Groq API Key → вставь gsk_...

🌐 Кастомный STT endpoint

Groq может блокировать прямые запросы из некоторых сетей. Направь скрипт на свой nginx-прокси:

  1. Разверни nginx reverse proxy, который форвардит на api.groq.com:
    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 = детерминированный вывод, диапазон 01) снижает галлюцинации.


💬 Support and contacts / Поддержка и контакты

👉 slaid098.dev/support