Jelajahi Sumber

feat: 升级 @ant/computer-use-mcp — 类型安全 stub + sentinel apps

- types.ts: 替换所有 any 为真实类型 (CoordinateMode, CuSubGates,
  Logger, GrantFlags, CuPermissionRequest/Response, ComputerUseHostAdapter)
- index.ts: 所有导出类型化 (DisplayGeometry, FrontmostApp, InstalledApp,
  RunningApp, ScreenshotResult, CuCallToolResult 等);
  targetImageSize() 实现真实缩放逻辑;
  bindSessionContext() 返回类型正确的空调度器
- sentinelApps.ts: 添加 10 个 macOS 敏感应用 (Terminal, iTerm2,
  Finder, System Preferences 等) 及其分类

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
claude-code-best 3 minggu lalu
induk
melakukan
b51b2d7675

+ 2 - 2
TODO.md

@@ -10,8 +10,8 @@
 - [x] `color-diff-napi` — 颜色差异计算 NAPI 模块 (纯 TS 实现)
 - [x] `image-processor-napi` — 图像处理 NAPI 模块 (sharp + osascript 剪贴板)
 
-<!-- - [ ] `@ant/computer-use-swift` — Computer Use Swift 原生模块
-- [ ] `@ant/computer-use-mcp` — Computer Use MCP 服务 -->
+<!-- - [ ] `@ant/computer-use-swift` — Computer Use Swift 原生模块 -->
+- [x] `@ant/computer-use-mcp` — Computer Use MCP 服务 (类型安全 stub + sentinel apps + targetImageSize)
 - [x] `@ant/computer-use-input` — Computer Use 输入模块 (macOS AppleScript/JXA 实现)
 <!-- - [ ] `@ant/claude-for-chrome-mcp` — Chrome MCP 扩展 -->
 

+ 156 - 23
packages/@ant/computer-use-mcp/src/index.ts

