Files
mnote/design/07-ai/process/7-61-yuxi-reference-middleware-extensions-dashboard-v1.md
T

495 lines
25 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 7-61 [process] Yuxi reference: middleware tool composition, extensions entry, knowledge settings UI, and local dashboard v1
> 2026-06-28 覆盖说明:本文中 Hermes / LightRAG 相关实现口径已部分退为 legacy。仍可参考 Yuxi 的 middleware、extensions 入口和 dashboard 信息架构,但当前 MNote 知识库 / agent 主线以 OpenHub / opencode / WeKnora 为准。
> 创建时间:2026-06-13
>
> 当前状态:`PROCESS`
>
> Owner07-ai / 03-rust-web / Hermes tools / Page AI settings / Knowledge RAG UI / Dashboard
>
> 上位设计:`design/07-ai/done/7-57-yuxi-reference-ai-run-config-knowledge-facade-v1.md`
>
> 本稿是 7-57 的补充,覆盖 7-57 未涉及的 Yuxi 参考领域。
>
> 参考代码:
> - `reference-code/Yuxi/backend/package/yuxi/agents/middlewares/`(中间件分层组合)
> - `reference-code/Yuxi/backend/package/yuxi/agents/base.py`Agent 基类 + checkpointer
> - `reference-code/Yuxi/web/src/views/ExtensionsView.vue`(扩展统一入口)
> - `reference-code/Yuxi/web/src/views/DataBaseInfoView.vue`(知识库详情页)
> - `reference-code/Yuxi/web/src/views/DashboardView.vue`Dashboard 可观测性)
> - `reference-code/Yuxi/web/src/composables/useAgentStreamHandler.js`(流式事件状态机)
> - `reference-code/Yuxi/backend/package/yuxi/agents/backends/sandbox/paths.py`(虚拟路径安全)
>
> 上位依据:
> - `ARCHITECTURE.md`
> - `CURRENT_ARCHITECTURE.md`
> - `design/07-ai/done/7-50-lightrag-knowledge-rag-provider-v1.md`
> - `design/07-ai/done/7-57-yuxi-reference-ai-run-config-knowledge-facade-v1.md`
> - `design/07-ai/process/7-18-local-first-agent-file-editing-control-plane-v1.md`
> - `design/03-rust-web/reference/3-23-sidebar-local-folder-resource-runtime-followup-v1.md`
> - `design/10-review/done/16-mnote-web-runtime-module-maintainability-checklist-v1.md`
## 1. 第一结论
Yuxi 有六个工程模式值得 MNote 借鉴,但不适合整体搬移:
1. **中间件分层工具组合**Hermes tool manifest 当前是扁平 Vec<Value>,每次新增能力(knowledge base、skills、MCP、filesystem、subagent、summary)都在同一个 manifest 函数中线性追加。Yuxi 的 middleware 模式把每种能力作为独立层,按需组合。
2. **扩展管理统一入口**:当前 MNote 的 Skills/MCP/Knowledge Base/Tools 入口分散在 settings、Page AI settings、侧边栏等不同位置。Yuxi 的 `ExtensionsView` 用 tab 统一管理所有扩展。
3. **知识库详情设置页**:当前 LightRAG settings 较薄,只有 source directory 和 basic status。Yuxi 的 `DataBaseInfoView` 提供了文件管理、检索配置、图谱配置、评估等完整详情页。
4. **流式事件状态机规范化**:当前 Hermes SSE/WS 事件处理分散在多个 consumersidebar runtime、document adapter、Page AI sidebar)。Yuxi 的 `handleStreamChunk` 是单一状态机,覆盖 init→loading→stream_event→finished/interrupted/error 全生命周期。
5. **本地 Dashboard**:当前 MNote 没有本地可观测性面板。Yuxi 的 Dashboard 提供了 agent run 调用量、token 消耗、知识库检索次数、工具调用频率等可视化。
6. **虚拟路径安全**:当前 `WorkspacePath` 校验较松散。Yuxi 的 sandbox paths 有 `validate_thread_id` + `relative_to` 防穿越、虚拟路径前缀隔离、按 thread/user 分层。
这些都属于 MNote 现有主线的 enhancer,不改变底层(Hermes ACP / Reasonix / LightRAG / Rust SSR),不引入新存储或新 agent 框架。
## 2. 非目标
- 不引入 LangGraph / DeepAgents 作为 agent runtime。
- 不复制 Yuxi 的 Milvus / Neo4j / Postgres 存储体系。
- 不把 Vue/Ant Design 前端模式迁入 Rust SSR / browser runtime。
- 不改变 LightRAG 作为唯一知识库 provider 的定位。
- 不新增定时轮询刷新。
- 不改变 local-first 普通 Markdown 编辑主路径。
- 不改变 7-57 已完成的 run journal / agent descriptor / knowledge facade 成果。
## 3. 六个借鉴领域详析
### 3.1 中间件分层工具组合
**Yuxi 模式**
```python
class ChatbotAgent(BaseAgent):
async def get_graph(self, context=None, **kwargs):
middlewares = [
create_agent_filesystem_middleware(...), # 文件系统
save_attachments_to_fs, # 附件落地
KnowledgeBaseMiddleware(), # 知识库检索
SkillsMiddleware(), # Skills 注入
create_subagent_task_middleware(context), # 子智能体
summary_middleware, # 上下文压缩
TodoListMiddleware(...), # 任务列表
PatchToolCallsMiddleware(), # 工具调用修复
ModelRetryMiddleware(max_retries=2), # 模型重试
]
return create_agent(model=..., tools=..., middleware=middlewares, ...)
```
每个中间件是独立类/函数,按声明顺序构成 agent 的能力栈。新增能力只需新增一个 middleware,不改动 agent 核心流程。
**MNote 当前状态**
`manifest.rs` 中 Hermes tool manifest 是扁平 `Vec<Value>`,约 30+ 个工具在一个函数中线性追加。新增 knowledge_rag、skills、context、block、onlyoffice 等工具时,每次都在同一个 manifest 函数末尾追加,没有按能力域分组。
```rust
pub fn manifest() -> Value {
let tools = annotate_tools_with_capabilities(vec![
skill_read_tool(),
context_snapshot_tool(),
// ... 30+ tools
available_tool("mnote.artifact.create_summary", ...),
]);
// ...
}
```
**借鉴方向**
不是引入 Python 式 class middleware,而是把 Rust manifest 按能力域拆成独立 registry 模块,每个模块自声明工具和能力:
```text
hermes_tools/
manifest.rs → 顶层装配,组合各 registry
registry/
context_registry.rs → context.* 工具组
doc_registry.rs → mnote.doc.* 工具组
block_registry.rs → mnote.block.* 工具组
page_registry.rs → mnote.page.* 工具组
knowledge_rag_registry.rs → mnote.knowledge_rag.* 工具组
skill_registry.rs → mnote.skill.* 工具组
mindmap_registry.rs → mindmap.* 工具组
onlyoffice_registry.rs → onlyoffice.* 工具组
artifact_registry.rs → mnote.artifact.* 工具组
```
每个 registry 暴露 `pub fn tools() -> Vec<Value>``pub fn capabilities() -> Vec<&'static str>`。manifest 只负责装配和 capability annotation。Agent descriptor 可以按 capability 选择性包含工具组。
### 3.2 扩展管理统一入口
**Yuxi 模式**
`ExtensionsView.vue` 用一个 tab 组件统一管理四种扩展:
```
智能体扩展
├── 知识库(管理员可见)
├── 工具(管理员可见)
├── MCP(管理员可见)
└── Skills(所有用户可见)
```
每种扩展是独立子组件,通过 tab 切换懒加载。URL query 参数持久化当前 tab,刷新后不丢失。
**MNote 当前状态**
- Skills 入口:Page AI settings → Skills 子面板
- Knowledge base 入口:settings → 资料库 settings
- MCPHermes MCP 配置在 Hermes workspace settings
- Tools:无独立管理入口,Hermes tool manifest 是编译期静态
这四个入口分散在不同 settings surface,用户需要记住去哪找。
**借鉴方向**
在 settings 页面增加"扩展"tab(或在现有 settings IA 中统一),按权限分组:
```text
设置
├── 通用
├── 外观
├── 编辑器
├── 扩展 ← 新增
│ ├── 知识库(LightRAG 资料库管理)
│ ├── Skills(已安装 + 可用)
│ ├── MCP 服务器
│ └── Agent 工具状态(只读能力清单)
├── AIHermes / Reasonix 配置)
└── 关于
```
第一阶段不要求完整 CRUD,先做只读能力清单 + 已安装 Skills/MCP 状态展示 + 知识库详情入口。URL hash 持久化当前 tab。
### 3.3 知识库详情设置页
**Yuxi 模式**
`DataBaseInfoView.vue` 是知识库详情页,子 tab 包括:
- **文件管理**:文件夹树、上传、解析状态跟踪(pending/processing/done/error)、批量删除、文件预览
- **检索测试**:输入 query → 展示检索结果 + 相似度分数 + 来源文件
- **检索配置**:向量/BM25/混合检索模式选择、TopK、相似度阈值、BM25 权重
- **图谱配置**:实体抽取 schema、关系类型约束
- **评估**:检索质量评估、问答对测试
- **设置**:名称、描述、嵌入模型、分块策略、共享配置
**MNote 当前状态**
LightRAG settings 较薄,只有:
- source directory 配置
- ingest 触发按钮
- 基本状态灯(indexed / pending
- OCR 开关
**借鉴方向**
在不改变 LightRAG provider 的前提下,增强 knowledge base settings UI
1. **文件管理面板**:展示已 ingest 文件列表、解析状态(parsing/chunking/indexing/done/error)、文件类型图标、最后更新时间
2. **检索测试面板**:输入 query → 直接调 `/api/knowledge-rag/search` → 展示 top-K 结果 + citation preview + 来源文件 + 相关度
3. **检索参数配置**search modelocal/global/hybrid/naive/mix)、top_k、相似度阈值(expose LightRAG `QueryParam` 可配置项)
4. **Ingest 状态跟踪**:LightRAG 后台完成状态通过现有 status bridge/backoff 同步到 UI,展示每个文件的 stage 和 error
不新增:
- 分块策略 UI(由 LightRAG 管)
- 图谱 schema 编辑(由 LightRAG 管)
- 嵌入模型切换(由 LightRAG 管)
### 3.4 流式事件状态机规范化
**Yuxi 模式**
`useAgentStreamHandler.js``handleStreamChunk` 是一个规范的状态机:
```
┌─────────────────────────────────────────────┐
│ stream start │
└─────────────────┬───────────────────────────┘
┌────────────▼────────────┐
│ init │ ← 建立 request_id 绑定
│ → replyLoadingVisible │
└────────────┬────────────┘
┌────────────▼────────────┐
│ loading │ ← message_delta / tool_call_delta
│ → push msgChunks │
└────────────┬────────────┘
┌────────────▼────────────┐
│ stream_event │ ← tool-started / tool-finished
│ → 关联 tool_call_id │ agent_state (todos/uploads)
└────────────┬────────────┘
┌────────────▼────────────┐
│ finished / interrupted │ ← terminal
│ / error / approval │
└──────────────────────────┘
```
关键设计点:
- 每种 status 有明确的过渡规则
- `stream_event` 中的 `tool-finished` 通过 `tool_call_id` 关联到对应 AI 消息
- `agent_state` 事件同步 todos/uploads 等运行时状态
- 中断(approval/interrupted)有独立的恢复路径
**MNote 当前状态**
Hermes SSE/WS 事件处理分散在多个 consumer:
- `sidebar-page-ai-runtime.js` 处理 Page AI 面板的流式回复
- `document-editor-adapter-runtime.js` 处理编辑器内的 agent 交互
- 每个 consumer 有自己的事件解析和状态管理
**借鉴方向**
不是引入 Vue composable,而是在 browser runtime 中抽出一个共享的 `AgentStreamEventRouter`
```javascript
// rust/crates/mnote-web/browser/agent-stream-event-router.js
const EVENT_STATES = {
INIT: 'init',
LOADING: 'loading',
STREAM_EVENT: 'stream_event',
FINISHED: 'finished',
INTERRUPTED: 'interrupted',
ERROR: 'error',
APPROVAL_REQUIRED: 'approval_required',
};
function createAgentStreamRouter({ onDelta, onToolCall, onToolResult, onAgentState, onTerminal }) {
return function routeEvent(event) {
switch (event.status) {
case EVENT_STATES.INIT:
// 建立 request_id ↔ message 绑定
break;
case EVENT_STATES.LOADING:
// 判断 message_delta / tool_call_delta → onDelta / onToolCall
break;
case EVENT_STATES.STREAM_EVENT:
// tool-started / tool-finished → onToolResult
// agent_state → onAgentState
break;
case EVENT_STATES.FINISHED:
case EVENT_STATES.INTERRUPTED:
case EVENT_STATES.ERROR:
onTerminal(event);
break;
case EVENT_STATES.APPROVAL_REQUIRED:
// 中断等待用户确认
break;
}
};
}
```
Page AI sidebar runtime 和 document editor adapter 都消费同一个 router,各自提供自己的 `onDelta`/`onToolCall`/`onTerminal` 回调。
### 3.5 本地 Dashboard
**Yuxi 模式**
Dashboard 包含:
- **调用统计**:按时间线的 agent run 次数、成功/失败率
- **用户活跃度**DAU/MAU、会话时长
- **AI 智能体分析**:各 agent 调用量排行
- **工具调用监控**:各 tool 被调用次数、耗时
- **知识库使用情况**:检索次数、文件数、chunk 数
**MNote 当前状态**:无 Dashboard。
**借鉴方向**
为 local-first 场景做最小 Dashboard
1. **Agent Run 统计**(基于 7-57 run journal):最近 N 天 run 次数、平均耗时、成功/失败/中断分布
2. **Token 消耗**(基于 run journal 中的 token usage):按 agent、按日期维度
3. **知识库状态**(基于 LightRAG status bridge):已索引文件数、总 chunk 数、最近 ingest 时间
4. **Skills/MCP 健康**:已安装 skill 数、MCP 连接状态
数据源优先级:
- Agent run 统计:SQLite control-plane `agent_runs` 表(7-57 已建)
- Token 消耗:从 run journal 中提取
- 知识库状态:LightRAG `/status` API + MNote status bridge
- Skills/MCPHermes workspace 配置 + Rust manifest
不新增:
- 多用户统计(local-first 不需要)
- 实时推送更新(10 分钟 TTL + 手动刷新即可)
- 独立的时序数据库
### 3.6 虚拟路径安全加固
**Yuxi 模式**
沙盒路径的关键安全设计:
```python
# 1. ID 安全校验
_SAFE_ID_RE = re.compile(r"^[A-Za-z0-9_-]+$")
def validate_thread_id(thread_id: str) -> str:
if not _SAFE_ID_RE.match(value):
raise ValueError("thread_id contains invalid characters")
# 2. 虚拟路径前缀隔离
def get_virtual_path_prefix() -> str:
return "/" + VIRTUAL_PATH_PREFIX.strip("/") # /sandbox-v1
# 3. 路径穿越防护
def resolve_virtual_path(thread_id, virtual_path, *, uid):
# 必须从虚拟前缀开始
# 用 relative_to 校验不穿越 base_dir
# 4. 按 thread/user 分层
# workspace/ → 用户级共享
# uploads/ → 线程级
# outputs/ → 线程级
```
**MNote 当前状态**
`WorkspacePath` 主要通过 `allowed_roots` 做目录白名单校验,但没有:
- 线程级隔离(同一用户的多个 agent run 共享同一文件系统视图)
- 虚拟路径前缀(agent 直接看到宿主机真实路径)
- 正则 ID 校验
**借鉴方向**
不是引入 Yuxi 的 Python sandbox,而是在 Rust `WorkspacePath` / `AiAccessScope` 中加固:
1. **Agent 可见路径使用虚拟前缀**agent 通过 `mnote://workspace/``mnote://uploads/` 等虚拟路径引用文件,MNote 在 tool 边界做映射
2. **Run 级临时目录隔离**:每个 agent run 有独立 `mnote://runs/{run_id}/outputs/`,不污染 workspace
3. **路径穿越防护**:所有 agent 发来的路径必须在 allowed roots 内,且经过 `canonicalize` + `starts_with` 双重校验
4. **Attachments 目录**agent 上传/生成的附件落 `mnote://attachments/{run_id}/`,与 workspace 文件明确分开
第一阶段只加固现有 `AiAccessScope` + `allowed_roots`,不改变 agent 现有文件操作语义。
## 4. 执行优先级
| 批次 | 内容 | 优先级 | 预计影响面 |
|------|------|--------|-----------|
| **Batch A** | Hermes tool registry 模块化拆分 | 中 | manifest.rs 重构,不改变 API |
| **Batch B** | 扩展管理 settings 入口 + 能力清单 | 高 | settings UI,不改变后端 |
| **Batch C** | LightRAG 知识库详情页(文件管理 + 检索测试 + 检索参数) | 高 | knowledge-rag settings UI + 少量 API |
| **Batch D** | AgentStreamEventRouter 抽共享 | 中 | browser runtime 重构,不改变 API |
| **Batch E** | 本地 Dashboard 最小版 | 低 | 新页面 + SQLite 查询 |
| **Batch F** | WorkspacePath 虚拟路径安全加固 | 低 | AiAccessScope 增强,agent tool 适配 |
## 5. Checklist
### Batch AHermes tool registry 模块化拆分
- [ ] A1. 在 `hermes_tools/` 下创建 `registry/` 子目录
- [ ] A2. 把 `manifest.rs` 中工具按能力域拆到独立 registry 模块
- [ ] A2a. `context_registry.rs``context_snapshot``context_read_current_page``context_resolve_target`
- [ ] A2b. `doc_registry.rs``doc_fetch``doc_find``doc_markdown_edit``doc_apply_block_ops``doc_plan_update`
- [ ] A2c. `block_registry.rs``block_fetch``block_replace``block_insert_after``block_delete``block_move_after`
- [ ] A2d. `page_registry.rs``page_get``page_save``page_update_title``page_update_options`
- [ ] A2e. `knowledge_rag_registry.rs``knowledge_rag_status``knowledge_rag_query``knowledge_rag_section_context``knowledge_rag_open_reference`
- [ ] A2f. `skill_registry.rs``skill_read``skill_*`
- [ ] A2g. `mindmap_registry.rs``mindmap_fetch``mindmap_apply_ops``mindmap_create_from_outline`
- [ ] A2h. `onlyoffice_registry.rs`:所有 `onlyoffice_*` 工具
- [ ] A2i. `artifact_registry.rs``artifact_*` 工具
- [ ] A3. 每个 registry 暴露 `pub fn tools() -> Vec<Value>` + `pub fn capability_names() -> &[&str]`
- [ ] A4. `manifest.rs` 改为装配层:收集各 registry 的 tools + 统一 capability annotation
- [ ] A5. `cargo test -p mnote-web hermes_tool_manifest --lib` 通过
- [ ] A6. Agent descriptor smoke 验证 manifest 返回的工具列表与拆分前一致(`scripts/task557-page-ai-agent-descriptor-smoke.js`
### Batch B:扩展管理 settings 入口
- [ ] B1. 在 settings 页面增加"扩展"tab,路由 `/settings?tab=extensions`
- [ ] B2. 扩展 tab 包含子面板:知识库、Skills、MCP、Agent 工具
- [ ] B3. 知识库子面板:展示 LightRAG 当前状态 + 已索引文件数 + "管理"按钮 → 跳转知识库详情
- [ ] B4. Skills 子面板:展示已安装 skill 列表(名称、版本、状态、来源)
- [ ] B5. MCP 子面板:展示已配置 MCP 服务器列表(名称、URL、连接状态)
- [ ] B6. Agent 工具子面板:从 `/api/page-ai/agent-descriptors` 读取能力清单,只读展示
- [ ] B7. URL query 参数持久化当前子 tab(`&ext=knowledge|skills|mcp|tools`
- [x] B8. 登录态浏览器验证:settings → 扩展 tab,切换子面板,刷新后 tab 不丢失
### Batch CLightRAG 知识库详情页
- [ ] C1. 新增知识库详情页路由 `/knowledge-base`
- [ ] C2. 文件管理面板
- [ ] C2a. 展示已 ingest 文件列表(文件名、类型图标、大小、状态灯、最后更新时间)
- [ ] C2b. 状态灯映射:pending/parsing/chunking/indexing/done/error,每 30s 有界刷新(来自 status bridge
- [ ] C2c. 文件删除按钮(调 `mnote.knowledge_rag.delete` 或 LightRAG API
- [ ] C2d. 手动 re-index 按钮(单文件)
- [ ] C3. 检索测试面板
- [ ] C3a. 输入框 + 搜索按钮 → 调 `/api/knowledge-rag/search`
- [ ] C3b. 结果列表:citation preview + 来源文件 + 相关度分数
- [ ] C3c. 点击结果 → `open_reference` 打开对应资源
- [ ] C4. 检索参数配置面板
- [ ] C4a. search mode 下拉:local/global/hybrid/naive/mix
- [ ] C4b. top_k 数字输入(1-100
- [ ] C4c. 相似度阈值滑块(0.0-1.0
- [ ] C4d. 保存到 `user_ui_preferences`SQLite control-plane
- [ ] C5. Ingest 源目录管理:展示当前 source roots + 添加/移除(只改 MNote source registry,不动 LightRAG 配置)
- [x] C6. 登录态浏览器验证:知识库详情页三个面板切换、检索测试真实返回结果、参数保存后刷新不丢失
### Batch DAgentStreamEventRouter 抽共享
- [ ] D1. 在 `rust/crates/mnote-web/browser/` 创建 `agent-stream-event-router.js`
- [ ] D2. 定义标准事件类型 enuminit/loading/stream_event/finished/interrupted/error/approval_required
- [ ] D3. 实现 `createAgentStreamRouter({ onDelta, onToolCall, onToolResult, onAgentState, onTerminal })` 工厂函数
- [ ] D4. `sidebar-page-ai-runtime.js` 改为消费 AgentStreamEventRouter
- [ ] D5. `document-editor-adapter-runtime.js` 改为消费 AgentStreamEventRouter(如涉及编辑器内 agent 交互)
- [ ] D6. 浏览器 smoke 回归:Page AI 对话、tool call 展示、中断恢复、finished 状态均正常
- [ ] D7. `scripts/task*-page-ai-*.js` 相关 smoke 通过
### Batch E:本地 Dashboard 最小版
- [ ] E1. 新增 `/dashboard` 路由 + 页面壳
- [ ] E2. Agent Run 统计卡片
- [ ] E2a. 后端:`GET /api/dashboard/agent-run-stats?days=7` → 返回 run 总数、成功/失败/中断分布、按 agent 分组
- [ ] E2b. 前端:卡片 + 简易柱状图(按天分布)
- [ ] E3. Token 消耗卡片
- [ ] E3a. 后端:从 `agent_runs` 表提取 token usage 汇总(总 token、按 agent 分组)
- [ ] E3b. 前端:数值卡片(本周消耗 / 总计)
- [ ] E4. 知识库状态卡片
- [ ] E4a. 后端:代理 LightRAG `/status` + MNote status bridge,返回文件数、chunk 数、最近 ingest 时间
- [ ] E4b. 前端:数值卡片 + 状态灯
- [ ] E5. Skills/MCP 健康卡片
- [ ] E5a. 后端:从 Hermes workspace 配置 + Rust manifest 汇总
- [ ] E5b. 前端:列表 + 状态灯
- [ ] E6. 所有卡片使用 10 分钟 TTL + 手动刷新按钮,不做实时推送
- [x] E7. 登录态浏览器验证:Dashboard 页面展示各卡片数据
### Batch FWorkspacePath 虚拟路径安全加固
- [ ] F1. 在 `AiAccessScope` 中增加 `run_id` 字段
- [ ] F2. 实现 `AgentVirtualPath` 类型:`mnote://workspace/``mnote://outputs/{run_id}/``mnote://uploads/{run_id}/`
- [ ] F3. 在 Hermes tool 边界做虚拟路径 ↔ 真实路径映射(`resolve_agent_path` / `to_agent_virtual_path`
- [ ] F4. 路径穿越防护:`canonicalize` + `starts_with(allowed_root)` 双重校验
- [ ] F5. Run 级临时目录:每个 agent run 开始时创建 `mnote://outputs/{run_id}/`run 结束时清理
- [ ] F6. Agent tool smoke 验证:agent 只能访问 allowed roots 内文件,路径穿越被拒绝
## 6. 与现有设计的关系
| 现有设计 | 本稿关系 |
|----------|---------|
| 7-57 Batch A (run journal) | 本稿 Batch E (Dashboard) 消费 run journal 做统计 |
| 7-57 Batch B (agent descriptor) | 本稿 Batch B 的工具清单面板消费 descriptor |
| 7-50 (LightRAG provider) | 本稿 Batch C 是其 UI 增强 |
| 7-18 (agent file editing) | 本稿 Batch F 加固其 AiAccessScope |
| 3-23 (sidebar local folder runtime) | 本稿 Batch B/C 在 settings 中增加入口 |
| 7-38 (Page AI sidebar owner split) | 本稿 Batch D 是 sidebar runtime 的事件路由重构 |
## 7. 风险
- **Batch A 重构 manifest**:如果工具名或 capability annotation 在拆分中漂移,会导致 agent descriptor 不一致。必须用 smoke 对比拆分前后的 manifest JSON。
- **Batch C 检索参数**LightRAG `QueryParam` 的字段可能随版本变化。MNote 透传用户配置时应做字段白名单,未知字段忽略。
- **Batch D 事件路由重构**:如果 browser runtime 中的事件格式在不同 consumer 间有细微差异(例如 Page AI 用 `message_id`editor 用 `msg_id`),统一 router 时需要兼容映射。
- **Batch E Dashboard**SQLite `agent_runs` 表可能膨胀。后续需要 TTL 清理策略,当前阶段保留最近 30 天。
- **Batch F 虚拟路径**agent 端(Hermes / Reasonix)需要能处理 `mnote://` 前缀,或 MNote 在 tool 边界双向映射。第一阶段先只映射,不要求 agent 原生理解虚拟路径。
## 8. 验证基线
- `cargo test -p mnote-web --lib` 全绿
- `scripts/task557-page-ai-agent-descriptor-smoke.js` 通过
- `scripts/task529-knowledge-rag-citation-resource-tab-smoke.js` 通过
- `scripts/task530-knowledge-rag-page-ai-final-answer-smoke.js` 通过
- 新增 smoke`scripts/task561-extensions-settings-smoke.js`Batch B+C
- 新增 smoke`scripts/task561-dashboard-smoke.js`Batch E
- 登录态浏览器验证:settings 扩展 tab、知识库详情页、Dashboard 页面均可正常访问