Skip to content

Latest commit

 

History

History
315 lines (246 loc) · 12.8 KB

File metadata and controls

315 lines (246 loc) · 12.8 KB

Computer Use Windows 增强实施计划

更新时间:2026-04-03 依赖文档:docs/features/windows-ai-desktop-control.mddocs/features/computer-use.md

1. 目标

在已有的 PowerShell 子进程方案基础上,利用 Windows 原生 API 增强 Computer Use 的 Windows 实现,解决 3 个核心问题:

  1. 窗口绑定截图:当前 CopyFromScreen 只能全屏截图,无法对指定窗口截图(尤其是被遮挡/最小化窗口)
  2. UI 结构感知:当前只能通过坐标点击,无法像 macOS Accessibility 那样理解 UI 元素树
  3. 性能:每次 PowerShell 启动约 273ms,剪贴板/窗口枚举等高频操作需要更快的方式

2. 已验证的 Windows API 能力

以下 API 全部通过 PowerShell P/Invoke 实测通过:

能力 API 验证结果
窗口绑定截图 PrintWindow(hwnd, hdc, PW_RENDERFULLCONTENT) ✅ VS Code 342KB, Chrome 273KB
枚举窗口+HWND EnumWindows + GetWindowText + GetWindowThreadProcessId ✅ 38 个窗口,含 HWND/PID/标题
UI 元素树 System.Windows.Automation.AutomationElement ✅ 记事本 39 个元素
UI 写值 ValuePattern.SetValue() ✅ 成功写入记事本文本
UI 点击 InvokePattern.Invoke() ✅ 按钮可程序化点击
坐标元素识别 AutomationElement.FromPoint(x, y) ✅ 返回元素类型+名称
OCR Windows.Media.Ocr.OcrEngine ✅ 英语+中文引擎可用
全局热键 RegisterHotKey ✅ API 可调
剪贴板直接操作 System.Windows.Forms.Clipboard ✅ 读/写/图片检测
Shell 启动 ShellExecute ✅ 打开文件/URL/应用

3. 架构设计

3.1 文件结构

在现有 backends/win32.ts 基础上新增 Windows 专属模块:

packages/@ant/computer-use-input/src/
├── backends/
│   ├── darwin.ts          ← 不动
│   ├── win32.ts           ← 增强:直接 Win32 API 替代部分 PowerShell
│   └── linux.ts           ← 不动

packages/@ant/computer-use-swift/src/
├── backends/
│   ├── darwin.ts          ← 不动
│   ├── win32.ts           ← 增强:PrintWindow 窗口截图 + EnumWindows
│   └── linux.ts           ← 不动

packages/@ant/computer-use-mcp/src/
│   └── tools.ts           ← 增加 Windows 专属工具定义(UI Automation、OCR)

src/utils/computerUse/
│   └── win32/              ← 新增目录:Windows 专属能力
│       ├── uiAutomation.ts  ← UI 元素树、点击、写值
│       ├── ocr.ts           ← 截图 + OCR 文字识别
│       ├── windowCapture.ts ← PrintWindow 窗口绑定截图
│       └── windowEnum.ts    ← EnumWindows 窗口枚举

3.2 分层

┌──────────────────────────────────────────────┐
│           Computer Use MCP Tools             │
│  screenshot / click / type / request_access  │
│  + Windows 专属: ui_tree / ocr / window_cap  │
├──────────────────────────────────────────────┤
│           src/utils/computerUse/             │
│  executor.ts → 按平台 dispatch               │
│  win32/ → Windows 专属能力模块               │
├──────────────────────────────────────────────┤
│     packages/@ant/computer-use-{input,swift}  │
│  backends/win32.ts → PowerShell + Win32 API  │
├──────────────────────────────────────────────┤
│           Windows Native API                 │
│  PrintWindow / EnumWindows / UI Automation   │
│  SendInput / Clipboard / OCR / ShellExecute  │
└──────────────────────────────────────────────┘

4. 实施计划

Phase A:窗口绑定截图(解决核心问题)

问题:当前 CopyFromScreen 只能全屏截图,无法对指定窗口截图。 方案:用 PrintWindow + FindWindow 实现窗口级截图。

