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>
This commit is contained in:
claude-code-best 2026-04-01 08:36:12 +08:00
parent 975b4876cc
commit b51b2d7675
4 changed files with 255 additions and 33 deletions

View File

@ -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 扩展 -->

View File

@ -1,30 +1,163 @@
export const API_RESIZE_PARAMS: any = {}
/**
* @ant/computer-use-mcp Stub
*
* stub
* feature('CHICAGO_MCP') = false
* import
*/
export class ComputerExecutor {}
import type {
ComputerUseHostAdapter,
CoordinateMode,
GrantFlags,
Logger,
} from './types'
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
// 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'
export function bindSessionContext(..._args: any[]): any {
return null
// ---------------------------------------------------------------------------
// 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 function buildComputerUseTools(..._args: any[]): any[] {
export interface FrontmostApp {
bundleId: string
displayName: string
}
export interface InstalledApp {
bundleId: string
displayName: string
path: string
}
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

View File

@ -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
}

View File

@ -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>
}