news 2026/9/13 20:45:35

CuaBot 多玩家计算机使用实战:用 Xpra 沙箱让多个 Agent 与人类共享同一桌面

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
CuaBot 多玩家计算机使用实战:用 Xpra 沙箱让多个 Agent 与人类共享同一桌面

CuaBot 多玩家计算机使用实战:用 Xpra 沙箱让多个 Agent 与人类共享同一桌面

【免费下载链接】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 开源仓库中的 CuaBot 模块,深入讲解"多玩家计算机使用"(Multi-Player Computer-Use)这一核心设计:每个编程 Agent(Claude Code、Gemini CLI、Codex、Aider、OpenClaw 等)在自己的 Docker 沙箱内获得独立桌面、独立彩色光标与独立窗口管理,而人类用户仍可随时在自己的宿主桌面上与这些 Agent 窗口交互。读完本文,你将掌握 CuaBot 的容器 + Xpra 流式窗口 + hairpin 回环(容器→宿主→容器)的完整架构、多会话并行启动方法、computer-use MCP 工具全集,以及 OpenClaw 的集成方式。

CuaBot 界面截图

从"独占桌面"到"多玩家桌面":为什么要重写计算机使用的交互模型

传统计算机使用(Computer-Use)Agent 有一个根深蒂固的前提:操作系统只有一个光标、一个键盘焦点、一个活动窗口——这套假设可以追溯到 Xerox PARC 时代。当 Agent 接管桌面时,你的输入与 Agent 的输入互相冲突,你只能等它跑完才能重新使用自己的电脑。

CuaBot 试图打破这个假设,其核心理念是多玩家:Agent 和人类各自拥有自己的光标、自己的键盘焦点、自己的窗口管理,全部共存于同一块屏幕上。这来自 Cua 社区的高频需求——用户希望把 cua-computer-server 直接跑在宿主机器上,让 Agent 操作真实桌面,但代价是 Agent 一运行,你的屏幕就被接管。CuaBot 给出的答案是:不把 Agent 放进你的桌面,而是为每个 Agent 建一个独立桌面,再以流式窗口的形式"借"给你看。

该方案的设计取向在仓库文档中也有体现:CuaBot 的定位是"给任何编码 Agent 提供协作式计算机使用能力"(见 libs/cuabot/README.md),它把 computer-use 视为通用 Agent 系统中的一件工具,而不是独立的屏幕接管程序。

核心架构:容器 + Xpra 流式窗口 + hairpin 回环

CuaBot 的运行链路由三层组成:

1. Docker 容器内的 X11 桌面

CuaBot 启动一个 Docker 容器(镜像trycua/cuabot:latest),内部运行完整的 X11 Linux 桌面。容器入口脚本 entrypoint.sh 会先拉起 dbus 会话,再以 seamless(无缝)模式启动 Xpra:

dbus-daemon --session --fork --address=unix:path=/tmp/dbus-session exec xpra seamless :100 --sharing=yes --no-daemon --bind-tcp=0.0.0.0:10000 --html=on --dpi=96

这里:100是容器内的显示编号,--sharing=yes开启共享会话(这是多玩家得以成立的前提之一),--html=on启用 Xpra 的 HTML5 客户端端点,端口 10000 通过-p hostPort:10000映射到宿主。

2. 宿主上的 cuabotd 服务

宿主机上运行着一个名为cuabotd的 Node.js HTTP/WebSocket 服务(默认端口 7842,见 cuabotd.ts)。它负责:

  • 检查 Docker 连接、拉取镜像、创建并启动容器;
  • 维护宿主上的 Xpra 客户端进程,把容器内应用窗口"附着"(attach)到宿主桌面;
  • 暴露一组计算机使用 API(截图、点击、输入、滚轮、按键、拖拽等),供容器内的 MCP 服务器调用;
  • 维护多会话状态(每个命名会话有独立的 PID 文件、端口文件与容器名)。

创建容器时注入的关键环境变量(见ensureContainer逻辑):

环境变量作用
DISPLAY:100容器内 X 显示编号
CUABOT_HOSThttp://host.docker.internal:<serverPort>容器内 MCP 服务器回连宿主 cuabotd 的地址
CUABOT_TELEMETRYtrue/false使用遥测开关
CUABOT_NAME/CUABOT_COLOR会话名 / 派生颜色用于 overlay 光标与窗口标识

