8.4 KiB
8.4 KiB
Refactor Notes — 重构建议与架构审核
生成日期: 2026-06-05 | 基于 chain-map 和 module-boundary 的架构分析
总体评估
三个仓库形成了一个清晰的 3 层架构:App → Bridge → (Providers + Gateway + Plugins)。架构在职责拆分上是合理的,但在以下几个方面存在可改进的空间:
- 循环依赖已收敛: Plugin → Bridge (HTTP) 反向调用已从目标架构中移除,Plugin 只保留被 Gateway 调用的 artifact adapter 职责
- 协议层过多: Chain 2 经过 4 层跳转 (App → Bridge → Gateway → Plugin)
- 容错不足: 多处依赖未处理的状态丢失场景
- 配置分散: App/Bridge/Plugin 各自维护连接配置,缺乏统一管理
问题 1: Plugin ↔ Bridge 循环依赖
现状
Bridge → (Gateway RPC) → Plugin (xworkmate.artifacts.*)
Plugin → (HTTP JSON-RPC) → Bridge (session.start, multiAgent)
问题
- 两个方向使用不同协议 (Gateway RPC vs HTTP JSON-RPC),增加调试难度
- 循环引用导致: Bridge 故障 → Plugin 不可用 → Bridge 的 agent 调用失败 → Plugin 的 bridge agent 反向调用也无法工作
- 版本升级需要同步两个方向
建议
方案 A (推荐): 统一为单向调用
删除 Plugin 中的 bridgeAgents.ts 反向 HTTP 客户端;多 agent 编排归 Bridge 或 OpenClaw 原生 runtime:
Bridge
internal/
acp/
orchestrator.go ← 拥有 bridge 侧编排逻辑
gateway.go ← 保留 xworkmate.artifacts.* 调用
Plugin 变为纯工件管理 (只被调,不反向调用):
Plugin (简化后)
src/exportArtifacts.ts ← 只保留 prepare/export/list/read
删除 src/bridgeAgents.ts ← 不再从插件反向调用 Bridge
方案 B: 统一协议方向
Plugin ↔ Bridge 全部走 Gateway RPC (去掉 Plugin 中的 HTTP 调用):
- Bridge 新增
xworkmate.bridge.*网关方法供 Plugin 调用 - Plugin 通过
api.callGatewayMethod()而非fetch()调用 Bridge
影响范围
- 方案 A: 删除 Plugin 的 bridgeAgents.ts;Bridge/OpenClaw 原生 runtime 拥有编排
- 方案 B: 改动 Bridge (新增网关方法) + Plugin (改用网关调用)
问题 2: Chain 2 协议层过多
现状
App ──(ACP/WS)──► Bridge ──(GW RPC/WS)──► Gateway ──(Plugin API)──► Plugin
跳数: 4 协议变换: 2 次
问题
- 每层增加延迟和故障点
- 错误信息层层包装,难以定位根因
- Gateway 层是性能瓶颈 (WebSocket 单连接复用)
建议
短期优化:
在 Bridge 中增加 Gateway 连接池(当前为单连接):
// gatewayruntime/pool.go (新增)
type GatewayPool struct {
conns []*GatewayRuntime
maxSize int
mu sync.Mutex
}
func (p *GatewayPool) Acquire() *GatewayRuntime { ... }
func (p *GatewayPool) Release(rt *GatewayRuntime) { ... }
中期优化:
Bridge 缓存工件元数据,减少实时 Gateway 调用:
// internal/acp/artifact_cache.go (新增)
type ArtifactCache struct {
cache map[string]*CachedArtifact
ttl time.Duration
}
// 命中缓存时跳过 Gateway→Plugin 调用
func (c *ArtifactCache) GetOrFetch(sessionKey, runId string) { ... }
长期考虑:
如果 Plugin 始终与 Bridge 在同一主机,考虑内嵌 Plugin 为 Bridge 内部模块(避免 Gateway RPC 中转)。
问题 3: 容错与恢复
3.1 SSE 流中断降级为轮询
现状 (external_code_agent_acp_desktop_transport.dart):
SSE 流中断 → 降级为 xworkmate.tasks.get 轮询 → 非实时
建议:
- 在 Bridge 中维护任务状态的增量日志,支持断点续传
- App 重连时发送
session.resume而非重新session.start
3.2 Gateway WebSocket 断连 → 任务状态丢失
现状 (gatewayruntime/runtime.go): 断连后未持久化任务状态。
建议:
- Bridge 中维护
tasksmap,断连时标记为STALE - 重连后自动查询任务最新状态
- 超过 TTL 的 STALE 任务发出
session.cancel通知 App
3.3 Gemini/Hermes 子进程崩溃
现状: 子进程崩溃后无自动重启。
建议:
// internal/geminiadapter/process_manager.go (增强)
type ProcessManager struct {
cmd *exec.Cmd
restartMax int // 最大重启次数
backoff time.Duration // 退避策略
}
func (pm *ProcessManager) Start() {
for i := 0; i < pm.restartMax; i++ {
if err := pm.run(); err != nil {
time.Sleep(pm.backoff * time.Duration(1<<i))
continue
}
break
}
}
问题 4: 配置管理分散
现状
| 组件 | 配置位置 | 管理方式 |
|---|---|---|
| App | config/settings.yaml |
本地文件 |
| App | config/feature_flags.yaml |
本地文件 |
| Bridge | 环境变量 / config.yaml |
Ansible 部署 |
| Plugin | openclaw.plugin.json / 环境变量 |
插件清单 |
问题
- 旧版 Plugin 的
bridgeUrl和bridgeToken已从目标架构中移除;剩余连接配置集中在 App/Bridge/Gateway - 配置不一致导致调试困难
- 无版本化配置管理
建议
集中配置源: 使用 accounts.svc.plus 作为配置中心。
accounts.svc.plus
GET /api/config/bridge → { serverUrl, authToken, providers... }
GET /api/config/plugin → { workspaceDir, artifact policy... }
本地配置缓存:
- App 首次启动从 accounts 拉取配置
- Bridge 启动时从 accounts 拉取 providers 配置
- Plugin 从 OpenClaw 网关配置中继承 bridge 连接信息
问题 5: 无版本兼容性检查
现状
三个仓库独立发布,无版本契约:
- xworkmate-app: 1.1.4
- xworkmate-bridge: (无显式版本)
- openclaw-multi-session-plugins: 0.1.15
建议
在 ACP 协议中增加版本协商:
// acp.capabilities 响应中增加
{
"protocolVersion": "1.0.0",
"minCompatibleVersion": "1.0.0",
"componentVersions": {
"app": "1.1.4",
"bridge": "0.2.0",
"gateway": "2026.5.28",
"plugins": "0.1.15"
}
}
App 启动时校验:
// gateway_runtime_core.dart
final caps = await gatewayRuntime.getCapabilities();
if (!isCompatible(caps.minCompatibleVersion)) {
showUpdateDialog();
return;
}
重构优先级矩阵
| 优先级 | 问题 | 改动量 | 影响 | 建议时序 |
|---|---|---|---|---|
| P0 | Plugin↔Bridge 循环依赖 | 中 (删除 bridgeAgents) | 消除循环 + 简化协议 | 已落实为目标架构 |
| P0 | Gateway 断连任务丢失 | 小 (增加持久化) | 核心可靠性 | 本周 |
| P1 | Gemini/Hermes 进程崩溃 | 小 (增加重启) | 提供商可用性 | 本周 |
| P1 | 配置管理分散 | 大 (集中配置) | 运维效率 | 本月 |
| P2 | Chain 2 协议层过多 | 大 (连接池+缓存) | 性能 + 延迟 | 本月 |
| P2 | 版本兼容性检查 | 小 (协议扩展) | 升级安全 | 本月 |
| P3 | SSE 降级轮询优化 | 中 (增量日志) | 用户体验 | 下月 |
各仓库具体改动清单
xworkmate-app
lib/runtime/gateway_acp_client.dart: 增加版本兼容性检查lib/runtime/external_code_agent_acp_desktop_transport.dart: 支持 session.resumelib/runtime/runtime_models_account.dart: 从 accounts 拉取集中配置config/settings.yaml: 减少硬编码 URL,改为从 accounts 获取
xworkmate-bridge
internal/acp/orchestrator.go: 保持 Bridge 侧编排归属,不从 Plugin 反向调用 Bridgeinternal/gatewayruntime/runtime.go: 增加连接池 + 任务状态持久化internal/gatewayruntime/pool.go: 新增连接池internal/acp/artifact_cache.go: 新增工件缓存internal/geminiadapter/+internal/hermesadapter/: 增加子进程自动重启internal/acp/rpc_handler.go: 支持 session.resume
openclaw-multi-session-plugins
src/bridgeAgents.ts: 删除反向 HTTP 调用边界openclaw.plugin.json: 简化配置(从网关继承 bridge 信息)src/exportArtifacts.ts: 增加 artifactRef TTL 可配置
不做的事情
| 项目 | 原因 |
|---|---|
| 引入 gRPC 替代 JSON-RPC | 现有协议工作正常,切换成本高于收益 |
| 合并 App 和 Bridge 为单体 | 拆分有明确的价值 (独立部署、技术栈隔离) |
| 引入消息队列 | 当前规模不需要,会增加运维复杂度 |
| 统一为单一编程语言 | Dart/Go/TS 各有适用场景,不必强行统一 |