opencode-voice-dictation/docs/handoff/pr-29-v1-18-composer-selectors.md
Sergey af5bc63bcc
fix(ui): support OpenCode 1.18.x composer selectors (#29)
## Что сделано
- Обновлён массив COMPOSER_SELECTORS в src/ui.ts: добавлены новые
селекторы [data-component="prompt-input-v2"] и
[data-component="session-prompt-dock"] как primary для OpenCode v1.18.x
- Старые селекторы session-new-composer/session-composer сохранены как
fallback для обратной совместимости
- README обновлён с указанием совместимой версии OpenCode v1.18.x
(русский и английский блоки)
- Добавлен handoff-документ и ADR 0001 с обоснованием порядка
fallback-селекторов

## Почему
В OpenCode v1.18.x селекторы session-composer/session-new-composer
удалены из исходников, из-за чего findComposer() возвращал null и кнопка
🎤 не появлялась в чате. Порядок массива обновлён как primary (v1.18.x) →
fallback (pre-1.18), чтобы сохранить совместимость с OpenCode <1.18 до
oldInterfaceSunset (2026-09-14).

Closes #28

---------

Co-authored-by: opencode-agent <agent@opencode.local>
2026-07-25 01:29:00 +03:00

6.6 KiB
Raw Blame History

pr_number branch issue title status created
29 fix/ui/v1-18-composer-selectors 28 support OpenCode 1.18.x composer selectors open 2026-07-24

Handoff — PR #29: v1.18.x composer selectors

Контекст

Userscript opencode-voice-dictation не вставляет кнопку микрофона в OpenCode web v1.18.x — findComposer() в src/ui.ts возвращал null, потому что массив COMPOSER_SELECTORS содержал только устаревшие селекторы [data-component="session-composer"] и [data-component="session-new-composer"], которые полностью удалены из исходников OpenCode v1.18.x.

В OpenCode v1.18.x контейнер композера переименован:

  • [data-component="session-prompt-dock"] — обёртка региона композера (packages/app/src/pages/session/composer/session-composer-region.tsx:26)
  • [data-component="prompt-input-v2"] — v2 form-контейнер (packages/session-ui/src/v2/components/prompt-input/index.tsx:107)

Уцелели в v1.18.x (НЕ трогались): [data-component="prompt-input"] (contenteditable), [data-action="prompt-submit"] (кнопка отправки), [data-slot="question-custom-input"] (textarea).

Issue: #28.

Что сделано

  • Обновлён массив COMPOSER_SELECTORS в src/ui.ts: добавлены новые селекторы [data-component="prompt-input-v2"] и [data-component="session-prompt-dock"] как primary для OpenCode v1.18.x (первые в массиве).
  • Старые селекторы session-new-composer / session-composer сохранены как fallback для обратной совместимости с OpenCode <1.18.
  • README.md обновлён с указанием совместимой версии OpenCode v1.18.x (русский и английский блоки).
  • Добавлен ADR 0001 с обоснованием порядка fallback-селекторов.

Почему

В OpenCode v1.18.x селекторы session-composer / session-new-composer полностью удалены из исходников, из-за чего findComposer() возвращал null и кнопка 🎤 не появлялась в чате. Порядок массива обновлён как primary (v1.18.x) → fallback (pre-1.18), чтобы сохранить совместимость с OpenCode <1.18 до oldInterfaceSunset (2026-09-14). Функция findComposer() уже перебирает массив сверху вниз — изменений в логике не потребовалось.

Pending

  • После oldInterfaceSunset (2026-09-14) legacy-селекторы session-new-composer / session-composer станут мёртвым кодом — удалить отдельным PR.
  • Отслеживать дальнейшие переименования контейнера композера в OpenCode (источник: sst/opencode main).

Watch out

  • Порядок COMPOSER_SELECTORS = приоритет детекции; не менять без обновления ADR 0001.
  • prompt-input-v2 появляется раньше session-prompt-dock в lifecycle (form-контейнер монтируется внутри dock'а) — порядок primary→fallback важен для раннего появления кнопки.
  • Home-страница нового layout (NewHome) не содержит композера — userscript активен только на /new-session или открытых сессиях.
  • src/insert.ts не затронут: gate [data-component="prompt-input"] остаётся валидным в обеих версиях UI.

Изменения

src/ui.ts

  • Обновлён массив COMPOSER_SELECTORS (новые селекторы v1.18.x первыми как primary, старые сохранены как fallback):
    const COMPOSER_SELECTORS = [
      '[data-component="prompt-input-v2"]',
      '[data-component="session-prompt-dock"]',
      '[data-component="session-new-composer"]',
      '[data-component="session-composer"]',
    ];
    
  • Функция findComposer() уже перебирает массив — изменений не потребовалось.

README.md

  • Строка 13 (русский блок): предупреждение о "New UI" уточнено до совместимой версии OpenCode v1.18.x.
  • Строка 68 (english-блок): аналогичное уточнение для английского блока.

Файлы вне спеки

  • src/insert.ts, src/audio.ts, src/transcribe.ts, src/config.ts, src/keyboard.ts, src/types.ts, src/index.ts — без изменений.

Проверки

Проверка Команда Результат
Lint npm run lint (biome check) Checked 21 files, no fixes
Typecheck npm run typecheck (tsc --noEmit) No errors
Tests npm run test (vitest run) 47/47 passed (5 files)
Knip npm run knip No unused exports

Acceptance criteria

  • Кнопка 🎤 появляется в OpenCode web v1.18.x (через новые primary-селекторы prompt-input-v2 / session-prompt-dock)
  • Старые версии OpenCode остаются совместимы (fallback-селекторы session-new-composer / session-composer сохранены)
  • npm run lint && npm run typecheck && npm run test && npm run knip проходят
  • README обновлён с указанием совместимой версии OpenCode v1.18.x (русский и английский блоки)

Коммиты

  1. fix(ui): add v1.18.x composer selectors — обновление COMPOSER_SELECTORS в src/ui.ts
  2. docs(readme): specify OpenCode v1.18.x compatibility — уточнение совместимости в обоих языковых блоках README
  3. docs(handoff): add handoff + ADR for PR — handoff-документ и ADR
  4. docs(handoff): set PR number — подстановка реального номера PR (после gh pr create)

ADR

См. docs/handoff/adr/0001-pr-29-v1-18-composer-selectors-fallback-order.md.

Источники

  • Память: technical/opencode-web-ui-composer-selectors-1.18.4.md (исследование sst/opencode main commit 2b2aacc, web pkg 1.18.4)
  • Память: repos/opencode-voice-dictation.md (архитектура репо)