diff --git a/docs/superpowers/specs/2026-04-03-claw-backend-adapter-design.md b/docs/superpowers/specs/2026-04-03-claw-backend-adapter-design.md new file mode 100644 index 0000000..3b2258b --- /dev/null +++ b/docs/superpowers/specs/2026-04-03-claw-backend-adapter-design.md @@ -0,0 +1,294 @@ +# Boss `ClawBackendAdapter` 最小接入设计 + +## 背景 + +Boss 已经完成了第一阶段执行底座抽象层: + +- `ExecutionBackend` +- `ExecutionBackendSelector` +- `PromptAssembler` +- `MemoryResolver` +- `PermissionPolicy` +- `RemoteRuntimeAdapter` +- `OrchestrationBackend` + +当前生产执行主链仍然是: + +- `boss-master-agent.ts` +- `master-agent task queue` +- `local-agent/server.mjs` +- `codex exec resume` +- `/api/v1/master-agent/tasks/[taskId]/complete` + +现在的目标不是替换这条链,而是让 Boss 拥有一个**可插拔的外部执行内核候选**,为后续吸收 `claw-code` 的 runtime 演进打基础。 + +## 目标 + +本轮要实现的是: + +1. 在 Boss 中新增一个 `ClawBackendAdapter` +2. 让它成为 `ExecutionBackend` 的一个可选实现 +3. 保持默认关闭,不影响当前生产主链 +4. 让 Boss 可以在显式启用时,把单次执行请求交给 `claw-code` +5. 让失败回退继续走 Boss 现有后端选择链 + +## 非目标 + +本轮明确不做: + +1. 不直接把 `claw-code` 作为默认主执行链 +2. 不直接依赖 `claw-code` 仓库内部目录结构 +3. 不让 `claw-code` 接管群聊、审批、设备导入、多租户、账本或 UI +4. 不实现 `claw-code` 的完整 session/runtime 集成 +5. 不实现 `claw-code` 自动拉取或自动升级 +6. 不把 `oh-my-codex` 一起接入这一轮 + +## 设计结论 + +采用“**最小单次执行适配器**”方案: + +- Boss 保持产品层和业务层控制权 +- `ClawBackendAdapter` 只负责单次执行 +- 当前只接: + - `master_agent_reply` + - `thread_reply` +- `attachment_analysis` 仅预留 contract + +它的定位是: + +- 一个新的 `ExecutionBackend` +- 默认关闭 +- 只在显式启用并且配置完整时参与 backend 选择 + +## Boss 与 Claw 的边界 + +### Boss 继续负责 + +Boss 继续负责: + +- 会话模型 +- 项目归档 / 线程下钻 +- 群聊 +- 审批流 +- 设备导入 +- 提示词 / 记忆 +- 账本和聚合投影 +- 主控切换 +- 前台 Web / Android 交互 + +### `ClawBackendAdapter` 只负责 + +`ClawBackendAdapter` 只负责: + +- 接收标准化 `ExecutionRequest` +- 使用 `PromptAssembler` 产出的最终 prompt +- 调用外部 `claw-code` runtime +- 返回统一的 `ExecutionQueuedResult | ExecutionImmediateResult` + +## 接入模式 + +本轮采用 **本地可注入 backend** 模式,不采用“构建时自动拉仓库”。 + +原因: + +1. `claw-code` 上游还在持续快速更新 +2. 当前远端仓库存在重定向到 disabled 仓库的情况,不能把生产构建绑在它的可访问性上 +3. Boss 需要的是稳定 adapter,不是把上游源码写死进仓库 + +因此本轮的外部依赖方式是: + +- Boss 通过配置知道 `claw-code` 可执行入口在哪里 +- Boss 通过稳定协议调用它 +- 是否提供可执行文件、脚本或包装器,由本地环境决定 + +## 适配器协议 + +### 输入 + +`ClawBackendAdapter` 接收: + +- `ExecutionRequest` +- 由 `PromptAssembler` 生成的执行 prompt +- 模型覆盖 +- 推理强度覆盖 +- 目标项目/线程信息 + +### 输出 + +Boss 只认两种标准结果: + +1. `ExecutionImmediateResult` +2. `ExecutionQueuedResult` + +本轮默认优先实现: + +- `completed` +- `failed` + +如后续 `claw-code` 能稳定提供队列态或可恢复 session,再扩展为 `queued/running`。 + +### 建议协议形态 + +本轮建议适配器通过一个很薄的 CLI JSON 协议与 `claw-code` 对话: + +- 输入:JSON 文件或标准输入 +- 输出:JSON 到标准输出 + +最小输出结构: + +```json +{ + "status": "completed", + "output": "..." +} +``` + +失败时: + +```json +{ + "status": "failed", + "error": "..." +} +``` + +这样 Boss 不需要理解 `claw-code` 内部 Python/Rust 目录布局,只需要理解 adapter 协议。 + +## 新增抽象 + +### 1. `ClawBackendAdapter` + +建议位置: + +- `src/lib/execution/backends/claw-backend.ts` + +职责: + +- 读取本地 `claw` backend 配置 +- 判断当前请求是否可由 claw 处理 +- 调用 `claw` 可执行入口 +- 把结果映射成 Boss 的标准 `ExecutionResult` + +### 2. `ClawBackendConfig` + +建议位置: + +- `src/lib/execution/backends/claw-config.ts` + +字段至少包含: + +- `enabled` +- `command` +- `args` +- `cwd` +- `defaultModel?` +- `timeoutMs` + +说明: + +- `enabled=false` 时,该 backend 不进入 selector 候选 +- 配置缺失时要明确返回不可用,而不是隐式失败 + +### 3. `ClawInvocation` + +建议位置: + +- `src/lib/execution/backends/claw-runner.ts` + +职责: + +- 封装对外部 `claw-code` 进程的调用 +- 统一 stdin/stdout/stderr 处理 +- 做超时、退出码、JSON 解析 + +## Backend 选择规则 + +本轮 `ExecutionBackendSelector` 的扩展规则: + +1. 默认行为不变: + - `ready primary` + - 否则 `aliyun_qwen -> openai -> master_codex_node` + - 最后 primary 兜底 +2. `claw` 仅在显式启用时参与候选 +3. `claw` 只对这些请求种类可选: + - `master_agent_reply` + - `thread_reply` +4. `dispatch_execution` 当前仍优先沿用 Boss 既有链 +5. `approval_required` 等审批逻辑不下沉给 `claw` + +本轮推荐规则: + +- 不改变当前默认优先级 +- `claw` 通过会话级或账户级显式开关进入可选范围 +- 只有当用户或管理员明确选择 `claw` 作为当前对话 backend 时才启用 + +## 配置来源 + +本轮不做复杂后台页面,先允许通过运行时配置启用: + +- 本地环境变量 +- 服务器环境变量 +- 后续再补 Web 后台 + +建议字段: + +- `BOSS_CLAW_ENABLED` +- `BOSS_CLAW_COMMAND` +- `BOSS_CLAW_ARGS` +- `BOSS_CLAW_WORKDIR` +- `BOSS_CLAW_TIMEOUT_MS` + +说明: + +- 如果只配置 `enabled=true`,但没有 `command`,adapter 必须明确报错不可用 +- 不允许“半启用”状态默默进入生产回退链 + +## 回退策略 + +`ClawBackendAdapter` 的失败不能把主链拖死。 + +必须遵守: + +1. 若 `claw` 不可用: + - selector 视其为不可选 +2. 若 `claw` 调用失败: + - 记录失败 + - 返回标准错误 + - 允许 Boss 按现有链路继续回退 +3. 不允许把 `claw` 的内部 stderr 直接原样暴露成产品态文案 +4. 需要生成人类可读错误摘要 + +## 测试要求 + +本轮至少补以下测试: + +1. `ClawBackendAdapter` 在未启用配置时不可选 +2. 配置完整时,`canHandle(master_agent_reply)` 返回 true +3. 配置完整时,`canHandle(dispatch_execution)` 仍返回 false +4. 适配器能把外部 JSON 成功结果映射成 `completed` +5. 适配器能把非零退出码或非法 JSON 映射成 `failed` +6. selector 在 `claw` 未启用时行为不变 +7. selector 在 `claw` 启用且显式选中时,会优先选 `claw` + +## 文档更新要求 + +实现完成后,需要同步更新: + +- `README.md` +- `docs/architecture/current_runtime_and_deploy_status_cn.md` +- `docs/architecture/api_and_service_inventory_cn.md` + +必须明确写: + +- `claw-code` 已接入为可选执行 backend +- 当前默认主链仍不是 `claw` +- 当前接入范围只覆盖单次执行,不覆盖群聊编排和审批 + +## 结论 + +本轮最重要的不是“让 Boss 立即切到 claw”,而是: + +- 先把 `claw-code` 放到 Boss 的稳定 adapter 边界内 +- 让它成为一个真正可插拔、可升级、可回退的执行 backend + +这样后续 `claw-code` 继续迭代时,Boss 主要升级的是 adapter,而不是重写产品主链。