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

495 lines
25 KiB
Markdown
Raw Normal View History

# [recycle] 7-61 [process] Yuxi reference: middleware tool composition, extensions entry, knowledge settings UI, and local dashboard v1
2026-06-28 18:35:56 +08:00
> 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 页面均可正常访问