Subtract dead agent husks and unify the gateway executor path.

Remove SpecialistAgentRunner, plan_agent_v2 re-export shims, empty runtime husks, and disconnected Admin knobs. Fold ops into build_gateway_executor, align AIA_ENABLE_PLUGIN_TOOLS with catalog, and allow ops on the default MCP specialist list.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
oliver 2026-08-11 01:02:29 +08:00
parent e2fc72607e
commit 628a9dffd2
32 changed files with 127 additions and 870 deletions

View file

@ -6,27 +6,38 @@
- `runtime/`:运行时主域(agent、gateway 执行流、skills/hooks/extensions、operations)。
- `interfaces/`:对外接口层(HTTP、WS、Admin、Gateway method bridge)。
- `platform/`:通用平台能力(配置、存储、LLM transport、文件层)。
- `runtime/workspaces/_system/`:内置系统提示词 Markdown 树(原顶层 `prompts/`,与按角色分区的 `workspaces/<role>/` 并列);`runtime/prompt_templates/` 为加载与 frontmatter 解析。
- `svc/`:通用平台能力(配置、存储、LLM transport、文件层)。
- `runtime/workspaces/_system/`:内置系统提示词 Markdown 树(与按角色分区的 `workspaces/<role>/` 并列);`runtime/prompt_templates/` 为加载与 frontmatter 解析。
- `tests/`:测试代码(按你的要求保持顶层)。
- `docs/`:设计文档、运维说明、迁移记录。
## 现行 Agent 脊梁
```text
interfaces (HTTP/WS/Admin/channel)
→ OclawGateway.handle_turn
→ run_agent_core → run_direct_loop
→ SkillExecutor / ToolExecutor → ToolRegistry (MCP/public/expert/plugin)
→ SqliteStore → outbound
```
工厂入口:`runtime/agents/factory.py::build_gateway_executor`(按 specialist 构建 `Agent`)。
## runtime 内部建议边界
- `runtime/core/`:可复用执行内核(如 agent 执行管线聚合入口)。
- `runtime/app/`:应用侧入口组织(面向外部流程的 runtime 编排)。
- `runtime/agents|chat|orchestration|workers`:领域能力模块。
- `runtime/application/gateway/`:渠道入站用例(WhatsApp/Weixin/WeCom)。
- `runtime/agents|chat|orchestration`:领域能力模块。
- `skills/`、`runtime/hooks`、`runtime/extensions`:可扩展能力载体(技能包在仓库根 `skills/`)。
- `runtime/operations/scripts`:运维脚本与生成器。
## 路径规范
- 运行时资源路径统一通过 `platform/config/runtime_paths.py` 获取。
- 运行时资源路径统一通过 `svc/config/runtime_paths.py` 获取。
- 禁止新增硬编码目录字符串(如直接拼 `oclaw/runtime/...`)。
## 依赖方向(原则)
- `interfaces -> runtime -> platform`(尽量单向)。
- `interfaces -> runtime -> svc`(尽量单向)。
- `runtime` 不反向依赖 `interfaces`(必要时通过协议/回调解耦)。
- `docs/tests` 可依赖任意层,但不应反向影响运行时代码设计。

View file

