Fix Raycast paste fallback regression#2768
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughAdds structured image materialization outcomes and a plain-text fallback to paste planning; updates paste planner to act on those outcomes (file, reject, or fallback to text); refactors pasteboard helper and adds focused-terminal key-repair gating plus tests. Changes
Sequence DiagramsequenceDiagram
participant User as User
participant Planner as TerminalImageTransferPlanner
participant Helper as GhosttyPasteboardHelper
participant PB as NSPasteboard
participant Result as TerminalPasteTarget
User->>Planner: preparePaste(mode: .paste)
Planner->>Helper: materializeImageFileURLIfNeeded(from: PB)
Helper->>PB: read image payloads
PB-->>Helper: image bytes / no usable image
Helper-->>Planner: ImageFileMaterializationResult
alt saved(URL)
Planner->>Result: .fileURLs([URL])
else rejectedImagePayload
Planner->>Result: .reject
else noDecodableImagePayload
Planner->>Helper: fallbackPlainTextContents(from: PB)
Helper->>PB: read plain-text UTIs
PB-->>Helper: String?
alt plain-text found
Planner->>Result: .insertText(string)
else no text
Planner->>Result: continue URL handling / .reject
end
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Greptile SummaryThis PR fixes a regression where Raycast-style clipboard payloads — containing both unusable image data (e.g. invalid TIFF) and valid plain text — were silently rejected during paste instead of falling back to the text. The fix adds a Confidence Score: 5/5Safe to merge — minimal, targeted fix with correct fallback placement and a proper behavioral regression test. All findings are P2 or below. The fallback logic is sound: it only fires after image materialization genuinely fails, so real image pastes are unaffected. The test exercises the new code path through observable runtime behavior (pasteboard → plan), not implementation shape. No files require special attention. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[preparePaste called] --> B{fileURLs non-empty?}
B -- yes --> Z1[.fileURLs]
B -- no --> C{stringContents non-nil?}
C -- yes --> Z2[.insertText from rich/plain text]
C -- no\nhasImageData=true,\nno HTML/RTF/RTFD --> D{saveImageFileURLIfNeeded\nreturns URL?}
D -- yes\nreal image --> Z3[.fileURLs imageURL]
D -- no\ninvalid image data --> E{fallbackPlainTextContents\nnon-nil? NEW}
E -- yes\nRaycast plain text --> Z4[.insertText fallback text]
E -- no --> F{URL string on pasteboard?}
F -- yes --> Z5[.insertText escaped URL]
F -- no --> Z6[.reject]
Reviews (1): Last reviewed commit: "Fix Raycast paste fallback regression" | Re-trigger Greptile |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
cmuxTests/ShortcutAndCommandPaletteTests.swift (1)
63-91: Optional: add the remaining truth-table branch for future-proofing.Consider adding
flags: [.command], responderIsWindow: true, responderHasViableKeyRoutingOwner: trueto explicitly lock the “window responder always repairs” behavior.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@cmuxTests/ShortcutAndCommandPaletteTests.swift` around lines 63 - 91, Add the missing truth-table test case that covers flags: [.command], responderIsWindow: true, responderHasViableKeyRoutingOwner: true to explicitly assert the “window responder always repairs” behavior; create a new test (e.g., testRepairsCommandEquivalentWhenWindowResponderHasViableOwner) that calls shouldRepairFocusedTerminalCommandEquivalentInputs with those arguments and XCTAssertTrue the result so the four-way branch is fully covered alongside the existing tests (testRepairsCommandEquivalentWhenFirstResponderFallsBackToWindow, testRepairsCommandEquivalentWhenResponderHasNoViableOwner, testDoesNotRepairCommandEquivalentWhenResponderHasViableOwner).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@Sources/AppDelegate.swift`:
- Around line 1833-1843: The current
shouldRepairFocusedTerminalCommandEquivalentInputs implementation returns false
for Cmd-modified events whenever any viable in-window owner exists, which skips
the hosted view’s responderMatchesPreferredKeyboardFocus check and allows stale
responders to keep routing command equivalents; update the logic in
shouldRepairFocusedTerminalCommandEquivalentInputs (and the corresponding branch
in repairFocusedTerminalKeyboardRoutingIfNeeded(window:event:)) so that when
.command is present you query the focused terminal’s
hostedView.responderMatchesPreferredKeyboardFocus(currentFirstResponder,
window:) (or equivalent preferred keyboard target check) and only skip repair if
that check returns true—i.e., repair unless the hosted view reports the current
responder already matches the focused terminal’s preferred keyboard focus; apply
the same fix to the other occurrence around lines 5729-5744.
---
Nitpick comments:
In `@cmuxTests/ShortcutAndCommandPaletteTests.swift`:
- Around line 63-91: Add the missing truth-table test case that covers flags:
[.command], responderIsWindow: true, responderHasViableKeyRoutingOwner: true to
explicitly assert the “window responder always repairs” behavior; create a new
test (e.g., testRepairsCommandEquivalentWhenWindowResponderHasViableOwner) that
calls shouldRepairFocusedTerminalCommandEquivalentInputs with those arguments
and XCTAssertTrue the result so the four-way branch is fully covered alongside
the existing tests
(testRepairsCommandEquivalentWhenFirstResponderFallsBackToWindow,
testRepairsCommandEquivalentWhenResponderHasNoViableOwner,
testDoesNotRepairCommandEquivalentWhenResponderHasViableOwner).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 7edc9608-9ee4-4ee2-95d6-9909685f301e
📒 Files selected for processing (4)
Sources/AppDelegate.swiftSources/GhosttyTerminalView.swiftSources/TerminalImageTransfer.swiftcmuxTests/ShortcutAndCommandPaletteTests.swift
🚧 Files skipped from review as they are similar to previous changes (2)
- Sources/TerminalImageTransfer.swift
- Sources/GhosttyTerminalView.swift
There was a problem hiding this comment.
1 issue found across 2 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="cmuxTests/ShortcutAndCommandPaletteTests.swift">
<violation number="1" location="cmuxTests/ShortcutAndCommandPaletteTests.swift:83">
P2: This test now duplicates an existing viable-owner case instead of validating responder-drift behavior, so the regression suite no longer protects the drift-specific command-equivalent repair policy.
(Based on your team's feedback about focused-terminal responder-drift repair policy.) [FEEDBACK_USED]</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| ) | ||
| } | ||
|
|
||
| func testDoesNotRepairCommandEquivalentWhenLiveResponderDiffersFromSelectedPane() { |
There was a problem hiding this comment.
P2: This test now duplicates an existing viable-owner case instead of validating responder-drift behavior, so the regression suite no longer protects the drift-specific command-equivalent repair policy.
(Based on your team's feedback about focused-terminal responder-drift repair policy.)
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At cmuxTests/ShortcutAndCommandPaletteTests.swift, line 83:
<comment>This test now duplicates an existing viable-owner case instead of validating responder-drift behavior, so the regression suite no longer protects the drift-specific command-equivalent repair policy.
(Based on your team's feedback about focused-terminal responder-drift repair policy.) </comment>
<file context>
@@ -76,19 +75,17 @@ final class CommandEquivalentTransientFocusRepairTests: XCTestCase {
- func testRepairsCommandEquivalentWhenResponderDriftsWithinSameWindow() {
- XCTAssertTrue(
+ func testDoesNotRepairCommandEquivalentWhenLiveResponderDiffersFromSelectedPane() {
+ XCTAssertFalse(
shouldRepairFocusedTerminalCommandEquivalentInputs(
</file context>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is kicking off a free cloud agent to fix this issue. This run is complimentary, but you can enable autofix for all future PRs in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 9b25888. Configure here.
| responderHasViableKeyRoutingOwner: true | ||
| ) | ||
| ) | ||
| } |
There was a problem hiding this comment.
Duplicate test masks missing coverage for window+viable-owner case
Low Severity
testDoesNotRepairCommandEquivalentWhenLiveResponderDiffersFromSelectedPane and testDoesNotRepairCommandEquivalentWhenResponderHasViableOwner have identical bodies — same function, same arguments, same assertion. The first test name suggests it may have been intended to cover responderIsWindow: true, responderHasViableKeyRoutingOwner: true, which is the only input combination of shouldRepairFocusedTerminalCommandEquivalentInputs not covered by the test suite.
Reviewed by Cursor Bugbot for commit 9b25888. Configure here.


Summary
Closes #2762.
Testing
./scripts/reload.sh --tag issue-2762-raycast-paste-regression./scripts/reload.sh --tag issue-2762-raycast-paste-regression --launchNote
Medium Risk
Touches keyboard focus repair and pasteboard parsing logic, which can affect global shortcut handling and clipboard pastes across the app. Changes are scoped and backed by new targeted unit tests, but could still introduce edge-case regressions in input routing.
Overview
Fixes paste handling for Raycast-style mixed clipboard payloads by distinguishing no decodable image vs rejected/unusable image and falling back to alternate plain text only when appropriate.
Refines terminal focus “key repair” so Cmd-modified key equivalents only retarget focus when the responder state is genuinely broken (e.g.,
NSWindowis first responder), while keeping existing behavior for non-command key events.Adds regression tests covering the new command-equivalent repair decision and the mixed clipboard payload plain-text fallback.
Reviewed by Cursor Bugbot for commit 9b25888. Bugbot is set up for automated code reviews on this repo. Configure here.