Skip to content

Navigation Menu

Sign in
Sign up

Improve e2e auto paste performance - #30

Merged
sumerc merged 4 commits into
main from
improve-e2e-auto-paste
Aug 6, 2026
Merged

Improve e2e auto paste performance #30
sumerc merged 4 commits into
main from
improve-e2e-auto-paste

Conversation

@sumerc

@sumerc sumerc commented Aug 6, 2026

Copy link
Copy Markdown
Owner

No description provided.

@sumerc sumerc self-assigned this Aug 6, 2026
@sumerc sumerc changed the title (削除) Improve e2e auto paste (削除ここまで) (追記) Improve e2e auto paste performance (追記ここまで) Aug 6, 2026

Copy link
Copy Markdown

📋 PR Summary

Replaces the macOS clipboard backend: Copy/Read now use NSPasteboard and Paste synthesizes Cmd+V via CGEvent directly (dropping the pbcopy/pbpaste fork, the LC_CTYPE locale hack, and the keybd_event dependency + its 100 ms key-hold sleep); Linux keeps the atotto backend. The feedback beep's -play is now dispatched to a serial queue so it no longer blocks the push-to-talk path. Adds a per-stage LatencyBreakdown to the felt_latency log line (tail wait, mic stop, PCM convert, inference, clipboard save/wait, paste copy/keystroke) and records the design rationale in docs/design-notes.md.

Changes
Layer / File(s) Summary
Native clipboard backend
clipboard/clipboard.go Public Read/Copy now delegate to platform read()/write() hooks instead of calling atotto directly.
clipboard/clipboard_darwin.go Drops keybd_event and the LC_CTYPE locale hack; write/read/Paste now call the new cgo C funcs; Init becomes a no-op.
clipboard/clipboard_darwin.m New Objective-C: clipCopy/clipRead via NSPasteboard and clipPaste via CGEvent Cmd+V.
clipboard/clipboard_darwin_test.go New round-trip and benchmark test through the real pasteboard, including multibyte characters.
clipboard/clipboard_linux.go Adds read/write shims over atotto for the Linux backend.
go.mod Removes the micmonay/keybd_event dependency.
go.sum Removes keybd_event checksums.
Non-blocking beep
audio/beep_darwin.m Dispatches AVAudioPlayer -play to a serial queue so it no longer blocks the caller; updates header comment.
Latency instrumentation
log/log.go Adds LatencyBreakdown struct and extends ReleaseToText to log per-stage timings plus an unaccounted remainder.
main.go Adds clipSave (prev + saveMs) and micStopMs plumbing; finishTranscription fills the LatencyBreakdown from clip/paste/convert timings.
recording.go Measures capture Stop()+ClearCallback duration into micStopMs.
clipboard_session.go PasteText now returns copyMs/keyMs timings for the breakdown.
transcriber/local_session.go Times the PCM→f32/WAV conversion and reports it as BatchStats.ConvertMs.
transcriber/session.go Adds ConvertMs field to BatchStats.
Docs & conventions
CLAUDE.md Rewrites the CHANGELOG rule to 'do not touch it' and adds a 'no performance numbers in code comments' rule.
docs/design-notes.md Adds notes on the Core ML/ANE mechanism, Voxtral local-engine research, and the paste/beep latency findings behind this PR.

@upsun-dispatch-dev upsun-dispatch-dev Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

Changes suggested — 🟡 1 warning · 1 minor point

🔍 Full review · 16 files reviewed

🔵 Minor points

Not blocking, and no threads opened for these.

  • log/log.go:245 — The LatencyBreakdown field comments name a mechanism this PR removes: ClipSaveMs is documented as "pbpaste fork", PasteCopyMs (line 247) as "pbcopy fork", and the struct doc (line 236) as "the pbpaste fork's own duration". After this change macOS SaveCurrent/Copy go through NSPasteboard (no fork), and the Linux backend forks xclip/xsel — not pbpaste/pbcopy — so the comments describe a fork that runs on no platform. The added clipSave doc in main.go ("how long the pbpaste fork took") is stale for the same reason. Reword to name the clipboard save/copy stage generically.
Review details
  • Commit: 54425b3
  • Model: claude-opus-4-8
  • Panel: security · correctness · robustness · design

// without it macOS drops the events silently.
void clipPaste(void) {
const CGKeyCode kVK_V = 0x09;
CGEventRef down = CGEventCreateKeyboardEvent(NULL, kVK_V, true);

@upsun-dispatch-dev upsun-dispatch-dev Bot Aug 6, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Warning — A NULL event-create result crashes the app instead of dropping the paste.

clipPaste never checks the results of CGEventCreateKeyboardEvent. When the function returns NULL (event source cannot be created under resource pressure or certain TCC/sandbox states), CGEventSetFlags(down, ...) is undefined and CFRelease(down)/CFRelease(up) on a NULL ref is a documented crash — so a failed event creation terminates the app on the paste path instead of a silently-dropped keystroke. Guard each ref (return early / skip CFRelease when NULL) as the replaced keybd_event path did internally.

sumerc merged commit 33268fa into main Aug 6, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@upsun-dispatch-dev upsun-dispatch-dev[bot] upsun-dispatch-dev[bot] left review comments

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

1 participant

AltStyle によって変換されたページ (->オリジナル) /