解析:用快照锁住跨语言 SDK、CLI 与 MCP 的公开契约)
cua-driver 兼容性夹具Compatibility Fixtures解析用快照锁住跨语言 SDK、CLI 与 MCP 的公开契约【免费下载链接】cuaScale computer-use 2.0 with open-source drivers, cross-OS fleets, and benchmarks for training, evaluation, and data generation.项目地址: https://gitcode.com/GitHub_Trending/cua/cua导读本篇文章围绕 cua-driver 仓库中libs/cua-driver/compat-fixtures/目录展开剖析这一套兼容性夹具compatibility fixtures的设计思路与工程实践它以cua-driver-rs-v0.12.6发布版为基准把 Python / TypeScript SDK 的导出与签名、CLI 帮助与 manifest 字段、MCP 初始化与工具列表等稳定公开契约固化成 JSON 快照并通过 Rust / Python / TypeScript 三套测试在每次构建时校验新版本是否仍然兼容旧契约。读完本文你将理解这套夹具锁定了哪些契约面、如何做语义级而非进程级的对比校验、什么样的变更被允许增量新增、什么样的变更必须走显式兼容决策破坏性修改以及 RFC 3682 与 RFC 2549 两条已接受变更在夹具中的具体落地方式。一、为什么原生驱动需要兼容性夹具cua-driver 是一个跨平台 computer-use 自动化驱动其 SDK 并非单一语言实现底层是 Rust 原生核心与生成绑定generated bindings上层同时暴露 Python、TypeScript 两个 SDK 语言面对外还提供 CLI 子命令与 MCP JSON-RPC 服务。多语言、多入口意味着同一个功能面会同时出现在__init__.py、.d.ts声明、--help输出和tools/list响应中——任何一个入口发生无意的漂移都会在升级后静默破坏下游调用方的代码。compat-fixtures 正是为此设计的契约保险丝它从**发布标签release tag**而非当前工作区提取快照锁住选定字段后任何后续开发只要触发了契约变化CI 就会立即报告。这套机制的价值在于契约可被机器校验快照是结构化 JSON测试逐字段比对语义不依赖人工 review 记忆变更可被显式决策新增是默认允许的删除或修改必须经过明确的兼容决策并同步更新夹具多语言同步受控Rust、Python、TypeScript 三套测试读取同一套夹具避免某一语言面悄悄偏离基线。二、快照基线从发布标签提取的 0.12.6 契约夹具锁定的是cua-driver-rs-v0.12.6发布标签对应提交为9eb1f481b8a12cd6ffda2ad5af21653a9e5aa9e5。快照的生成来源在 compat-fixtures/README.md 中明确列出发布标签对应的包源码release-tagged package sources生成绑定generated bindingscua-driver --help输出cua-driver manifest输出MCP JSON-RPC 实际响应。一个关键设计是夹具锚定的是语义字段而非整进程输出。测试有意排除了可执行文件路径、socket 路径、PID、会话标识符、平台相关散文platform-specific prose以及其他易变值。这样做的直接好处是快照不会因为测试环境差异如 macOS 与 Linux 的默认 socket 路径不同而产生虚假失败。另一个精妙之处在于版本号字段只校验形状而非冻结值夹具不会把版本号锁死为0.12.6而是只校验其满足语义化版本semver格式。原因正如 README 所写——一个兼容的后续版本必须改变版本号若把版本号冻结反而会让每次发布都触发一次无意义的契约变更。三、四个 JSON 快照分别锁住哪一层契约目录下四个 JSON 文件各自负责一个契约面下面逐一展开。3.1python-package.jsonPython 包导出与可调用签名该快照记录三组内容见 python-package.json包根导出package_root_exports共 51 个符号覆盖类型与函数两类类型/常量CaptureScope、ClickButton、ClickInput、DriverOptions、DriverError、DriverExecutionMode、DriverMetadata、Platform、SessionStateOutput、ToolResult等函数与模块级 API__version__、current_mac_os_permission_status、get_binary_path、open_mac_os_screen_recording_settings、request_mac_os_permissions、run_cua_driver。构造器签名package_constructor_signatures锁住类方法_connect_python_sdk(cls, socket_path)与_create_python_sdk(cls, options None)两个内部构造入口。CuaDriver 方法集cua_driver_methods锁住 25 个公开方法的完整签名包括异步动作与查询会话管理start_session/get_session_state/end_session/escalate_session桌面操作click、drag、scroll、hotkey、press_key、type_text、move_cursor、get_cursor_position、get_desktop_state、get_screen_size生命周期connect/connect_with_client_kind/create/create_with_client_kind/shutdown/socket_path/is_available/execution_mode/metadata/list_tools_json。以click为例其冻结签名为async click(self, input: cua_driver._native_contract.ClickInput) - cua_driver._native_contract.ActionResult——注意返回类型是ActionResult而非通用ToolResult这正是 RFC 3682 破坏性变更后的形态详见第六节。3.2typescript-package.json子路径导出、声明导出与 CuaDriver 声明该快照锁住四个层面见 typescript-package.jsonpackage_exports包子路径导出锁住三个入口的解析条件——根入口.指向dist/index.d.ts/dist/index.js./embedded指向dist/embedded.*./electron指向dist/electron.*。这意味着包的三入口布局本身就是契约的一部分不允许在后续版本中悄然移除。root_declaration_exports根声明导出约 53 个符号除与 Python 对应的类型外还包括 TypeScript 特有的CuaDriverInterface、CuaDriverLike、DriverError_Tags、EmbeddedCuaDriverHostInterface、EmbeddedCuaDriverHostLike、SdkClientKind等。cua_driver_declarations生成的 CuaDriver 声明方法锁住静态构造器与核心方法的声明文本例如static connect(socketPath: string | undefined): CuaDriverLike;static create(options: DriverOptions | undefined): CuaDriverLike;callTool(name: string, argumentsJson: string, asyncOpts_?: { signal: AbortSignal; }): PromiseToolResult;shutdown(asyncOpts_?: { signal: AbortSignal; }): Promisevoid;注意asyncOpts_上的{ signal: AbortSignal }——异步取消能力也被视为契约的一部分被锁定。entrypoint_declarations各入口的声明内容进一步细化到index.d.tsexport * from ./native/index.js与 default 导出、embedded.d.ts必须暴露EmbeddedCuaDriverHost、EmbeddedDriverConnection、EmbeddedPermissionMode、electron.d.ts必须暴露 macOS 权限相关 APIMacOSPermissionStatus、requestMacOSPermissions、hasRequiredMacOSPermissions、openMacOSScreenRecordingSettings。3.3cli.jsonCLI 帮助目录与 manifest 字段该快照锁住 CLI 的稳定面见 cli.jsonhelp_lines锁住--help输出的头部与子命令目录包括 cross-platform computer-use automation driver 描述行以及mcp, list-tools, describe, call, serve, stop, revoke, status, config, telemetry, recording, update, check-update, doctor, diagnose, permissions, autostart, skills, manifest共 18 个子命令。manifest锁住cua-driver manifest输出的关键字段schema_version: 1、binary_version_format: semvermcp_args: [mcp]MCP 的调用参数形式各子命令的参数目录如mcp的--socketstring、--grantrepeatable-string、--claude-code-computer-use-compatflag、--embeddedflag、--host-bundle-idstringserve的--permission-mode、--capability-manifest、--approve-capability-manifest、--session-policy、--approve-session-policy、--no-permissions-gate、--dangerously-bypass-approvals等call的两个位置参数toolpositional-string与json-argspositional-json以及--screenshot-out-file、--socketmanifest自身的--prettyflag。3.4mcp.jsonMCP 初始化、工具列表与错误类别该快照锁住 MCP 服务的协议面见 mcp.jsoninitializejsonrpc: 2.0、protocol_version: 2025-06-18、能力键[tools]、server_name: cua-driver且 server 版本号只校验 semver 形状tools_listschema_version: 1、capability_version: 1以及 7 个必备工具——list_apps、list_windows、get_window_state、launch_app、click、type_text、press_key。同时针对click工具锁定了其字段集合name、description、inputSchema、annotations、capabilities、riskunknown_method_error方法不存在时的错误类别被锁定为code: -32601、message: Unknown method: compatibility/unknown——这里特意用一个固定方法名做基准确保错误响应的结构而非具体动态内容稳定tool_call工具调用结果必须包含content、isError、structuredContent三个字段。四、apps/三语言基线应用验证不开守护进程也能用除了 JSON 快照apps/目录还冻结了三份未修改的基线应用源码见 apps/README.mdCI 会针对候选包candidate packages实际编译并运行它们。三个应用刻意只使用发布版连接构造器 端点访问器 语言专属清理操作三件套且不需要运行中的守护进程构造兼容客户端并读取其选中的端点是无副作用的本地产物。Pythonapps/python/app.pyfrom cua_driver import CuaDriver driver CuaDriver.connect(None) endpoint driver.socket_path() if not endpoint.strip(): raise RuntimeError(default endpoint must be selected) print(endpoint)Rustapps/rust/src/main.rs依赖指向工作区内的cua-driver-sdkcrate见 Cargo.tomluse cua_driver_sdk::CuaDriver; fn main() { let driver CuaDriver::connect(None).expect(create compatibility client); let endpoint driver.socket_path(); assert!(!endpoint.trim().is_empty(), default endpoint must be selected); println!({endpoint}); }TypeScriptapps/typescript/app.mjs从trycua/cua-driver导入并显式调用uniffiDestroy()清理import { CuaDriver } from trycua/cua-driver; const driver CuaDriver.connect(undefined); const endpoint driver.socketPath(); if (!endpoint.trim()) throw new Error(default endpoint must be selected); console.log(endpoint); driver.uniffiDestroy();三个应用验证的是同一个事实connect(None/undefined)必须能在无守护进程的前提下返回默认端点。由于三者完全一致地断言默认端点必须非空任何破坏默认连接行为的改动都会在 CI 的三语言维度上同时失败。五、测试如何消费夹具三套语义比对实现夹具本身不产生约束力真正起作用的是消费它们的测试。仓库中三套测试分别从各自语言面的视角校验契约这里以 Rust 测试为主线展开compatibility_contract_test.rs。5.1 Rust真实运行二进制 JSON-RPC 会话Rust 测试通过include_str!把cli.json与mcp.json编译进测试二进制然后用Command真实执行cua-driver --help与cua-driver manifesthelp 校验遍历夹具中的help_lines断言帮助输出包含每一行assert!(help.contains(line))manifest 校验对比schema_version用semver::Version::parse验证binary_version仍是合法语义化版本并断言mcp_invocation.args [mcp]且 command 为非空可执行路径子命令参数校验对 manifest 中每个子命令的每个参数(name, type)对在真实输出中查找匹配项——这正是只允许新增、不允许删除的机械化表达MCP 协议校验测试通过RawDriver::spawn()拉起真实驱动依次发送initialize、tools/list、compatibility/unknown、tools/call四组 JSON-RPC 请求逐一断言协议版本、能力键、必备工具、click工具字段、-32601错误类别以及工具结果三字段content/isError/structuredContent全部与夹具一致。此外还包含两个平台分支测试非 macOS 上验证--directMCP 运行时与发布协议契约一致macOS 上验证显式--direct模式下权限工具只读direct_capture_status: not_checked且拒绝 overlay 工具拒绝码facility_unavailable。5.2 PythonAST 静态解析不运行进程Python 测试test_compatibility_contract.py采用纯静态 AST 比对用ast.parse解析src/cua_driver/__init__.py、wrapper.py、_native.py把函数签名渲染成字符串后与夹具比对。这种方式的优点是零进程开销、不受运行时环境影响且能精确锁定形如async click(self, input: ...) - ActionResult的声明细节。测试同时断言__all__中的导出集合是夹具导出集的超集set(expected) actual——再一次落实只增不减原则。5.3 TypeScript读取产物声明文件TypeScript 测试compatibility-contract.test.mjs直接读取构建产物比对package.json的exports映射、dist/native/cua_driver_contract.d.ts与cua_driver_sdk.d.ts中提取的声明导出集合、规范化后的CuaDriver方法声明文本以及index.d.ts/embedded.d.ts/electron.d.ts三个入口必须包含的导出片段。它还额外验证了新版原生窗口方法的类型化输出例如listApps(input: ListAppsInput, asyncOpts_?: { signal: AbortSignal; }): PromiseListAppsOutput。六、两条已接受的契约变更夹具如何演进夹具不是一成不变的枷锁它区分了两种变更并给予不同待遇。6.1 RFC 3682一次有意的破坏性 SDK 修订RFC 3682Typed native-window SDK flow and explicit click addressing接受了一次有意的破坏性变更旧的click只接受 x/y 坐标且返回通用结果无法表达元素 token 或后台投递新契约要求ClickInput必须包含ActionTarget明确的窗口或桌面目标ClickPosition坐标或快照绑定的元素 token二选一的 sum type显式的InputDeliveryMode后台 / 前台。同时click直接返回ActionResult工具拒绝时抛出DriverError.Tool。该变更落地后Python 的click签名同步更新TypeScript 基线则没有冻结该方法因此不受影响夹具中其余冻结的包签名、CLI/MCP 快照与基线应用保持不变。测试覆盖了新的签名以及类型化原生窗口的发现list_apps、list_windows与观察get_window_state方法。这一案例说明夹具的运作逻辑破坏性变更本身被允许但必须以 RFC 形式显式决策并在夹具中留下痕迹——python-package.json中click的返回类型变为ActionResult正是该决策的冻结证据。6.2 RFC 2549一个纯新增的 CLI flag与上述不同RFC 2549 带来的cua-driver mcp --direct属于纯新增裸mcp行为保持平台定义Windows / Linux 直接运行macOS 为签名应用服务--socket继续选择显式服务。由于夹具测试采用候选参数集合包含夹具参数集合的语义比对这个新增 flag不需要重写冻结的cli.json基线也能通过校验——这正是语义比对而非整进程输出比对的设计回报新增是零成本兼容删除才需要成本。七、工程启示把兼容性变成可测试的资产回顾整套机制可以提炼出几条可复用的工程原则从发布标签提取基线而不是从主干提取——快照代表用户实际在用的契约而非团队想要的状态锁定语义字段而非进程输出——排除路径、PID、平台散文等易变值让快照跨平台、跨环境稳定版本号只校验形状semver——避免兼容性测试与版本递增相互打架新增默认放行删除/修改必须显式决策——通过子集/超集断言expected actual把这一策略直接写进测试多语言面共享同一套夹具——Rust、Python、TypeScript 各自动态的测试读取同一批 JSON任何语言面漂移都会立刻暴露。对于任何维护多语言 SDK、CLI 与协议服务的项目而言libs/cua-driver/compat-fixtures/都是一个可以直接借鉴的契约保险范式它让我们不破坏下游从一句口头承诺变成了 CI 中每一次构建都会自动执行的断言。【免费下载链接】cuaScale computer-use 2.0 with open-source drivers, cross-OS fleets, and benchmarks for training, evaluation, and data generation.项目地址: https://gitcode.com/GitHub_Trending/cua/cua创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考