# aws-runtime-bridge

AgentsWorkStudio 机器实例运行时桥接服务，用于在实例上管理 Agent 运行时、终端、配置与回调通信。

> `aws-runtime-bridge` 面向机器实例宿主机运行，需要访问本机工作区、终端、运行时配置和文件系统；不要将它作为 Docker/Compose 服务部署。Docker Compose 仅用于仓库根目录的 `aws-dashboard` 与 `aws-mcp-server` Web 服务。

## 全局安装

从 npm 包安装时：

```bash
npm install -g aws-runtime-bridge
```

安装脚本会在 macOS、Linux 与常见 Unix 平台自动为 CLI 入口补齐可执行权限；Windows 平台无需 chmod，会自动跳过该步骤。

> **Linux 编译工具链自动安装**：`node-pty`（终端 PTY）只为 macOS/Windows 提供预编译产物，Linux 上安装时必然现场编译，因此服务器需有 `g++`/`make`/`python3`。以 root 执行 `npm install -g`（或 `sudo npm install -g`）时，安装过程会自动用 `apt-get`/`dnf`/`yum`/`zypper`/`apk`/`pacman` 补齐工具链，无需手动干预；非 root 环境会提示手动执行 `sudo apt-get install -y build-essential python3`（按发行版对应命令）。可用 `AWS_BRIDGE_SKIP_BUILD_TOOLS=1` 跳过自动安装。

> **浏览器内核自动安装**：安装完成后会自动下载 Playwright Chromium（约 150MB，存于 `~/.cache/ms-playwright`），Linux 上以 root 安装（如 `sudo npm install -g`）时还会自动补齐系统依赖，装完即可使用浏览器功能。可用 `AWS_BRIDGE_SKIP_PLAYWRIGHT_INSTALL=1 npm install -g aws-runtime-bridge` 跳过；跳过或安装失败后，可随时手动执行：`npx playwright install chromium`（Linux 缺系统库时：`sudo npx playwright install --with-deps chromium`）。

从当前仓库安装时：

```bash
cd aws-runtime-bridge
npm install
npm run build
npm install -g .
```

## 启动

首次运行 `awsb` / `aws-bridge` 时，如果不存在 `~/.aws-bridge/config.json`，CLI 会进入交互式配置引导；也可以在提示中选择跳过。跳过时仍会创建配置文件并自动生成随机 `connectionKey`，终端会输出该密钥，请保存后在 server/面板连接此 Bridge 时使用。非交互环境（如 systemd、CI 后台启动）不会阻塞等待输入，也会自动生成随机 `connectionKey` 并跳过引导。

引导会生成类似下面的配置：

```json
{
  "connectionKey": "awsb_xxxxxxxxxxxxxxxxxxxxxxxx",
  "autoRegisterTargets": [
    {
      "serverUrl": "http://203.0.113.10:8080",
      "instanceName": "my-instance",
      "userKey": "aws_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
      "registerAddr": "127.0.0.1"
    }
  ]
}
```

### `registerAddr` 字段说明

`registerAddr` 用于告知调度中心如何回连本机 Bridge，支持三种写法：

| 写法 | 示例 | 解析结果 | 适用场景 |
| --- | --- | --- | --- |
| 完整 URL（含协议） | `https://bridge.example.com` | 原样使用 | Bridge 在反代后面或启用 TLS |
| `host:port` | `127.0.0.1:18081` | 自动补 `http://` 前缀 | http 直连 + 自定义端口 |
| 纯 `host` | `10.0.0.8` | 自动补 `http://` 前缀和 `AWS_RUNTIME_BRIDGE_PORT`（默认 18081） | http 直连 + 默认端口 |

> **TLS / 反代场景**：当 Bridge 部署在 Nginx/Caddy/Cloudflare 后面走 https 时，必须用完整 URL 形式（如 `https://bridge.example.com`），此时环境变量 `AWS_RUNTIME_BRIDGE_PORT` 不再生效。

> **向后兼容**：旧字段 `registerIp`（仅接受纯 IP）仍可读取，但已废弃，推荐迁移到 `registerAddr`。配置引导会在重新配置时自动将 `registerIp` 迁移为 `registerAddr` 并剥离老字段。

如需在交互式终端中也强制跳过引导，可设置 `AWS_BRIDGE_SKIP_SETUP=true`；此时仍会生成随机 `connectionKey`。

```bash
AWS_RUNTIME_BRIDGE_PORT=18081 \
AWS_RUNTIME_HOME_DIR=/opt/agentswork/runtime-home \
aws-bridge
```

当 `~/.aws-bridge/config.json` 只配置了一个 `autoRegisterTargets[].serverUrl` 时，bridge 会自动将该地址作为 `/runtime/ping` 回连调度中心的地址，无需重复配置 `AWS_RUNTIME_SCHEDULER_BASE_URL`。如需显式覆盖，或同一个 bridge 配置了多个自动注册目标，请设置 `AWS_RUNTIME_SCHEDULER_BASE_URL` 指定当前实例测试连接时应回连的调度中心。

If an existing runtime binding still stores an old scheduler URL such as `http://127.0.0.1:8080`, re-run auto-register, refresh the runtime token, or re-pair after changing `serverUrl` / `AWS_RUNTIME_SCHEDULER_BASE_URL`; bridge will not reuse a token issued for the old scheduler URL against the new scheduler URL.

`aws-runtime-bridge` 命令仍作为兼容别名保留。安装 `aws-runtime-bridge` 后，包内会随附
`aws-client-agent-mcp` 的编译产物；bridge 启动时只负责准备该 MCP 产物，不再在 Agent 启动时默认动态注入 `aws-mcp`。

请在面板中为目标运行时安装/配置 MCP；这样 Claude Code、Codex、OpenCode 等 SDK 启动模式都走一致的持久化 MCP 配置链路。

如需使用自定义 MCP 可执行文件，可设置：

```bash
AWS_CLIENT_AGENT_MCP_COMMAND=/absolute/path/to/aws-client-agent-mcp \
AWS_CLIENT_AGENT_MCP_ARGS='[]' \
aws-bridge
```

## 开发环境与生产环境

Bridge 区分两类运行形态，二者可在同一台机器上同时运行、互不干扰（适用于"用本项目开发本项目"的场景）：

| | 生产环境 | 开发环境 |
| --- | --- | --- |
| 启动方式 | npm 全局安装后 `awsb` / `node dist/index.js` / 系统服务 | 仓库内 `npm run dev` |
| 判定依据 | 无环境标记（默认即生产） | `scripts/dev-runner.mjs` 注入 `AWS_RUNTIME_ENV=development` |
| 运行主目录 | `~/.aws-bridge/` | `<仓库根>/.dev-home/.aws-bridge/` |
| 首选端口 | `18081` | `28081` |
| MCP 服务名 | `aws-mcp` | `aws-mcp-dev` |

行为要点：

- **数据隔离**：开发态的全部持久化数据（config.json、自动注册目标、面板凭据、IP 访问控制、日志、实例状态、mcp/acode 部署目录等）都落在仓库根 `.dev-home/` 下（已加入 `.gitignore`），不碰已安装实例的 `~/.aws-bridge/`；删除 `.dev-home/` 即可完全重置开发环境。
- **Agent CLI 配置保持共享**：`~/.claude`、`~/.codex`、`~/.opencode` 等 Agent CLI 配置在两种环境下都使用真实用户主目录——开发态 Bridge 拉起的也是真实 Agent 进程。MCP 服务名按环境区分（`aws-mcp` / `aws-mcp-dev`），两个实例写入 Agent 配置的条目并存，互不顶掉线。
- **端口错开**：两环境首选端口不同（冲突时仍会自动顺延），保证同时监听、地址可预期。
- **显式覆盖优先**：设置 `AWS_TEST_HOME` 或 `AWS_RUNTIME_HOME_DIR` 时，无论何种环境都使用该目录，测试与系统服务部署行为不受影响。
- **注意**：在仓库内直接执行 `npm start` / `node dist/index.js` 视为生产环境（与已安装实例共用 `~/.aws-bridge/`），需要隔离时请使用 `npm run dev`。

## systemd 服务管理

Linux systemd 环境中可使用 CLI 安装或卸载 `awsb.service`。安装命令会写入 systemd unit、执行 `systemctl daemon-reload`、启用开机自启，并在服务尚未运行时立即启动：

```bash
sudo awsb service install
```

卸载命令会在服务运行时先停止服务，禁用开机自启，删除 unit 文件，并重新执行 `systemctl daemon-reload`：

```bash
sudo awsb service uninstall
```

`service` 命令还支持 `start` / `stop` / `restart` 子命令，分别对应 `systemctl start/stop/restart awsb.service`。生成的 unit 会设置 `AWS_BRIDGE_SKIP_SETUP=true`，避免后台服务启动时阻塞在交互式配置引导。

## macOS launchd 服务管理

macOS 环境中可使用同一套 `awsb service` CLI 安装或卸载用户级 LaunchAgent（无需 `sudo`）。安装命令会生成 plist 文件写入 `~/Library/LaunchAgents/com.agentsworkstudio.awsb.plist`，并通过 `launchctl bootstrap` 加载启动：

```bash
awsb service install
```

卸载命令会执行 `launchctl bootout` 停止并卸载服务，然后删除 plist 文件：

```bash
awsb service uninstall
```

其他子命令与 launchctl 的对应关系：

