第 13 章:CLI、移动端与插件平台
1. Runtime 把桌面产品变成平台
当 Git、PTY、browser、worktree 都只能通过 React UI 操作时,Orca 只是桌面应用。Runtime RPC 把它们变成可组合能力:
各客户端看见的 allowlist 不同,并不共享完全相同的权限。
2. CLI 的架构
CLI 入口 src/cli/index.ts 分四层:
- Command specs:命令树、positionals、flags、help;
- Parser/validator:在连接 runtime 前报告语法错误;
- Handlers:把 flags 变成领域 request;
- RuntimeClient:发现并连接 host,执行 RPC。
RuntimeClient 采用动态 import:--help 和 flag 错误不加载 zod、ws、tweetnacl 等 100 多个模块,改善 CLI 冷启动。
3. 命令规格是单一事实源
src/cli/specs/ 定义 account、worktree、terminal、browser、computer、automation、orchestration、environment、skills 等命令。help、flag validation 与 dispatch registry 做 parity 检查,避免文档中有命令、handler 却缺失,或反之。
4. Selector:脚本地址层
用户/Agent 不应手拼内部对象。CLI 支持:
id:<...>;path:<abs>;name:<display>;branch:<name>;active/current;folder:<id>/worktree:<id>。
selector 在 host 上解析,避免客户端拿旧 list 后用错误 path 操作。结果建议 --json,便于 Agent 读取稳定字段而不是解析人类表格。
5. Runtime 发现与 transport
CLI 可连接:
- 本机 runtime metadata 指向的 socket;
- 由
orca open/serve启动的 runtime; --pairing-code/ environment selector 指定的远端;- SSH relay bridge 注入的
ORCA_CLI_CWD。
命令如 account/environment/serve 强制 local,不接受环境变量偷偷切换到 remote,防止账户和主机管理误发另一台机器。
6. CLI 操作 terminal 的原则
Terminal handle 是 runtime-scoped。CLI:
- list/show/read 使用 cursor;
- send 支持 text、enter 和等待 TUI idle;
- create/split/close 由 host 维护 layout;
- stale handle 必须重新 list;
- 不向旧、新 handle 双写。
这让 Agent 可以用 orca 驱动另一个 Agent 或 browser,但仍走统一所有权裁决。
7. 移动端配对
移动端是 Expo/React Native 应用。首次配对:
配对 token 带 mobile 或 runtime scope。设备 registry、E2EE key 不可用时,server 返回明确 guidance,而不是生成弱 fallback。
8. Mobile session tabs 是 host 投影
手机不复制桌面 Zustand store。Host 发布 RuntimeMobileSessionTabsSnapshot:
- publication epoch、snapshot version;
- active group/tab;
- tab groups 与 layout;
- terminal/file/markdown/browser tab 的窄字段;
- Agent status、theme、view mode。
手机可以乐观切 tab,但 host snapshot 最终收敛。每个 device 还保存自己的 tab selection,因此两部手机无需争夺同一个 active tab。
9. 二进制 terminal stream
控制 RPC 用 JSON,PTY output 使用固定 16-byte header 的二进制帧:
| Opcode | 用途 |
|---|---|
| Output / OutputSpan | live bytes |
| SnapshotStart/Chunk/End | 分块恢复 |
| Input / Resize | 客户端交互 |
| Subscribe/Unsubscribe | stream 生命周期 |
| Ack | flow control |
| ClaimViewport | driver ownership |
| SetOutputPaused | 协商暂停 |
JSON payload 仍有 8MB 和结构 token/depth 上限。协议定义见 terminal-stream-protocol.ts。
10. Driver ownership
同一个 PTY 可能同时被桌面和手机观察,但键盘/resize 需要一个 driver。状态为 idle、desktop 或 mobile(clientId)。ClaimViewport 防止两端尺寸和输入同时争夺。
观察者仍可收输出;driver 才控制 viewport 与交互。
11. 移动端内部结构
mobile/src 按能力拆分:
transport:pairing、WebSocket、RPC;session:tab snapshot 与 mutation;terminal:xterm WebView engine;worktree、files、source-control;browser、tasks、notifications;storage/cache:离线与设备状态。
React Native 负责 native shell,终端 engine 仍复用 xterm 能力,通过 WebView/构建脚本封装。
12. 插件 manifest 与贡献点
插件 manifest 声明:
- id、version、Orca engine range;
- capabilities;
- commands;
- panels;
- event subscriptions;
- 可选 skills、VM recipe 等资产。
所有 id、相对路径、贡献数量都有 schema 和上限。__proto__ 等危险名称被拒绝,Windows 设备名/非法字符也经过 path safety 校验。
13. Plugin worker 隔离
插件代码运行在独立 host process/worker,不直接 import main 内部对象。协议包含:
- init / ready;
- invoke command / result;
- deliver event / ack;
- host call;
- log / fatal / shutdown。
worker 有 ready/invoke timeout、最大并发数与 idle reap。Capability consent 由用户确认,并对 capability fingerprint;manifest 变更后旧 consent 不能无条件沿用。
14. Plugin panel 隔离
Panel HTML 包装在固定 shell 与 CSP 中,通过 postMessage bridge 调 host action。安全措施包括:
- frame name 与 session token;
- 64KB message 上限;
- 速率限制;
- 独立 control-message budget;
- ping/pong watchdog;
- 参数 schema;
- 设计 token allowlist。
Panel 不能因为运行在 Orca 窗口里就获得 preload API。
15. Marketplace、签名与 kill list
Plugin marketplace service 负责目录与安装;installer 验证 manifest、路径和版本。远端 kill list 可按 plugin key/version 禁用已知危险版本,并检查时间是否异常超前。
kill list 是紧急制动,不替代初始 capability 与 sandbox 设计。
16. 三种扩展方式的取舍
| 方式 | 最适合 | 权限 |
|---|---|---|
| CLI | 自动化脚本、Agent 驱动 | runtime allowlist |
| Mobile | 人类远程观察/操控 | mobile device scope |
| Plugin | 产品内长期扩展 | manifest capabilities + consent |
CLI 是进程外即时调用,插件是长期驻留扩展,手机是受限远程客户端。共用 runtime 语义,但不应共用信任级别。
17. 源码导航
- CLI specs:
src/cli/specs/ - CLI client:
src/cli/runtime-client.ts - WebSocket transport:
src/cli/runtime/websocket-transport.ts - Mobile:
mobile/src/ - Plugin manifest:
src/shared/plugins/plugin-manifest.ts - Plugin service:
src/main/plugins/plugin-service.ts - Panel bridge:
src/shared/plugins/plugin-panel-bridge.ts