docs: restructure docs to support full en/zh bilingual versions with language toggles
This commit is contained in:
parent
fa49b2fda1
commit
2a227deddc
18
README.md
18
README.md
@ -1,3 +1,5 @@
|
||||
[🇺🇸 English](README.md) | [🇨🇳 中文](README.zh.md)
|
||||
|
||||
# XWorkspace Console
|
||||
|
||||
XWorkspace Console is the local AI workspace control plane for AI Workspace Lab. It brings together a React dashboard, Go status API, systemd user services, and XFCE desktop templates into one tabbed surface for services, runtime, terminal access, and workspace navigation.
|
||||
@ -77,14 +79,14 @@ http://127.0.0.1:17000
|
||||
- Latest source: [GitHub repository](https://github.com/ai-workspace-lab/xworkspace-console)
|
||||
- Releases: [GitHub Releases](https://github.com/ai-workspace-lab/xworkspace-console/releases)
|
||||
- Bootstrap script: `scripts/setup-ai-workspace-all-in-one.sh`
|
||||
- Offline installer docs: [`docs/OFFLINE_AI_WORKSPACE_INSTALLER.md`](docs/OFFLINE_AI_WORKSPACE_INSTALLER.md)
|
||||
- Offline installer docs: [`docs/en/OFFLINE_AI_WORKSPACE_INSTALLER.md`](docs/en/OFFLINE_AI_WORKSPACE_INSTALLER.md)
|
||||
|
||||
## Docs / Links
|
||||
|
||||
- [`docs/FEATURES.md`](docs/FEATURES.md)
|
||||
- [`docs/VERSION_MATRIX.md`](docs/VERSION_MATRIX.md)
|
||||
- [`docs/REPOSITORY_OVERVIEW.md`](docs/REPOSITORY_OVERVIEW.md)
|
||||
- [`docs/SETUP_AI_WORKSPACE_ALL_IN_ONE.md`](docs/SETUP_AI_WORKSPACE_ALL_IN_ONE.md)
|
||||
- [`docs/OFFLINE_AI_WORKSPACE_INSTALLER.md`](docs/OFFLINE_AI_WORKSPACE_INSTALLER.md)
|
||||
- [`docs/operations/service-port-plan.md`](docs/operations/service-port-plan.md)
|
||||
- [`docs/designs/2026-06-07-ai-workspace-desktop-design.md`](docs/designs/2026-06-07-ai-workspace-desktop-design.md)
|
||||
- [`docs/en/FEATURES.md`](docs/en/FEATURES.md)
|
||||
- [`docs/en/VERSION_MATRIX.md`](docs/en/VERSION_MATRIX.md)
|
||||
- [`docs/en/REPOSITORY_OVERVIEW.md`](docs/en/REPOSITORY_OVERVIEW.md)
|
||||
- [`docs/en/SETUP_AI_WORKSPACE_ALL_IN_ONE.md`](docs/en/SETUP_AI_WORKSPACE_ALL_IN_ONE.md)
|
||||
- [`docs/en/OFFLINE_AI_WORKSPACE_INSTALLER.md`](docs/en/OFFLINE_AI_WORKSPACE_INSTALLER.md)
|
||||
- [`docs/en/operations/service-port-plan.md`](docs/en/operations/service-port-plan.md)
|
||||
- [`docs/en/designs/2026-06-07-ai-workspace-desktop-design.md`](docs/en/designs/2026-06-07-ai-workspace-desktop-design.md)
|
||||
|
||||
92
README.zh.md
Normal file
92
README.zh.md
Normal file
@ -0,0 +1,92 @@
|
||||
[🇺🇸 English](README.md) | [🇨🇳 中文](README.zh.md)
|
||||
|
||||
# XWorkspace Console
|
||||
|
||||
XWorkspace Console 是 AI Workspace Lab 的本地 AI 工作区控制平面。它将 React 仪表板、Go 状态 API、systemd 用户服务以及 XFCE 桌面模板整合到一个多标签页界面中,用于服务管理、运行时管理、终端访问以及工作区导航。
|
||||
|
||||
## 预览 (Preview)
|
||||
|
||||

|
||||
|
||||
### 图片 / 视频
|
||||
|
||||
图片和视频工作流可以作为自定义标签页自然地集成在控制台 shell 中。这使得制品审查、服务切换和运行时操作都集中在一个地方,而不是分散在不同的应用程序中。
|
||||
|
||||
## 关于 (About)
|
||||
|
||||
- 工作区 UI 的单一入口点:`http://127.0.0.1:17000`
|
||||
- 以标签页优先的控制台,涵盖工作区、服务、运行时和嵌入式工具
|
||||
- 旨在协调本地 AI 服务、网关访问和桌面引导流程
|
||||
- 后端由 `dashboard/`、`api/`、`config/`、`scripts/` 和 `docs/` 支持
|
||||
|
||||
## 快速开始 (Start TLDR)
|
||||
|
||||
> **注意:** 目前支持 **macOS**、**Debian** 和 **Ubuntu**。其他系统未经测试。
|
||||
|
||||
### 安装 (Installation)
|
||||
|
||||
1. 启动一体化安装程序:
|
||||
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | bash -
|
||||
```
|
||||
|
||||
2. 自动注册模型(通过 API 密钥):
|
||||
|
||||
在运行安装程序之前导出密钥,会自动在网关中注册模型(例如 DeepSeek、NVIDIA、OLLAMA/GLM):
|
||||
```bash
|
||||
export DEEPSEEK_API_KEY="sk-..."
|
||||
export NVIDIA_API_KEY="nvapi-..."
|
||||
export OLLAMA_API_KEY="your-key-here"
|
||||
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | bash -
|
||||
```
|
||||
|
||||
3. 离线安装 (Offline installation):
|
||||
|
||||
通过指定文件路径使用预先下载的部署包:
|
||||
```bash
|
||||
export AI_WORKSPACE_OFFLINE_PACKAGE="/path/to/offline-package.tar.gz"
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | bash -
|
||||
```
|
||||
|
||||
### 卸载 (Uninstallation)
|
||||
|
||||
```bash
|
||||
# 标准卸载(保留配置和状态)
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | bash -s -- uninstall
|
||||
|
||||
# 彻底清理(删除所有数据、密钥和配置)
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | bash -s -- uninstall --purge
|
||||
```
|
||||
|
||||
### 使用 (Usage)
|
||||
|
||||
1. 通过浏览器打开控制台:
|
||||
|
||||
```text
|
||||
http://127.0.0.1:17000
|
||||
```
|
||||
|
||||
2. 或启动本地桌面控制台应用程序:
|
||||
|
||||
```bash
|
||||
./scripts/setup-xworkspace-desktop.sh
|
||||
```
|
||||
|
||||
## 下载 (Download)
|
||||
|
||||
- 最新源码:[GitHub repository](https://github.com/ai-workspace-lab/xworkspace-console)
|
||||
- 发布版本:[GitHub Releases](https://github.com/ai-workspace-lab/xworkspace-console/releases)
|
||||
- 引导脚本:`scripts/setup-ai-workspace-all-in-one.sh`
|
||||
- 离线安装文档:[`docs/zh/OFFLINE_AI_WORKSPACE_INSTALLER.md`](docs/zh/OFFLINE_AI_WORKSPACE_INSTALLER.md)
|
||||
|
||||
## 文档 / 链接 (Docs / Links)
|
||||
|
||||
- [`docs/zh/FEATURES.md`](docs/zh/FEATURES.md)
|
||||
- [`docs/zh/VERSION_MATRIX.md`](docs/zh/VERSION_MATRIX.md)
|
||||
- [`docs/zh/REPOSITORY_OVERVIEW.md`](docs/zh/REPOSITORY_OVERVIEW.md)
|
||||
- [`docs/zh/SETUP_AI_WORKSPACE_ALL_IN_ONE.md`](docs/zh/SETUP_AI_WORKSPACE_ALL_IN_ONE.md)
|
||||
- [`docs/zh/OFFLINE_AI_WORKSPACE_INSTALLER.md`](docs/zh/OFFLINE_AI_WORKSPACE_INSTALLER.md)
|
||||
- [`docs/zh/operations/service-port-plan.md`](docs/zh/operations/service-port-plan.md)
|
||||
- [`docs/zh/designs/2026-06-07-ai-workspace-desktop-design.md`](docs/zh/designs/2026-06-07-ai-workspace-desktop-design.md)
|
||||
@ -1,619 +0,0 @@
|
||||
# AI Workspace Runtime 交付规划
|
||||
|
||||
> 目标:把 `setup-ai-workspace-all-in-one.sh` 从“一组分散的基础设施 Playbook”收敛为一个**可直接使用的 AI Workspace Runtime 产品**——版本受控、运行模式可组合、对外仅暴露 Bridge、部署完成后输出一次性统一摘要。
|
||||
>
|
||||
> 本文是落地前的详细规划(设计 + 变更清单 + 提交/部署/验收方案)。实现阶段严格按本文执行,不扩大修改范围、不做大规模重构、优先复用现有实现。
|
||||
|
||||
- 状态:Linux 离线包链路与 macOS 本地校验链路已进入联调阶段;macOS 已越过多数 role 兼容性阻塞,当前重点是 LiteLLM 离线 runtime 接入、完整安装复跑和幂等验收
|
||||
- 影响仓库:`ai-workspace-infra/playbooks`、`ai-workspace-lab/xworkspace-console`、`ai-workspace-lab/xworkspace-core-skills`、`ai-workspace-services/qmd`、`ai-workspace-services/litellm`
|
||||
- 目标主机:`root@acp-bridge.onwalk.net`
|
||||
- 对外默认域名(唯一公开服务):`acp-bridge.onwalk.net`
|
||||
|
||||
## TODO
|
||||
|
||||
- [x] 等待并核对 `xworkspace-console` 的离线包 GitHub Actions 发布链路,确认 `publish-release` 完整结束且 release 产物上传成功。
|
||||
- [ ] 继续核对 `root@acp-bridge.onwalk.net` 的远程部署进度,确认 `setup-ai-workspace-all-in-one.sh` 最终完成并输出统一摘要。
|
||||
- [x] `setup-ai-workspace-all-in-one.sh` 在目标主机上优先使用离线安装包加速部署,减少在线拉取与安装耗时。
|
||||
- [x] 为 LiteLLM 新增 runtime wheelhouse release workflow,供 all-in-one 离线包消费。
|
||||
- [ ] 验证 `ai-workspace-services/litellm` 的 runtime release 实际生成成功,并确认 console 离线包能下载 matching `litellm-runtime-<distro>-<version>-<arch>.tar.gz`。
|
||||
- [ ] 验证 `setup-ai-workspace-all-in-one.sh` 幂等性:同一主机连续执行两次均成功,复用凭据、离线包缓存与已导入镜像,并安全等待部署/APT 锁。
|
||||
- [ ] 完成 macOS 本地最终验收核对:Portal、Bridge、OpenClaw、QMD、Hermes、PostgreSQL、Vault、LiteLLM 状态正常,`http://localhost:8181/mcp` 和 LiteLLM health 可达。
|
||||
- [ ] 完成远程 Linux 最终验收核对:Bridge 对外可达、其余服务默认仅本地监听、`acp-codex` / `opencode` / `gemini` / `hermes` / `qmd` / `litellm` 状态正常。
|
||||
- [ ] 记录最终提交哈希、GitHub Actions run、release tag 与远端验证结果,回填到本计划的交付结果部分。
|
||||
|
||||
---
|
||||
|
||||
## 1. 交付目标与验收标准
|
||||
|
||||
### 1.1 总体目标
|
||||
|
||||
1. 在不扩大修改范围、不做大规模重构的前提下,完成必要调整并分别提交三个仓库。
|
||||
2. 使用 `scripts/setup-ai-workspace-all-in-one.sh` 将 AI Workspace 部署到 `root@acp-bridge.onwalk.net`。
|
||||
3. `xworkmate bridge` 统一使用 `acp-bridge.onwalk.net` 作为对外域名,且是**唯一默认公开**的服务。
|
||||
4. 交付一个完整的 AI Workspace Runtime:`xfce_desktop` + NodeJS + Playwright 全部版本受控。
|
||||
5. 运行模式 `docker / k3s / systemd` 可选、可自由组合(`docker` 与 `k3s` 互斥,`docker + systemd` 可组合)。
|
||||
6. 角色拆分:`roles/vhosts/xfce_xrdp_minimal` → `roles/vhosts/xfce_desktop_minimal_runtime` + `roles/vhosts/remote_desktop_xrdp_server`。
|
||||
7. 部署脚本结束后输出一份**面向最终用户**的统一部署摘要,重要认证信息**仅显示一次**。
|
||||
|
||||
### 1.2 验收标准(Definition of Done)
|
||||
|
||||
- [ ] 三个仓库完成代码提交,提供各自 Commit Hash。
|
||||
- [ ] `setup-ai-workspace-all-in-one.sh` 在目标主机以远程 exec 模式执行成功(无 rsync,仓库由远程主机自 GitHub pull)。
|
||||
- [ ] Bridge 对外使用 `acp-bridge.onwalk.net`,其余服务默认不公开。
|
||||
- [ ] 脚本结束输出统一部署摘要:访问入口、一次性凭据、各服务运行状态、可用 Agent CLI。
|
||||
- [ ] `xfce_desktop / NodeJS / Playwright` 版本均可在单一来源(role defaults)查到并被固定。
|
||||
- [ ] 同一主机连续执行两次安装均成功,第二次执行不生成新凭据、不重复下载同一 release 包,并等待而非破坏并发 APT/dpkg 操作。
|
||||
|
||||
---
|
||||
|
||||
## 2. 部署执行模型(远程 exec / GitHub pull)
|
||||
|
||||
- `scripts/setup-ai-workspace-all-in-one.sh` 运行**在远程主机上**,全程 remote exec 模式。
|
||||
- **不使用 rsync**;所需仓库由远程主机直接从 GitHub `pull`:
|
||||
- Playbooks:`https://github.com/ai-workspace-infra/playbooks.git`
|
||||
- Core Skills:`https://github.com/ai-workspace-lab/xworkspace-core-skills.git`
|
||||
- Console(脚本自身所在仓库):`https://github.com/ai-workspace-lab/xworkspace-console.git`
|
||||
- QMD:`https://github.com/ai-workspace-services/qmd.git`
|
||||
- LiteLLM:`https://github.com/ai-workspace-services/litellm.git`
|
||||
- 含义:**本地提交必须推送到上述 GitHub 仓库后,远程部署才能拉到改动**。
|
||||
|
||||
> ⚠️ 注意仓库地址不一致:playbooks 本地 `origin` 当前为 `git@github.com:x-evor/playbooks.git`,而部署权威源是 `ai-workspace-infra/playbooks`。实现阶段需将脚本中的 pull 源对齐到 `ai-workspace-infra/playbooks`,并把提交推送到该仓库。
|
||||
|
||||
### 2.1 环境变量接口契约(权威)
|
||||
|
||||
bootstrap 入口固定为 console 仓库的原始脚本,所有暴露/安全/可选桌面行为均通过 `bash -` 前的环境变量控制。
|
||||
|
||||
**标准安装**(默认安全本地工作区,仅需一个统一 token):
|
||||
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | bash -
|
||||
```
|
||||
|
||||
**全部参数(默认值与推荐用法):**
|
||||
|
||||
| 变量 | 默认 | 推荐用法 |
|
||||
|---|---|---|
|
||||
| `TOKEN` | 生成或复用 | 为 Bridge / Portal / LiteLLM / OpenClaw / Vault 设置**统一**认证 token |
|
||||
| `AI_WORKSPACE_SECURITY_LEVEL` | `standard` | 公网/半公网主机使用 `strict` |
|
||||
| `XWORKMATE_BRIDGE_PUBLIC_ACCESS` | `true` | Bridge 为默认唯一公开服务;如需关闭对外访问可显式设 `false` |
|
||||
| `XWORKMATE_BRIDGE_DOMAIN` | host-specific | 设置 Bridge 公网域名,例如 `acp-bridge.onwalk.net` |
|
||||
| `XWORKSPACE_CONSOLE_PUBLIC_ACCESS` | `false` | 仅当 Portal 必须公开时开启;本地优先更安全 |
|
||||
| `XWORKSPACE_CONSOLE_ENABLE_XRDP` | `false` | 仅当需要远程桌面访问时开启 |
|
||||
| `GATEWAY_OPENCLAW_PUBLIC_ACCESS` | `false` | 除非 OpenClaw 必须直接暴露,保持 false |
|
||||
| `VAULT_PUBLIC_ACCESS` | `false` | 常规部署保持 false |
|
||||
| `LITELLM_API_CADDY_STRICT_WHITELIST` | `false` | strict 且 LiteLLM 经 Caddy 暴露时开启 |
|
||||
|
||||
**进阶安装示例:**
|
||||
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | \
|
||||
AI_WORKSPACE_SECURITY_LEVEL=strict \
|
||||
XWORKSPACE_CONSOLE_ENABLE_XRDP=true \
|
||||
XWORKSPACE_CONSOLE_PUBLIC_ACCESS=true \
|
||||
XWORKMATE_BRIDGE_PUBLIC_ACCESS=true \
|
||||
GATEWAY_OPENCLAW_PUBLIC_ACCESS=false \
|
||||
VAULT_PUBLIC_ACCESS=false \
|
||||
LITELLM_API_CADDY_STRICT_WHITELIST=true \
|
||||
TOKEN="your-unified-auth-token" \
|
||||
bash -
|
||||
```
|
||||
|
||||
**目标主机(ACP Bridge)示例:**
|
||||
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | \
|
||||
XWORKMATE_BRIDGE_DOMAIN=acp-bridge.onwalk.net \
|
||||
XWORKMATE_BRIDGE_PUBLIC_ACCESS=true \
|
||||
AI_WORKSPACE_SECURITY_LEVEL=strict \
|
||||
bash -
|
||||
```
|
||||
|
||||
> 关键校准:`XWORKMATE_BRIDGE_PUBLIC_ACCESS` 默认 **`true`**——Bridge 是**默认唯一公开**的服务(域名经 `XWORKMATE_BRIDGE_DOMAIN` 自定义传入);其余服务(Console/OpenClaw/Vault/QMD/Hermes/PG/LiteLLM)默认 `false`,保持 `127.0.0.1` 本地监听。如需关闭 Bridge 对外访问,显式设 `XWORKMATE_BRIDGE_PUBLIC_ACCESS=false`。`TOKEN` 输出务必私密保存——不得拷入前端源码或提交到 Git。
|
||||
|
||||
### 2.2 预期最终输出(部署摘要)
|
||||
|
||||
部署成功后,脚本将**一次性**打印部署域名与 token,随后报告各服务运行状态:
|
||||
|
||||
- AI Workspace 域名与 token(仅显示一次)
|
||||
- OpenClaw
|
||||
- QMD
|
||||
- PostgreSQL
|
||||
- Vault
|
||||
- Workspace Portal / Console
|
||||
- LiteLLM
|
||||
- Hermes
|
||||
- Agent CLI:opencode、gemini、codex、claude
|
||||
|
||||
### 2.3 本地 macOS 校验模式
|
||||
|
||||
在 macOS 上脚本默认进入**本地校验模式**,在 `http://127.0.0.1:17000` 启动 Portal。若因端口占用校验失败,先停止已有本地服务或在干净会话中重试。
|
||||
|
||||
---
|
||||
|
||||
## 3. 现状分析:角色层级关系
|
||||
|
||||
`setup-ai-workspace-all-in-one.sh`(位于 console 仓库)在目标主机引导后,运行 `setup-ai-workspace-all-in-one.yml`(位于 playbooks 仓库)。其按导入顺序的角色层级:
|
||||
|
||||
```
|
||||
setup-ai-workspace-all-in-one.sh [repo: xworkspace-console/scripts]
|
||||
└─ ansible-playbook setup-ai-workspace-all-in-one.yml [repo: playbooks]
|
||||
├─1 setup-nodejs.yml → role roles/vhosts/nodejs NodeJS(22.x)+yarn
|
||||
├─2 setup-xworkspace-console.yaml WORKSPACE PORTAL/CONSOLE(内联 task,无 role)
|
||||
│ apt: caddy,xfce4,python3,golang-go,google-chrome-stable,ttyd
|
||||
│ git clone console → npm build;systemd --user: console(:17000)/api(:8788)/ttyd(:7681)/status.timer
|
||||
│ Caddy 公网站点 workspace.svc.plus ⚠ 标准模式下也公开
|
||||
├─3 setup-ai-agent-skills.yml → role roles/ai_agent_runtime AI WORKSPACE RUNTIME 核心
|
||||
│ NodeJS(24.x)+Playwright;Agent CLI: opencode/gemini/codex/claude;Python/browser/docs/fonts
|
||||
│ └─ role agent_skills → 注入 xworkspace-core-skills 市场技能
|
||||
├─4 deploy_gateway_openclaw.yml → role roles/vhosts/gateway_openclaw OpenClaw(2026.5.28)
|
||||
├─5 deploy_xworkmate_bridge_vhosts.yml BRIDGE + ACP 集群
|
||||
│ ├─ import setup-xworkspace-console.yaml(带 bridge 变量再跑一次)
|
||||
│ └─ roles: acp_server_codex / acp_server_opencode / acp_server_gemini /
|
||||
│ acp_server_hermes / xworkmate_bridge(:8787 本地,公网 Caddy)
|
||||
│ 域名默认 xworkmate-bridge.svc.plus → acp-bridge.onwalk.net
|
||||
├─6 setup-vault.yaml → role roles/vhosts/vault Vault(1.20.4) :8200
|
||||
├─7 setup-postgres-standalone.yaml → role roles/vhosts/postgres(dep: common) 原生 apt PG17 :5432
|
||||
├─8 setup-litellm.yaml → role roles/vhosts/litellm pip 安装 :4000
|
||||
├─9 deploy_QMD.yml → role roles/vhosts/qmd bun qmd, MCP :8181
|
||||
├─10 deploy_agent_hermes.yml → role roles/vhosts/acp_server_hermes ⚠ Hermes 重复部署(与步骤5重叠)
|
||||
└─11 setup-xfce-xrdp.yaml [可选] → role roles/vhosts/xfce_xrdp_minimal
|
||||
→ 拆分为 xfce_desktop_minimal_runtime + remote_desktop_xrdp_server
|
||||
```
|
||||
|
||||
### 3.1 关键发现
|
||||
|
||||
1. **公开面冲突**:步骤 2/5 在 `ai_workspace_security_level != strict` 时为 `workspace.svc.plus` 部署公网 Caddy 站点,导致 Portal 也对外暴露,与“Bridge 唯一公开”冲突。
|
||||
2. **Hermes 重复部署**:步骤 5(ACP 集群内)与步骤 10(独立)各部署一次,冗余。
|
||||
3. **版本固定点分散**:OpenClaw、Vault 已有固定变量;NodeJS 有但偏宽松(`22.x`/`24.x`);Hermes、QMD、LiteLLM 缺少显式版本/源固定。
|
||||
|
||||
---
|
||||
|
||||
## 4. 关键设计决策
|
||||
|
||||
### 4.1 对外公开面:Bridge Only
|
||||
|
||||
- **Bridge 是默认唯一公开的服务**:`XWORKMATE_BRIDGE_PUBLIC_ACCESS` 默认 `true`,公网域名由 `XWORKMATE_BRIDGE_DOMAIN` 自定义传入(目标主机 `acp-bridge.onwalk.net`)。如需关闭可显式设 `false`。
|
||||
- `xworkspace_console_public_access` 默认 `false`(仅 `XWORKSPACE_CONSOLE_PUBLIC_ACCESS=true` 时公开)。
|
||||
- `GATEWAY_OPENCLAW_PUBLIC_ACCESS` / `VAULT_PUBLIC_ACCESS` 默认 `false`;其余(QMD / Hermes / PG / LiteLLM)维持本地监听(`127.0.0.1`),不部署公网 Caddy 站点。
|
||||
- 实现方式:**最小改动**——仅调整默认值/开关并对齐 env 名称(§2.1),不删除既有 public_access 能力(保留可手动放开)。
|
||||
|
||||
### 4.2 Hermes 去重
|
||||
|
||||
- `setup-ai-workspace-all-in-one.yml` 中移除步骤 10 的独立 `deploy_agent_hermes.yml` 导入(步骤 5 的 ACP 集群已含 hermes)。
|
||||
- 保留 `deploy_agent_hermes.yml` 文件本身,供单独部署场景使用,仅从 all-in-one 聚合链里去重。
|
||||
|
||||
### 4.3 运行模式矩阵(docker / k3s / systemd)
|
||||
|
||||
引入一个**校验型**变量 `ai_workspace_runtime_modes`(列表),在 all-in-one 顶部加一段 `assert` 守卫,不重写各组件部署逻辑:
|
||||
|
||||
| 约束 | 规则 |
|
||||
|---|---|
|
||||
| 互斥 | `docker` 与 `k3s` 不可同时出现 |
|
||||
| 可组合 | `docker + systemd` 允许;`systemd` 可单独 |
|
||||
| 默认 | `['docker','systemd']`(多数 Agent 服务 systemd,PostgreSQL 走 docker compose) |
|
||||
|
||||
组件与模式映射(复用现有能力,不新增重型实现):
|
||||
|
||||
| 组件 | systemd | docker | k3s |
|
||||
|---|---|---|---|
|
||||
| Console / API / ttyd / Bridge / ACP / OpenClaw / QMD / LiteLLM | ✅ 默认 | — | — |
|
||||
| PostgreSQL | 可选 | ✅ **默认 docker compose** | 可选 |
|
||||
| Vault | `vault_deploy_mode=systemd` | — | `vault_deploy_mode=kubernetes`(k3s) |
|
||||
|
||||
守卫伪代码(放入 all-in-one 顶层 play):
|
||||
|
||||
```yaml
|
||||
- name: Validate runtime mode combination
|
||||
hosts: all
|
||||
gather_facts: false
|
||||
tasks:
|
||||
- assert:
|
||||
that:
|
||||
- not ('docker' in ai_workspace_runtime_modes and 'k3s' in ai_workspace_runtime_modes)
|
||||
- ai_workspace_runtime_modes | length > 0
|
||||
fail_msg: "docker 与 k3s 互斥;请选择 docker/k3s/systemd 的合法组合。"
|
||||
```
|
||||
|
||||
### 4.4 PostgreSQL 默认 docker compose
|
||||
|
||||
- 新增开关 `postgresql_deploy_mode`,默认 `compose`。
|
||||
- `compose` 模式:在 `roles/vhosts/postgres` 增加一条 compose 部署路径(镜像版本固定,端口/口令复用现有变量),与现有原生 apt 路径并存、互斥择一。
|
||||
- 不删除原生 apt 路径(设 `postgresql_deploy_mode=native` 可回退)。
|
||||
|
||||
### 4.5 QMD / LiteLLM 源仓库与版本固定
|
||||
|
||||
- QMD:安装源指向 `https://github.com/ai-workspace-services/qmd.git`,新增 `qmd_source_repo` / `qmd_version` 变量固定。
|
||||
- LiteLLM:安装源指向 `https://github.com/ai-workspace-services/litellm.git`,新增 `litellm_source_repo` / `litellm_version` 变量固定。
|
||||
|
||||
---
|
||||
|
||||
## 5. 详细变更清单
|
||||
|
||||
### 5.1 角色拆分:`xfce_xrdp_minimal` → 两个角色
|
||||
|
||||
按职责拆分,**逐文件映射**,行为不变;`setup-xfce-xrdp.yaml` 改为顺序组合两个新角色。
|
||||
|
||||
**`roles/vhosts/xfce_desktop_minimal_runtime`(桌面运行时)**
|
||||
|
||||
| 来源 | 去向 | 说明 |
|
||||
|---|---|---|
|
||||
| `tasks/install.yml`(仅桌面包:`xfce4-session/xfwm4/xfdesktop4/xfce4-panel/xfce4-terminal/dbus-x11/fonts-noto-cjk/xserver-xorg-core`) | `tasks/install.yml` | 移除 `xorgxrdp/xrdp` 包与 xrdp 服务启动 |
|
||||
| `tasks/browser.yml`(Google Chrome 固定版) | `tasks/browser.yml` | 原样保留 |
|
||||
| 新增 `tasks/runtime.yml` | NodeJS + Playwright(引用既有 `nodejs` / `ai_agent_runtime` 的固定版本变量) | 版本受控单一来源 |
|
||||
| `defaults/main.yml`(desktop/chrome/node/playwright 版本变量) | `defaults/main.yml` | 见 §5.2 版本表 |
|
||||
|
||||
**`roles/vhosts/remote_desktop_xrdp_server`(远程桌面 XRDP 服务)**
|
||||
|
||||
| 来源 | 去向 | 说明 |
|
||||
|---|---|---|
|
||||
| `tasks/install.yml`(`xorgxrdp/xrdp`、ssl-cert 组、daemon-reload、enable/start、unit 校验/fail) | `tasks/install.yml` | XRDP 服务层 |
|
||||
| `tasks/config.yml`(用户/口令 RDP 认证、`.xsession`、xfconf 目录) | `tasks/config.yml` | RDP 会话粘合 |
|
||||
| `handlers/main.yml`(Restart xrdp / sesman) | `handlers/main.yml` | 原样保留 |
|
||||
| `vars/main.yml`(`xfce_xrdp_services` 等)+ `xfce_rdp_port/xfce_enable_ufw` | `defaults`/`vars` | 端口/ufw |
|
||||
|
||||
**组合点 `setup-xfce-xrdp.yaml`:**
|
||||
|
||||
```yaml
|
||||
- name: Deploy XFCE desktop + optional XRDP (Optional)
|
||||
hosts: all
|
||||
become: true
|
||||
vars:
|
||||
xworkspace_console_enable_xrdp: false
|
||||
tasks:
|
||||
- include_role: { name: roles/vhosts/xfce_desktop_minimal_runtime }
|
||||
- include_role: { name: roles/vhosts/remote_desktop_xrdp_server }
|
||||
when: xworkspace_console_enable_xrdp | bool
|
||||
```
|
||||
|
||||
> 旧角色 `roles/vhosts/xfce_xrdp_minimal`:拆分完成且引用全部切换后删除(当前唯一引用即 `setup-xfce-xrdp.yaml`)。
|
||||
|
||||
### 5.2 版本固定表(单一来源)
|
||||
|
||||
| 组件 | 变量 | 当前 | 目标 | 文件 |
|
||||
|---|---|---|---|---|
|
||||
| OpenClaw | `gateway_openclaw_required_version` | `2026.5.28` | `2026.6.1` | `roles/vhosts/gateway_openclaw/defaults/main.yml:23` |
|
||||
| Vault | `vault_version`(env 默认值) | `1.20.4` | `1.21.4` | `roles/vhosts/vault/vars/main.yml:6` |
|
||||
| Hermes | `acp_hermes_version`(新增) | 无 | `0.15` | `roles/vhosts/acp_server_hermes/defaults/main.yml` |
|
||||
| QMD | `qmd_version` / `qmd_source_repo`(新增) | 无 | 取自 `ai-workspace-services/qmd` | `roles/vhosts/qmd/defaults/main.yml` |
|
||||
| LiteLLM | `litellm_version` / `litellm_source_repo`(新增) | 无 | 取自 `ai-workspace-services/litellm` | `roles/vhosts/litellm/defaults/main.yml` |
|
||||
| NodeJS | `nodejs_version` / `ai_agent_runtime_nodejs_version` | `22.x` / `24.x` | 固定明确小版本 | `roles/vhosts/nodejs/defaults` + `roles/ai_agent_runtime/defaults` |
|
||||
| Playwright | `ai_agent_runtime_playwright_version`(新增/固定) | 无显式 | 固定 | `roles/ai_agent_runtime/defaults/main.yml` |
|
||||
| Google Chrome | `xfce_google_chrome_version` | `148.0.7778.167-1` | 保持固定 | 运行时角色 `defaults/main.yml` |
|
||||
| XFCE | `xfce_packages` | 列表 | 保持(apt 发行版固定) | 运行时角色 `defaults/main.yml` |
|
||||
|
||||
### 5.3 Bridge 对外域名(自定义参数,非硬编码默认)
|
||||
|
||||
- **`acp-bridge.onwalk.net` 是 host-specific 的自定义参数**,经 `XWORKMATE_BRIDGE_DOMAIN` 在部署时传入,**不写死为 role 默认值**。
|
||||
- 实现要点(最小改动):确保 `XWORKMATE_BRIDGE_DOMAIN` 经 bootstrap 脚本 → playbook → `roles/vhosts/xworkmate_bridge` 正确透传。现有 env 覆盖链已支持:`XWORKMATE_BRIDGE_DOMAIN` → `ai_workspace_public_domain`(`SERVER_DOMAIN/ACP_BRIDGE_DOMAIN/BRIDGE_DOMAIN`)。
|
||||
- `roles/vhosts/xworkmate_bridge/defaults/main.yml:47` 的中性回退默认值(`xworkmate-bridge.svc.plus`)**保持不变**——仅作为未显式传参时的兜底;目标主机通过 `XWORKMATE_BRIDGE_DOMAIN=acp-bridge.onwalk.net` 指定真实域名。
|
||||
- 验收只要求“Bridge 使用指定域名”,由自定义参数满足,无需改动 role 默认。
|
||||
|
||||
### 5.4 部署脚本统一摘要(`setup-ai-workspace-all-in-one.sh`)
|
||||
|
||||
在现有脚本(console 仓库,约 39KB)末尾**追加**一段摘要渲染(探测主机实时状态,不硬编码),结构如下:
|
||||
|
||||
```
|
||||
================ AI Workspace 部署摘要 ================
|
||||
[访问入口]
|
||||
Workspace Portal (Console) : http://127.0.0.1:17000 (本地)
|
||||
XWorkMate Bridge : https://acp-bridge.onwalk.net ← 唯一公开
|
||||
[一次性凭据](仅显示一次)
|
||||
AI_WORKSPACE_AUTH_TOKEN : ********
|
||||
Vault root token : ********
|
||||
[服务状态]
|
||||
Portal / Bridge / OpenClaw / QMD / Hermes / PostgreSQL / Vault / LiteLLM : active/inactive
|
||||
[Agent CLI]
|
||||
opencode / gemini / codex / claude : <version | 缺失>
|
||||
======================================================
|
||||
```
|
||||
|
||||
- 状态探测复用 console 的 `generate-status.py` 逻辑与各 role 的 `validate.yml` 健康检查(`systemctl is-active` + `curl` 健康端点)。
|
||||
- 凭据“仅显示一次”:摘要从已落盘的 token 文件读取展示后,提示用户保存;脚本不重复打印。
|
||||
|
||||
### 5.5 all-in-one 聚合链调整
|
||||
|
||||
- 顶部新增 §4.3 运行模式 `assert` 守卫 play。
|
||||
- 移除步骤 10 独立 `deploy_agent_hermes.yml` 导入(去重,见 §4.2)。
|
||||
- 其余导入顺序保持不变。
|
||||
|
||||
---
|
||||
|
||||
## 6. 仓库与提交计划
|
||||
|
||||
| 仓库 | 主要改动 | Commit message(建议) | 推送目标 |
|
||||
|---|---|---|---|
|
||||
| `playbooks` | 角色拆分、版本固定、Bridge 域名、运行模式守卫、PG compose、QMD/LiteLLM 源、聚合链去重、本规划文档 | `feat: deliver versioned AI Workspace Runtime (role split, run-mode matrix, bridge domain)` | `ai-workspace-infra/playbooks` |
|
||||
| `xworkspace-console` | `setup-ai-workspace-all-in-one.sh` 统一摘要、pull 源对齐、console 默认不公开 | `feat: unified one-time deploy summary + bridge-only public surface` | `ai-workspace-lab/xworkspace-console` |
|
||||
| `xworkspace-core-skills` | (按需)技能种子/版本对齐 | `chore: align skills seed for workspace runtime` | `ai-workspace-lab/xworkspace-core-skills` |
|
||||
|
||||
> 每个仓库**独立提交**,分别记录 Commit Hash 写入最终交付说明。
|
||||
|
||||
### 6.1 当前实现进度(2026-06-22)
|
||||
|
||||
| 仓库 | 已完成进展 | 已知待处理 |
|
||||
|---|---|---|
|
||||
| `ai-workspace-infra/playbooks` | OpenClaw doctor/restart 已拆分;QMD 已补 macOS LaunchAgent;OpenClaw `acpx` 兼容性 assert 已修;LiteLLM 已切 Python 3.13 venv、安装探测和 `.install-spec` 跳过重复安装 | 需要完整 macOS 复跑确认 `qmd :8181/mcp`、OpenClaw registry、LiteLLM health;需要确认 all-in-one 的 macOS patch 与 playbooks main 不再互相覆盖 |
|
||||
| `ai-workspace-lab/xworkspace-console` | all-in-one 离线包链路已能消费 console/bridge/qmd/litellm runtime release;macOS 调试案例持续记录在 `docs/case/macos_compatibility_tests.md` | `uninstall purge` 仍需打印删除路径;需要清理离线包生成目录等非源码正式目录;需要确认 `install.svc.plus/ai-workspace` 发布入口同步到最新 main |
|
||||
| `ai-workspace-services/qmd` | all-in-one 离线包脚本按 `qmd-runtime-linux-${ARCH}.tar.gz` 消费 release;playbooks 已补 QMD macOS LaunchAgent | 需要确认 latest runtime release 与 offline package 拉取路径持续可用;macOS 需实测 MCP endpoint |
|
||||
| `ai-workspace-services/litellm` | 新增 `.github/workflows/offline-package-litellm-runtime.yaml`,产出 `litellm-runtime-<distro>-<version>-<arch>.tar.gz`、wheelhouse、可选 portable Python、`metadata/runtime.env` | 需要触发 GitHub Actions 并确认 release asset 与 `SHA256SUMS`;需要确认 console 离线包使用 `latest-runtime` 能解析到该 release |
|
||||
| `ai-workspace-lab/xworkspace-core-skills` | all-in-one 离线包仍按 core-skills repo/ref 打包 | 当前未发现新的 macOS 阻塞;最终验收仍需确认技能注入与 OpenClaw/QMD 可见 |
|
||||
|
||||
### 6.2 近期关键提交
|
||||
|
||||
| 仓库 | Commit | 说明 |
|
||||
|---|---|---|
|
||||
| `ai-workspace-infra/playbooks` | `09a39e6` | `perf(openclaw): avoid unnecessary doctor repairs` |
|
||||
| `ai-workspace-infra/playbooks` | `f01e0bb` | `fix(qmd): provision macOS LaunchAgent` |
|
||||
| `ai-workspace-infra/playbooks` | `c11f51b` | `fix(openclaw): allow version-matched acpx plugin` |
|
||||
| `ai-workspace-infra/playbooks` | `71ebe64` | `fix(litellm): isolate runtime in Python 3.13 venv` |
|
||||
| `ai-workspace-infra/playbooks` | `6a2f05f` | `fix(litellm): skip redundant dependency installs` |
|
||||
| `ai-workspace-services/litellm` | `51cde5e32` | `ci: add offline litellm runtime workflow` |
|
||||
|
||||
### 6.3 当前最需要收口的问题
|
||||
|
||||
1. `LiteLLM`:在线 `pip install litellm[proxy]` 仍可能因大 wheel 下载中断失败;应以 runtime wheelhouse release 作为 all-in-one 默认加速路径,并保留在线路径为 fallback。
|
||||
2. `install.svc.plus/ai-workspace`:需要确认公开短链实际拉到的是 `xworkspace-console@main` 最新脚本,否则 macOS 仍可能运行旧 bootstrap。
|
||||
3. `uninstall purge`:需要输出将删除/已删除/不存在的路径,覆盖 macOS 与 Linux 的 token、Vault/OpenClaw 状态、临时部署目录、系统配置目录。
|
||||
4. 工作区清理:需要清理 `ai-workspace-all-in-one-offline-*` 等生成目录,避免离线包产物混入源码根目录。
|
||||
5. 最终验收:需要在 macOS 上做一次干净安装和一次重复安装,记录各服务端口、LaunchAgent/systemd 状态、health endpoint 与 changed 统计。
|
||||
|
||||
---
|
||||
|
||||
## 7. 部署与验证
|
||||
|
||||
### 7.1 部署命令(在目标主机或对其有网络/SSH 访问的环境执行)
|
||||
|
||||
```bash
|
||||
# 远程 exec:脚本在主机上自 GitHub pull 仓库并运行 ansible 到 localhost
|
||||
# 采用 §2.1 权威环境变量契约(目标主机示例)
|
||||
ssh root@acp-bridge.onwalk.net \
|
||||
'curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | \
|
||||
XWORKMATE_BRIDGE_DOMAIN=acp-bridge.onwalk.net \
|
||||
XWORKMATE_BRIDGE_PUBLIC_ACCESS=true \
|
||||
AI_WORKSPACE_SECURITY_LEVEL=strict \
|
||||
bash -'
|
||||
```
|
||||
|
||||
### 7.2 验证清单
|
||||
|
||||
- [ ] 脚本结束输出统一摘要,且 Bridge 显示 `https://acp-bridge.onwalk.net`。
|
||||
- [ ] `curl -I https://acp-bridge.onwalk.net` 可达;其余服务端口仅 `127.0.0.1` 监听。
|
||||
- [ ] `systemctl --user is-active` 各服务为 `active`。
|
||||
- [ ] `opencode/gemini/codex/claude --version` 均可执行。
|
||||
- [ ] 凭据仅在摘要中出现一次。
|
||||
|
||||
---
|
||||
|
||||
## 8. 风险与回退
|
||||
|
||||
| 风险 | 缓解 / 回退 |
|
||||
|---|---|
|
||||
| 沙箱无法直连 GitHub/目标主机 | 本地完成代码+提交;push 与远程部署由有网络的环境执行 |
|
||||
| PG 切 compose 影响既有数据 | 保留 `postgresql_deploy_mode=native` 回退路径 |
|
||||
| 角色拆分回归 | `setup-xfce-xrdp.yaml` 组合两角色,行为等价;保留旧角色直至引用切换验证通过 |
|
||||
| 版本固定导致拉取失败 | 版本变量集中、可单点覆盖(env / `-e`) |
|
||||
|
||||
---
|
||||
|
||||
## 9. 实现顺序(落地次序)
|
||||
|
||||
1. 本规划文档入库(docs/)。
|
||||
2. 角色拆分 + `setup-xfce-xrdp.yaml` 组合。
|
||||
3. 版本固定(OpenClaw/Vault/Hermes/QMD/LiteLLM/Node/Playwright/Chrome)。
|
||||
4. Bridge 域名参数透传(`XWORKMATE_BRIDGE_DOMAIN`,自定义,不改 role 默认)。
|
||||
5. 运行模式守卫 + PG compose 默认。
|
||||
6. 聚合链去重(Hermes)+ console 默认不公开。
|
||||
7. `setup-ai-workspace-all-in-one.sh` 统一摘要。
|
||||
8. 三仓库分别提交,记录 Commit Hash。
|
||||
9. 推送 + 远程部署 + 按 §7.2 验证。
|
||||
10. 并发优化落地(见 §10),最后做 §10.8 等价性回归。
|
||||
|
||||
---
|
||||
|
||||
## 10. 并发优化设计(深入分析 + 定制策略)
|
||||
|
||||
> 目标:在**不丢 tasks、不破坏现有 role 结构、不牺牲稳定性**的前提下,提升单机部署速度。
|
||||
> 总策略:三相执行——**Phase 1 串行(系统全局/抢锁)→ Phase 2 并发(互不依赖 I/O)→ Phase 3 串行(确定性收口)**。不要把多个 role 直接改并发;只把“耗时、互不依赖、不写同一文件、不抢同一锁”的任务做 `async`,最后 `async_status` 收口。
|
||||
|
||||
### 10.1 三相模型(权威定义)
|
||||
|
||||
**Phase 1 — 必须串行**(抢锁 / 修改系统全局状态):
|
||||
`apt update`、`apt install`、`dpkg` 相关、添加 apt repo / keyring、用户/用户组创建、基础目录创建、基础权限设置、Docker 安装、Caddy 安装、systemd 基础准备、防火墙基础规则、**全局 pip / 全局 npm(-g) 安装**。
|
||||
|
||||
**Phase 2 — 可以并发**(互不依赖、不写同一文件、不操作同一锁):
|
||||
`docker pull` 多镜像、下载多个二进制、`git clone` 多仓库、`go build`、**不同目录**的 `npm/pnpm install`、**不同目录**的前端 build、拉取插件、拉取静态资源、生成互不冲突的服务配置、初始化各服务独立工作目录、各服务独立 prepare 脚本。
|
||||
|
||||
**Phase 3 — 必须串行**(收口确定性):
|
||||
渲染最终配置、`systemd daemon-reload`、`enable service`、按依赖顺序 `start/restart`、health check、输出部署结果、清理临时文件。
|
||||
|
||||
### 10.2 关键定制结论(针对本 Playbook 的深入分析)
|
||||
|
||||
1. **所有 `npm -g` 共享同一 prefix → 必须 Phase 1 串行。**
|
||||
`roles/vhosts/nodejs` 设 `npm_config_prefix=/usr/local/lib/npm`;Agent CLI(opencode-ai / @google/gemini-cli / @openai/codex / @anthropic-ai/claude-code)、`yarn`、`openclaw@ver` 全部 `npm -g` 到该 prefix。并发会争用同一 `node_modules`/`.staging` 与 npm cache 锁 → **不可并发**。
|
||||
2. **LiteLLM 已改为独立 Python 3.13 venv,但依赖安装仍应串行收口**。它不再写系统 site-packages,但 `pip install litellm[proxy]` 依赖树大、网络失败率高,默认方向应是优先消费离线 wheelhouse,在线 venv 安装仅作 fallback。
|
||||
3. **真正安全的 Phase 2 候选是“外部 I/O 预取”**:git clone、二进制下载、docker pull、独立目录的前端 build、runtime release 下载。它们不碰 dpkg/npm-prefix/pip 全局锁,且写入各自独立路径。
|
||||
4. **跨 sub-playbook 的并发收益最大处在 Shell 预取层**:11 个步骤由 ansible 顺序导入,play 间难并发;把可并行的 I/O 上提到 bootstrap 的 Phase 2 fork 池(§10.5)预取,ansible 仅消费已就位产物,是收益/风险比最高的定制。
|
||||
5. **离线包优先**(呼应 TODO):已有离线安装包/已导入镜像时,Phase 2 预取应短路跳过,直接复用缓存。
|
||||
|
||||
### 10.3 现状任务 → 三相映射
|
||||
|
||||
| 步骤 / role | Phase 1(串行) | Phase 2(可并发预取) | Phase 3(串行收口) |
|
||||
|---|---|---|---|
|
||||
| 1 nodejs | nodesource keyring/repo、`apt install nodejs`、`npm -g yarn` | — | — |
|
||||
| 2 console | apt(caddy/xfce4/python3/golang-go/chrome)+chrome repo/key、用户/目录/权限 | `get_url` ttyd 二进制、`git clone` console、dashboard `npm install && build`(独立目录) | 渲染 systemd unit/env/portal-services.json、`daemon-reload`/enable/restart、Caddy 写入+reload |
|
||||
| 3 ai_agent_runtime | `npm -g` Agent CLI、全局 pip(python deps)、apt(browser/docs/fonts)、Playwright(-g) | `agent_skills` 拉取 core-skills 市场(独立目录) | 校验/health、register 输出 |
|
||||
| 4 gateway_openclaw | `npm -g openclaw@ver`+插件 | (插件若独立目录拉取可并发) | 配置渲染、systemd、版本 assert、health |
|
||||
| 5 bridge + ACP | 同步 console;acp_server_* 的全局安装部分 | `xworkmate-go-core` 二进制下载/放置、acp 各自独立工作目录 prepare | 配置渲染、按依赖 `requires acp-*.service` 顺序启动、validation |
|
||||
| 6 vault | (systemd 基础准备) | `get_url` vault zip 下载、解压放置 | 配置渲染、systemd/init、health |
|
||||
| 7 postgres | Docker 安装、common 基础 | `docker pull` PG 镜像、初始化独立 data 目录 | compose 渲染、`compose up`、health |
|
||||
| 8 litellm | apt/Homebrew Python 准备、Python 3.13 venv 创建、离线 wheelhouse 或 fallback pip 安装 | 下载 `litellm-runtime-<distro>-<version>-<arch>.tar.gz`、校验 SHA256、准备 `packages/pip`/`metadata/runtime.env` | 配置渲染、Prisma client generate、systemd/launchd、health(`:4000/health`) |
|
||||
| 9 qmd | (bun 运行时安装,全局) | 条件并发:qmd 拉取/`bun install`(隔离于 `~/.bun`,不碰 dpkg) | qmd.env/index.yml 渲染、systemd --user、health(`:8181`) |
|
||||
| 11 xfce(可选) | apt 桌面包/xrdp/chrome、`npm -g`/Playwright | — | xrdp 服务 enable/start、会话配置 |
|
||||
|
||||
> 说明:标“条件并发”的(如 qmd `bun`)仅当确认其只写入服务自身用户目录、且不与同时段其它全局安装争锁时才纳入 Phase 2,否则归 Phase 1。
|
||||
|
||||
### 10.4 Ansible 层 async 模式(保留全部属性)
|
||||
|
||||
在**单个 play 内**对 Phase 2 任务用 `poll:0` 发起、集中 `async_status` 收口。`register`/`when`/`notify`/`tags`/`become`/`failed_when` 一律保留:
|
||||
|
||||
```yaml
|
||||
- name: Download ttyd binary (async)
|
||||
ansible.builtin.get_url: { url: "...", dest: "{{ ttyd_path }}", mode: "0755" }
|
||||
async: 1800
|
||||
poll: 0
|
||||
register: ttyd_job
|
||||
|
||||
- name: Clone xworkspace-console (async)
|
||||
ansible.builtin.git: { repo: "...", dest: "{{ repo_dir }}", version: main, depth: 1 }
|
||||
become_user: "{{ xworkspace_console_user }}"
|
||||
async: 1800
|
||||
poll: 0
|
||||
register: console_clone_job
|
||||
|
||||
# …其它独立 Phase 2 任务一并 poll:0 发起…
|
||||
|
||||
- name: Collect async Phase-2 jobs
|
||||
ansible.builtin.async_status: { jid: "{{ item }}" }
|
||||
register: p2
|
||||
until: p2.finished
|
||||
retries: 120
|
||||
delay: 5
|
||||
loop:
|
||||
- "{{ ttyd_job.ansible_job_id }}"
|
||||
- "{{ console_clone_job.ansible_job_id }}"
|
||||
```
|
||||
|
||||
- 收口铁律:任一 Phase 2 产物在**被 Phase 3 消费前**必须 `finished`。
|
||||
- dpkg/全局 npm/全局 pip **绝不** `async`;LiteLLM venv 安装虽然不再是全局 pip,也应在 wheelhouse 准备完成后串行执行,便于失败定位与重试(§10.2)。
|
||||
|
||||
### 10.5 Shell 层动态 fork 并发(≤ CPU 核心数 × 2,预取层)
|
||||
|
||||
bootstrap 把可并行的外部 I/O 收敛到一个**负载自适应的有界 fork 池**,在 ansible 前(Phase 2 预取)与摘要阶段使用。硬上限为目标主机在线 CPU 核心数的 2 倍;`AI_WORKSPACE_MAX_PARALLEL_JOBS` 可设更低人工上限,默认 `auto`。每次启动子任务前读取 1 分钟 load average,按 `min(人工上限, 2 × CPU - ceil(load1))` 动态收缩,最低保留 1 路:
|
||||
|
||||
```bash
|
||||
CPU_COUNT="$(getconf _NPROCESSORS_ONLN)"
|
||||
HARD_LIMIT=$((CPU_COUNT * 2))
|
||||
LOAD_CEILING="$(awk -v load="$(cut -d' ' -f1 /proc/loadavg)" 'BEGIN { n=int(load); print load > n ? n + 1 : n }')"
|
||||
DYNAMIC_LIMIT=$((HARD_LIMIT - LOAD_CEILING))
|
||||
[ "$DYNAMIC_LIMIT" -ge 1 ] || DYNAMIC_LIMIT=1
|
||||
|
||||
run_bounded() {
|
||||
while [ "$(jobs -rp | wc -l)" -ge "$DYNAMIC_LIMIT" ]; do wait -n; done
|
||||
"$@" &
|
||||
}
|
||||
|
||||
# Phase 2 预取:5 仓库 pull + 二进制下载 + 镜像 pull(离线包存在则短路跳过)
|
||||
for r in playbooks console core-skills qmd litellm; do run_bounded fetch_repo "$r"; done
|
||||
for b in ttyd vault xworkmate-go-core; do run_bounded fetch_binary "$b"; done
|
||||
for img in "${PG_IMAGES[@]}"; do run_bounded docker_pull "$img"; done
|
||||
for p in "${pids[@]}"; do wait "$p" || rc=1; done
|
||||
[ "$rc" -eq 0 ] || { echo "[phase2] 存在失败子任务"; exit 1; }
|
||||
```
|
||||
|
||||
- 健康探测 fan-out(摘要前):对 Portal/Bridge/OpenClaw/QMD/Hermes/PG/Vault/LiteLLM 的 `systemctl is-active`+`curl` 使用同一动态上限,统一按固定顺序汇总。
|
||||
- 每子进程带日志前缀(`[repo:qmd]`/`[bin:vault]`),失败非零退出、不静默。
|
||||
- 串行保留:`ansible-playbook` 主执行(Phase 1/Phase 3 由其内部保证)、一次性 token/摘要打印。
|
||||
|
||||
### 10.6 不允许丢失的内容(硬约束)
|
||||
|
||||
逐一保留现有所有 tasks 及属性:`apt/package`、用户/目录/权限、env 文件、systemd unit 渲染、Caddy/Nginx、Docker/compose、服务启动、health check、`debug`、失败处理、`handlers`、`tags`、`become`、`when`、`notify`、`register`。**不得因并发删除/合并/跳过任何已有任务**;仅改变“何时等待”(`poll:0`+`async_status`),不改变“做什么”。
|
||||
|
||||
### 10.7 安全的全局提速(与 async 互补,不改 task 语义)
|
||||
|
||||
`ansible.cfg`(已存在)可叠加低风险项:
|
||||
|
||||
```ini
|
||||
[defaults]
|
||||
gathering = smart
|
||||
fact_caching = jsonfile
|
||||
fact_caching_connection = /tmp/ansible_facts
|
||||
[ssh_connection]
|
||||
pipelining = true
|
||||
```
|
||||
|
||||
并补足 TODO 关注点:APT/部署锁需**安全等待**(重试而非强删锁),保证二次幂等执行成功。`strategy: free` 单机收益有限、改变执行观感,**默认不启用**。
|
||||
|
||||
### 10.8 验收(等价性回归)
|
||||
|
||||
- [ ] 优化前后 `ansible-playbook --list-tasks` 任务集合一致(无丢失/合并)。
|
||||
- [ ] 每个 `async` 任务都有对应 `async_status` 收口,无悬挂 job。
|
||||
- [ ] Phase 1(apt/全局 npm/全局 pip/dpkg、LiteLLM venv 安装)与 Phase 3(daemon-reload/enable/start/health/摘要/清理)仍严格串行。
|
||||
- [ ] Phase 2 任务互不写同一文件、不抢同一锁;离线包存在时短路跳过。
|
||||
- [ ] 连续两次执行均成功、`changed=0` 幂等行为不变;Shell fork 池失败子任务非零退出且日志可见。
|
||||
|
||||
---
|
||||
|
||||
## 附录 A. AI Workspace All-in-One Setup(bootstrap 使用指南)
|
||||
|
||||
> 面向最终用户的官方安装指南,已合并入本规划作为单一权威来源。
|
||||
> 本附录相对上游 README 有两处校准:① `XWORKMATE_BRIDGE_PUBLIC_ACCESS` 默认 **`true`**(Bridge 为默认唯一公开服务);② `acp-bridge.onwalk.net` 为 **host-specific 自定义参数**,经 `XWORKMATE_BRIDGE_DOMAIN` 传入。
|
||||
|
||||
这是从 `xworkspace-console` 仓库安装 AI Workspace Runtime 的推荐 bootstrap 入口。脚本以该仓库为公开入口,随后通过 AI Workspace playbooks 与各组件仓库准备运行时服务。
|
||||
|
||||
### A.1 标准安装
|
||||
|
||||
适用于默认安全的本地工作区,仅需一个生成或既有的统一 token:
|
||||
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | bash -
|
||||
```
|
||||
|
||||
### A.2 进阶安装
|
||||
|
||||
在 `bash -` 前用环境变量自定义暴露面、安全级别与可选桌面功能:
|
||||
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | \
|
||||
AI_WORKSPACE_SECURITY_LEVEL=strict \
|
||||
XWORKSPACE_CONSOLE_ENABLE_XRDP=true \
|
||||
XWORKSPACE_CONSOLE_PUBLIC_ACCESS=true \
|
||||
XWORKMATE_BRIDGE_PUBLIC_ACCESS=true \
|
||||
GATEWAY_OPENCLAW_PUBLIC_ACCESS=false \
|
||||
VAULT_PUBLIC_ACCESS=false \
|
||||
LITELLM_API_CADDY_STRICT_WHITELIST=true \
|
||||
TOKEN="your-unified-auth-token" \
|
||||
bash -
|
||||
```
|
||||
|
||||
### A.3 推荐参数
|
||||
|
||||
| 变量 | 默认 | 推荐用法 |
|
||||
|---|---|---|
|
||||
| `TOKEN` | 生成或复用 | 为 Bridge、Portal、LiteLLM、OpenClaw、Vault 设置一个统一认证 token |
|
||||
| `AI_WORKSPACE_SECURITY_LEVEL` | `standard` | 公网/半公网主机使用 `strict` |
|
||||
| `XWORKMATE_BRIDGE_PUBLIC_ACCESS` | `true` | Bridge 为默认唯一公开服务;需关闭对外访问时显式设 `false` |
|
||||
| `XWORKMATE_BRIDGE_DOMAIN` | host-specific(自定义) | Bridge 公网域名,例如 `acp-bridge.onwalk.net` |
|
||||
| `XWORKSPACE_CONSOLE_PUBLIC_ACCESS` | `false` | 仅当 Portal 必须公开时开启;本地优先更安全 |
|
||||
| `GATEWAY_OPENCLAW_PUBLIC_ACCESS` | `false` | 除非 OpenClaw 必须直接暴露,保持 false |
|
||||
| `VAULT_PUBLIC_ACCESS` | `false` | 常规部署保持 false |
|
||||
| `LITELLM_API_CADDY_STRICT_WHITELIST` | `false` | strict 部署且 LiteLLM 经 Caddy 暴露时开启 |
|
||||
| `XWORKSPACE_CONSOLE_ENABLE_XRDP` | `false` | 仅当需要远程桌面访问时开启 |
|
||||
|
||||
### A.4 目标主机示例(当前 ACP Bridge 主机)
|
||||
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | \
|
||||
XWORKMATE_BRIDGE_DOMAIN=acp-bridge.onwalk.net \
|
||||
XWORKMATE_BRIDGE_PUBLIC_ACCESS=true \
|
||||
AI_WORKSPACE_SECURITY_LEVEL=strict \
|
||||
bash -
|
||||
```
|
||||
|
||||
### A.5 预期最终输出
|
||||
|
||||
部署成功后,脚本**一次性**打印部署域名与 token,随后报告以下服务状态:
|
||||
|
||||
- AI Workspace 域名与 token
|
||||
- OpenClaw
|
||||
- QMD
|
||||
- PostgreSQL
|
||||
- Vault
|
||||
- Workspace Portal / Console
|
||||
- LiteLLM
|
||||
- Agent CLI:opencode、gemini、codex、claude
|
||||
|
||||
> Token 输出务必私密保存,不得拷入前端源码或提交到 Git。
|
||||
|
||||
### A.6 本地 macOS 校验
|
||||
|
||||
在 macOS 上脚本默认进入本地校验模式,在 `http://127.0.0.1:17000` 启动 Portal。若因端口占用导致校验失败,先停止已有本地服务或在干净会话中重试。
|
||||
@ -1,3 +1,5 @@
|
||||
[🇺🇸 English](../../README.md) | [🇨🇳 中文](../../README.zh.md)
|
||||
|
||||
# XWorkspace Architecture
|
||||
|
||||
XWorkspace is an AI Workspace Shell built on top of standard Linux, systemd, Chrome / Chromium, and local runtime services.
|
||||
@ -79,6 +81,7 @@ XWorkspace is designed around the following principles:
|
||||
│ - Code Server │
|
||||
│ - File Browser │
|
||||
└──────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 3. Runtime Flow
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
[🇺🇸 English](../../README.md) | [🇨🇳 中文](../../README.zh.md)
|
||||
|
||||
# AI Workspace Data Management TL;DR
|
||||
|
||||
This document provides a quick reference for managing the AI Workspace lifecycle, including backup, restoration, migration, and uninstallation using the one-line bootstrap script.
|
||||
@ -1,3 +1,5 @@
|
||||
[🇺🇸 English](../../README.md) | [🇨🇳 中文](../../README.zh.md)
|
||||
|
||||
# XWorkspace Console Features
|
||||
|
||||
This document summarizes the user-facing and operator-facing features of XWorkspace Console. It is intended as the detailed feature reference linked from the homepage README.
|
||||
@ -1,3 +1,5 @@
|
||||
[🇺🇸 English](../../README.md) | [🇨🇳 中文](../../README.zh.md)
|
||||
|
||||
# Offline AI Workspace Installer
|
||||
|
||||
`offline-package-ai-workspace-installer.yaml` builds tarball resource packs for
|
||||
@ -1,3 +1,5 @@
|
||||
[🇺🇸 English](../../README.md) | [🇨🇳 中文](../../README.zh.md)
|
||||
|
||||
# Repository Overview
|
||||
|
||||
This document collects the repository details that are useful for maintainers and integrators, while keeping the homepage README focused on entry points.
|
||||
231
docs/en/RUNTIME_ARCHITECTURE.md
Normal file
231
docs/en/RUNTIME_ARCHITECTURE.md
Normal file
@ -0,0 +1,231 @@
|
||||
[🇺🇸 English](../../README.md) | [🇨🇳 中文](../../README.zh.md)
|
||||
|
||||
## 3. Current Situation Analysis: Role Hierarchy
|
||||
|
||||
`setup-ai-workspace-all-in-one.sh` (located in the console repository) runs `setup-ai-workspace-all-in-one.yml` (located in the playbooks repository) after bootstrapping on the target host. Its role hierarchy in import order is as follows:
|
||||
|
||||
```
|
||||
setup-ai-workspace-all-in-one.sh [repo: xworkspace-console/scripts]
|
||||
└─ ansible-playbook setup-ai-workspace-all-in-one.yml [repo: playbooks]
|
||||
├─1 setup-nodejs.yml → role roles/vhosts/nodejs NodeJS(22.x)+yarn
|
||||
├─2 setup-xworkspace-console.yaml WORKSPACE PORTAL/CONSOLE (inline task, no role)
|
||||
│ apt: caddy,xfce4,python3,golang-go,google-chrome-stable,ttyd
|
||||
│ git clone console → npm build; systemd --user: console(:17000)/api(:8788)/ttyd(:7681)/status.timer
|
||||
│ Caddy public site workspace.svc.plus ⚠ also public in standard mode
|
||||
├─3 setup-ai-agent-skills.yml → role roles/ai_agent_runtime AI WORKSPACE RUNTIME Core
|
||||
│ NodeJS(24.x)+Playwright; Agent CLI: opencode/gemini/codex/claude; Python/browser/docs/fonts
|
||||
│ └─ role agent_skills → inject xworkspace-core-skills market skills
|
||||
├─4 deploy_gateway_openclaw.yml → role roles/vhosts/gateway_openclaw OpenClaw(2026.5.28)
|
||||
├─5 deploy_xworkmate_bridge_vhosts.yml BRIDGE + ACP Cluster
|
||||
│ ├─ import setup-xworkspace-console.yaml (run again with bridge variables)
|
||||
│ └─ roles: acp_server_codex / acp_server_opencode / acp_server_gemini /
|
||||
│ acp_server_hermes / xworkmate_bridge(:8787 local, public Caddy)
|
||||
│ domain defaults to xworkmate-bridge.svc.plus → acp-bridge.onwalk.net
|
||||
├─6 setup-vault.yaml → role roles/vhosts/vault Vault(1.20.4) :8200
|
||||
├─7 setup-postgres-standalone.yaml → role roles/vhosts/postgres(dep: common) native apt PG17 :5432
|
||||
├─8 setup-litellm.yaml → role roles/vhosts/litellm pip install :4000
|
||||
├─9 deploy_QMD.yml → role roles/vhosts/qmd bun qmd, MCP :8181
|
||||
├─10 deploy_agent_hermes.yml → role roles/vhosts/acp_server_hermes ⚠ Hermes duplicate deployment (overlaps with step 5)
|
||||
└─11 setup-xfce-xrdp.yaml [Optional] → role roles/vhosts/xfce_xrdp_minimal
|
||||
→ Split into xfce_desktop_minimal_runtime + remote_desktop_xrdp_server
|
||||
```
|
||||
|
||||
### 3.1 Key Findings
|
||||
|
||||
1. **Public Surface Conflict**: Steps 2/5 deploy the public Caddy site for `workspace.svc.plus` when `ai_workspace_security_level != strict`, causing the Portal to also be exposed externally, which conflicts with "Bridge as the only public service".
|
||||
2. **Hermes Duplicate Deployment**: Step 5 (within the ACP cluster) and Step 10 (independent) each deploy it once, causing redundancy.
|
||||
3. **Scattered Version Pinning**: OpenClaw and Vault have fixed variables; NodeJS has them but is too loose (`22.x`/`24.x`); Hermes, QMD, and LiteLLM lack explicit version/source pinning.
|
||||
|
||||
---
|
||||
|
||||
## 4. Key Design Decisions
|
||||
|
||||
### 4.1 Public Surface: Bridge Only
|
||||
|
||||
- **Bridge is the default and only public service**: `XWORKMATE_BRIDGE_PUBLIC_ACCESS` defaults to `true`, and the public domain is passed customly via `XWORKMATE_BRIDGE_DOMAIN` (target host `acp-bridge.onwalk.net`). To disable this, explicitly set it to `false`.
|
||||
- `xworkspace_console_public_access` defaults to `false` (only public when `XWORKSPACE_CONSOLE_PUBLIC_ACCESS=true`).
|
||||
- `GATEWAY_OPENCLAW_PUBLIC_ACCESS` / `VAULT_PUBLIC_ACCESS` default to `false`; the rest (QMD / Hermes / PG / LiteLLM) maintain local listening (`127.0.0.1`) and do not deploy public Caddy sites.
|
||||
- Implementation approach: **Minimal changes** — only adjust default values/switches and align env names (§2.1), without removing the existing public_access capability (keep the manual override available).
|
||||
|
||||
### 4.2 Hermes Deduplication
|
||||
|
||||
- Remove the independent `deploy_agent_hermes.yml` import of Step 10 in `setup-ai-workspace-all-in-one.yml` (the ACP cluster in Step 5 already includes hermes).
|
||||
- Keep the `deploy_agent_hermes.yml` file itself for standalone deployment scenarios, only deduplicating it from the all-in-one aggregation chain.
|
||||
|
||||
### 4.3 Runtime Mode Matrix (docker / k3s / systemd)
|
||||
|
||||
Introduce a **validation** variable `ai_workspace_runtime_modes` (list), and add an `assert` guard at the top of the all-in-one without rewriting the deployment logic of each component:
|
||||
|
||||
| Constraint | Rule |
|
||||
|---|---|
|
||||
| Mutually Exclusive | `docker` and `k3s` cannot be present at the same time |
|
||||
| Composable | `docker + systemd` is allowed; `systemd` can be standalone |
|
||||
| Default | `['docker','systemd']` (most Agent services use systemd, PostgreSQL uses docker compose) |
|
||||
|
||||
Component to mode mapping (reusing existing capabilities, no heavy new implementations):
|
||||
|
||||
| Component | systemd | docker | k3s |
|
||||
|---|---|---|---|
|
||||
| Console / API / ttyd / Bridge / ACP / OpenClaw / QMD / LiteLLM | ✅ Default | — | — |
|
||||
| PostgreSQL | Optional | ✅ **Default docker compose** | Optional |
|
||||
| Vault | `vault_deploy_mode=systemd` | — | `vault_deploy_mode=kubernetes` (k3s) |
|
||||
|
||||
Guard pseudo-code (place in the top-level play of all-in-one):
|
||||
|
||||
```yaml
|
||||
- name: Validate runtime mode combination
|
||||
hosts: all
|
||||
gather_facts: false
|
||||
tasks:
|
||||
- assert:
|
||||
that:
|
||||
- not ('docker' in ai_workspace_runtime_modes and 'k3s' in ai_workspace_runtime_modes)
|
||||
- ai_workspace_runtime_modes | length > 0
|
||||
fail_msg: "docker and k3s are mutually exclusive; please select a valid combination of docker/k3s/systemd."
|
||||
```
|
||||
|
||||
### 4.4 PostgreSQL Default docker compose
|
||||
|
||||
- Add switch `postgresql_deploy_mode`, defaulting to `compose`.
|
||||
- `compose` mode: Add a compose deployment path in `roles/vhosts/postgres` (fixed image version, reusing existing variables for ports/passwords), coexisting with the current native apt path, choosing one exclusively.
|
||||
- Do not remove the native apt path (can fallback by setting `postgresql_deploy_mode=native`).
|
||||
|
||||
### 4.5 QMD / LiteLLM Source Repo and Version Pinning
|
||||
|
||||
- QMD: Installation source points to `https://github.com/ai-workspace-services/qmd.git`, adding `qmd_source_repo` / `qmd_version` variables for pinning.
|
||||
- LiteLLM: Installation source points to `https://github.com/ai-workspace-services/litellm.git`, adding `litellm_source_repo` / `litellm_version` variables for pinning.
|
||||
|
||||
---
|
||||
|
||||
## 10. Concurrency Optimization Design (Deep Analysis + Custom Strategy)
|
||||
|
||||
> Goal: Improve single-machine deployment speed **without dropping tasks, breaking existing role structures, or sacrificing stability**.
|
||||
> Overall Strategy: Three-phase execution — **Phase 1 Sequential (system global/lock grabbing) → Phase 2 Concurrent (mutually independent I/O) → Phase 3 Sequential (deterministic closing)**. Do not blindly convert multiple roles to concurrent; only make tasks that are "time-consuming, independent, non-writing to the same file, non-grabbing the same lock" `async`, and finally close with `async_status`.
|
||||
|
||||
### 10.1 Three-Phase Model (Authoritative Definition)
|
||||
|
||||
**Phase 1 — Must be sequential** (grabbing locks / modifying system global state):
|
||||
`apt update`, `apt install`, `dpkg` related, adding apt repo / keyring, user/group creation, base directory creation, base permissions setting, Docker installation, Caddy installation, systemd base preparation, basic firewall rules, **global pip / global npm(-g) installation**.
|
||||
|
||||
**Phase 2 — Can be concurrent** (mutually independent, no same-file writing, no same-lock grabbing):
|
||||
`docker pull` multiple images, downloading multiple binaries, `git clone` multiple repos, `go build`, `npm/pnpm install` in **different directories**, frontend builds in **different directories**, pulling plugins, pulling static assets, generating non-conflicting service configurations, initializing independent working directories for each service, independent prepare scripts for each service.
|
||||
|
||||
**Phase 3 — Must be sequential** (deterministic closing):
|
||||
Rendering final configurations, `systemd daemon-reload`, `enable service`, `start/restart` in dependency order, health checks, outputting deployment results, cleaning temporary files.
|
||||
|
||||
### 10.2 Key Customization Conclusions (Deep Analysis for this Playbook)
|
||||
|
||||
1. **All `npm -g` share the same prefix → must be Phase 1 sequential.**
|
||||
`roles/vhosts/nodejs` sets `npm_config_prefix=/usr/local/lib/npm`; Agent CLI (opencode-ai / @google/gemini-cli / @openai/codex / @anthropic-ai/claude-code), `yarn`, `openclaw@ver` all use `npm -g` to this prefix. Concurrency would contend for the same `node_modules`/`.staging` and npm cache lock → **Cannot be concurrent**.
|
||||
2. **LiteLLM has been changed to a standalone Python 3.13 venv, but dependency installation must still be sequential closing**. It no longer writes to system site-packages, but `pip install litellm[proxy]` has a large dependency tree and high network failure rate. The default direction should be to consume offline wheelhouse first, with online venv installation only as a fallback.
|
||||
3. **Truly safe Phase 2 candidates are "External I/O prefetching"**: git clone, binary downloads, docker pull, frontend builds in separate directories, runtime release downloads. They do not touch dpkg/npm-prefix/pip global locks and write to their own distinct paths.
|
||||
4. **The greatest concurrency benefit across sub-playbooks is at the Shell prefetch layer**: 11 steps are sequentially imported by ansible, making inter-play concurrency difficult; lifting parallelizable I/O to the Phase 2 fork pool in bootstrap (§10.5) for prefetching, while ansible only consumes ready artifacts, yields the highest risk/reward ratio.
|
||||
5. **Offline packages priority** (addresses TODO): When offline installation packages/imported images exist, Phase 2 prefetching should short-circuit and skip, directly reusing caches.
|
||||
|
||||
### 10.3 Current Tasks → Three-Phase Mapping
|
||||
|
||||
| Step / Role | Phase 1 (Sequential) | Phase 2 (Concurrent prefetchable) | Phase 3 (Sequential closing) |
|
||||
|---|---|---|---|
|
||||
| 1 nodejs | nodesource keyring/repo, `apt install nodejs`, `npm -g yarn` | — | — |
|
||||
| 2 console | apt(caddy/xfce4/python3/golang-go/chrome)+chrome repo/key, users/dirs/perms | `get_url` ttyd binary, `git clone` console, dashboard `npm install && build` (independent dir) | render systemd unit/env/portal-services.json, `daemon-reload`/enable/restart, Caddy write+reload |
|
||||
| 3 ai_agent_runtime | `npm -g` Agent CLI, global pip(python deps), apt(browser/docs/fonts), Playwright(-g) | `agent_skills` pull core-skills market (independent dir) | validation/health, register output |
|
||||
| 4 gateway_openclaw | `npm -g openclaw@ver`+plugins | (plugins can be concurrent if pulled to independent dirs) | configuration rendering, systemd, version assert, health |
|
||||
| 5 bridge + ACP | sync console; global install parts of acp_server_* | `xworkmate-go-core` binary download/placement, acp independent working directory prepare | render configs, start in `requires acp-*.service` order, validation |
|
||||
| 6 vault | (systemd base prep) | `get_url` vault zip download, extract and place | render config, systemd/init, health |
|
||||
| 7 postgres | Docker install, common base | `docker pull` PG image, initialize independent data dir | compose render, `compose up`, health |
|
||||
| 8 litellm | apt/Homebrew Python prep, Python 3.13 venv creation, offline wheelhouse or fallback pip install | Download `litellm-runtime-<distro>-<version>-<arch>.tar.gz`, SHA256 validation, prep `packages/pip`/`metadata/runtime.env` | Config render, Prisma client generate, systemd/launchd, health(`:4000/health`) |
|
||||
| 9 qmd | (bun runtime install, global) | conditional concurrency: pull qmd/`bun install` (isolated to `~/.bun`, does not touch dpkg) | qmd.env/index.yml render, systemd --user, health(`:8181`) |
|
||||
| 11 xfce (opt) | apt desktop packages/xrdp/chrome, `npm -g`/Playwright | — | xrdp service enable/start, session config |
|
||||
|
||||
> Note: Items marked "conditional concurrency" (like qmd `bun`) are included in Phase 2 only when confirmed to write strictly to the service's own user directory and not contend for global locks with other installations at the same time; otherwise, they fall into Phase 1.
|
||||
|
||||
### 10.4 Ansible Layer async Mode (Retaining all properties)
|
||||
|
||||
Within **a single play**, initiate Phase 2 tasks using `poll:0` and centrally close them with `async_status`. `register`/`when`/`notify`/`tags`/`become`/`failed_when` are always retained:
|
||||
|
||||
```yaml
|
||||
- name: Download ttyd binary (async)
|
||||
ansible.builtin.get_url: { url: "...", dest: "{{ ttyd_path }}", mode: "0755" }
|
||||
async: 1800
|
||||
poll: 0
|
||||
register: ttyd_job
|
||||
|
||||
- name: Clone xworkspace-console (async)
|
||||
ansible.builtin.git: { repo: "...", dest: "{{ repo_dir }}", version: main, depth: 1 }
|
||||
become_user: "{{ xworkspace_console_user }}"
|
||||
async: 1800
|
||||
poll: 0
|
||||
register: console_clone_job
|
||||
|
||||
# ...other independent Phase 2 tasks initiated with poll:0...
|
||||
|
||||
- name: Collect async Phase-2 jobs
|
||||
ansible.builtin.async_status: { jid: "{{ item }}" }
|
||||
register: p2
|
||||
until: p2.finished
|
||||
retries: 120
|
||||
delay: 5
|
||||
loop:
|
||||
- "{{ ttyd_job.ansible_job_id }}"
|
||||
- "{{ console_clone_job.ansible_job_id }}"
|
||||
```
|
||||
|
||||
- Iron rule for closing: Any Phase 2 product must be `finished` **before being consumed by Phase 3**.
|
||||
- dpkg / global npm / global pip are **never** `async`; although LiteLLM venv installation is no longer a global pip, it should also run sequentially after the wheelhouse preparation is complete, facilitating failure isolation and retry (§10.2).
|
||||
|
||||
### 10.5 Shell Layer Dynamic fork Concurrency (≤ CPU Cores × 2, prefetch layer)
|
||||
|
||||
Bootstrap converges parallelizable external I/O into a **load-adaptive bounded fork pool**, used before ansible (Phase 2 prefetch) and at the summary stage. The hard limit is 2 times the online CPU cores of the target host; `AI_WORKSPACE_MAX_PARALLEL_JOBS` can set a lower manual limit, defaulting to `auto`. Before starting each sub-task, it reads the 1-minute load average, dynamically shrinking based on `min(manual limit, 2 × CPU - ceil(load1))`, reserving at least 1 slot:
|
||||
|
||||
```bash
|
||||
CPU_COUNT="$(getconf _NPROCESSORS_ONLN)"
|
||||
HARD_LIMIT=$((CPU_COUNT * 2))
|
||||
LOAD_CEILING="$(awk -v load="$(cut -d' ' -f1 /proc/loadavg)" 'BEGIN { n=int(load); print load > n ? n + 1 : n }')"
|
||||
DYNAMIC_LIMIT=$((HARD_LIMIT - LOAD_CEILING))
|
||||
[ "$DYNAMIC_LIMIT" -ge 1 ] || DYNAMIC_LIMIT=1
|
||||
|
||||
run_bounded() {
|
||||
while [ "$(jobs -rp | wc -l)" -ge "$DYNAMIC_LIMIT" ]; do wait -n; done
|
||||
"$@" &
|
||||
}
|
||||
|
||||
# Phase 2 prefetch: pull 5 repos + download binaries + pull images (short-circuited if offline packages exist)
|
||||
for r in playbooks console core-skills qmd litellm; do run_bounded fetch_repo "$r"; done
|
||||
for b in ttyd vault xworkmate-go-core; do run_bounded fetch_binary "$b"; done
|
||||
for img in "${PG_IMAGES[@]}"; do run_bounded docker_pull "$img"; done
|
||||
for p in "${pids[@]}"; do wait "$p" || rc=1; done
|
||||
[ "$rc" -eq 0 ] || { echo "[phase2] Sub-tasks failed"; exit 1; }
|
||||
```
|
||||
|
||||
- Health check fan-out (before summary): Use the same dynamic limit for `systemctl is-active` + `curl` health endpoints of Portal/Bridge/OpenClaw/QMD/Hermes/PG/Vault/LiteLLM, summarizing them in a fixed order.
|
||||
- Each child process has a log prefix (`[repo:qmd]`/`[bin:vault]`), exits non-zero on failure, and is not silenced.
|
||||
- Sequential preservation: The main `ansible-playbook` execution (Phase 1/Phase 3 guaranteed internally), one-time token/summary printing.
|
||||
|
||||
### 10.6 Content that Must Not Be Lost (Hard Constraints)
|
||||
|
||||
Retain all existing tasks and properties one by one: `apt/package`, users/dirs/perms, env files, systemd unit rendering, Caddy/Nginx, Docker/compose, service starts, health checks, `debug`, failure handling, `handlers`, `tags`, `become`, `when`, `notify`, `register`. **Do not delete/merge/skip any existing task for the sake of concurrency**; only change "when to wait" (`poll:0`+`async_status`), not "what to do".
|
||||
|
||||
### 10.7 Safe Global Acceleration (Complementary to async, does not change task semantics)
|
||||
|
||||
`ansible.cfg` (already exists) can overlay low-risk items:
|
||||
|
||||
```ini
|
||||
[defaults]
|
||||
gathering = smart
|
||||
fact_caching = jsonfile
|
||||
fact_caching_connection = /tmp/ansible_facts
|
||||
[ssh_connection]
|
||||
pipelining = true
|
||||
```
|
||||
|
||||
And address TODO concerns: APT/deployment locks require **safe waiting** (retry rather than forceful lock deletion) to ensure secondary idempotent execution succeeds. `strategy: free` offers limited single-machine benefit and changes the execution feel, so it is **disabled by default**.
|
||||
|
||||
### 10.8 Acceptance (Equivalence Regression)
|
||||
|
||||
- [ ] The task sets from `ansible-playbook --list-tasks` are identical before and after optimization (no loss/merges).
|
||||
- [ ] Every `async` task has a corresponding `async_status` close, with no dangling jobs.
|
||||
- [ ] Phase 1 (apt/global npm/global pip/dpkg, LiteLLM venv install) and Phase 3 (daemon-reload/enable/start/health/summary/cleanup) remain strictly sequential.
|
||||
- [ ] Phase 2 tasks do not write to the same file or grab the same lock; they short-circuit and skip when offline packages exist.
|
||||
- [ ] Two consecutive executions both succeed; the idempotent behavior of `changed=0` remains unchanged; failed sub-tasks in the Shell fork pool exit non-zero with visible logs.
|
||||
|
||||
---
|
||||
93
docs/en/RUNTIME_DELIVERY_PLAN.md
Normal file
93
docs/en/RUNTIME_DELIVERY_PLAN.md
Normal file
@ -0,0 +1,93 @@
|
||||
[🇺🇸 English](../../README.md) | [🇨🇳 中文](../../README.zh.md)
|
||||
|
||||
# AI Workspace Runtime Delivery Plan
|
||||
|
||||
> Goal: Converge `setup-ai-workspace-all-in-one.sh` from "a set of scattered infrastructure Playbooks" into a **ready-to-use AI Workspace Runtime product**—version controlled, composable run modes, exposing only the Bridge externally, and outputting a one-time unified summary upon deployment completion.
|
||||
>
|
||||
> This document is the detailed plan before implementation (design + change list + commit/deploy/acceptance scheme). During the implementation phase, follow this document strictly, do not expand the scope of modification, do not do large-scale refactoring, and prioritize reusing existing implementations.
|
||||
|
||||
- Status: The Linux offline package pipeline and macOS local verification pipeline have entered the joint debugging phase; macOS has overcome most role compatibility blockers, the current focus is LiteLLM offline runtime integration, full installation rerun, and idempotent acceptance.
|
||||
- Impacted repositories: `ai-workspace-infra/playbooks`, `ai-workspace-lab/xworkspace-console`, `ai-workspace-lab/xworkspace-core-skills`, `ai-workspace-services/qmd`, `ai-workspace-services/litellm`
|
||||
- Target host: `root@acp-bridge.onwalk.net`
|
||||
- Default external domain (only public service): `acp-bridge.onwalk.net`
|
||||
|
||||
## TODO
|
||||
|
||||
- [x] Wait and check the offline package GitHub Actions release pipeline of `xworkspace-console`, confirm `publish-release` completes fully and release artifacts upload successfully.
|
||||
- [ ] Continue to check the remote deployment progress of `root@acp-bridge.onwalk.net`, confirm `setup-ai-workspace-all-in-one.sh` finally completes and outputs the unified summary.
|
||||
- [x] `setup-ai-workspace-all-in-one.sh` preferentially uses offline installation packages on the target host to accelerate deployment, reducing online pull and installation time.
|
||||
- [x] Add a runtime wheelhouse release workflow for LiteLLM, for all-in-one offline package consumption.
|
||||
- [ ] Verify that the `ai-workspace-services/litellm` runtime release actually generates successfully, and confirm the console offline package can download the matching `litellm-runtime-<distro>-<version>-<arch>.tar.gz`.
|
||||
- [ ] Verify the idempotency of `setup-ai-workspace-all-in-one.sh`: executing twice consecutively on the same host both succeed, reusing credentials, offline package cache and imported images, and safely waiting for deployment/APT locks.
|
||||
- [ ] Complete macOS local final acceptance check: Portal, Bridge, OpenClaw, QMD, Hermes, PostgreSQL, Vault, LiteLLM statuses are normal, `http://localhost:8181/mcp` and LiteLLM health are reachable.
|
||||
- [ ] Complete remote Linux final acceptance check: Bridge is externally reachable, other services only listen locally by default, `acp-codex` / `opencode` / `gemini` / `hermes` / `qmd` / `litellm` statuses are normal.
|
||||
- [ ] Record the final commit hash, GitHub Actions run, release tag and remote verification results, backfill into the delivery results section of this plan.
|
||||
|
||||
---
|
||||
|
||||
## 6. Repository and Commit Plan
|
||||
|
||||
| Repository | Main Changes | Commit message (suggested) | Push Target |
|
||||
|---|---|---|---|
|
||||
| `playbooks` | Role split, version pinning, Bridge domain, run-mode guard, PG compose, QMD/LiteLLM source, aggregation chain deduplication, this plan document | `feat: deliver versioned AI Workspace Runtime (role split, run-mode matrix, bridge domain)` | `ai-workspace-infra/playbooks` |
|
||||
| `xworkspace-console` | `setup-ai-workspace-all-in-one.sh` unified summary, pull source alignment, console not public by default | `feat: unified one-time deploy summary + bridge-only public surface` | `ai-workspace-lab/xworkspace-console` |
|
||||
| `xworkspace-core-skills` | (On demand) skills seed/version alignment | `chore: align skills seed for workspace runtime` | `ai-workspace-lab/xworkspace-core-skills` |
|
||||
|
||||
> Submit **independently** for each repository, record the Commit Hash separately and write into the final delivery description.
|
||||
|
||||
### 6.1 Current Implementation Progress (2026-06-22)
|
||||
|
||||
| Repository | Completed Progress | Known Pending Issues |
|
||||
|---|---|---|
|
||||
| `ai-workspace-infra/playbooks` | OpenClaw doctor/restart split; QMD macOS LaunchAgent added; OpenClaw `acpx` compatibility assert fixed; LiteLLM switched to Python 3.13 venv, installation detection and `.install-spec` skip redundant installation | Full macOS rerun needed to confirm `qmd :8181/mcp`, OpenClaw registry, LiteLLM health; need to confirm all-in-one macOS patch and playbooks main no longer overwrite each other |
|
||||
| `ai-workspace-lab/xworkspace-console` | all-in-one offline package pipeline can now consume console/bridge/qmd/litellm runtime releases; macOS debugging cases continuously recorded in `docs/case/macos_compatibility_tests.md` | `uninstall purge` still needs to print deleted paths; need to clean offline package generation directories and other non-source official directories; need to confirm `install.svc.plus/ai-workspace` publish entry syncs to latest main |
|
||||
| `ai-workspace-services/qmd` | all-in-one offline package script consumes release as `qmd-runtime-linux-${ARCH}.tar.gz`; playbooks added QMD macOS LaunchAgent | Need to confirm latest runtime release and offline package pull path remain available; macOS needs to actually test MCP endpoint |
|
||||
| `ai-workspace-services/litellm` | Added `.github/workflows/offline-package-litellm-runtime.yaml`, yielding `litellm-runtime-<distro>-<version>-<arch>.tar.gz`, wheelhouse, optional portable Python, `metadata/runtime.env` | Need to trigger GitHub Actions and confirm release asset and `SHA256SUMS`; need to confirm console offline package resolves this release using `latest-runtime` |
|
||||
| `ai-workspace-lab/xworkspace-core-skills` | all-in-one offline package still packages by core-skills repo/ref | Currently no new macOS blockers found; final acceptance still needs to confirm skill injection and OpenClaw/QMD visibility |
|
||||
|
||||
### 6.2 Recent Key Commits
|
||||
|
||||
| Repository | Commit | Description |
|
||||
|---|---|---|
|
||||
| `ai-workspace-infra/playbooks` | `09a39e6` | `perf(openclaw): avoid unnecessary doctor repairs` |
|
||||
| `ai-workspace-infra/playbooks` | `f01e0bb` | `fix(qmd): provision macOS LaunchAgent` |
|
||||
| `ai-workspace-infra/playbooks` | `c11f51b` | `fix(openclaw): allow version-matched acpx plugin` |
|
||||
| `ai-workspace-infra/playbooks` | `71ebe64` | `fix(litellm): isolate runtime in Python 3.13 venv` |
|
||||
| `ai-workspace-infra/playbooks` | `6a2f05f` | `fix(litellm): skip redundant dependency installs` |
|
||||
| `ai-workspace-services/litellm` | `51cde5e32` | `ci: add offline litellm runtime workflow` |
|
||||
|
||||
### 6.3 Issues Most Needing Closure Currently
|
||||
|
||||
1. `LiteLLM`: Online `pip install litellm[proxy]` may still fail due to large wheel download interruptions; the runtime wheelhouse release should be used as the default acceleration path for all-in-one, retaining the online path as fallback.
|
||||
2. `install.svc.plus/ai-workspace`: Need to confirm the public shortlink actually pulls the latest script from `xworkspace-console@main`, otherwise macOS may still run old bootstrap.
|
||||
3. `uninstall purge`: Need to output the paths to be deleted/deleted/non-existent, covering macOS and Linux tokens, Vault/OpenClaw states, temporary deployment directories, system configuration directories.
|
||||
4. Workspace cleanup: Need to clean generated directories like `ai-workspace-all-in-one-offline-*` to prevent offline package artifacts from mixing into the source root directory.
|
||||
5. Final acceptance: Need to do one clean installation and one repeat installation on macOS, recording each service port, LaunchAgent/systemd status, health endpoint and changed statistics.
|
||||
|
||||
---
|
||||
|
||||
## 8. Risks and Rollbacks
|
||||
|
||||
| Risk | Mitigation / Rollback |
|
||||
|---|---|
|
||||
| Sandbox cannot connect directly to GitHub/target host | Complete code+commits locally; push and remote deployment executed from an environment with network |
|
||||
| PG switching to compose affects existing data | Retain `postgresql_deploy_mode=native` rollback path |
|
||||
| Role split regression | `setup-xfce-xrdp.yaml` combines both roles, behavior is equivalent; retain old roles until reference switch passes validation |
|
||||
| Version pinning causes pull failure | Version variables are centralized, can be overridden at a single point (env / `-e`) |
|
||||
|
||||
---
|
||||
|
||||
## 9. Implementation Sequence (Delivery Order)
|
||||
|
||||
1. Check in this plan document (`docs/`).
|
||||
2. Role split + `setup-xfce-xrdp.yaml` combination.
|
||||
3. Version pinning (OpenClaw/Vault/Hermes/QMD/LiteLLM/Node/Playwright/Chrome).
|
||||
4. Bridge domain parameter pass-through (`XWORKMATE_BRIDGE_DOMAIN`, custom, does not change role default).
|
||||
5. Run-mode guard + PG compose default.
|
||||
6. Aggregation chain deduplication (Hermes) + console not public by default.
|
||||
7. `setup-ai-workspace-all-in-one.sh` unified summary.
|
||||
8. Commit separately for the three repositories, record Commit Hashes.
|
||||
9. Push + remote deployment + verify according to §7.2.
|
||||
10. Concurrency optimization delivery (see §10), finally do §10.8 equivalence regression.
|
||||
|
||||
---
|
||||
115
docs/en/RUNTIME_FEATURES.md
Normal file
115
docs/en/RUNTIME_FEATURES.md
Normal file
@ -0,0 +1,115 @@
|
||||
[🇺🇸 English](../../README.md) | [🇨🇳 中文](../../README.zh.md)
|
||||
|
||||
## 1. Delivery Goals and Acceptance Criteria
|
||||
|
||||
### 1.1 Overall Goals
|
||||
|
||||
1. Make necessary adjustments and submit them separately to the three repositories without expanding the scope of modifications or making large-scale refactors.
|
||||
2. Use `scripts/setup-ai-workspace-all-in-one.sh` to deploy AI Workspace to `root@acp-bridge.onwalk.net`.
|
||||
3. `xworkmate bridge` will uniformly use `acp-bridge.onwalk.net` as the external domain, and it is the **default and only public** service.
|
||||
4. Deliver a complete AI Workspace Runtime: versions of `xfce_desktop` + NodeJS + Playwright are all fully controlled.
|
||||
5. Runtime modes `docker / k3s / systemd` are optional and freely composable (`docker` and `k3s` are mutually exclusive, `docker + systemd` can be combined).
|
||||
6. Role split: `roles/vhosts/xfce_xrdp_minimal` → `roles/vhosts/xfce_desktop_minimal_runtime` + `roles/vhosts/remote_desktop_xrdp_server`.
|
||||
7. After the deployment script finishes, it will output a unified deployment summary **aimed at the end user**, and important authentication information will be **displayed only once**.
|
||||
|
||||
### 1.2 Acceptance Criteria (Definition of Done)
|
||||
|
||||
- [ ] Code submissions for all three repositories are completed, providing their respective Commit Hashes.
|
||||
- [ ] `setup-ai-workspace-all-in-one.sh` executes successfully in remote exec mode on the target host (no rsync, repositories are pulled from GitHub by the remote host).
|
||||
- [ ] Bridge uses `acp-bridge.onwalk.net` externally; other services are not public by default.
|
||||
- [ ] The script finishes by outputting a unified deployment summary: access entry points, one-time credentials, running status of each service, and available Agent CLIs.
|
||||
- [ ] Versions of `xfce_desktop / NodeJS / Playwright` can all be found and pinned in a single source of truth (role defaults).
|
||||
- [ ] Two consecutive installations on the same host both succeed; the second execution does not generate new credentials, does not redownload the same release packages, and waits for concurrent APT/dpkg operations rather than breaking them.
|
||||
|
||||
---
|
||||
|
||||
## 5. Detailed Change List
|
||||
|
||||
### 5.1 Role Split: `xfce_xrdp_minimal` → Two Roles
|
||||
|
||||
Split by responsibility, **file-by-file mapping**, preserving behavior; `setup-xfce-xrdp.yaml` is modified to sequentially compose the two new roles.
|
||||
|
||||
**`roles/vhosts/xfce_desktop_minimal_runtime` (Desktop Runtime)**
|
||||
|
||||
| Source | Destination | Description |
|
||||
|---|---|---|
|
||||
| `tasks/install.yml` (only desktop packages: `xfce4-session/xfwm4/xfdesktop4/xfce4-panel/xfce4-terminal/dbus-x11/fonts-noto-cjk/xserver-xorg-core`) | `tasks/install.yml` | Removed `xorgxrdp/xrdp` packages and xrdp service start |
|
||||
| `tasks/browser.yml` (Fixed version of Google Chrome) | `tasks/browser.yml` | Kept as is |
|
||||
| New `tasks/runtime.yml` | NodeJS + Playwright (references existing fixed version variables from `nodejs` / `ai_agent_runtime`) | Version-controlled single source of truth |
|
||||
| `defaults/main.yml` (desktop/chrome/node/playwright version variables) | `defaults/main.yml` | See §5.2 version table |
|
||||
|
||||
**`roles/vhosts/remote_desktop_xrdp_server` (Remote Desktop XRDP Service)**
|
||||
|
||||
| Source | Destination | Description |
|
||||
|---|---|---|
|
||||
| `tasks/install.yml` (`xorgxrdp/xrdp`, ssl-cert group, daemon-reload, enable/start, unit validation/fail) | `tasks/install.yml` | XRDP service layer |
|
||||
| `tasks/config.yml` (User/password RDP authentication, `.xsession`, xfconf directory) | `tasks/config.yml` | RDP session glue |
|
||||
| `handlers/main.yml` (Restart xrdp / sesman) | `handlers/main.yml` | Kept as is |
|
||||
| `vars/main.yml` (`xfce_xrdp_services` etc.) + `xfce_rdp_port/xfce_enable_ufw` | `defaults`/`vars` | Ports/ufw |
|
||||
|
||||
**Composition Point `setup-xfce-xrdp.yaml`:**
|
||||
|
||||
```yaml
|
||||
- name: Deploy XFCE desktop + optional XRDP (Optional)
|
||||
hosts: all
|
||||
become: true
|
||||
vars:
|
||||
xworkspace_console_enable_xrdp: false
|
||||
tasks:
|
||||
- include_role: { name: roles/vhosts/xfce_desktop_minimal_runtime }
|
||||
- include_role: { name: roles/vhosts/remote_desktop_xrdp_server }
|
||||
when: xworkspace_console_enable_xrdp | bool
|
||||
```
|
||||
|
||||
> Old role `roles/vhosts/xfce_xrdp_minimal`: Delete it after the split is complete and all references have been switched (the only current reference is `setup-xfce-xrdp.yaml`).
|
||||
|
||||
### 5.2 Version Pinning Table (Single Source of Truth)
|
||||
|
||||
| Component | Variable | Current | Target | File |
|
||||
|---|---|---|---|---|
|
||||
| OpenClaw | `gateway_openclaw_required_version` | `2026.5.28` | `2026.6.1` | `roles/vhosts/gateway_openclaw/defaults/main.yml:23` |
|
||||
| Vault | `vault_version` (env default) | `1.20.4` | `1.21.4` | `roles/vhosts/vault/vars/main.yml:6` |
|
||||
| Hermes | `acp_hermes_version` (New) | None | `0.15` | `roles/vhosts/acp_server_hermes/defaults/main.yml` |
|
||||
| QMD | `qmd_version` / `qmd_source_repo` (New) | None | From `ai-workspace-services/qmd` | `roles/vhosts/qmd/defaults/main.yml` |
|
||||
| LiteLLM | `litellm_version` / `litellm_source_repo` (New) | None | From `ai-workspace-services/litellm` | `roles/vhosts/litellm/defaults/main.yml` |
|
||||
| NodeJS | `nodejs_version` / `ai_agent_runtime_nodejs_version` | `22.x` / `24.x` | Pin to specific minor version | `roles/vhosts/nodejs/defaults` + `roles/ai_agent_runtime/defaults` |
|
||||
| Playwright | `ai_agent_runtime_playwright_version` (New/pinned) | No explicit | Pinned | `roles/ai_agent_runtime/defaults/main.yml` |
|
||||
| Google Chrome | `xfce_google_chrome_version` | `148.0.7778.167-1` | Keep pinned | Runtime role `defaults/main.yml` |
|
||||
| XFCE | `xfce_packages` | List | Keep (pinned by apt distro) | Runtime role `defaults/main.yml` |
|
||||
|
||||
### 5.3 Bridge External Domain (Custom Parameter, Not Hardcoded Default)
|
||||
|
||||
- **`acp-bridge.onwalk.net` is a host-specific custom parameter**, passed via `XWORKMATE_BRIDGE_DOMAIN` during deployment, **not hardcoded as a role default**.
|
||||
- Implementation key points (minimal changes): Ensure `XWORKMATE_BRIDGE_DOMAIN` is correctly passed through from the bootstrap script → playbook → `roles/vhosts/xworkmate_bridge`. The existing env override chain already supports this: `XWORKMATE_BRIDGE_DOMAIN` → `ai_workspace_public_domain` (`SERVER_DOMAIN/ACP_BRIDGE_DOMAIN/BRIDGE_DOMAIN`).
|
||||
- The neutral fallback default value in `roles/vhosts/xworkmate_bridge/defaults/main.yml:47` (`xworkmate-bridge.svc.plus`) **remains unchanged**—it serves only as a fallback when no explicit parameter is passed; the target host specifies the real domain via `XWORKMATE_BRIDGE_DOMAIN=acp-bridge.onwalk.net`.
|
||||
- Acceptance only requires "Bridge uses the specified domain", which is met by the custom parameter, requiring no changes to role defaults.
|
||||
|
||||
### 5.4 Deployment Script Unified Summary (`setup-ai-workspace-all-in-one.sh`)
|
||||
|
||||
At the end of the existing script (in the console repository, roughly 39KB), **append** a block for summary rendering (probing real-time host status, without hardcoding), structured as follows:
|
||||
|
||||
```
|
||||
================ AI Workspace Deployment Summary ================
|
||||
[Access Entry]
|
||||
Workspace Portal (Console) : http://127.0.0.1:17000 (Local)
|
||||
XWorkMate Bridge : https://acp-bridge.onwalk.net ← Only Public
|
||||
[One-time Credentials] (displayed once only)
|
||||
AI_WORKSPACE_AUTH_TOKEN : ********
|
||||
Vault root token : ********
|
||||
[Service Status]
|
||||
Portal / Bridge / OpenClaw / QMD / Hermes / PostgreSQL / Vault / LiteLLM : active/inactive
|
||||
[Agent CLI]
|
||||
opencode / gemini / codex / claude : <version | Missing>
|
||||
======================================================
|
||||
```
|
||||
|
||||
- Status probing reuses the `generate-status.py` logic from the console and the `validate.yml` health checks of each role (`systemctl is-active` + `curl` health endpoints).
|
||||
- Credentials "displayed once only": The summary reads the tokens from the persisted token files and prompts the user to save them; the script does not repeatedly print them.
|
||||
|
||||
### 5.5 all-in-one Aggregation Chain Adjustments
|
||||
|
||||
- Add the §4.3 runtime mode `assert` guard play at the top.
|
||||
- Remove the Step 10 independent `deploy_agent_hermes.yml` import (deduplication, see §4.2).
|
||||
- The rest of the import order remains unchanged.
|
||||
|
||||
---
|
||||
185
docs/en/RUNTIME_SETUP.md
Normal file
185
docs/en/RUNTIME_SETUP.md
Normal file
@ -0,0 +1,185 @@
|
||||
[🇺🇸 English](../../README.md) | [🇨🇳 中文](../../README.zh.md)
|
||||
|
||||
## 2. Deploy Execution Model (Remote exec / GitHub pull)
|
||||
|
||||
- `scripts/setup-ai-workspace-all-in-one.sh` runs **on the remote host**, purely in remote exec mode.
|
||||
- **Do not use rsync**; the required repositories are `pull`ed directly from GitHub by the remote host:
|
||||
- Playbooks: `https://github.com/ai-workspace-infra/playbooks.git`
|
||||
- Core Skills: `https://github.com/ai-workspace-lab/xworkspace-core-skills.git`
|
||||
- Console (where the script itself resides): `https://github.com/ai-workspace-lab/xworkspace-console.git`
|
||||
- QMD: `https://github.com/ai-workspace-services/qmd.git`
|
||||
- LiteLLM: `https://github.com/ai-workspace-services/litellm.git`
|
||||
- Implication: **Local commits must be pushed to the above GitHub repositories before remote deployment can fetch the changes**.
|
||||
|
||||
> ⚠️ Note the repository address inconsistency: the local `origin` of playbooks is currently `git@github.com:x-evor/playbooks.git`, but the authoritative source for deployment is `ai-workspace-infra/playbooks`. During the implementation phase, align the pull source in the script to `ai-workspace-infra/playbooks` and push commits to that repository.
|
||||
|
||||
### 2.1 Environment Variable Interface Contract (Authoritative)
|
||||
|
||||
The bootstrap entry is fixed to the original script in the console repository. All exposure/security/optional desktop behaviors are controlled via environment variables prior to `bash -`.
|
||||
|
||||
**Standard Install** (default secure local workspace, requires only one unified token):
|
||||
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | bash -
|
||||
```
|
||||
|
||||
**All Parameters (Defaults and Recommended Usage):**
|
||||
|
||||
| Variable | Default | Recommended Use |
|
||||
|---|---|---|
|
||||
| `TOKEN` | generated or reused | Set a **unified** auth token for Bridge / Portal / LiteLLM / OpenClaw / Vault |
|
||||
| `AI_WORKSPACE_SECURITY_LEVEL` | `standard` | Use `strict` for public/semi-public hosts |
|
||||
| `XWORKMATE_BRIDGE_PUBLIC_ACCESS` | `true` | Bridge is the default sole public service; explicitly set `false` to disable external access |
|
||||
| `XWORKMATE_BRIDGE_DOMAIN` | host-specific | Set the public Bridge domain, e.g., `acp-bridge.onwalk.net` |
|
||||
| `XWORKSPACE_CONSOLE_PUBLIC_ACCESS` | `false` | Enable only when Portal must be public; local-first is safer |
|
||||
| `XWORKSPACE_CONSOLE_ENABLE_XRDP` | `false` | Enable only when remote desktop access is required |
|
||||
| `GATEWAY_OPENCLAW_PUBLIC_ACCESS` | `false` | Keep false unless OpenClaw must be exposed directly |
|
||||
| `VAULT_PUBLIC_ACCESS` | `false` | Keep false for normal deployments |
|
||||
| `LITELLM_API_CADDY_STRICT_WHITELIST` | `false` | Enable in strict mode when LiteLLM is exposed via Caddy |
|
||||
|
||||
**Advanced Install Example:**
|
||||
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | \
|
||||
AI_WORKSPACE_SECURITY_LEVEL=strict \
|
||||
XWORKSPACE_CONSOLE_ENABLE_XRDP=true \
|
||||
XWORKSPACE_CONSOLE_PUBLIC_ACCESS=true \
|
||||
XWORKMATE_BRIDGE_PUBLIC_ACCESS=true \
|
||||
GATEWAY_OPENCLAW_PUBLIC_ACCESS=false \
|
||||
VAULT_PUBLIC_ACCESS=false \
|
||||
LITELLM_API_CADDY_STRICT_WHITELIST=true \
|
||||
TOKEN="your-unified-auth-token" \
|
||||
bash -
|
||||
```
|
||||
|
||||
**Target Host (ACP Bridge) Example:**
|
||||
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | \
|
||||
XWORKMATE_BRIDGE_DOMAIN=acp-bridge.onwalk.net \
|
||||
XWORKMATE_BRIDGE_PUBLIC_ACCESS=true \
|
||||
AI_WORKSPACE_SECURITY_LEVEL=strict \
|
||||
bash -
|
||||
```
|
||||
|
||||
> Key Alignment: `XWORKMATE_BRIDGE_PUBLIC_ACCESS` defaults to **`true`**——Bridge is the **default and only public** service (with its domain passed customized via `XWORKMATE_BRIDGE_DOMAIN`); other services (Console/OpenClaw/Vault/QMD/Hermes/PG/LiteLLM) default to `false` and remain listening on `127.0.0.1` locally. If you need to disable external access to the Bridge, explicitly set `XWORKMATE_BRIDGE_PUBLIC_ACCESS=false`. The `TOKEN` output must be kept private——do not copy it into frontend source code or commit it to Git.
|
||||
|
||||
### 2.2 Expected Final Output (Deployment Summary)
|
||||
|
||||
Upon successful deployment, the script will print the deployment domain and token **exactly once**, followed by the running status of each service:
|
||||
|
||||
- AI Workspace domain and token (displayed once only)
|
||||
- OpenClaw
|
||||
- QMD
|
||||
- PostgreSQL
|
||||
- Vault
|
||||
- Workspace Portal / Console
|
||||
- LiteLLM
|
||||
- Hermes
|
||||
- Agent CLI: opencode, gemini, codex, claude
|
||||
|
||||
### 2.3 Local macOS Validation Mode
|
||||
|
||||
On macOS, the script defaults to **local validation mode** and starts the Portal at `http://127.0.0.1:17000`. If validation fails due to port conflict, stop the existing local service or retry in a clean session.
|
||||
|
||||
---
|
||||
|
||||
## 7. Deployment and Validation
|
||||
|
||||
### 7.1 Deployment Command (Execute on the target host or in an environment with network/SSH access to it)
|
||||
|
||||
```bash
|
||||
# Remote exec: The script pulls the repos from GitHub onto the host and runs ansible to localhost
|
||||
# Adopts §2.1 authoritative env var contract (Target Host Example)
|
||||
ssh root@acp-bridge.onwalk.net \
|
||||
'curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | \
|
||||
XWORKMATE_BRIDGE_DOMAIN=acp-bridge.onwalk.net \
|
||||
XWORKMATE_BRIDGE_PUBLIC_ACCESS=true \
|
||||
AI_WORKSPACE_SECURITY_LEVEL=strict \
|
||||
bash -'
|
||||
```
|
||||
|
||||
### 7.2 Validation Checklist
|
||||
|
||||
- [ ] The script finishes by outputting a unified summary, and the Bridge displays `https://acp-bridge.onwalk.net`.
|
||||
- [ ] `curl -I https://acp-bridge.onwalk.net` is reachable; other service ports are listening only on `127.0.0.1`.
|
||||
- [ ] `systemctl --user is-active` shows each service is `active`.
|
||||
- [ ] `opencode/gemini/codex/claude --version` are all executable.
|
||||
- [ ] Credentials appear only once in the summary.
|
||||
|
||||
---
|
||||
|
||||
## Appendix A. AI Workspace All-in-One Setup (Bootstrap User Guide)
|
||||
|
||||
> Official installation guide intended for end users, integrated into this plan as the single authoritative source.
|
||||
> This appendix has two alignments compared to the upstream README: ① `XWORKMATE_BRIDGE_PUBLIC_ACCESS` defaults to **`true`** (Bridge is the default sole public service); ② `acp-bridge.onwalk.net` is a **host-specific custom parameter** passed via `XWORKMATE_BRIDGE_DOMAIN`.
|
||||
|
||||
This is the recommended bootstrap entry point to install the AI Workspace Runtime from the `xworkspace-console` repository. The script uses this repository as the public entry point, then prepares runtime services through AI Workspace playbooks and component repositories.
|
||||
|
||||
### A.1 Standard Install
|
||||
|
||||
Suitable for default secure local workspaces where only a generated or existing unified token is needed:
|
||||
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | bash -
|
||||
```
|
||||
|
||||
### A.2 Advanced Install
|
||||
|
||||
Use environment variables before `bash -` to customize the exposure surface, security level, and optional desktop features:
|
||||
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | \
|
||||
AI_WORKSPACE_SECURITY_LEVEL=strict \
|
||||
XWORKSPACE_CONSOLE_ENABLE_XRDP=true \
|
||||
XWORKSPACE_CONSOLE_PUBLIC_ACCESS=true \
|
||||
XWORKMATE_BRIDGE_PUBLIC_ACCESS=true \
|
||||
GATEWAY_OPENCLAW_PUBLIC_ACCESS=false \
|
||||
VAULT_PUBLIC_ACCESS=false \
|
||||
LITELLM_API_CADDY_STRICT_WHITELIST=true \
|
||||
TOKEN="your-unified-auth-token" \
|
||||
bash -
|
||||
```
|
||||
|
||||
### A.3 Recommended Parameters
|
||||
|
||||
| Variable | Default | Recommended Use |
|
||||
|---|---|---|
|
||||
| `TOKEN` | generated or reused | Set one unified auth token for Bridge, Portal, LiteLLM, OpenClaw, and Vault |
|
||||
| `AI_WORKSPACE_SECURITY_LEVEL` | `standard` | Use `strict` for public/semi-public hosts |
|
||||
| `XWORKMATE_BRIDGE_PUBLIC_ACCESS` | `true` | Bridge is the default sole public service; explicitly set `false` to disable external access |
|
||||
| `XWORKMATE_BRIDGE_DOMAIN` | host-specific (custom) | Public Bridge domain, e.g., `acp-bridge.onwalk.net` |
|
||||
| `XWORKSPACE_CONSOLE_PUBLIC_ACCESS` | `false` | Enable only when Portal must be public; local-first is safer |
|
||||
| `GATEWAY_OPENCLAW_PUBLIC_ACCESS` | `false` | Keep false unless OpenClaw must be exposed directly |
|
||||
| `VAULT_PUBLIC_ACCESS` | `false` | Keep false for normal deployments |
|
||||
| `LITELLM_API_CADDY_STRICT_WHITELIST` | `false` | Enable for strict deployments when LiteLLM is exposed via Caddy |
|
||||
| `XWORKSPACE_CONSOLE_ENABLE_XRDP` | `false` | Enable only when remote desktop access is required |
|
||||
|
||||
### A.4 Target Host Example (Current ACP Bridge Host)
|
||||
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | \
|
||||
XWORKMATE_BRIDGE_DOMAIN=acp-bridge.onwalk.net \
|
||||
XWORKMATE_BRIDGE_PUBLIC_ACCESS=true \
|
||||
AI_WORKSPACE_SECURITY_LEVEL=strict \
|
||||
bash -
|
||||
```
|
||||
|
||||
### A.5 Expected Final Output
|
||||
|
||||
Upon successful deployment, the script prints the deployment domain and token **exactly once**, and then reports the status of the following services:
|
||||
|
||||
- AI Workspace domain and token
|
||||
- OpenClaw
|
||||
- QMD
|
||||
- PostgreSQL
|
||||
- Vault
|
||||
- Workspace Portal / Console
|
||||
- LiteLLM
|
||||
- Agent CLI: opencode, gemini, codex, claude
|
||||
|
||||
> The Token output must be kept private, and not copied into frontend source code or committed to Git.
|
||||
|
||||
### A.6 Local macOS Validation
|
||||
|
||||
On macOS, the script defaults to local validation mode and starts the Portal at `http://127.0.0.1:17000`. If validation fails due to port conflicts, stop any existing local service or retry in a clean session.
|
||||
@ -1,3 +1,5 @@
|
||||
[🇺🇸 English](../../README.md) | [🇨🇳 中文](../../README.zh.md)
|
||||
|
||||
# AI Workspace All-in-One Setup
|
||||
|
||||
This is the recommended bootstrap entry for installing AI Workspace Runtime from the `xworkspace-console` repository.
|
||||
29
docs/en/VERSION_MATRIX.md
Normal file
29
docs/en/VERSION_MATRIX.md
Normal file
@ -0,0 +1,29 @@
|
||||
[🇺🇸 English](../../README.md) | [🇨🇳 中文](../../README.zh.md)
|
||||
|
||||
# Version Matrix
|
||||
|
||||
This document lists the recommended runtime environments and component versions for the AI Workspace Lab Console (XWorkspace Console) and its associated components.
|
||||
|
||||
## Operating Systems
|
||||
- **macOS**: 26 / 27
|
||||
- **Linux (Debian)**: 11 / 12 / 13
|
||||
- **Linux (Ubuntu LTS)**: 22.04 / 24.04 / 26.04
|
||||
|
||||
## Runtimes
|
||||
- **Python**: 3.14
|
||||
- **NodeJS**: 22
|
||||
|
||||
## Services & Components
|
||||
- **OpenClaw**: 2026.6.1
|
||||
- **QMD**: 2.1 (Custom Edition)
|
||||
- **Hermes**: 1.15
|
||||
- **PostgreSQL**: 16
|
||||
- **Extensions**: `pgvector`, `uuid-ossp`, `pgcrypto`
|
||||
- **Vault**: v1.21.4
|
||||
- **LiteLLM**: v1.89
|
||||
|
||||
## Code Agent CLI
|
||||
- `gemini` (Antigravity)
|
||||
- `code`
|
||||
- `opencode`
|
||||
- `claude`
|
||||
104
docs/en/case/combination_tests.md
Normal file
104
docs/en/case/combination_tests.md
Normal file
@ -0,0 +1,104 @@
|
||||
[🇺🇸 English](../../../README.md) | [🇨🇳 中文](../../../README.zh.md)
|
||||
|
||||
# Combination Test Cases
|
||||
|
||||
This document defines the end-to-end combination test matrix for `setup-ai-workspace-all-in-one.sh`.
|
||||
|
||||
## Test Prerequisites
|
||||
|
||||
| Condition | Description |
|
||||
|------|------|
|
||||
| Supported Platforms | macOS (Darwin) / Debian / Ubuntu |
|
||||
| Required Tools | `curl`, `bash` (`brew` is additionally required on macOS) |
|
||||
| Network Requirements | Accessible to GitHub / npm registry |
|
||||
|
||||
---
|
||||
|
||||
## Test Matrix
|
||||
|
||||
### COMBO-001: Fresh Installation (No API Key)
|
||||
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | bash -
|
||||
```
|
||||
|
||||
**Expected Result**: Installation completes, services like LiteLLM start with empty configurations, and the console is accessible.
|
||||
|
||||
---
|
||||
|
||||
### COMBO-002: Fresh Installation + API Key Injection
|
||||
|
||||
```bash
|
||||
export DEEPSEEK_API_KEY="sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
export NVIDIA_API_KEY="nvapi-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
export OLLAMA_API_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxx"
|
||||
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | bash -
|
||||
```
|
||||
|
||||
**Expected Result**: Installation completes, API keys are automatically injected into the LiteLLM configuration, and the AI model gateway can proxy requests normally.
|
||||
|
||||
---
|
||||
|
||||
### COMBO-003: Uninstall (Keep Data)
|
||||
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | bash -s -- uninstall
|
||||
```
|
||||
|
||||
**Expected Result**: All services are stopped, runtime files are removed, but user data and configurations are preserved.
|
||||
|
||||
---
|
||||
|
||||
### COMBO-004: Complete Uninstall (Purge All Data)
|
||||
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | bash -s -- uninstall --purge
|
||||
```
|
||||
|
||||
**Expected Result**: All services are stopped, runtime files are removed, and all user data, configurations, and local databases are purged.
|
||||
|
||||
---
|
||||
|
||||
### COMBO-005: Reinstall after Uninstall (Full Lifecycle)
|
||||
|
||||
```bash
|
||||
# Step 1: Complete Uninstall
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | bash -s -- uninstall --purge
|
||||
|
||||
# Step 2: Reinstall with Keys
|
||||
export DEEPSEEK_API_KEY="sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
export NVIDIA_API_KEY="nvapi-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
export OLLAMA_API_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxx"
|
||||
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | bash -
|
||||
```
|
||||
|
||||
**Expected Result**: Uninstall leaves no residue, everything runs normally after reinstallation, and API keys are injected correctly.
|
||||
|
||||
---
|
||||
|
||||
### COMBO-006: Idempotency Test (Repeated Installation)
|
||||
|
||||
```bash
|
||||
# Run installation twice consecutively
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | bash -
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | bash -
|
||||
```
|
||||
|
||||
**Expected Result**: The second run should complete idempotently without errors, and the `changed` count should be close to 0.
|
||||
|
||||
---
|
||||
|
||||
## Platform Coverage Matrix
|
||||
|
||||
| Test ID | macOS (Darwin) | Debian | Ubuntu |
|
||||
|----------|:--------------:|:------:|:------:|
|
||||
| COMBO-001 | ✅ | ✅ | ✅ |
|
||||
| COMBO-002 | ✅ | ✅ | ✅ |
|
||||
| COMBO-003 | ✅ | ✅ | ✅ |
|
||||
| COMBO-004 | ✅ | ✅ | ✅ |
|
||||
| COMBO-005 | ✅ | ✅ | ✅ |
|
||||
| COMBO-006 | ✅ | ✅ | ✅ |
|
||||
|
||||
> **Note**: Currently, only macOS / Debian / Ubuntu have been verified by actual tests; other Linux distributions are untested.
|
||||
368
docs/en/case/macos_compatibility_tests.md
Normal file
368
docs/en/case/macos_compatibility_tests.md
Normal file
@ -0,0 +1,368 @@
|
||||
[🇺🇸 English](../../../README.md) | [🇨🇳 中文](../../../README.zh.md)
|
||||
|
||||
# macOS Compatibility Deployment Test Cases
|
||||
|
||||
This document records the cross-platform compatibility issues encountered and their fix solutions during the fully automated deployment of `setup-ai-workspace-all-in-one.sh` in the macOS (Darwin) environment.
|
||||
|
||||
## Core Background
|
||||
|
||||
The original script and Ansible Playbooks were designed for Debian/Ubuntu Linux, strongly relying on `root` permissions, the `apt` package manager, system directories (`/usr/local/sbin`, `/etc/systemd`), and default user paths (`/home/ubuntu`). Deploying in unprivileged mode on macOS triggered a massive amount of permission and path exceptions.
|
||||
|
||||
---
|
||||
|
||||
## TC-MAC-001: TTYD Binary and Path Exceptions
|
||||
|
||||
| Item | Content |
|
||||
|------|------|
|
||||
| **Trigger File** | `setup-ai-workspace-all-in-one.sh` |
|
||||
| **Trigger Error** | The script attempts to download the ttyd binary and write it to `/usr/local/bin/ttyd`, but lacks permissions and the architecture mismatches |
|
||||
| **Fix Solution** | Intercept binary download under Darwin, switch to `brew install ttyd`; use `command -v ttyd` to dynamically resolve the path |
|
||||
|
||||
## TC-MAC-002: Global Privilege Escalation (Sudo) Blocking
|
||||
|
||||
| Item | Content |
|
||||
|------|------|
|
||||
| **Trigger File** | `setup-ai-workspace-all-in-one.sh` → Ansible Playbook |
|
||||
| **Trigger Error** | `sudo: a password is required` |
|
||||
| **Fix Solution** | Inject `--extra-vars "ansible_become=false"` under Darwin to cancel automatic privilege escalation |
|
||||
|
||||
## TC-MAC-003: Default User Group Allocation Failure
|
||||
|
||||
| Item | Content |
|
||||
|------|------|
|
||||
| **Trigger File** | `setup-xworkspace-console.yaml` |
|
||||
| **Trigger Error** | `chown` cannot find the `ubuntu` group |
|
||||
| **Fix Solution** | Conditional rendering: `"{{ 'staff' if ansible_os_family == 'Darwin' else 'ubuntu' }}"` |
|
||||
|
||||
## TC-MAC-004: Hardcoded Paths
|
||||
|
||||
| Item | Content |
|
||||
|------|------|
|
||||
| **Trigger File** | `setup-xworkspace-console.yaml` Header Variables Area |
|
||||
| **Trigger Error** | `cd /home/ubuntu/xworkspace-console/dashboard: No such file or directory` |
|
||||
| **Fix Solution** | Refactor `xworkspace_console_home` to `{{ ansible_env.HOME }}`, and chain-evaluate all derived directories |
|
||||
|
||||
## TC-MAC-005: Template Engine Rendering Exception (Undefined Variable)
|
||||
|
||||
| Item | Content |
|
||||
|------|------|
|
||||
| **Trigger File** | `console.plist.j2` |
|
||||
| **Trigger Error** | `AnsibleUndefinedVariable: 'nodejs_version' is undefined` |
|
||||
| **Fix Solution** | Remove NVM environment initialization and `nodejs_version` dependency, directly append `/opt/homebrew/bin` to PATH |
|
||||
|
||||
## TC-MAC-006: NPM Global Helper Script Installation Refused
|
||||
|
||||
| Item | Content |
|
||||
|------|------|
|
||||
| **Trigger File** | `roles/ai_agent_runtime/tasks/nodejs.yml` |
|
||||
| **Trigger Error** | `chown failed: [Errno 1] Operation not permitted: '/usr/local/sbin/...'` |
|
||||
| **Fix Solution** | Downgrade installation path to `~/.local/bin` under macOS, create directory beforehand, turn off `become` |
|
||||
|
||||
## TC-MAC-007: Playwright Hardcoded Associated Call Failure
|
||||
|
||||
| Item | Content |
|
||||
|------|------|
|
||||
| **Trigger File** | `roles/ai_agent_runtime/tasks/nodejs.yml` |
|
||||
| **Trigger Error** | `[Errno 13] Permission denied: '/usr/local/sbin/ai-workspace-manage-npm-global-package'` |
|
||||
| **Fix Solution** | Uniformly use conditional path statements in all `cmd` |
|
||||
|
||||
## TC-MAC-008: Apt Browser Installation Crash
|
||||
|
||||
| Item | Content |
|
||||
|------|------|
|
||||
| **Trigger File** | `roles/ai_agent_runtime/tasks/browser.yml` |
|
||||
| **Trigger Error** | `[Errno 2] No such file or directory: b'update'` (macOS has no apt) |
|
||||
| **Fix Solution** | Add `when: ansible_os_family != 'Darwin'`; supplement macOS Chrome detection path; change environment variable script path to user directory |
|
||||
|
||||
## TC-MAC-009: Playwright Environment Variable Mount Directory Missing
|
||||
|
||||
| Item | Content |
|
||||
|------|------|
|
||||
| **Trigger File** | `roles/ai_agent_runtime/tasks/browser.yml` |
|
||||
| **Trigger Error** | `Destination directory ~/.local/state/ai-workspace/env does not exist` |
|
||||
| **Fix Solution** | Pre-create the env directory; add `default(ansible_env.HOME)` to the variable for fault tolerance |
|
||||
|
||||
## TC-MAC-010: Agent Skills Role Hardcoded Path and User
|
||||
|
||||
| Item | Content |
|
||||
|------|------|
|
||||
| **Trigger File** | `roles/agent_skills/defaults/main.yml`, `roles/agent_skills/tasks/main.yml` |
|
||||
| **Trigger Error** | `[Errno 45] Operation not supported: b'/home/ubuntu'` |
|
||||
| **Fix Solution** | Change all defaults to `ansible_env.USER/HOME`; add Darwin skip to apt rsync installation |
|
||||
|
||||
## TC-MAC-011: Chromium Version Check Path Contains Spaces
|
||||
|
||||
| Item | Content |
|
||||
|------|------|
|
||||
| **Trigger File** | `roles/ai_agent_runtime/tasks/verify.yml` |
|
||||
| **Trigger Error** | `No such file or directory: b'/Applications/Google'` (Path containing space is split) |
|
||||
| **Fix Solution** | Change `ansible.builtin.command` to use `argv` list format parameter passing to avoid space truncation |
|
||||
|
||||
## TC-MAC-012: XWorkMate Bridge Base Directory System Path Write Denied
|
||||
|
||||
| Item | Content |
|
||||
|------|------|
|
||||
| **Trigger File** | `setup-ai-workspace-all-in-one.sh` → `roles/vhosts/xworkmate_bridge` (Variable `xworkmate_bridge_base_dir`) |
|
||||
| **Trigger Error** | `TASK [roles/vhosts/xworkmate_bridge/ : Ensure xworkmate-bridge base directory exists]` → `There was an issue creating /opt/cloud-neutral as requested: [Errno 13] Permission denied: b'/opt/cloud-neutral'` |
|
||||
| **Root Cause** | `xworkmate_bridge_base_dir` is hardcoded to `/opt/cloud-neutral/xworkmate-bridge` by default. macOS runs with `ansible_become=false`, has no permission to write to `/opt`; moreover, `/opt` is not a standard macOS directory. This base dir is simultaneously referenced by `config.yaml` and the launchd plist's `WorkingDirectory` |
|
||||
| **Directory Strategy** | Linux maintains `/opt/cloud-neutral/xworkmate-bridge`; macOS switches to the Apple standard user-level application data directory `~/Library/Application Support/cloud-neutral/xworkmate-bridge` |
|
||||
| **Fix Solution** | Two-layer: ① The Darwin branch of `setup-ai-workspace-all-in-one.sh` injects `-e xworkmate_bridge_base_dir="$HOME/Library/Application Support/cloud-neutral/xworkmate-bridge"` (`curl \| bash` pulls the script from this repo, playbooks come from an independent repo, so `-e` on the script side is the only effective fix point under this path); ② The role's `defaults/main.yml` changes the default value to a ternary expression based on `ansible_os_family`, making the offline/local playbook path also correct |
|
||||
| **Effectiveness Prerequisite** | `curl \| bash` pulls the script from GitHub `main`. The fix must first be pushed to `main` of `ai-workspace-lab/xworkspace-console`; otherwise, the remote is still the old script (extra-vars have the highest priority, if `-e` was executed it would never fall back to `/opt`, thereby determining the unfixed remote script was executed) |
|
||||
|
||||
## TC-MAC-013: Vault standalone Directory System Path Write Denied
|
||||
|
||||
| Item | Content |
|
||||
|------|------|
|
||||
| **Trigger File** | `roles/vhosts/vault/tasks/main.yml`, `roles/vhosts/vault/vars/main.yml`, `roles/vhosts/vault/tasks/macos.yml` |
|
||||
| **Trigger Error** | `TASK [roles/vhosts/vault/ : Ensure standalone Vault directories exist]` → `[Errno 13] Permission denied: b'/etc/vault.d'`, `b'/opt/vault'` |
|
||||
| **Root Cause** | The "Ensure standalone Vault directories exist" task creates `/etc/vault.d` and `/opt/vault/data` with `owner: root`, and **lacks** the `ansible_os_family != 'Darwin'` guard that other standalone tasks in the vault role have. macOS runs with `become=false`, has no permission to write to `/etc`, `/opt`, and chown of `owner: root` cannot complete. Unlike bridge (whose directory owner is the service user, fixable by `-e`), the `owner: root` in this task is hardcoded, cannot be overridden by extra-vars, and the role logic must be changed |
|
||||
| **Directory Strategy** | Linux maintains `/etc/vault.d`, `/opt/vault/data`; macOS switches to Apple standard `~/Library/Application Support/vault`, `~/Library/Application Support/vault/data`; macOS binary path takes `/opt/homebrew/bin/vault` (brew installation location), eliminating the need for `/usr/local/bin` symlinks that require sudo |
|
||||
| **Fix Solution** | The role is located in an independent playbooks repo, cannot be directly committed from this repo; reuse the script's existing "post-clone patch" mechanism (see `patch_playbook_user_systemd`), add `patch_playbook_vault_macos()` to `setup-ai-workspace-all-in-one.sh`, and only apply to the cloned vault role under Darwin: ① Append `ansible_os_family != 'Darwin'` guard to the directory creation task; ② Change `vault_config_dir`/`vault_data_dir`/`vault_binary_path` to OS-based ternary expressions; ③ Pre-create user-owned data directories (including launchd log directory `~/.local/state/xworkspace`) in `macos.yml`. This patch is effective for both `curl \| bash` and local execution paths, is idempotent, and does not alter Linux behavior |
|
||||
|
||||
## TC-MAC-014: common Role Linux Baseline (timedatectl, etc.) Fails on macOS
|
||||
|
||||
| Item | Content |
|
||||
|------|------|
|
||||
| **Trigger File** | `roles/vhosts/common/tasks/main.yml` |
|
||||
| **Trigger Error** | `TASK [common : Base | set timezone]` → `[Errno 2] No such file or directory: b'timedatectl'` (macOS lacks systemd's `timedatectl`) |
|
||||
| **Root Cause** | The `Base | *` series of tasks in the `common` role are Linux server baselines: `timedatectl` to set timezone, rewriting `/etc/hostname`, `/etc/hosts`, setting hostname, SSH hardening, configuring fail2ban, adjusting file descriptor limits, allowing firewall ports. All are `become: true` and rely on Linux-specific tools/paths. On macOS (`become=false`), they will fail sequentially, with `set timezone` just being the first |
|
||||
| **Fix Solution** | Evaluated that these baselines are neither applicable nor authorized for execution on local macOS development deployments. Therefore, `patch_playbook_common_macos()` is added to `setup-ai-workspace-all-in-one.sh` (also via post-clone patch) to append the `ansible_os_family != 'Darwin'` guard to the entire `Base | *` block only under Darwin (9 places total: 7 tasks appended `when`, 2 existing `when` lists appended this condition). The `when` on `import_tasks` propagates to subtasks, so ssh hardening/fail2ban/limits/firewall subtasks are skipped together. Idempotent, valid YAML, Linux behavior unchanged |
|
||||
| **Note** | The user only explicitly mentioned `set timezone`, but the subsequent Base tasks would fail continuously for the same reason, so they were guarded together to avoid step-by-step round trips |
|
||||
|
||||
## TC-MAC-015: Vault Admin Initialization Script Lacks Dependencies/PATH on macOS
|
||||
|
||||
| Item | Content |
|
||||
|------|------|
|
||||
| **Trigger File** | `roles/vhosts/vault/tasks/main.yml` (Bootstrap task), `roles/vhosts/vault/files/init_vault_admin.sh`, `roles/vhosts/vault/tasks/macos.yml` |
|
||||
| **Trigger Error** | `TASK [vault : Bootstrap Vault admin userpass auth]` failed (`no_log: true` hides details). Vault is already up at this point (health check passed), failure occurs during execution of `init_vault_admin.sh` |
|
||||
| **Root Cause** | Script uses `require_cmd vault/jq/curl/base64`. macOS default **does not include jq**, and the "Install standalone Vault dependencies" (apt) task that installs jq is skipped by the `!= 'Darwin'` guard → jq is missing; simultaneously, `ansible.builtin.script` uses a minimal PATH that doesn't include Homebrew's `/opt/homebrew/bin`, so even `brew install`ed `vault`/`jq` might not be found |
|
||||
| **Fix Solution** | Extend `patch_playbook_vault_macos()`: ① Add `brew install jq` (`creates: /opt/homebrew/bin/jq`) in `macos.yml`; ② Append `environment: PATH: "/opt/homebrew/bin:/usr/local/bin:{{ ansible_env.PATH }}"` to the Bootstrap task, ensuring the script can find brew-installed vault/jq. The script itself already has macOS adaptation (`base64 -D` detection). Patch is idempotent, valid YAML, Linux unchanged |
|
||||
| **Note** | If it still fails, temporarily disable `no_log` on the task to view the real stderr of `init_vault_admin.sh` for further troubleshooting |
|
||||
|
||||
## TC-MAC-016: Vault Admin Initialization Non-Idempotent (re-run reports missing entityID)
|
||||
|
||||
| Item | Content |
|
||||
|------|------|
|
||||
| **Trigger File** | `roles/vhosts/vault/files/init_vault_admin.sh` |
|
||||
| **Trigger Error** | `Error writing data to identity/mfa/method/totp/admin-generate ... Code: 400 ... * missing entityID`, accompanied by `A login request was issued that is subject to MFA validation` |
|
||||
| **Root Cause** | The script attempts to get `entity_id` by "logging in as that user" (`auth/userpass/login/<user>`). However, the script then creates a login-MFA enforcement for userpass. The dev mode Vault runs persistently across multiple deployments (launchd daemon), so in the **second and subsequent** deployments, this login is intercepted by MFA. It returns an MFA pending validation response instead of a complete token, `entity_id` is empty → `admin-generate` reports `missing entityID`. This is a re-run idempotency defect, not specific to macOS (Linux will fall into the same trap on the second run) |
|
||||
| **Fix Solution** | Stop relying on logins that will be intercepted by MFA: change to parsing `entity_id` via userpass identity **entity-alias** — iterate through `identity/entity-alias/id`, find the alias where name==user and mount_accessor==userpass accessor, and take its `canonical_id`; on the first run (no alias), explicitly create entity + entity-alias. Remove the `vault token revoke` which is subsequently no longer needed. Idempotent, backward compatible (can recognize implicitly created entities from older version logins). Fixed in the real playbooks repository `init_vault_admin.sh`; clone path synchronized via `patch_playbook_vault_macos()` |
|
||||
| **Troubleshooting Method** | The `no_log: true` on this task hid the error; temporarily changed `no_log: false` + register + wrote stdout/stderr to a mounted directory file, read directly to obtain the true error |
|
||||
|
||||
## TC-MAC-017: PostgreSQL Misuses compose Mode on macOS
|
||||
|
||||
| Item | Content |
|
||||
|------|------|
|
||||
| **Trigger File** | `roles/vhosts/postgres/tasks/compose.yml`, `roles/vhosts/postgres/defaults/main.yml` |
|
||||
| **Trigger Error** | `TASK [postgres : Materialize PostgreSQL admin password]` failed (`no_log: true`). assert `postgresql_admin_password | length > 0` evaluates to empty |
|
||||
| **Root Cause** | `postgresql_deploy_mode` defaults to `compose`. compose.yml follows the Docker path (check/install apt version of docker), and `postgresql_admin_password` is generated by default via `lookup('password', '/root/.ai_workspace_postgres_password ...')` — macOS has no permission to write to `/root`, lookup fails → password is empty → assert fails. The role actually has a `native`+`macos.yml` (Homebrew postgresql@16) path prepared, but wasn't switched to by default on macOS |
|
||||
| **Directory/Mode Strategy** | macOS deployment `postgresql_deploy_mode=native` (→ `macos.yml`, brew install); Linux deployment keeps default `compose` |
|
||||
| **Fix Solution** | Inject `-e postgresql_deploy_mode=native` in the Darwin branch of `setup-ai-workspace-all-in-one.sh`, and provide the password directly with `append_secret_var postgresql_admin_password=$UNIFIED_AUTH_TOKEN` (extra-vars have highest priority, completely bypassing the `/root` password lookup). Linux branch remains unchanged |
|
||||
|
||||
## TC-MAC-018: postgres native Install Misuses Expired Intel Homebrew Crash
|
||||
|
||||
| Item | Content |
|
||||
|------|------|
|
||||
| **Trigger File** | `roles/vhosts/postgres/tasks/macos.yml` |
|
||||
| **Trigger Error** | `Ensure PostgreSQL 16 is installed via Homebrew` → `/usr/local/Homebrew/.../macos_version.rb: unknown or unsupported macOS version: "27.0" (MacOSVersion::Error)` |
|
||||
| **Root Cause** | This task uses the `community.general.homebrew` module. The module auto-detects the brew prefix and hit the **expired Intel Homebrew** (`/usr/local/Homebrew`) on the machine. Its built-in macOS version table does not recognize `27.0`, causing brew to crash on startup. Meanwhile, vault/openclaw using `command: brew` (which uses the available brew on PATH, like Apple Silicon's `/opt/homebrew`) worked fine—this is the module selecting the wrong brew, not brew being entirely unavailable |
|
||||
| **Fix Solution** | Align with vault/openclaw: change to `ansible.builtin.command: brew install postgresql@16`, and prepend `/opt/homebrew/bin:/usr/local/bin` to `environment.PATH` (prioritizing the available brew), add `HOMEBREW_NO_AUTO_UPDATE=1`; maintain idempotency using `register`+`changed_when`/`failed_when`. Real repository `macos.yml` is updated; clone path synchronized via `patch_playbook_postgres_macos()` |
|
||||
| **Note** | If the machine only has a single, expired brew (pure Intel), the root cause is the environment, requiring `brew update`/reinstalling Homebrew; this fix bypasses the issue as long as an "available brew exists" (the vault step proved an available brew exists) |
|
||||
|
||||
## TC-MAC-019: litellm Similarly Misuses Homebrew Module Crash
|
||||
|
||||
| Item | Content |
|
||||
|------|------|
|
||||
| **Trigger File** | `roles/vhosts/litellm/tasks/main.yml` |
|
||||
| **Trigger Error** | `Install LiteLLM prerequisites (macOS)` → `/usr/local/Homebrew/.../macos_version.rb: unknown or unsupported macOS version: "27.0"` |
|
||||
| **Root Cause** | Same root as TC-MAC-018: `community.general.homebrew` module hits expired Intel Homebrew and crashes |
|
||||
| **Fix Solution** | Change to `ansible.builtin.command: brew install python@3.13` + prepend `/opt/homebrew/bin:/usr/local/bin` to `environment.PATH` + `HOMEBREW_NO_AUTO_UPDATE=1`. Real repository updated; clone path synchronized via `patch_playbook_litellm_macos()` |
|
||||
| **Note** | litellm still has macOS gaps to be handled individually subsequently: `/root` derived salt/db secret asserts, `/etc/litellm` config directory, pip/prisma tasks using `become: true` + `become_user` (service user is not created on macOS), DB provisioning, etc. |
|
||||
|
||||
## Current Progress Snapshot (2026-06-22)
|
||||
|
||||
The current macOS debugging entry point remains the public installation command:
|
||||
|
||||
```bash
|
||||
curl -sfL https://install.svc.plus/ai-workspace | bash -
|
||||
```
|
||||
|
||||
As of 2026-06-22, the `xworkspace-console` bootstrap entry, `playbooks` all-in-one role pipeline, and `ai-workspace-services/litellm` runtime release pipeline have formed a three-repository coordination. The macOS local deployment has bypassed early path, permission, Homebrew, Vault, PostgreSQL, OpenClaw, QMD and other blocking points. Current remaining risks mainly focus on the network stability of LiteLLM dependency installation, the product verification of the offline runtime release, and the final consecutive idempotent deployments.
|
||||
|
||||
Key commits pushed to `ai-workspace-infra/playbooks`:
|
||||
|
||||
| Commit | Theme | Impact on macOS Deployment |
|
||||
|---|---|---|
|
||||
| `09a39e6` | `perf(openclaw): avoid unnecessary doctor repairs` | Separates OpenClaw doctor and restart, preventing normal restart from triggering `doctor --fix --force` |
|
||||
| `f01e0bb` | `fix(qmd): provision macOS LaunchAgent` | Supplements user-level LaunchAgent for QMD, supporting starting MCP service on macOS |
|
||||
| `c11f51b` | `fix(openclaw): allow version-matched acpx plugin` | Supports version-matched `acpx` plugin, avoiding accidental kill by plugin registry assert |
|
||||
| `71ebe64` | `fix(litellm): isolate runtime in Python 3.13 venv` | LiteLLM changed to Python 3.13 venv isolation, avoiding mixing Python 3.13/3.14 |
|
||||
| `6a2f05f` | `fix(litellm): skip redundant dependency installs` | Adds package detection and install markers, skipping installed LiteLLM dependencies during repeated execution |
|
||||
|
||||
Key commits pushed to `ai-workspace-services/litellm`:
|
||||
|
||||
| Commit | Theme | Impact on macOS/Offline Deployment |
|
||||
|---|---|---|
|
||||
| `51cde5e32` | `ci: add offline litellm runtime workflow` | Adds `.github/workflows/offline-package-litellm-runtime.yaml`, outputting `litellm-runtime-<distro>-<version>-<arch>.tar.gz` for console offline package scripts |
|
||||
|
||||
Still need to use a clean install to verify if the remote script pointed to by `install.svc.plus` already contains the latest bootstrap logic. If the failure point still shows old tasks or old paths, first confirm whether the release entry point has been synchronized to the latest version of `ai-workspace-lab/xworkspace-console@main`.
|
||||
|
||||
## TC-MAC-020: OpenClaw doctor is Too Heavy Causing Slow Handler
|
||||
|
||||
| Item | Content |
|
||||
|------|------|
|
||||
| **Trigger File** | `roles/vhosts/gateway_openclaw/handlers/main.yml` |
|
||||
| **Trigger Phenomenon** | `RUNNING HANDLER [roles/vhosts/gateway_openclaw/ : Repair OpenClaw health findings (POSIX)]` takes about 5-6 seconds; previously restart and doctor were bound, normal config changes could also trigger `openclaw doctor --fix --force --yes` |
|
||||
| **Root Cause** | The handler coupled "lightweight restart" and "doctor repair", and `--fix --force` runs the repair path by default, suitable for real health issues, not suitable to run on every deployment conclusion |
|
||||
| **Fix Solution** | Doctor and restart have been split in `playbooks`: normally only do lightweight restart; trigger doctor only on actual package/config/plugin changes; prioritize lighter check/repair mode, reducing unrelated changes pulling up doctor |
|
||||
| **Verification Status** | Committed `09a39e6`. Still need to observe if the OpenClaw handler is only triggered on real changes in a complete macOS deployment |
|
||||
|
||||
## TC-MAC-021: QMD Lacks macOS LaunchAgent
|
||||
|
||||
| Item | Content |
|
||||
|------|------|
|
||||
| **Trigger File** | `roles/vhosts/qmd/` |
|
||||
| **Trigger Phenomenon** | QMD MCP port `http://localhost:8181/mcp` needs to run as a macOS user service, but the role lacks launchd provisioning |
|
||||
| **Root Cause** | The Linux/systemd path already has service management, macOS lacks user-level service descriptions like `LaunchAgents/plus.svc.xworkspace.qmd.plist` |
|
||||
| **Fix Solution** | Add QMD LaunchAgent: `plus.svc.xworkspace.qmd`, starting it as a macOS user-level service |
|
||||
| **Verification Status** | Committed `f01e0bb`. Still need to verify `launchctl` status and `http://localhost:8181/mcp` reachability after complete install |
|
||||
|
||||
## TC-MAC-022: OpenClaw Codex Plugin Compatibility Assert Accidental Kill
|
||||
|
||||
| Item | Content |
|
||||
|------|------|
|
||||
| **Trigger File** | `roles/vhosts/gateway_openclaw/tasks/main.yml` |
|
||||
| **Trigger Error** | `Assert OpenClaw Codex plugin matches gateway version` fails, prompting that it must run `@openclaw/codex 2026.6.1` and `openclaw-multi-session-plugins 2026.6.1`, and must not retain stale global `@openclaw/acpx` |
|
||||
| **Root Cause** | The assert treats all `acpx` as stale, but the current OpenClaw plugin registry might contain version-matched `acpx`. It should check the version instead of just existence |
|
||||
| **Fix Solution** | Adjust assert: allow version-matched `acpx`, only reject stale/global mismatched versions |
|
||||
| **Verification Status** | Committed `c11f51b`. Still need to observe assert results after plugin registry refresh in a full deployment |
|
||||
|
||||
## TC-MAC-023: LiteLLM Python 3.13/3.14 Mixed Use
|
||||
|
||||
| Item | Content |
|
||||
|------|------|
|
||||
| **Trigger File** | `roles/vhosts/litellm/defaults/main.yml`, `roles/vhosts/litellm/tasks/main.yml` |
|
||||
| **Trigger Phenomenon** | On macOS, Homebrew Python mixes with system/other Python versions. LiteLLM dependencies might be installed into inconsistent interpreters or site-packages, causing instability in `prisma generate` and service startup |
|
||||
| **Root Cause** | Early installation paths didn't enforce independent venvs, and the macOS environment might simultaneously possess Python 3.13 and 3.14 |
|
||||
| **Fix Solution** | LiteLLM runtime fixed to use Python 3.13 to create an isolated venv: `~/.local/share/litellm/venv`; `pip`, `litellm`, and `prisma` are all executed from this venv |
|
||||
| **Verification Status** | Committed `71ebe64`. Still need a full deployment to verify service startup and `prisma generate` |
|
||||
|
||||
## TC-MAC-024: LiteLLM Dependency Install is Slow and Public Network Download Easily Interrupts
|
||||
|
||||
| Item | Content |
|
||||
|------|------|
|
||||
| **Trigger File** | `roles/vhosts/litellm/tasks/main.yml`, `roles/vhosts/litellm/defaults/main.yml` |
|
||||
| **Trigger Error** | `Ensure LiteLLM and DB dependencies are installed` took up to ~581 seconds, then failed due to download interruptions from GitHub archive or PyPI wheel like `IncompleteRead` / `curl 18` / EOF |
|
||||
| **Root Cause** | The `litellm[proxy]` dependency tree is large, containing huge packages like `polars-runtime-32`, `cryptography`, `boto3`, `mcp`. Direct online `pip install` is both slow and relies on network stability. Changing `git+https` to GitHub archive solved git clone EOF, but large wheel download interruptions are still unavoidable |
|
||||
| **Fixed** | ① Default install source changed from `git+https` to GitHub archive; ② Added `PIP_CACHE_DIR` and longer timeout; ③ Probe for installed `litellm/prisma/psycopg2-binary` before install, and skip duplicate installs using `.install-spec` marker; ④ Added offline runtime workflow to `ai-workspace-services/litellm` to pre-build target distribution wheelhouses |
|
||||
| **Current Status** | Online install path has mitigated but not eradicated network risks; the true long-term solution is to have all-in-one prioritize consuming the wheelhouse within `litellm-runtime-<distro>-<version>-<arch>.tar.gz` |
|
||||
| **To Verify** | Need to trigger and confirm `offline-package-litellm-runtime.yaml` generates a release in GitHub Actions, and `xworkspace-console/scripts/create-ai-workspace-offline-package.sh` can pull the matching runtime asset from `ai-workspace-services/litellm` |
|
||||
|
||||
## TC-MAC-025: LiteLLM runtime release Connection with all-in-one Offline Package
|
||||
|
||||
| Item | Content |
|
||||
|------|------|
|
||||
| **Trigger File** | `ai-workspace-services/litellm/.github/workflows/offline-package-litellm-runtime.yaml`, `xworkspace-console/scripts/create-ai-workspace-offline-package.sh`, `xworkspace-console/scripts/ai-workspace-offline-install.sh` |
|
||||
| **Contract** | The console offline package script will download `litellm-runtime-${DISTRO_ID}-${DISTRO_VERSION}-${ARCH}.tar.gz` under `LITELLM_RUNTIME_RELEASE_REPO=ai-workspace-services/litellm`, extract it, and copy `packages/pip`, optionally `packages/python`, and `metadata/runtime.env` |
|
||||
| **Completed** | Added workflow to `litellm` repo, with matrix covering Debian 11/12/13 and Ubuntu 22.04/24.04/26.04 on amd64/arm64; Ubuntu 26.04 additionally packages portable Python 3.13.14; SHA256SUMS merged in release |
|
||||
| **To Do** | Need to verify if GitHub Actions actual runs succeed; need to confirm release tag naming matches console side `latest-runtime` resolution; need to practically test if `metadata/litellm-runtime.env` correctly injects `LITELLM_PACKAGE_SPEC` in the offline all-in-one package |
|
||||
|
||||
## TC-MAC-026: uninstall purge Needs to Print Deleted Paths
|
||||
|
||||
| Item | Content |
|
||||
|------|------|
|
||||
| **Trigger Command** | `curl -sfL https://install.svc.plus/ai-workspace \| bash -s -- uninstall purge` |
|
||||
| **Requirement** | The purge mode not only deletes local state but should also explicitly print paths to be/already deleted, facilitating user confirmation of the cleanup scope |
|
||||
| **Current Status** | Identified as a to-do item; need to extract a unified `purge_path` / `purge_matching_paths` helper in the uninstall/purge branch of `setup-ai-workspace-all-in-one.sh`, outputting existing paths before deletion, and also outputting skipped/absent when not existing |
|
||||
| **Involved Paths** | macOS includes at least `~/.ai_workspace_auth_token`, `~/.vault_password`, `~/.openclaw`, `/tmp/xworkspace-core-skills`, `/tmp/xworkmate-bridge`, `/tmp/ai-workspace-deploy`; Linux additionally includes `/opt/ai-workspace`, `/etc/ai-workspace`, user systemd units, etc. |
|
||||
|
||||
## TC-MAC-027: Non-Source Code Formal Directory Cleanup
|
||||
|
||||
| Item | Content |
|
||||
|------|------|
|
||||
| **Trigger Phenomenon** | Generated directories like `ai-workspace-all-in-one-offline-ubuntu-22.04-amd64/` appear in the workspace |
|
||||
| **Root Cause** | Offline package build/extraction products entered the development workspace, easily mistaken for source code directories |
|
||||
| **Handling Principle** | Generated products that don't belong to the formal directories of the source repository should be cleaned up from the workspace; offline package output should be placed in explicit `dist/`, release artifact, or temp directories, and shouldn't mix into the source root |
|
||||
| **To Do** | Need to append a repo-level sweep subsequently: confirm `git status --ignored` for `xworkspace-console`, `playbooks`, and `litellm` respectively, clean untracked offline package directories, and append `.gitignore` as needed |
|
||||
|
||||
## TC-MAC-028: LiteLLM Dependency Version Detection One-Line Python Syntax Error Causes set_fact Crash
|
||||
|
||||
| Item | Content |
|
||||
|------|------|
|
||||
| **Trigger File** | `roles/vhosts/litellm/tasks/main.yml` (Inspect/Decide task) |
|
||||
| **Trigger Error** | `TASK [litellm : Decide whether LiteLLM dependencies need installation]` → `the field 'args' ... could not be converted to dict.. Expecting value: line 1 column 1 (char 0)` |
|
||||
| **Root Cause** | The "Inspect installed LiteLLM dependency versions" detection script was written as multi-line Python, but under YAML `>-` folding, all newlines were compressed into spaces, turning `for package in packages: try: ... except:` into an illegal single line → SyntaxError. `failed_when: false` swallowed the failure causing empty stdout, and subsequently `set_fact`'s `from_json('')` crashed. `default('{}')` does not replace empty strings (only undefined) |
|
||||
| **Fix Solution** | Changed detection to a true one-liner program (using dict/list comprehensions for `importlib.metadata.distributions()`, connected by semicolons); decision `set_fact` uses `default('{}', true)`, meaning empty/illegal output degrades to "installation needed" instead of aborting the playbook. Commit `ce2070e` |
|
||||
|
||||
## TC-MAC-029: prisma generate Cannot Find prisma-client-py Generator
|
||||
|
||||
| Item | Content |
|
||||
|------|------|
|
||||
| **Trigger File** | `roles/vhosts/litellm/tasks/main.yml` (Generate Prisma Python Client) |
|
||||
| **Trigger Error** | `Error: Generator "prisma-client-py" failed: /bin/sh: prisma-client-py: command not found` |
|
||||
| **Root Cause** | `prisma generate` invokes the `prisma-client-py` generator as a `/bin/sh` subprocess, its console script is installed in the venv's bin directory. However, the task called prisma with an absolute path but didn't put the venv bin into PATH, so the default command PATH couldn't resolve the generator |
|
||||
| **Fix Solution** | Added `environment.PATH` to this task, prepending `{{ litellm_venv_dir }}/bin` (then Homebrew prefix), making the generator subprocess resolvable. Commit `bbf5260` |
|
||||
|
||||
## TC-MAC-030: QMD LaunchAgent References Undefined nodejs_version
|
||||
|
||||
| Item | Content |
|
||||
|------|------|
|
||||
| **Trigger File** | `roles/vhosts/qmd/templates/qmd.plist.j2` |
|
||||
| **Trigger Error** | `TASK [qmd : Deploy QMD LaunchAgent]` → `AnsibleUndefinedVariable: 'nodejs_version' is undefined` |
|
||||
| **Root Cause** | The plist's PATH hardcoded `~/.nvm/versions/node/{{ nodejs_version }}/bin`, but under Homebrew deployment, `nodejs_version` was never defined (same anti-pattern as TC-MAC-005) |
|
||||
| **Fix Solution** | QMD is a bun binary, and the Linux user unit already uses `.bun/bin:.local/bin:...`; plist PATH aligned to `{{ qmd_home }}/.bun/bin:{{ qmd_home }}/.local/bin:/opt/homebrew/bin:...`, removing nvm/nodejs_version dependencies. Commit `d903396` |
|
||||
|
||||
## TC-MAC-031: QMD better-sqlite3 Native Module Node ABI Mismatch
|
||||
|
||||
| Item | Content |
|
||||
|------|------|
|
||||
| **Trigger File** | `roles/vhosts/qmd/tasks/main.yml` (npm install / npm run build / Validate QMD status) |
|
||||
| **Trigger Error** | `TASK [qmd : Validate QMD status]` → `Error: ... better_sqlite3.node was compiled against a different Node.js version using NODE_MODULE_VERSION 137. This version of Node.js requires NODE_MODULE_VERSION 115` (`ERR_DLOPEN_FAILED`) |
|
||||
| **Root Cause** | better-sqlite3 was compiled with node@24 (ABI 137), but the validate-status task didn't fix PATH. The user PATH's nvm Node 20 (ABI 115) ranked before Homebrew, causing inconsistent Node ABI between runtime and build |
|
||||
| **Fix Solution** | The three tasks (npm install / npm run build / validate-status) under Darwin use `{{ '/opt/homebrew/bin:/usr/local/bin:' if ansible_os_family == 'Darwin' else '' }}{{ ansible_env.PATH }}` to fix node@24, ensuring build and runtime ABI consistency (consistent with plist); Linux PATH unchanged. Commit `6091b9d` |
|
||||
|
||||
## TC-MAC-032: XFCE/XRDP Linux Desktop Stack Fails to run apt on macOS
|
||||
|
||||
| Item | Content |
|
||||
|------|------|
|
||||
| **Trigger File** | `setup-xfce-xrdp.yaml` → `roles/vhosts/xfce_desktop_minimal_runtime` |
|
||||
| **Trigger Error** | `TASK [xfce_desktop_minimal_runtime : Update apt cache]` → `[Errno 2] No such file or directory: b'update'` (macOS lacks apt) |
|
||||
| **Root Cause** | XFCE + XRDP is a Linux remote desktop stack (apt/systemd), which is meaningless on macOS that already has a native GUI, but all-in-one still ran this play down to Darwin |
|
||||
| **Fix Solution** | Both `include_role`s in `setup-xfce-xrdp.yaml` gained `when: ansible_os_family != 'Darwin'`, skipping the entire stack on macOS; Linux unchanged. Commit `ef67c61` |
|
||||
|
||||
## TC-MAC-033: LiteLLM DATABASE_URL Password Not Percent-Encoded Causes Prisma P1013
|
||||
|
||||
| Item | Content |
|
||||
|------|------|
|
||||
| **Trigger File** | `roles/vhosts/litellm/defaults/main.yml` (`litellm_database_url`) |
|
||||
| **Trigger Phenomenon** | Deployment "succeeds" (ansible `failed=0`) but service summary shows `LiteLLM : inactive (not detected;http:000)`, launchd exit code non-0, port 4000 not listening; `litellm.err.log` repeats `Error: P1013: The provided database string is invalid. invalid port number in database URL` |
|
||||
| **Root Cause** | Unified auth token generated via `openssl rand -base64` may contain `/`, `+`, `=`; when directly concatenated into userinfo of `postgresql://litellm:<token>@host:port/db`, `/` truncates the URL authority, failing port parsing, proxy fails to start, 4000 not listening. Health check `failed_when: false` masked it, ansible still reported success |
|
||||
| **Fix Solution** | Percent-encode only the password in DATABASE_URL (added `litellm_database_password_urlencoded`, explicit replace chain prioritizing `%`; Jinja `urlencode` doesn't escape `/` so it's unusable). The actual DB user password in provision-database and `LITELLM_DB_PASSWORD` keeps original text, URL format decoded matches original (round-trip verified), auth remains unchanged. Commit `9926a46` |
|
||||
| **Verification Method** | ansible `failed=0` ≠ service available: need independent confirmation via `launchctl list` (Status 0), `lsof -iTCP:4000 -sTCP:LISTEN`, `curl /health` (**401 means healthy**, auth-gated) |
|
||||
|
||||
---
|
||||
|
||||
## Fix Dimension Summary
|
||||
|
||||
| Dimension | Involved Cases |
|
||||
|------|---------|
|
||||
| Component acquisition method replacement (brew vs binary) | TC-001 |
|
||||
| Privilege reduction (become: false) | TC-002, TC-006, TC-007, TC-008, TC-009 |
|
||||
| User group adaptation (staff vs ubuntu) | TC-003, TC-010 |
|
||||
| Directory path downgrade ($HOME vs /home/ubuntu, /opt, /etc) | TC-004, TC-006, TC-009, TC-010, TC-012, TC-013 |
|
||||
| Post-clone patch injection | TC-013, TC-014 |
|
||||
| Linux baseline total skip (skip Linux baseline on Darwin) | TC-014, TC-032 |
|
||||
| brew dep supplement + PATH injection (jq via brew, Homebrew on PATH) | TC-015 |
|
||||
| Package manager bypass (skip apt on Darwin) | TC-008, TC-010, TC-032 |
|
||||
| Template variable decoupling (remove nvm/nodejs_version) | TC-005, TC-030 |
|
||||
| Path space compatibility (argv vs string) | TC-011 |
|
||||
| Homebrew module bypass (command brew + PATH) | TC-018, TC-019 |
|
||||
| venv/Node subprocess PATH injection (resolve generator/native ABI) | TC-029, TC-031 |
|
||||
| Node ABI consistency (build == runtime node@24) | TC-031 |
|
||||
| macOS launchd user service | TC-021 |
|
||||
| handler trigger condition convergence | TC-020 |
|
||||
| Python venv isolation and pip cache | TC-023, TC-024 |
|
||||
| One-line template/folding syntax robustness (`>-` folding, default(.,true)) | TC-028 |
|
||||
| Connection string password percent encoding (URL-encode secrets) | TC-033 |
|
||||
| Offline runtime wheelhouse | TC-025 |
|
||||
| purge observability | TC-026 |
|
||||
85
docs/en/case/test_prompts.md
Normal file
85
docs/en/case/test_prompts.md
Normal file
@ -0,0 +1,85 @@
|
||||
[🇺🇸 English](../../../README.md) | [🇨🇳 中文](../../../README.zh.md)
|
||||
|
||||
# Test Prompt Templates
|
||||
|
||||
This document provides standardized prompt templates used for testing `setup-ai-workspace-all-in-one.sh`, which can be directly copied and pasted into the terminal for execution.
|
||||
|
||||
---
|
||||
|
||||
## 1. Quick Installation (One-Click Deployment)
|
||||
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | bash -
|
||||
```
|
||||
|
||||
## 2. Installation with API Keys
|
||||
|
||||
```bash
|
||||
export DEEPSEEK_API_KEY="<your-deepseek-api-key>"
|
||||
export NVIDIA_API_KEY="<your-nvidia-api-key>"
|
||||
export OLLAMA_API_KEY="<your-ollama-api-key>"
|
||||
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | bash -
|
||||
```
|
||||
|
||||
## 3. Uninstall (Keep Data)
|
||||
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | bash -s -- uninstall
|
||||
```
|
||||
|
||||
## 4. Complete Uninstall (Purge All Data)
|
||||
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | bash -s -- uninstall --purge
|
||||
```
|
||||
|
||||
## 5. Full Lifecycle Test (Uninstall → Reinstall)
|
||||
|
||||
```bash
|
||||
# Step 1: Complete Uninstall
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | bash -s -- uninstall --purge
|
||||
|
||||
# Step 2: Set API Keys
|
||||
export DEEPSEEK_API_KEY="<your-deepseek-api-key>"
|
||||
export NVIDIA_API_KEY="<your-nvidia-api-key>"
|
||||
export OLLAMA_API_KEY="<your-ollama-api-key>"
|
||||
|
||||
# Step 3: Reinstall
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | bash -
|
||||
```
|
||||
|
||||
## 6. Develop and Debug with Local Playbooks
|
||||
|
||||
```bash
|
||||
export PLAYBOOK_DIR="/path/to/local/playbooks"
|
||||
export DEEPSEEK_API_KEY="<your-deepseek-api-key>"
|
||||
export NVIDIA_API_KEY="<your-nvidia-api-key>"
|
||||
export OLLAMA_API_KEY="<your-ollama-api-key>"
|
||||
|
||||
bash /path/to/setup-ai-workspace-all-in-one.sh
|
||||
```
|
||||
|
||||
> Setting `PLAYBOOK_DIR` makes the script use the local Playbook directory instead of pulling from the Git remote, which is suitable for development and debugging scenarios.
|
||||
|
||||
---
|
||||
|
||||
## Environment Variable Reference
|
||||
|
||||
| Variable Name | Purpose | Required |
|
||||
|--------|------|:----:|
|
||||
| `DEEPSEEK_API_KEY` | DeepSeek model API key | Optional |
|
||||
| `NVIDIA_API_KEY` | NVIDIA NIM API key | Optional |
|
||||
| `OLLAMA_API_KEY` | Ollama service API key | Optional |
|
||||
| `PLAYBOOK_DIR` | Local Playbook directory path (for dev/debugging) | Optional |
|
||||
|
||||
---
|
||||
|
||||
## Supported Platforms
|
||||
|
||||
| Platform | Status |
|
||||
|------|:----:|
|
||||
| macOS (Apple Silicon / Intel) | ✅ Tested |
|
||||
| Debian 11/12 | ✅ Tested |
|
||||
| Ubuntu 22.04/24.04 | ✅ Tested |
|
||||
| Other Linux Distributions | ⚠️ Untested |
|
||||
@ -1,3 +1,5 @@
|
||||
[🇺🇸 English](../../../README.md) | [🇨🇳 中文](../../../README.zh.md)
|
||||
|
||||
# AI Workspace Desktop Design
|
||||
|
||||
Date: 2026-06-07
|
||||
161
docs/en/designs/xworkspace-console-homepage-v1.md
Normal file
161
docs/en/designs/xworkspace-console-homepage-v1.md
Normal file
@ -0,0 +1,161 @@
|
||||
[🇺🇸 English](../../../README.md) | [🇨🇳 中文](../../../README.zh.md)
|
||||
|
||||
# XWorkspace Console Homepage V1
|
||||
|
||||
Date: 2026-06-07
|
||||
Status: First implementation design
|
||||
|
||||
## Goal
|
||||
|
||||
Build the first React implementation of the `xworkspace-console` homepage based on the provided control-plane design reference.
|
||||
|
||||
The first version may use temporary mock data, but the component structure must be ready for real runtime integration:
|
||||
|
||||
- custom tabs
|
||||
- service status
|
||||
- active agents
|
||||
- recent tasks
|
||||
- artifacts
|
||||
- system health
|
||||
- embedded `ttyd`
|
||||
- quick access links
|
||||
- system telemetry integration points
|
||||
|
||||
## Information Architecture
|
||||
|
||||
The homepage is organized around an operations dashboard:
|
||||
|
||||
- Left navigation
|
||||
- Workspace
|
||||
- Dashboard
|
||||
- Agents
|
||||
- Tasks
|
||||
- Artifacts
|
||||
- OpenClaw
|
||||
- Bridge
|
||||
- LiteLLM
|
||||
- Vault
|
||||
- Runtime
|
||||
- Terminal
|
||||
- Settings
|
||||
- Top status bar
|
||||
- CPU
|
||||
- GPU
|
||||
- VPN state
|
||||
- notifications
|
||||
- user/profile
|
||||
- Main overview
|
||||
- metric cards
|
||||
- services status
|
||||
- active agents
|
||||
- recent tasks
|
||||
- artifacts
|
||||
- system health
|
||||
- quick access
|
||||
|
||||
## Required Links
|
||||
|
||||
The following navigation and quick access targets are canonical for V1:
|
||||
|
||||
- OpenClaw: `http://127.0.0.1:18789/channels`
|
||||
- Vault: `http://127.0.0.1:8200`
|
||||
- LiteLLM: `http://127.0.0.1:4000/ui`
|
||||
- Terminal: `http://127.0.0.1:7681`
|
||||
|
||||
## Custom Tabs
|
||||
|
||||
Tabs should be represented as data, not hardcoded across the UI.
|
||||
|
||||
Initial tab shape:
|
||||
|
||||
```ts
|
||||
type Tab = {
|
||||
id: string;
|
||||
label: string;
|
||||
href: string;
|
||||
kind: 'internal' | 'external' | 'embed';
|
||||
};
|
||||
```
|
||||
|
||||
This allows the homepage to support later user-defined tabs from YAML or an API response.
|
||||
|
||||
## Embedded Terminal
|
||||
|
||||
The Terminal tab should render a real `ttyd` embed:
|
||||
|
||||
```text
|
||||
http://127.0.0.1:7681
|
||||
```
|
||||
|
||||
The first implementation can use an iframe. A later version may proxy or authenticate the terminal if needed.
|
||||
|
||||
## System Probes
|
||||
|
||||
The homepage should be designed to consume local status data from the Go API and related observability tools.
|
||||
|
||||
Initial local API:
|
||||
|
||||
- `GET http://127.0.0.1:8788/health`
|
||||
- `GET http://127.0.0.1:8788/services`
|
||||
- `GET http://127.0.0.1:8788/metrics/simple`
|
||||
|
||||
Future integrations:
|
||||
|
||||
- Prometheus metrics
|
||||
- Vector logs
|
||||
- local service logs
|
||||
- agent readiness probes
|
||||
- Vault connectivity
|
||||
- OpenClaw gateway state
|
||||
|
||||
## Mock Data Policy
|
||||
|
||||
V1 may use mock data for:
|
||||
|
||||
- metric cards
|
||||
- agents
|
||||
- tasks
|
||||
- artifacts
|
||||
- system health score
|
||||
|
||||
V1 should attempt to read `/services` from the Go API when available and gracefully fall back to mock service rows.
|
||||
|
||||
## Visual Direction
|
||||
|
||||
The provided design reference uses a bright, clean operations console style:
|
||||
|
||||
- white panels
|
||||
- blue primary action color
|
||||
- subtle borders
|
||||
- compact tables
|
||||
- low-noise status indicators
|
||||
- rounded corners kept moderate
|
||||
- dashboard-first layout, not a marketing page
|
||||
|
||||
Cards should be used for repeated dashboard items and bounded panels only.
|
||||
|
||||
## V1 Implementation Notes
|
||||
|
||||
Implemented in:
|
||||
|
||||
- `dashboard/src/main.tsx`
|
||||
- `dashboard/src/styles.css`
|
||||
|
||||
V1 includes:
|
||||
|
||||
- mock metrics
|
||||
- mock agents
|
||||
- mock tasks
|
||||
- mock artifacts
|
||||
- real external links for OpenClaw, Vault, LiteLLM
|
||||
- embedded `ttyd` terminal tab
|
||||
- attempted service status fetch from `http://127.0.0.1:8788/services`
|
||||
|
||||
## Next Steps
|
||||
|
||||
- Move tab definitions to `config/xworkspace-desktop.yaml`
|
||||
- Add a `/tabs` endpoint to the Go API
|
||||
- Add CORS support if dashboard and API are served from separate ports
|
||||
- Add real host metrics for CPU, memory, disk, and network
|
||||
- Add Prometheus and Vector probes
|
||||
- Replace letter placeholders with a formal icon system
|
||||
@ -1,3 +1,5 @@
|
||||
[🇺🇸 English](../../../README.md) | [🇨🇳 中文](../../../README.zh.md)
|
||||
|
||||
# XWorkspace Console Service Port Plan
|
||||
|
||||
Date: 2026-06-07
|
||||
50
docs/en/plan/openclaw_litellm_compat.md
Normal file
50
docs/en/plan/openclaw_litellm_compat.md
Normal file
@ -0,0 +1,50 @@
|
||||
[🇺🇸 English](../../../README.md) | [🇨🇳 中文](../../../README.zh.md)
|
||||
|
||||
# Unified AI Gateway (LiteLLM) and OpenClaw Compatible Providers Design Plan
|
||||
|
||||
To maintain the OpenClaw client's native `provider/model` syntax habits, while still routing all traffic through the unified LiteLLM gateway for centralized authentication, rate limiting, and log management, we are refactoring the gateway mapping layer.
|
||||
|
||||
## Design Goals
|
||||
1. Deprecate the thin `litellm` provider, and switch to a compatible mode directly configuring the three major providers `deepseek`, `nvidia`, and `ollama` in OpenClaw.
|
||||
2. In the backend configuration of OpenClaw, these three major providers will all point to `http://127.0.0.1:4000/v1` (LiteLLM endpoint), and use the unified `AI_WORKSPACE_AUTH_TOKEN` for authentication.
|
||||
3. The routing (Alias ID) inside LiteLLM strictly adopts the `provider/model` naming format, exactly matching the three major channels. This not only bypasses OpenClaw's routing interception, but also achieves full-channel centralized proxying.
|
||||
|
||||
## Channel Mapping Matrix
|
||||
|
||||
Based on current API access, the channel distribution plan is as follows:
|
||||
|
||||
### 1. DEEPSEEK_API_KEY (DeepSeek Official Channel)
|
||||
* `deepseek/deepseek-v4-flash`
|
||||
* `deepseek/deepseek-v4-pro`
|
||||
* `deepseek/deepseek-chat`
|
||||
* `deepseek/deepseek-reasoner`
|
||||
|
||||
### 2. NVIDIA_API_KEY (NVIDIA NIM / Proxy Channel)
|
||||
* `nvidia/deepseek-v4-flash`
|
||||
* `nvidia/deepseek-v4-pro`
|
||||
* `nvidia/glm-5.2`
|
||||
* `nvidia/minimax-m3`
|
||||
* `nvidia/qwen3.5`
|
||||
* `nvidia/kimi-k2.7-code`
|
||||
|
||||
### 3. OLLAMA_API_KEY (OLLAMA Cloud / Proxy Channel)
|
||||
* `ollama/deepseek-v4-flash`
|
||||
* `ollama/deepseek-v4-pro`
|
||||
* `ollama/glm-5.2`
|
||||
* `ollama/minimax-m3`
|
||||
* `ollama/qwen3.5`
|
||||
* `ollama/kimi-k2.7-code`
|
||||
|
||||
## Implementation Details
|
||||
|
||||
1. **LiteLLM Model Registration Layer (`register_mainstream_models.sh`)**
|
||||
Modify the invocation logic of `add_model`, registering corresponding prefix aliases under the protection of DeepSeek, NVIDIA, and OLLAMA environment variables respectively according to the matrix above.
|
||||
|
||||
2. **OpenClaw Gateway Configuration Layer (`gateway_openclaw/defaults/main.yml`)**
|
||||
- Add three new Provider nodes: `deepseek`, `nvidia`, and `ollama`.
|
||||
- The `api` is uniformly set to `openai-completions`, and `baseUrl` points to LiteLLM.
|
||||
- Remove the old `litellm` monolithic configuration.
|
||||
- Update the UI dropdown `gateway_openclaw_default_models` to encompass all new channel models.
|
||||
|
||||
## Effects
|
||||
After the configuration takes effect, the frontend can intuitively experience different channels like native calls (such as selecting `glm-5.2` under the `NVIDIA` category), while all backend traffic is centralized in the LiteLLM proxy, eradicating Auth parsing errors.
|
||||
47
docs/en/register_mainstream_models.md
Normal file
47
docs/en/register_mainstream_models.md
Normal file
@ -0,0 +1,47 @@
|
||||
[🇺🇸 English](../../README.md) | [🇨🇳 中文](../../README.zh.md)
|
||||
|
||||
# LiteLLM Model Registration Mapping Architecture and Plan
|
||||
|
||||
This document records the large model routing and unified mapping architecture of `openclaw` -> `litellm` (AI Gateway) -> `register_mainstream_models.sh`.
|
||||
|
||||
## Architecture Principles
|
||||
|
||||
1. **Multi-endpoint Native Simulation and Unified Routing**: To be compatible with OpenClaw's native route hijacking feature for different providers, we have deprecated the monolithic `litellm` node in the OpenClaw configuration, and instead directly **simulate the three native providers: `deepseek`, `nvidia`, `ollama`**.
|
||||
2. **Underlying Convergence**: All API Endpoints and Auth Tokens of these three providers point entirely to the local LiteLLM gateway (`http://127.0.0.1:4000/v1`) and the unified `AI_WORKSPACE_AUTH_TOKEN`. LiteLLM acts as the true gateway, converging various heterogeneous platforms into a unified OpenAI standard format.
|
||||
3. **Prefix Routing and Precision Striking**: In `register_mainstream_models.sh`, we forcefully add the corresponding `provider/` prefix (e.g. `nvidia/glm-5.2`) to the models of each platform. This naming perfectly bypasses OpenClaw's built-in `No API key found` Provider parsing limitation, allowing requests to seamlessly penetrate and reach the gateway.
|
||||
|
||||
## Channel Registration Matrix
|
||||
|
||||
To account for resource allocation of different proxy pools/distribution channels, the current architecture designs a full-matrix registration channel. As long as the corresponding environment variable Key is configured, the installation script will immediately register the corresponding node to LiteLLM.
|
||||
|
||||
### 1. DEEPSEEK_API_KEY (DeepSeek Official Channel)
|
||||
Mainly proxies basic models provided by the official:
|
||||
* `deepseek/deepseek-v4-flash`
|
||||
* `deepseek/deepseek-v4-pro`
|
||||
* `deepseek/deepseek-chat`
|
||||
* `deepseek/deepseek-reasoner`
|
||||
|
||||
### 2. NVIDIA_API_KEY (NVIDIA NIM / Proxy Channel)
|
||||
As a high-speed concurrent or third-party proxy aggregation interface:
|
||||
* `nvidia/deepseek-v4-flash`
|
||||
* `nvidia/deepseek-v4-pro`
|
||||
* `nvidia/glm-5.2`
|
||||
* `nvidia/minimax-m3`
|
||||
* `nvidia/qwen3.5`
|
||||
* `nvidia/kimi-k2.7-code`
|
||||
|
||||
### 3. OLLAMA_API_KEY (OLLAMA Cloud / Proxy Channel)
|
||||
As another alternate distribution channel:
|
||||
* `ollama/deepseek-v4-flash`
|
||||
* `ollama/deepseek-v4-pro`
|
||||
* `ollama/glm-5.2`
|
||||
* `ollama/minimax-m3`
|
||||
* `ollama/qwen3.5`
|
||||
* `ollama/kimi-k2.7-code`
|
||||
|
||||
## Updates and Workflow
|
||||
|
||||
1. **Set Authentication**: Use commands like `export DEEPSEEK_API_KEY="sk-xxx"` to set target environment variables.
|
||||
2. **One-click Deployment**: Run `curl -sfL https://install.svc.plus/ai-workspace | bash -` to deploy the entire AI Workspace.
|
||||
3. **Registration Channels**: The `register_mainstream_models.sh` script is triggered during installation, opening up LiteLLM's routing table based on the keys you configured (non-empty).
|
||||
4. **Direct Frontend Experience**: After OpenClaw restarts, it will automatically pull the latest category form, and users can directly click on `glm-5.2` or `deepseek-v4-flash` under the category (like NVIDIA) in the UI interface for high-concurrency inference.
|
||||
209
docs/en/report/TC-MAC-012-26-06-18-19.md
Normal file
209
docs/en/report/TC-MAC-012-26-06-18-19.md
Normal file
@ -0,0 +1,209 @@
|
||||
[🇺🇸 English](../../../README.md) | [🇨🇳 中文](../../../README.zh.md)
|
||||
|
||||
# Progress Report · TC-MAC-012
|
||||
|
||||
| Item | Content |
|
||||
|------|------|
|
||||
| **Test Case ID** | TC-MAC-012 |
|
||||
| **Report Time** | 2026-06-18 19:00 (Asia/Shanghai) |
|
||||
| **Associated Commit** | `cf97344` fix: relocate xworkmate-bridge base dir under $HOME on macOS |
|
||||
| **Platform** | macOS (Darwin) Local Deployment |
|
||||
| **Status** | ✅ Fixed and committed (Pending re-verification on Mac) |
|
||||
|
||||
## 1. Issue Phenomenon
|
||||
|
||||
`curl -sfL .../setup-ai-workspace-all-in-one.sh | bash -` interrupted during local deployment on macOS:
|
||||
|
||||
```
|
||||
TASK [roles/vhosts/xworkmate_bridge/ : Ensure xworkmate-bridge base directory exists]
|
||||
fatal: [127.0.0.1]: FAILED! => {"changed": false,
|
||||
"msg": "There was an issue creating /opt/cloud-neutral as requested:
|
||||
[Errno 13] Permission denied: b'/opt/cloud-neutral'",
|
||||
"path": "/opt/cloud-neutral/xworkmate-bridge"}
|
||||
PLAY RECAP
|
||||
127.0.0.1 : ok=145 changed=12 unreachable=0 failed=1 skipped=176
|
||||
```
|
||||
|
||||
## 2. Root Cause Analysis
|
||||
|
||||
- In `roles/vhosts/xworkmate_bridge/defaults/main.yml`, `xworkmate_bridge_base_dir` is hardcoded to `/opt/cloud-neutral/xworkmate-bridge`.
|
||||
- macOS deployment runs with `ansible_become=false` (see TC-MAC-002), and a regular user has no permission to create directories under `/opt`, triggering `Errno 13`.
|
||||
- This base dir is also referenced by `config.yaml` and the `WorkingDirectory` in the launchd plist, so it must point to a user-writable path.
|
||||
|
||||
## 3. Fix Solution
|
||||
|
||||
Following the existing macOS adaptation conventions in this repository: we do not modify the independent playbooks repository. Instead, we inject an override using `-e` in the Darwin branch of `setup-ai-workspace-all-in-one.sh` (handled similarly to `gateway_openclaw_home`, `agent_skills_home`, `xworkspace_console_root`, etc.).
|
||||
|
||||
```bash
|
||||
ANSIBLE_EXTRA_VARS+=("-e" "xworkmate_bridge_base_dir=$HOME/.local/state/cloud-neutral/xworkmate-bridge")
|
||||
```
|
||||
|
||||
Ansible extra-vars have a higher priority than role defaults, so they take effect for both online (`curl | bash`) and offline installation paths; `config.yaml` and the plist `WorkingDirectory` are migrated along with it because they are derived from this variable.
|
||||
|
||||
## 4. Verification Status
|
||||
|
||||
- Passed `bash -n` syntax check.
|
||||
- Confirmed that the `-e` override exists in the commit and behaves correctly (extra-vars override role defaults).
|
||||
- Reviewed other system paths in the bridge role, confirming failure won't be pushed down:
|
||||
- `xworkmate_bridge_binary_path` (`/usr/local/bin/...`) is only read via `stat`, not written to.
|
||||
- All `/etc/systemd` tasks already have the `when: ansible_os_family != 'Darwin'` guard.
|
||||
- Tasks related to `/etc/caddy` are identical to `gateway_openclaw`, and that role already passed within the 145 OK tasks, indicating `/etc/caddy` is writable on that machine.
|
||||
- Limitations: Currently lacking a Darwin host environment, a complete deployment run could not be executed; verification is based on variable priority deduction + path auditing.
|
||||
|
||||
## 5. Deliverables
|
||||
|
||||
- `scripts/setup-ai-workspace-all-in-one.sh`: Added base dir override in the Darwin branch (+4 lines).
|
||||
- `docs/case/macos_compatibility_tests.md`: Added TC-MAC-012 and updated the fix dimension summary.
|
||||
- `docs/case/{combination_tests,test_prompts}.md`: Included in version control along with the commit.
|
||||
|
||||
## 6. Follow-up Recommendations
|
||||
|
||||
1. Rerun `COMBO-001` on Mac to verify the bridge tasks pass.
|
||||
2. If the next blockage point is `/etc/caddy` permissions, it can be handled similarly (Darwin guard or `-e` redirection).
|
||||
3. Not included in this commit: Pre-existing and unrelated `create-ai-workspace-offline-package.sh` changes (added `npm`), and the generated offline package directories.
|
||||
|
||||
---
|
||||
|
||||
## 7. Retrospective Update (19:09 Second Failure)
|
||||
|
||||
**Phenomenon**: The user re-executed `curl -sfL .../main/scripts/setup-ai-workspace-all-in-one.sh | bash -` and it still reported the same `/opt/cloud-neutral` `Errno 13`.
|
||||
|
||||
**Troubleshooting**:
|
||||
- `git log origin/main..HEAD` shows that commits `cf97344` and `d094c27` are **only local, not pushed**.
|
||||
- `curl | bash` pulls the script on the GitHub `main` branch, i.e., the unfixed version; hence the `-e` override never entered this run.
|
||||
- Evidence: Ansible extra-vars have the highest priority. If `-e xworkmate_bridge_base_dir` was executed, it would never fall back to the role's default `/opt`. Therefore, we can determine the unfixed remote script was executed.
|
||||
- This sandbox cannot push (SSH port 22 to github.com is blocked), so the push must be done on the user's machine.
|
||||
|
||||
**Strategy Adjustment (Differentiate platforms per user request + use Apple standard directories)**:
|
||||
- Linux: Keep `/opt/cloud-neutral/xworkmate-bridge`.
|
||||
- macOS: Switch to the Apple standard user-level application data directory `~/Library/Application Support/cloud-neutral/xworkmate-bridge` (replacing the previous version's `~/.local/state/...`).
|
||||
- Implementation: The script's Darwin branch `-e` override is updated to the above path; meanwhile, the default value in role `defaults/main.yml` is changed to a ternary expression based on `ansible_os_family` (so offline/local playbook paths are also correct). Jinja rendering and `bash -n` have both been verified.
|
||||
|
||||
**Two ways to make the fix take effect immediately (choose one)**:
|
||||
|
||||
```bash
|
||||
# Method A: Local repo already contains the fix, run the local script directly (no need to wait for push)
|
||||
bash "/Users/shenlan/workspaces/ai-workspace-lab/xworkspace-console/scripts/setup-ai-workspace-all-in-one.sh"
|
||||
|
||||
# Method B: Push the fix to main, then curl | bash will take effect
|
||||
cd /Users/shenlan/workspaces/ai-workspace-lab/xworkspace-console
|
||||
git push origin main
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | bash -
|
||||
```
|
||||
|
||||
> Note: Method A bypasses `curl | bash` to use local execution, where the script-side `-e` override directly takes effect; the role's default ternary expression covers the offline `PLAYBOOK_DIR` scenario.
|
||||
|
||||
---
|
||||
|
||||
## 8. Cont.: vault role blockage (TC-MAC-013, 19:24)
|
||||
|
||||
**Progress**: After the bridge fix took effect, deployment advanced from 145 → 154 tasks, and the new blockage point is vault:
|
||||
|
||||
```
|
||||
TASK [roles/vhosts/vault/ : Ensure standalone Vault directories exist]
|
||||
failed (item=/etc/vault.d): Permission denied: b'/etc/vault.d'
|
||||
failed (item=/opt/vault/data): Permission denied: b'/opt/vault'
|
||||
```
|
||||
|
||||
**Root Cause**: This directory creation task uses `owner: root` to create `/etc/vault.d` and `/opt/vault/data`, and lacks the `ansible_os_family != 'Darwin'` guard that other standalone tasks in vault have. Under `become=false`, there is no permission to write to `/etc` or `/opt`, and chown to `owner: root` fails.
|
||||
|
||||
**Key difference from bridge**: The bridge directory owner is the service user (on macOS, the current user), so it can be fixed with the script's `-e xworkmate_bridge_base_dir=...`; but `owner: root` here in vault is **hardcoded**, extra-vars cannot override it, and the role logic must be changed. However, the role is in an independent playbooks repository, not this one.
|
||||
|
||||
**Solution (still in this repo, effective for both `curl|bash` and local execution)**: Reuse the script's existing "post-clone patch" mechanism (`patch_playbook_user_systemd` is a precedent). Add `patch_playbook_vault_macos()` to do the following only under Darwin on the cloned vault role:
|
||||
1. Append the `ansible_os_family != 'Darwin'` guard to "Ensure standalone Vault directories exist";
|
||||
2. Change `vault_config_dir`/`vault_data_dir`/`vault_binary_path` to OS-based ternary expressions (Linux remains unchanged; macOS uses `~/Library/Application Support/vault[/data]` and `/opt/homebrew/bin/vault`);
|
||||
3. Pre-create the data directory owned by the user in `macos.yml` (including the launchd log directory `~/.local/state/xworkspace`).
|
||||
|
||||
**Directory Strategy (Confirmed by User)**: Linux → `/opt/vault/data`; macOS → `~/Library/Application Support/vault/data`.
|
||||
|
||||
**Verification**: Passed `bash -n`; running the patch with a real vault role copy resulted in valid YAML, the Darwin guard count went from 5→6, secondary execution is idempotent, Linux renders original system paths, and macOS renders Apple standard paths.
|
||||
|
||||
**Note (Execution Mode)**: The pipeline in the previous `bash scripts/setup-...sh | bash -` was misused (it fed the script log to a second bash). Local execution should drop the pipeline: `bash scripts/setup-ai-workspace-all-in-one.sh`.
|
||||
|
||||
---
|
||||
|
||||
## 9. Cont.: common role Linux baseline (TC-MAC-014, 19:41)
|
||||
|
||||
**Progress**: After the vault fix, deployment pushed to 161 tasks, and the new blockage point is `common : Base | set timezone`:
|
||||
|
||||
```
|
||||
fatal: timedatectl set-timezone Asia/Shanghai -> [Errno 2] No such file or directory: b'timedatectl'
|
||||
```
|
||||
|
||||
**Root Cause**: `Base | *` in `common` are Linux server baselines (timezone, hostname, /etc/hosts, SSH hardening, fail2ban, limits, firewall), all of which require `become: true` and Linux-specific tools/paths. `set timezone` is just the first one, the rest will fail sequentially.
|
||||
|
||||
**Solution**: Added `patch_playbook_common_macos()` (still via post-clone patch), which adds the `ansible_os_family != 'Darwin'` guard to the entire Base block under Darwin (9 locations). The `when` on `import_tasks` automatically propagates to subtasks, so ssh/fail2ban/limits/firewall are skipped together.
|
||||
|
||||
**Verification**: Passed `bash -n`; running the patch against a real `common/tasks/main.yml` yields valid YAML, 9 guard counts, idempotent secondary execution, and unchanged Linux sections (Debian/RedHat/addon).
|
||||
|
||||
**Note**: The user only specifically mentioned timezone, but to avoid back-and-forth, all homologous Base tasks that would fail have been guarded together.
|
||||
|
||||
---
|
||||
|
||||
## 10. Cont.: Vault Admin Initialization Script (TC-MAC-015, 19:50)
|
||||
|
||||
**Progress**: After common guarding, deployment advanced, vault has successfully started (passed health check), and the new blockage point is `vault : Bootstrap Vault admin userpass auth` (`no_log: true`, details hidden).
|
||||
|
||||
**Root Cause**: This task executes `files/init_vault_admin.sh`, and the script relies on `require_cmd vault/jq/curl/base64`. macOS does not have `jq` by default, and the apt dependency installation task for it was skipped on Darwin; furthermore, the minimal PATH for `ansible.builtin.script` does not include `/opt/homebrew/bin`, so brew-installed vault/jq might not be found.
|
||||
|
||||
**Solution**: Extended `patch_playbook_vault_macos()`:
|
||||
1. `macos.yml` added `brew install jq` (`creates: /opt/homebrew/bin/jq`);
|
||||
2. Bootstrap task appended `environment: PATH: "/opt/homebrew/bin:/usr/local/bin:{{ ansible_env.PATH }}"`.
|
||||
|
||||
**Verification**: Passed `bash -n`; running the patch on the vault role showed 1 jq task and 1 environment insertion, valid YAML, idempotent secondary execution, and correct bootstrap structure (environment is located between script parameters and `no_log`).
|
||||
|
||||
**Fallback**: If it still fails, temporarily disable `no_log` on the task to see the actual stderr from the script for further troubleshooting.
|
||||
|
||||
---
|
||||
|
||||
## 11. Cont.: True Cause of Vault Initialization Non-Idempotency (TC-MAC-016, 20:29)
|
||||
|
||||
**Investigation**: After temporarily disabling `no_log` on the bootstrap task and writing the output to a file in a mounted directory, the true error was captured:
|
||||
|
||||
```
|
||||
Code: 400 ... * missing entityID
|
||||
"A login request was issued that is subject to MFA validation ..."
|
||||
PUT /v1/identity/mfa/method/totp/admin-generate
|
||||
```
|
||||
|
||||
**True Cause (Not macOS specific)**: `init_vault_admin.sh` uses "login as that user" to retrieve `entity_id`, but the script also creates a login-MFA enforcement for userpass. Since the dev Vault persists across multiple deployments, during the second startup the login is blocked by MFA → no `entity_id` → `admin-generate` reports `missing entityID`. This is a re-run idempotency defect (jq/PATH had long ceased to be the issue).
|
||||
|
||||
**Fix**: Changed to parsing `entity_id` via identity **entity-alias** (iterate through aliases to match name+mount_accessor and retrieve canonical_id; on first run, explicitly create entity+alias), and removed the redundant token revoke. Real repo `init_vault_admin.sh` fixed; clone path gets synchronized patch via `patch_playbook_vault_macos()`. Diagnostic scaffolding removed, restoring `no_log: true`.
|
||||
|
||||
**Verification**: Both repository scripts passed `bash -n`; running the patch with git HEAD pristine vault role correctly rewrote the init script, zeroed out `bootstrap_token`, idempotent secondary execution, and the tasks YAML is valid with no diagnostic residue.
|
||||
|
||||
**Execution Recommendation**: Using the real repository as the source is the cleanest:
|
||||
`PLAYBOOK_DIR=/Users/shenlan/workspaces/cloud-neutral-toolkit/playbooks bash scripts/setup-ai-workspace-all-in-one.sh`
|
||||
(Or push both repositories to their respective mains, then `curl | bash`).
|
||||
|
||||
---
|
||||
|
||||
## 12. Cont.: PostgreSQL Mode Selection (TC-MAC-017, 20:43)
|
||||
|
||||
**Progress**: Vault bootstrap has passed (appeared on the duration board, no longer failing). New blockage point: `postgres : Materialize PostgreSQL admin password`.
|
||||
|
||||
**Root Cause**: `postgresql_deploy_mode` defaults to `compose` (Docker path), which doesn't apply to macOS; and the password by default is generated via password lookup at `/root/.ai_workspace_postgres_password`, but macOS lacks permission to write to `/root` → empty password → assert fails. The role actually has a `native`+`macos.yml` path prepared (brew postgresql@16).
|
||||
|
||||
**Strategy (Confirmed by User)**: macOS → `native`; Linux → default `compose`.
|
||||
|
||||
**Fix**: The Darwin branch of the script injects `-e postgresql_deploy_mode=native` + `append_secret_var postgresql_admin_password=$UNIFIED_AUTH_TOKEN` (directly provides the password, bypassing the `/root` lookup). Pure script change, Linux remains unchanged. Passed `bash -n`, `append_secret_var` is defined before use.
|
||||
|
||||
**Follow-up Observation**: The native path `macos.yml` uses the `community.general.homebrew` module. If this collection isn't installed, it might be the next issue; verifying this step first.
|
||||
|
||||
---
|
||||
|
||||
## 13. Cont.: postgres native installation Homebrew crash (TC-MAC-018, 20:50)
|
||||
|
||||
**Progress**: The native mode is active (postgres entered `macos.yml`). New error:
|
||||
|
||||
```
|
||||
/usr/local/Homebrew/.../macos_version.rb: unknown or unsupported macOS version: "27.0"
|
||||
```
|
||||
|
||||
**Root Cause (Not a general brew failure)**: The `community.general.homebrew` module auto-detected an expired **Intel Homebrew** (`/usr/local/Homebrew`), which doesn't recognize macOS 27.0 and crashed on startup; whereas vault/openclaw using `command: brew` (via the available brew on PATH) worked fine—it was the module choosing the wrong brew.
|
||||
|
||||
**Fix**: postgres `macos.yml` installation changed to `command: brew install postgresql@16` + `environment.PATH` prepended with `/opt/homebrew/bin:/usr/local/bin` + `HOMEBREW_NO_AUTO_UPDATE=1`, matching vault/openclaw. Real repo updated; clone path synchronized via new `patch_playbook_postgres_macos()`.
|
||||
|
||||
**Verification**: Script passed `bash -n`; running the patch with git HEAD pristine `macos.yml` replaced the module with command:brew, yielded valid YAML, and idempotent secondary execution.
|
||||
|
||||
**Note**: If the machine only has a single expired brew (pure Intel), it's an environment issue requiring `brew update` or Homebrew reinstallation.
|
||||
206
docs/zh/ARCHITECTURE.md
Normal file
206
docs/zh/ARCHITECTURE.md
Normal file
@ -0,0 +1,206 @@
|
||||
[🇺🇸 English](../../README.md) | [🇨🇳 中文](../../README.zh.md)
|
||||
|
||||
# XWorkspace 架构
|
||||
|
||||
XWorkspace 是一个构建在标准 Linux、systemd、Chrome / Chromium 以及本地运行时服务之上的 AI 工作区 Shell。
|
||||
|
||||
核心理念很简单:
|
||||
|
||||
不要向用户暴露传统的 Linux 桌面。
|
||||
使用 Chrome / Chromium 作为桌面 Shell,并使用本地 AI 工作区门户作为主要入口点。
|
||||
|
||||
XWorkspace 并不是要从头构建一个完整的操作系统。它保持了 Linux 基础的稳定和标准,同时用一个原生 AI 工作区替换了面向用户的桌面体验。
|
||||
|
||||
⸻
|
||||
|
||||
## 1. 设计目标
|
||||
|
||||
XWorkspace 围绕以下原则进行设计:
|
||||
|
||||
### 1. Chrome / Chromium 作为桌面 Shell
|
||||
用户通过 Chrome / Chromium 而不是 XFCE、GNOME 或传统的桌面环境进入工作区。
|
||||
|
||||
### 2. 门户优先的用户体验
|
||||
主要的工作区 UI 是一个本地的 Web 门户,通常暴露在:http://localhost:17000
|
||||
|
||||
3. 最少的传统桌面暴露
|
||||
XWorkspace 避免暴露面板、桌面图标、文件管理器桌面或传统的应用程序菜单。
|
||||
4. 本地优先的运行时服务
|
||||
核心服务通过用户级 systemd 服务在本地运行。
|
||||
5. 面向 AI 智能体的工作流
|
||||
工作区针对智能体 (Agent)、终端 (Terminal)、浏览器使用 (Browser Use)、计算机使用 (Computer Use)、模型网关 (Model Gateway)、金库 (Vault)、工作流 (Workflow)、技能 (Skill) 和插件 (Plugin) 场景进行了优化。
|
||||
6. 可组合的服务架构
|
||||
每个运行时能力都是一个独立的服务,可以单独启动、停止、升级或替换。
|
||||
|
||||
⸻
|
||||
|
||||
## 2. 顶层架构
|
||||
|
||||
```i11·
|
||||
┌──────────────────────────────────────────────┐
|
||||
│ Layer 1:Chrome / Chromium 桌面 Shell │
|
||||
│ │
|
||||
│ - 应用模式 (App mode) / Kiosk 模式 │
|
||||
│ - 全屏工作区入口 │
|
||||
│ - 替换传统的 Linux 桌面入口 │
|
||||
│ - 打开 http://localhost:17000 │
|
||||
└──────────────────────┬───────────────────────┘
|
||||
↓
|
||||
┌──────────────────────────────────────────────┐
|
||||
│ Layer 2:AI 工作区门户 (AI Workspace Portal) │
|
||||
│ │
|
||||
│ - 仪表板 (Dashboard) │
|
||||
│ - 应用启动器 (App launcher) │
|
||||
│ - 运行时状态 (Runtime status) │
|
||||
│ - 智能体主会话 (Agent sessions) │
|
||||
│ - 终端 / VSCode / 文件 │
|
||||
│ - 模型 / 金库 / 工作流入口 │
|
||||
└──────────────────────┬───────────────────────┘
|
||||
↓
|
||||
┌──────────────────────────────────────────────┐
|
||||
│ Layer 3:核心服务 (Core Services) │
|
||||
│ │
|
||||
│ - 桥接 (Bridge) │
|
||||
│ - 智能体运行时 / 网关 (Agent Runtime / Gateway)│
|
||||
│ - LiteLLM 代理 │
|
||||
│ - 金库 / 金库代理 (Vault / Vault Proxy) │
|
||||
│ - ttyd │
|
||||
│ - 状态生成器 (Status Generator) │
|
||||
│ - 本地 API / SSE / WebSocket │
|
||||
└──────────────────────┬───────────────────────┘
|
||||
↓
|
||||
┌──────────────────────────────────────────────┐
|
||||
│ Layer 4:应用 / 附加服务 (App / Extra Services) │
|
||||
│ │
|
||||
│ - 智能体 (Agent) │
|
||||
│ - 技能 (Skill) │
|
||||
│ - 工作流 (Workflow) │
|
||||
│ - 插件 (Plugin) │
|
||||
│ - 计算机使用 (Computer Use) │
|
||||
│ - 浏览器使用 (Browser Use) │
|
||||
│ - 代码服务器 (Code Server) │
|
||||
│ - 文件浏览器 (File Browser) │
|
||||
└──────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 3. 运行时流程
|
||||
|
||||
Linux 启动
|
||||
↓
|
||||
用户级 systemd 会话
|
||||
↓
|
||||
核心服务启动
|
||||
↓
|
||||
xworkspace-portal.service 启动本地门户
|
||||
↓
|
||||
xworkspace-shell.service 启动 Chrome / Chromium
|
||||
↓
|
||||
Chrome / Chromium 打开 http://localhost:17000
|
||||
↓
|
||||
用户进入 AI 工作区门户
|
||||
↓
|
||||
门户与桥接、智能体、LiteLLM、金库、ttyd 和附加服务通信
|
||||
|
||||
## 4. 核心概念
|
||||
|
||||
传统 Linux 桌面:
|
||||
桌面环境
|
||||
├─ 面板
|
||||
├─ 文件管理器
|
||||
├─ 终端
|
||||
├─ 浏览器
|
||||
├─ 应用菜单
|
||||
└─ 设置
|
||||
|
||||
XWorkspace 桌面
|
||||
|
||||
Chrome / Chromium 桌面 Shell
|
||||
└─ AI 工作区门户
|
||||
├─ 智能体控制台
|
||||
├─ 终端
|
||||
├─ VSCode / 代码服务器
|
||||
├─ 文件
|
||||
├─ 模型网关
|
||||
├─ 金库机密
|
||||
├─ 运行时状态
|
||||
├─ 工作流运行器
|
||||
├─ 插件中心
|
||||
├─ 浏览器使用
|
||||
└─ 计算机使用
|
||||
|
||||
|
||||
## 5. 显示栈策略
|
||||
|
||||
XWorkspace 避免将传统的 X11 桌面体验作为产品界面进行支持。
|
||||
然而,Chrome / Chromium 仍然需要一个显示栈。
|
||||
推荐的演进路径:
|
||||
|
||||
第一阶段:
|
||||
|
||||
使用 XFCE 或轻量级桌面会话,但隐藏传统桌面组件,仅暴露 Chrome / Chromium Shell。
|
||||
|
||||
第二阶段:
|
||||
|
||||
用一个最小化的窗口管理器替换 XFCE。只有 Chrome / Chromium 作为可见的工作区 Shell 被启动。
|
||||
|
||||
第三阶段:
|
||||
|
||||
转向 Wayland / Weston / Cage 模式。Chrome / Chromium 成为唯一面向用户的 Shell。
|
||||
|
||||
|
||||
## 访问与暴露策略
|
||||
|
||||
XWorkspace 遵循默认安全的访问策略。
|
||||
|
||||
默认情况下,XWorkspace 不会将完整的 AI 工作区门户、WebRTC 桌面、ttyd、LiteLLM、金库或其他内部服务直接暴露给公共互联网。
|
||||
|
||||
默认的公共入口应被限制为:https://xworkmate-bridge.example.com
|
||||
|
||||
此端点在早期阶段受访问令牌 (access token) 保护,并应在未来版本中演进为基于 JWT 的身份验证。
|
||||
|
||||
默认访问模型
|
||||
|
||||
公共互联网
|
||||
↓
|
||||
https://xworkmate-bridge.example.com
|
||||
↓
|
||||
令牌 / 未来 JWT 验证
|
||||
↓
|
||||
XWorkmate Bridge
|
||||
↓
|
||||
本地核心服务
|
||||
|
||||
AI 工作区门户默认保持本地访问:
|
||||
|
||||
Chrome / Chromium 桌面 Shell
|
||||
↓
|
||||
http://localhost:17000
|
||||
↓
|
||||
AI 工作区门户
|
||||
|
||||
|
||||
默认不暴露的服务:
|
||||
|
||||
- AI 工作区门户
|
||||
- WebRTC 桌面
|
||||
- ttyd
|
||||
- LiteLLM
|
||||
- Vault
|
||||
- OpenClaw 网关
|
||||
- 内部状态端点
|
||||
- 插件 / 工作流服务
|
||||
|
||||
高级用户模式
|
||||
|
||||
高级用户可以选择暴露额外的服务,但他们应明确地这样做并配置更强的访问控制。
|
||||
推荐的高级暴露要求:
|
||||
|
||||
- HTTPS
|
||||
|
||||
- MFA(多因素认证)
|
||||
- JWT 身份验证
|
||||
- IP 白名单(可选)
|
||||
- 反向代理访问策略
|
||||
- 审计日志
|
||||
- 速率限制
|
||||
- 敏感服务使用独立的子域名
|
||||
77
docs/zh/DATA_MANAGEMENT_TLDR.md
Normal file
77
docs/zh/DATA_MANAGEMENT_TLDR.md
Normal file
@ -0,0 +1,77 @@
|
||||
[🇺🇸 English](../../README.md) | [🇨🇳 中文](../../README.zh.md)
|
||||
|
||||
# AI 工作区数据管理 TL;DR
|
||||
|
||||
本文档提供了管理 AI 工作区生命周期的快速参考,包括使用单行引导脚本进行备份、恢复、迁移和卸载。
|
||||
|
||||
`setup-ai-workspace-all-in-one.sh` 脚本作为一个强大的编排器。你可以使用 `--` 或 `-s` 在 `bash` 管道的末尾传递特殊的子命令。
|
||||
|
||||
---
|
||||
|
||||
## 1. 备份 (Backup)
|
||||
|
||||
创建整个工作区(金库密钥、LiteLLM 数据库、QMD 记忆、会话状态和插件配置)的 AES-256 加密归档。
|
||||
|
||||
**默认备份:**
|
||||
(默认将备份到 `~/ai_workspace_backup.tar.gz.enc`)
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | bash -s -- backup
|
||||
```
|
||||
|
||||
**自定义输出路径:**
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | bash -s -- backup --output /data/my_cold_backup.tar.gz.enc
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 恢复 (Restore)
|
||||
|
||||
从冷备份归档中恢复 AI 工作区。这将会无缝地把金库 K/V 机密、PostgreSQL 数据库状态以及所有配置设置重新注入到一个工作环境中。
|
||||
|
||||
**默认恢复:**
|
||||
(默认查找 `~/ai_workspace_backup.tar.gz.enc`)
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | bash -s -- restore
|
||||
```
|
||||
|
||||
**自定义输入路径:**
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | bash -s -- restore --input /data/my_cold_backup.tar.gz.enc
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 跨主机迁移 (Migrate)
|
||||
|
||||
使用安全的 SSH 路径 (`rsync`) 和 `qmd sync`,将 AI 工作区从远程节点无缝迁移并合并到本地机器。这会在保持远程主机非破坏性状态的同时,将状态、向量索引和记忆网络带到本地主机。
|
||||
|
||||
**从远程用户/主机迁移:**
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | bash -s -- migrate --source ubuntu@openclaw.svc.plus
|
||||
```
|
||||
*(在运行此命令之前,请确保你拥有免密 SSH,或者已为 `ubuntu@openclaw.svc.plus` 加载了活动的代理)。*
|
||||
|
||||
---
|
||||
|
||||
## 4. 卸载清理 (Uninstall)
|
||||
|
||||
卸载 AI 工作区组件和配置。
|
||||
|
||||
**标准卸载:**
|
||||
(停止服务并移除二进制文件,但保持数据缓存完整)
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | bash -s -- uninstall
|
||||
```
|
||||
|
||||
**清除卸载:**
|
||||
(停止服务并销毁所有数据库、缓存、配置和用户状态。请极度谨慎使用!)
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | bash -s -- uninstall --purge
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 技术说明
|
||||
- **安全性:** 备份归档高度敏感。它们包含金库导出的机密和 LiteLLM 数据库转储。它们会通过使用部署的对称密钥(`Vault Password` 或 `AI_WORKSPACE_AUTH_TOKEN`)经 AES-256-CBC 自动加密。
|
||||
- **依赖关系:** 迁移、备份和恢复例程会在执行其特定的 Ansible 负载之前,自动确保相关依赖(如 PostgreSQL 和 Vault 服务)已完全运行。
|
||||
140
docs/zh/FEATURES.md
Normal file
140
docs/zh/FEATURES.md
Normal file
@ -0,0 +1,140 @@
|
||||
[🇺🇸 English](../../README.md) | [🇨🇳 中文](../../README.zh.md)
|
||||
|
||||
# XWorkspace 控制台特性
|
||||
|
||||
本文档总结了 XWorkspace 控制台面向用户和操作者的特性。它旨在作为主页 README 中链接的详细特性参考。
|
||||
|
||||
## 1. 产品范围
|
||||
|
||||
XWorkspace 控制台是一个本地 AI 工作区控制平面,它结合了:
|
||||
|
||||
- 用于工作区导航的 React 仪表板
|
||||
- 用于服务和健康状态的 Go API
|
||||
- 用于运行时编排的 systemd 用户服务
|
||||
- 用于桌面集成的 XFCE 和 XDG 模板
|
||||
- 对本地 AI 工具和服务的基于浏览器的访问
|
||||
|
||||
该控制台针对本地优先的使用场景进行了优化,浏览器充当主要的操作员界面。
|
||||
|
||||
## 2. 主页体验
|
||||
|
||||
主页作为中央控制界面:
|
||||
|
||||
- 显示工作区概览
|
||||
- 呈现服务健康和运行时状态
|
||||
- 提供对服务和选项卡的快速访问
|
||||
- 保持布局紧凑且具有操作性
|
||||
- 支持将图像和视频伪影审查作为自定义选项卡
|
||||
|
||||
README 中的主页预览是规范的视觉入口点。
|
||||
|
||||
## 3. 选项卡系统
|
||||
|
||||
选项卡是在工作区不同区域之间导航的主要方式。
|
||||
|
||||
### 内置选项卡
|
||||
|
||||
- `Workspace` (工作区)
|
||||
- 主要概览和仪表板入口
|
||||
- `OpenClaw`
|
||||
- 网关访问和频道视图
|
||||
- `LiteLLM`
|
||||
- 模型路由和提供商管理
|
||||
- `Vault` (金库)
|
||||
- 机密和身份验证管理
|
||||
- `Terminal` (终端)
|
||||
- 嵌入式的本地 Shell 访问
|
||||
|
||||
### 自定义选项卡
|
||||
|
||||
控制台还可以托管用于面向伪影工作流的自定义选项卡。这正是图像和视频工作流自然契合的地方。
|
||||
|
||||
这种选项卡模型让工作区能够将审查、导航和运行时操作保持在一个地方,而不是将它们分散到不同的应用程序中。
|
||||
|
||||
## 4. 图像和视频工作流
|
||||
|
||||
图像和视频工作流是首要的控制台用例。
|
||||
|
||||
它们被设计为支持:
|
||||
|
||||
- 预览生成或导入的媒体
|
||||
- 在查看服务状态的同时审查输出
|
||||
- 在不离开控制台 Shell 的情况下,在伪影和运行时工具之间切换
|
||||
- 将以媒体为中心的工作保持在同一个操作工作区内
|
||||
|
||||
## 5. 服务集成
|
||||
|
||||
控制台集成了本地运行时服务,并将它们作为工作区体验的一部分暴露出来。
|
||||
|
||||
### 核心服务
|
||||
|
||||
- 控制台仪表板 (Console dashboard)
|
||||
- Go 状态 API (Go status API)
|
||||
- 桥接控制平面 (Bridge control plane)
|
||||
- OpenClaw 网关 (OpenClaw Gateway)
|
||||
- LiteLLM UI/API
|
||||
- 金库 (Vault)
|
||||
- ttyd 终端 (ttyd terminal)
|
||||
|
||||
### 状态表面
|
||||
|
||||
仪表板可以使用:
|
||||
|
||||
- `/health`
|
||||
- `/services`
|
||||
- `/metrics/simple`
|
||||
|
||||
这使得 UI 在保持响应的同时,仍能反映当前的本地运行时状态。
|
||||
|
||||
## 6. 桌面集成
|
||||
|
||||
该代码库包含用于以下用途的桌面支持文件:
|
||||
|
||||
- XFCE 会话和面板配置
|
||||
- XDG 自动启动启动器
|
||||
- systemd 用户单元
|
||||
- Chrome 或 Chromium 应用模式启动路径
|
||||
- 本地控制台启动脚本
|
||||
|
||||
这使得控制台很容易自动启动,并易于与最小化桌面 Shell 对齐。
|
||||
|
||||
## 7. 访问模型
|
||||
|
||||
控制台专为本地优先访问而设计。
|
||||
|
||||
常见的访问点包括:
|
||||
|
||||
- `http://127.0.0.1:17000` 用于主控制台
|
||||
- `http://127.0.0.1:8788` 用于 Go API
|
||||
- `http://127.0.0.1:18789` 用于 OpenClaw
|
||||
- `http://127.0.0.1:4000/ui` 用于 LiteLLM
|
||||
- `http://127.0.0.1:8200/ui` 用于 Vault
|
||||
- `http://127.0.0.1:7681` 用于嵌入式终端
|
||||
|
||||
端口规划在 [`docs/operations/service-port-plan.md`](./operations/service-port-plan.md) 中进行了单独记录。
|
||||
|
||||
## 8. 代码库角色
|
||||
|
||||
该代码库被划分为清晰的功能区域:
|
||||
|
||||
- `dashboard/`
|
||||
- 用户界面
|
||||
- `api/`
|
||||
- 状态和健康端点
|
||||
- `config/`
|
||||
- 桌面和服务配置
|
||||
- `scripts/`
|
||||
- 安装、启动、重置和启动辅助脚本
|
||||
- `docs/`
|
||||
- 架构、设置、操作和特性参考
|
||||
|
||||
## 9. 这个代码库不是什么
|
||||
|
||||
XWorkspace 控制台的目的**不是**成为:
|
||||
|
||||
- 一个完整的桌面环境替代品
|
||||
- 一个自定义合成器 (compositor) 项目
|
||||
- 一个没有服务编排的通用 Web 应用程序 Shell
|
||||
- 一个没有运行时集成的营销网站
|
||||
|
||||
它是一个专注于 AI 工作区操作的控制平面。
|
||||
95
docs/zh/OFFLINE_AI_WORKSPACE_INSTALLER.md
Normal file
95
docs/zh/OFFLINE_AI_WORKSPACE_INSTALLER.md
Normal file
@ -0,0 +1,95 @@
|
||||
[🇺🇸 English](../../README.md) | [🇨🇳 中文](../../README.zh.md)
|
||||
|
||||
# 离线 AI 工作区安装程序
|
||||
|
||||
`offline-package-ai-workspace-installer.yaml` 为 `setup-ai-workspace-all-in-one.sh` 构建了用于 tarball 资源包的离线打包程序。
|
||||
|
||||
## 支持的目标系统
|
||||
|
||||
- Debian: 13, 12, 11
|
||||
- Ubuntu LTS: 26.04, 24.04, 22.04
|
||||
- 架构: amd64, arm64
|
||||
|
||||
Ubuntu 20.04 不在默认支持矩阵中,因为标准支持已移至 Ubuntu Pro/ESM。
|
||||
|
||||
## 包内容
|
||||
|
||||
- `repos/playbooks`
|
||||
- `repos/xworkspace-console`
|
||||
- `repos/xworkspace-core-skills`
|
||||
- `repos/xworkmate-bridge`
|
||||
- `repos/qmd`
|
||||
- `repos/litellm`
|
||||
- `packages/apt`
|
||||
- `packages/npm`
|
||||
- `packages/npm-cache`
|
||||
- `packages/pip`
|
||||
- `packages/bin`
|
||||
- `packages/images`
|
||||
- `scripts/ai-workspace-offline-install.sh`
|
||||
- `metadata/manifest.json`
|
||||
- `metadata/*.commit`
|
||||
|
||||
## 运行时用法
|
||||
|
||||
在线引导脚本优先使用 `ai-workspace-lab/xworkspace-console` GitHub 版本发布中对应的离线包(当其可用时):
|
||||
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | bash -
|
||||
```
|
||||
|
||||
将 `AI_WORKSPACE_OFFLINE_MODE=off` 设置为强制使用传统的纯在线路径,或者将 `AI_WORKSPACE_OFFLINE_MODE=force` 设置为在无法准备匹配的离线包时失败。
|
||||
|
||||
默认包的获取源是:
|
||||
|
||||
```text
|
||||
https://github.com/ai-workspace-lab/xworkspace-console/releases/download/<tag>/ai-workspace-all-in-one-offline-<distro>-<version>-<arch>.tar.gz
|
||||
```
|
||||
|
||||
当 `AI_WORKSPACE_OFFLINE_RELEASE_TAG=latest` 时,引导脚本会向 GitHub 请求最新且实际包含匹配 tarball 资产的非草稿发布版本,因此如果 `releases/latest` 目标缺少该文件,它将跳过该发布版本。固定的发布版本标签仍可像以前一样工作。
|
||||
|
||||
对于私有镜像或固定发布,请使用:
|
||||
|
||||
```bash
|
||||
AI_WORKSPACE_OFFLINE_PACKAGE_BASE_URL=https://mirror.example/offline-package/ai-workspace/offline-ai-workspace-<run_number> \
|
||||
bash scripts/setup-ai-workspace-all-in-one.sh
|
||||
|
||||
AI_WORKSPACE_OFFLINE_RELEASE_TAG=offline-ai-workspace-<run_number> \
|
||||
bash scripts/setup-ai-workspace-all-in-one.sh
|
||||
```
|
||||
|
||||
要使用来自本地文件系统的特定、预先下载的离线部署包:
|
||||
|
||||
```bash
|
||||
AI_WORKSPACE_OFFLINE_PACKAGE=/path/to/offline-package.tar.gz \
|
||||
bash scripts/setup-ai-workspace-all-in-one.sh
|
||||
```
|
||||
|
||||
你也可以在主机上提取目标包并运行:
|
||||
|
||||
```bash
|
||||
sudo ./scripts/ai-workspace-offline-install.sh
|
||||
```
|
||||
|
||||
需要时,通过 `sudo env` 明确传递部署设置:
|
||||
|
||||
```bash
|
||||
sudo env \
|
||||
XWORKMATE_BRIDGE_DOMAIN=acp-bridge.onwalk.net \
|
||||
AI_WORKSPACE_SECURITY_LEVEL=strict \
|
||||
./scripts/ai-workspace-offline-install.sh
|
||||
```
|
||||
|
||||
该脚本配置了一个本地 APT 存储库,安装了捆绑的二进制文件,在 Docker 可用时加载了打包的容器镜像,并运行了带有本地源目录的打包的 all-in-one 引导脚本。
|
||||
|
||||
## 部署时间记录
|
||||
|
||||
在 `acp-bridge.onwalk.net` 上的远程 `setup-ai-workspace-all-in-one.sh` 运行中,显示了以下可见的时间耗费点:
|
||||
|
||||
- OpenClaw npm 包/插件安装和依赖修复:约 68 秒
|
||||
- Codex ACP Go 编译:约 37 秒
|
||||
- Codex/OpenCode/Gemini/Hermes 的 ACP 虚拟主机配置:约 95 秒
|
||||
- 控制台运行时 apt/package 设置和 ttyd:约 47 秒
|
||||
- 智能体技能同步和质量检查:约 48 秒
|
||||
|
||||
被采样日志的前几分钟包括了 Node、apt 以及 AI 运行时的环境配置(在上述被捕获的时间窗口之前)。这些阶段被视为极其耗费资源的准备阶段,所以它们通过 APT 缓存、npm tarballs、pip wheels、本地 git 源码库、二进制文件和容器镜像 tarballs 被包含在了离线包中。
|
||||
55
docs/zh/REPOSITORY_OVERVIEW.md
Normal file
55
docs/zh/REPOSITORY_OVERVIEW.md
Normal file
@ -0,0 +1,55 @@
|
||||
[🇺🇸 English](../../README.md) | [🇨🇳 中文](../../README.zh.md)
|
||||
|
||||
# 代码库概览
|
||||
|
||||
本文档收集了对于维护者和集成者来说有用的代码库细节,同时保持主页 README 专注于使用入口。
|
||||
|
||||
## 核心结构
|
||||
|
||||
- `config/xworkspace-desktop.yaml`
|
||||
- 桌面端口、浏览器选择和服务命名的单一事实来源
|
||||
- `scripts/`
|
||||
- 设置、重置、安装和浏览器启动辅助脚本
|
||||
- `config/xfce4/`
|
||||
- XFCE 面板、窗口管理器、会话和快捷方式模板
|
||||
- `config/autostart/`
|
||||
- 控制台的 XDG 自动启动入口
|
||||
- `config/systemd/user/`
|
||||
- 用于控制台、OpenClaw、Bridge、LiteLLM 和 Vault 的 systemd 用户服务
|
||||
- `api/`
|
||||
- 暴露 `/health`、`/services` 和 `/metrics/simple` 的 Go API
|
||||
- `dashboard/`
|
||||
- React + Vite + TypeScript 仪表板
|
||||
|
||||
## 主要服务名称
|
||||
|
||||
此代码库在命名上将 `xworkspace-console` 统一标准化为主要的本地控制平面 UI 服务。
|
||||
|
||||
早期重叠的名称(如 `xworkspace-dashboard` 和 `xworkspace-portal`)被视为历史概念,而不是该代码库中独立的主要服务。
|
||||
|
||||
## 端点规划
|
||||
|
||||
规范的本地控制台端点是:
|
||||
|
||||
- `http://127.0.0.1:17000`
|
||||
|
||||
端口分配:
|
||||
|
||||
- `17000`: XWorkspace 控制台 React 仪表板
|
||||
- `8788`: XWorkspace Go 状态 API
|
||||
- `8787`: XWorkmate Bridge 控制平面
|
||||
- `18789`: OpenClaw 网关
|
||||
- `4000`: LiteLLM UI/API
|
||||
- `8200`: Vault
|
||||
- `7681`: ttyd 嵌入式终端
|
||||
- `7000`: 已弃用的旧版门户,不要在新的控制台部署中使用
|
||||
|
||||
查看 [`docs/operations/service-port-plan.md`](./operations/service-port-plan.md) 以了解实机检查和迁移顺序。
|
||||
|
||||
## 备注
|
||||
|
||||
- XFCE 仍然是桌面基础层。
|
||||
- 仪表板是基于 React + Vite + TypeScript 构建的。
|
||||
- 状态 API 是用 Go 编写的。
|
||||
- 服务管理通过 systemd 用户单元进行。
|
||||
- 主题和 Shell 定制通过 XFCE 配置、兼容 GTK/XDG 的模板以及 Shell 脚本来处理。
|
||||
231
docs/zh/RUNTIME_ARCHITECTURE.md
Normal file
231
docs/zh/RUNTIME_ARCHITECTURE.md
Normal file
@ -0,0 +1,231 @@
|
||||
[🇺🇸 English](../../README.md) | [🇨🇳 中文](../../README.zh.md)
|
||||
|
||||
## 3. 现状分析:角色层级关系
|
||||
|
||||
`setup-ai-workspace-all-in-one.sh`(位于 console 仓库)在目标主机引导后,运行 `setup-ai-workspace-all-in-one.yml`(位于 playbooks 仓库)。其按导入顺序的角色层级:
|
||||
|
||||
```
|
||||
setup-ai-workspace-all-in-one.sh [repo: xworkspace-console/scripts]
|
||||
└─ ansible-playbook setup-ai-workspace-all-in-one.yml [repo: playbooks]
|
||||
├─1 setup-nodejs.yml → role roles/vhosts/nodejs NodeJS(22.x)+yarn
|
||||
├─2 setup-xworkspace-console.yaml WORKSPACE PORTAL/CONSOLE(内联 task,无 role)
|
||||
│ apt: caddy,xfce4,python3,golang-go,google-chrome-stable,ttyd
|
||||
│ git clone console → npm build;systemd --user: console(:17000)/api(:8788)/ttyd(:7681)/status.timer
|
||||
│ Caddy 公网站点 workspace.svc.plus ⚠ 标准模式下也公开
|
||||
├─3 setup-ai-agent-skills.yml → role roles/ai_agent_runtime AI WORKSPACE RUNTIME 核心
|
||||
│ NodeJS(24.x)+Playwright;Agent CLI: opencode/gemini/codex/claude;Python/browser/docs/fonts
|
||||
│ └─ role agent_skills → 注入 xworkspace-core-skills 市场技能
|
||||
├─4 deploy_gateway_openclaw.yml → role roles/vhosts/gateway_openclaw OpenClaw(2026.5.28)
|
||||
├─5 deploy_xworkmate_bridge_vhosts.yml BRIDGE + ACP 集群
|
||||
│ ├─ import setup-xworkspace-console.yaml(带 bridge 变量再跑一次)
|
||||
│ └─ roles: acp_server_codex / acp_server_opencode / acp_server_gemini /
|
||||
│ acp_server_hermes / xworkmate_bridge(:8787 本地,公网 Caddy)
|
||||
│ 域名默认 xworkmate-bridge.svc.plus → acp-bridge.onwalk.net
|
||||
├─6 setup-vault.yaml → role roles/vhosts/vault Vault(1.20.4) :8200
|
||||
├─7 setup-postgres-standalone.yaml → role roles/vhosts/postgres(dep: common) 原生 apt PG17 :5432
|
||||
├─8 setup-litellm.yaml → role roles/vhosts/litellm pip 安装 :4000
|
||||
├─9 deploy_QMD.yml → role roles/vhosts/qmd bun qmd, MCP :8181
|
||||
├─10 deploy_agent_hermes.yml → role roles/vhosts/acp_server_hermes ⚠ Hermes 重复部署(与步骤5重叠)
|
||||
└─11 setup-xfce-xrdp.yaml [可选] → role roles/vhosts/xfce_xrdp_minimal
|
||||
→ 拆分为 xfce_desktop_minimal_runtime + remote_desktop_xrdp_server
|
||||
```
|
||||
|
||||
### 3.1 关键发现
|
||||
|
||||
1. **公开面冲突**:步骤 2/5 在 `ai_workspace_security_level != strict` 时为 `workspace.svc.plus` 部署公网 Caddy 站点,导致 Portal 也对外暴露,与“Bridge 唯一公开”冲突。
|
||||
2. **Hermes 重复部署**:步骤 5(ACP 集群内)与步骤 10(独立)各部署一次,冗余。
|
||||
3. **版本固定点分散**:OpenClaw、Vault 已有固定变量;NodeJS 有但偏宽松(`22.x`/`24.x`);Hermes、QMD、LiteLLM 缺少显式版本/源固定。
|
||||
|
||||
---
|
||||
|
||||
## 4. 关键设计决策
|
||||
|
||||
### 4.1 对外公开面:Bridge Only
|
||||
|
||||
- **Bridge 是默认唯一公开的服务**:`XWORKMATE_BRIDGE_PUBLIC_ACCESS` 默认 `true`,公网域名由 `XWORKMATE_BRIDGE_DOMAIN` 自定义传入(目标主机 `acp-bridge.onwalk.net`)。如需关闭可显式设 `false`。
|
||||
- `xworkspace_console_public_access` 默认 `false`(仅 `XWORKSPACE_CONSOLE_PUBLIC_ACCESS=true` 时公开)。
|
||||
- `GATEWAY_OPENCLAW_PUBLIC_ACCESS` / `VAULT_PUBLIC_ACCESS` 默认 `false`;其余(QMD / Hermes / PG / LiteLLM)维持本地监听(`127.0.0.1`),不部署公网 Caddy 站点。
|
||||
- 实现方式:**最小改动**——仅调整默认值/开关并对齐 env 名称(§2.1),不删除既有 public_access 能力(保留可手动放开)。
|
||||
|
||||
### 4.2 Hermes 去重
|
||||
|
||||
- `setup-ai-workspace-all-in-one.yml` 中移除步骤 10 的独立 `deploy_agent_hermes.yml` 导入(步骤 5 的 ACP 集群已含 hermes)。
|
||||
- 保留 `deploy_agent_hermes.yml` 文件本身,供单独部署场景使用,仅从 all-in-one 聚合链里去重。
|
||||
|
||||
### 4.3 运行模式矩阵(docker / k3s / systemd)
|
||||
|
||||
引入一个**校验型**变量 `ai_workspace_runtime_modes`(列表),在 all-in-one 顶部加一段 `assert` 守卫,不重写各组件部署逻辑:
|
||||
|
||||
| 约束 | 规则 |
|
||||
|---|---|
|
||||
| 互斥 | `docker` 与 `k3s` 不可同时出现 |
|
||||
| 可组合 | `docker + systemd` 允许;`systemd` 可单独 |
|
||||
| 默认 | `['docker','systemd']`(多数 Agent 服务 systemd,PostgreSQL 走 docker compose) |
|
||||
|
||||
组件与模式映射(复用现有能力,不新增重型实现):
|
||||
|
||||
| 组件 | systemd | docker | k3s |
|
||||
|---|---|---|---|
|
||||
| Console / API / ttyd / Bridge / ACP / OpenClaw / QMD / LiteLLM | ✅ 默认 | — | — |
|
||||
| PostgreSQL | 可选 | ✅ **默认 docker compose** | 可选 |
|
||||
| Vault | `vault_deploy_mode=systemd` | — | `vault_deploy_mode=kubernetes`(k3s) |
|
||||
|
||||
守卫伪代码(放入 all-in-one 顶层 play):
|
||||
|
||||
```yaml
|
||||
- name: Validate runtime mode combination
|
||||
hosts: all
|
||||
gather_facts: false
|
||||
tasks:
|
||||
- assert:
|
||||
that:
|
||||
- not ('docker' in ai_workspace_runtime_modes and 'k3s' in ai_workspace_runtime_modes)
|
||||
- ai_workspace_runtime_modes | length > 0
|
||||
fail_msg: "docker 与 k3s 互斥;请选择 docker/k3s/systemd 的合法组合。"
|
||||
```
|
||||
|
||||
### 4.4 PostgreSQL 默认 docker compose
|
||||
|
||||
- 新增开关 `postgresql_deploy_mode`,默认 `compose`。
|
||||
- `compose` 模式:在 `roles/vhosts/postgres` 增加一条 compose 部署路径(镜像版本固定,端口/口令复用现有变量),与现有原生 apt 路径并存、互斥择一。
|
||||
- 不删除原生 apt 路径(设 `postgresql_deploy_mode=native` 可回退)。
|
||||
|
||||
### 4.5 QMD / LiteLLM 源仓库与版本固定
|
||||
|
||||
- QMD:安装源指向 `https://github.com/ai-workspace-services/qmd.git`,新增 `qmd_source_repo` / `qmd_version` 变量固定。
|
||||
- LiteLLM:安装源指向 `https://github.com/ai-workspace-services/litellm.git`,新增 `litellm_source_repo` / `litellm_version` 变量固定。
|
||||
|
||||
---
|
||||
|
||||
## 10. 并发优化设计(深入分析 + 定制策略)
|
||||
|
||||
> 目标:在**不丢 tasks、不破坏现有 role 结构、不牺牲稳定性**的前提下,提升单机部署速度。
|
||||
> 总策略:三相执行——**Phase 1 串行(系统全局/抢锁)→ Phase 2 并发(互不依赖 I/O)→ Phase 3 串行(确定性收口)**。不要把多个 role 直接改并发;只把“耗时、互不依赖、不写同一文件、不抢同一锁”的任务做 `async`,最后 `async_status` 收口。
|
||||
|
||||
### 10.1 三相模型(权威定义)
|
||||
|
||||
**Phase 1 — 必须串行**(抢锁 / 修改系统全局状态):
|
||||
`apt update`、`apt install`、`dpkg` 相关、添加 apt repo / keyring、用户/用户组创建、基础目录创建、基础权限设置、Docker 安装、Caddy 安装、systemd 基础准备、防火墙基础规则、**全局 pip / 全局 npm(-g) 安装**。
|
||||
|
||||
**Phase 2 — 可以并发**(互不依赖、不写同一文件、不操作同一锁):
|
||||
`docker pull` 多镜像、下载多个二进制、`git clone` 多仓库、`go build`、**不同目录**的 `npm/pnpm install`、**不同目录**的前端 build、拉取插件、拉取静态资源、生成互不冲突的服务配置、初始化各服务独立工作目录、各服务独立 prepare 脚本。
|
||||
|
||||
**Phase 3 — 必须串行**(收口确定性):
|
||||
渲染最终配置、`systemd daemon-reload`、`enable service`、按依赖顺序 `start/restart`、health check、输出部署结果、清理临时文件。
|
||||
|
||||
### 10.2 关键定制结论(针对本 Playbook 的深入分析)
|
||||
|
||||
1. **所有 `npm -g` 共享同一 prefix → 必须 Phase 1 串行。**
|
||||
`roles/vhosts/nodejs` 设 `npm_config_prefix=/usr/local/lib/npm`;Agent CLI(opencode-ai / @google/gemini-cli / @openai/codex / @anthropic-ai/claude-code)、`yarn`、`openclaw@ver` 全部 `npm -g` 到该 prefix。并发会争用同一 `node_modules`/`.staging` 与 npm cache 锁 → **不可并发**。
|
||||
2. **LiteLLM 已改为独立 Python 3.13 venv,但依赖安装仍应串行收口**。它不再写系统 site-packages,但 `pip install litellm[proxy]` 依赖树大、网络失败率高,默认方向应是优先消费离线 wheelhouse,在线 venv 安装仅作 fallback。
|
||||
3. **真正安全的 Phase 2 候选是“外部 I/O 预取”**:git clone、二进制下载、docker pull、独立目录的前端 build、runtime release 下载。它们不碰 dpkg/npm-prefix/pip 全局锁,且写入各自独立路径。
|
||||
4. **跨 sub-playbook 的并发收益最大处在 Shell 预取层**:11 个步骤由 ansible 顺序导入,play 间难并发;把可并行的 I/O 上提到 bootstrap 的 Phase 2 fork 池(§10.5)预取,ansible 仅消费已就位产物,是收益/风险比最高的定制。
|
||||
5. **离线包优先**(呼应 TODO):已有离线安装包/已导入镜像时,Phase 2 预取应短路跳过,直接复用缓存。
|
||||
|
||||
### 10.3 现状任务 → 三相映射
|
||||
|
||||
| 步骤 / role | Phase 1(串行) | Phase 2(可并发预取) | Phase 3(串行收口) |
|
||||
|---|---|---|---|
|
||||
| 1 nodejs | nodesource keyring/repo、`apt install nodejs`、`npm -g yarn` | — | — |
|
||||
| 2 console | apt(caddy/xfce4/python3/golang-go/chrome)+chrome repo/key、用户/目录/权限 | `get_url` ttyd 二进制、`git clone` console、dashboard `npm install && build`(独立目录) | 渲染 systemd unit/env/portal-services.json、`daemon-reload`/enable/restart、Caddy 写入+reload |
|
||||
| 3 ai_agent_runtime | `npm -g` Agent CLI、全局 pip(python deps)、apt(browser/docs/fonts)、Playwright(-g) | `agent_skills` 拉取 core-skills 市场(独立目录) | 校验/health、register 输出 |
|
||||
| 4 gateway_openclaw | `npm -g openclaw@ver`+插件 | (插件若独立目录拉取可并发) | 配置渲染、systemd、版本 assert、health |
|
||||
| 5 bridge + ACP | 同步 console;acp_server_* 的全局安装部分 | `xworkmate-go-core` 二进制下载/放置、acp 各自独立工作目录 prepare | 配置渲染、按依赖 `requires acp-*.service` 顺序启动、validation |
|
||||
| 6 vault | (systemd 基础准备) | `get_url` vault zip 下载、解压放置 | 配置渲染、systemd/init、health |
|
||||
| 7 postgres | Docker 安装、common 基础 | `docker pull` PG 镜像、初始化独立 data 目录 | compose 渲染、`compose up`、health |
|
||||
| 8 litellm | apt/Homebrew Python 准备、Python 3.13 venv 创建、离线 wheelhouse 或 fallback pip 安装 | 下载 `litellm-runtime-<distro>-<version>-<arch>.tar.gz`、校验 SHA256、准备 `packages/pip`/`metadata/runtime.env` | 配置渲染、Prisma client generate、systemd/launchd、health(`:4000/health`) |
|
||||
| 9 qmd | (bun 运行时安装,全局) | 条件并发:qmd 拉取/`bun install`(隔离于 `~/.bun`,不碰 dpkg) | qmd.env/index.yml 渲染、systemd --user、health(`:8181`) |
|
||||
| 11 xfce(可选) | apt 桌面包/xrdp/chrome、`npm -g`/Playwright | — | xrdp 服务 enable/start、会话配置 |
|
||||
|
||||
> 说明:标“条件并发”的(如 qmd `bun`)仅当确认其只写入服务自身用户目录、且不与同时段其它全局安装争锁时才纳入 Phase 2,否则归 Phase 1。
|
||||
|
||||
### 10.4 Ansible 层 async 模式(保留全部属性)
|
||||
|
||||
在**单个 play 内**对 Phase 2 任务用 `poll:0` 发起、集中 `async_status` 收口。`register`/`when`/`notify`/`tags`/`become`/`failed_when` 一律保留:
|
||||
|
||||
```yaml
|
||||
- name: Download ttyd binary (async)
|
||||
ansible.builtin.get_url: { url: "...", dest: "{{ ttyd_path }}", mode: "0755" }
|
||||
async: 1800
|
||||
poll: 0
|
||||
register: ttyd_job
|
||||
|
||||
- name: Clone xworkspace-console (async)
|
||||
ansible.builtin.git: { repo: "...", dest: "{{ repo_dir }}", version: main, depth: 1 }
|
||||
become_user: "{{ xworkspace_console_user }}"
|
||||
async: 1800
|
||||
poll: 0
|
||||
register: console_clone_job
|
||||
|
||||
# …其它独立 Phase 2 任务一并 poll:0 发起…
|
||||
|
||||
- name: Collect async Phase-2 jobs
|
||||
ansible.builtin.async_status: { jid: "{{ item }}" }
|
||||
register: p2
|
||||
until: p2.finished
|
||||
retries: 120
|
||||
delay: 5
|
||||
loop:
|
||||
- "{{ ttyd_job.ansible_job_id }}"
|
||||
- "{{ console_clone_job.ansible_job_id }}"
|
||||
```
|
||||
|
||||
- 收口铁律:任一 Phase 2 产物在**被 Phase 3 消费前**必须 `finished`。
|
||||
- dpkg/全局 npm/全局 pip **绝不** `async`;LiteLLM venv 安装虽然不再是全局 pip,也应在 wheelhouse 准备完成后串行执行,便于失败定位与重试(§10.2)。
|
||||
|
||||
### 10.5 Shell 层动态 fork 并发(≤ CPU 核心数 × 2,预取层)
|
||||
|
||||
bootstrap 把可并行的外部 I/O 收敛到一个**负载自适应的有界 fork 池**,在 ansible 前(Phase 2 预取)与摘要阶段使用。硬上限为目标主机在线 CPU 核心数的 2 倍;`AI_WORKSPACE_MAX_PARALLEL_JOBS` 可设更低人工上限,默认 `auto`。每次启动子任务前读取 1 分钟 load average,按 `min(人工上限, 2 × CPU - ceil(load1))` 动态收缩,最低保留 1 路:
|
||||
|
||||
```bash
|
||||
CPU_COUNT="$(getconf _NPROCESSORS_ONLN)"
|
||||
HARD_LIMIT=$((CPU_COUNT * 2))
|
||||
LOAD_CEILING="$(awk -v load="$(cut -d' ' -f1 /proc/loadavg)" 'BEGIN { n=int(load); print load > n ? n + 1 : n }')"
|
||||
DYNAMIC_LIMIT=$((HARD_LIMIT - LOAD_CEILING))
|
||||
[ "$DYNAMIC_LIMIT" -ge 1 ] || DYNAMIC_LIMIT=1
|
||||
|
||||
run_bounded() {
|
||||
while [ "$(jobs -rp | wc -l)" -ge "$DYNAMIC_LIMIT" ]; do wait -n; done
|
||||
"$@" &
|
||||
}
|
||||
|
||||
# Phase 2 预取:5 仓库 pull + 二进制下载 + 镜像 pull(离线包存在则短路跳过)
|
||||
for r in playbooks console core-skills qmd litellm; do run_bounded fetch_repo "$r"; done
|
||||
for b in ttyd vault xworkmate-go-core; do run_bounded fetch_binary "$b"; done
|
||||
for img in "${PG_IMAGES[@]}"; do run_bounded docker_pull "$img"; done
|
||||
for p in "${pids[@]}"; do wait "$p" || rc=1; done
|
||||
[ "$rc" -eq 0 ] || { echo "[phase2] 存在失败子任务"; exit 1; }
|
||||
```
|
||||
|
||||
- 健康探测 fan-out(摘要前):对 Portal/Bridge/OpenClaw/QMD/Hermes/PG/Vault/LiteLLM 的 `systemctl is-active`+`curl` 使用同一动态上限,统一按固定顺序汇总。
|
||||
- 每子进程带日志前缀(`[repo:qmd]`/`[bin:vault]`),失败非零退出、不静默。
|
||||
- 串行保留:`ansible-playbook` 主执行(Phase 1/Phase 3 由其内部保证)、一次性 token/摘要打印。
|
||||
|
||||
### 10.6 不允许丢失的内容(硬约束)
|
||||
|
||||
逐一保留现有所有 tasks 及属性:`apt/package`、用户/目录/权限、env 文件、systemd unit 渲染、Caddy/Nginx、Docker/compose、服务启动、health check、`debug`、失败处理、`handlers`、`tags`、`become`、`when`、`notify`、`register`。**不得因并发删除/合并/跳过任何已有任务**;仅改变“何时等待”(`poll:0`+`async_status`),不改变“做什么”。
|
||||
|
||||
### 10.7 安全的全局提速(与 async 互补,不改 task 语义)
|
||||
|
||||
`ansible.cfg`(已存在)可叠加低风险项:
|
||||
|
||||
```ini
|
||||
[defaults]
|
||||
gathering = smart
|
||||
fact_caching = jsonfile
|
||||
fact_caching_connection = /tmp/ansible_facts
|
||||
[ssh_connection]
|
||||
pipelining = true
|
||||
```
|
||||
|
||||
并补足 TODO 关注点:APT/部署锁需**安全等待**(重试而非强删锁),保证二次幂等执行成功。`strategy: free` 单机收益有限、改变执行观感,**默认不启用**。
|
||||
|
||||
### 10.8 验收(等价性回归)
|
||||
|
||||
- [ ] 优化前后 `ansible-playbook --list-tasks` 任务集合一致(无丢失/合并)。
|
||||
- [ ] 每个 `async` 任务都有对应 `async_status` 收口,无悬挂 job。
|
||||
- [ ] Phase 1(apt/全局 npm/全局 pip/dpkg、LiteLLM venv 安装)与 Phase 3(daemon-reload/enable/start/health/摘要/清理)仍严格串行。
|
||||
- [ ] Phase 2 任务互不写同一文件、不抢同一锁;离线包存在时短路跳过。
|
||||
- [ ] 连续两次执行均成功、`changed=0` 幂等行为不变;Shell fork 池失败子任务非零退出且日志可见。
|
||||
|
||||
---
|
||||
94
docs/zh/RUNTIME_DELIVERY_PLAN.md
Normal file
94
docs/zh/RUNTIME_DELIVERY_PLAN.md
Normal file
@ -0,0 +1,94 @@
|
||||
[🇺🇸 English](../../README.md) | [🇨🇳 中文](../../README.zh.md)
|
||||
|
||||
# AI Workspace Runtime 交付规划
|
||||
|
||||
> 目标:把 `setup-ai-workspace-all-in-one.sh` 从“一组分散的基础设施 Playbook”收敛为一个**可直接使用的 AI Workspace Runtime 产品**——版本受控、运行模式可组合、对外仅暴露 Bridge、部署完成后输出一次性统一摘要。
|
||||
>
|
||||
> 本文是落地前的详细规划(设计 + 变更清单 + 提交/部署/验收方案)。实现阶段严格按本文执行,不扩大修改范围、不做大规模重构、优先复用现有实现。
|
||||
|
||||
- 状态:Linux 离线包链路与 macOS 本地校验链路已进入联调阶段;macOS 已越过多数 role 兼容性阻塞,当前重点是 LiteLLM 离线 runtime 接入、完整安装复跑和幂等验收
|
||||
- 影响仓库:`ai-workspace-infra/playbooks`、`ai-workspace-lab/xworkspace-console`、`ai-workspace-lab/xworkspace-core-skills`、`ai-workspace-services/qmd`、`ai-workspace-services/litellm`
|
||||
- 目标主机:`root@acp-bridge.onwalk.net`
|
||||
- 对外默认域名(唯一公开服务):`acp-bridge.onwalk.net`
|
||||
|
||||
## TODO
|
||||
|
||||
- [x] 等待并核对 `xworkspace-console` 的离线包 GitHub Actions 发布链路,确认 `publish-release` 完整结束且 release 产物上传成功。
|
||||
- [ ] 继续核对 `root@acp-bridge.onwalk.net` 的远程部署进度,确认 `setup-ai-workspace-all-in-one.sh` 最终完成并输出统一摘要。
|
||||
- [x] `setup-ai-workspace-all-in-one.sh` 在目标主机上优先使用离线安装包加速部署,减少在线拉取与安装耗时。
|
||||
- [x] 为 LiteLLM 新增 runtime wheelhouse release workflow,供 all-in-one 离线包消费。
|
||||
- [ ] 验证 `ai-workspace-services/litellm` 的 runtime release 实际生成成功,并确认 console 离线包能下载 matching `litellm-runtime-<distro>-<version>-<arch>.tar.gz`。
|
||||
- [ ] 验证 `setup-ai-workspace-all-in-one.sh` 幂等性:同一主机连续执行两次均成功,复用凭据、离线包缓存与已导入镜像,并安全等待部署/APT 锁。
|
||||
- [ ] 完成 macOS 本地最终验收核对:Portal、Bridge、OpenClaw、QMD、Hermes、PostgreSQL、Vault、LiteLLM 状态正常,`http://localhost:8181/mcp` 和 LiteLLM health 可达。
|
||||
- [ ] 完成远程 Linux 最终验收核对:Bridge 对外可达、其余服务默认仅本地监听、`acp-codex` / `opencode` / `gemini` / `hermes` / `qmd` / `litellm` 状态正常。
|
||||
- [ ] 记录最终提交哈希、GitHub Actions run、release tag 与远端验证结果,回填到本计划的交付结果部分。
|
||||
|
||||
---
|
||||
|
||||
## 6. 仓库与提交计划
|
||||
|
||||
| 仓库 | 主要改动 | Commit message(建议) | 推送目标 |
|
||||
|---|---|---|---|
|
||||
| `playbooks` | 角色拆分、版本固定、Bridge 域名、运行模式守卫、PG compose、QMD/LiteLLM 源、聚合链去重、本规划文档 | `feat: deliver versioned AI Workspace Runtime (role split, run-mode matrix, bridge domain)` | `ai-workspace-infra/playbooks` |
|
||||
| `xworkspace-console` | `setup-ai-workspace-all-in-one.sh` 统一摘要、pull 源对齐、console 默认不公开 | `feat: unified one-time deploy summary + bridge-only public surface` | `ai-workspace-lab/xworkspace-console` |
|
||||
| `xworkspace-core-skills` | (按需)技能种子/版本对齐 | `chore: align skills seed for workspace runtime` | `ai-workspace-lab/xworkspace-core-skills` |
|
||||
|
||||
> 每个仓库**独立提交**,分别记录 Commit Hash 写入最终交付说明。
|
||||
|
||||
### 6.1 当前实现进度(2026-06-22)
|
||||
|
||||
| 仓库 | 已完成进展 | 已知待处理 |
|
||||
|---|---|---|
|
||||
| `ai-workspace-infra/playbooks` | OpenClaw doctor/restart 已拆分;QMD 已补 macOS LaunchAgent;OpenClaw `acpx` 兼容性 assert 已修;LiteLLM 已切 Python 3.13 venv、安装探测和 `.install-spec` 跳过重复安装 | 需要完整 macOS 复跑确认 `qmd :8181/mcp`、OpenClaw registry、LiteLLM health;需要确认 all-in-one 的 macOS patch 与 playbooks main 不再互相覆盖 |
|
||||
| `ai-workspace-lab/xworkspace-console` | all-in-one 离线包链路已能消费 console/bridge/qmd/litellm runtime release;macOS 调试案例持续记录在 `docs/case/macos_compatibility_tests.md` | `uninstall purge` 仍需打印删除路径;需要清理离线包生成目录等非源码正式目录;需要确认 `install.svc.plus/ai-workspace` 发布入口同步到最新 main |
|
||||
| `ai-workspace-services/qmd` | all-in-one 离线包脚本按 `qmd-runtime-linux-${ARCH}.tar.gz` 消费 release;playbooks 已补 QMD macOS LaunchAgent | 需要确认 latest runtime release 与 offline package 拉取路径持续可用;macOS 需实测 MCP endpoint |
|
||||
| `ai-workspace-services/litellm` | 新增 `.github/workflows/offline-package-litellm-runtime.yaml`,产出 `litellm-runtime-<distro>-<version>-<arch>.tar.gz`、wheelhouse、可选 portable Python、`metadata/runtime.env` | 需要触发 GitHub Actions 并确认 release asset 与 `SHA256SUMS`;需要确认 console 离线包使用 `latest-runtime` 能解析到该 release |
|
||||
| `ai-workspace-lab/xworkspace-core-skills` | all-in-one 离线包仍按 core-skills repo/ref 打包 | 当前未发现新的 macOS 阻塞;最终验收仍需确认技能注入与 OpenClaw/QMD 可见 |
|
||||
|
||||
### 6.2 近期关键提交
|
||||
|
||||
| 仓库 | Commit | 说明 |
|
||||
|---|---|---|
|
||||
| `ai-workspace-infra/playbooks` | `09a39e6` | `perf(openclaw): avoid unnecessary doctor repairs` |
|
||||
| `ai-workspace-infra/playbooks` | `f01e0bb` | `fix(qmd): provision macOS LaunchAgent` |
|
||||
| `ai-workspace-infra/playbooks` | `c11f51b` | `fix(openclaw): allow version-matched acpx plugin` |
|
||||
| `ai-workspace-infra/playbooks` | `71ebe64` | `fix(litellm): isolate runtime in Python 3.13 venv` |
|
||||
| `ai-workspace-infra/playbooks` | `6a2f05f` | `fix(litellm): skip redundant dependency installs` |
|
||||
| `ai-workspace-services/litellm` | `51cde5e32` | `ci: add offline litellm runtime workflow` |
|
||||
|
||||
### 6.3 当前最需要收口的问题
|
||||
|
||||
1. `LiteLLM`:在线 `pip install litellm[proxy]` 仍可能因大 wheel 下载中断失败;应以 runtime wheelhouse release 作为 all-in-one 默认加速路径,并保留在线路径为 fallback。
|
||||
2. `install.svc.plus/ai-workspace`:需要确认公开短链实际拉到的是 `xworkspace-console@main` 最新脚本,否则 macOS 仍可能运行旧 bootstrap。
|
||||
3. `uninstall purge`:需要输出将删除/已删除/不存在的路径,覆盖 macOS 与 Linux 的 token、Vault/OpenClaw 状态、临时部署目录、系统配置目录。
|
||||
4. 工作区清理:需要清理 `ai-workspace-all-in-one-offline-*` 等生成目录,避免离线包产物混入源码根目录。
|
||||
5. 最终验收:需要在 macOS 上做一次干净安装和一次重复安装,记录各服务端口、LaunchAgent/systemd 状态、health endpoint 与 changed 统计。
|
||||
|
||||
---
|
||||
|
||||
## 8. 风险与回退
|
||||
|
||||
| 风险 | 缓解 / 回退 |
|
||||
|---|---|
|
||||
| 沙箱无法直连 GitHub/目标主机 | 本地完成代码+提交;push 与远程部署由有网络的环境执行 |
|
||||
| PG 切 compose 影响既有数据 | 保留 `postgresql_deploy_mode=native` 回退路径 |
|
||||
| 角色拆分回归 | `setup-xfce-xrdp.yaml` 组合两角色,行为等价;保留旧角色直至引用切换验证通过 |
|
||||
| 版本固定导致拉取失败 | 版本变量集中、可单点覆盖(env / `-e`) |
|
||||
|
||||
---
|
||||
|
||||
## 9. 实现顺序(落地次序)
|
||||
|
||||
1. 本规划文档入库(docs/)。
|
||||
2. 角色拆分 + `setup-xfce-xrdp.yaml` 组合。
|
||||
3. 版本固定(OpenClaw/Vault/Hermes/QMD/LiteLLM/Node/Playwright/Chrome)。
|
||||
4. Bridge 域名参数透传(`XWORKMATE_BRIDGE_DOMAIN`,自定义,不改 role 默认)。
|
||||
5. 运行模式守卫 + PG compose 默认。
|
||||
6. 聚合链去重(Hermes)+ console 默认不公开。
|
||||
7. `setup-ai-workspace-all-in-one.sh` 统一摘要。
|
||||
8. 三仓库分别提交,记录 Commit Hash。
|
||||
9. 推送 + 远程部署 + 按 §7.2 验证。
|
||||
10. 并发优化落地(见 §10),最后做 §10.8 等价性回归。
|
||||
|
||||
---
|
||||
|
||||
115
docs/zh/RUNTIME_FEATURES.md
Normal file
115
docs/zh/RUNTIME_FEATURES.md
Normal file
@ -0,0 +1,115 @@
|
||||
[🇺🇸 English](../../README.md) | [🇨🇳 中文](../../README.zh.md)
|
||||
|
||||
## 1. 交付目标与验收标准
|
||||
|
||||
### 1.1 总体目标
|
||||
|
||||
1. 在不扩大修改范围、不做大规模重构的前提下,完成必要调整并分别提交三个仓库。
|
||||
2. 使用 `scripts/setup-ai-workspace-all-in-one.sh` 将 AI Workspace 部署到 `root@acp-bridge.onwalk.net`。
|
||||
3. `xworkmate bridge` 统一使用 `acp-bridge.onwalk.net` 作为对外域名,且是**唯一默认公开**的服务。
|
||||
4. 交付一个完整的 AI Workspace Runtime:`xfce_desktop` + NodeJS + Playwright 全部版本受控。
|
||||
5. 运行模式 `docker / k3s / systemd` 可选、可自由组合(`docker` 与 `k3s` 互斥,`docker + systemd` 可组合)。
|
||||
6. 角色拆分:`roles/vhosts/xfce_xrdp_minimal` → `roles/vhosts/xfce_desktop_minimal_runtime` + `roles/vhosts/remote_desktop_xrdp_server`。
|
||||
7. 部署脚本结束后输出一份**面向最终用户**的统一部署摘要,重要认证信息**仅显示一次**。
|
||||
|
||||
### 1.2 验收标准(Definition of Done)
|
||||
|
||||
- [ ] 三个仓库完成代码提交,提供各自 Commit Hash。
|
||||
- [ ] `setup-ai-workspace-all-in-one.sh` 在目标主机以远程 exec 模式执行成功(无 rsync,仓库由远程主机自 GitHub pull)。
|
||||
- [ ] Bridge 对外使用 `acp-bridge.onwalk.net`,其余服务默认不公开。
|
||||
- [ ] 脚本结束输出统一部署摘要:访问入口、一次性凭据、各服务运行状态、可用 Agent CLI。
|
||||
- [ ] `xfce_desktop / NodeJS / Playwright` 版本均可在单一来源(role defaults)查到并被固定。
|
||||
- [ ] 同一主机连续执行两次安装均成功,第二次执行不生成新凭据、不重复下载同一 release 包,并等待而非破坏并发 APT/dpkg 操作。
|
||||
|
||||
---
|
||||
|
||||
## 5. 详细变更清单
|
||||
|
||||
### 5.1 角色拆分:`xfce_xrdp_minimal` → 两个角色
|
||||
|
||||
按职责拆分,**逐文件映射**,行为不变;`setup-xfce-xrdp.yaml` 改为顺序组合两个新角色。
|
||||
|
||||
**`roles/vhosts/xfce_desktop_minimal_runtime`(桌面运行时)**
|
||||
|
||||
| 来源 | 去向 | 说明 |
|
||||
|---|---|---|
|
||||
| `tasks/install.yml`(仅桌面包:`xfce4-session/xfwm4/xfdesktop4/xfce4-panel/xfce4-terminal/dbus-x11/fonts-noto-cjk/xserver-xorg-core`) | `tasks/install.yml` | 移除 `xorgxrdp/xrdp` 包与 xrdp 服务启动 |
|
||||
| `tasks/browser.yml`(Google Chrome 固定版) | `tasks/browser.yml` | 原样保留 |
|
||||
| 新增 `tasks/runtime.yml` | NodeJS + Playwright(引用既有 `nodejs` / `ai_agent_runtime` 的固定版本变量) | 版本受控单一来源 |
|
||||
| `defaults/main.yml`(desktop/chrome/node/playwright 版本变量) | `defaults/main.yml` | 见 §5.2 版本表 |
|
||||
|
||||
**`roles/vhosts/remote_desktop_xrdp_server`(远程桌面 XRDP 服务)**
|
||||
|
||||
| 来源 | 去向 | 说明 |
|
||||
|---|---|---|
|
||||
| `tasks/install.yml`(`xorgxrdp/xrdp`、ssl-cert 组、daemon-reload、enable/start、unit 校验/fail) | `tasks/install.yml` | XRDP 服务层 |
|
||||
| `tasks/config.yml`(用户/口令 RDP 认证、`.xsession`、xfconf 目录) | `tasks/config.yml` | RDP 会话粘合 |
|
||||
| `handlers/main.yml`(Restart xrdp / sesman) | `handlers/main.yml` | 原样保留 |
|
||||
| `vars/main.yml`(`xfce_xrdp_services` 等)+ `xfce_rdp_port/xfce_enable_ufw` | `defaults`/`vars` | 端口/ufw |
|
||||
|
||||
**组合点 `setup-xfce-xrdp.yaml`:**
|
||||
|
||||
```yaml
|
||||
- name: Deploy XFCE desktop + optional XRDP (Optional)
|
||||
hosts: all
|
||||
become: true
|
||||
vars:
|
||||
xworkspace_console_enable_xrdp: false
|
||||
tasks:
|
||||
- include_role: { name: roles/vhosts/xfce_desktop_minimal_runtime }
|
||||
- include_role: { name: roles/vhosts/remote_desktop_xrdp_server }
|
||||
when: xworkspace_console_enable_xrdp | bool
|
||||
```
|
||||
|
||||
> 旧角色 `roles/vhosts/xfce_xrdp_minimal`:拆分完成且引用全部切换后删除(当前唯一引用即 `setup-xfce-xrdp.yaml`)。
|
||||
|
||||
### 5.2 版本固定表(单一来源)
|
||||
|
||||
| 组件 | 变量 | 当前 | 目标 | 文件 |
|
||||
|---|---|---|---|---|
|
||||
| OpenClaw | `gateway_openclaw_required_version` | `2026.5.28` | `2026.6.1` | `roles/vhosts/gateway_openclaw/defaults/main.yml:23` |
|
||||
| Vault | `vault_version`(env 默认值) | `1.20.4` | `1.21.4` | `roles/vhosts/vault/vars/main.yml:6` |
|
||||
| Hermes | `acp_hermes_version`(新增) | 无 | `0.15` | `roles/vhosts/acp_server_hermes/defaults/main.yml` |
|
||||
| QMD | `qmd_version` / `qmd_source_repo`(新增) | 无 | 取自 `ai-workspace-services/qmd` | `roles/vhosts/qmd/defaults/main.yml` |
|
||||
| LiteLLM | `litellm_version` / `litellm_source_repo`(新增) | 无 | 取自 `ai-workspace-services/litellm` | `roles/vhosts/litellm/defaults/main.yml` |
|
||||
| NodeJS | `nodejs_version` / `ai_agent_runtime_nodejs_version` | `22.x` / `24.x` | 固定明确小版本 | `roles/vhosts/nodejs/defaults` + `roles/ai_agent_runtime/defaults` |
|
||||
| Playwright | `ai_agent_runtime_playwright_version`(新增/固定) | 无显式 | 固定 | `roles/ai_agent_runtime/defaults/main.yml` |
|
||||
| Google Chrome | `xfce_google_chrome_version` | `148.0.7778.167-1` | 保持固定 | 运行时角色 `defaults/main.yml` |
|
||||
| XFCE | `xfce_packages` | 列表 | 保持(apt 发行版固定) | 运行时角色 `defaults/main.yml` |
|
||||
|
||||
### 5.3 Bridge 对外域名(自定义参数,非硬编码默认)
|
||||
|
||||
- **`acp-bridge.onwalk.net` 是 host-specific 的自定义参数**,经 `XWORKMATE_BRIDGE_DOMAIN` 在部署时传入,**不写死为 role 默认值**。
|
||||
- 实现要点(最小改动):确保 `XWORKMATE_BRIDGE_DOMAIN` 经 bootstrap 脚本 → playbook → `roles/vhosts/xworkmate_bridge` 正确透传。现有 env 覆盖链已支持:`XWORKMATE_BRIDGE_DOMAIN` → `ai_workspace_public_domain`(`SERVER_DOMAIN/ACP_BRIDGE_DOMAIN/BRIDGE_DOMAIN`)。
|
||||
- `roles/vhosts/xworkmate_bridge/defaults/main.yml:47` 的中性回退默认值(`xworkmate-bridge.svc.plus`)**保持不变**——仅作为未显式传参时的兜底;目标主机通过 `XWORKMATE_BRIDGE_DOMAIN=acp-bridge.onwalk.net` 指定真实域名。
|
||||
- 验收只要求“Bridge 使用指定域名”,由自定义参数满足,无需改动 role 默认。
|
||||
|
||||
### 5.4 部署脚本统一摘要(`setup-ai-workspace-all-in-one.sh`)
|
||||
|
||||
在现有脚本(console 仓库,约 39KB)末尾**追加**一段摘要渲染(探测主机实时状态,不硬编码),结构如下:
|
||||
|
||||
```
|
||||
================ AI Workspace 部署摘要 ================
|
||||
[访问入口]
|
||||
Workspace Portal (Console) : http://127.0.0.1:17000 (本地)
|
||||
XWorkMate Bridge : https://acp-bridge.onwalk.net ← 唯一公开
|
||||
[一次性凭据](仅显示一次)
|
||||
AI_WORKSPACE_AUTH_TOKEN : ********
|
||||
Vault root token : ********
|
||||
[服务状态]
|
||||
Portal / Bridge / OpenClaw / QMD / Hermes / PostgreSQL / Vault / LiteLLM : active/inactive
|
||||
[Agent CLI]
|
||||
opencode / gemini / codex / claude : <version | 缺失>
|
||||
======================================================
|
||||
```
|
||||
|
||||
- 状态探测复用 console 的 `generate-status.py` 逻辑与各 role 的 `validate.yml` 健康检查(`systemctl is-active` + `curl` 健康端点)。
|
||||
- 凭据“仅显示一次”:摘要从已落盘的 token 文件读取展示后,提示用户保存;脚本不重复打印。
|
||||
|
||||
### 5.5 all-in-one 聚合链调整
|
||||
|
||||
- 顶部新增 §4.3 运行模式 `assert` 守卫 play。
|
||||
- 移除步骤 10 独立 `deploy_agent_hermes.yml` 导入(去重,见 §4.2)。
|
||||
- 其余导入顺序保持不变。
|
||||
|
||||
---
|
||||
185
docs/zh/RUNTIME_SETUP.md
Normal file
185
docs/zh/RUNTIME_SETUP.md
Normal file
@ -0,0 +1,185 @@
|
||||
[🇺🇸 English](../../README.md) | [🇨🇳 中文](../../README.zh.md)
|
||||
|
||||
## 2. 部署执行模型(远程 exec / GitHub pull)
|
||||
|
||||
- `scripts/setup-ai-workspace-all-in-one.sh` 运行**在远程主机上**,全程 remote exec 模式。
|
||||
- **不使用 rsync**;所需仓库由远程主机直接从 GitHub `pull`:
|
||||
- Playbooks:`https://github.com/ai-workspace-infra/playbooks.git`
|
||||
- Core Skills:`https://github.com/ai-workspace-lab/xworkspace-core-skills.git`
|
||||
- Console(脚本自身所在仓库):`https://github.com/ai-workspace-lab/xworkspace-console.git`
|
||||
- QMD:`https://github.com/ai-workspace-services/qmd.git`
|
||||
- LiteLLM:`https://github.com/ai-workspace-services/litellm.git`
|
||||
- 含义:**本地提交必须推送到上述 GitHub 仓库后,远程部署才能拉到改动**。
|
||||
|
||||
> ⚠️ 注意仓库地址不一致:playbooks 本地 `origin` 当前为 `git@github.com:x-evor/playbooks.git`,而部署权威源是 `ai-workspace-infra/playbooks`。实现阶段需将脚本中的 pull 源对齐到 `ai-workspace-infra/playbooks`,并把提交推送到该仓库。
|
||||
|
||||
### 2.1 环境变量接口契约(权威)
|
||||
|
||||
bootstrap 入口固定为 console 仓库的原始脚本,所有暴露/安全/可选桌面行为均通过 `bash -` 前的环境变量控制。
|
||||
|
||||
**标准安装**(默认安全本地工作区,仅需一个统一 token):
|
||||
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | bash -
|
||||
```
|
||||
|
||||
**全部参数(默认值与推荐用法):**
|
||||
|
||||
| 变量 | 默认 | 推荐用法 |
|
||||
|---|---|---|
|
||||
| `TOKEN` | 生成或复用 | 为 Bridge / Portal / LiteLLM / OpenClaw / Vault 设置**统一**认证 token |
|
||||
| `AI_WORKSPACE_SECURITY_LEVEL` | `standard` | 公网/半公网主机使用 `strict` |
|
||||
| `XWORKMATE_BRIDGE_PUBLIC_ACCESS` | `true` | Bridge 为默认唯一公开服务;如需关闭对外访问可显式设 `false` |
|
||||
| `XWORKMATE_BRIDGE_DOMAIN` | host-specific | 设置 Bridge 公网域名,例如 `acp-bridge.onwalk.net` |
|
||||
| `XWORKSPACE_CONSOLE_PUBLIC_ACCESS` | `false` | 仅当 Portal 必须公开时开启;本地优先更安全 |
|
||||
| `XWORKSPACE_CONSOLE_ENABLE_XRDP` | `false` | 仅当需要远程桌面访问时开启 |
|
||||
| `GATEWAY_OPENCLAW_PUBLIC_ACCESS` | `false` | 除非 OpenClaw 必须直接暴露,保持 false |
|
||||
| `VAULT_PUBLIC_ACCESS` | `false` | 常规部署保持 false |
|
||||
| `LITELLM_API_CADDY_STRICT_WHITELIST` | `false` | strict 且 LiteLLM 经 Caddy 暴露时开启 |
|
||||
|
||||
**进阶安装示例:**
|
||||
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | \
|
||||
AI_WORKSPACE_SECURITY_LEVEL=strict \
|
||||
XWORKSPACE_CONSOLE_ENABLE_XRDP=true \
|
||||
XWORKSPACE_CONSOLE_PUBLIC_ACCESS=true \
|
||||
XWORKMATE_BRIDGE_PUBLIC_ACCESS=true \
|
||||
GATEWAY_OPENCLAW_PUBLIC_ACCESS=false \
|
||||
VAULT_PUBLIC_ACCESS=false \
|
||||
LITELLM_API_CADDY_STRICT_WHITELIST=true \
|
||||
TOKEN="your-unified-auth-token" \
|
||||
bash -
|
||||
```
|
||||
|
||||
**目标主机(ACP Bridge)示例:**
|
||||
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | \
|
||||
XWORKMATE_BRIDGE_DOMAIN=acp-bridge.onwalk.net \
|
||||
XWORKMATE_BRIDGE_PUBLIC_ACCESS=true \
|
||||
AI_WORKSPACE_SECURITY_LEVEL=strict \
|
||||
bash -
|
||||
```
|
||||
|
||||
> 关键校准:`XWORKMATE_BRIDGE_PUBLIC_ACCESS` 默认 **`true`**——Bridge 是**默认唯一公开**的服务(域名经 `XWORKMATE_BRIDGE_DOMAIN` 自定义传入);其余服务(Console/OpenClaw/Vault/QMD/Hermes/PG/LiteLLM)默认 `false`,保持 `127.0.0.1` 本地监听。如需关闭 Bridge 对外访问,显式设 `XWORKMATE_BRIDGE_PUBLIC_ACCESS=false`。`TOKEN` 输出务必私密保存——不得拷入前端源码或提交到 Git。
|
||||
|
||||
### 2.2 预期最终输出(部署摘要)
|
||||
|
||||
部署成功后,脚本将**一次性**打印部署域名与 token,随后报告各服务运行状态:
|
||||
|
||||
- AI Workspace 域名与 token(仅显示一次)
|
||||
- OpenClaw
|
||||
- QMD
|
||||
- PostgreSQL
|
||||
- Vault
|
||||
- Workspace Portal / Console
|
||||
- LiteLLM
|
||||
- Hermes
|
||||
- Agent CLI:opencode、gemini、codex、claude
|
||||
|
||||
### 2.3 本地 macOS 校验模式
|
||||
|
||||
在 macOS 上脚本默认进入**本地校验模式**,在 `http://127.0.0.1:17000` 启动 Portal。若因端口占用校验失败,先停止已有本地服务或在干净会话中重试。
|
||||
|
||||
---
|
||||
|
||||
## 7. 部署与验证
|
||||
|
||||
### 7.1 部署命令(在目标主机或对其有网络/SSH 访问的环境执行)
|
||||
|
||||
```bash
|
||||
# 远程 exec:脚本在主机上自 GitHub pull 仓库并运行 ansible 到 localhost
|
||||
# 采用 §2.1 权威环境变量契约(目标主机示例)
|
||||
ssh root@acp-bridge.onwalk.net \
|
||||
'curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | \
|
||||
XWORKMATE_BRIDGE_DOMAIN=acp-bridge.onwalk.net \
|
||||
XWORKMATE_BRIDGE_PUBLIC_ACCESS=true \
|
||||
AI_WORKSPACE_SECURITY_LEVEL=strict \
|
||||
bash -'
|
||||
```
|
||||
|
||||
### 7.2 验证清单
|
||||
|
||||
- [ ] 脚本结束输出统一摘要,且 Bridge 显示 `https://acp-bridge.onwalk.net`。
|
||||
- [ ] `curl -I https://acp-bridge.onwalk.net` 可达;其余服务端口仅 `127.0.0.1` 监听。
|
||||
- [ ] `systemctl --user is-active` 各服务为 `active`。
|
||||
- [ ] `opencode/gemini/codex/claude --version` 均可执行。
|
||||
- [ ] 凭据仅在摘要中出现一次。
|
||||
|
||||
---
|
||||
|
||||
## 附录 A. AI Workspace All-in-One Setup(bootstrap 使用指南)
|
||||
|
||||
> 面向最终用户的官方安装指南,已合并入本规划作为单一权威来源。
|
||||
> 本附录相对上游 README 有两处校准:① `XWORKMATE_BRIDGE_PUBLIC_ACCESS` 默认 **`true`**(Bridge 为默认唯一公开服务);② `acp-bridge.onwalk.net` 为 **host-specific 自定义参数**,经 `XWORKMATE_BRIDGE_DOMAIN` 传入。
|
||||
|
||||
这是从 `xworkspace-console` 仓库安装 AI Workspace Runtime 的推荐 bootstrap 入口。脚本以该仓库为公开入口,随后通过 AI Workspace playbooks 与各组件仓库准备运行时服务。
|
||||
|
||||
### A.1 标准安装
|
||||
|
||||
适用于默认安全的本地工作区,仅需一个生成或既有的统一 token:
|
||||
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | bash -
|
||||
```
|
||||
|
||||
### A.2 进阶安装
|
||||
|
||||
在 `bash -` 前用环境变量自定义暴露面、安全级别与可选桌面功能:
|
||||
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | \
|
||||
AI_WORKSPACE_SECURITY_LEVEL=strict \
|
||||
XWORKSPACE_CONSOLE_ENABLE_XRDP=true \
|
||||
XWORKSPACE_CONSOLE_PUBLIC_ACCESS=true \
|
||||
XWORKMATE_BRIDGE_PUBLIC_ACCESS=true \
|
||||
GATEWAY_OPENCLAW_PUBLIC_ACCESS=false \
|
||||
VAULT_PUBLIC_ACCESS=false \
|
||||
LITELLM_API_CADDY_STRICT_WHITELIST=true \
|
||||
TOKEN="your-unified-auth-token" \
|
||||
bash -
|
||||
```
|
||||
|
||||
### A.3 推荐参数
|
||||
|
||||
| 变量 | 默认 | 推荐用法 |
|
||||
|---|---|---|
|
||||
| `TOKEN` | 生成或复用 | 为 Bridge、Portal、LiteLLM、OpenClaw、Vault 设置一个统一认证 token |
|
||||
| `AI_WORKSPACE_SECURITY_LEVEL` | `standard` | 公网/半公网主机使用 `strict` |
|
||||
| `XWORKMATE_BRIDGE_PUBLIC_ACCESS` | `true` | Bridge 为默认唯一公开服务;需关闭对外访问时显式设 `false` |
|
||||
| `XWORKMATE_BRIDGE_DOMAIN` | host-specific(自定义) | Bridge 公网域名,例如 `acp-bridge.onwalk.net` |
|
||||
| `XWORKSPACE_CONSOLE_PUBLIC_ACCESS` | `false` | 仅当 Portal 必须公开时开启;本地优先更安全 |
|
||||
| `GATEWAY_OPENCLAW_PUBLIC_ACCESS` | `false` | 除非 OpenClaw 必须直接暴露,保持 false |
|
||||
| `VAULT_PUBLIC_ACCESS` | `false` | 常规部署保持 false |
|
||||
| `LITELLM_API_CADDY_STRICT_WHITELIST` | `false` | strict 部署且 LiteLLM 经 Caddy 暴露时开启 |
|
||||
| `XWORKSPACE_CONSOLE_ENABLE_XRDP` | `false` | 仅当需要远程桌面访问时开启 |
|
||||
|
||||
### A.4 目标主机示例(当前 ACP Bridge 主机)
|
||||
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | \
|
||||
XWORKMATE_BRIDGE_DOMAIN=acp-bridge.onwalk.net \
|
||||
XWORKMATE_BRIDGE_PUBLIC_ACCESS=true \
|
||||
AI_WORKSPACE_SECURITY_LEVEL=strict \
|
||||
bash -
|
||||
```
|
||||
|
||||
### A.5 预期最终输出
|
||||
|
||||
部署成功后,脚本**一次性**打印部署域名与 token,随后报告以下服务状态:
|
||||
|
||||
- AI Workspace 域名与 token
|
||||
- OpenClaw
|
||||
- QMD
|
||||
- PostgreSQL
|
||||
- Vault
|
||||
- Workspace Portal / Console
|
||||
- LiteLLM
|
||||
- Agent CLI:opencode、gemini、codex、claude
|
||||
|
||||
> Token 输出务必私密保存,不得拷入前端源码或提交到 Git。
|
||||
|
||||
### A.6 本地 macOS 校验
|
||||
|
||||
在 macOS 上脚本默认进入本地校验模式,在 `http://127.0.0.1:17000` 启动 Portal。若因端口占用导致校验失败,先停止已有本地服务或在干净会话中重试。
|
||||
84
docs/zh/SETUP_AI_WORKSPACE_ALL_IN_ONE.md
Normal file
84
docs/zh/SETUP_AI_WORKSPACE_ALL_IN_ONE.md
Normal file
@ -0,0 +1,84 @@
|
||||
[🇺🇸 English](../../README.md) | [🇨🇳 中文](../../README.zh.md)
|
||||
|
||||
# AI Workspace 一站式安装
|
||||
|
||||
这是从 `xworkspace-console` 仓库安装 AI Workspace Runtime 的推荐启动程序入口。
|
||||
|
||||
启动脚本以本仓库为公开入口点,随后通过 AI Workspace playbooks 和组件仓库准备运行时服务。
|
||||
|
||||
## 1. 标准安装
|
||||
|
||||
当需要默认安全的本地工作区且仅需要生成或现有的统一 token 时使用此方式。
|
||||
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | bash -
|
||||
```
|
||||
|
||||
## 2. 进阶安装
|
||||
|
||||
在 `bash -` 之前使用环境变量来自定义公开访问、安全级别和可选的桌面功能。
|
||||
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | \
|
||||
AI_WORKSPACE_SECURITY_LEVEL=strict \
|
||||
XWORKSPACE_CONSOLE_ENABLE_XRDP=true \
|
||||
XWORKSPACE_CONSOLE_PUBLIC_ACCESS=true \
|
||||
XWORKMATE_BRIDGE_PUBLIC_ACCESS=true \
|
||||
GATEWAY_OPENCLAW_PUBLIC_ACCESS=false \
|
||||
VAULT_PUBLIC_ACCESS=false \
|
||||
LITELLM_API_CADDY_STRICT_WHITELIST=true \
|
||||
TOKEN="your-unified-auth-token" \
|
||||
bash -
|
||||
```
|
||||
|
||||
## 3. 推荐参数
|
||||
|
||||
| 变量 | 默认值 | 推荐用法 |
|
||||
| --- | --- | --- |
|
||||
| `TOKEN` | 生成或复用 | 为 Bridge、Portal、LiteLLM、OpenClaw 和 Vault 设置统一认证 token。 |
|
||||
| `AI_WORKSPACE_SECURITY_LEVEL` | standard | 公网或半公网主机使用 `strict`。 |
|
||||
| `XWORKMATE_BRIDGE_PUBLIC_ACCESS` | false | 仅当 Bridge 域名需要从互联网访问时启用。 |
|
||||
| `XWORKSPACE_CONSOLE_PUBLIC_ACCESS` | false | 仅当 Portal 必须公开时启用。仅限本地访问更安全。 |
|
||||
| `GATEWAY_OPENCLAW_PUBLIC_ACCESS` | false | 除非 OpenClaw 必须直接暴露,否则保持为 false。 |
|
||||
| `VAULT_PUBLIC_ACCESS` | false | 常规部署保持为 false。 |
|
||||
| `LITELLM_API_CADDY_STRICT_WHITELIST` | false | strict 部署且 LiteLLM 经 Caddy 暴露时启用。 |
|
||||
| `XWORKSPACE_CONSOLE_ENABLE_XRDP` | false | 仅当需要远程桌面访问时启用。 |
|
||||
| `XWORKMATE_BRIDGE_DOMAIN` | 特定于主机 | 设置公开的 Bridge 域名,例如 `acp-bridge.onwalk.net`。 |
|
||||
| `AI_WORKSPACE_OFFLINE_PACKAGE` | 无 | 使用预下载的离线包进行安装(例如 `/path/to/offline.tar.gz`)。 |
|
||||
|
||||
## 4. 目标主机示例
|
||||
|
||||
对于当前 ACP Bridge 主机:
|
||||
|
||||
```bash
|
||||
curl -sfL https://raw.githubusercontent.com/ai-workspace-lab/xworkspace-console/main/scripts/setup-ai-workspace-all-in-one.sh | \
|
||||
XWORKMATE_BRIDGE_DOMAIN=acp-bridge.onwalk.net \
|
||||
XWORKMATE_BRIDGE_PUBLIC_ACCESS=true \
|
||||
AI_WORKSPACE_SECURITY_LEVEL=strict \
|
||||
bash -
|
||||
```
|
||||
|
||||
## 5. 预期最终输出
|
||||
|
||||
部署成功后,脚本会一次性打印部署的域名与 token,然后报告以下服务状态:
|
||||
|
||||
- AI Workspace 域名与 token
|
||||
- OpenClaw
|
||||
- QMD
|
||||
- PostgreSQL
|
||||
- Vault
|
||||
- Workspace Portal / Console
|
||||
- LiteLLM
|
||||
- Agent CLI:`opencode`、`gemini`、`codex`、`claude`
|
||||
|
||||
请妥善保管 token。它不应该被复制到前端源代码或提交到 Git 中。
|
||||
|
||||
## 6. 本地 macOS 验证
|
||||
|
||||
在 macOS 上,脚本默认进入本地验证模式并在以下地址启动 Portal:
|
||||
|
||||
```text
|
||||
http://127.0.0.1:17000
|
||||
```
|
||||
|
||||
如果因为端口已被占用导致验证失败,请先停止现有的本地服务或在干净的会话中重试。
|
||||
@ -1,3 +1,5 @@
|
||||
[🇺🇸 English](../../README.md) | [🇨🇳 中文](../../README.zh.md)
|
||||
|
||||
# 版本兼容性与组件矩阵 (Version Matrix)
|
||||
|
||||
此文档列出了 AI Workspace Lab 控制台 (XWorkspace Console) 及其关联组件的推荐运行环境与组件版本。
|
||||
@ -1,3 +1,5 @@
|
||||
[🇺🇸 English](../../../README.md) | [🇨🇳 中文](../../../README.zh.md)
|
||||
|
||||
# 组合测试用例
|
||||
|
||||
本文档定义了 `setup-ai-workspace-all-in-one.sh` 的端到端组合测试矩阵。
|
||||
@ -1,3 +1,5 @@
|
||||
[🇺🇸 English](../../../README.md) | [🇨🇳 中文](../../../README.zh.md)
|
||||
|
||||
# macOS 兼容性部署测试用例
|
||||
|
||||
本文档记录了在 macOS (Darwin) 环境下进行 `setup-ai-workspace-all-in-one.sh` 全自动部署时遇到的跨平台兼容性问题及修复方案。
|
||||
@ -1,3 +1,5 @@
|
||||
[🇺🇸 English](../../../README.md) | [🇨🇳 中文](../../../README.zh.md)
|
||||
|
||||
# 测试提示词模板
|
||||
|
||||
本文档提供了用于测试 `setup-ai-workspace-all-in-one.sh` 的标准化提示词模板,可直接复制粘贴到终端执行。
|
||||
508
docs/zh/designs/2026-06-07-ai-workspace-desktop-design.md
Normal file
508
docs/zh/designs/2026-06-07-ai-workspace-desktop-design.md
Normal file
@ -0,0 +1,508 @@
|
||||
[🇺🇸 English](../../../README.md) | [🇨🇳 中文](../../../README.zh.md)
|
||||
|
||||
# AI Workspace 桌面设计
|
||||
|
||||
日期:2026-06-07
|
||||
项目:`xworkspace-console`
|
||||
状态:实施对齐草案
|
||||
|
||||
## 1. 概述
|
||||
|
||||
本文档定义了基于 XFCE 构建的 AI Workspace 桌面环境的目标设计,其中 `xworkspace-console` 作为合并的实现仓库。
|
||||
|
||||
我们的目标不是构建一个新的桌面环境。目标是通过组合以下内容,组装一个极简、可靠的 AI 工作区 shell:
|
||||
|
||||
- XFCE 作为桌面基础层
|
||||
- XFCE 面板和兼容 GTK/XDG 的配置用于桌面界面
|
||||
- `Plank` 作为首选的自动隐藏停靠栏 (Dock)
|
||||
- `systemd --user` 用于每个用户的服务编排
|
||||
- `Go` 用于本地状态收集 API
|
||||
- `React + Vite + TypeScript` 用于仪表板 UI
|
||||
- `ttyd` 用于嵌入式终端界面
|
||||
- `Chrome` 或 `Chromium` 应用程序模式作为主要操作员入口点
|
||||
|
||||
预期的视觉方向是一个低干扰的工作区,感觉更接近 NomadBSD、ChromeOS 和简化的 macOS Dock 设置,而不是传统的 Linux 桌面。
|
||||
|
||||
## 2. 产品目标
|
||||
|
||||
桌面启动后应进入一个专注的 AI 操作环境,其中基于浏览器的控制平面是主要的用户体验。
|
||||
|
||||
主要成果:
|
||||
|
||||
- 用户登录 XFCE 后进入一个极简工作区,而不是经典的 Linux 桌面
|
||||
- 顶部状态栏仅显示基本的运行时状态
|
||||
- 底部停靠栏提供对固定操作员工具集的快速访问
|
||||
- 浏览器直接打开 XWorkspace 控制平面
|
||||
- OpenClaw、Bridge、LiteLLM、Vault 和 console 服务通过 systemd 进行管理和检查
|
||||
- 控制平面可显示本地服务运行状况、基本主机指标和终端访问
|
||||
|
||||
## 3. 非目标
|
||||
|
||||
第一阶段明确避免以下方向:
|
||||
|
||||
- 没有自定义窗口管理器
|
||||
- 没有自定义桌面 shell 框架
|
||||
- 没有完整的桌面主题引擎
|
||||
- 没有 KDE 或 GNOME 依赖项
|
||||
- 没有将传统的应用程序启动器菜单作为主要交互模型
|
||||
- 没有桌面小部件或图标混乱
|
||||
- 不尝试用新的合成器或 shell 替换 XFCE 内部组件
|
||||
|
||||
## 4. 用户体验
|
||||
|
||||
### 4.1 桌面体验
|
||||
|
||||
默认的桌面会话应该给人一种有针对性的、类似设备的感觉:
|
||||
|
||||
- 顶部面板高度在 28px 和 32px 之间
|
||||
- 顶部面板左侧显示 `XWorkspace`
|
||||
- 右侧显示紧凑的指示器:CPU、内存、网络、Agent 就绪状态、Vault 状态和时间
|
||||
- 没有桌面图标
|
||||
- 没有可见的应用程序菜单
|
||||
- 底部停靠栏默认隐藏,鼠标指向屏幕边缘时显示
|
||||
- 停靠栏条目是固定的、基于角色的,不是开放式的
|
||||
|
||||
### 4.2 停靠栏条目
|
||||
|
||||
首选的第一组停靠栏操作是:
|
||||
|
||||
- 浏览器
|
||||
- 终端
|
||||
- 文件
|
||||
- VS Code
|
||||
- XWorkmate
|
||||
- OpenClaw
|
||||
|
||||
这些启动器应该指向稳定的系统二进制文件或应用程序模式 URL,而不是临时的用户 shell 别名。
|
||||
|
||||
### 4.3 浏览器条目
|
||||
|
||||
主要的操作员 shell 是 Chrome 或 Chromium 应用程序模式:
|
||||
|
||||
- 首选默认 URL:`http://127.0.0.1:17000`
|
||||
- 备用部署 URL:`https://workspace.local`
|
||||
|
||||
应用程序模式的启动路径应封装在脚本中,而不是在自动启动和服务文件之间复制。
|
||||
|
||||
## 5. 架构
|
||||
|
||||
设计分为五层:
|
||||
|
||||
1. 桌面 shell 层
|
||||
2. 服务编排层
|
||||
3. 本地状态 API 层
|
||||
4. 仪表板 UI 层
|
||||
5. 部署/配置层
|
||||
|
||||
### 5.1 桌面 Shell 层
|
||||
|
||||
此层由以下组成:
|
||||
|
||||
- XFCE 会话
|
||||
- XFCE 顶部面板
|
||||
- GTK/XDG 配置文件
|
||||
- Plank 停靠栏
|
||||
- XDG 自动启动条目
|
||||
|
||||
职责:
|
||||
|
||||
- 强制执行最小的桌面布局
|
||||
- 禁用桌面图标和传统菜单混乱
|
||||
- 暴露稳定的操作员 shell
|
||||
- 保持与标准 Linux 工具的兼容性
|
||||
|
||||
### 5.2 服务编排层
|
||||
|
||||
此层使用 `systemd --user`。
|
||||
|
||||
管理的服务:
|
||||
|
||||
- `xworkspace-console.service`
|
||||
- `xworkspace-openclaw.service`
|
||||
- `xworkspace-bridge.service`
|
||||
- `xworkspace-litellm.service`
|
||||
- `xworkspace-vault.service`
|
||||
|
||||
职责:
|
||||
|
||||
- 服务启动顺序
|
||||
- 重启策略
|
||||
- 面向操作员的单元命名
|
||||
- 通过 `systemctl --user` 进行本地自省
|
||||
|
||||
### 5.3 本地状态 API 层
|
||||
|
||||
此层用 `Go` 编写。
|
||||
|
||||
职责:
|
||||
|
||||
- 为仪表板暴露健康端点
|
||||
- 标准化来自 systemd 的服务状态
|
||||
- 收集简单的主机指标
|
||||
- 响应来自本地仪表板的轻量级轮询流量
|
||||
|
||||
端点:
|
||||
|
||||
- `/health`
|
||||
- `/services`
|
||||
- `/metrics/simple`
|
||||
|
||||
API 应该有意保持小巧和本地优先。
|
||||
|
||||
### 5.4 仪表板 UI 层
|
||||
|
||||
此层使用 `React + Vite + TypeScript` 编写。
|
||||
|
||||
职责:
|
||||
|
||||
- 渲染服务卡片
|
||||
- 在 MVP 中渲染任务和 Agent 占位符
|
||||
- 展示制品和设置部分
|
||||
- 通过 `ttyd` 嵌入或链接终端访问
|
||||
- 充当默认浏览器控制平面
|
||||
|
||||
视觉语言应偏暗、精确、侧重操作性,而不是装饰性。
|
||||
|
||||
### 5.5 部署和配置层
|
||||
|
||||
此层使用:
|
||||
|
||||
- Shell 脚本
|
||||
- YAML 配置
|
||||
- XFCE XML 模板
|
||||
- systemd 服务文件
|
||||
|
||||
仓库应维护一个人类可读的 YAML 配置文件,用于桌面级默认设置,如端口、浏览器偏好和服务命名。如果 XFCE 和 XDG 需要,生成或复制的运行时文件仍然可以是 XML 或 `.desktop` 文件。
|
||||
|
||||
## 6. 规范仓库结构
|
||||
|
||||
合并后的仓库应保持以下结构:
|
||||
|
||||
```text
|
||||
xworkspace-console/
|
||||
├─ api/
|
||||
├─ assets/
|
||||
│ ├─ icons/
|
||||
│ ├─ themes/
|
||||
│ └─ wallpaper/
|
||||
├─ config/
|
||||
│ ├─ autostart/
|
||||
│ ├─ systemd/
|
||||
│ │ └─ user/
|
||||
│ ├─ xfce4/
|
||||
│ └─ xworkspace-desktop.yaml
|
||||
├─ dashboard/
|
||||
│ ├─ src/
|
||||
│ ├─ package.json
|
||||
│ ├─ tsconfig.json
|
||||
│ └─ vite.config.ts
|
||||
├─ docs/
|
||||
│ └─ designs/
|
||||
├─ scripts/
|
||||
│ ├─ reset-xfce-profile.sh
|
||||
│ ├─ setup-xworkspace-desktop.sh
|
||||
│ └─ start-chromium-console.sh
|
||||
└─ README.md
|
||||
```
|
||||
|
||||
移出范围:
|
||||
|
||||
- Flutter
|
||||
- Dart
|
||||
- 静态 web shell 冗余
|
||||
|
||||
## 7. 命名模型
|
||||
|
||||
该仓库统一使用 `xworkspace-console` 作为主要的控制平面名称。
|
||||
|
||||
命名决定:
|
||||
|
||||
- 保留:`xworkspace-console`
|
||||
- 保留:`xworkspace-openclaw`
|
||||
- 保留:`xworkspace-bridge`
|
||||
- 保留:`xworkspace-litellm`
|
||||
- 保留:`xworkspace-vault`
|
||||
- 仅作为历史/重叠标签对待:`xworkspace-dashboard`、`xworkspace-portal`
|
||||
|
||||
理由:
|
||||
|
||||
- `console` 足够宽泛,涵盖桌面 shell 加上浏览器控制平面
|
||||
- 一旦服务编排和桌面问题合并,`dashboard` 就显得过于狭隘
|
||||
- `portal` 与特定的 Web 界面重叠,会导致命名重复
|
||||
|
||||
## 8. 在线环境对齐
|
||||
|
||||
实时参考主机为:
|
||||
|
||||
- SSH 入口:`ubuntu@xworkmate-bridge.svc.plus`
|
||||
- 实际主机:`jp-xhttp-contabo.svc.plus`
|
||||
|
||||
已观察到的参考在线服务行为:
|
||||
|
||||
### 8.1 Bridge
|
||||
|
||||
线上单元:
|
||||
|
||||
- `xworkmate-bridge.service`
|
||||
|
||||
观察到的形态:
|
||||
|
||||
- `WorkingDirectory=/opt/cloud-neutral/xworkmate-bridge`
|
||||
- `ExecStart=/home/ubuntu/.local/bin/xworkmate-go-core serve --listen 127.0.0.1:8787`
|
||||
|
||||
### 8.2 OpenClaw
|
||||
|
||||
线上单元:
|
||||
|
||||
- `openclaw-gateway.service`
|
||||
|
||||
观察到的形态:
|
||||
|
||||
- `WorkingDirectory=/home/ubuntu`
|
||||
- `ExecStart=/home/ubuntu/.local/bin/openclaw gateway run --port 18789 --force`
|
||||
|
||||
### 8.3 含义
|
||||
|
||||
本地仓库应在服务模板中保留这些真实的启动模式,即使仓库级名称被标准化为:
|
||||
|
||||
- `xworkspace-bridge.service`
|
||||
- `xworkspace-openclaw.service`
|
||||
|
||||
这可防止桌面仓库偏离线上环境。
|
||||
|
||||
## 9. Systemd 设计
|
||||
|
||||
### 9.1 单元
|
||||
|
||||
必需的用户单元:
|
||||
|
||||
- `xworkspace-console.service`
|
||||
- `xworkspace-openclaw.service`
|
||||
- `xworkspace-bridge.service`
|
||||
- `xworkspace-litellm.service`
|
||||
- `xworkspace-vault.service`
|
||||
|
||||
稍后推荐的可选单元:
|
||||
|
||||
- `xworkspace-status-api.service`
|
||||
- `xworkspace-ttyd.service`
|
||||
|
||||
### 9.2 服务规则
|
||||
|
||||
每个服务都应定义:
|
||||
|
||||
- 明确的 `Description`
|
||||
- 当依赖网络就绪时使用 `After=network-online.target`
|
||||
- `Restart=always`
|
||||
- 当运行时行为依赖于工作目录时,显式使用 `WorkingDirectory`
|
||||
- 当工具路径或配置重要时,显式添加 `Environment=` 条目
|
||||
|
||||
### 9.3 Console 服务
|
||||
|
||||
在 MVP 中,`xworkspace-console.service` 应运行 React 仪表板的 dev server,但预期的演进是:
|
||||
|
||||
- 早期迭代期间的 dev 模式
|
||||
- 稍后由轻量级本地 Web 服务器提供的已构建静态资源
|
||||
|
||||
该未来的转变不应改变服务名称。
|
||||
|
||||
## 10. YAML 配置模型
|
||||
|
||||
主要配置文件:
|
||||
|
||||
- `config/xworkspace-desktop.yaml`
|
||||
|
||||
职责:
|
||||
|
||||
- 浏览器二进制文件选择
|
||||
- 仪表板 URL 和端口
|
||||
- 服务命名默认值
|
||||
- Shell 级别的 UI 默认设置,如停靠栏策略和面板高度
|
||||
|
||||
设置脚本应读取此 YAML 并使用它在合理的情况下修补或生成面向部署的文件。
|
||||
|
||||
## 11. XFCE 和主题配置
|
||||
|
||||
### 11.1 XFCE
|
||||
|
||||
配置模板应保留在 `config/xfce4/` 中。
|
||||
|
||||
关键职责:
|
||||
|
||||
- 面板放置
|
||||
- 面板大小
|
||||
- 快捷键默认值
|
||||
- 会话行为
|
||||
- 窗口焦点默认值
|
||||
|
||||
### 11.2 GTK / XDG
|
||||
|
||||
主题定制应保持轻量级:
|
||||
|
||||
- GTK 主题选择
|
||||
- 图标主题选择
|
||||
- XDG 自动启动条目
|
||||
- 桌面图标抑制
|
||||
|
||||
MVP 中不需要大型主题子系统。
|
||||
|
||||
## 12. 仪表板 MVP
|
||||
|
||||
### 12.1 各个部分
|
||||
|
||||
仪表板应公开以下部分:
|
||||
|
||||
- 服务 (Services)
|
||||
- 任务 (Tasks)
|
||||
- Agent
|
||||
- 制品 (Artifacts)
|
||||
- 终端 (Terminal)
|
||||
- 设置 (Settings)
|
||||
|
||||
### 12.2 终端
|
||||
|
||||
终端行为应为以下之一:
|
||||
|
||||
- 嵌入式的 `ttyd` 框架
|
||||
- 链接到 `ttyd` 的本地跳转链接
|
||||
|
||||
MVP 可以从嵌入式面板或链接了状态的 shell 区域开始。
|
||||
|
||||
### 12.3 视觉方向
|
||||
|
||||
界面应遵循:
|
||||
|
||||
- 深色背景
|
||||
- 蓝色/白色操作强调色
|
||||
- 低视觉噪音
|
||||
- 合理的间距和可读的密度
|
||||
- 像设备一样的专注度,而非营销美学
|
||||
|
||||
卡片仅应被用于重复的仪表板项目和有界限的面板中。
|
||||
|
||||
## 13. Go API MVP
|
||||
|
||||
### 13.1 端点
|
||||
|
||||
- `/health`
|
||||
- 状态、架构、操作系统、CPU 数量、服务快照
|
||||
- `/services`
|
||||
- 标准化的 systemd 服务状态
|
||||
- `/metrics/simple`
|
||||
- 机器可读的指标行输出
|
||||
|
||||
### 13.2 数据源
|
||||
|
||||
MVP 可以使用:
|
||||
|
||||
- `systemctl --user is-active`
|
||||
- 仅使用标准库 HTTP
|
||||
- 简单的主机运行时自省
|
||||
|
||||
后续版本可能会添加:
|
||||
|
||||
- CPU 百分比
|
||||
- 内存使用率
|
||||
- 磁盘使用率
|
||||
- 网络可用性
|
||||
- Agent 就绪探针
|
||||
|
||||
## 14. 设置和重置流程
|
||||
|
||||
### 14.1 设置
|
||||
|
||||
`scripts/setup-xworkspace-desktop.sh` 应该:
|
||||
|
||||
- 安装所需的包
|
||||
- 创建目标配置目录
|
||||
- 复制 XFCE 和 systemd 模板
|
||||
- 复制 XDG 自动启动条目
|
||||
- 启用相关的用户服务
|
||||
|
||||
### 14.2 重置
|
||||
|
||||
`scripts/reset-xfce-profile.sh` 应该:
|
||||
|
||||
- 移除复制的 XFCE 面板/会话配置
|
||||
- 移除 XWorkspace 自动启动条目
|
||||
- 移除 XWorkspace 用户服务文件和符号链接
|
||||
|
||||
重置路径必须避免破坏无关的 shell 配置。
|
||||
|
||||
## 15. 风险和限制
|
||||
|
||||
### 15.1 浏览器二进制变体
|
||||
|
||||
不同的 Debian/Ubuntu 变体可能会提供:
|
||||
|
||||
- `google-chrome`
|
||||
- `chromium-browser`
|
||||
- `chromium`
|
||||
|
||||
启动器必须至少支持一个首选二进制文件加上后备选项。
|
||||
|
||||
### 15.2 XFCE 插件可用性
|
||||
|
||||
停靠栏策略可能因发行版打包而异:
|
||||
|
||||
- 首选 `Plank`
|
||||
- 需要时使用 `xfce4-docklike-plugin` 作为后备
|
||||
|
||||
### 15.3 Dev Server 对比静态构建
|
||||
|
||||
在 MVP 中运行 Vite 开发模式是可以接受的,但长远来看,如果将仪表板构建并作为静态文件提供,桌面可靠性会提高。
|
||||
|
||||
### 15.4 线上漂移
|
||||
|
||||
桌面仓库必须定期根据线上主机重新验证服务模板,以避免过时的假设,特别是针对:
|
||||
|
||||
- OpenClaw 启动标志
|
||||
- bridge 二进制路径
|
||||
- 与授权相关的环境变量
|
||||
|
||||
## 16. 实施路线图
|
||||
|
||||
### 阶段 1
|
||||
|
||||
- 移除 Flutter/Dart 残留物
|
||||
- 仅保留 YAML + Go + React + XFCE/systemd
|
||||
- 将 openclaw 和 bridge 服务模板与线上主机会齐
|
||||
- 将仪表板保持为本地 Vite MVP
|
||||
|
||||
### 阶段 2
|
||||
|
||||
- 向 Go API 添加真实的主机指标
|
||||
- 向仪表板添加 `ttyd` 集成
|
||||
- 添加基于 YAML 配置生成的停靠栏/面板设置行为
|
||||
- 改进 Plank 自动隐藏设置和启动器配置
|
||||
|
||||
### 阶段 3
|
||||
|
||||
- 打包为 Debian 制品
|
||||
- 准备 ISO/bootstrap 路径
|
||||
- 将仪表板服务从开发模式切换到生产静态资产
|
||||
|
||||
## 17. 验收标准
|
||||
|
||||
满足以下条件时,桌面环境被认为在 MVP 中是可以接受的:
|
||||
|
||||
1. 一个干净的 Ubuntu 或 Debian 虚拟机可以成功运行设置脚本
|
||||
2. XFCE 加载到极简的 workspace shell
|
||||
3. 桌面图标被隐藏
|
||||
4. 传统的应用程序菜单不是工作流程的核心
|
||||
5. 浏览器应用模式自动打开 XWorkspace console
|
||||
6. 仪表板可以读取本地服务运行状况
|
||||
7. 重置脚本可以回滚 XWorkspace 特定的桌面变更
|
||||
8. 标准的终端、浏览器和文件管理器行为保持完整
|
||||
|
||||
## 18. 当前仓库方向
|
||||
|
||||
截至此设计草案,`xworkspace-console` 应被视为:
|
||||
|
||||
- 规范的合并仓库
|
||||
- 桌面 shell 模板的来源
|
||||
- systemd 服务模板的来源
|
||||
- Go 本地 API 的来源
|
||||
- React 仪表板的来源
|
||||
|
||||
该设计取代了早期的 Flutter 控制台仓库、静态 portal 概念和单独的桌面骨架之间的划分。
|
||||
162
docs/zh/designs/xworkspace-console-homepage-v1.md
Normal file
162
docs/zh/designs/xworkspace-console-homepage-v1.md
Normal file
@ -0,0 +1,162 @@
|
||||
[🇺🇸 English](../../../README.md) | [🇨🇳 中文](../../../README.zh.md)
|
||||
|
||||
# XWorkspace 控制台主页 V1
|
||||
|
||||
日期:2026-06-07
|
||||
状态:初次实施设计
|
||||
|
||||
## 目标
|
||||
|
||||
基于提供的控制平面设计参考,构建 `xworkspace-console` 主页的第一个 React 实现。
|
||||
|
||||
第一个版本可以使用临时的模拟数据,但组件结构必须为真正的运行时集成做好准备:
|
||||
|
||||
- 自定义选项卡
|
||||
- 服务状态
|
||||
- 活跃的 Agent
|
||||
- 最近任务
|
||||
- 制品
|
||||
- 系统健康状态
|
||||
- 嵌入式 `ttyd`
|
||||
- 快速访问链接
|
||||
- 系统遥测集成点
|
||||
|
||||
## 信息架构
|
||||
|
||||
主页围绕操作仪表板进行组织:
|
||||
|
||||
- 左侧导航
|
||||
- 工作区 (Workspace)
|
||||
- 仪表板 (Dashboard)
|
||||
- Agent
|
||||
- 任务 (Tasks)
|
||||
- 制品 (Artifacts)
|
||||
- OpenClaw
|
||||
- Bridge
|
||||
- LiteLLM
|
||||
- Vault
|
||||
- 运行时 (Runtime)
|
||||
- 终端 (Terminal)
|
||||
- 设置 (Settings)
|
||||
- 顶部状态栏
|
||||
- CPU
|
||||
- GPU
|
||||
- VPN 状态
|
||||
- 通知
|
||||
- 用户/个人资料
|
||||
- 主概览
|
||||
- 指标卡片
|
||||
- 服务状态
|
||||
- 活跃的 Agent
|
||||
- 最近任务
|
||||
- 制品
|
||||
- 系统健康状态
|
||||
- 快速访问
|
||||
|
||||
## 必需链接
|
||||
|
||||
以下导航和快速访问目标对于 V1 是规范的:
|
||||
|
||||
- OpenClaw: `http://127.0.0.1:18789/channels`
|
||||
- Vault: `http://127.0.0.1:8200`
|
||||
- LiteLLM: `http://127.0.0.1:4000/ui`
|
||||
- 终端: `http://127.0.0.1:7681`
|
||||
|
||||
## 自定义选项卡
|
||||
|
||||
选项卡应表示为数据,而不是在整个 UI 中硬编码。
|
||||
|
||||
初始选项卡形态:
|
||||
|
||||
```ts
|
||||
type Tab = {
|
||||
id: string;
|
||||
label: string;
|
||||
href: string;
|
||||
kind: 'internal' | 'external' | 'embed';
|
||||
};
|
||||
```
|
||||
|
||||
这允许主页稍后支持从 YAML 或 API 响应中获取的用户定义的选项卡。
|
||||
|
||||
## 嵌入式终端
|
||||
|
||||
终端选项卡应渲染一个真正的 `ttyd` 嵌入:
|
||||
|
||||
```text
|
||||
http://127.0.0.1:7681
|
||||
```
|
||||
|
||||
第一个实现可以使用 iframe。如果需要,后续版本可以对终端进行代理或身份验证。
|
||||
|
||||
## 系统探针
|
||||
|
||||
主页的设计应能消费来自 Go API 和相关可观测性工具的本地状态数据。
|
||||
|
||||
初始本地 API:
|
||||
|
||||
- `GET http://127.0.0.1:8788/health`
|
||||
- `GET http://127.0.0.1:8788/services`
|
||||
- `GET http://127.0.0.1:8788/metrics/simple`
|
||||
|
||||
未来的集成:
|
||||
|
||||
- Prometheus 指标
|
||||
- Vector 日志
|
||||
- 本地服务日志
|
||||
- Agent 就绪探针
|
||||
- Vault 连接状态
|
||||
- OpenClaw 网关状态
|
||||
|
||||
## 模拟数据策略
|
||||
|
||||
V1 可以在以下方面使用模拟数据:
|
||||
|
||||
- 指标卡片
|
||||
- Agent
|
||||
- 任务
|
||||
- 制品
|
||||
- 系统健康评分
|
||||
|
||||
V1 应该在可用时尝试从 Go API 读取 `/services`,并在失败时优雅地回退到模拟的服务行。
|
||||
|
||||
## 视觉方向
|
||||
|
||||
提供的设计参考使用了明亮、整洁的操作控制台风格:
|
||||
|
||||
- 白色面板
|
||||
- 蓝色主要操作色
|
||||
- 细微的边框
|
||||
- 紧凑的表格
|
||||
- 低噪点的状态指示器
|
||||
- 适度的圆角
|
||||
- 仪表板优先的布局,而不是营销页面
|
||||
|
||||
卡片仅应被用于重复的仪表板项目和有界限的面板中。
|
||||
|
||||
## V1 实施说明
|
||||
|
||||
实施位置:
|
||||
|
||||
- `dashboard/src/main.tsx`
|
||||
- `dashboard/src/styles.css`
|
||||
|
||||
V1 包含:
|
||||
|
||||
- 模拟指标
|
||||
- 模拟 Agent
|
||||
- 模拟任务
|
||||
- 模拟制品
|
||||
- OpenClaw、Vault、LiteLLM 的真实外部链接
|
||||
- 嵌入式的 `ttyd` 终端选项卡
|
||||
- 尝试从 `http://127.0.0.1:8788/services` 获取服务状态
|
||||
|
||||
## 下一步
|
||||
|
||||
- 将选项卡定义移动到 `config/xworkspace-desktop.yaml`
|
||||
- 向 Go API 添加 `/tabs` 端点
|
||||
- 如果仪表板和 API 从不同的端口提供服务,添加 CORS 支持
|
||||
- 添加真实的 CPU、内存、磁盘和网络主机指标
|
||||
- 添加 Prometheus 和 Vector 探针
|
||||
- 用正式的图标系统替换字母占位符
|
||||
```
|
||||
49
docs/zh/operations/service-port-plan.md
Normal file
49
docs/zh/operations/service-port-plan.md
Normal file
@ -0,0 +1,49 @@
|
||||
[🇺🇸 English](../../../README.md) | [🇨🇳 中文](../../../README.zh.md)
|
||||
|
||||
# XWorkspace 控制台服务端口规划
|
||||
|
||||
日期:2026-06-07
|
||||
|
||||
本规划基于对 `ubuntu@xworkmate-bridge.svc.plus` (`jp-xhttp-contabo.svc.plus`) 的线上主机检查以及本地 XWorkspace 控制台仓库状态制定。
|
||||
|
||||
## 规范端点映射
|
||||
|
||||
| 组件 | 绑定 | 端口 | URL | 所有者 | 备注 |
|
||||
| --- | --- | ---: | --- | --- | --- |
|
||||
| XWorkspace Console | `127.0.0.1` | `17000` | `http://127.0.0.1:17000` | `xworkspace-console.service` | 规范的仪表板端点。避免与 macOS 上的 `ControlCenter` 发生 `7000` 端口冲突。 |
|
||||
| XWorkspace Status API | `127.0.0.1` | `8788` | `http://127.0.0.1:8788` | `xworkspace-api.service` | 用于 `/health`、`/services`、`/metrics/simple` 的 Go API。 |
|
||||
| XWorkmate Bridge | `127.0.0.1` | `8787` | `http://127.0.0.1:8787` | `xworkspace-bridge.service` / 线上 `xworkmate-bridge.service` | 预留给 bridge 控制面。不要在仪表板中重复使用。 |
|
||||
| OpenClaw Gateway | `127.0.0.1` | `18789` | `http://127.0.0.1:18789/channels` | `xworkspace-openclaw.service` / 线上 `openclaw-gateway.service` | OpenClaw UI 与网关入口。 |
|
||||
| LiteLLM | `127.0.0.1` | `4000` | `http://127.0.0.1:4000/ui` | `xworkspace-litellm.service` | 线上主机重定向后返回 HTTP 200。 |
|
||||
| Vault | `0.0.0.0` 或 `127.0.0.1` | `8200` | `http://127.0.0.1:8200` | `xworkspace-vault.service` / 系统 Vault | 线上主机在 `0.0.0.0:8200` 暴露 Vault;如果没有远程客户端需要,则后续收紧至环回地址。 |
|
||||
| Embedded Terminal | `127.0.0.1` | `7681` | `http://127.0.0.1:7681` | `ttyd.service` 或 `xworkspace-ttyd.service` | 仅使用一个所有者。线上主机已经有系统的 `ttyd.service`;用户级的 `xworkspace-ttyd.service` 因端口冲突而失败。 |
|
||||
| Legacy Portal | `0.0.0.0` | `7000` | `http://127.0.0.1:7000` | `xworkspace-portal.service` | 已废弃。将由使用 `17000` 的 Console 替代。 |
|
||||
|
||||
## 线上主机发现
|
||||
|
||||
- `xworkspace-portal.service` 在 `0.0.0.0:7000` 激活,使用 `python3 -m http.server 7000`。
|
||||
- `xworkspace-chrome.service` 目前使用 `--app=http://localhost:7000` 打开。
|
||||
- `xworkspace-console.service` 存在但未激活,仍指向旧脚本模式。
|
||||
- `xworkmate-bridge.service` 在 `127.0.0.1:8787` 激活。
|
||||
- `openclaw-gateway.service` 在 `127.0.0.1:18789` 激活。
|
||||
- `xworkspace-litellm.service` 在 `127.0.0.1:4000` 激活。
|
||||
- Vault 在 `0.0.0.0:8200` 激活。
|
||||
- 系统 `ttyd.service` 在 `127.0.0.1:7681` 激活。
|
||||
- 用户 `xworkspace-ttyd.service` 正在自动重启,因为 `7681` 已被占用。
|
||||
|
||||
## 迁移顺序
|
||||
|
||||
1. 部署 React Console 到 `~/xworkspace-console/dashboard`。
|
||||
2. 将 `xworkspace-console.service` 替换为在 `127.0.0.1:17000` 运行的常驻服务。
|
||||
3. 将 Chrome app 模式更改为 `http://127.0.0.1:17000`,并使其依赖于 `xworkspace-console.service`。
|
||||
4. 在 Console 通过健康检查后,禁用 `xworkspace-portal.service`。
|
||||
5. 保持 `xworkmate-bridge.service` 在 `127.0.0.1:8787`。
|
||||
6. 保持 `ttyd` 在 `127.0.0.1:7681`;当系统 `ttyd.service` 处于激活状态时,不要启动 `xworkspace-ttyd.service`。
|
||||
7. 保持 LiteLLM、Vault 和 OpenClaw 在其现有的线上端口。
|
||||
|
||||
## 冲突规则
|
||||
|
||||
- 绝不能将 Console 分配到 `7000`;macOS 可能会保留它,而且线上主机已经将其用于废弃的 portal。
|
||||
- 绝不能将 Console 分配到 `8787`;那是 bridge 控制面的端口。
|
||||
- 将 `7681` 视为终端单例拥有;若系统 `ttyd.service` 存在则优先使用。
|
||||
- 除非有反向代理明确暴露,否则所有控制面服务优先绑定环回地址。
|
||||
@ -1,3 +1,5 @@
|
||||
[🇺🇸 English](../../../README.md) | [🇨🇳 中文](../../../README.zh.md)
|
||||
|
||||
# 统一 AI 网关 (LiteLLM) 与 OpenClaw 兼容提供商设计规划
|
||||
|
||||
为了保持 OpenClaw 客户端原生的 `provider/model` 语法习惯,同时让所有流量依然经由 LiteLLM 统一网关进行集中鉴权、限流和日志管理,我们对网关映射层进行重构。
|
||||
@ -1,3 +1,5 @@
|
||||
[🇺🇸 English](../../README.md) | [🇨🇳 中文](../../README.zh.md)
|
||||
|
||||
# LiteLLM 模型注册映射架构与规划
|
||||
|
||||
本文档记录了 `openclaw` -> `litellm` (AI Gateway) -> `register_mainstream_models.sh` 的大模型路由和统一映射架构。
|
||||
@ -1,3 +1,5 @@
|
||||
[🇺🇸 English](../../../README.md) | [🇨🇳 中文](../../../README.zh.md)
|
||||
|
||||
# 进度报告 · TC-MAC-012
|
||||
|
||||
| 项目 | 内容 |
|
||||
Loading…
Reference in New Issue
Block a user