Skip to content

fix(web): prevent duplicate terminal paste - #8457

Closed
Adamulek123 wants to merge 2 commits into
pingdotgg:mainfrom
Adamulek123:fix/terminal-paste-race
Closed

Adamulek123 wants to merge 2 commits into
pingdotgg:mainfrom
Adamulek123:fix/terminal-paste-race

Conversation

@Adamulek123

@Adamulek123 Adamulek123 commented Aug 27, 2026 •

Copy link
Copy Markdown
Contributor

What Changed

Centralized terminal paste delivery so every non-empty paste invalidates older clipboard reads before writing to the PTY. Added focused coverage for keyboard/context-menu races, native/shortcut races, and empty paste data.

Why

Terminal paste can arrive through an async clipboard read or a native paste event. Keeping token invalidation in one method prevents both paths from delivering the same clipboard content.

Validation

  • vp test run apps/web/src/terminal/ghostty/surface.test.ts (46 passed)
  • Targeted lint for surface.ts and surface.test.ts
  • vp run --filter @t3tools/web typecheck

Checklist

  • This PR is small and focused
  • I explained what changed and why

Implemented with GPT-5.6 Codex in T3 Code.


Note

Low Risk
Focused change to web terminal input handling with new regression tests; no auth, data persistence, or broader API surface changes.

Overview
Centralizes Ghostty terminal paste delivery in a new paste() method so native events, keyboard shortcut clipboard reads, and host pasteFromClipboard all share one path to bracketed-paste encode and send data to the PTY.

When a non-empty paste wins, paste() bumps pasteShortcutToken, which invalidates slower async reads that still hold an older token—so context-menu vs keyboard and shortcut vs native races no longer double-send the same clipboard text. Empty paste() calls are no-ops and do not bump the token, so an empty native paste still lets a pending shortcut read complete.

Adds unit tests for those race scenarios using a lightweight surface stub.

Reviewed by Cursor Bugbot for commit 7e5f267. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Fix duplicate terminal paste by consolidating delivery in GhosttyTerminalSurface.paste

  • Adds a single paste(data) method to GhosttyTerminalSurface that handles token bumping, encoding, and delivery via options.onData; early-returns on disposed surfaces or empty strings.
  • Routes all three paste paths — onKeyDown clipboard read, onPaste event handler, and pasteFromClipboard — through this.paste() instead of duplicating the token/dispatch logic inline.
  • Adds unit tests in surface.test.ts covering paste race scenarios (keyboard vs context-menu, native vs shortcut) and empty-paste-while-pending behavior.
  • Behavioral Change: pasteFromClipboard now calls onData for non-empty clipboard text even when core.encodePaste returns an empty string; empty input remains a no-op.

Macroscope summarized 7e5f267.

@coderabbitai

coderabbitai Bot commented Aug 27, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3287ae89-610f-4bb7-b256-ee933dc79cdd

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels Aug 27, 2026
@macroscopeapp

macroscopeapp Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at 7e5f267

Macroscope's review found this PR approvable — This is a small, localized terminal bug fix that consolidates existing paste paths to prevent duplicate PTY input during clipboard races. Focused regression tests cover the affected scenarios, with no schema, security, persistence, or deployment changes.

You can add or adjust custom eligibility rules. Learn more.

@t3dotgg

t3dotgg commented Sep 1, 2026

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

Closing this because current main already prevents the duplicate-paste orderings covered here. pasteFromClipboard, the keyboard shortcut path, and the native paste handler already claim or invalidate pasteShortcutToken, while an empty native paste leaves the pending read current.

This patch now centralizes existing behavior, and its tests call the proposed helper instead of the current event paths. It also does not cover the remaining inverse ordering where the async clipboard read delivers before a later native paste event. There is no behavior left in this PR that should land.

@t3dotgg t3dotgg closed this Sep 1, 2026
@Adamulek123
Adamulek123 deleted the fix/terminal-paste-race branch September 1, 2026 11:22
@Ar-Kareem

Copy link
Copy Markdown

Not sure why but I'm struggling with CMD+V double pasting everywhere whether inside or outside tmux.

It might be because safari again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S 10-29 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants