Skip to content

fix(tui): collapse large pastes to prevent input freeze - #2777

Open
dhnihaoya wants to merge 2 commits into
MoonshotAI:mainfrom
dhnihaoya:fix/paste-collapse-freeze
Open

fix(tui): collapse large pastes to prevent input freeze#2777
dhnihaoya wants to merge 2 commits into
MoonshotAI:mainfrom
dhnihaoya:fix/paste-collapse-freeze

Conversation

@dhnihaoya

Copy link
Copy Markdown

Related Issue

Resolve #2776

Problem

See linked issue. In short: pasting a large block of text (thousands of chars, especially mixed CJK/English) into the TUI input froze the whole interface until the process was killed/restarted. Typing the same text character-by-character was fine.

Root cause: on terminals that do not honour bracketed-paste mode (or where it gets stripped — e.g. tmux without pass-through, some SSH setups, older terminals), the paste arrives as plain stdin and is inserted character-by-character. Each character triggers a full editor reflow + re-render, so a single bulk paste is O(n²) on the main thread and locks all input.

What changed

  • pi-tui stdin-buffer: detect plain stdin chunks over 800 chars (no escape sequences) and coalesce them into a single paste event, with a 100 ms debounce window to merge read-split continuation chunks. terminal.ts already re-wraps paste events with bracketed-paste markers, so the editor's existing handlePaste path folds the whole payload in one O(n) pass instead of per-character.
  • pi-tui editor: fold pastes into a [Pasted text #N] marker when they exceed 800 chars or 10 newlines (keeps short multi-line pastes visible). Marker format switched to Claude-style [Pasted text #N +x lines]; the segmenting/expansion regex accepts both the new and the legacy [paste #N …] form, so existing markers still expand.
  • kimi-code custom-editor: its paste-marker regex tracks the same dual format.

Notes / trade-offs

  • Coalescing triggers when a single stdin read exceeds 800 chars — the common case, since the terminal writes the whole clipboard in one syscall. A paste delivered as many sub-800-char chunks from the very first read would still process per-character; robustly covering that needs time-based detection and is left as a follow-up.
  • The fold line threshold is 10 newlines (≈11 lines); 4–10 line pastes render literally.

Checklist

Pasting a large block into the TUI input froze the interface on terminals
that do not honour bracketed-paste mode: the payload arrived as plain stdin
and was inserted character-by-character, each keystroke triggering a full
editor reflow (O(n^2)).

- pi-tui stdin-buffer: coalesce plain stdin chunks over 800 chars into a
  single `paste` event (100ms debounce to merge split reads), so the editor
  folds the whole payload once instead of per-character.
- pi-tui editor: fold pastes into a `[Pasted text #N]` marker when they
  exceed 800 chars or 10 newlines; keep short multi-line pastes visible.
  The marker regex accepts both the new and the legacy `[paste #N]` format.
- kimi-code custom-editor: track the dual-format paste-marker regex.

Resolve MoonshotAI#2776
@changeset-bot

changeset-bot Bot commented Aug 10, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: db559d2

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@moonshot-ai/kimi-code Patch
@moonshot-ai/pi-tui Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7a46b73604

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +334 to +335
this.appendNonBracketedPaste(str);
return;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Do not append post-paste key sequences to the paste buffer

When a large non-bracketed paste is pending, this branch appends every following stdin chunk for 100 ms, including control/escape sequences that are user keystrokes rather than paste continuations. If the user immediately presses Enter to submit, or an arrow/backspace key after pasting >800 chars, that key is swallowed into the synthetic paste event instead of being dispatched; escape sequences can also be rewrapped as bracketed paste content and leak printable tails like [D into the editor. Flush the pending paste before handling non-plain key sequences, or only coalesce chunks that are still plain paste content.

Useful? React with 👍 / 👎.

While the non-bracketed paste coalescing window is open, any stdin chunk
arriving within 100ms was appended verbatim to the synthetic paste, so an
arrow / backspace / Ctrl key pressed right after a large paste was swallowed
into the paste event and escape sequences leaked printable tails (e.g. [D)
into the editor.

Only coalesce continuation chunks that are still plain paste content; the
first ESC / DEL / C0 control flushes the pending paste and is processed as a
normal keystroke instead. CR / LF / tab stay coalesced so a multi-line paste
split across reads is not flushed mid-stream.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] TUI 输入框一次性粘贴大量文字时整个界面完全卡死(多平台可复现)

1 participant