@ -18,18 +18,12 @@
- `AIA_ASSISTANT_MODE`
- 默认:空(代码内决定默认模式)
- 作用:助手模式选择
- 生效:`oclaw/platform/llm/chat_models.py`, `oclaw/runtime/agents/factory.py`
- `AIA_MANAGER_DECISION_MODE`
- 默认:空
- 作用:**Legacy(已断开)**:旧 manager 决策模式(如 `rule`)
- 说明:oclaw runtime 默认不再走 `CompositeOpsAgent` 的 manager 决策;该变量仅保留以便后续接回 legacy
- 生效:`oclaw/runtime/agents/manager_agent.py`(仅 legacy 链路)
- 生效:`svc/llm/chat_models.py`, `runtime/agents/factory.py`
- `AIA_TURN_MAX_TOOL_WORKERS`
- 默认:`8`
- 作用:单轮工具并发上限
- 生效:`oclaw/oclaw_runtime/gateway.py`, `oclaw/oclaw_runtime/direct_loop.py`
- 生效:`runtime/gateway.py`, `runtime/direct_loop.py`
- `AIA_TURN_MAX_TOOL_ROUNDS`
- 默认:`100`
@ -95,28 +89,7 @@
- 默认:`0`
- 作用:控制 Admin 保存 `AIA_OCLAW_RETRYABLE_ERROR_CODES` 时的未知 code 行为
- 说明:`0`=过滤并告警;`1`=直接拒绝保存(HTTP 400)
- 生效:`oclaw/interfaces/admin/routes.py`, `oclaw/interfaces/admin/static/app.js`
- `AIA_TOOL_ENFORCED_RETRY_MODE`
- 默认:`first_round_only`
- 作用:**Legacy(已断开)**:工具必需场景下的强制重试策略
- 生效:仅 legacy 链路(保留占位,暂不影响 oclaw)
- `AIA_TOOL_LOOP_STATE_MACHINE`
- 默认:`1`
- 作用:**Legacy(已断开)**:工具循环状态机开关
- 生效:仅 legacy 链路(保留占位,暂不影响 oclaw)
- `AIA_TOOL_SIGNATURE_BUDGET`
- 默认:`2`
- 作用:**Legacy(已断开)**:同签名工具调用预算
- 生效:仅 legacy 链路(保留占位,暂不影响 oclaw)
- `AIA_OCLAW_ALLOW_LEGACY_FALLBACK`
- 默认:`0`(关闭)
- 作用:oclaw 执行失败时,是否允许回退到 legacy `executor.run_turn(...)`
- 说明:默认 fail-closed(不回退),避免无意中触发旧 manager/runner
- 生效:`oclaw/oclaw_runtime/gateway.py`, `oclaw/runtime/agents/specialist_agent.py`
- 生效:`interfaces/admin/routes.py`, `interfaces/admin/static/app.js`
## LLM 传输与 replay(OpenAI 兼容)
@ -162,26 +135,26 @@
## 工具执行与安全
- `AIA_DISABLE_TOOL_CONFIRM`
- 默认:`0`
- 作用:**Legacy(已断开)**:是否禁用高风险工具确认
- 说明:oclaw 工具执行已移除执行时确认策略;该变量保留以便后续接回 legacy
- 生效:仅 legacy 链路(保留占位)
- `AIA_ENABLE_MCP_TOOLS`
- 默认:`1`
- 作用:启用 MCP 工具
- 生效:`oclaw/tools/catalog.py`
- 生效:`runtime/tools/catalog.py`
- `AIA_ENABLE_PLUGIN_TOOLS`
- 默认:`0`
- 作用:启用插件工具
- 生效:`oclaw/tools/catalog.py`
- 默认:`1`(未设置时开启;Admin 可关)
- 作用:启用 Python 扩展插件工具
- 说明:与历史别名 `AIA_PLUGIN_TOOLS_ENABLED` 等价;Admin DB 设置优先
- 生效:`runtime/tools/catalog.py`, `interfaces/admin/routes.py`
- `AIA_PLUGIN_TOOLS_ENABLED`
- 默认:同 `AIA_ENABLE_PLUGIN_TOOLS`
- 作用:**别名**(兼容旧 env);新代码请用 `AIA_ENABLE_PLUGIN_TOOLS`
- 生效:`runtime/tools/catalog.py`
- `AIA_ENABLE_RUN_COMMAND`
- 默认:`0`
- 作用:允许高风险 `run_command` 工具
- 生效:`oclaw/tools/catalog.py`, `oclaw/tools/experts/workspace/shell_tools.py`
- 生效:`runtime/tools/catalog.py`, `runtime/tools/experts/workspace/shell_tools.py`
- `AIA_TOOL_LLM_MESSAGE_MAX_CHARS`
- 默认:`0`(不限制)
@ -247,9 +220,9 @@
## MCP 与工具线侧
- `AIA_MCP_SPECIALISTS`
- 默认:`generalist`
- 作用:允许使用 MCP 的 specialist 列表
- 生效:`oclaw/tools/mcp/adapter.py`
- 默认:`generalist,manager,ops`
- 作用:未配置 `mcp_specialist_server_binding` 时,允许使用 MCP 的 specialist 列表
- 生效:`runtime/tools/mcp/adapter.py`
- `AIA_MCP_ENV_ALLOWLIST`
- 默认:未设置时使用内置补充名单(仅用于**未**出现在 `mcp_local.env` 里、但要从宿主环境透传的变量名,见 `mcp_env._DEFAULT_ALLOWLIST`)

View file

