e3264a1691
Phase 1: Replace @ant/computer-use-mcp stub (12 files, 6517 lines). Phase 2: Remove 8 macOS-only guards in src/: - main.tsx: remove getPlatform()==='macos' check - swiftLoader.ts: remove darwin-only throw - executor.ts: extend platform guard, clipboard dispatch, paste key - drainRunLoop.ts: skip CFRunLoop pump on non-darwin - escHotkey.ts: non-darwin returns false (Ctrl+C fallback) - hostAdapter.ts: non-darwin permissions granted - common.ts: dynamic platform + screenshotFiltering - gates.ts: enabled:true, subscription check removed Phase 3: Add Linux backends (xdotool/scrot/xrandr/wmctrl): - computer-use-input/backends/linux.ts (173 lines) - computer-use-swift/backends/linux.ts (278 lines) Verified on Windows x64: mouse, screenshot, displays, foreground app. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
56 lines
2.0 KiB
TypeScript
56 lines
2.0 KiB
TypeScript
import { logForDebugging } from '../debug.js'
|
|
import { releasePump, retainPump } from './drainRunLoop.js'
|
|
import { requireComputerUseSwift } from './swiftLoader.js'
|
|
|
|
/**
|
|
* Global Escape → abort. Mirrors Cowork's `escAbort.ts` but without Electron:
|
|
* CGEventTap via `@ant/computer-use-swift`. While registered, Escape is
|
|
* consumed system-wide (PI defense — a prompt-injected action can't dismiss
|
|
* a dialog with Escape).
|
|
*
|
|
* Lifecycle: register on fresh lock acquire (`wrapper.tsx` `acquireCuLock`),
|
|
* unregister on lock release (`cleanup.ts`). The tap's CFRunLoopSource sits
|
|
* in .defaultMode on CFRunLoopGetMain(), so we hold a drainRunLoop pump
|
|
* retain for the registration's lifetime — same refcounted setInterval as
|
|
* the `@MainActor` methods.
|
|
*
|
|
* `notifyExpectedEscape()` punches a hole for model-synthesized Escapes: the
|
|
* executor's `key("escape")` calls it before posting the CGEvent. Swift
|
|
* schedules a 100ms decay so a CGEvent that never reaches the tap callback
|
|
* doesn't eat the next user ESC.
|
|
*/
|
|
|
|
let registered = false
|
|
|
|
export function registerEscHotkey(onEscape: () => void): boolean {
|
|
if (process.platform !== 'darwin') return false
|
|
if (registered) return true
|
|
const cu = requireComputerUseSwift()
|
|
if (!(cu as any).hotkey.registerEscape(onEscape)) {
|
|
// CGEvent.tapCreate failed — typically missing Accessibility permission.
|
|
// CU still works, just without ESC abort. Mirrors Cowork's escAbort.ts:81.
|
|
logForDebugging('[cu-esc] registerEscape returned false', { level: 'warn' })
|
|
return false
|
|
}
|
|
retainPump()
|
|
registered = true
|
|
logForDebugging('[cu-esc] registered')
|
|
return true
|
|
}
|
|
|
|
export function unregisterEscHotkey(): void {
|
|
if (!registered) return
|
|
try {
|
|
(requireComputerUseSwift() as any).hotkey.unregister()
|
|
} finally {
|
|
releasePump()
|
|
registered = false
|
|
logForDebugging('[cu-esc] unregistered')
|
|
}
|
|
}
|
|
|
|
export function notifyExpectedEscape(): void {
|
|
if (!registered) return
|
|
(requireComputerUseSwift() as any).hotkey.notifyExpectedEscape()
|
|
}
|