docs: record metadata issue and task routing
This commit is contained in:
parent
f6e1f84aab
commit
a9e552737e
@ -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` 的分层关系。
|
||||
|
||||
归档文档仍可保留作为历史背景,但不再参与当前设计说明。
|
||||
|
||||
@ -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 路径 |
|
||||
|
||||
|
||||
@ -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.
|
||||
Loading…
Reference in New Issue
Block a user