* feat: support OpenCode steer delivery / follow-up behavior settings
Implements issue #1766 — steer delivery mode for mid-turn message
insertion, replacing the old boolean queue-mode toggle with a tri-state
follow-up behavior setting (Steer / Queue / Send immediately).
- Plumbing: threaded optional delivery: 'steer' through sendMessage
-> routeMessage -> opencodeClient.sendMessage -> promptAsync
- Store: messageQueueStore stores followUpBehavior; migration from
legacy queueModeEnabled persisted state
- Settings: Chat -> Follow-up behavior shows three radio options
using existing settings UI patterns
- Composer: when session is busy, a floating queue button remains;
force-sending a queued message (via chip click) uses delivery: 'steer'
during a busy session; Steer button intentionally omitted — steer is
available via the two-gesture path (Enter to queue -> chip to steer)
- Keyboard: queue mode = Enter queues, Ctrl+Enter sends; otherwise
Enter sends, Ctrl+Enter queues
- Persistence: DesktopSettings, web settings payload, and server-side
sanitizer handle the new key with legacy fallback
- i18n: follow-up behavior section and option labels in all 9 locales
plus new chat.chatInput.actions.queue label
- Search: settings registry updated from chat.queue-mode to
chat.follow-up-behavior
Validation: type-check passes (no new errors), lint clean.
* fix(#1766): make steer mode actually steer
The followUpBehavior === 'steer' branch in handlePrimaryAction and the
keyboard handler was a no-op — both fell into the else branch and sent
without the delivery: 'steer' flag, so selecting 'Steer (insert into
the running turn)' in settings produced identical behavior to 'Send
immediately'.
- handlePrimaryAction: when steer mode is selected and the session is
busy, call handleSubmit({ delivery: 'steer' }) directly
- Keyboard handler: in steer mode, Enter steers and Ctrl+Enter sends
immediately (consistent with queue mode where Ctrl+Enter bypasses
the special handling)
Also removes the unused chat.chatInput.actions.queue i18n key from all
9 locales (it was a dead key after the Steer button was removed from
the composer).
Validation: type-check clean, lint clean.
* refactor(#1766): flatten nested ternary in followUpBehavior resolution
Replace nested ternary with explicit if/else chain per project code style
(CONTRIBUTING.md). Import FollowUpBehavior type explicitly for the new
let declaration.
* feat(chat): drop redundant 'immediate' follow-up mode, keep Queue + Steer
'Immediate' was wire-identical to 'Steer' on a busy session: OpenCode only
supports delivery 'steer' | 'queue' and defaults to 'steer', so an immediate
send (no delivery flag) already steered into the running turn. The three-mode
UI therefore exposed two settings that did the same thing.
Collapse to two modes — Queue (unchanged: client-side queue with edit/reorder)
and Steer. Any persisted/legacy 'immediate' (and legacy queueModeEnabled=false)
now maps to 'steer', preserving prior behavior. Removes the immediate option,
its keyboard branch, the i18n label across all locales, and narrows the
followUpBehavior union to 'steer' | 'queue'.
---------
Co-authored-by: Leonid Skorobogatyy <bash@opencode.itc.local>
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>