步骤 文件 改动
A.1 src/utils/computerUse/win32/windowCapture.ts 新建:captureWindow(title) 用 PrintWindow 截取指定窗口
A.2 src/utils/computerUse/win32/windowEnum.ts 新建:listWindows() 用 EnumWindows 返回 {hwnd, pid, title}[]
A.3 packages/@ant/computer-use-swift/src/backends/win32.ts screenshot.captureExcluding 增加按窗口截图能力
A.4 packages/@ant/computer-use-swift/src/backends/win32.ts apps.listRunning 用 EnumWindows 替代 Get-Process(返回 HWND)

PowerShell 脚本核心

# PrintWindow 截取指定窗口
Add-Type -AssemblyName System.Drawing
Add-Type -ReferencedAssemblies System.Drawing @'
using System; using System.Runtime.InteropServices; using System.Drawing; using System.Drawing.Imaging;
public class WinCap {
    [DllImport("user32.dll", CharSet=CharSet.Unicode)]
    public static extern IntPtr FindWindow(string c, string t);
    [DllImport("user32.dll")]
    public static extern bool GetWindowRect(IntPtr h, out RECT r);
    [DllImport("user32.dll")]
    public static extern bool PrintWindow(IntPtr h, IntPtr hdc, uint f);
    [StructLayout(LayoutKind.Sequential)]
    public struct RECT { public int L, T, R, B; }
    // ... CaptureByTitle(string title) → base64
}
'@

验证标准

  • 能按窗口标题截图
  • 被遮挡的窗口也能截图
  • 返回 base64 + width + height

Phase B:UI Automation(Windows 专属新能力)

问题:macOS 有 Accessibility API 可以读取/操作 UI 元素,Windows 当前只能坐标点击。 方案:用 System.Windows.Automation 实现 UI 树读取和元素操作。

步骤 文件 改动
B.1 src/utils/computerUse/win32/uiAutomation.ts 新建:核心 UIA 操作封装
B.2 packages/@ant/computer-use-mcp/src/tools.ts 增加 Windows 专属工具定义

uiAutomation.ts 导出函数

// 获取窗口的 UI 元素树
getUITree(windowTitle: string, depth: number): UIElement[]

// 按名称/类型/AutomationId 查找元素
findElement(windowTitle: string, query: {name?, controlType?, automationId?}): UIElement | null

// 点击元素(InvokePattern)
clickElement(windowTitle: string, automationId: string): boolean

// 设置元素值(ValuePattern)
setValue(windowTitle: string, automationId: string, value: string): boolean

// 获取坐标处的元素
elementAtPoint(x: number, y: number): UIElement | null

UIElement 类型

interface UIElement {
  name: string
  controlType: string    // Button, Edit, Text, List, etc.
  automationId: string
  boundingRect: { x: number, y: number, w: number, h: number }
  isEnabled: boolean
  value?: string         // ValuePattern 可用时
  children?: UIElement[]
}

PowerShell 脚本核心

Add-Type -AssemblyName UIAutomationClient
Add-Type -AssemblyName UIAutomationTypes

# 读取 UI 树
$root = [AutomationElement]::RootElement
$window = $root.FindFirst([TreeScope]::Children, 
  [PropertyCondition]::new([AutomationElement]::NameProperty, $title))
$elements = $window.FindAll([TreeScope]::Descendants, [Condition]::TrueCondition)

# 写入文本
$element.GetCurrentPattern([ValuePattern]::Pattern).SetValue($text)

# 点击按钮
$element.GetCurrentPattern([InvokePattern]::Pattern).Invoke()

验证标准

  • 能读取记事本的 UI 树(按钮、文本框、菜单)
  • 能向文本框写入内容
  • 能点击按钮
  • 能识别坐标处的元素

Phase C:OCR 屏幕文字识别

问题:截图后 AI 只能看到图片,无法直接读取文字。 方案:用 Windows.Media.Ocr 对截图进行文字识别。

步骤 文件 改动
C.1 src/utils/computerUse/win32/ocr.ts 新建:截图 + OCR 识别
C.2 packages/@ant/computer-use-mcp/src/tools.ts 增加 screen_ocr 工具定义

ocr.ts 导出函数

// 对屏幕区域 OCR
ocrRegion(x: number, y: number, w: number, h: number, lang?: string): OcrResult

// 对指定窗口 OCR
ocrWindow(windowTitle: string, lang?: string): OcrResult

interface OcrResult {
  text: string
  lines: { text: string, bounds: {x,y,w,h} }[]
  language: string
}

已确认可用语言:英语 (en-US) + 中文 (zh-Hans-CN)

验证标准

  • 能识别屏幕区域中的英文和中文
  • 返回文字内容 + 每行的位置信息