3. hairpin 回环:容器 → 宿主 → 容器

这是 CuaBot 最巧妙的设计。当容器内的 Agent 调用screenshot()click(x, y)时,请求链路如下:

容器内 Agent → computer-use MCP 服务器(FastMCP,运行在容器内) → HTTP POST 到 CUABOT_HOST(即宿主上的 cuabotd) → cuabotd 驱动 Playwright 控制的 headless Chromium → Chromium 打开 Xpra HTML5 客户端页面(http://localhost:<containerPort>/?steal=no&sharing=yes) → 操作经 WebSocket 回传容器内的 X11 服务器

这条"容器 → 宿主 → 容器"的路径被作者称为hairpin(发夹)。它虽然多绕了一圈,却干净利落地把 Agent 的显示服务器与宿主操作系统隔离开来——这正是多玩家能够成立的根本原因:Agent 的桌面是容器里的虚拟桌面,宿主桌面永远是人类的。

从代码可以印证这一点:cuabotd.ts 中的ensurePlaywrightConnected()launchPlaywright()启动chromium.launch({ headless: true }),然后page.goto("http://localhost:{containerPort}/?steal=no&sharing=yes"),并轮询页面中是否出现<canvas>来判断 Xpra HTML5 是否就绪。

多玩家:并行 Agent、独立光标、独立窗口

由于每个 Agent 运行在自己的容器、自己的 Xpra 实例中,并行启动多个 Agent 是天然支持的:

cuabot claude # 第一个 Agent:Claude Code cuabot gemini -n second # 第二个 Agent:Gemini CLI,命名会话 second

-n, --name <name>是 cuabot.tsx 中解析的会话名参数(parseSessionName支持--name/-n两种写法)。命名会话在源码中有完整的隔离机制:

  • 容器名变为cuabot-xpra-<session>(默认是cuabot-xpra);
  • 服务 PID 文件与端口文件分别变为server.<session>.pidserver.<session>.port(存放在~/.cuabot下);
  • 端口自动避让:findAvailableServerPort会从首选端口开始向上寻找可用端口,Docker 映射端口也通过findAvailablePort扫描docker ps已占用端口来避让。

每个 Agent 因此拥有:

  • 自己的桌面:独立容器 + 独立 Xpra display;
  • 自己的光标:颜色由会话名经 utils.ts 的nameToColor()用哈希 + 黄金比例(0.618033988749895)生成,饱和度为 0.7、亮度 0.5,保证不同会话颜色差异明显;
  • 自己的窗口集合:Xpra 以 seamless 模式把每个应用窗口作为宿主上的原生窗口展示,并带彩色边框与独立托盘图标。

Overlay 光标:Agent 在"哪里操作"一目了然

为了让人类能看到 Agent 当前的操作位置,容器内运行着一个透明的浮动光标指示器 overlay-cursor.py。它是一个无边框、无任务栏、点击穿透(input_shape_combine_region设为空区域)的 GTK 弹窗,会:

  • 按会话名渲染指定颜色的光标图标(cursor.png按颜色着色);
  • 用带重力与风力扰动的路径算法模拟类人鼠标移动轨迹(generate_pathgravity=9.0wind=3.0max_v=15.0);
  • 空闲 15 秒后开始 1 秒淡出;
  • 通过 Unix 域套接字/tmp/cuabot-overlay-cursor.sock接收宿主端命令(move / click / masked / hide / quit)。

宿主的 cuabotd.ts 还会做光标遮挡掩码计算:每 500ms 轮询一次宿主窗口列表(get-windows),对非 Xpra 窗口区域"添加"掩码、对 Xpra 窗口区域"挖洞"(AABB 差集运算 + 合并),当 Agent 光标落入宿主窗口之下时隐藏 overlay 光标,避免画在用户自己的窗口上面——这是多玩家体验里很关键的细节。

Xpra 客户端的附着参数

宿主端 Xpra 客户端由 cuabotd 以 detached 方式拉起(getXpraAttachArgs,见 utils.ts):

xpra attach tcp://localhost:<containerPort> \ --splash=no --notifications=no \ --border=auto,4 --sharing=yes \ --tray-icon=<icon> --window-icon=<icon> \ --session-name=cuabot (<name>)

--sharing=yes是关键:它允许 Playwright 的 HTML5 客户端与宿主的原生 Xpra 客户端同时挂接同一个会话,也就是"Agent 在容器里干活、你在宿主上看/插话"并行不悖的技术基础。剪贴板与音频会随 Xpra 会话自动同步。

computer-use MCP 工具全集

容器内通过 computer-use-mcp.py(FastMCP 实现,自包含 uv 脚本)向 Agent 暴露桌面自动化工具。它通过CUABOT_HOST环境变量回连宿主 cuabotd,每个工具最终落到 cuabotd 的 HTTP handler 上:

MCP 工具参数对应 cuabotd 端点说明
screenshotsave_path?POST /screenshot返回 JPEG;scaleScreenshot会把长边缩到 ≤1280 并记录缩放比,坐标自动换算回原屏幕坐标
clickx, y, button=leftPOST /click支持 left/right/middle;同步驱动 overlay 光标移动并播放点击动画
double_clickx, yPOST /doubleClick双击
type_texttext, delay=50POST /type按键间隔默认 50ms
mouse_movex, yPOST /mouseMove移动光标
mouse_down/mouse_upx, y, button=leftPOST /mouseDown/mouseUp按下/释放鼠标键
scrollx, y, delta_x, delta_yPOST /scroll滚轮(deltaY 负值向上)
key_down/key_up/key_presskeyPOST /keyDown/keyUp/keyPress组合键与快捷键(如 Enter、Tab、Shift、Control)
dragfrom_x, from_y, to_x, to_yPOST /drag拖拽,中间 10 步插值移动

MCP 客户端(CLI 侧)对应的完整命令见 cuabot.tsx 的帮助文本:cuabot --screenshot [path]--click <x> <y> [button]--doubleclick--move--mousedown--mouseup--drag <x1> <y1> <x2> <y2>--scroll <x> <y> <dx> <dy>--type <text>--key--keydown--keyup。此外还有服务管理命令--serve [port]--stop--status--reset [all|sandbox|settings],以及任意命令执行cuabot --bash <command>和交互式 WebSocket shell(ws://localhost:<port>/?command=...,基于 node-pty 的docker exec -itPTY 会话,支持 stdin 与窗口 resize)。

沙箱内的环境

Agent 一进沙箱就拥有一套可用的开发环境。容器内的系统提示词见 SYSTEM.md:

  • 操作系统:Ubuntu 22.04,拥有 sudo 权限;
  • 运行时:Node.js 22.x、Python 3.10、pip3、uv(Python 包管理器,可运行带内联依赖的自包含脚本);
  • 预装工具:chromium、agent-browser(浏览器自动化 CLI)、agent-device(adb / Android 自动化)、feh、claude-code、x11-apps;
  • 预装 Python 库:matplotlib、numpy、pandas、seaborn、plotly。

容器入口还会在后台通过npx skills安装callstackincubator/agent-devicevercel-labs/agent-browser技能(写入挂载到宿主的~/.claude目录,见 entrypoint.sh),使 Agent 具备浏览器与 Android 设备自动化能力。

支持的 Agent 与 OpenClaw 集成

CuaBot 的 Agent 注册表见 settings.ts,开箱支持六种编码 Agent:

Agent ID名称启动命令
claudeClaude Codeclaude --mcp-config /home/user/.mcp.json --append-system-prompt-file /home/user/CLAUDE.md
geminiGemini CLInpx @google/gemini-cli
codexOpenAI Codexcodex
aiderAideraider
openclawOpenClawopenclaw
vibeVibevibe

注意 Claude 的特殊处理:runAgent会为它显式传入--mcp-config /home/user/.mcp.json(即预配置好的 computer-use MCP)并追加系统提示词文件,其他 Agent 则使用注册表中的命令直接启动。cuabot <任意命令>还能在沙箱中运行任意 shell 命令。

OpenClaw:开箱即用的配合

CuaBot 与 OpenClaw 的集成分两种形态:

  1. 沙箱内运行cuabot openclaw在 CuaBot 沙箱内启动 OpenClaw,computer-use MCP 已预先配置好。OpenClaw 拥有完整桌面环境,窗口流式传输到宿主,你的机器不受影响,无需额外配置;
  2. 无沙箱注入cuabot --add-mcp openclaw可将 CuaBot 的 MCP 服务器注入到已有的 OpenClaw 安装中,为未沙箱化的 OpenClaw 补上计算机使用能力。

由于每个 Agent 独立成沙箱、各有光标,你完全可以让一个 OpenClaw 实例处理任务 A、一个 Claude Code 实例处理任务 B——它们在各自的桌面里并行工作,互不干扰。

快速开始:一条命令跑起来

npx cuabot

首次运行会进入引导流程(onboarding.tsx,交互式 TUI):检查 Docker 连接、Xpra 客户端、Playwright Chromium 与 Docker 镜像缓存,拉取容器镜像(约 2GB),把cuabot别名写入 shell 配置文件(macOS 写.bash_profile/.zshrc,Linux 写.bashrc,Windows 写 PowerShell profile 并生成cuabot.cmd),然后选择默认 Agent。之后直接输入cuabot即可启动默认 Agent。

运行前提

  • Node.js 18+;
  • Docker Desktop(macOS / Windows)或 Docker 守护进程(Linux);
  • Xpra 客户端:macOS 需安装到/Applications/Xpra.app(注意检查com.apple.quarantine隔离属性,被隔离时需sudo xattr -c /Applications/Xpra.app),Windows 在C:\Program Files\Xpra\xpra_cmd.exe,Linux 通过apt install xprabrew install xpra,见 utils.ts 的XPRA_PATHS与依赖检查逻辑。

依赖检查不通过时会给出明确指引,例如:

  • Docker 未安装 / 未运行 → 提示安装并启动 Docker Desktop;
  • Xpra 缺失 → 按平台给出安装命令;
  • Playwright Chromium 缺失 →npx playwright install chromium
  • 镜像未拉取 →docker pull trycua/cuabot:latest

服务日志写入~/.cuabot/server.log,如需彻底重置可执行cuabot --reset all(移除容器、镜像与~/.cuabot配置)。

多玩家进阶:把多个 Agent 与你自己编排到同一屏

综合以上机制,一个典型的多玩家工作流是:

# 终端 1:默认会话跑 Claude Code cuabot claude # 终端 2:命名会话跑 Gemini CLI(独立容器、独立光标颜色) cuabot gemini -n second # 终端 3:随时查看两个会话的服务状态 cuabot --status cuabot --status -n second

运行后,你的宿主桌面上会看到两组带彩色边框的原生窗口:一组属于 Claude(默认颜色),一组属于 Gemini(second会话派生颜色)。你可以直接点击任意一组的窗口输入内容、切回自己的工作窗口继续干活,Agent 不会因为你的操作而中断。若启用了遥测(首次引导时可配置),cuabotd 会记录 CLI 调用、MCP 工具调用等事件,并在停止时刷新数据。

未来方向

按照发布文档的规划,CuaBot 后续将推进:

  • macOS VM 支持(借助 Lume):为需要 macOS 原生应用的 Agent 提供沙箱化 macOS 环境;
  • 跨沙箱的多 Agent 编排:在多个沙箱之上统一调度任务;
  • 沙箱上的 RL 训练环境:以沙箱为底座构建 gym 风格的评估循环,用于训练计算机使用模型。

这些方向与 Cua 生态中计算机使用基础设施(如 Lume、cua-sandbox、cua-bench 等模块)一脉相承,读者可在仓库中继续深入。

小结

CuaBot 用"每人一个桌面"取代"大家抢一个桌面":Docker 容器隔离出独立 X11 桌面,Xpra seamless 会话把应用窗口流式呈现到宿主,hairpin 回环让 Agent 的输入经由宿主 Playwright 回流容器,而 overlay 光标与窗口掩码让"谁在操作哪里"一目了然。无论你用的是 Claude Code、Gemini CLI、Codex、Aider 还是 OpenClaw,只需npx cuabot,即可在保住自己机器使用权的同时,让任意多个 Agent 与你共享同一块屏幕并行工作。

【免费下载链接】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),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/13 20:37:57

StarRocks表达式分区:精准时间窗口裁剪实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华