| 子命令 | 行为 |
| --- | --- |
| `start` | 先尝试 `launchctl kickstart`（已加载未运行时启动），失败再 `bootstrap` 重新加载 |
| `stop` | `launchctl bootout` 卸载并停止（保留 plist，下次 `start` 重新加载） |
| `restart` | `launchctl bootout`（忽略错误）→ `launchctl bootstrap` 重新加载 |

生成的 plist 配置要点：

- `RunAtLoad=true`：加载时立即启动；
- `KeepAlive=true`：进程退出后自动拉起；
- `AWS_BRIDGE_SKIP_SETUP=true`：避免后台服务阻塞在交互式配置引导；
- `AWS_RUNTIME_HOME_DIR`：注入当前用户主目录，确保服务读到 `~/.aws-bridge/config.json`；
- `StandardOutPath` / `StandardErrorPath`：日志输出到 `~/.aws-bridge/log/awsb.out.log` 与 `awsb.err.log`，可用 `awsb log` 读取。

> 注意：因 `KeepAlive=true`，`stop` 通过 `bootout` 卸载服务才能真正停止；仅发信号会被 launchd 立即拉起。`stop` 后 plist 仍保留，`start` 会重新 `bootstrap` 加载。

## Windows 服务管理

Windows 环境中可使用同一套 `awsb service` CLI 通过 [node-windows](https://github.com/coreybutler/node-windows)（随包作为可选依赖安装）注册系统服务。安装命令会用 node-windows 注册服务（SCM 服务名 `awsb.exe`），并调用 `sc.exe start` 启动：

```bash
awsb service install
```

卸载命令会执行 `sc.exe stop` + `sc.exe delete`：

```bash
awsb service uninstall
```

其他子命令均通过 `sc.exe` 操作：`start` / `stop` / `restart`（`stop` + `start`）。服务日志重定向到 `~/.aws-bridge/log/awsb.out.log`，可用 `awsb log` 读取。

> Windows 服务默认以 `LocalSystem` 身份运行，其主目录是 `C:\Windows\System32\config\systemprofile`，找不到当前用户的 `~/.aws-bridge/config.json`。安装时会自动注入 `AWS_RUNTIME_HOME_DIR` 环境变量指向当前用户主目录，bridge 才能读到正确配置。

## 查看服务日志

`awsb log` 命令按平台读取服务日志，支持 `--follow` / `-f` 实时跟踪：

- Linux：`journalctl -u awsb.service`；
- macOS：`tail -n 200 ~/.aws-bridge/log/awsb.out.log`（`--follow` 时 `tail -f`）；
- Windows：`Get-Content -Tail 200 ~/.aws-bridge/log/awsb.out.log`（`--follow` 时附加 `-Wait`）。

服务未安装或日志文件未生成时会返回明确错误提示。

## 关键环境变量

| 变量名 | 说明 | 默认值 |
| --- | --- | --- |
| `AWS_RUNTIME_BRIDGE_PORT` | Bridge HTTP 端口 | `18081`（开发态 `28081`） |
| `AWS_RUNTIME_ENV` | 运行环境标记；仅 `npm run dev` 由 `scripts/dev-runner.mjs` 自动注入 `development`，一般无需手动设置。决定运行主目录、默认端口与 MCP 服务名，详见上文「开发环境与生产环境」 | 未设置（生产） |
| `AWS_RUNTIME_SCHEDULER_BASE_URL` | aws-mcp-server 地址；显式配置优先级最高，未配置且只有一个 `autoRegisterTargets[].serverUrl` 时自动使用该地址 | 单目标自动注册地址；否则 `http://localhost:8080` |
| `AWS_REGISTER_ADDR` | Bridge 对外注册地址，覆盖配置文件中的 `registerAddr`；支持 `host:port` / 纯 `host` / 完整 URL（`http(s)://...`） | 未设置时读取配置文件 |
| `AWS_REGISTER_IP` | 已废弃，仅做向后兼容；等同 `registerAddr` 但只接受纯 IP，端口由 `AWS_RUNTIME_BRIDGE_PORT` 决定 | 未设置时读取配置文件 |
| `AWS_RUNTIME_HOME_DIR` | Bridge 管理配置与状态的主目录；显式设置时优先于开发/生产环境的默认主目录 | 当前用户 Home（开发态为 `<仓库根>/.dev-home`） |
| `AWS_RUNTIME_CORS_ORIGINS` | 允许访问 bridge 的来源，逗号分隔 | 本地开发地址 |

生产环境中，bridge 最终解析出的调度中心地址必须是机器实例可访问的 `aws-mcp-server` 地址，不能使用不可达的容器内 `localhost`。如果配置了多个 `autoRegisterTargets`，bridge 不会静默选择第一个目标，需通过 `AWS_RUNTIME_SCHEDULER_BASE_URL` 或后续多调度中心身份路由明确目标。