Phase D:高频操作性能优化

问题:每次 PowerShell 启动 273ms,鼠标移动等高频操作太慢。 方案:用 .NET System.Windows.Forms.Clipboard 等直接 API 替代 PowerShell 子进程。

步骤 文件 改动
D.1 src/utils/computerUse/executor.ts 剪贴板操作用直接 API 替代 PowerShell
D.2 考虑驻留 PowerShell 进程 通过 stdin/stdout 交互,摊平启动成本

剪贴板直接 API(不需要 PowerShell 子进程):

# 读:50ms → <1ms
[System.Windows.Forms.Clipboard]::GetText()

# 写:50ms → <1ms  
[System.Windows.Forms.Clipboard]::SetText($text)

# 图片检测
[System.Windows.Forms.Clipboard]::ContainsImage()

Phase E:request_access Windows 适配

问题request_access 依赖 macOS bundleId 识别应用,Windows 没有这个概念。 方案:在 Windows 上用 exe 路径 + 窗口标题替代 bundleId。

步骤 文件 改动
E.1 packages/@ant/computer-use-mcp/src/toolCalls.ts resolveRequestedApps 在 Windows 上用 exe 路径匹配
E.2 packages/@ant/computer-use-mcp/src/sentinelApps.ts 增加 Windows 危险应用列表(cmd.exe, powershell.exe 等)
E.3 packages/@ant/computer-use-mcp/src/deniedApps.ts 增加 Windows 浏览器/终端识别规则
E.4 src/utils/computerUse/hostAdapter.ts ensureOsPermissions Windows 上检查 UAC 状态

Windows 应用标识映射

macOS bundleId          →  Windows 等价
com.apple.Safari        →  C:\Program Files\...\msedge.exe(或窗口标题匹配)
com.google.Chrome       →  chrome.exe
com.apple.Terminal      →  WindowsTerminal.exe / cmd.exe

Phase F:全局热键(ESC 拦截)

问题:当前非 darwin 直接跳过 ESC 热键,用 Ctrl+C 替代。 方案:用 RegisterHotKeySetWindowsHookEx(WH_KEYBOARD_LL) 实现。

步骤 文件 改动
F.1 src/utils/computerUse/escHotkey.ts Windows 分支:RegisterHotKey 注册 ESC

优先级低——当前 Ctrl+C fallback 可用,ESC 热键是体验优化。

5. 执行优先级

Phase A: 窗口绑定截图          ← P0 核心需求,解决"操作其他界面"
Phase B: UI Automation         ← P0 核心能力,AI 理解 UI 结构
Phase C: OCR                   ← P1 增值能力,AI 读屏幕文字
Phase D: 性能优化              ← P1 体验优化,高频操作提速
Phase E: request_access 适配   ← P1 功能完整性,权限模型适配
Phase F: ESC 热键              ← P2 体验优化,可后做

6. 每个 Phase 的改动量估算

Phase 新增文件 修改文件 新增代码行 风险
A 窗口截图 2 1 ~200
B UI Automation 1 1 ~300
C OCR 1 1 ~150
D 性能优化 0 2 ~50
E request_access 0 3 ~100
F ESC 热键 0 1 ~50
总计 4 9 ~850

7. 不动的文件

  • backends/darwin.ts(两个包都不动)
  • backends/linux.ts(两个包都不动)
  • src/utils/computerUse/ 中 macOS 相关代码路径不动
  • packages/@ant/computer-use-mcp/src/ 中已复制的参考项目代码不动(只追加 Windows 工具)

8. 与 macOS/Linux 方案的对比

能力 macOS Windows (增强后) Linux
截图方式 SCContentFilter (per-app) PrintWindow (per-window) scrot (全屏/区域)
UI 结构 Accessibility API UI Automation
OCR 无内置 Windows.Media.Ocr 无内置
键鼠 CGEvent + enigo SendInput + keybd_event xdotool
窗口管理 NSWorkspace EnumWindows + Win32 wmctrl
剪贴板 pbcopy/pbpaste Clipboard 直接 API xclip
ESC 热键 CGEventTap RegisterHotKey
应用标识 bundleId exe 路径 + 窗口标题 /proc + wmctrl

Windows 增强后将在 UI Automation 和 OCR 方面超过 macOS 方案——这两项 macOS 原始实现也没有(Anthropic 用的是截图 + Claude 视觉理解,没有结构化 UI 数据)。