跳转到内容

远程控制与移动端

Control Center 是一款桌面应用,但它所跟踪的工作不会在你离开书桌时停下来。 远程控制借助 Remote——位于 remote.usectrl.dev 的伴侣应用——把你的手机与 cc_server 配对,让你可以在那里 跟进机群:阅读消息与工单、回复智能体、分拣新闻流,而服务器上的音频、转录、 源代码和凭据始终不会离开服务器。

可以把它看作主界面的伴侣应用,以读取为主。它并不打算取代完整的桌面客户端。

手机通过 WebSocket 访问 cc_server:要么是直连(回环、LAN、tailnet 或 wss://),要么是信令代理上需邀请才能加入的房间,由该代理转发密封帧。这里没有 点对点的数据通道。

已配对的手机只能触达服务器表面里很小、且有意划定的一块:

  • 读取工单、智能体、空间及其消息,以及你的新闻流
  • 回复:在空间中发送消息、更新或分配工单、把文章标为已读或已保存
  • 运行剧本:用参数实例化一个已保存的计划模板。它只会_提出_一个计划;在 操作者在完整客户端的 Plan Studio 中批准之前,不会有任何执行或花费
  • 切换工作区,在手机自己的选择器里

大致就这些。相比完整客户端,手机是权限更低的主体。它不能启动进程、消耗 LLM 预算、推送到 GitHub,也不能创建工作区。它为何是被真正强制执行而不只是设计 意图,见访问模型。

连接依托一条经代理中转的中继:服务器作为所有者加入 wss:// 代理上一个 需邀请才能进入的房间,而每个已配对客户端——桌面端、Web、手机——都凭一个有期限 的准入令牌加入同一个房间。有三部分共同起作用:

组成部分 作用
Remote(手机应用) 伴侣 Web 应用,默认托管在 remote.usectrl.dev,也可自托管。它在浏览器中加载,把配对记录保存在 IndexedDB 中。
中继代理 一条无状态的 wss:// 中继(cc_signaling_server),托管 N 方房间。它只承载不透明的帧:每个负载都在手机与服务器之间端到端密封,因此代理既看不到应用数据,也看不到配对密钥,更不会解释它转发的任何内容。
cc_server 房间的所有者。它通过其他所有客户端所用的同一个调度器来应答手机的调用。

一次配对邀约携带一个连接描述符,列出通往服务器的每条路径(LAN、tailnet、 公共 wss://、中继)以及服务器的身份指纹。手机的解析器会选出最好的可达路径, 并在首次连接时固定该指纹(TOFU);即使不存在直连路径,中继也能保证连通,同时 始终无法读取流量。

配对凭据由应用生成,并以深链接的形式交付;具体步骤见 配对设备。这里重要的是它的结构。

https://<pwa-host>/#<payload>

负载位于 URL 的片段中,也就是 # 之后、浏览器从不发给服务器的那一段,因此 PWA 的 HTTPS 主机也看不到它。它携带了手机访问服务器并证明自己身份所需的一切: 连接描述符(每条路径加上身份指纹)、一个新生成的设备 id、一个 32 字节的预共享 密钥,以及一个过期时间戳。手机会解码它,在本地保存配对记录,并去掉片段,让密钥 从 URL 中消失。

负载有两种形态,二者不可互换。从应用内配对面板生成的手机二维码就是上面那种 v2 PairingPayload,指向 Remote PWA 主机。cc_server pair --client-url 发出的 是另一种更旧的 v1 链接({s, i, k} —— 服务器 URL、设备 id、密钥),只面向 Web 客户端。

两者的有效期也不同,这一点很容易搞错:

生成方式 凭据有效期
应用内配对面板(pairing.mint) 始终为 30 天
命令行上的 cc_server pair 无 —— 凭据不会过期

已配对的设备是经过身份验证但不受信任的。若干相互独立的关卡,让一次获批 (或泄露)的配对不会变成对服务器的完全控制。

有效的配对密钥只能证明你是_哪台设备_。你可以读取或修改什么,由你的工作区 角色决定——每次调用都会重新解析——凡涉及仓库内容的操作,还要看按仓库授予的 权限。设备持有完全有效的密钥,但其所属用户不是所指定工作区的成员时,会被拒绝并 提示 “Not a member of this workspace”。

角色下限由操作的类型推导,除非操作自己声明:读取需要 guest,变更需要 member,破坏性操作需要 admin。

除角色检查之外,手机会话所携带的能力也低于桌面端或 Web 会话。声明为仅限完整 客户端的操作,会在处理程序运行之前就对手机拒绝,无论其背后的用户权限多高:生成、 列出、重命名和吊销设备配对;读取和设置隧道连接;服务器备份与工作区导出/导入; 进程检测与终止;适配器探测;服务器设置;SSO 管理;机群控制;以及接管或交回 正在运行的智能体。

具体到 MCP 工具面(tools/call),哪些工具可以被手机调用,由一份默认拒绝的 允许列表决定。未列入的工具在运行之前就会被拒绝。这份列表以读取和观察为主,另加 少量仅限本地的写入——一条消息、一次工单更新、一个文章标记——它们不消耗 LLM 预算、不启动进程,也不接触任何外部系统。

例如被拒绝的有:向智能体咨询、启动 AI 审查、终止智能体、把审查发布到 GitHub、 招聘或解雇智能体、创建工作区。

服务器不保存“当前工作区”。它按设计是无状态的:每个以工作区为作用域的调用 都必须在其参数中给出目标的 workspace_id,一旦缺少该参数,或它指向一个服务器 未注册的工作区,调度器就会直接拒绝这次调用——这发生在任何数据库被打开之前。 因此手机永远无法继承或漂移到另一个客户端的作用域,指定一个外来的工作区也没有用, 因为第 1 道关卡里的成员身份检查仍然适用。这与产品其余部分强制执行的 工作区隔离是同一个不变式。

5. 以预共享密钥为密钥的端到端密封帧

标题为“5. 以预共享密钥为密钥的端到端密封帧”的部分

手机与服务器之间的每一帧都用配对密钥密封;准入令牌只能让客户端进入房间,它不 解密任何东西。代理转发的只是密文,永远看不到密钥。已吊销的设备会发现自己的凭据 早已消失,因此它在重新连接时失败即关闭。

由应用生成的凭据有 30 天的期限;超过之后,连接关卡会判定它失败,手机必须重新 配对。吊销是实时的:服务器监视设备表,会在几秒内断开已吊销设备的现有会话,而不是 等它下次连接。

滑动窗口限流器把远程工具流量限制在每分钟 120 次调用,并对变更类操作再加一个更严 的每分钟 30 次子上限。配额属于主体,而不是会话:你的三台设备共用同一份额度, 因此被劫持的客户端无法通过多开会话来换取余量,一个吵闹的成员也无法让其他人挨饿。

中继代理被刻意做得笨拙:它托管房间、转发密封帧,不保存任何账户、应用数据或密钥。 房间需邀请才能加入,而且是临时的。应用数据、音频、转录、源代码和凭据全都留在 服务器上。

配对之后,手机会以通知帧的形式收到实时更新——新的智能体消息、分配给你的工单、 状态变化——与桌面端自己的通知如出一辙。服务器把这些帧广播给每个已连接的会话, 工作区过滤在客户端一侧应用,因此你看到的内容被限定在你正在查看的那个工作区。

界面 显示内容
设置 → 你 → 你的设备(/workspaces/:workspaceId/settings/you/devices) 已配对客户端及其实时状态,另有配对新客户端(网页浏览器、桌面应用或手机)和吊销

同一个面板也能为第二个浏览器或桌面应用生成配对,并不只限于手机——流程完全相同, 只有深链接不同。