hostAdapter.ts 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. import type {
  2. ComputerUseHostAdapter,
  3. Logger,
  4. } from '@ant/computer-use-mcp/types'
  5. import { format } from 'util'
  6. import { logForDebugging } from '../debug.js'
  7. import { COMPUTER_USE_MCP_SERVER_NAME } from './common.js'
  8. import { createCliExecutor } from './executor.js'
  9. import { getChicagoEnabled, getChicagoSubGates } from './gates.js'
  10. import { requireComputerUseSwift } from './swiftLoader.js'
  11. class DebugLogger implements Logger {
  12. silly(message: string, ...args: unknown[]): void {
  13. logForDebugging(format(message, ...args), { level: 'debug' })
  14. }
  15. debug(message: string, ...args: unknown[]): void {
  16. logForDebugging(format(message, ...args), { level: 'debug' })
  17. }
  18. info(message: string, ...args: unknown[]): void {
  19. logForDebugging(format(message, ...args), { level: 'info' })
  20. }
  21. warn(message: string, ...args: unknown[]): void {
  22. logForDebugging(format(message, ...args), { level: 'warn' })
  23. }
  24. error(message: string, ...args: unknown[]): void {
  25. logForDebugging(format(message, ...args), { level: 'error' })
  26. }
  27. }
  28. let cached: ComputerUseHostAdapter | undefined
  29. /**
  30. * Process-lifetime singleton. Built once on first CU tool call; native modules
  31. * (both `@ant/computer-use-input` and `@ant/computer-use-swift`) are loaded
  32. * here via the executor factory, which throws on load failure — there is no
  33. * degraded mode.
  34. */
  35. export function getComputerUseHostAdapter(): ComputerUseHostAdapter {
  36. if (cached) return cached
  37. cached = {
  38. serverName: COMPUTER_USE_MCP_SERVER_NAME,
  39. logger: new DebugLogger(),
  40. executor: createCliExecutor({
  41. getMouseAnimationEnabled: () => getChicagoSubGates().mouseAnimation,
  42. getHideBeforeActionEnabled: () => getChicagoSubGates().hideBeforeAction,
  43. }),
  44. ensureOsPermissions: async () => {
  45. const cu = requireComputerUseSwift()
  46. const accessibility = (cu as any).tcc.checkAccessibility()
  47. const screenRecording = (cu as any).tcc.checkScreenRecording()
  48. return accessibility && screenRecording
  49. ? { granted: true }
  50. : { granted: false, accessibility, screenRecording }
  51. },
  52. isDisabled: () => !getChicagoEnabled(),
  53. getSubGates: getChicagoSubGates,
  54. // cleanup.ts always unhides at turn end — no user preference to disable it.
  55. getAutoUnhideEnabled: () => true,
  56. // Pixel-validation JPEG decode+crop. MUST be synchronous (the package
  57. // does `patch1.equals(patch2)` directly on the return value). Cowork uses
  58. // Electron's `nativeImage` (sync); our `image-processor-napi` is
  59. // sharp-compatible and async-only. Returning null → validation skipped,
  60. // click proceeds — the designed fallback per `PixelCompareResult.skipped`.
  61. // The sub-gate defaults to false anyway.
  62. cropRawPatch: () => null,
  63. }
  64. return cached
  65. }