@ -26,7 +26,7 @@
4. **有图**:调用 **`send_legacy_image_messages`**(`/chat/completions` 兼容路径,非 Responses API)。
5. **输出解析**:**`legacy_image_turn_bundle`**
- 文本可为空;若有生成图则 **`materialize_legacy_response_output_attachments`** 写入本地 blob,产出 **`image_ref`**(或退化为 **`image_url`**)。
6. **占位文案**:成功但只有图、无模型正文时,由 **`legacy_image_assistant_body_with_placeholder`**(`image_legacy_client`)写入中英文占位句;网关与 `specialist_agent` 共用,避免两处字符串分叉。
6. **占位文案**:成功但只有图、无模型正文时,由 **`legacy_image_assistant_body_with_placeholder`**(`image_legacy_client`)写入中英文占位句;与 `direct_loop` early-exit 共用。
7. **持久化**:**`store.add_message(role=assistant, event_type=assistant_text, attachments=…)`** —— 附件以 JSON 形式挂在助手消息上,而非 tool 行。
---
@ -36,7 +36,7 @@
| 场景 | 模块 | 说明 |
|------|------|------|
| Chat 网关 + 图片专家 | `direct_loop._maybe_image_specialist_legacy_gateway_turn` | 上文主路径;Early Return,不进主 LLM 循环。 |
| Specialist 编排临时会话 | `runtime/agents/specialist_agent.py` | 同样调用 `send_legacy_image_messages` / `legacy_image_turn_bundle`,逻辑对齐但不经过同一 Early Return。 |
| Gateway early-exit | `runtime/direct_loop.py` | Image specialist 走 legacy HTTP lane,不经过 Responses 协议。 |
两处共用 **`platform/llm/image_legacy_client.py`**,避免分叉实现。
@ -78,7 +78,7 @@
## 8. 变更原则(避免波及其它链路)
1. **默认改动范围**:`image_legacy_client.py`、`image_http_common.py`、`direct_loop` 中 **`_maybe_image_specialist_*` 函数体**、`specialist_agent` 中与 legacy image 调用相邻代码、`turn_runner` / `chat.js` 中与 **assistant + attachments** 展示相邻逻辑。
1. **默认改动范围**:`image_legacy_client.py`、`image_http_common.py`、`direct_loop` 中 **`_maybe_image_specialist_*` 函数体**、`turn_runner` / `chat.js` 中与 **assistant + attachments** 展示相邻逻辑。
2. **勿在** `openai_responses.py` **中为图片专家单独分支**,除非明确要做「非 legacy」通用能力。
3. 新增开关优先 **`AIA_IMAGE_*` / `AIA_IMAGE_SPECIALIST_*`**,勿复用 OCR 变量。
4. UI 层附件渲染:**assistant_text 与 tool_result** 对称处理引用型附件,避免只修一端。

View file

@ -27,7 +27,7 @@
5. **调用**:`send_video_generation_request` — `POST .../video-synthesis`(`X-DashScope-Async: enable`),再轮询 **`GET .../api/v1/tasks/{task_id}`** 直至 `SUCCEEDED` / 失败 / 超时。
6. **输出**:成功时从 `output.video_url` 下载为本地 blob,产出 **`video_ref`**;下载失败时退化为仅带 **`url`** 的 `video_ref` 行(前端仍可尝试外链播放)。
7. **占位文案**:`legacy_video_assistant_body_with_placeholder` 与图片专家对称(仅附件、无正文时插入中英文短句)。
8. **编排**:`runtime/agents/specialist_agent.py` 在 `step.specialist == "video"` 时调用同一客户端(按父任务附件 + 父会话历史解析首帧),保证综合模式子专家与专家模式行为一致。
8. **编排**:video specialist 在 `direct_loop` early-exit 中调用同一客户端;综合模式经 gateway 选中 video specialist 后走同一路径。
---
@ -64,5 +64,5 @@
## 8. 变更原则
1. 默认只改 **`video_generation_client.py`**、`direct_loop` 的 **`_maybe_video_specialist_*`**、`specialist_agent` 视频分支、`factory` / `gateway` 白名单、**`chat.js`** 附件展示、本文与 **`ENVIRONMENT_VARIABLES.md`**。
1. 默认只改 **`video_generation_client.py`**、`direct_loop` 的 **`_maybe_video_specialist_*`**、`factory` / `gateway` 白名单、**`chat.js`** 附件展示、本文与 **`ENVIRONMENT_VARIABLES.md`**。
2. 勿在通用 **`openai_responses`** 中为视频专家单独绕路,除非产品明确要求统一传输。

View file

@ -1,36 +0,0 @@
# Plan Agent V2 Gateway Cutover Draft
## Purpose
- Provide a minimal, reviewable gateway cutover sketch without changing production routing yet.
- Keep existing `runtime/gateway.py` behavior unchanged until explicit cutover approval.
## Draft Helper
- New module:
- `runtime/plan_agent_v2_gateway_cutover.py`
- Entrypoint:
- `maybe_handle_expert_turn_v2_draft(...)`
## Draft Behavior
- If v2 shadow is not selected:
- returns `handled=False`, gateway should continue legacy flow.
- If decision is `enter_plan` or `stay_plan`:
- returns `handled=True` with an `OclawGatewayResult` built from v2 shadow compatibility mapper.
- If decision is `run_agent`:
- returns `handled=False` and provides `system_prompt_override`.
- gateway would continue legacy execution path but with injected approved-plan context.
## Why This Is Safe
- No import or call-site changes in `runtime/gateway.py` yet.
- Feature remains effectively dormant unless future cutover patch wires this helper.
- Existing tests continue to validate legacy and shadow independently.
## Future Minimal Cutover (single commit)
- In `OclawGateway.handle_turn(...)` expert path, add one early branch:
1) call `maybe_handle_expert_turn_v2_draft(...)`
2) if `handled=True`, return result immediately
3) else continue existing flow; if `system_prompt_override` exists, use it as specialist system prompt
## Rollback
- Revert only the gateway wiring commit.
- Keep shadow modules and tests as dormant assets.