fix(cli): bracketed-paste timeout prevents permanent input freeze (#16263)#32018
Merged
Conversation
Contributor
🔎 Lint report:
|
| Rule | Count |
|---|---|
unresolved-import |
4 |
invalid-argument-type |
1 |
First entries
tests/cli/test_bracketed_paste_timeout.py:45: [invalid-argument-type] invalid-argument-type: Argument to function `exec` is incorrect: Expected `str | Buffer | CodeType`, found `str | None`
cli.py:2380: [unresolved-import] unresolved-import: Cannot resolve imported module `prompt_toolkit.input.vt100_parser`
tests/cli/test_bracketed_paste_timeout.py:51: [unresolved-import] unresolved-import: Cannot resolve imported module `prompt_toolkit.input.vt100_parser`
cli.py:2382: [unresolved-import] unresolved-import: Cannot resolve imported module `prompt_toolkit.key_binding.key_processor`
tests/cli/test_bracketed_paste_timeout.py:14: [unresolved-import] unresolved-import: Cannot resolve imported module `prompt_toolkit.keys`
✅ Fixed issues: none
Unchanged: 4924 pre-existing issues carried over.
Diagnostics are surfaced as warnings — this check never fails the build.
…6263) When the terminal drops the ESC[201~ end mark during a bracketed paste (terminal race, torn write, SSH glitch, macOS sleep/wake), prompt_toolkit's Vt100Parser keeps buffering all later input in _paste_buffer forever. From the user's perspective, the CLI appears frozen — the only recovery was closing the tab/session. This patch monkey-patches Vt100Parser.feed() so that bracketed-paste mode flushes buffered content as a normal BracketedPaste event after 2 seconds without an end marker, then restores normal parsing. Includes 8 regression tests covering normal paste, timeout recovery, torn end marks, and edge cases. Surgical reapply of PR #27518. Original branch was many months stale (1193 files / 172k LOC of unrelated reverts); the substantive ~77 LOC patch in cli.py plus the new 157-line test file were reapplied onto current main with the contributor's authorship preserved via --author.
…o Tranquil-Flow (PR #27518)
2460b73 to
1c71e9c
Compare
19 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
When the terminal drops the
ESC[201~end mark during a bracketed paste — SSH glitch, terminal race, macOS sleep/wake, torn network write — prompt_toolkit'sVt100Parserkeeps buffering all later input in_paste_bufferforever. From the user's perspective, the CLI appears frozen. The only recovery was killing the tab. Fixes #16263.Fix
Monkey-patch
Vt100Parser.feed()to track a_hermes_bp_starttimestamp when bracketed-paste mode is entered. IfESC[201~hasn't arrived after 2 seconds, flush the buffered content as a normalBracketedPasteevent, restore normal parsing, and log a warning so the user can correlate it with#16263inagent.log.The patch is idempotent — repeated calls are no-ops via a sentinel on the module.
Changes
cli.py— new_apply_bracketed_paste_timeout_patch()function (~80 LOC) defined alongside the existing_strip_leaked_bracketed_paste_wrappers, called once during app setup right before_original_on_resize = app._on_resize.tests/cli/test_bracketed_paste_timeout.py— 8 regression tests covering normal paste, timeout recovery, torn end marks, buffered-content preservation, normal-keys-after-recovery, no-timeout-on-quick-end-mark, subsequent-data-after-incomplete, no-timeout-under-threshold.scripts/release.py—AUTHOR_MAPentry mapping66773372+Tranquil-Flow@users.noreply.github.comto@Tranquil-Flowfor the attribution check.Validation
logger.warning("Bracketed-paste timeout (...)" + #16263)Targeted tests:
tests/cli/test_bracketed_paste_timeout.py— 8/8 passing.Salvage notes
Surgical reapply of PR #27518 by @Tranquil-Flow (commit
098643c5e,Evi Nova <66773372+Tranquil-Flow@users.noreply.github.com>). The original branch was many months stale against currentmainand a direct cherry-pick would have reverted 1,193 unrelated files (−172,209 LOC), including the entire kanban tutorial, docker s6 infrastructure, dozens of skill files, and hundreds of test files. The substantive ~80 LOC patch function incli.py(with a_apply_bracketed_paste_timeout_patch()call at app setup) plus the new 157-line regression test file were reapplied by hand onto currentmainwith the contributor's authorship preserved viagit commit --author=.Original PR #27518 will be closed pointing to this one. Issue #16263 will auto-close from the merge commit footer.
Infographic
https://v3b.fal.media/files/b/0a9b9df7/VSCZbTjTxtN78Bft8Or6A_TRm7Jxv5.png