advance 1-8 post-mvp execution batches
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
# Batch J Worker A:旧 HTTP proxy / page AI fallback 调用链审查
|
||||
|
||||
> 创建时间:2026-05-21
|
||||
>
|
||||
> 只读审查,不修改代码。
|
||||
|
||||
## 1. 读取过的关键文件
|
||||
|
||||
| 文件 | 行数 | 内容 |
|
||||
|------|------|------|
|
||||
| `rust/crates/mnote-web/src/routes/hermes_client.rs` | 8202 | 首页面 AI Hermes 路由:session/run/tool 的 proxy 和 ACP 双路径 |
|
||||
| `rust/crates/mnote-web/src/page_ai_workflow.rs` | — | **不存在**(不在根目录,在 `routes/` 下) |
|
||||
| `rust/crates/mnote-web/src/routes/page_ai_workflow.rs` | 500+ | 页面 AI block-edit fast path |
|
||||
| `rust/crates/mnote-web/src/acp_runtime.rs` | 500+ | ACP runtime manager |
|
||||
| `rust/crates/mnote-web/src/acp_session_manager.rs` | 700+ | ACP session lifecycle |
|
||||
| `rust/crates/mnote-web/src/routes/mod.rs` | 200+ | 全路线由注册 |
|
||||
| `rust/crates/mnote-web/src/routes/compat.rs` | 200+ | 旧 `/api/ai-agent/run` 退役 guard |
|
||||
|
||||
## 2. 调用链分析
|
||||
|
||||
### 2.1 旧 HTTP proxy 路径
|
||||
|
||||
**判断函数:** `hermes_client.rs:2844` `hermes_http_proxy_enabled()`
|
||||
|
||||
```rust
|
||||
fn hermes_http_proxy_enabled() -> bool {
|
||||
["MNOTE_WEB_ENABLE_HERMES_HTTP_PROXY", "MNOTE_ENABLE_HERMES_HTTP_PROXY"]
|
||||
.into_iter().find_map(env_or_dotenv)
|
||||
.map(|v| matches!(v.trim().to_ascii_lowercase(), "1" | "true" | "yes"))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
```
|
||||
|
||||
**默认关闭**(`unwrap_or(false)`)。HTTP proxy 仅在显式设 `MNOTE_WEB_ENABLE_HERMES_HTTP_PROXY=true` 时启用。
|
||||
|
||||
**上游 URL 来源:** `configured_upstream()`(`hermes_client.rs:2813`)
|
||||
|
||||
- 检查 `MNOTE_WEB_HERMES_UPSTREAM_URL` → `MNOTE_HERMES_UPSTREAM_URL` → `MNOTE_HERMES_API_BASE_URL`
|
||||
- 均不存在时返回 `None`
|
||||
|
||||
**`is_acp_profile()` 路由逻辑**(`hermes_client.rs:2871`):
|
||||
|
||||
```rust
|
||||
fn is_acp_profile(profile: &str) -> bool {
|
||||
if !hermes_http_proxy_enabled() { return true; } // 默认全走 ACP
|
||||
if profile == "reasonix" || profile == "hermes" { return true; }
|
||||
// 还可通过 MNOTE_WEB_{PROFILE}_RUNTIME_TYPE=acp 环境变量控制
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
### 2.2 各路由入口分类
|
||||
|
||||
| Route | Handler | HTTP proxy 条件 | 默认走 | 分类 |
|
||||
|-------|---------|-----------------|--------|------|
|
||||
| `GET /client/sessions` | `list_sessions` | `!is_acp_profile(profile) && configured_upstream_for_profile(profile).is_some()` | **ACP** | `compat` |
|
||||
| `GET /client/sessions/search` | `search_sessions` | 同上 | **ACP** | `compat` |
|
||||
| `GET /client/gateway/health` | `gateway_health` | `!is_acp_profile(&profile)` → HTTP proxy | **ACP**(对于非 ACP profile 走 HTTP proxy) | `compat` |
|
||||
| `POST /client/runs` | `create_run` | `configured_upstream_for_profile(®istration.profile).is_some()` | **ACP** | `compat` |
|
||||
| `GET /client/events/{run_id}` | `stream_events` | 先查 `acp_runtime_for_run()`,再 fallback `configured_upstream_for_profile()` | **ACP** | `compat` |
|
||||
| `POST /client/runs/{run_id}/abort` | `abort_run` | 同上 | **ACP** | `compat` |
|
||||
| `GET /client/models` | `list_models` | 直接 `configured_upstream()` | HTTP proxy(与 ACP 无关的 model 列表) | `compat` |
|
||||
| 队列自动处理 | `auto_start_next_queued_run`(line 5377) | `configured_upstream_for_profile(queued.profile)` | **ACP** | `compat` |
|
||||
| `POST /api/ai-agent/run` | `compat::next_ai_agent_run` | — | **始终返回 410 GONE** | `retired` |
|
||||
| `POST /api/page-ai/block-edit-workflow` | `page_ai_workflow::block_edit_workflow` | 绕过 ACP,直接调模型 API + `execute_mnote_tool_call` | debug-only fast path | `debug-only` |
|
||||
|
||||
### 2.3 page_ai_workflow 是否绕过 ACP / tool executor?
|
||||
|
||||
**调用链:**
|
||||
|
||||
```
|
||||
POST /api/page-ai/block-edit-workflow
|
||||
→ looks_like_block_edit(message) ← 中文关键词匹配
|
||||
→ call_block_edit_model() ← 直调 DeepSeek/etc API(HTTP)
|
||||
→ extract_markdown_plan_from_model_text()
|
||||
→ 构造 ToolCallInput { tool_name: "mnote.doc.markdown_edit", capability_scope: ["block.write","page.write"], ... }
|
||||
→ hermes_tools::execute_mnote_tool_call() ← 共享 tool executor
|
||||
→ is_mnote_tool_disabled() & ensure_write_authorized() & 实际执行
|
||||
```
|
||||
|
||||
**结论:**
|
||||
|
||||
1. **不经过旧 HTTP proxy** ✓ — 没有调用 `configured_upstream_for_profile`
|
||||
2. **不经过 ACP session manager** — 直接调用 `execute_mnote_tool_call`,没有 `session/new` + `session/prompt` 生命周期
|
||||
3. **但经过共享 tool executor** — 受 `is_mnote_tool_disabled()`、`ensure_write_authorized()`、`is_shared_read_scope()` 等守卫保护
|
||||
4. **设计意图**:`7-15` 设计文档说明 "local-first 普通正文编辑默认不经过它",该路径是给合模型快速做 search/replace 块编辑的 fast path,不是常规 AI 执行路径
|
||||
|
||||
### 2.4 `compat::next_ai_agent_run` 状态
|
||||
|
||||
`routes/compat.rs:10` 的 `next_ai_agent_run()` 始终返回 `410 GONE` + 消息"旧 /api/ai-agent/run 页面 AI 主链已退场"。**已确认退役**,无 P0 风险。
|
||||
|
||||
## 3. 各入口分类汇总
|
||||
|
||||
| 分类 | 条目 | 说明 |
|
||||
|------|------|------|
|
||||
| `default` | 无 | HTTP proxy 默认关闭;ACP 是默认 runtime |
|
||||
| `compat` | `list_sessions`, `search_sessions`, `gateway_health`, `create_run`, `stream_events`, `abort_run`, `list_models`, 队列处理 | 仅当 `MNOTE_WEB_ENABLE_HERMES_HTTP_PROXY=true` 时激活;不影响正常用户 |
|
||||
| `debug-only` | `page_ai_workflow::block_edit_workflow` | bypass ACP session,但受工具 executor 守卫保护 |
|
||||
| `retired` | `compat::next_ai_agent_run` | 已返回 410,无降级路径 |
|
||||
| `未被调用` | `configured_runtime_for_profile()`(line 3368) | 标记 `#[allow(dead_code)]` |
|
||||
|
||||
## 4. P0 缺口评估
|
||||
|
||||
**当前没有 P0 必须修复的缺口。**
|
||||
|
||||
理由:
|
||||
1. HTTP proxy 默认关闭(`hermes_http_proxy_enabled() = false`)
|
||||
2. `compat::next_ai_agent_run` 已正确返回 410
|
||||
3. `page_ai_workflow` 经过共享 tool executor 守卫,不绕过权限检查
|
||||
4. 所有路由的第一分支都是 ACP
|
||||
|
||||
## 5. 建议的后续修改范围
|
||||
|
||||
| 项 | 建议 | 紧急程度 |
|
||||
|----|------|---------|
|
||||
| HTTP proxy 完整退役 | 删除 `configured_upstream()` / `configured_upstream_for_profile()` / `proxy_json()` 相关代码 | P2(cleanup) |
|
||||
| `list_models` 从 HTTP proxy 迁移 | 改为 ACP 的 `session/initialize` 返回 model 信息 | P2(依赖 ACP 协议增强) |
|
||||
| `page_ai_workflow` 检查驱动 | 确保测试覆盖其 bypass ACP session 的行为的非期望路径(`task-page-block-ai-smoke.js` → 已存在) | 已有 |
|
||||
| 旧环境变量清理 | 文档标记 `MNOTE_WEB_HERMES_UPSTREAM_URL` 等为退役 | P2 |
|
||||
|
||||
## 6. 建议测试
|
||||
|
||||
```
|
||||
# 确认 HTTP proxy 默认关闭(infra 测试)
|
||||
cd /mnt/Data1T/mnote/rust && cargo test -p mnote-web hermes_http_proxy -- --test-threads=1
|
||||
|
||||
# 确认 compat 路由返回 410(已存在)
|
||||
cd /mnt/Data1T/mnote/rust && cargo test -p mnote-web direct_ai_agent_run_returns_legacy_retired_guard -- --test-threads=1
|
||||
|
||||
# 确认 page_ai_workflow 受守卫保护(已存在)
|
||||
cd /mnt/Data1T/mnote/rust && cargo test -p mnote-web block_edit_workflow_respects_disabled_markdown_edit_tool -- --test-threads=1
|
||||
```
|
||||
Reference in New Issue
Block a user