feat(mobile): keep agent composers editable during live dictation - #5607
Conversation
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Executive SummaryReviewed the Files Reviewed (86 files)
Previous Review Summaries (5 snapshots, latest commit c2664e9)Current summary above is authoritative. Previous snapshots are kept for context only. Previous review (commit c2664e9)Status: No Issues Found | Recommendation: Merge Executive SummaryReviewed the new-session prompt controls extract and clone-entry wiring across 3 files with high confidence and no correctness, security, or runtime issues. Files Reviewed (3 files)
Previous review (commit 49dfa87)Status: No Issues Found | Recommendation: Merge Executive SummaryReviewed the new-session mic size bump to Files Reviewed (1 file)
Previous review (commit 95839c3)Status: No Issues Found | Recommendation: Merge Executive SummaryReviewed send-gating on failed attachments and the enlarged composer mic target across 6 files with high confidence and no correctness, security, or runtime issues. Files Reviewed (6 files)
Previous review (commit 9552aeb)Status: No Issues Found | Recommendation: Merge Executive SummaryReviewed the Files Reviewed (2 files)
Previous review (commit c646c88)Status: No Issues Found | Recommendation: Merge Executive SummaryReviewed selection-aware dictation, composer editability during voice, and send/stop animation across 11 files with high confidence and no correctness, security, or runtime issues. Files Reviewed (11 files)
Reviewed by grok-4.6 · Input: 107.2K · Output: 10K · Cached: 333.2K Review guidance: REVIEW.md from base branch |
# Conflicts: # apps/mobile/src/components/agents/new-session-prompt.tsx
Summary
Maintainer changelog
File sizes count added and removed lines from the supplied statistics.
Mmeans modified;Ameans added.applyVoiceDraftAtSelectionaddsApplyVoiceDraftAtSelectionOptionsandApplyVoiceDraftAtSelectionResult, returninginsertedorabortedinstead of always replacing the draft.VoiceInputTextInputgains optionalVoiceInputSelection;resolveVoiceTranscriptDeltaextracts speech, andresolveVoiceInsertionusesResolveVoiceInsertionOptionsandResolvedVoiceInsertionto preserve surrounding text.maxLengthlimits inserted speech; edits or composition abort without writing, while existingapplyVoiceDraftToInputcallers retain full-draft replacement.Files
apps/mobile/src/lib/voice-input/voice-input-draft.ts— Source, M, 149 changed lines; adds selection normalization, range replacement, spacing, transcript limits, and native text-and-caret updates before callbacks.apps/mobile/src/lib/voice-input/voice-input-draft.test.ts— Test, M, 220 changed lines; updates the draft-bridge regression tests.ChatComposerandNewSessionPromptno longer use speech alone to disableinputEditable;getDraftrecords the starting draft and selection.If any text edit changes the expected draft, they call
abortand announcevoiceInput.listeningStoppedrather than overwrite the edit.React Native 0.86 exposes no composition event, so
isComposingstays false and draft comparison also protects input method editor edits.Files
apps/mobile/src/components/agents/chat-composer.tsx— Source, M, 47 changed lines; wires caret-based speech, abort announcements, and the attachment-failure flag while retaining send and persistence flows.apps/mobile/src/components/agents/new-session-prompt.tsx— Source, M, 101 changed lines; wires caret-based speech and delegates the action row while retaining clone, prefill, and creation flows.apps/mobile/src/components/agents/new-session-prompt-state.ts— Source, M, 12 changed lines; permits editing and paste during speech while retaining the creation lock and attachment-picker lock.apps/mobile/src/components/agents/new-session-prompt-state.test.ts— Test, M, 6 changed lines; updates the prompt-state regression tests for editable voice sessions.ChatComposerControlInputadds requiredhasFailedAttachments;resolveChatComposerControlStateincludes it incanSend, so failed files disable Send before submission.Callers must supply the failure flag instead of relying only on press-time errors; existing content, upload, and send checks remain.
Files
apps/mobile/src/components/agents/chat-composer-input-state.ts— Source, M, 16 changed lines; adds failure-aware send admission and removes voice activity from editability while retaining attachment and toolbar locks.apps/mobile/src/components/agents/chat-composer-input-state.test.ts— Test, M, 38 changed lines; updates the control-state regression tests.ChatComposerInputRowkeeps the microphone available duringisStreamingand switches keyed Send/Stop controls with 150-millisecond entrances and 100-millisecond exits.useReducedMotionremoves both fades; the existing content, send, and disabled checks still decide which action appears and accepts presses.Files
apps/mobile/src/components/agents/chat-composer-input-row.tsx— Source, M, 84 changed lines; retains the microphone during streaming, selects its large size, and adds reduced-motion-aware action transitions.apps/mobile/src/components/agents/chat-composer-input-row.mounted.test.tsx— Test, M, 41 changed lines; updates the mounted input-row tests.VoiceInputButtonSizeaddslg: a 40-point control with four-point hit slop on each side, giving the agent inputs a 48-point target.Existing
sm,md, and default styles remain unchanged, so other voice-button callers keep their current sizes.Files
apps/mobile/src/components/voice-input-control.tsx— Source, M, 7 changed lines; adds the large button style and its paired touch-area expansion.NewSessionPromptControlsandNewSessionPromptControlsPropsseparate the attachment, paste, listening status, and large microphone controls from prompt state.The props reuse the control-state and voice-hook return types, preserving attachment limits, input-based paste gating, voice availability, and existing action callbacks.
Files
apps/mobile/src/components/agents/new-session-prompt-controls.tsx— Source, A, 73 changed lines; extracts the action row, retains its accessibility labels and gates, and selects the large microphone.apps/mobile/src/components/agents/new-session-prompt-initial-prompt.test.ts— Test, M, 73 changed lines; updates the initial-prompt regression tests for the control extraction.voiceInput.listeningStoppedadds a localized accessibility announcement for edit-triggered dictation cancellation in English and 86 translated catalogs.English supplies the canonical message; the prepared translation merge updates the 86 bundled locale assets.
Each translated catalog gains one value without changing existing text, key order, hierarchy, placeholders, or plural forms.
Files
apps/mobile/src/i18n/locales/en.json— Source, M, 1 changed line; adds the canonical message, “Listening stopped.”apps/mobile/src/i18n/locales/af.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/am.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/ar.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/az.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/be.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/bg.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/bn.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/bs.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/ca.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/ckb.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/cs.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/cy.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/da.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/de.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/el.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/es.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/et.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/eu.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/fa.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/fi.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/fil.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/fr.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/ga.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/gl.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/gu.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/ha.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/he.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/hi.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/hr.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/ht.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/hu.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/hy.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/id.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/ig.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/is.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/it.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/ja.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/ka.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/kk.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/km.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/kn.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/ko.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/lo.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/lt.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/lv.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/mg.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/mi.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/mk.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/ml.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/mn.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/mr.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/ms.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/mt.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/my.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/nb.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/ne.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/nl.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/om.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/or.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/pa.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/pl.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/ps.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/pt-BR.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/pt.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/ro.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/ru.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/si.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/sk.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/sl.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/so.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/sq.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/sr.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/sv.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/sw.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/ta.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/te.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/th.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/tr.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/uk.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/ur.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/uz.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/vi.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/yo.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/zh-Hans.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/zh-Hant.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.apps/mobile/src/i18n/locales/zu.json— Generated, M, 3 changed lines; adds the prepared listening-stopped translation.Inventory: 100 files — 9 source files, 5 test files, and 86 generated assets; 909 insertions and 217 deletions.
Tests: 5 files updated —
chat-composer-input-row.mounted.test.tsx,chat-composer-input-state.test.ts,new-session-prompt-initial-prompt.test.ts,new-session-prompt-state.test.ts, andvoice-input-draft.test.ts; 378 changed lines.Generated: 86 bundled translation catalogs updated; 258 changed lines, with one new value per catalog.
Verification
Visual Changes
Visual Changes: N/A
Reviewer Notes
Human steps
Scope and recorded checks
Kilo-Org/cloud; this description covers immutable level 5, PR 5607.70a2b95c57715dcb5a1d6bc355adb19eb8155bf2; head:ba3b08b933c5b2079439c199194f9d022f506429./Users/igor/Projects/.worktrees/agent-composers-c07a, checked out onagent-composers-c07a-s6; source reads use the immutable level-5 head./Users/igor/Projects/.worktrees/agent-composers-c07a-kilocode, branchagent-composers-c07a; reference only, with no sibling changes included.Cumulative runtime verification and its limits are recorded in #5617.
Stacked PRs — merge bottom to top. Each level shows only its own diff.
Runtime verification (E2E, user advocacy, simplify) runs on the tip PR over every level.
Every level keeps its own checks, its own bot review, and its own threads; each one is answered on its own PR.
Each level is its own deliverable: it builds and passes its own checks alone.
A finding on a level is repaired on that level, then carried upward with stack.sh forward.
agent-composers-c07a— feat(agent-composer): add message identity and queue cancel APIs #5537agent-composers-c07a-s2— feat(mobile): pre-upload attachments and release abandoned files #5538agent-composers-c07a-s3— feat(mobile): reorder composer attachments with drag and a11y moves #5540agent-composers-c07a-s4— feat(agent-composer): render sent messages immediately and cancel queued ones #5589agent-composers-c07a-s5— feat(mobile): keep agent composers editable during live dictation #5607agent-composers-c07a-s6— feat(mobile): adapt agent composers for keyboard, height, and preferences #5617 (tip)