source dump of claude code
at main 54 lines 2.0 kB view raw
1import { logForDebugging } from '../debug.js' 2import { releasePump, retainPump } from './drainRunLoop.js' 3import { requireComputerUseSwift } from './swiftLoader.js' 4 5/** 6 * Global Escape → abort. Mirrors Cowork's `escAbort.ts` but without Electron: 7 * CGEventTap via `@ant/computer-use-swift`. While registered, Escape is 8 * consumed system-wide (PI defense — a prompt-injected action can't dismiss 9 * a dialog with Escape). 10 * 11 * Lifecycle: register on fresh lock acquire (`wrapper.tsx` `acquireCuLock`), 12 * unregister on lock release (`cleanup.ts`). The tap's CFRunLoopSource sits 13 * in .defaultMode on CFRunLoopGetMain(), so we hold a drainRunLoop pump 14 * retain for the registration's lifetime — same refcounted setInterval as 15 * the `@MainActor` methods. 16 * 17 * `notifyExpectedEscape()` punches a hole for model-synthesized Escapes: the 18 * executor's `key("escape")` calls it before posting the CGEvent. Swift 19 * schedules a 100ms decay so a CGEvent that never reaches the tap callback 20 * doesn't eat the next user ESC. 21 */ 22 23let registered = false 24 25export function registerEscHotkey(onEscape: () => void): boolean { 26 if (registered) return true 27 const cu = requireComputerUseSwift() 28 if (!cu.hotkey.registerEscape(onEscape)) { 29 // CGEvent.tapCreate failed — typically missing Accessibility permission. 30 // CU still works, just without ESC abort. Mirrors Cowork's escAbort.ts:81. 31 logForDebugging('[cu-esc] registerEscape returned false', { level: 'warn' }) 32 return false 33 } 34 retainPump() 35 registered = true 36 logForDebugging('[cu-esc] registered') 37 return true 38} 39 40export function unregisterEscHotkey(): void { 41 if (!registered) return 42 try { 43 requireComputerUseSwift().hotkey.unregister() 44 } finally { 45 releasePump() 46 registered = false 47 logForDebugging('[cu-esc] unregistered') 48 } 49} 50 51export function notifyExpectedEscape(): void { 52 if (!registered) return 53 requireComputerUseSwift().hotkey.notifyExpectedEscape() 54}