Skip to content

Bug: Control UI chat composer breaks CJK IME composition #86035

Description

@Zhaoqj2016

Summary

The Control UI chat composer textarea breaks macOS/browser IME composition for CJK input (Chinese/Japanese/Korean). After switching to a Chinese input method, typing pinyin in the chat box shows raw Latin letters (e.g. dangqian) instead of IME candidate selection / committed characters.

This makes the WebChat / Control UI effectively unusable for CJK typing without copy-paste workarounds.

Environment

  • OpenClaw version: 2026.5.22 (a374c3a)
  • OS: macOS 26.3 (arm64)
  • Browser: Google Chrome (also reproducible in WebChat Control UI)
  • Gateway: local, http://127.0.0.1:18790/chat
  • Input method: macOS Chinese IME (system built-in / third-party pinyin)

Steps to reproduce

  1. Start local Gateway and open Control UI chat (/chat).
  2. Click the chat composer textarea (.agent-chat__composer-combobox > textarea).
  3. Switch to a Chinese input method.
  4. Type pinyin, e.g. zai ma or dangqian.
  5. Try to select candidates with space / number keys.

Expected behavior

  • IME candidate window appears.
  • User can compose and commit Chinese characters normally.
  • Committed text appears in the composer.

Actual behavior

  • Raw pinyin letters are inserted directly into the textarea.
  • IME candidate UI is missing or non-functional.
  • User cannot compose Chinese text in the Web UI.

Notes

  • Paste works as a workaround.
  • openclaw tui and openclaw agent -m "..." work fine (terminal/CLI paths are unaffected).
  • Prior fix macOS/ChatUI: keep Return for IME marked text commit #25178 added isComposing handling for Enter/send, but the issue persists during normal composition because @input still syncs draft state on every keystroke.

Root cause (observed in built Control UI)

The chat composer uses a controlled Lit textarea:

  • .value=${draft}
  • @input handler immediately calls onDraftChange(value) on every input event
  • @keydown does guard Enter with isComposing / keyCode === 229

In the built bundle (dist/control-ui/assets/index-*.js), the input handler is effectively:

// input handler
(t) => {
  const el = t.target;
  resizeTextarea(el);
  updateSlashMenu(el.value, rerender);
  onDraftChange(el.value);
}

// Enter handler (already guarded)
if (key === "Enter" && !shiftKey) {
  if (isComposing || keyCode === 229 || !connected) return;
  preventDefault();
  send();
}

A likely fix is to avoid syncing the controlled draft state while IME composition is active, and only commit the textarea value on compositionend (while still allowing resize/slash-menu behavior as appropriate).

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High-priority user-facing bug, regression, or broken workflow.clawsweeper:linked-pr-openClawSweeper found an open linked pull request for this issue.clawsweeper:needs-live-reproClawSweeper needs live local, crabbox, or manual validation to confirm this issue.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.impact:otherThis issue has meaningful maintainer-visible impact outside the owned taxonomy.issue-rating: 🐚 platinum hermitGood issue quality with a plausible reproduction path needing some confirmation.

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions