Skip to content

fix(prompt): scale bracketed-paste delay by line count to prevent stuck initial prompts#107

Merged
johannesjo merged 2 commits into
johannesjo:mainfrom
brooksc:fix/bracketed-paste-delay-large-prompts
May 15, 2026
Merged

fix(prompt): scale bracketed-paste delay by line count to prevent stuck initial prompts#107
johannesjo merged 2 commits into
johannesjo:mainfrom
brooksc:fix/bracketed-paste-delay-large-prompts

Conversation

@brooksc
Copy link
Copy Markdown
Contributor

@brooksc brooksc commented May 11, 2026

Summary

  • Track bracketed paste mode (CSI ?2004h/l) per agent in AgentTrackingState via updateBracketedPasteMode(), called on each PTY data chunk
  • Export isAgentBracketedPasteEnabled() so sendPrompt can conditionally wrap text in \x1b[200~...\x1b[201~ (matches what Codex expects to avoid its paste-burst guard)
  • Replace the fixed 50ms pre-Enter delay with pasteDelayMs(text): max(50ms, lines × 15ms) capped at 500ms

Problem

When an agent enables bracketed paste mode, synthetic prompt sends wrap the text in \x1b[200~...\x1b[201~. TUI agents like Claude Code process this paste asynchronously — if \r arrives while the paste is still being consumed (within the fixed 50ms window), it is absorbed into the input buffer as a newline rather than submitting the prompt.

The symptom: the agent sits in -- INSERT -- mode showing [Pasted text #1 +N lines], waiting indefinitely for Enter. Reproduces reliably with initial task prompts of 30+ lines.

Test plan

  • Create a task with a multi-line initial prompt (30+ lines) targeting a Claude Code agent — prompt should auto-send and not get stuck in INSERT mode
  • Create a task with a short (1-line) initial prompt — still sends within ~50ms, no noticeable lag
  • Create a Codex task — bracketed paste still wraps correctly, no paste-burst guard regression
  • Manual sends from the PromptInput textarea still work for all agent types

🤖 Generated with Claude Code

@brooksc
Copy link
Copy Markdown
Contributor Author

brooksc commented May 11, 2026

Root cause analysis

When introduced: Commit 1226f27 ("Fix Codex prompt auto-send") added bracketed paste wrapping to sendPrompt to prevent Codex's paste-burst guard from misfiring on rapid synthetic keystrokes. The fix wraps the prompt text in \x1b[200~...\x1b[201~ and sends \r 50ms later.

The problem: Claude Code processes bracketed paste asynchronously. The CSI ?2004h escape sequence tells the terminal "I support bracketed paste," and when a paste arrives, Claude Code reads the \x1b[200~, buffers the content, then processes it into its input on \x1b[201~. For short prompts this finishes in well under 50ms. For large prompts (a 31-line initial task prompt is a typical coordinator sub-task prompt), the buffering takes longer — \r arrives while Claude Code is still consuming the paste, so it lands inside the input buffer as a literal newline rather than as a submit key.

Result: the agent sits in -- INSERT -- mode with [Pasted text #1 +N lines] in its input field, waiting forever for an Enter key that already came and went.

The fix: Replace the fixed 50ms delay with pasteDelayMs(text) = min(500ms, max(50ms, lines × 15ms)). A 1-line prompt still fires in 50ms with no perceptible lag; a 31-line prompt waits ~465ms, which is enough for Claude Code to finish consuming the paste before \r arrives. The 500ms cap prevents noticeable slowdown on very long pastes.

The bracketed paste wrapping itself is preserved — Codex still needs it. Only the timing changes.

@johannesjo
Copy link
Copy Markdown
Owner

johannesjo commented May 11, 2026

Fresh code-review pass findings:

  1. Blocking: the branch is stale/unmergeable. GitHub reports mergeable=CONFLICTING; PR head 08426ee is based on b10447a and is missing current main commits including 1226f27, 4c52e11, d4d856e, and c4540f5. A direct compare against current main would also drop newer test/status/diff work such as src/store/tasks.test.ts and updated taskStatus behavior. Please rebase onto current main and resolve the conflicts while preserving the bracketed-paste tracking/tests already on main.

  2. Requested test: src/store/tasks.ts:69 adds pasteDelayMs() and src/store/tasks.ts:502 now uses it before sending Enter, but the PR does not add a regression test for the timing behavior. Please cover the core cases: a short prompt stays at 50ms, a ~31-line prompt scales to about 465ms, and a very large prompt caps at 500ms.

No additional actionable issues found in this fresh pass.

brooksc and others added 2 commits May 14, 2026 23:40
…ck initial prompts

When an agent enables bracketed paste mode (CSI ? 2004 h), synthetic prompt
sends wrap the text in \x1b[200~...\x1b[201~ to avoid Codex's paste-burst
guard. However, TUI agents like Claude Code process the paste asynchronously —
if \r arrives while the paste is still being consumed, it is absorbed into the
input buffer as a newline rather than submitting the prompt.

The previous fixed 50ms delay was sufficient for short prompts but too short
for large ones (e.g. a 31-line initial task prompt). The symptom is the agent
sitting in INSERT mode with "[Pasted text #1 +N lines]" in its input, never
sending.

Fix:
- Track bracketed paste mode (CSI ? 2004 h/l) in AgentTrackingState via
  updateBracketedPasteMode(), called on each PTY data chunk in markAgentOutput()
- Export isAgentBracketedPasteEnabled() so sendPrompt can conditionally wrap
- Scale the pre-Enter delay: max(50ms, lines * 15ms), capped at 500ms —
  a 31-line prompt now waits ~465ms instead of 50ms

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…cate constants

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@brooksc brooksc force-pushed the fix/bracketed-paste-delay-large-prompts branch from 08426ee to 4572e29 Compare May 15, 2026 06:43
@brooksc
Copy link
Copy Markdown
Contributor Author

brooksc commented May 15, 2026

Updates addressing review feedback

Rebased onto current main — resolved two conflicts:

  • taskStatus.ts: dropped the duplicate isAgentBracketedPasteEnabled export the PR introduced; the function already exists later in the file from a main commit
  • tasks.ts: kept the PR's pasteDelayMs(effectiveText) call over the fixed 50ms; also removed duplicate BRACKETED_PASTE_START/END constant declarations and a duplicate import that the rebase surfaced

Added pasteDelayMs regression tests (src/store/tasks.test.ts):

  • Exported pasteDelayMs so it can be unit-tested directly
  • Short (1-line) prompt → floors at 50ms
  • ~31-line prompt → scales to 465ms (31 × 15)
  • 100-line prompt → caps at 500ms

All 437 tests pass, typecheck and lint clean.

@johannesjo
Copy link
Copy Markdown
Owner

Thank you very much! <3

@johannesjo johannesjo merged commit cd79f2a into johannesjo:main May 15, 2026
2 checks passed
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.

2 participants