Qwen Code 内置 CUA Driver 0.20.0 上游同步:交付边界、同步流程与 Qwen 不变量解析
【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code
CUA Driver 是 Qwen Code 以 vendored(内嵌镜像)方式分发的一套跨平台桌面与浏览器自动化运行时。本文基于 docs/plans/2026-08-20-cua-driver-0.20.0-upstream-sync.md 及其配套设计文档,完整讲解一次"纯前置"上游同步的技术方案:如何把内嵌的 CUA Driver 从已发布的 0.17.0 快照推进到 0.20.0,同时保住 Qwen 自己的身份、遥测、坐标与负载过滤契约。读完本文,你将掌握该仓库的 vendored 同步机制、同步脚本的工作原理、哪些变更会被视为越界,以及如何分层验证一次大版本同步是否真正安全落地。
背景:为什么需要一次"纯前置"的上游同步
Qwen Code 仓库把trycua/cua的libs/cua-driver以 vendored 方式收纳进自己的packages/cua-driver目录,并在其上叠加 Qwen 特有的运行时与分发契约(详见 packages/cua-driver/README.md 的说明)。这意味着上游每一次大版本演进,Qwen Code 都需要走一次"拉取上游 delta → 解决冲突 → 重挂 Qwen 补丁 → 分层验证"的同步流程。
计划文档为这次同步给出了明确的交付边界:
Deliver one pure prerequisite change before Issue #9334: move the vendored CUA Driver from the released 0.17.0 snapshot to released 0.20.0 while preserving the documented Qwen distribution and compatibility patches. Do not change the built-in Computer Use adapter or downloader pin.
也就是说:
- 这是一次"纯前置变更",服务于后续的 Issue #9334(模型可见的 Computer Use 能力),但本次不实现 #9334 的任何模型侧 API;
- 只升级内嵌驱动本身:从已发布快照 0.17.0 迁到已发布版本 0.20.0;
- 内置 Computer Use adapter 与下载器 pin 保持不变,它们是独立评审的后续工作。
同步的"事实源":tag、commit 与 npm dist-tag
设计文档 docs/design/cua-driver-0.20.0-upstream-sync.md 明确了这次同步的权威依据(source of truth):
| 项 | 值 |
|---|---|
| 同步目标 | 上游稳定版cua-driver-rs-v0.20.0(trycua/cua) |
| 目标 commit | bb8c86049cad1bf0853c6d25c03c14875d0d047f |
npmlatestdist-tag | @trycua/cua-driver亦解析到0.20.0 |
| 排除项 | 0.20.1属于 nightly 预发布,不作为发布基线 |
| 当前快照 | cua-driver-rs-v0.17.0@ commit10279552e2bbe479e367a082f78b1b98ee85a697 |
| 合并策略 | 以 0.17.0 为共同祖先做三路合并,校验packages/cua-driver/scripts/sync-from-upstream.sh生成的 delta |
这里有两个容易被忽略的细节:一是"发布 tag 是唯一事实源",本地旧 checkout、旧设计笔记和已生成产物只作为比较输入;二是 npm 的latestdist-tag 与 Git tag 必须指向同一版本,避免"Git 同步到 0.20.0、npm 侧却漂到别的版本"的错位。
同步流程:从 delta 应用到全量复核的 8 个步骤
计划文档把整个同步拆成 8 个顺序步骤,覆盖"验证 → 应用 → 裁决 → 对齐 → 验证 → 冒烟 → 全量复核"的完整闭环:
- 验证官方元数据:核对 Git tag、commit、npm dist-tag 与发布元数据,确认 0.20.0 是稳定发布而非预发布;
- 应用 0.17.0 → 0.20.0 delta:用仓库自带的同步脚本 packages/cua-driver/scripts/sync-from-upstream.sh 拉取
libs/cua-driver的增量; - 三路合并裁决 reject:对每个冲突(
.rej文件)以上游 0.17.0 为共同祖先做三路合并,逐一裁决; - 采用上游 0.20 行为并保留 Qwen 补丁:采纳新的生命周期、target、授权、SDK 与浏览器 token 行为;保留 Qwen 身份、遥测、坐标适配、payload 过滤与 Windows 空标题窗口补丁;
- 恢复锁文件并对齐示例:恢复干净的
npm ci构建所需的 lockfile;把独立 SDK 示例对齐到已发布的 0.20.0 包;推进 Qwen 发布元数据到 0.20.0; - 全面验证:校验源码来源、版本一致性、生成契约、语言 SDK、Rust 包、安装器行为、发布接线以及外围 Qwen workspace;
- 调试运行时冒烟测试:平台相关或签名发布相关的缺口单独记录,与源码失败区分开;
- 两轮连续干净通过:以开放式通读方式检查全部已跟踪与未跟踪 diff,最终修复后必须连续两轮干净通过才能收尾。
第 2 步是唯一由脚本自动完成的环节,其余步骤都要求人工判断,这正是"vendored 同步"与普通依赖升级的本质区别——Qwen 的补丁必须在新基线上重新定位。
同步脚本源码剖析:reject-based apply 与三路合并
packages/cua-driver/scripts/sync-from-upstream.sh 是整个同步机制的核心。脚本头部注释解释了为什么不使用git subtree:git subtree split会在 trycua/cua 历史深处的某个 commit 上挂起,导致 subtree pull 流程无法使用,因此仓库选择"只 diff 两个 ref、不做全历史遍历"的 reject-based apply 方案。
关键流程(对应脚本源码 sync-from-upstream.sh):
- 读取旧基线:从
packages/cua-driver/.vendored-from读取当前 vendored 来源 ref(OLD_REF),并校验新旧两个 ref 都能在本地 trycua/cua clone 中解析; - 生成上游 delta:
git diff --binary --no-renames "$OLD_REF" "$NEW_REF" -- libs/cua-driver只取驱动目录的增量,--no-renames让重命名变成 delete + add,从而让三路应用更可预测; - 路径重写:
git apply --reject --directory=packages/cua-driver -p3剥掉a/libs/cua-driver/三个路径组件,再前置到packages/cua-driver/; - 冲突留痕:能应用的 hunk 全部应用,应用不上的写成同级
.rej文件。之所以不用--3way,是因为补丁的 base blob 在上游仓库而不在本地,本地无法做三路查找,而普通 apply 又是全有或全无的; - 更新基线记录:无论成功与否,
.vendored-from都会更新为NEW_REF,保证下次同步的起点正确; - 提示补丁表:脚本末尾提示检查 packages/cua-driver/.vendored-patches.md,如果新 ref 已经包含某个 cherry-pick PR 的合并点,就预期会在对应文件上产生
.rej,并在解决后把该行从"活跃补丁"表移除。
.vendored-patches.md的当前内容印证了计划第 4 步"保留 Windows 补丁、退役 EAGAIN 补丁"的要求:
| 上游 PR | 修复内容 | 状态 |
|---|---|---|
| trycua/cua#2021 | list_windows包含空/空标题顶层窗口 | 仍 open,由 Qwen 本地携带(platform-windows) |
| trycua/cua#2036 | daemon socket 写遇EAGAIN/EWOULDBLOCK时重试而非致命失败 | 已并入 0.17.0 基线,退役本地补丁 |
| trycua/cua#2025 / #2035 | X11 合成点击误报成功 /start_session复活空闲回收会话 | 0.7.0 基线已包含,退役 |
需要"重新决策"的停止条件
计划文档明确列出 5 种触发"需要新决策"的停止条件。换句话说,只要同步过程触碰了以下任何一条,就不能继续机械执行,而必须停下来重新讨论方案:
- 改变 Qwen 内置 Computer Use 下载器或 bootstrap 行为;
- 用上游值替换 Qwen 的身份、安装路径、签名归属或遥测默认值;
- 照搬上游独有的发布基础设施,或引入新的发布密钥;
- 在 Windows 本地补丁被上游合并之前擅自丢弃它;
- 把 Issue #9334 的模型侧 API 塞进本次同步变更。
这 5 条是"边界红线":前三条保护 Qwen 的分发与信任边界,第四条保护尚未上游化的本地修复,第五条保证变更范围单一、可独立评审。任何一条越界都意味着本次变更不再是"纯前置同步",需要回到决策层面重新规划。
采用的上游 0.20.0 行为
同步完成后,0.20.0 运行时成为新的 vendored 基线,设计文档列出的"被采纳的上游行为"包括:
- 传输层拥有的隐式生命周期会话与显式 per-action target:会话生命周期由传输层管理,动作目标逐动作显式指定;
- 跨权限 profile 生效的 capability manifest:能力清单不再只属于单一 profile;
- typed SDK、contract 与生成绑定更新:Python / TypeScript UniFFI 绑定随版本同步演进;
- 前台聚焦验证与后台输入加固:即 README 中提到的
verify_state、foreground-focus verification; - 策略过滤的工具发现与命名 CLI 会话行为;
- stable / nightly 发布通道支持;
- 移除旧版浏览器 approval token:
browser approval tokens are retired,已有 profile 的访问只能通过受信任的启动授权(launch grant)、受限 manifest 或嵌入宿主(embedding host)的授权回调继续。
其中最后一条是行为级破坏性变更,设计文档特别强调:被移除的浏览器 token 路径不作为 Qwen 兼容 fork 保留。也就是说,Qwen 不与上游"反向兼容",而是接受 0.20 的新授权模型。
从 packages/cua-driver/README.md 可以看到这一模型在用户侧的落地:qwen-cua-driver mcp --grant existing-profile显式授予已有 Chromium profile 的访问权,嵌入应用则可以提供DriverAuthorizationHost自己掌管权限提示与授权生命周期。权限模式分三档——standard(默认,无提示)、bounded(仅放行已评审工具与资源)、unrestricted(需--dangerously-bypass-approvals)。
Qwen 不变量:同步必须保住的下游边界
"采用上游行为"与"保住 Qwen 契约"是一体两面。设计文档把必须保留的 Qwen 不变量归纳为 6 条,计划第 4 步的"保留"清单与之完全对应:
- 身份归属:可执行文件、app、bundle、服务、安装、更新与发布身份全部保持 Qwen 所有。README 给出了具体形态:可执行文件
qwen-cua-driver/qwen-cua-driver.exe、macOS app/Applications/QwenCuaDriver.app、bundle identifiercom.qwencode.cua-driver、状态目录~/.cua-driver、Windows 计划任务qwen-cua-driver-serve;源码本地构建则使用独立的qwen-cua-driver-local身份; - 遥测默认关闭:Qwen 发行版默认禁用遥测,显式启用后也只走文档规定的上游端点(
qwen-cua-driver telemetry enable/status/disable,详见 README),不引入 Qwen 遥测服务或代理; MCP_MODEL_PAYLOAD_FILTER=1:继续作为面向 Qwen 的 payload 过滤器,作用于文本与结构化 MCP 内容,不改动二进制媒体,且不改变直接 SDK 契约;CUA_DRIVER_RS_COORDINATE_SPACE=1:继续作为可选的归一化坐标适配器,绝对像素仍是默认;CUA_DRIVER_RS_COORDINATE_SCALE可选(默认 1000)。坐标换算发生在 MCP、CLI、daemon、private worker、replay 与直接 SDK 共享的规范工具注册边界,窗口内动作用最近快照尺寸、屏幕空间动作用逻辑屏幕尺寸,缺失或过期坐标基失败关闭而非猜测;- 安装兼容路径:发布安装继续使用
~/.cua-driver保持升级兼容,源码构建保留独立的 Qwen 身份(~/.qwen-cua-driver-local); - Windows 空标题补丁:尚未上游合并的 trycua/cua#2021(空/空标题顶层窗口)继续携带并适配到新的窗口模型。
这 6 条中的身份与坐标契约,正是 0.17.0 同步时(docs/design/cua-driver-0.17.0-upstream-sync.md)确立的,0.20.0 同步的职责是"把同样的 Qwen delta 重新挂到新基线的规范边界上",而不是推翻它们。
发布与打包边界
Qwen 的发布流程保留在 .github/workflows/cd-cua-driver.yml,同步时只做维持新驱动构建与发布契约所需的最小改动:
- 保持既有签名、公证(notarization)、产物命名与发布归属;手工触发(
workflow_dispatch)的默认版本推进到 0.20.0(当前仓库该 workflow 的默认值已进一步演进为0.20.5,说明发布线在持续前进); - 恢复上游 TypeScript lockfile——
npm ci需要它才能干净构建; - 上游 0.20.0 tag 把独立 Agent SDK 示例钉在 0.19.2,尽管 npm 与 PyPI 都发布 0.20.0;因此 vendored 示例及其 npm lockfile 要对齐到 0.20.0,确保示例实际执行的是同步后的契约;
- macOS bundle 版本在存在预发布后缀时仍需保持合法。
同时,上游的 monorepo 级 nightly 编排、release-attribution 服务、Python 发布与文档发布基础设施一律不复制——它们依赖上游独有的脚本、密钥、仓库与发布治理。跨平台签名发布产物仍是 CI 门禁,不会本地代跑。
配套的产物契约(README 与 workflow 注释)如下:macOS 产出cua-driver-rs-<v>-darwin-{arm64,x86_64,universal}.tar.gz(含 Qwen 二进制、SDK 载荷与已签名QwenCuaDriver.app)及*-binary.tar.gz;Linux 产出-linux-{x86_64,arm64}.tar.gz;Windows 产出-windows-{x86_64,arm64}.zip。@qwen-code/cua-sdknpm 包通过匹配的*-binary归档下载并校验原生载荷(详见 docs/design/cua-driver-computer-use-sdk.md 的发布契约)。
分层验证:让单测绿无法掩盖分发与信任边界破损
验证设计强调"分层",因为窄而绿的单元测试可能掩盖发行版或信任边界的破坏。0.17.0 同步确立的验证层次(docs/design/cua-driver-0.17.0-upstream-sync.md)在 0.20.0 同步中继续适用,并结合计划第 6~8 步展开:
- Rust 层:
cargo fmt --all -- --check、包检查、core/contract/SDK 单元测试、生成契约一致性(对应 packages/cua-driver/rust 工作区); - 聚焦专项:坐标归一化、payload 过滤、Windows 窗口枚举、安装器与版本测试;
- 语言 SDK:Python 与 TypeScript SDK 生成/包检查(在包本地工具链可用时);
- 发布工作流静态检查:可执行名、app bundle 布局、bundle identifier、资产与烘焙版本(对应 scripts/tests/cua-driver-release-workflow.test.js 与 .github/workflows/cd-cua-driver.yml);
- 外围仓库:
npm run build && npm run typecheck; - 全量审计:完整 diff 与 untracked 文件审计,重复到连续两轮干净为止;
- 签名/公证生产发布与真实物理机 GUI 认证(Windows UIAccess、Linux X11/Wayland、macOS)属于发布门禁,不在本地验证范围内——这正是计划第 7 步"平台相关或签名发布缺口单独记录"的原因。
计划第 7、8 步在此基础上补充了"调试运行时冒烟测试"和"两轮连续干净通过"的收尾纪律,保证源码层失败与平台/签名层缺口被分开跟踪、分开裁决。
明确的范围边界与后续工作
设计文档的 Out of scope 与计划文档的停止条件互相呼应:本次同步不修改 Qwen Code 当前内置的下载器 pin、Computer Use MCP adapter、bootstrap 流程、权限 UX 与模型可见工具 schema,也不实现 Issue #9334。这些集成变更都作为"基于已验证 0.20.0 运行时与 TypeScript SDK 的独立可评审后续项"存在。
从仓库现状看,后续方向已经可见:关于 Computer Use 的 SDK 化与 accessibility observation revision 协议的独立阶段设计见 docs/design/cua-driver-computer-use-sdk.md 与 docs/plans/2026-08-20-cua-driver-computer-use-sdk.md,它们与本次同步是"先有稳定 0.20 基线、再在其上做 SDK 能力扩展"的前后置关系。
总结
一次成功的 vendored 上游同步,核心不在于"把新代码搬进来",而在于三件事:以发布 tag 为唯一事实源(0.20.0 而非 nightly 的 0.20.1)、用脚本加三路合并把冲突裁决干净(sync-from-upstream.sh + .vendored-patches.md)、把 Qwen 不变量重新挂到新基线的规范边界上(身份、遥测、payload 过滤、坐标契约、Windows 补丁)。配合 5 条停止条件的硬约束与 6 层验证的门禁,0.17.0 → 0.20.0 的同步才能以"纯前置变更"的姿态,安全地为后续 Issue #9334 与 Computer Use SDK 铺路。
【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考