# 远程桌面主机 一台服务器集中运行 Web(15300)与 Hermes(9119),其他 Mac 安装夭夭 App 后作为”桌面主机”出站连接服务器,向服务器上的 Bot 提供自己的真实桌面(截图、键鼠、独立浏览器)。服务器自己机器上的 App 继续走本机回环通道,等同一台编号为 `local` 的主机。 ## 服务端执行与统一权限 所有 Bot 的聊天、模型、配置、记忆提炼都运行于服务端 Hermes。客户端 App 只负责界面和已授权的电脑操作,无需安装 Hermes。虚拟机 Runner 只在调用 `computer_*` 时建立工具会话;虚拟机离线不会转移聊天,也不会让普通聊天启动虚拟机。 电脑开放范围与审批策略在 Bot 设置统一管理,默认开放服务器、客户端电脑、Grok Bot 云电脑和虚拟机。旧 Bot 的 `computer`、`execution`、`envs`、`approvalPolicy` 不再决定实际设备权限或模型运行位置。旧虚拟机共享关系保留,任务助手仍受所属任务的生命周期约束。 - **消息来源**:客户端每次发送时重新读取 `deviceHost`,服务端保存到消息和运行。省略 `host` 或使用「本机」/`local` 时,只解析为本轮来源电脑;切换客户端后新消息覆盖来源,已经运行的任务保留自己的来源快照。 - **明确目标**:`desktop_*` 的 `host` 可指定电脑名称或编号;`server` /「服务器」固定指服务器。重复名称需要用编号。来源未知、离线或全局关闭时明确报错,不用旧消息、Bot 绑定或其他在线机器兜底。普通浏览器未提供可控设备身份时须点名目标。 - **协作与定时任务**:Bot 转交、子任务和结果回传继承触发消息的来源。定时任务保存自己的「本机」目标,重启或换客户端查看不会改变它;旧任务未保存目标时须在内容中明确指定。 - **并行环境**:同一 Bot 可在一轮中操作多个环境。连接、系统授权和人工接管状态按设备校验,不按 Bot 区分权限。文件与命令授权不依赖屏幕录制或辅助功能。 - **审批**:所有 Bot 共用「询问我 / 自动允许 / 自动拒绝」,变更用于后续审批请求;已等待的请求单独答复。聊天中的允许只作用于本次,旧客户端的 `auto` 答复也只允许一次。 - **Hermes 原生工具**:原生终端和文件工具始终操作服务器,与消息来源无关;访问来源客户端应使用 `desktop_*`。全局服务器电脑开关控制 desktop 适配器,旧 `denyServerTools` 字段停用,不再展示未接入的封禁开关。 - **接管界面**:`/api/app/agents/:id/computer` 系列接受 `backend=desktop|cloud|vm`,桌面可附带 `host`。界面显式选择目标。此处的 `host=local` 是历史 API 的服务器编号,不等于 Bot 工具中随消息变化的别名。 ## 启用流程 1. 在那台 Mac 上启动夭夭 App。**首次启动会询问这台 Mac 的使用方式:「连接服务器(客户端)」或「作为服务器运行」,默认选择客户端**。 - 选「连接服务器」:弹出登录窗口,填写**夭夭服务器地址(如 `192.168.1.10:15300`)、用户名和密码**。登录成功后窗口直接使用远程服务器的夭夭界面(本机不运行 Web 服务);用**管理员账号**登录时,App 会自动把这台 Mac 注册为远程桌面主机(令牌经系统钥匙串加密保存在数据目录 `desktop-host.enc`,0600),无需任何配置文件。非管理员账号只登录界面,并提示需要管理员账号才能注册本机控制。 - 选「作为服务器运行」:在这台机器运行 Web,并连接这里配置的 Hermes。 - 勾选「记住选择,之后启动不再询问」会把选择写入偏好(`startupChoice`);也可在菜单「桌面主机 → 启动时询问使用方式」恢复每次询问。 2. 后续启动直接进入远程模式;若登录会话已过期,App 会重新弹出登录窗口(服务器地址已预填)。会话 Cookie 保存在 App 的会话存储中,密码不落盘。使用中可随时通过菜单「桌面主机 → 登录远程服务器… / 作为服务器运行」切换;「忘记配置」会移除本机的桌面主机凭据,下次登录时重新注册。 3. 服务器管理侧(可选):「设置 → Hermes 连接 → 桌面主机」列出各台已注册主机(在线状态、机器名、最后在线)并可停用;停用立即断开那台 Mac。手动注册并下载 `desktop-host.json` 仍可用于不便登录的机器(菜单「桌面主机 → 导入主机配置…」),但常规流程不再需要。 4. 管理员在全局设置中开放电脑类型,在聊天右侧电脑面板查看各台电脑的连接与授权状态;无需为各 Bot 单独勾选环境或绑定默认执行机。 5. 首次授权:管理员点「在桌面端授权」,那台 Mac 弹出原生授权对话框;确认后引导开启屏幕录制与辅助功能。授权按账号哈希(ownerKey)记录在各 Mac 的 `computer-permissions.json`,各机独立;菜单「撤销本机控制授权」同时作用于本机与远程通道。 ## 文件与命令(全面操作) 屏幕授权之外是独立的第二档授权「文件与命令」:电脑面板直接提供「授权文件与命令」按钮,无需先完成屏幕授权,Mac 端弹窗单独确认。授权后该账号下所有机器人获得四个工具: - `desktop_file_list` / `desktop_file_read` / `desktop_file_write`:在这台 Mac 的**用户主目录**范围内列目录、读文件(≤12MB)和写文件(≤10MB);`..`、绝对路径越界和符号链接逃逸都会被拒绝,TCC 保护目录仍按系统权限处理。 - `desktop_shell`:在主目录执行一条 zsh 命令(最长 120 秒,stdout/stderr 各截断 512KB,超时终止并如实报告)。 两档授权分别记录(`approved` 与 `approvedFull`),「撤销本机控制授权」同时清除;工具目录按账号下可用设备的授权汇总,且每次调用在服务端二次校验。 ## 传输与边界 - 机器端点 `POST /api/desktop-host/v1//exchange`:Bearer 令牌(sha256 后 timingSafeEqual)+ `x-desktop-host-protocol: 1`;拒绝任何携带 Origin 的请求,不进入用户会话、CSRF 或 CORS 体系;Host 白名单照常生效。 - 交换协议沿用桌面端 `{host, results} → {commands}` 格式:每轮最多 8 条命令、20 条结果,请求体上限 24MB。App 成功后 400ms 轮询,网络错误指数退避至 5s;令牌失效(401/403)即停止并提示重新导入。 - 每台主机独立持有命令队列、截图缓存、接管凭据与授权状态;宿主 epoch(App 每次启动/撤销时轮换的 host.id)变化即围栏在途命令。人工接管的 generation/epoch/30 秒续期语义与单主机时一致,接管记录以 `desktop::` 区分。 - 远程明文 HTTP(服务器地址以 `http://` 登录)时,App 保存的主机配置自动带 `allowInsecureLan: true`,与 Runner 规则一致;公网部署应使用 HTTPS 并把域名加入外网访问地址。登录凭据只走该服务器地址,密码不落盘。 - 停用主机立即断开那台 Mac 并围栏其在途命令;配置丢失时停用并重新注册,旧令牌不能恢复。 ## 范围 - 物理机控制仅支持 macOS(屏幕录制、辅助功能与 computer-helper 签名校验均为 macOS 专属)。 - 本功能只提供真实桌面与独立浏览器环境;远程机器上的 Linux 虚拟桌面(无 Hermes 电脑节点)不在本范围。 - 服务器侧 Bot 会话、模型与记忆全部留在服务器的 Hermes;卫星机不安装 Hermes。 ## 验证 - 服务端:`tests/server/desktopHosts.test.ts`(注册令牌一次性、准入与协议头、撤销围栏)、`tests/server/desktopEnvironments.test.ts`(消息来源解析、离线不回退、全局权限、文件与屏幕授权独立、并发来源隔离、按机围栏)。 - App:`desktop/remote-login.test.mjs`(地址归一化、账号密码登录的 CSRF/Origin 往返、管理员注册桌面主机、错误路径)、`desktop/host-files.test.mjs`(目录内列/读/写、路径与符号链接逃逸拒绝、命令退出码/超时/工作目录)、`desktop/host-manager.test.mjs`(配置校验、加密导入、交换往返、403 停止、退避重试)、`desktop/preferences.test.mjs`(启动选择与远程地址偏好持久化)。启动选择/登录窗口需按上述流程手工验收(自动化桌面测试通过 fixture 环境固定走本地路径)。 - 浏览器:`tests/e2e/desktop-hosts.spec.ts`(注册/下载/停用;模拟远程主机连接与电脑面板状态)。真实多机链路需按上述流程手工验收。