Prevent IME Enter from submitting Duo Agentic Chat prompt
What does this MR do and why?
On macOS, in both Chrome and Safari, I saw a bug with a Japanese IME. Pressing Enter to confirm a kanji conversion in the web UI Duo Agentic Chat sent the unfinished message.
Root cause
This is the event order I saw in Chrome DevTools:
- The Enter
keydownthat confirms the conversion fires before thekeyupof the last typed character. - The
keyupof the last character arrives. - The Enter
keyupfires. By nowisComposingis already false.
The old code sent the message on Enter keyup. It set a flag (compositionJustEnded) on compositionend to skip the next Enter. But every keyup cleared that flag. The keyup of the last character (step 2) cleared it. So the Enter keyup (step 3) sent the message.
Fix
In prompt_textarea.vue, I now send on keydown instead. At keydown, isComposing is still true for the confirming Enter. The component skips sending when:
- the key is not Enter
e.isComposingis true, ore.keyCode === 229. Key code 229 means the IME is handling the key. It is a fallback for browsers whereisComposingcan already be false. One example is Safari, whencompositionendfires beforekeydown.e.repeatis true (Enter is held down)- a modifier key is pressed (Shift+Enter still inserts a new line)
I also made these changes:
- I removed the
compositionJustEndedflag, thecompositionendhandler, and theresetComposition()method. - In
prompt_composer.vue, I removed theresetComposition()call after a slash command is selected. It is no longer needed. - The slash commands menu still catches Enter on
keydownin the capture phase and stops it. So picking a command with Enter does not send. Tests cover this. - In
slash_commands_menu.vue, I updated the comment onswallowKeyup. It no longer stops a keyup-based send, but it still keeps the keyup from reachingevaluate(). Without it, the menu would reopen right after Escape closes it. - I updated the specs. In
prompt_textarea_spec.js, I usekeydowninstead ofkeyup. I added cases for key code 229 andrepeat, and a check that a later Enter still submits after an IME Enter is ignored. I removed thecompositionendtests. Inprompt_composer_spec.js, I changedkeyuptokeydown. The composition-flag test now checks that a later Enter can send after picking a slash command. Inslash_commands_menu_spec.js, I added a check that the menu stays closed after the Escape keyup.
Scope
This changes only the web UI Duo Agentic Chat. The issue was first reported in the VS Code extension. I did not verify the fix there. The classic Duo Chat (ee/app/assets/javascripts/ai/tanuki_bot/components/duo_chat_view.vue) still uses the old keyup approach. I did not change it.
References
- Related to #588935
- Root cause investigation: #588935 (comment 3760316253)
- Similar earlier fix in GitLab UI: gitlab-ui!4305 (merged)
Screenshots or screen recordings
| Before | After |
|---|---|
I tested this locally in GDK on macOS Chrome and macOS Safari with a Japanese IME. Before the fix, both sent the message on the confirming Enter. After the fix, neither does.
How to set up and validate locally
- Open Duo Agentic Chat in the web UI in GDK.
- Turn on a Japanese IME.
- Type hiragana and press Enter to confirm the kanji conversion. The message is not sent.
- Press Enter again. The message is sent once.
- Press Shift+Enter. A new line is inserted.
- Type
/coand press Enter on a slash command. The command is inserted and nothing is sent.
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.