opencode-voice-dictation/docs/decisions/0001-pr-29-v1-18-composer-selectors-fallback-order.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

66 lines
No EOL
4.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ADR 0001: COMPOSER_SELECTORS fallback order for OpenCode v1.18.x
- **Date**: 2026-07-24
- **PR**: #29
- **Issue**: #28
## Статус
Accepted.
## Контекст
OpenCode web v1.18.x переименовал контейнер композера:
- `session-composer``session-new-composer`**`session-prompt-dock`** (текущий, обёртка региона)
- добавлен **`prompt-input-v2`** (v2 form-контейнер внутри `PromptInputV2Composer`)
Старые селекторы `session-composer` и `session-new-composer` **полностью удалены** из исходников OpenCode v1.18.x (0 совпадений по grep в `src/`, только упоминания в stories/comments).
Userscript opencode-voice-dictation использует `findComposer()` в `src/ui.ts` для позиционирования кнопки микрофона. Массив `COMPOSER_SELECTORS` перебирается сверху вниз, возвращается первый найденный элемент. С устаревшими селекторами `findComposer()` возвращал `null` в v1.18.x — кнопка 🎤 не появлялась.
Дополнительные ограничения:
- `oldInterfaceSunset = 2026-09-14` (`packages/app/src/context/settings.tsx:62`) — legacy UI окончательно уходит, после этой даты fallback на `session-composer` станет бесполезен.
- Home-страница нового layout (`NewHome`) не содержит композера вообще — userscript активен только на `/new-session` или открытых сессиях.
- `promptReady()` lazy-mount: prompt-input появляется асинхронно после загрузки сообщений; MutationObserver в `setupUI` корректно отслеживает.
## Решение
Обновить `COMPOSER_SELECTORS` в порядке **новое → старое** (primary → fallback):
```js
const COMPOSER_SELECTORS = [
'[data-component="prompt-input-v2"]', // v2 form-контейнер (v1.18.x primary)
'[data-component="session-prompt-dock"]', // v1.18.x регион-обёртка
'[data-component="session-new-composer"]', // pre-1.18 fallback
'[data-component="session-composer"]', // legacy fallback (<1.17)
];
```
## Альтернативы
### 1. Только новые селекторы (без fallback)
- **Плюс**: проще, нет мёртвого кода после `oldInterfaceSunset`.
- **Минус**: ломает пользователей на OpenCode <1.18 (а это основная установленная база до 14.09.2026). Нарушает acceptance criterion "старые версии остаются совместимы".
### 2. Только `session-prompt-dock` (без `prompt-input-v2`)
- **Плюс**: один селектор для региона.
- **Минус**: `prompt-input-v2` появляется раньше в lifecycle (form-контейнер монтируется внутри dock'а до того, как dock готов). Пропуск `prompt-input-v2` задерживает появление кнопки. Issue явно требует оба селектора.
### 3. Обратный порядок (fallback → primary)
- **Минус**: на v1.18.x `findComposer()` сразу вернёт `null` для `session-composer`/`session-new-composer` (они удалены), потом найдёт `session-prompt-dock` работает, но семантически неверно и менее читаемо. Плюс на гибридных сборках может совпасть устаревший элемент первым.
## Последствия
- Кнопка 🎤 появляется в OpenCode v1.18.x (через `prompt-input-v2` или `session-prompt-dock`).
- Обратная совместимость с OpenCode <1.18 сохранена через `session-new-composer` / `session-composer`.
- После `oldInterfaceSunset` (14.09.2026) два последних селектора станут мёртвым кодом можно удалить отдельным PR, не критично.
- Порядок массива = приоритет детекции; `findComposer()` без изменений.
- Не затрагивает `src/insert.ts` (gate `[data-component="prompt-input"]` остаётся валидным в обеих версиях UI).
## Источники
- `sst/opencode` main (commit 2b2aacc, web pkg 1.18.4):
- `packages/app/src/pages/session/composer/session-composer-region.tsx:26` `session-prompt-dock`
- `packages/session-ui/src/v2/components/prompt-input/index.tsx:107` `prompt-input-v2`
- `packages/app/src/context/settings.tsx:62` `oldInterfaceSunset = 2026-09-14`
- Память: `technical/opencode-web-ui-composer-selectors-1.18.4.md`