@@ -1,30 +1,163 @@
-export const API_RESIZE_PARAMS: any = {}
-
-export class ComputerExecutor {}
-
-export type ComputerUseSessionContext = any
-export type CuCallToolResult = any
-export type CuPermissionRequest = any
-export type CuPermissionResponse = any
-export const DEFAULT_GRANT_FLAGS: any = {}
-export type DisplayGeometry = any
-export type FrontmostApp = any
-export type InstalledApp = any
-export type ResolvePrepareCaptureResult = any
-export type RunningApp = any
-export type ScreenshotDims = any
-export type ScreenshotResult = any
-
-export function bindSessionContext(..._args: any[]): any {
-  return null
+/**
+ * @ant/computer-use-mcp — Stub 实现
+ *
+ * 提供类型安全的 stub,所有函数返回合理的默认值。
+ * 在 feature('CHICAGO_MCP') = false 时不会被实际调用,
+ * 但确保 import 不报错且类型正确。
+ */
+
+import type {
+  ComputerUseHostAdapter,
+  CoordinateMode,
+  GrantFlags,
+  Logger,
+} from './types'
+
+// Re-export types from types.ts
+export type { CoordinateMode, Logger } from './types'
+export type {
+  ComputerUseConfig,
+  ComputerUseHostAdapter,
+  CuPermissionRequest,
+  CuPermissionResponse,
+  CuSubGates,
+} from './types'
+export { DEFAULT_GRANT_FLAGS } from './types'
+
+// ---------------------------------------------------------------------------
+// Types (defined here for callers that import from the main entry)
+// ---------------------------------------------------------------------------
+
+export interface DisplayGeometry {
+  width: number
+  height: number
+  displayId?: number
+  originX?: number
+  originY?: number
+}
+
+export interface FrontmostApp {
+  bundleId: string
+  displayName: string
+}
+
+export interface InstalledApp {
+  bundleId: string
+  displayName: string
+  path: string
 }
 
-export function buildComputerUseTools(..._args: any[]): any[] {
+export interface RunningApp {
+  bundleId: string
+  displayName: string
+}
+
+export interface ScreenshotResult {
+  base64: string
+  width: number
+  height: number
+}
+
+export type ResolvePrepareCaptureResult = ScreenshotResult
+
+export interface ScreenshotDims {
+  width: number
+  height: number
+  displayWidth: number
+  displayHeight: number
+  displayId: number
+  originX: number
+  originY: number
+}
+
+export interface CuCallToolResultContent {
+  type: 'image' | 'text'
+  data?: string
+  mimeType?: string
+  text?: string
+}
+
+export interface CuCallToolResult {
+  content: CuCallToolResultContent[]
+  telemetry: {
+    error_kind?: string
+    [key: string]: unknown
+  }
+}
+
+export type ComputerUseSessionContext = Record<string, unknown>
+
+// ---------------------------------------------------------------------------
+// API_RESIZE_PARAMS — 默认的截图缩放参数
+// ---------------------------------------------------------------------------
+
+export const API_RESIZE_PARAMS = {
+  maxWidth: 1280,
+  maxHeight: 800,
+  maxPixels: 1280 * 800,
+}
+
+// ---------------------------------------------------------------------------
+// ComputerExecutor — stub class
+// ---------------------------------------------------------------------------
+
+export class ComputerExecutor {
+  capabilities: Record<string, boolean> = {}
+}
+
+// ---------------------------------------------------------------------------
+// Functions — 返回合理默认值的 stub
+// ---------------------------------------------------------------------------
+
+/**
+ * 计算目标截图尺寸。
+ * 在物理宽高和 API 限制之间取最优尺寸。
+ */
+export function targetImageSize(
+  physW: number,
+  physH: number,
+  _params?: typeof API_RESIZE_PARAMS,
+): [number, number] {
+  const maxW = _params?.maxWidth ?? 1280
+  const maxH = _params?.maxHeight ?? 800
+  const scale = Math.min(1, maxW / physW, maxH / physH)
+  return [Math.round(physW * scale), Math.round(physH * scale)]
+}
+
+/**
+ * 绑定会话上下文,返回工具调度函数。
+ * Stub 返回一个始终返回空结果的调度器。
+ */
+export function bindSessionContext(
+  _adapter: ComputerUseHostAdapter,
+  _coordinateMode: CoordinateMode,
+  _ctx: ComputerUseSessionContext,
+): (name: string, args: unknown) => Promise<CuCallToolResult> {
+  return async (_name: string, _args: unknown) => ({
+    content: [],
+    telemetry: {},
+  })
+}
+
+/**
+ * 构建 Computer Use 工具定义列表。
+ * Stub 返回空数组(无工具)。
+ */
+export function buildComputerUseTools(
+  _capabilities?: Record<string, boolean>,
+  _coordinateMode?: CoordinateMode,
+  _installedAppNames?: string[],
+): Array<{ name: string; description: string; inputSchema: Record<string, unknown> }> {
   return []
 }
 
-export function createComputerUseMcpServer(..._args: any[]): any {
+/**
+ * 创建 Computer Use MCP server。
+ * Stub 返回 null(服务未启用)。
+ */
+export function createComputerUseMcpServer(
+  _adapter?: ComputerUseHostAdapter,
+  _coordinateMode?: CoordinateMode,
+): null {
   return null
 }
-
-export const targetImageSize: any = null

+ 30 - 3
packages/@ant/computer-use-mcp/src/sentinelApps.ts

@@ -1,5 +1,32 @@
-export const sentinelApps: string[] = []
+/**
+ * Sentinel apps — 需要特殊权限警告的应用列表
+ *
+ * 包含终端、文件管理器、系统设置等敏感应用。
+ * Computer Use 操作这些应用时会显示额外警告。
+ */
 
-export function getSentinelCategory(_appName: string): string | null {
-  return null
+type SentinelCategory = 'shell' | 'filesystem' | 'system_settings'
+
+const SENTINEL_MAP: Record<string, SentinelCategory> = {
+  // Shell / Terminal
+  'com.apple.Terminal': 'shell',
+  'com.googlecode.iterm2': 'shell',
+  'dev.warp.Warp-Stable': 'shell',
+  'io.alacritty': 'shell',
+  'com.github.wez.wezterm': 'shell',
+  'net.kovidgoyal.kitty': 'shell',
+  'co.zeit.hyper': 'shell',
+
+  // Filesystem
+  'com.apple.finder': 'filesystem',
+
+  // System Settings
+  'com.apple.systempreferences': 'system_settings',
+  'com.apple.SystemPreferences': 'system_settings',
+}
+
+export const sentinelApps: string[] = Object.keys(SENTINEL_MAP)
+
+export function getSentinelCategory(bundleId: string): SentinelCategory | null {
+  return SENTINEL_MAP[bundleId] ?? null
 }

+ 70 - 8
packages/@ant/computer-use-mcp/src/types.ts

@@ -1,8 +1,70 @@
-export type ComputerUseConfig = any
-export type ComputerUseHostAdapter = any
-export type CoordinateMode = any
-export type CuPermissionRequest = any
-export type CuPermissionResponse = any
-export type CuSubGates = any
-export const DEFAULT_GRANT_FLAGS: any = {}
-export type Logger = any
+/**
+ * @ant/computer-use-mcp — Types
+ *
+ * 从调用侧反推的真实类型定义,替代 any stub。
+ */
+
+export type CoordinateMode = 'pixels' | 'normalized'
+
+export interface CuSubGates {
+  pixelValidation: boolean
+  clipboardPasteMultiline: boolean
+  mouseAnimation: boolean
+  hideBeforeAction: boolean
+  autoTargetDisplay: boolean
+  clipboardGuard: boolean
+}
+
+export interface Logger {
+  silly(message: string, ...args: unknown[]): void
+  debug(message: string, ...args: unknown[]): void
+  info(message: string, ...args: unknown[]): void
+  warn(message: string, ...args: unknown[]): void
+  error(message: string, ...args: unknown[]): void
+}
+
+export interface CuPermissionRequest {
+  apps: Array<{ bundleId: string; displayName: string }>
+  requestedFlags: GrantFlags
+  reason: string
+  tccState: { accessibility: boolean; screenRecording: boolean }
+  willHide: string[]
+}
+
+export interface GrantFlags {
+  clipboardRead: boolean
+  clipboardWrite: boolean
+  systemKeyCombos: boolean
+}
+
+export interface CuPermissionResponse {
+  granted: string[]
+  denied: string[]
+  flags: GrantFlags
+}
+
+export const DEFAULT_GRANT_FLAGS: GrantFlags = {
+  clipboardRead: false,
+  clipboardWrite: false,
+  systemKeyCombos: false,
+}
+
+export interface ComputerUseConfig {
+  coordinateMode: CoordinateMode
+  enabledTools: string[]
+}
+
+export interface ComputerUseHostAdapter {
+  serverName: string
+  logger: Logger
+  executor: ComputerExecutor
+  ensureOsPermissions(): Promise<{ granted: true } | { granted: false; accessibility: boolean; screenRecording: boolean }>
+  isDisabled(): boolean
+  getSubGates(): CuSubGates
+  getAutoUnhideEnabled(): boolean
+  cropRawPatch?(base64: string, x: number, y: number, w: number, h: number): Promise<string>
+}
+
+export interface ComputerExecutor {
+  capabilities: Record<string, boolean>
+}