Skip to content

Conversation

@cpjet64
Copy link
Contributor

@cpjet64 cpjet64 commented Oct 24, 2025

Harden Windows TUI paste-burst handling

Problem & intent

Large multi-read pastes on Windows could drop out of “pasting” mid-stream and submit early (often around line 6/12 on long inputs). This PR hardens the TUI input handler so pastes are treated as one cohesive input, without changing any platform env behavior (PATH/PATHEXT/etc. are already addressed by #5579).


Before / After

Before
The heuristic paste guard could expire between read() chunks; the next Enter/\r was treated as Submit instead of a newline.

After

  • A rolling, size‑adaptive idle window keeps is_pasting true across read() chunks.
  • Enter is gated during paste (inserts \n, no submit) until the paste ends or the window elapses.
  • Paste “recency” is tracked so micro‑gaps don’t leak a submit.
  • Bracketed paste (when available) remains handled as one paste input.

Scope of change

codex-rs/tui/src/bottom_pane/paste_burst.rs

  • Add last_paste_at timestamp to persist paste state across multi‑read bursts.
  • Introduce size‑adaptive window: base (from CODEX_PASTE_GUARD_MS, default 180 ms), +160 ms for ≥ 1 KiB, +320 ms for ≥ 2 KiB.
  • Widen submit grace to 16 ms; gate submit if still within deadline or within base guard since last_paste_at.
  • Provide mark_explicit_paste(size, now) and call it on explicit paste events.

codex-rs/tui/src/bottom_pane/chat_composer.rs

  • Call mark_explicit_paste(...) from the paste handler.

Note: Input-only CRLF normalization (while pasting) is unchanged and remains separate from file‑I/O CRLF preservation (to be addressed in a different PR).


Security effects

None. This only changes how input bytes are interpreted in the TUI. No policy, sandbox, or privilege changes.


Testing evidence

Static

  • cargo fmt
  • cargo clippy -p codex-tui -- -D warningsclean
  • cargo test -p codex-tuipassing (424 tests)

Manual verification (Windows Terminal, PowerShell 5/7)

A) Variant 1

Line 1 - short burst start
Line 2 - keep pasting
Line 3 - quick newline
Line 4 - no delay
Line 5 - halfway
Line 6 - watch if this submits
Line 7 - continuing
Line 8 - still going
Line 9 - nearly there
Line 10 - end of paste burst

B) Variant 2

First line of a Windows paste test.
This should appear as line two when pasted into Codex.
Line three contains multiple    spaces    and tabs.	Watch alignment.
Line four is deliberately long to simulate paragraph-like input that could be chunked by the terminal paste buffer when testing for burst detection in bracketed-paste mode. It includes commas, semicolons, and other punctuation—,;—to ensure UTF-8 and escape handling are intact.
Line five: verify that pressing Enter during paste doesn’t send prematurely.
Line six: watch for ghost submits or truncated characters at buffer boundaries.
Line seven: 🧪 emoji test.
Line eight: quotes " ' ` and backslashes \ check encoding.
Line nine: test line endings — should stay \r\n if CRLF mode is preserved.
Final line of test block. If the paste-burst guard works, all of these lines should appear together as one input buffer without auto-submission.

C) Variant 3

Short 1
Short 2
Long 3 - this line has a bit more content to test chunk boundaries in the paste buffer; it includes punctuation, quotes, and a few extra words.
Short 4
Long 5 - another extended line of text that would previously have tripped the burst detector if buffer size or timing thresholds were too low.
Short 6
Short 7
Final 8 - done.

D) Variant 4

[00] This is a large-burst stress test block intended to exercise multi-read paste handling on Windows terminals. It mixes very long lines and short lines to push through PTY/readline chunk boundaries without actually intending to submit anything mid-paste.
[01] short
[02] very long → Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vestibulum rhoncus, risus non ultricies pharetra, mauris augue hendrerit nulla, quis tincidunt nisl ex non urna. Donec porttitor, sapien id fermentum dictum, nibh sem tincidunt tortor, nec gravida sapien risus sed justo. Curabitur ultrices, arcu id suscipit sagittis, ligula ipsum mollis justo, laoreet congue nibh sapien eget tortor. Curabitur suscipit efficitur lectus. Mauris ut nunc orci. Suspendisse posuere, augue a pretium suscipit, dui arcu facilisis turpis, sit amet lacinia massa urna id dui.
[03] short
[04] very long → AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA (padding to increase payload) AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[05] short
[06] very long → brackets, quotes, slashes: [ { ( < > ) } ]  " ' `  / \  and some emoji to confirm UTF-8 🧪💻🧵⚙️  plus CRLF mention to ensure we don’t flip endings on Windows.
[07] short
[08] very long → Another paragraph to exceed a few kilobytes total. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit.
[09] short
[10] very long → Repeating pattern padding: xyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyz
[11] short
[12] very long → End-to-end check that Enter during paste is ignored and that no premature submit occurs even if this block crosses multiple read() calls internally. The final line below should still be part of the same input buffer.
[13] FINAL LINE — if the paste guard works, you’re reading this as part of one cohesive input without any auto-submission in the middle.

E) Variant 5

[SIZE-TEST] START
[PAD-01] AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[PAD-02] AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[PAD-03] AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[PAD-04] AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[PAD-05] AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[PAD-06] AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[PAD-07] AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[PAD-08] AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[PAD-09] AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[PAD-10] AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[SIZE-TEST] END

Configuration

  • Base window tunable via CODEX_PASTE_GUARD_MS (default 180 ms).

Checklist

…d; submit grace

- Track last_paste_at to keep paste active across large multi-read bursts
- Adaptive idle window: +160ms for >=1KB, +320ms for >=2KB chunks (base from CODEX_PASTE_GUARD_MS, default 180ms)
- Widen submit grace to 16ms; gate Enter while within deadline or recent paste window
- Treat bracketed paste as explicit paste; small-paste behavior unchanged
- Input-only: CRLF normalization remains in TUI paste path; no file I/O changes

Refs openai#5499 openai#2137; partial openai#5194
@luodaoyi
Copy link

迫切需要修复这个问题!

@luodaoyi
Copy link

没有人来审批吗? 迫切需要修复这个问题,现在windows的终端模式基本无法使用!

@etraut-openai
Copy link
Collaborator

Thanks for the contribution, and apologies for the slow response. We have a large backlog of PRs that we're getting through.

If you're still interested in pursuing this PR, could you please fix the CI failures? Looks like a formatting issue, so it should be easy to address.

@etraut-openai etraut-openai added the needs-response Additional information is requested label Nov 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-response Additional information is requested

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants