Skip to content

[Bug]: Desktop app: Enter key sends message during IME composition (Japanese, Chinese, Korean, etc.) #37483

@satotakumi

Description

@satotakumi

Bug Description

In the Hermes Desktop (macOS) chat composer, pressing Enter while an IME composition is in progress (Japanese, Chinese, Korean, Vietnamese, etc.) is treated as "send message" instead of "commit the composition".

Concrete example: type "きょうは" (pre-conversion kana) and press Enter to commit the conversion → "今日は". Instead of committing the candidate and leaving the draft in the composer, the message gets sent (often with the just-committed or partially-committed text) to the agent.

Steps to Reproduce

  1. Launch the Hermes Desktop app (v0.15.1) on macOS.
  2. Enable a Japanese IME (macOS "Japanese Input", ATOK, or Google Japanese Input).
  3. In the chat composer, type "きょうは" (pre-conversion kana).
  4. The candidate list appears (e.g. "今日", "京は", "京").
  5. Press Enter to commit the candidate.
  6. Actual: the commit fires AND the message is sent to the agent immediately.
  7. Expected: the candidate commits to "今日は" and stays in the composer; sending requires a separate action.

Expected Behavior

Enter while composing should commit the IME candidate and must NOT trigger message submission. After the composition ends, a subsequent Enter (or the send button / Cmd+Enter) submits the message.

Actual Behavior

Enter during composition fires the submit handler, so partially- or fully-committed text is sent to the agent. Users who rely on CJK or other compositional input methods are effectively blocked from using the composer normally.

Affected Component

  • Other (Desktop — macOS Electron app, apps/desktop/)

The bug_report template's component list does not include a "Desktop" option, so "Other" is selected. The bug lives in the Hermes Agent Desktop renderer (apps/desktop/, Electron + Vite + React + TypeScript + @assistant-ui/react).

Messaging Platform: N/A (CLI only)

Debug Report

Capturing Electron renderer logs for the desktop app via hermes debug share is not straightforward, so the direct code-level cause is documented here in place of the usual paste links.

  • File: apps/desktop/src/app/chat/composer/index.tsx

  • Handler: handleEditorKeyDown (bound at line 1042 via onKeyDown={handleEditorKeyDown})

  • Relevant code (line 592):

    if (event.key === 'Enter' && !event.shiftKey) {
      event.preventDefault()
      ...
      submitDraft()
    }

There is no isComposing check, so Enter events fired during an active IME composition (which Chromium sets KeyboardEvent.isComposing = true on) flow straight into the submit handler.

Operating System

macOS 26.5 (darwin-arm64, Apple Silicon)

Python Version

N/A (the Desktop renderer is independent of Python)

Hermes Version

Hermes Desktop v0.15.1

Additional Logs / Traceback (optional)

None. This is a pure UI key-event handling bug; no console errors are produced. With DevTools open, you can observe the sequence compositionstart → Enter keydown (isComposing=true) → compositionend → submit, all back-to-back.

Root Cause Analysis (optional)

Direct cause

The Enter-to-submit branch in apps/desktop/src/app/chat/composer/index.tsx:592 does not consult event.nativeEvent.isComposing:

if (event.key === 'Enter' && !event.shiftKey) {

For Enter fired during IME composition:

  • Chromium / modern IMEs: KeyboardEvent.isComposing === true
  • Older WebKit/Chromium: keyCode === 229 (the "Process" key)

Impact scope (entire Desktop app)

A grep of apps/desktop/src/ for isComposing, compositionstart, compositionend returns zero matches. Other Enter-handling sites with the same bug:

  1. apps/desktop/src/app/chat/composer/index.tsx:573 — Enter in the / @ trigger popover
  2. apps/desktop/src/app/chat/composer/index.tsx:592main submit (the primary symptom in this issue)
  3. apps/desktop/src/components/assistant-ui/thread.tsx:1239 — message edit mode submit
  4. apps/desktop/src/components/desktop-onboarding-overlay.tsx:486, 554 — API key / auth code input
  5. apps/desktop/src/app/chat/sidebar/session-actions-menu.tsx:227 — session rename

Related issues / PRs (for context — none target Desktop)

Proposed Fix (optional)

Minimal patch:

--- a/apps/desktop/src/app/chat/composer/index.tsx
+++ b/apps/desktop/src/app/chat/composer/index.tsx
@@ -589,7 +589,7 @@ export function ChatBar({
       }
     }

-    if (event.key === 'Enter' && !event.shiftKey) {
+    if (event.key === 'Enter' && !event.shiftKey && !event.nativeEvent.isComposing) {
       event.preventDefault()

       if (!busy && !hasComposerPayload && queuedPrompts.length > 0) {

Why event.nativeEvent.isComposing: React 17+ SyntheticEvent does expose isComposing, but referring to the native event directly is safer given Electron's bundled Chromium version skew and the wide variety of IME implementations in the wild.

The minimal patch above resolves the primary symptom reported here. The following sites need the same treatment and will be covered in the upcoming PR:

  • composer/index.tsx:573 (trigger popover)
  • assistant-ui/thread.tsx:1239 (edit mode)
  • desktop-onboarding-overlay.tsx:486, 554 (API input)
  • session-actions-menu.tsx:227 (rename)

Are you willing to submit a PR for this?

  • I'd like to fix this myself and submit a PR

Suggested labels (could not self-apply: AddLabels permission denied for the reporter account):

  • type/bug — UI input-handling bug
  • P2 — degraded but workaround exists (commit candidate, then press Enter again or use the send button)

Happy to apply both if a maintainer grants triage-level access, or to wait for maintainer triage.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium — degraded but workaround existstype/bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions