mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-09 04:30:20 +08:00
284 lines
14 KiB
Markdown
284 lines
14 KiB
Markdown
# aether-vscodex
|
||
|
||
这个项目让浏览器从本机 URL 或 Aether 云端查看、输入并处理 Codex 会话,提供两种
|
||
可随时切换的控制模式。默认的**同步模式**通过官方扩展使用的本机 IPC socket,严格
|
||
跟随 VS Code Codex 面板当前会话,不启动另一个 `codex` 进程;**异步模式**由伴随扩展
|
||
启动独立 app-server,网页可以自行列出、恢复、新建和切换会话。
|
||
|
||
同一个伴随扩展可同时连接两个互不替代的通道:本机 loopback 控制台和部署在
|
||
Aether 中的云端控制台。本机通道默认免密码且只能从本机访问;云端通道使用
|
||
Aether 登录鉴权、一次性浏览器票据和独立设备凭据;父页面不会通过协议把 Aether JWT
|
||
传给 iframe 或 Node sidecar。iframe 是随 Aether 一起发布的同源受信代码,不应被视为
|
||
隔离不受信内容的安全边界。
|
||
|
||
`vscode-extension/codex-remote-collab-0.4.0.vsix` 安装到 VS Code 后,会作为官方
|
||
`openai.chatgpt` Codex 扩展的伴随扩展,并自动托管只监听本机的 relay。开发时仍可
|
||
单独运行 `relay/server.js`。不要卸载或替换官方 Codex 扩展。
|
||
|
||
## 工作方式
|
||
|
||
```text
|
||
官方 VS Code Codex 会话
|
||
│ 本机私有 IPC(只在 VS Code 所在机器上)
|
||
▼
|
||
┌── 本机 relay ── http://127.0.0.1:8787
|
||
VS Code aether-vscodex 扩展 ────┤
|
||
└── Aether gateway ── 用户/设备隔离的云端 relay
|
||
```
|
||
|
||
控制模式与传输通道是两个独立维度:切换同步/异步不会重连本地或云端 relay。本机和
|
||
Aether 控制页连接到同一台 VS Code 主机时,会看到同一个当前模式。
|
||
|
||
| 控制模式 | 会话所有者 | 网页会话导航 |
|
||
| --- | --- | --- |
|
||
| 同步 | 官方 VS Code Codex 面板 | 禁止网页自行切换;自动跟随 VS Code |
|
||
| 异步 | 扩展启动的独立 app-server | 可列出、恢复、新建和切换会话 |
|
||
|
||
浏览器的 `operator` 可以发送任务、继续/中断当前 turn,并处理 Codex 的审批、
|
||
用户输入和 MCP elicitation;`viewer` 只能查看事件和输出。远程浏览器不接触
|
||
VS Code 的 SecretStorage,也不直接连接 IPC socket。
|
||
|
||
## 前端结构
|
||
|
||
Aether 页面使用仓库既有的 Vue 3、TypeScript、Vite 和 i18n。独立控制台也提供
|
||
Vue/Vite 源码入口,但当前高保真的会话渲染与协议状态机作为兼容运行时保留,构建到
|
||
`public/` 后同时供本机 URL 和 Aether 同源 iframe 使用。这样不需要一次性重写并丢失
|
||
命令展开、滚动锚点、思考状态、Markdown、子代理、模型和权限菜单等已有行为。
|
||
|
||
界面支持 `zh-CN` 与 `en-US`。Aether 的语言和深浅色主题会通过经过来源校验的
|
||
`postMessage` 同步给 iframe;VS Code 命令与设置说明使用 `package.nls` 本地化。
|
||
|
||
## Aether 云端部署
|
||
|
||
云端模式由 Aether gateway 和独立 Node sidecar 组成。sidecar 只在 Compose 内网暴露
|
||
8788,公网的 HTTP、配对交换和 WebSocket 都经 Aether gateway:
|
||
|
||
```text
|
||
GET /api/users/me/vscodex/devices
|
||
POST /api/users/me/vscodex/pairings
|
||
DELETE /api/users/me/vscodex/devices/:device_id
|
||
POST /api/users/me/vscodex/ws-tickets
|
||
POST /api/vscodex/pair
|
||
WS /api/vscodex/ws
|
||
```
|
||
|
||
生成至少 32 字节的内部令牌,并按 Aether 的公开 HTTPS 地址设置变量:
|
||
|
||
```sh
|
||
export AETHER_VSCODEX_INTERNAL_TOKEN="$(openssl rand -base64 32)"
|
||
export AETHER_VSCODEX_PUBLIC_WS_URL="wss://aether.example.com/api/vscodex/ws"
|
||
export AETHER_VSCODEX_ALLOWED_ORIGINS="https://aether.example.com"
|
||
|
||
docker compose \
|
||
-f docker-compose.yml \
|
||
-f docker-compose.local.yml \
|
||
-f aether-vscodex/docker-compose.aether.yml \
|
||
up -d --build
|
||
```
|
||
|
||
源码部署必须包含 `docker-compose.local.yml`,以保证 gateway、前端和 sidecar 来自同一份
|
||
checkout。使用发布镜像时可以去掉该文件,但 `APP_IMAGE` 必须固定为包含相同
|
||
`aether-vscodex` 协议版本的 Aether 镜像,不能把当前 sidecar 与旧的 `latest` gateway 混用。
|
||
|
||
首次使用源码 Compose 前先构建控制台;正式 Aether 发布流程与 Dockerfile 已自动执行
|
||
同一步骤:
|
||
|
||
```sh
|
||
npm --prefix aether-vscodex/web ci
|
||
npm --prefix aether-vscodex/web run build
|
||
```
|
||
|
||
第一阶段 sidecar 是有状态单副本:设备凭据的 scrypt 哈希保存在
|
||
`vscodex_data`,短期配对码、60 秒一次性浏览器票据和在线房间保存在内存。不要在未引入
|
||
共享连接目录前横向扩容 sidecar。
|
||
|
||
登录 Aether 后打开“远程控制”,生成一次性配对码。然后在 VS Code 命令面板执行
|
||
**Codex Remote: Pair with Aether**,填写 Aether 地址和配对码。插件会把设备凭据写入
|
||
VS Code SecretStorage,并同时保持本机控制台连接。
|
||
|
||
## 快速开始
|
||
|
||
前提:Node.js 20+;官方 `openai.chatgpt` VS Code 扩展已安装并登录;目标会话
|
||
已经在 VS Code 的 Codex 面板中打开。VS Code 和 relay 必须以同一个操作系统用户
|
||
运行,因为 IPC socket 是本机文件。
|
||
|
||
1. 安装依赖并构建伴随扩展:
|
||
|
||
```sh
|
||
npm --prefix vscode-extension install
|
||
npm --prefix vscode-extension run build
|
||
```
|
||
|
||
本机 `ws://` 地址会由扩展自动启动 relay;loopback 模式默认不需要 token,且
|
||
`host` 模式不会启动 `codex app-server`。
|
||
|
||
2. 安装 `vscode-extension/codex-remote-collab-0.4.0.vsix`(或在扩展目录先
|
||
`npm run build` 再用 `npx --yes @vscode/vsce package` 打包),然后在 VS Code
|
||
执行 **Developer: Reload Window**。
|
||
|
||
3. 在 VS Code 设置中填写:
|
||
|
||
```json
|
||
{
|
||
"codexRemoteCollab.localRelayUrl": "ws://127.0.0.1:8787/v1/connect",
|
||
"codexRemoteCollab.controlMode": "sync",
|
||
"codexRemoteCollab.autoDiscoverThread": true,
|
||
"codexRemoteCollab.autoStart": true
|
||
}
|
||
```
|
||
|
||
4. 执行一次 **Developer: Reload Window** 后,扩展会自动找到最近的、仍由官方
|
||
VS Code Codex owner 持有的会话,并把已有输出同步到 relay;如果没有自动启动,
|
||
无需手动启动或断开。右下角状态项只用于显示状态并打开 Web。需要精确指定会话时,执行
|
||
**Codex Remote: Set Existing Thread ID**;留空则恢复自动发现。
|
||
官方 Codex 面板切换会话时,Web 默认会在新会话快照就绪后自动跟随;正在执行或等待
|
||
授权的旧会话会先保持附着,结束后再安全切换。
|
||
|
||
5. 浏览器打开 `http://127.0.0.1:8787`,页面会自动以本机 operator 身份连接,
|
||
不需要输入密码。
|
||
|
||
如果页面显示“等待 VS Code 主机连接”,先确认 relay 地址与扩展设置的端口完全一致,
|
||
然后在 VS Code 执行一次 **Developer: Reload Window**。同步模式必须在官方 Codex
|
||
面板已经打开至少一个会话后才能发现 owner;通常不需要手工填写
|
||
`codexRemoteCollab.threadId`,留空会自动选择最近的可用会话。若之前填写过已经关闭的
|
||
thread ID,清空该设置后再重载窗口。
|
||
|
||
### 发布与下载插件
|
||
|
||
正式发布时不需要用户在本地编译。仓库的 `.github/workflows/release.yml` 在推送
|
||
`vX.Y.Z`、`vX.Y.Z-beta.N` 或 `vX.Y.Z-rc.N` 标签时,会在 GitHub Actions 中完成 Web
|
||
前端构建、扩展编译和 VSIX 打包,并把
|
||
`aether-vscodex-<extension-version>.vsix` 附加到对应的 GitHub Release。用户从 Release
|
||
页面下载该 VSIX,在 VS Code 的扩展视图中选择“从 VSIX 安装...”即可;安装后执行一次
|
||
**Developer: Reload Window**。
|
||
|
||
手动运行该 workflow 时,VSIX 会作为 `aether-vscodex-vsix` Actions artifact 提供下载,
|
||
但不会创建 GitHub Release。源码目录中的 VSIX 只用于本地开发验证,不是用户发布渠道。
|
||
|
||
如果命令面板提示 `command 'codexRemoteCollab.start' not found`,通常是旧版
|
||
VSIX 激活失败(旧包可能没有包含 `ws` 运行依赖)。请安装当前的
|
||
`codex-remote-collab-0.4.0.vsix` 并使用 `--force` 覆盖旧版本,然后执行一次
|
||
**Developer: Reload Window**:
|
||
|
||
```sh
|
||
code --install-extension vscode-extension/codex-remote-collab-0.4.0.vsix --force
|
||
```
|
||
|
||
也可以在 **Output → Codex Remote Collaboration** 中确认没有
|
||
`Cannot find module 'ws'`;出现该错误时,说明扩展尚未成功激活。
|
||
|
||
网页现在按官方 Codex Webview 的会话模型展示:历史和实时输出在中间消息流,用户、
|
||
助手、reasoning、命令输出分别投影为对应的消息项;助手内容支持安全的 Markdown、
|
||
代码块和复制操作,reasoning/命令活动可折叠。底部 composer 使用可编辑富文本区域,
|
||
回车发送、Shift+Enter 换行;审批和用户输入会以内嵌 card 出现在会话流中,支持风险
|
||
标记、输入控件、授权范围和明确的允许/拒绝动作。附着适配器会额外发送可选的
|
||
`messages` 角色投影,旧版 host 没有该字段时网页仍回退到纯文本快照。
|
||
|
||
页面打开后自动连接并在断线后重连,不再需要手动点击“连接”或“断开”。同步模式下
|
||
会话列表、返回历史和新建入口会被禁用,所有输入都发送到 VS Code 当前会话。这里复刻的是从本机已安装
|
||
官方 bundle 审计出的布局、状态和交互;官方 bundle 依赖 VS Code 私有 Webview API,
|
||
不能安全地直接作为 iframe 嵌入浏览器。
|
||
|
||
底部的“同步 / 异步”分段控件发送 `control/mode/set`。当前 turn 正在执行或存在待处理
|
||
授权、用户输入时,主机拒绝切换;候选适配器启动失败时保留原模式和原会话。切入异步
|
||
模式后,页面顶部会恢复会话历史、新建和选择入口;`session/list` 映射到
|
||
`thread/list`,选择会话使用 `thread/resume` 并水合完整历史,新建会话使用
|
||
`thread/start`。切回同步模式会关闭独立 app-server,并重新以 VS Code 面板为唯一
|
||
会话导航来源。
|
||
|
||
### 认证(可选)
|
||
|
||
如果以后需要保护 relay,可显式开启认证;本机流程默认不需要这些变量:
|
||
|
||
```sh
|
||
CODEX_REMOTE_AUTH=required \
|
||
CODEX_REMOTE_HOST_TOKEN='host-only-secret' \
|
||
CODEX_REMOTE_TOKEN='browser-operator-secret' \
|
||
CODEX_REMOTE_VIEW_TOKEN='browser-viewer-secret' \
|
||
CODEX_REMOTE_MODE=host npm start
|
||
```
|
||
|
||
认证开启后,Host token 填在 VS Code 扩展中,Operator/Viewer token 填在浏览器中。
|
||
|
||
## `spawn codex ENOENT` 是什么
|
||
|
||
这个错误只表示某处正在尝试启动**独立**的 `codex app-server`,但 VS Code 图形
|
||
进程的 `PATH` 找不到可执行文件。对于本项目默认的同步模式,不会调用
|
||
`spawn codex`,因此不需要通过设置 `codexCommand` 来修复它。
|
||
|
||
只有切换到异步模式(或仍使用旧版兼容设置)才需要独立可执行文件:
|
||
|
||
```json
|
||
"codexRemoteCollab.controlMode": "async"
|
||
```
|
||
|
||
扩展会优先解析 `codexRemoteCollab.codexCommand`,并可回退到官方 Codex 扩展内置的
|
||
可执行文件;`codexRemoteCollab.codexArgs` 默认是 `["app-server", "--stdio"]`。
|
||
旧 `mode=attach/spawn` 会分别迁移为 `sync/async`。
|
||
|
||
## Relay 模式
|
||
|
||
### `host`(推荐)
|
||
|
||
relay 只负责认证、事件缓存和转发;VS Code 扩展通过私有 IPC 附着官方 Codex
|
||
会话。必须先打开目标会话;本机 loopback 默认不需要 host token,只有显式开启认证时
|
||
才把 host token 提供给扩展。
|
||
|
||
### `embedded`(旧的独立进程模式)
|
||
|
||
只有显式设置 `CODEX_REMOTE_MODE=embedded` 时,relay 才会启动自己的
|
||
`codex app-server --stdio`,适合测试页面和公开 app-server 协议;它与 VS Code
|
||
当前会话无关:
|
||
|
||
```sh
|
||
CODEX_REMOTE_MODE=embedded CODEX_CWD="$PWD" npm start
|
||
```
|
||
|
||
`CODEX_BIN` 可指定独立进程的可执行文件;`CODEX_ARGS_JSON` 可覆盖其参数。不要
|
||
把这些设置误认为 attach 模式的必要配置。
|
||
|
||
## HTTP API
|
||
|
||
认证开启时,除 `/api/health` 外的 `/api/*` 都需要
|
||
`Authorization: Bearer <operator-or-viewer-token>` 或 `X-Codex-Token`;本机免认证
|
||
模式下 loopback 请求直接作为 operator 处理。
|
||
|
||
```text
|
||
GET /api/health
|
||
GET /api/state
|
||
GET /api/events?fromSeq=0
|
||
POST /api/command {"commandId":"...","method":"turn/start","params":{...}}
|
||
POST /api/respond {"requestId":"...","result":{...}}
|
||
```
|
||
|
||
host 模式下,同步控制会拒绝 `thread/start` 和网页会话导航;异步控制会把它们转给
|
||
独立 app-server。浏览器使用 `threadId` 发送 `turn/start`、`turn/steer` 或
|
||
`turn/interrupt`。认证开启时写操作和
|
||
响应请求必须使用 operator token;本机免认证模式下 loopback operator 可直接操作。
|
||
|
||
## 私有协议和限制
|
||
|
||
- IPC follower 协议是官方 VS Code 扩展的私有、带版本号实现,不是公开 API;官方
|
||
扩展升级后可能需要同步适配。启用 `codexRemoteCollab.ipcStrictVersions`
|
||
时,未知 stream 版本会让连接报错而不是猜测执行。
|
||
- 自动发现只把本地 rollout 元数据当作候选,最终仍通过 IPC owner discovery
|
||
验证;生产或多会话场景建议设置明确的 `threadId`。
|
||
- relay 默认只监听 loopback,且 loopback 默认免认证;这意味着同一台机器上能访问
|
||
loopback 的本地进程都可能控制会话,不要把它反向代理或暴露到外部。如果开启 token
|
||
认证,token 是 bearer secret。高风险授权默认被 host policy 拒绝,只有显式设置
|
||
`codexRemoteCollab.allowHighRiskApprovals=true` 才允许。
|
||
- 输出会做常见 token/密码脱敏,但不能识别所有秘密;不要把凭据发送给 Codex。
|
||
- 当前 UI 控制一个 host 会话,不提供多人同时编辑或文件同步。
|
||
|
||
## 测试
|
||
|
||
根目录测试使用假的 stdio app-server,不会向真实 Codex 发送任务:
|
||
|
||
```sh
|
||
npm test
|
||
cd vscode-extension && npm run check && npm run build
|
||
```
|
||
|
||
要验证真实附着,只读地打开官方 VS Code 会话后启动 bridge;不要在验证脚本中
|
||
调用 `turn/start`,除非你确实要向该会话发送任务。
|