docs: record metadata issue and task routing

This commit is contained in:
Haitao Pan 2026-04-06 14:17:36 +08:00
parent f6e1f84aab
commit a9e552737e
3 changed files with 91 additions and 22 deletions

View File

@ -11,7 +11,7 @@
3. UI 选中线程后,系统必须读取完整 `TaskThread`,而不是从页面状态拼装线程信息。
4. `TaskThread` 持久化 schema 保持不变,但 `workspaceBinding` 在 create/load 时必须完整;缺失 binding 的旧记录按非法数据处理并跳过加载。
5. 执行请求由 controller / runtime 根据 `ownerScope / workspaceBinding / executionBinding / contextState` 构造。
6. controller / runtime 统一通过 `GoTaskService` 调度执行OpenClaw task 走 `TaskThread -> GoTaskService -> GatewayRuntime / Web relay -> OpenClaw gateway``singleAgent / multiAgent` 走 `TaskThread -> GoTaskService -> ExternalCodeAgentAcp* -> ACP/provider route`
6. controller / runtime 统一通过 `GoTaskService` 调度执行,并遵循 `TaskThread` 驱动的任务分流语义`OpenClaw task``TaskThread -> GoTaskService -> GatewayRuntime / Web relay -> OpenClaw gateway``singleAgent / multiAgent` 等 ACP lane`TaskThread -> GoTaskService -> ExternalCodeAgentAcp* -> ACP/provider route`
7. 执行结果先回写 `TaskThread.contextState`主体区域同步显示UI 与执行始终只读取当前 `TaskThread.workspaceBinding`,不再存在 runtime first-binding 或 fallback 到 `main`
8. `contextState` 是线程上下文真相源;`lifecycleState` 只表达生命周期摘要controller 侧缓存不承载线程持久语义。
@ -78,7 +78,7 @@ ExecutionBinding
- 定义线程当前执行模式
- 定义 provider / endpoint 绑定
- 为 `GoTaskService / runtime` 协调层提供调度输入
- 为 `GoTaskService / runtime` 的任务分流与执行通道选择提供调度输入
### 2.4 contextState
@ -133,14 +133,18 @@ flowchart LR
D3 --> E
D4 --> E
E --> F["GoTaskService\nDesktop: GatewayRuntime / ExternalCodeAgentAcpDesktopTransport\nWeb: relay / ExternalCodeAgentAcpWebTransport"]
F --> G["执行结果"]
E --> F{"GoTaskService 任务分流"}
F -->|OpenClaw task| G["GatewayRuntime / Web relay -> OpenClaw gateway"]
F -->|singleAgent / multiAgent| H["ExternalCodeAgentAcp* -> ACP/provider route"]
G --> H["回写线程上下文\n(主体区域 同步显示)"]
G --> I["仅显式更新当前线程 workspaceBinding"]
G --> I["执行结果"]
H --> I
H --> J["右栏显示"]
I --> J
I --> J["回写线程上下文\n(主体区域 同步显示)"]
I --> K["仅显式更新当前线程 workspaceBinding"]
J --> L["右栏显示"]
K --> L
```
这条链路是当前唯一生命周期基准:
@ -148,10 +152,12 @@ flowchart LR
1. UI 仍保持现有形态,但只负责选择 `threadId` 与消费回写结果。
2. 线程的执行输入来自完整 `TaskThread`
3. `构造执行请求` 属于 `GoTaskService / runtime` 协调层,不属于 UI。
4. `GoTaskService` 是唯一执行调度面Desktop / Web 共用同一套 session 语义,只在 transport 上有差异。
5. `回写线程上下文` 是执行结束后的第一落点;主体区域同步显示依赖这一回写。
6. `workspaceBinding` 不是运行时补齐对象;线程在 create/load 时必须已经完整。
7. `右栏显示` 与执行请求都读取当前 `TaskThread.workspaceBinding`,因此它与主体区域共享同一线程事实来源。
4. 当前任务流不是单一路由:`OpenClaw task` 与 ACP lane 在 `TaskThread` 读取之后立即分流。
5. `OpenClaw task` 的规范路径是 `TaskThread -> GoTaskService -> GatewayRuntime / Web relay -> OpenClaw gateway`
6. `singleAgent / multiAgent` 的规范路径是 `TaskThread -> GoTaskService -> ExternalCodeAgentAcp* -> ACP/provider route`
7. `回写线程上下文` 是执行结束后的第一落点;主体区域同步显示依赖这一回写。
8. `workspaceBinding` 不是运行时补齐对象;线程在 create/load 时必须已经完整。
9. `右栏显示` 与执行请求都读取当前 `TaskThread.workspaceBinding`,因此它与主体区域共享同一线程事实来源。
## 4. 当前设计约束
@ -165,7 +171,9 @@ flowchart LR
### 4.2 GoTaskService / runtime 协调层约束
- 根据 `ownerScope / workspaceBinding / executionBinding / contextState` 构造执行请求。
- 负责把线程请求调度到 `GoTaskService`,而不是让 Flutter UI 直接承担 runtime 职责。
- 负责根据任务类型把线程请求分流到正确执行通道,而不是让 Flutter UI 直接承担 runtime 职责。
- `OpenClaw task` 必须走 `TaskThread -> GoTaskService -> GatewayRuntime / Web relay -> OpenClaw gateway`
- `singleAgent / multiAgent` 必须走 `TaskThread -> GoTaskService -> ExternalCodeAgentAcp* -> ACP/provider route`
- 接收执行结果并驱动 `TaskThread` 回写。
### 4.3 TaskThread 约束
@ -183,5 +191,7 @@ flowchart LR
说明线程信息如何进入 UI、`GoTaskService / runtime` 请求构造、结果回写和右栏展示。
- [xworkmate-internal-state-architecture.md](xworkmate-internal-state-architecture.md)
说明控制器、状态存储和派生 UI 状态如何围绕 `TaskThread` 组织。
- [xworkmate-layered-architecture.md](xworkmate-layered-architecture.md)
说明 `GoTaskService`、`GatewayRuntime / Web relay`、`ExternalCodeAgentAcp*` 与 `ACP/provider route` 的分层关系。
归档文档仍可保留作为历史背景,但不再参与当前设计说明。

View File

@ -9,7 +9,7 @@ Last Updated: 2026-03-29
- 本地用户、Web 用户、远程租户如何进入系统
- 任务线程如何成为 UI 与执行之间的控制面主对象
- Desktop / Mobile / Web 三个界面层如何共用同一套 `GoTaskService` 执行主链
- Desktop / Mobile / Web 三个界面层如何共用同一套 `GoTaskService` 执行主链与任务分流语义
- 本地 agent、OpenClaw Gateway、ACP endpoint、AI Gateway、Skills / MCP
等扩展能力应该落在哪一层
@ -48,7 +48,7 @@ Last Updated: 2026-03-29
- UI 不是执行状态真值源
- `TaskThread` 才是线程级控制面真值源
- `GoTaskService` 负责把线程状态翻译成可执行请求
- `GoTaskService` 负责把线程状态翻译成可执行请求,并在 OpenClaw lane 与 ACP lane 之间分流
- 真正的 provider / gateway / ACP / Skills / MCP 都应放在 `GoTaskService` 之下
## 整体架构
@ -202,12 +202,21 @@ flowchart TB
因此,推荐把所有“切换线程、发消息、切换目标、切换 provider、回写远端目录”
都看成对线程控制面的更新,而不是页面局部状态切换。
### 4. Agent-core 调度层
### 4. GoTaskService 调度层
这是 XWorkmate 的核心中枢。
它不只是“某个 agent SDK”而是一整套把线程控制面翻译成执行请求的调度层。
这一层的上位语义应该理解为:
- `OpenClaw task`
- `TaskThread -> GoTaskService -> GatewayRuntime / Web relay -> OpenClaw gateway`
- `ACP task`
- `TaskThread -> GoTaskService -> ExternalCodeAgentAcp* -> ACP/provider route`
也就是说,`GoTaskService` 才是整层的上位名字;具体 transport 与 gateway/ACP lane 只是它的执行子路径。
当前代码里,这层最关键的组件是:
- `AppControllerDesktop`
@ -233,6 +242,17 @@ flowchart TB
- `MultiAgentOrchestrator` / `MultiAgentMountManager` 负责协作执行与挂载
- Config bridge 只负责受管配置写入,不越权持有 UI 真值
## 术语表
| 术语 | 规范语义 | 当前作用 |
| --- | --- | --- |
| `TaskThread` | 线程级控制面主对象 | 承载线程身份、工作区、执行绑定、上下文与生命周期 |
| `OpenClaw task` | 面向本地或远端 OpenClaw gateway 的任务 | 规范路径:`TaskThread -> GoTaskService -> GatewayRuntime / Web relay -> OpenClaw gateway` |
| `ACP task` | 不走 OpenClaw gateway 的任务 | 规范路径:`TaskThread -> GoTaskService -> ExternalCodeAgentAcp* -> ACP/provider route` |
| `GatewayRuntime` | OpenClaw task 的 App 侧 runtime 门面 | 负责 gateway chat / session / pairing / history 等语义 |
| `ExternalCodeAgentAcp*` | ACP task 的 transport 组件 | 负责把任务送入 ACP/provider route |
| `ACP/provider route` | 非 OpenClaw provider 的执行通道 | 包括 ACP transport、provider endpoint、兼容 relay/provider 路径 |
### 5. 对接服务与扩展层
这一层是实际被调用的执行对象和扩展对象,不应与 controller 混层。
@ -294,9 +314,9 @@ flowchart LR
C3 --> D
C4 --> D
D --> E{"executionMode"}
E -->|openclaw task| G["GoTaskService -> GatewayRuntime / Web relay"]
E -->|singleAgent / multiAgent| H["GoTaskService -> ExternalCodeAgentAcp* / ACP route"]
D --> E{"任务类型分流"}
E -->|OpenClaw task| G["GoTaskService -> GatewayRuntime / Web relay -> OpenClaw gateway"]
E -->|singleAgent / multiAgent| H["GoTaskService -> ExternalCodeAgentAcp* -> ACP route"]
G --> I
H --> I
@ -313,7 +333,9 @@ flowchart LR
- UI 先选线程,不是先选 provider
- 线程先绑定,再执行
- 执行模式由 `executionBinding` 决定
- 执行模式与 provider 绑定共同决定最终任务分流
- `OpenClaw task` 不再走 ACP 兼容桥,而是统一走 `GoTaskService -> GatewayRuntime / Web relay -> OpenClaw gateway`
- `singleAgent / multiAgent` 统一走 `GoTaskService -> ExternalCodeAgentAcp* -> ACP/provider route`
- 结果先回写线程,再刷新 UI
- 远端返回新的 working directory 时,只能显式回写当前已完整线程的 `workspaceBinding`
- 这类回写不能创建 first binding也不能改变线程身份
@ -325,7 +347,7 @@ flowchart LR
| 访问与归属层 | `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` | 保存线程级真值状态 |
| `GoTaskService` 调度层 | `AppControllerDesktop/Web`、`GoTaskServiceClient`、`RuntimeCoordinator`、`CodeAgentNodeOrchestrator`、`MultiAgentOrchestrator` | `lib/app/`, `lib/runtime/`, `lib/web/` | 把线程状态翻译为执行请求并协调 transport |
| `GoTaskService` 调度层 | `AppControllerDesktop/Web`、`GoTaskServiceClient`、`RuntimeCoordinator`、`CodeAgentNodeOrchestrator`、`MultiAgentOrchestrator` | `lib/app/`, `lib/runtime/`, `lib/web/` | 把线程状态翻译为执行请求,并按 OpenClaw / ACP 路径分流执行 |
| 对接服务与扩展层 | local agent、OpenClaw Gateway、ACP endpoint、AI Gateway、Skills / MCP / adapters | `lib/runtime/external_code_agent_acp_desktop_transport.dart`, `lib/web/external_code_agent_acp_web_transport.dart`, `lib/runtime/multi_agent_mounts.dart` | 真实执行与扩展接入 |
| 安全与持久化基座 | `SettingsStore`、`SecretStore`、`SecureConfigStore`、`WebStore` | `lib/runtime/`, `lib/web/web_store.dart` | 提供持久化与 secret 保护 |
@ -333,7 +355,7 @@ flowchart LR
| 平台 | UI 入口 | 线程控制面 | `GoTaskService` 重点 | 当前执行特点 |
| --- | --- | --- | --- | --- |
| Desktop | `AppShellDesktop` + workspace 页面 | `TaskThread` 持久化最完整 | `AppControllerDesktop` + `RuntimeCoordinator` + Desktop transport | 支持本地 single-agent、gateway local、gateway remote |
| Desktop | `AppShellDesktop` + workspace 页面 | `TaskThread` 持久化最完整 | `AppControllerDesktop` + `GoTaskService` + `GatewayRuntime / ExternalCodeAgentAcp*` | 支持本地 single-agent、OpenClaw local / remote、ACP/provider route |
| Mobile | `mobile_shell_*` | 复用同一线程模型 | 仍走 native host/controller 体系 | 当前以 remote gateway 场景为主 |
| Web | `AppShellWeb` | 同 schema 的 thread records | `AppControllerWeb` + `ExternalCodeAgentAcpWebTransport` + relay/acp client | 远程 ACP / relay / AI Gateway 路径 |

View File

@ -0,0 +1,37 @@
# GitHub Issue Record: INVALID_REQUEST on Single-Agent Task Mode
- Date: 2026-04-06
- Source: In-app error report from desktop app (Task chat mode -> Single Agent)
- Scope: Task conversation in `单机智能体` mode
## Title
`INVALID_REQUEST: invalid chat.send params: at root: unexpected property 'metadata'`
## Reproduction Steps
1. Open XWorkmate app.
2. Click **新对话**.
3. In task mode selector, choose **任务对话模式 -> 单机智能体**.
4. Send any message.
5. Observe error in conversation pane:
- `INVALID_REQUEST: invalid chat.send params: at root: unexpected property 'metadata'`
## Actual Result
The conversation fails immediately and returns request validation error because `chat.send` request payload contains an unexpected root-level `metadata` field.
## Expected Result
Single-agent task chat should send a provider-compatible payload and complete message dispatch without schema validation errors.
## Impact
- Users cannot reliably start new single-agent task conversations.
- Reproducible in normal workflow, blocks core single-agent usage path.
## Notes for Follow-up
- Inspect request assembly path for single-agent `chat.send` payload.
- Confirm whether metadata must be nested, filtered, or omitted for the current provider endpoint.
- Add regression tests for provider schema compatibility in single-agent mode.