From c1c5a94a54fae437d7004ba14da0518b7fcc16b1 Mon Sep 17 00:00:00 2001 From: Haitao Pan Date: Sun, 29 Mar 2026 12:42:09 +0800 Subject: [PATCH] docs(architecture): add layered architecture overview --- .../xworkmate-layered-architecture.md | 439 ++++++++++++++++++ 1 file changed, 439 insertions(+) create mode 100644 docs/architecture/xworkmate-layered-architecture.md diff --git a/docs/architecture/xworkmate-layered-architecture.md b/docs/architecture/xworkmate-layered-architecture.md new file mode 100644 index 00000000..fde0f77d --- /dev/null +++ b/docs/architecture/xworkmate-layered-architecture.md @@ -0,0 +1,439 @@ +# XWorkmate 整体分层架构 + +Last Updated: 2026-03-29 + +## 目的 + +这份文档不是只画一张“UI 在上、服务在下”的静态框图,而是基于当前仓库代码, +重新规划 XWorkmate 的整体分层架构,回答四个问题: + +- 本地用户、Web 用户、远程租户如何进入系统 +- 任务线程如何成为 UI 与执行之间的控制面主对象 +- Desktop / Mobile / Web 三个界面层如何共用同一套 agent core +- 本地 agent、OpenClaw Gateway、ACP endpoint、AI Gateway、Skills / MCP + 等扩展能力应该落在哪一层 + +这份文档是整体总览。专题细节仍以以下文档为准: + +- `docs/architecture/assistant-thread-target-model-20260328.md` +- `docs/architecture/xworkmate-internal-state-architecture.md` +- `docs/architecture/xworkmate-integrations.md` + +## 为什么要重新规划 + +如果只用“用户 -> UI -> Agent-core -> 服务”四层表达,当前项目里最关键的 +一个事实会被隐藏掉: + +**XWorkmate 的运行主对象不是某个页面,也不是某个 gateway session,而是 +`TaskThread`。** + +当前代码里,线程已经有清晰的 canonical schema: + +- `ownerScope` +- `workspaceBinding` +- `executionBinding` +- `contextState` +- `lifecycleState` + +这意味着整体架构更适合规划成: + +1. 访问与归属层 +2. 多端 UI 层 +3. 线程控制面 +4. Agent-core 调度层 +5. 对接服务与扩展层 +6. 安全与持久化基座(横切,不单独作为主业务层) + +推荐的关键判断是: + +- UI 不是执行状态真值源 +- `TaskThread` 才是线程级控制面真值源 +- Agent-core 负责把线程状态翻译成可执行请求 +- 真正的 provider / gateway / ACP / Skills / MCP 都应放在 Agent-core 之下 + +## 整体架构 + +```mermaid +flowchart TB + subgraph L1["① 访问与归属层"] + A1["本地用户 / 设备身份
Desktop / Native host"] + A2["Web 用户 / Browser session"] + A3["远程租户 / owner realm"] + end + + subgraph L2["② 多端 UI 层 (Flutter / Dart)"] + B1["AppShellDesktop / mobile_shell / AppShellWeb"] + B2["AssistantPage / SettingsPage / Tasks / Modules / Account"] + B3["WorkspacePageRegistry / destination routing / feature flags"] + end + + subgraph L3["③ 线程控制面"] + C1["TaskThread"] + C2["ownerScope"] + C3["workspaceBinding"] + C4["executionBinding"] + C5["contextState"] + C6["lifecycleState"] + C7["线程持久化
SettingsStore / WebSessionRepository"] + end + + subgraph L4["④ Agent-core 调度层"] + D1["AppControllerDesktop / AppControllerWeb"] + D2["GoAgentCoreClient 抽象"] + D3["RuntimeCoordinator / GatewayRuntime / ModeSwitcher"] + D4["CodeAgentNodeOrchestrator"] + D5["SingleAgentRunner / DirectSingleAgentAppServerClient / CodexRuntime"] + D6["MultiAgentOrchestrator / MultiAgentMountManager"] + D7["CodexConfigBridge / OpencodeConfigBridge"] + D8["Desktop transport
GoAgentCoreDesktopTransport / go_core / codex_ffi_bindings"] + D9["Web transport
GoAgentCoreWebTransport / WebAcpClient / Relay"] + end + + subgraph L5["⑤ 对接服务与扩展层"] + E1["本地 Agent / local app-server / Codex"] + E2["OpenClaw Gateway / Host"] + E3["Remote ACP endpoint / custom providers"] + E4["AI Gateway / Ollama / LLM endpoints"] + E5["Skills / MCP / workspace / attachments / adapters"] + end + + F1[("安全与持久化基座
SecretStore / SecureConfigStore / SettingsSnapshot")] + + A1 --> B1 + A2 --> B1 + A3 --> B1 + + B1 --> B2 + B1 --> B3 + B2 --> C1 + B3 --> C1 + + C1 --> C2 + C1 --> C3 + C1 --> C4 + C1 --> C5 + C1 --> C6 + C1 --> D1 + + D1 --> D2 + D1 --> D3 + D1 --> D4 + D1 --> D6 + D1 --> D7 + + D2 --> D8 + D2 --> D9 + D3 --> E2 + D4 --> E2 + D5 --> E1 + D6 --> E5 + D7 --> E3 + D7 --> E5 + D8 --> E1 + D8 --> E2 + D8 --> E4 + D9 --> E2 + D9 --> E3 + D9 --> E4 + + C7 -.-> C1 + F1 -.-> B2 + F1 -.-> C1 + F1 -.-> D1 + F1 -.-> D3 +``` + + +## 这五层分别是什么 + +### 1. 访问与归属层 + +这一层表达“谁在用系统、线程归谁所有”,不是具体页面。 + +在当前代码里,最接近这层的是: + +- Desktop 本地设备身份:`DeviceIdentityStore` +- Web 会话身份与远程持久化身份:`WebSessionPersistenceConfig` +- 线程归属对象:`ThreadOwnerScope` + +它的意义是把“用户入口”和“线程归属”从 UI 外观里抽离出来,让后续的 +线程绑定、远端工作区路径、租户隔离都围绕 `ownerScope` 来展开。 + +### 2. 多端 UI 层 + +这一层只负责交互、展示和编辑,不拥有执行真值。 + +当前项目对应: + +- Desktop shell:`lib/app/app_shell_desktop.dart` +- Mobile shell:`lib/features/mobile/` +- Web shell:`lib/app/app_shell_web.dart` +- 统一页面入口:`WorkspacePageRegistry` +- 页面族:`AssistantPage`、`SettingsPage`、`TasksPage`、`ModulesPage` + +重规划后的规则是: + +- UI 负责选择线程、展示线程、编辑设置、发起动作 +- UI 不直接决定真实工作目录、真实执行模式、真实 provider 绑定 +- UI 必须通过 `TaskThread` + `AppController` 读写运行状态 + +### 3. 线程控制面 + +这是这次重规划里最重要的一层。 + +`TaskThread` 应被视为整个 App 的线程级控制面主对象,而不是聊天列表记录。 + +当前代码里它已经具备完整控制面字段: + +- `ownerScope` +- `workspaceBinding` +- `executionBinding` +- `contextState` +- `lifecycleState` + +它的职责是: + +- 绑定线程归属 +- 绑定工作区路径与展示路径 +- 绑定执行模式与 provider +- 保存模型、技能、消息、权限、视图模式 +- 保存线程的归档与最近执行状态 + +因此,推荐把所有“切换线程、发消息、切换目标、切换 provider、回写远端目录” +都看成对线程控制面的更新,而不是页面局部状态切换。 + +### 4. Agent-core 调度层 + +这是 XWorkmate 的核心中枢。 + +它不只是“某个 agent SDK”,而是一整套把线程控制面翻译成执行请求的调度层。 + +当前代码里,这层最关键的组件是: + +- `AppControllerDesktop` +- `AppControllerWeb` +- `RuntimeCoordinator` +- `GatewayRuntime` +- `CodeAgentNodeOrchestrator` +- `GoAgentCoreClient` +- `GoAgentCoreDesktopTransport` +- `GoAgentCoreWebTransport` +- `SingleAgentRunner` +- `MultiAgentOrchestrator` +- `MultiAgentMountManager` +- `CodexConfigBridge` +- `OpencodeConfigBridge` + +重规划后的职责边界应当是: + +- `AppController*` 负责从 `TaskThread` 解析出当前线程的执行上下文 +- `GoAgentCoreClient` 负责统一 Desktop / Web 的 agent-core 会话调用抽象 +- `RuntimeCoordinator` / `GatewayRuntime` 负责 runtime 与 gateway 连接能力 +- `CodeAgentNodeOrchestrator` 负责 app-mediated cooperative node metadata +- `MultiAgentOrchestrator` / `MultiAgentMountManager` 负责协作执行与挂载 +- Config bridge 只负责受管配置写入,不越权持有 UI 真值 + +### 5. 对接服务与扩展层 + +这一层是实际被调用的执行对象和扩展对象,不应与 controller 混层。 + +当前代码和文档中,对应的能力面包括: + +- 本地单机 agent / local app-server / Codex runtime +- OpenClaw Gateway / Host +- Remote ACP endpoint / 自定义 provider endpoint +- AI Gateway / Ollama / LLM provider +- Skills / MCP / workspace / attachments +- Codex / Claude / Gemini / OpenCode / OpenClaw adapters + +重规划后的原则是: + +- 新 provider 进入这一层 +- 新 gateway 进入这一层 +- 新 Skills / MCP / 附件能力进入这一层 +- UI 不因为新增 provider 而重新设计页面结构 +- 新扩展优先通过 `executionBinding`、transport、adapter、mount manager + 接入,而不是直接打穿到页面 + +### 6. 安全与持久化基座 + +它是横切基座,不应抢占主业务层。 + +当前代码里主要是: + +- `SettingsStore` +- `SecretStore` +- `SecureConfigStore` +- `SettingsSnapshot` +- `WebStore` + +职责是: + +- 持久化线程记录和设置 +- 安全保存 secret +- 提供 settings snapshot +- 为 Desktop / Web 各自提供持久化后端 + +## 线程执行主链路 + +下面这张图把你给出的“UI 选择线程 -> 读取线程 -> 构造请求 -> 执行 -> 回写” +链路,映射到当前代码里的真实对象。 + +```mermaid +flowchart LR + A["UI 选择 / 新建 / 切换线程"] --> B["currentSessionKey"] + B --> C["读取 TaskThread"] + + C --> C1["ownerScope"] + C --> C2["workspaceBinding"] + C --> C3["executionBinding"] + C --> C4["contextState"] + + C1 --> D["构造 GoAgentCoreSessionRequest
或 Gateway 执行请求"] + C2 --> D + C3 --> D + C4 --> D + + D --> E{"executionMode"} + E -->|localAgent| F["GoAgentCoreDesktopTransport / SingleAgentRunner"] + E -->|gatewayLocal| G["GatewayRuntime / OpenClaw local"] + E -->|gatewayRemote| H["GatewayAcpClient / WebAcpClient / Remote ACP"] + + F --> I["执行结果 / delta / resolvedWorkingDirectory"] + G --> I + H --> I + + I --> J["回写 contextState / lifecycleState"] + I --> K["必要时回写 workspaceBinding"] + + J --> L["持久化 TaskThread"] + K --> L + L --> M["对话区 / 右栏 / 文件面板 / Tasks 刷新"] +``` + +这条链路里的关键点是: + +- UI 先选线程,不是先选 provider +- 线程先绑定,再执行 +- 执行模式由 `executionBinding` 决定 +- 结果先回写线程,再刷新 UI +- 远端返回新的 working directory 时,应该回写 `workspaceBinding` + +## 当前代码里的真实组件映射 + +| 层级 | 当前主组件 | 代表文件 | 当前职责 | +| --- | --- | --- | --- | +| 访问与归属层 | `ThreadOwnerScope`、`DeviceIdentityStore`、Web session identity | `lib/runtime/runtime_models_runtime_payloads.dart`, `lib/runtime/device_identity_store.dart`, `lib/web/web_session_repository.dart` | 定义线程归属、设备身份、远程会话身份 | +| 多端 UI 层 | `AppShellDesktop`、`mobile_shell_*`、`AppShellWeb`、`AssistantPage`、`SettingsPage` | `lib/app/`, `lib/features/assistant/`, `lib/features/mobile/`, `lib/features/settings/` | 接收用户操作、展示线程与设置 | +| 线程控制面 | `TaskThread` + thread records | `lib/runtime/runtime_models_runtime_payloads.dart`, `lib/runtime/settings_store.dart`, `lib/web/web_session_repository.dart` | 保存线程级真值状态 | +| Agent-core 调度层 | `AppControllerDesktop/Web`、`GoAgentCoreClient`、`RuntimeCoordinator`、`CodeAgentNodeOrchestrator`、`MultiAgentOrchestrator` | `lib/app/`, `lib/runtime/`, `lib/web/` | 把线程状态翻译为执行请求并协调 transport | +| 对接服务与扩展层 | local agent、OpenClaw Gateway、ACP endpoint、AI Gateway、Skills / MCP / adapters | `lib/runtime/go_agent_core_desktop_transport.dart`, `lib/web/go_agent_core_web_transport.dart`, `lib/runtime/multi_agent_mounts.dart` | 真实执行与扩展接入 | +| 安全与持久化基座 | `SettingsStore`、`SecretStore`、`SecureConfigStore`、`WebStore` | `lib/runtime/`, `lib/web/web_store.dart` | 提供持久化与 secret 保护 | + +## 三端职责矩阵 + +| 平台 | UI 入口 | 线程控制面 | agent-core 重点 | 当前执行特点 | +| --- | --- | --- | --- | --- | +| Desktop | `AppShellDesktop` + workspace 页面 | `TaskThread` 持久化最完整 | `AppControllerDesktop` + `RuntimeCoordinator` + Desktop transport | 支持本地 single-agent、gateway local、gateway remote | +| Mobile | `mobile_shell_*` | 复用同一线程模型 | 仍走 native host/controller 体系 | 当前以 remote gateway 场景为主 | +| Web | `AppShellWeb` | 同 schema 的 thread records | `AppControllerWeb` + `GoAgentCoreWebTransport` + relay/acp client | 远程 ACP / relay / AI Gateway 路径 | + +## 对你给出的旧图,按代码需要做的三个修正 + +### 修正 1:`TaskThread` 必须上提成独立控制面 + +你给的第二张图其实已经接近真实代码主链路了。 + +真正需要正式化的是: + +- `TaskThread` 不是“聊天线程 UI 对象” +- 它应该成为 UI 与调度层之间的唯一线程级真值对象 + +这也是为什么这次重规划把“线程控制面”单独从 UI 和 runtime 中抽出来。 + +### 修正 2:`MultiAgentBrokerServer` 目前更适合作为概念 seam,不是已落地的独立主类 + +现有仓库里没有真正的 `MultiAgentBrokerServer` 实现类。 + +从代码现实出发,当前更准确的 seam 是: + +- `GoAgentCoreClient` +- `GoAgentCoreDesktopTransport` +- `GoAgentCoreWebTransport` +- `GatewayAcpClient` +- `WebAcpClient` +- `MultiAgentOrchestrator` + +因此,新的整体架构里应把“broker / ACP / transport”归到 Agent-core 调度层内部, +而不是单独挂成一个与 UI 并列的主系统。 + +### 修正 3:`Assistant composer / Settings / Feature flags` 属于 UI 层,不属于运行时层 + +旧图里把 `Assistant composer / Settings / Feature flags` 和 runtime 节点并排。 + +按代码来看,它们更准确的定位是: + +- UI 入口 +- 运行时配置编辑器 +- 线程动作触发点 + +它们不应该拥有执行调度职责,只应通过 controller 和线程控制面驱动 runtime。 + +## 未来扩展时的落点规则 + +### 新 UI surface + +如果未来加新 surface,例如专门的平板布局或独立工作台视图: + +- 放在多端 UI 层 +- 复用 `TaskThread` 控制面 +- 不直接接 provider SDK + +### 新执行目标 + +如果未来新增新的执行目标或新的 gateway 类型: + +- 先扩展 `executionBinding` +- 再扩展 `GoAgentCoreClient` transport 或 runtime coordinator +- 不要先改页面分支逻辑 + +### 新 provider / adapter / MCP / skill capability + +如果未来新增 Codex / Claude / Gemini / OpenCode 之外的 provider: + +- 放在对接服务与扩展层 +- 通过 mount manager、config bridge、ACP endpoint、adapter 接入 +- UI 只展示能力,不成为 provider 真值层 + +### 新租户/归属模型 + +如果未来要支持团队、项目、组织、设备共享: + +- 先扩展 `ThreadOwnerScope` +- 其次扩展远端 `workspaceBinding` 规则 +- 不要把租户逻辑散落到页面和 provider 配置里 + +## 架构结论 + +结合当前代码和你给的两张图,XWorkmate 最合适的整体定位不是: + +- 一个 UI + 若干 provider 接口 + +而是: + +- 一个以 `TaskThread` 为控制面核心的多端 agent workspace App +- UI 负责交互 +- 线程控制面负责真值 +- Agent-core 负责调度与 transport +- Gateway / ACP / local agent / Skills / MCP 负责实际执行与扩展 + +一句话概括: + +**XWorkmate 应该被设计成“线程先行、界面多端、调度内聚、执行可插拔”的 agent workspace 平台。** + +## 相关文档 + +- `docs/architecture/assistant-thread-target-model-20260328.md` +- `docs/architecture/xworkmate-internal-state-architecture.md` +- `docs/architecture/xworkmate-integrations.md` +- `docs/architecture/assistant-thread-information-architecture.md`