docs: 同步第二阶段进度与扩展复盘

This commit is contained in:
2026-09-02 20:22:06 +08:00
parent ff3da5d6b1
commit 1e32b2e0f4
18 changed files with 505 additions and 37 deletions
+4 -3
View File
@@ -2,7 +2,7 @@
> 本文件用于团队开发期间快速配置环境和启动项目,不是正式的项目 README。 > 本文件用于团队开发期间快速配置环境和启动项目,不是正式的项目 README。
> 当前基线:2026-08-30。第一阶段 Web 联调版的前端页面、Knowledge/Retrieval Core、AI/Agent Core、Extension Core、Provider 预设与本地加密凭据链路均已实现Tauri Host、Stronghold、真实桌面文件系统和 Sync Server 尚未接入。 > 当前基线:2026-09-02。第一阶段 Web 联调前后端已经完成;第二阶段已完成 Workspace 去 Mock、Agent Trace 持久化与 SSE 恢复、stdio MCP Bridge、隔离 Plugin Host,以及 Plugin Command/Settings 后端 Contract 和前端 Service。真实音频、Provider 协议增强、Benchmark、导出、主题包、Trace 可视化、Mermaid 与函数图像仍在后续开发Tauri Host、Stronghold、原生多 Vault 文件系统和 Sync Server 尚未接入。
## 当前目录 ## 当前目录
@@ -118,7 +118,7 @@ cd frontend
pnpm test pnpm test
``` ```
当前回归基线为后端 126 项测试、前端 29 项测试,且 TypeScript 类型检查和生产构建通过。测试数量会随功能增长,以本地实际输出和 CI 为准。 当前回归基线为后端 136 项测试、前端 29 项测试,且 TypeScript 类型检查和生产构建通过。测试数量会随功能增长,以本地实际输出和 CI 为准。
构建产物位于 `frontend/dist`,该目录不提交到 Git。 构建产物位于 `frontend/dist`,该目录不提交到 Git。
@@ -134,6 +134,7 @@ pnpm test
| [AI Core 与 Agent Core](docs/development/AI-Core与Agent-Core开发说明.md) | Provider、Agent、Tool、Permission 与 Extension Core | | [AI Core 与 Agent Core](docs/development/AI-Core与Agent-Core开发说明.md) | Provider、Agent、Tool、Permission 与 Extension Core |
| [MCP Bridge 与 Plugin Host](docs/development/MCP-Bridge与Plugin-Host开发说明.md) | stdio MCP、隔离进程、Tool 映射、状态与错误边界 | | [MCP Bridge 与 Plugin Host](docs/development/MCP-Bridge与Plugin-Host开发说明.md) | stdio MCP、隔离进程、Tool 映射、状态与错误边界 |
| [Plugin Command 与 Settings](docs/development/Plugin-Command与Settings开发说明.md) | Command Registry、Settings Schema、Secret 引用与联调边界 | | [Plugin Command 与 Settings](docs/development/Plugin-Command与Settings开发说明.md) | Command Registry、Settings Schema、Secret 引用与联调边界 |
| [Plugin Command 与 Settings 复盘](docs/retrospectives/Plugin-Command与Settings问题与修复复盘.md) | 阶段 D 连续审阅发现的安全、事务、Schema 与运行时契约问题 |
| [Git 使用细则](docs/guides/Git使用细则-团队开发版.md) | 分支、提交、PR、Review 与合并流程 | | [Git 使用细则](docs/guides/Git使用细则-团队开发版.md) | 分支、提交、PR、Review 与合并流程 |
| [CI/CD 细则](docs/guides/CI-CD细则-团队开发版.md) | Gitea 流水线、质量门禁、产物、发布与回滚规则 | | [CI/CD 细则](docs/guides/CI-CD细则-团队开发版.md) | Gitea 流水线、质量门禁、产物、发布与回滚规则 |
| [Agent Trace 复盘](docs/retrospectives/Agent-Core第二阶段问题与修复复盘.md) | Agent 持久化、SSE 恢复、事件契约与脱敏问题复盘 | | [Agent Trace 复盘](docs/retrospectives/Agent-Core第二阶段问题与修复复盘.md) | Agent 持久化、SSE 恢复、事件契约与脱敏问题复盘 |
@@ -147,6 +148,6 @@ pnpm test
- 后端附件目录默认是 `backend/data/attachments`,可通过 `APP_ATTACHMENTS_PATH` 覆盖;该目录由桌面 Host 管理。 - 后端附件目录默认是 `backend/data/attachments`,可通过 `APP_ATTACHMENTS_PATH` 覆盖;该目录由桌面 Host 管理。
- 跨模块接口发生变化时,需要同步更新前后端类型和 `docs` 中的接口说明。 - 跨模块接口发生变化时,需要同步更新前后端类型和 `docs` 中的接口说明。
- 当前已实现接口见 `docs/contracts/后端接口契约-开发版.md`,第二阶段规划接口见 `docs/contracts/第二阶段接口契约-开发版.md`;已实现能力以 `/openapi.json` 为准。 - 当前已实现接口见 `docs/contracts/后端接口契约-开发版.md`,第二阶段规划接口见 `docs/contracts/第二阶段接口契约-开发版.md`;已实现能力以 `/openapi.json` 为准。
- 前端页面、交互、状态管理和第一阶段验收要求见 `docs/contracts/前端页面需求说明-开发版.md` - 前端页面、交互、状态管理及当前阶段后续页面需求见 `docs/contracts/前端页面需求说明-开发版.md`
- 分支、提交、Pull Request、Review 和冲突处理规范见 `docs/guides/Git使用细则-团队开发版.md` - 分支、提交、Pull Request、Review 和冲突处理规范见 `docs/guides/Git使用细则-团队开发版.md`
- CI 检查、产物、发布和回滚规范见 `docs/guides/CI-CD细则-团队开发版.md` - CI 检查、产物、发布和回滚规范见 `docs/guides/CI-CD细则-团队开发版.md`
+1 -1
View File
@@ -23,7 +23,7 @@ uv run uvicorn app.main:app --reload --host 127.0.0.1 --port 8000
uv run pytest uv run pytest
``` ```
当前基线为 126 项测试通过。Provider API Key 可通过前端设置页写入,也可用 `OPENAI_API_KEY``DEEPSEEK_API_KEY``AINOTE_CREDENTIAL_<ID>` 注入;不要把真实密钥写入仓库。`plugin.*` 是 Plugin Settings 的保留凭据命名空间,通用 Provider 凭据接口不能读写。 当前基线为 136 项测试通过。Provider API Key 可通过前端设置页写入,也可用 `OPENAI_API_KEY``DEEPSEEK_API_KEY``AINOTE_CREDENTIAL_<ID>` 注入;不要把真实密钥写入仓库。`plugin.*` 是 Plugin Settings 的保留凭据命名空间,通用 Provider 凭据接口不能读写。
团队接口清单见 `../docs/contracts/后端接口契约-开发版.md`,机器可读契约以运行时的 `/openapi.json` 为准。 团队接口清单见 `../docs/contracts/后端接口契约-开发版.md`,机器可读契约以运行时的 `/openapi.json` 为准。
+1
View File
@@ -49,6 +49,7 @@
- [后端全面审阅问题与修复复盘](retrospectives/后端全面审阅问题与修复复盘.md) - [后端全面审阅问题与修复复盘](retrospectives/后端全面审阅问题与修复复盘.md)
- [Agent Core 第二阶段问题与修复复盘](retrospectives/Agent-Core第二阶段问题与修复复盘.md) - [Agent Core 第二阶段问题与修复复盘](retrospectives/Agent-Core第二阶段问题与修复复盘.md)
- [Knowledge 与 Retrieval Core 问题与修复复盘](retrospectives/Knowledge与Retrieval-Core问题与修复复盘.md) - [Knowledge 与 Retrieval Core 问题与修复复盘](retrospectives/Knowledge与Retrieval-Core问题与修复复盘.md)
- [Plugin Command 与 Settings 问题与修复复盘](retrospectives/Plugin-Command与Settings问题与修复复盘.md)
- [前端合并审阅问题与修复复盘](retrospectives/前端合并审阅问题与修复复盘.md) - [前端合并审阅问题与修复复盘](retrospectives/前端合并审阅问题与修复复盘.md)
## 推荐阅读顺序 ## 推荐阅读顺序
@@ -2329,7 +2329,7 @@ Markdown Workspace
第一阶段 Plugin Runtime 已完成安装、启用、停用、权限和声明式 Tool 注册,建立 Skill 调用 Plugin Tool 的基础链路。Command、Settings 和 MCP 执行不计入第一阶段完成项。 第一阶段 Plugin Runtime 已完成安装、启用、停用、权限和声明式 Tool 注册,建立 Skill 调用 Plugin Tool 的基础链路。Command、Settings 和 MCP 执行不计入第一阶段完成项。
截至 2026-09-02,上述第一阶段后端链路和 Web 联调前端均已完成;第二阶段前置的 Workspace 去 Mock 联调、Agent Trace 持久化/恢复接口、stdio MCP Bridge / Plugin Host 以及 Plugin Command/Settings 后端 Contract 也已完成。当前验证基线为后端 126 项测试、前端 29 项测试、TypeScript 类型检查及生产构建通过。向量链路当前使用 `HashEmbeddingProvider` 验证工程正确性,真实 Embedding 召回质量不属于该测试结论。 截至 2026-09-02,上述第一阶段后端链路和 Web 联调前端均已完成;第二阶段的 Workspace 去 Mock 联调、Agent Trace 持久化/恢复接口、stdio MCP Bridge / Plugin Host 以及 Plugin Command/Settings 后端 Contract 与前端 Service 也已完成。当前验证基线为后端 136 项测试、前端 29 项测试、TypeScript 类型检查及生产构建通过。向量链路当前使用 `HashEmbeddingProvider` 验证工程正确性,真实 Embedding 召回质量不属于该测试结论。
第二阶段在既有 Contract 上接入: 第二阶段在既有 Contract 上接入:
@@ -2361,7 +2361,7 @@ Frontend Extension
└── Plugin Settings UI └── Plugin Settings UI
``` ```
上述列表描述第二阶段技术范围,其中 stdio MCP Bridge 已实现,其余能力以各自开发说明的状态为准。每项功能必须继续经过现有 Service、Contract、Permission 和 Adapter 边界,不因 Demo 需要在 Vue 组件、Router 或 Agent Runtime 中直接绑定第三方协议。 上述列表描述第二阶段技术范围,其中 stdio MCP Bridge、Plugin Command Contribution 和 Plugin Settings Contribution 后端 Contract 已实现,其余能力以各自开发说明的状态为准。每项功能必须继续经过现有 Service、Contract、Permission 和 Adapter 边界,不因 Demo 需要在 Vue 组件、Router 或 Agent Runtime 中直接绑定第三方协议。
第三阶段处理: 第三阶段处理:
@@ -2415,9 +2415,9 @@ Sync Server 按独立服务开发和部署,不进入桌面客户端核心启
目标桌面端采用 Tauri 2、Rust、Vue 3 和 TypeScript;当前可运行形态是 Vue/Vite Web 前端加 FastAPI。用户笔记以 Markdown 和 Assets 保存在本地 Vault,SQLite 已管理笔记元数据、全文索引、向量索引、任务及 Agent TraceProvider/Extension Registry 当前仍为内存实现。 目标桌面端采用 Tauri 2、Rust、Vue 3 和 TypeScript;当前可运行形态是 Vue/Vite Web 前端加 FastAPI。用户笔记以 Markdown 和 Assets 保存在本地 Vault,SQLite 已管理笔记元数据、全文索引、向量索引、任务及 Agent TraceProvider/Extension Registry 当前仍为内存实现。
Python AI Core 未来作为 Tauri Sidecar 运行,当前由开发命令独立启动,FastAPI 提供本地接口。Knowledge Core 管理笔记结构;Retrieval Core 当前通过 FTS5、`HashEmbeddingProvider`、sqlite-vec、RRF 和轻量 Reranker 跑通混合检索,真实 Embedding 与正式 Benchmark 第二阶段接入;Agent Runtime 使用 Tool Registry 操作知识库和任务,并将扩展 Agent Trace Contract 供可视化和 Benchmark 共用Skill Runtime 将提示词、工具、权限和检索参数组装为可复用 Agent 配置。 Python AI Core 未来作为 Tauri Sidecar 运行,当前由开发命令独立启动,FastAPI 提供本地接口。Knowledge Core 管理笔记结构;Retrieval Core 当前通过 FTS5、`HashEmbeddingProvider`、sqlite-vec、RRF 和轻量 Reranker 跑通混合检索,真实 Embedding 与正式 Benchmark 仍待第二阶段后续接入;Agent Runtime 使用 Tool Registry 操作知识库和任务,并已持久化可供前端可视化与 Benchmark 共用的 Agent Trace ContractSkill Runtime 将提示词、工具、权限和检索参数组装为可复用 Agent 配置。
当前 Plugin Runtime 支持 Manifest、生命周期声明式白名单 Tool Contribution,并已通过 stdio MCP Bridge 接入独立进程 Tool、Host 状态与重启接口;Command 与 Settings Contribution 尚待后续阶段实现。Provider Adapter 当前实现 Mock、OpenAI Chat/OpenAI-Compatible 与 Ollama第二阶段按统一行为测试完善 OpenAI Responses、Anthropic Messages 等协议。多模态目标方案使用 faster-whisper、pyannote.audio 和可选 emotion2vec;当前只读取 Host 预生成 transcript。 当前 Plugin Runtime 支持 Manifest、生命周期声明式白名单 Tool Contribution、Plugin Command 与 Plugin Settings/Secret,并已通过 stdio MCP Bridge 接入独立进程 Tool、专用 MCP Command Target、Host 状态与重启接口。Provider Adapter 当前实现 Mock、OpenAI Chat/OpenAI-Compatible 与 OllamaOpenAI Responses、Anthropic Messages 等协议仍待第二阶段后续完善。多模态目标方案使用 faster-whisper、pyannote.audio 和可选 emotion2vec;当前只读取 Host 预生成 transcript。
第二阶段内容输出以 Document AST、Exporter Adapter、Mermaid Renderer 和 Function Plot Renderer 为共同边界,支持 HTML、PDF、DOCX 与静态图导出。Theme Package 使用 Manifest、Design Token 和受限 CSS 实现本地导入;联网主题市场不属于本阶段核心依赖。API Key 在 Web 联调期由 Fernet 开发存储加密保存,桌面版迁移到 Tauri Stronghold。多设备同步的目标方案为独立、可自托管的 Sync Server,目前尚未实现;本地核心功能不依赖 Sync Server。 第二阶段内容输出以 Document AST、Exporter Adapter、Mermaid Renderer 和 Function Plot Renderer 为共同边界,支持 HTML、PDF、DOCX 与静态图导出。Theme Package 使用 Manifest、Design Token 和受限 CSS 实现本地导入;联网主题市场不属于本阶段核心依赖。API Key 在 Web 联调期由 Fernet 开发存储加密保存,桌面版迁移到 Tauri Stronghold。多设备同步的目标方案为独立、可自托管的 Sync Server,目前尚未实现;本地核心功能不依赖 Sync Server。
+1 -1
View File
@@ -1,6 +1,6 @@
# 第一阶段分工表 # 第一阶段分工表
> 状态更新:2026-08-30。本文保留原始职责划分,同时记录当前交付状态。第一阶段后端目标已完成,前端 Web 联调页面已完成;尚未纳入本阶段完成项的是 Tauri Host、Stronghold、真实桌面文件系统、独立 MCP Plugin Host、真实音频模型和 Sync Server。 > 状态更新:2026-09-02。本文保留第一阶段原始职责划分和交付口径。第一阶段后端目标前端 Web 联调页面已完成;第二阶段此后又完成 Agent Trace 持久化与 SSE 恢复、独立 stdio MCP Plugin Host 和 Plugin Command/Settings 后端 Contract。Tauri Host、Stronghold、原生多 Vault 文件系统、真实音频模型和 Sync Server 仍未实现
## 当前交付状态 ## 当前交付状态
@@ -1,6 +1,6 @@
# 后端接口契约(开发版) # 后端接口契约(开发版)
> 更新日期:2026-09-01。本文档记录当前前后端联调使用的已实现接口;机器可读字段、校验规则和响应模型以 FastAPI 运行时生成的 OpenAPI 为准。第二阶段尚未实现的规划接口见 `第二阶段接口契约-开发版.md`,不要将规划路径视为当前服务能力。 > 更新日期:2026-09-02。本文档记录当前前后端联调使用的已实现接口;机器可读字段、校验规则和响应模型以 FastAPI 运行时生成的 OpenAPI 为准。第二阶段尚未实现的规划接口见 `第二阶段接口契约-开发版.md`,不要将规划路径视为当前服务能力。
## 契约入口 ## 契约入口
@@ -176,7 +176,7 @@ RunCancelled
## 当前实现状态 ## 当前实现状态
更新至 2026-09-02:后端 126 项回归测试通过;第二阶段 Plugin Command 与 Plugin Settings/Secret 接口已实现,详细 DTO 和边界见《第二阶段接口契约-开发版》第 7 节。 更新至 2026-09-02:后端 136 项回归测试通过;第二阶段 Plugin Command 与 Plugin Settings/Secret 接口已实现,详细 DTO 和边界见《第二阶段接口契约-开发版》第 7 节。
- Chat、Agent Run、Agent Events、Tool 列表、Provider 配置生命周期、模型列表和连接测试已经接入 AI Core。 - Chat、Agent Run、Agent Events、Tool 列表、Provider 配置生命周期、模型列表和连接测试已经接入 AI Core。
- Agent Run/Event 已持久化到 SQLiteSSE 帧携带 sequence `id`,断线后可以回放缺失事件。Trace API 与 Benchmark 共用同一事件事实,并在入库前执行 Secret 脱敏和结果限长。 - Agent Run/Event 已持久化到 SQLiteSSE 帧携带 sequence `id`,断线后可以回放缺失事件。Trace API 与 Benchmark 共用同一事件事实,并在入库前执行 Secret 脱敏和结果限长。
@@ -2,7 +2,7 @@
> 文档状态:接口冻结草案 > 文档状态:接口冻结草案
> >
> 更新日期:2026-09-01 > 更新日期:2026-09-02
> >
> 依据:`../architecture/第二阶段团队分工表.md`、`../architecture/AI笔记软件技术栈说明-团队版-v2.3.md`、`后端接口契约-开发版.md` > 依据:`../architecture/第二阶段团队分工表.md`、`../architecture/AI笔记软件技术栈说明-团队版-v2.3.md`、`后端接口契约-开发版.md`
@@ -27,7 +27,7 @@
| 标记 | 含义 | | 标记 | 含义 |
| --- | --- | | --- | --- |
| 已实现 | 第一阶段接口已经存在,第二阶段保持兼容 | | 已实现 | 接口已经落地并由当前 OpenAPI 与自动化测试覆盖 |
| 扩展 | 路径已存在,第二阶段增加字段、事件或行为 | | 扩展 | 路径已存在,第二阶段增加字段、事件或行为 |
| 计划新增 | 第二阶段需要新增实现 | | 计划新增 | 第二阶段需要新增实现 |
| 内部 Contract | 不直接暴露 HTTP,由两个模块共同遵守 | | 内部 Contract | 不直接暴露 HTTP,由两个模块共同遵守 |
@@ -2,7 +2,7 @@
> 本文档用于团队开发和模块联调,记录当前已经落地的核心边界与使用方式。 > 本文档用于团队开发和模块联调,记录当前已经落地的核心边界与使用方式。
> 更新日期:2026-09-02。第一阶段 AI Core、Agent Core、Extension Core 和 Model Core 主链路已经完成;第二阶段 Agent Trace 持久化、可恢复 SSE、stdio MCP Bridge、隔离 Plugin Host 以及 Plugin Command/Settings 已落地,后端当前回归基线为 126 项测试通过。 > 更新日期:2026-09-02。第一阶段 AI Core、Agent Core、Extension Core 和 Model Core 主链路已经完成;第二阶段 Agent Trace 持久化、可恢复 SSE、stdio MCP Bridge、隔离 Plugin Host 以及 Plugin Command/Settings 已落地,后端当前回归基线为 136 项测试通过。
## 当前实现 ## 当前实现
@@ -347,6 +347,6 @@ Skill Manifest
- Run/Trace 已通过 Repository 接入 SQLite;后续增加按保留策略归档和 Benchmark 引用保护。 - Run/Trace 已通过 Repository 接入 SQLite;后续增加按保留策略归档和 Benchmark 引用保护。
- Permission 已有核心等待/恢复机制,前端确认 UI 已完成联调和中文展示。 - Permission 已有核心等待/恢复机制,前端确认 UI 已完成联调和中文展示。
- Task 已持久化到 SQLiteAttachment Tool 读取 Host 管理目录中的 UTF-8 文件。 - Task 已持久化到 SQLiteAttachment Tool 读取 Host 管理目录中的 UTF-8 文件。
- `audio.transcribe` 当前消费 Host 预生成的 transcriptfaster-whisper 与说话人分离仍按技术基线在第二阶段接入。 - `audio.transcribe` 当前消费 Host 预生成的 transcriptfaster-whisper 与说话人分离仍第二阶段后续接入。
- Extension 安装记录暂存内存;后续接入持久化 Registry 与版本升级流程。 - Extension 安装记录暂存内存;后续接入持久化 Registry 与版本升级流程。
- 当前 Plugin Host 支持内置声明式 handler、本地 stdio MCP Server 以及 Plugin Command/SettingsStreamable HTTP、OS 级沙箱与 UI Contribution 留在后续阶段。 - 当前 Plugin Host 支持内置声明式 handler、本地 stdio MCP Server 以及 Plugin Command/SettingsStreamable HTTP、OS 级沙箱与 UI Contribution 留在后续阶段。
@@ -3,7 +3,7 @@
> 本文档用于团队开发和模块联调,记录 Knowledge Core / Retrieval Core 已经落地的 > 本文档用于团队开发和模块联调,记录 Knowledge Core / Retrieval Core 已经落地的
> 模块边界、数据模型、接口与使用方式,对应分工表中的杨星萱。 > 模块边界、数据模型、接口与使用方式,对应分工表中的杨星萱。
> 更新日期:2026-09-02。第一阶段 Knowledge/Retrieval 主链路已经完成,并已接入 Agent Tool Registry;完整后端回归基线为 126 项测试通过。 > 更新日期:2026-09-02。第一阶段 Knowledge/Retrieval 主链路已经完成,并已接入 Agent Tool Registry;完整后端回归基线为 136 项测试通过。
## 当前实现 ## 当前实现
@@ -198,7 +198,7 @@ cd backend
uv run pytest -q uv run pytest -q
``` ```
当前后端完整测试共 71 个用例通过(单元 + 端到端)。测试通过 `tests/conftest.py` 的 autouse fixture 把 当前后端完整测试共 136 个用例通过(单元 + 端到端)。测试通过 `tests/conftest.py` 的 autouse fixture 把
数据目录/DB/Vault 重定向到临时目录,不读写真实 `backend/data`,任何本机状态下结果确定。 数据目录/DB/Vault 重定向到临时目录,不读写真实 `backend/data`,任何本机状态下结果确定。
## 配置 ## 配置
@@ -1,6 +1,6 @@
# Plugin Command 与 Settings 开发说明 # Plugin Command 与 Settings 开发说明
> 更新日期:2026-09-02。本文记录第二阶段阶段 D 已实现的 Plugin Command Contribution、Plugin Settings Contribution、Secret 边界和前端 Service Contract。当前回归基线为后端 126 项测试、前端 29 项测试,TypeScript 类型检查和生产构建通过。 > 更新日期:2026-09-02。本文记录第二阶段阶段 D 已实现的 Plugin Command Contribution、Plugin Settings Contribution、Secret 边界和前端 Service Contract。当前回归基线为后端 136 项测试、前端 29 项测试,TypeScript 类型检查和生产构建通过。
## 1. 阶段目标 ## 1. 阶段目标
@@ -1,6 +1,6 @@
# 前端写作体验优化开发说明 # 前端写作体验优化开发说明
> 更新日期:2026-08-30。本文所述优化均已进入当前分支;前端完整回归基线为 14 项测试通过,TypeScript 检查和 Vite 生产构建通过。 > 更新日期:2026-09-02。本文所述优化均已进入 `main`当前前端完整回归基线为 29 项测试通过,TypeScript 检查和 Vite 生产构建通过。
## 1. 本次目标 ## 1. 本次目标
@@ -103,7 +103,7 @@ pnpm build
pnpm test pnpm test
``` ```
验证结果:TypeScript 类型检查与 Vite 生产构建均通过。当前前端完整回归测试共 14 项;其中写作与文件切换相关回归覆盖: 验证结果:TypeScript 类型检查与 Vite 生产构建均通过。当前前端完整回归测试共 29 项;其中写作与文件切换相关回归覆盖:
- 顶部工具栏对选区应用加粗; - 顶部工具栏对选区应用加粗;
- 浮动工具栏对选区应用斜体; - 浮动工具栏对选区应用斜体;
@@ -1,6 +1,6 @@
# 前端壳子与接口层开发说明 # 前端壳子与接口层开发说明
> 更新日期:2026-08-30 > 更新日期:2026-09-02
> 适用范围:Vue 3 + TypeScript 页面、Workspace、公共 Service、FastAPI 接口适配和 SSE。 > 适用范围:Vue 3 + TypeScript 页面、Workspace、公共 Service、FastAPI 接口适配和 SSE。
> 文档用途:帮助团队理解当前前端可用能力、模块边界、启动方式和后续页面开发入口。 > 文档用途:帮助团队理解当前前端可用能力、模块边界、启动方式和后续页面开发入口。
@@ -187,12 +187,12 @@ pnpm build
```text ```text
pnpm build passed pnpm build passed
pnpm test 29 passed pnpm test 29 passed
uv run pytest 126 passed uv run pytest 136 passed
preview smoke HTTP 200 preview smoke HTTP 200
git diff --check passed git diff --check passed
``` ```
当前前端使用 Vitest 执行 Store、Workspace API Adapter、SSE 恢复游标、Plugin Command/Settings Service、文件树、编辑器组件、智能体标签、轻量动效约束、Markdown 对比度 Token、scoped CSS 选择器约束和 Shiki GitHub 双主题测试;`pnpm build` 同时执行 `vue-tsc -b` 与 Vite 生产构建。后端测试出现过 `.pytest_cache` 无法写入的 Windows 权限警告,不影响 126 项测试结果,也不涉及产品代码。 当前前端使用 Vitest 执行 Store、Workspace API Adapter、SSE 恢复游标、Plugin Command/Settings Service、文件树、编辑器组件、智能体标签、轻量动效约束、Markdown 对比度 Token、scoped CSS 选择器约束和 Shiki GitHub 双主题测试;`pnpm build` 同时执行 `vue-tsc -b` 与 Vite 生产构建。后端测试出现过 `.pytest_cache` 无法写入的 Windows 权限警告,不影响 136 项测试结果,也不涉及产品代码。
Vite 当前会提示 Chat 与 Workspace 的部分异步 Chunk 超过 500 kB,这是 Milkdown、CodeMirror、KaTeX 和 Shiki 等编辑/渲染依赖带来的性能优化项,不影响构建成功或功能正确性;进入桌面打包前应通过手动分包或更细粒度动态加载继续优化。 Vite 当前会提示 Chat 与 Workspace 的部分异步 Chunk 超过 500 kB,这是 Milkdown、CodeMirror、KaTeX 和 Shiki 等编辑/渲染依赖带来的性能优化项,不影响构建成功或功能正确性;进入桌面打包前应通过手动分包或更细粒度动态加载继续优化。
@@ -1,6 +1,6 @@
# 模型提供商与模型发现开发说明 # 模型提供商与模型发现开发说明
> 更新日期:2026-08-30。OpenAI、DeepSeek、Ollama 预设、模型自动发现、默认模型选择和开发阶段加密凭据存储均已实现并接入设置页。 > 更新日期:2026-09-02。OpenAI、DeepSeek、Ollama 预设、模型自动发现、默认模型选择和开发阶段加密凭据存储均已实现并接入设置页。
## 1. 本次目标 ## 1. 本次目标
@@ -104,4 +104,4 @@ pnpm build
自动化验证覆盖 Provider 预设、OpenAI-Compatible `/models` 请求与鉴权头、模型映射、前端自动刷新、排序去重及按 Provider 隔离错误。生产构建同时执行 Vue 和 TypeScript 类型检查。 自动化验证覆盖 Provider 预设、OpenAI-Compatible `/models` 请求与鉴权头、模型映射、前端自动刷新、排序去重及按 Provider 隔离错误。生产构建同时执行 Vue 和 TypeScript 类型检查。
当前完整回归基线:后端 126 项测试、前端 29 项测试通过,前端类型检查和生产构建通过。Provider 配置目前仍保存在内存 Registry,AI Core 重启后需要重新创建;凭据密文会保留。`plugin.*` 为 Plugin Secret 保留命名空间,Provider 配置、临时测试凭据和通用凭据 API 均拒绝该前缀。OpenAI Responses 与 Anthropic Messages Adapter 尚未实现,设置页正式预设不会使用这两种协议。 当前完整回归基线:后端 136 项测试、前端 29 项测试通过,前端类型检查和生产构建通过。Provider 配置目前仍保存在内存 Registry,AI Core 重启后需要重新创建;凭据密文会保留。`plugin.*` 为 Plugin Secret 保留命名空间,Provider 配置、临时测试凭据和通用凭据 API 均拒绝该前缀。OpenAI Responses 与 Anthropic Messages Adapter 尚未实现,设置页正式预设不会使用这两种协议。
@@ -1,9 +1,11 @@
# 第一阶段测试验证操作手册 # 第一阶段测试验证操作手册
> 适用基线:2026-08-30 `main` > 适用基线:2026-09-02 `main`
> 适用对象:开发、自测、代码审阅、合并验收和 Demo 前检查 > 适用对象:开发、自测、代码审阅、合并验收和 Demo 前检查
> 验证范围:Vue Web 前端、FastAPI、Knowledge/Retrieval Core、AI/Agent Core、Extension Core、Provider 与开发阶段凭据链路 > 验证范围:Vue Web 前端、FastAPI、Knowledge/Retrieval Core、AI/Agent Core、Extension Core、Provider 与开发阶段凭据链路
> 状态说明:本文保留第一阶段功能验收口径;当前全量自动化回归同时覆盖第二阶段已经合并的 Agent Trace 持久化与 SSE 恢复、stdio MCP Host、Plugin Command/Settings Contract 和前端 Service,但不反向修改第一阶段的交付定义。
## 1. 验证目标 ## 1. 验证目标
本手册用于确认第一阶段已经形成可运行的本地知识工作流: 本手册用于确认第一阶段已经形成可运行的本地知识工作流:
@@ -18,7 +20,7 @@
→ Skill / Plugin 完成生命周期与 Tool 注册 → Skill / Plugin 完成生命周期与 Tool 注册
``` ```
当前不作为第一阶段通过条件的内容:Tauri/Rust Host、Stronghold、真实桌面文件系统、独立 MCP Plugin Host、真实音频模型和 Sync Server 当前不作为第一阶段通过条件的内容:Tauri/Rust Host、Stronghold、原生多 Vault 文件系统、真实音频模型和 Sync Server。独立 stdio MCP Plugin Host 已在第二阶段完成,并进入当前全量回归测试
## 2. 环境准备 ## 2. 环境准备
@@ -68,7 +70,7 @@ uv run pytest -q -p no:cacheprovider
当前基线: 当前基线:
```text ```text
81 passed 136 passed
``` ```
通过标准:退出码为 0、失败数为 0。用例数可以随功能增加,但不得低于当前基线。 通过标准:退出码为 0、失败数为 0。用例数可以随功能增加,但不得低于当前基线。
@@ -83,11 +85,11 @@ pnpm test
当前基线: 当前基线:
```text ```text
11 test files passed 12 test files passed
27 tests passed 29 tests passed
``` ```
通过标准:退出码为 0、失败数为 0。测试覆盖 Provider Store、主题偏好、Workspace、文件树、文件切换、可视化编辑器、智能体中文标签、轻量动效性能约束、Markdown 对比度 Token、scoped CSS 选择器约束和 Shiki GitHub 双主题输出。 通过标准:退出码为 0、失败数为 0。测试覆盖 Provider Store、主题偏好、Workspace、文件树、文件切换、可视化编辑器、智能体中文标签、SSE 恢复游标、Plugin Command/Settings Service、轻量动效性能约束、Markdown 对比度 Token、scoped CSS 选择器约束和 Shiki GitHub 双主题输出。
### 3.3 类型检查与生产构建 ### 3.3 类型检查与生产构建
@@ -330,7 +332,7 @@ Invoke-RestMethod -Method Delete -Uri "$apiBase/notes/$noteId"
- 没有真实密钥、生成目录或运行数据进入 Git; - 没有真实密钥、生成目录或运行数据进入 Git;
- 已记录测试环境、提交、结果、警告和遗留问题。 - 已记录测试环境、提交、结果、警告和遗留问题。
外部 OpenAI/DeepSeek、Tauri、Stronghold、真实文件系统、真实音频模型与 Sync Server 失败或未测,不阻止当前第一阶段 Web 联调基线通过,但必须在验收记录中注明“未纳入本阶段”或“选测未执行”。 外部 OpenAI/DeepSeek、Tauri、Stronghold、原生多 Vault 文件系统、真实音频模型与 Sync Server 失败或未测,不阻止当前第一阶段 Web 联调基线通过,但必须在验收记录中注明“未纳入本阶段”或“选测未执行”。
## 9. 验收记录模板 ## 9. 验收记录模板
@@ -3,7 +3,7 @@
> 本文记录 `feat/knowledge-retrieval-core` 合并前后的两轮代码审阅、问题复现、修复过程与工程经验。 > 本文记录 `feat/knowledge-retrieval-core` 合并前后的两轮代码审阅、问题复现、修复过程与工程经验。
> 它既是团队内部的问题档案,也可作为后续技术文档、课程报告和博客文章的素材底稿。 > 它既是团队内部的问题档案,也可作为后续技术文档、课程报告和博客文章的素材底稿。
> 2026-08-30 状态补充:本文中的 43 项测试是当时该模块的历史基线,不应替换为当前全仓测试数。相关修复仍有效,当前完整后端回归为 71 项通过,Knowledge/Retrieval 已通过 `notes.*``rag.search` Tool 接入 Agent Runtime。 > 2026-09-02 状态补充:本文中的 43 项测试是当时该模块的历史基线,不应替换为当前全仓测试数。相关修复仍有效,当前完整后端回归为 136 项通过,Knowledge/Retrieval 已通过 `notes.*``rag.search` Tool 接入 Agent Runtime。
## 1. 背景 ## 1. 背景
@@ -0,0 +1,464 @@
# Plugin Command 与 Settings 问题与修复复盘
> 审阅与修复日期:2026-09-02
> 涉及分支:`feat/plugin-command-settings`
> 初始功能提交:`6a08ad8 feat(extension): 实现插件命令与设置贡献`
> 最终修复提交:`d39ae72 fix(extension): 收紧插件命令运行时契约`
> 合并提交:`ff3da5d Merge pull request 'feat(extension): 实现 Plugin Command 与 Settings Contribution' (#10)`
> 文档用途:记录阶段 D 从首次提交、连续审阅到合并期间发现的问题,说明形成原因、实际后果、解决思路和最终方案,供后续开发、问题定位、比赛材料和技术博客写作使用。
## 1. 背景与结论
阶段 D 在既有 Extension Core、MCP Bridge 和 Plugin Host 上增加 Plugin Command 与 Settings Contribution。初始实现已经具备命令注册、参数校验、设置持久化、Secret 加密存储和前端 Service,但首次提交仍把若干“接口能够调用”误当成了“安全边界已经闭合”。
本次分支没有在初始功能提交后直接合并,而是围绕清单输入、凭据隔离、JSON Schema、MCP 协议、事务一致性和前后端 Contract 连续审阅。最终共形成 1 个功能提交和 6 个修复提交,处理 12 类问题:
| 编号 | 问题 | 级别 | 处理结果 |
| --- | --- | --- | --- |
| D-01 | Plugin Secret 可被通用凭据接口或 Provider 引用 | P0 | 建立 `plugin.*` 保留命名空间和双层访问门禁 |
| D-02 | Command 与 Settings 清单边界不完整 | P1 | 收紧空值、重复项、权限、类型和数值边界校验 |
| D-03 | MCP Command Target 只有声明,没有真实执行链路 | P0 | 增加专用 MCP 命令目标并与 Agent Tool 隔离 |
| D-04 | JSON Schema 外部引用可能触发越权 I/O | P0 | 只允许当前文档内 Fragment 引用 |
| D-05 | Secret 引用可被篡改并跨凭据命名空间 | P0 | 改用定长哈希引用并在读取、删除前重新核对 |
| D-06 | Secret 删除和插件卸载缺少事务一致性 | P0 | 原子替换凭据表,失败时恢复 Settings 引用 |
| D-07 | Schema 引用校验忽略嵌套 `$id` 资源作用域 | P1 | 使用 Draft 2020-12 Resource Resolver 按资源解析 |
| D-08 | MCP Command 未收到普通 Settings | P1 | 在固定信封中同时传递 Settings 与声明过的 Secret |
| D-09 | Command Effect 是任意字典,前后端边界过宽 | P0 | 改为五类判别联合并限制各自 Payload |
| D-10 | 必填普通设置没有阻止启用和执行 | P1 | 在 Enable 与 Execute 两个入口增加运行时门禁 |
| D-11 | MCP 工具 Schema 被发现后丢弃,真实信封未校验 | P0 | 保存目标 Schema,并在调用前校验完整信封 |
| D-12 | 启用探测和回归测试存在假阳性或假阴性 | P1 | 使用最小协议标记,移除自制求解器并补强测试 |
最终验证基线为后端 136 项测试、前端 29 项测试、TypeScript 类型检查、前端生产构建、`uv lock --check``git diff --check` 通过。PR #10 已合并到 `main`
## 2. 提交与审阅过程
| 顺序 | 提交 | 主要内容 |
| --- | --- | --- |
| 1 | `6a08ad8` | 首次实现 Plugin Command、Settings、Secret API 和前端 Service |
| 2 | `c3ef9df` | 收紧 Plugin Secret、Provider 凭据和 Command 清单边界 |
| 3 | `9e680a0` | 补齐真实 MCP Command Target,限制 JSON Schema 外部引用 |
| 4 | `022c322` | 改造 Secret 引用,修复删除和卸载事务 |
| 5 | `c06b962` | 按 Draft 2020-12 资源作用域修复 Schema 引用解析 |
| 6 | `eb3464b` | 补回 MCP Command 信封中的普通 Settings |
| 7 | `d39ae72` | 收紧 Effect、必填设置和 MCP 运行时 Contract,修复测试盲点 |
| 合并 | `ff3da5d` | PR #10 合并进入 `main` |
这段过程说明,Extension Core 的风险主要不在正常路径能否运行,而在不同入口是否共享同一套边界。HTTP、Provider Factory、Plugin Runtime、MCP Host、Settings Store 和测试 Fixture 只要有一个入口绕过限制,就可能形成跨命名空间访问、错误执行或假测试通过。
## 3. D-01Plugin Secret 可被通用凭据接口或 Provider 引用
### 原因
初始实现把 Plugin Secret 存入已有 `EncryptedCredentialStore`,但只在 Plugin Settings API 中隐藏明文,没有为凭据 ID 建立用途隔离。通用凭据 API 可以读写或删除同名 ID,Provider 配置也可以把 Plugin Secret 的凭据引用当作自己的 API Key 使用。
此外,Command 能否读取 Secret 只依赖 Plugin 拥有 `secrets.use` 权限,没有继续限制到当前 Command 在 `commands.yaml` 中明确声明的字段。
### 后果
- 前端或其他模块可以覆盖、删除 Plugin 私有 Secret
- Provider 可能把插件密钥发送给外部模型服务;
- 同一 Plugin 内权限较低的 Command 可以读取与自己无关的 Secret;
- API 没有回显明文并不代表 Secret 没有发生横向流动。
### 解决思路
Secret 隔离必须同时覆盖存储命名空间、公共 HTTP 入口、Provider 解析入口和 Command 字段级授权,不能只在返回 DTO 上隐藏值。
### 解决方案
- 将 `plugin.*` 设为 Plugin Settings 专用保留命名空间;
- 通用凭据查询、写入和删除接口拒绝访问该前缀;
- 在 `ProviderFactory` 外包一层 `ProviderCredentialResolver`,即使绕过 HTTP 配置校验也不能读取 Plugin Secret
- Command 通过 `secrets` 字段声明允许读取的 Setting Key
- Resolver 同时检查插件权限、字段是否存在、字段类型和 Command 声明;
- 未声明字段返回 `PLUGIN_SECRET_ACCESS_DENIED`,必填 Secret 未配置返回 `PLUGIN_SECRET_REQUIRED`
- 审计事件不记录 arguments、effect 或 Secret。
## 4. D-02Command 与 Settings 清单边界不完整
### 原因
YAML 解析成功只说明语法可读,并不代表清单结构满足宿主协议。初始校验对 `commands:` 空值、重复 Secret、未声明权限、无效执行目标、Settings 默认值及非有限数值边界等情况覆盖不足。
例如 YAML 中只有 `commands:` 时,解析结果是 `null` 而不是空数组;`NaN` 和正负无穷虽然属于 Python 浮点值,却不能成为可移植的表单边界。
### 后果
- 安装阶段可能放过无法执行的 Command;
- 空清单在后续遍历时变成内部异常,而不是稳定业务错误;
- 前后端对数值范围和默认值产生不一致理解;
- 重复声明或越过 Plugin 命名空间的 ID 会污染全局注册表;
- 错误只能到运行期暴露,定位成本更高。
### 解决思路
把 Plugin 包视为不可信输入,在安装阶段完成结构、语义和权限的完整验证,并将解析异常统一转换成稳定的 `ExtensionError`
### 解决方案
- 要求 `contributes` 声明与 `commands.yaml``settings.yaml` 内容完全一致;
- 拒绝 `null` Command 列表、重复 ID、重复 Secret 和越过 Plugin 命名空间的标识;
- 执行目标只能在受控 `handler` 与当前 Plugin 的 `mcp_tool` 中二选一;
- 校验 `when`、Context、Location 和权限白名单;
- Settings 类型限定为 `string``number``boolean``select``secret`
- 校验默认值、Select 选项、必填规则和最小/最大边界;
- 拒绝 `NaN`、正无穷和负无穷;
- 清单错误统一返回可定位的稳定错误码。
## 5. D-03MCP Command Target 只有声明,没有真实执行链路
### 原因
初始 Command 执行器只支持宿主内置 Handler。接口和规划中虽然存在 MCP Command 的概念,但 Runtime 没有把 Command 绑定到 MCP 工具,也没有定义 Command Context、Settings 和 Secret 如何进入 MCP 请求。
直接复用 Agent `ToolRegistry` 看似省事,却会把“用户主动执行的插件命令”和“模型可自主调用的 Agent Tool”混成同一种能力。
### 后果
- MCP 插件声明的 Command 实际无法执行;
- 如果简单注册为 Agent Tool,模型可能绕过命令位置、Context 裁剪和 Secret 声明直接调用;
- Command 超时、Effect 和错误边界无法统一;
- 前端看到命令已注册,点击后却只能得到运行时错误。
### 解决思路
为 MCP Command 建立独立执行通道。它可以复用 MCP 连接,但不能自动进入 Agent Tool Registry;宿主负责构造固定协议信封并验证返回的白名单 Effect。
### 解决方案
- `commands.yaml` 支持当前 Plugin 命名空间内的 `mcp_tool` 目标;
- Runtime 在 Plugin 启用后绑定目标,在禁用、异常退出和重启时同步注销;
- MCP Command 不注册到 Agent `ToolRegistry`
- 宿主只传递已校验 arguments、已裁剪 Context、有效 Settings 和当前 Command 声明的 Secret
- MCP 返回结果必须转换成受控 Effect;
- 远程原始异常、过大结果和超时统一映射为稳定宿主错误。
## 6. D-04JSON Schema 外部引用可能触发越权 I/O
### 原因
Command 和 MCP Tool 都接受插件提供的 JSON Schema。初始实现直接交给校验器处理 `$ref``$dynamicRef`,没有限制引用 URI。恶意或错误 Schema 可以引用本地文件、HTTP 地址或其他外部资源。
### 后果
- Schema 校验可能读取宿主文件或发起未授权网络请求;
- 安装一个插件就可能产生隐式 I/O;
- 离线环境中校验结果不稳定;
- 外部资源变化会让相同插件包得到不同验证结果;
- Command 和 Agent Tool 如果采用不同规则,会出现新的绕过路径。
### 解决思路
当前阶段不需要跨文件 Schema。宿主应只允许当前文档内部的 Fragment 引用,并在注册阶段递归检查所有 Schema 节点。
### 解决方案
- Command 与 Tool 共用 `schema_security` 校验边界;
- 递归扫描 `$ref``$dynamicRef`
- 只允许以 `#` 开头的当前文档 Fragment
- 拒绝文件、HTTP 和其他外部资源 URI;
- 无法解析的本地引用在安装或注册阶段直接失败;
- 运行期继续使用官方 Draft 2020-12 Validator 校验数据。
## 7. D-05Secret 引用可被篡改并跨凭据命名空间
### 原因
初始 Settings 文件保存的 Secret 引用由可读的 Plugin ID 和 Setting Key 拼接而成。长度随名称增长,而且 Runtime 读取引用时默认信任磁盘内容,没有重新确认该引用确实属于当前字段。
本地文件损坏或被篡改后,一个 Plugin Setting 可以被改为指向 Provider 凭据或另一个 Plugin 的 Secret。
### 后果
- 长 Plugin ID 和 Setting Key 可能超过凭据 ID 长度限制;
- Settings 文件泄露内部字段名称;
- 篡改引用可能造成跨命名空间读取或删除;
- 卸载一个插件时可能误删其他模块的凭据。
### 解决思路
Secret 引用应由宿主确定性生成,长度固定,并在每次敏感操作前由当前 `plugin_id + setting_key` 重新计算,而不是信任持久化文件。
### 解决方案
使用以下语义生成引用:
```text
plugin.<sha256(plugin_id + "\\0" + setting_key)>
```
- 引用长度固定且符合凭据 ID 规则;
- Settings Store 只保存引用和 `configured` 状态,不保存明文;
- 读取、覆盖、删除和卸载前重新计算期望引用;
- 引用不匹配时按损坏存储拒绝处理;
- 增加跨命名空间篡改回归测试。
## 8. D-06Secret 删除和插件卸载缺少事务一致性
### 原因
Secret 同时涉及 Settings 引用文件和加密凭据文件。初始删除流程按顺序修改两个存储,但任一步失败都没有完整回滚。插件卸载多个 Secret 时逐条删除,执行到一半失败会留下部分清理状态。
### 后果
- Settings 显示未配置,但密文仍残留;
- 凭据已删除,Settings 却仍显示已配置;
- 多 Secret 卸载可能只删除前几项;
- 重试操作无法判断上一次执行到哪里;
- 用户以为插件卸载已清除密钥,实际磁盘仍可能保留数据。
### 解决思路
把引用更新和凭据删除看作一个逻辑事务。底层单文件凭据表应一次构造新状态并原子替换;跨 Settings 与 Credential Store 的操作需要显式补偿回滚。
### 解决方案
- `EncryptedCredentialStore` 增加多凭据原子删除;
- 先验证全部目标引用,再生成新的凭据表;
- 通过临时文件和原子替换一次提交;
- 删除单个 Secret 时,凭据删除失败则恢复原 Settings 引用;
- 卸载 Plugin 时,批量删除失败则恢复完整 Settings 命名空间;
- 错误统一转换为稳定存储错误,避免部分成功被当作完整成功。
## 9. D-07Schema 引用校验忽略嵌套 `$id` 资源作用域
### 原因
第一版本地引用检查把整个 Schema 当成单一 Fragment 树,用根文档指针或 Anchor 查找所有引用。Draft 2020-12 允许嵌套 `$id` 创建新的 Schema Resource;资源内部的 `#anchor` 应相对于新的 Base URI 解析,根资源也不能反向使用嵌套资源的 Anchor。
### 后果
- 合法的嵌套资源引用被误拒绝;
- 根 Schema 可能错误引用只属于子资源的 Anchor;
- 宿主预检结果与官方运行时 Validator 不一致;
- 同一 Schema 在安装阶段通过,却可能在执行阶段失败,反之亦然。
### 解决思路
安全限制仍然是“禁止外部资源”,但本地资源内部的解析语义必须遵守 JSON Schema 标准,不能自己用字符串和全局 Anchor 集合近似实现。
### 解决方案
- 引入与 Draft 2020-12 Validator 配套的 Resource Registry
- 为根资源和嵌套 `$id` 建立正确作用域;
- 每个引用按其所在资源的 Base URI 解析;
- 保留外部资源拒绝策略;
- 增加“根资源不能使用子资源 Anchor”和“子资源可使用自身 Anchor”的成对测试。
## 10. D-08MCP Command 未收到普通 Settings
### 原因
真实 MCP Command 链路补齐后,固定信封传递了 Command ID、Arguments、Context 和 Secret,但遗漏了已经通过 Schema 校验的普通 Settings。声明式内置 Handler 能读取 SettingsMCP Handler 却不能,两个执行目标语义不一致。
### 后果
- 用户在插件设置页修改普通配置,对 MCP Command 不生效;
- 插件只能把非敏感设置错误地编码进 arguments 或 Secret
- 内置 Handler 测试通过会掩盖 MCP 路径的缺口;
- 插件从内置实现迁移到 MCP 后行为发生变化。
### 解决思路
内置 Handler 与 MCP Command 应消费同一份运行时配置。差别只在执行介质,不在 Command Contract。
### 解决方案
- MCP 固定信封增加 `settings`
- Settings 由 `PluginSettingsStore.runtime_values()` 产生;
- 只传递当前 Plugin Schema 中有效的非敏感字段;
- Secret 继续放在独立 `secrets` 命名空间;
- Fixture 回显非敏感配置用于断言,但不回显 Secret;
- 增加 Settings 实际到达 MCP Server 的集成测试。
## 11. D-09Command Effect 是任意字典,前后端边界过宽
### 原因
初始 `PluginCommandEffect` 只有 `type` 和任意 `payload`。宿主虽然限制 Effect 名称和总体大小,却没有限制 Payload 字段、路由名称、刷新范围或通知级别。前端 TypeScript 也只能把 Payload 当成普通对象处理。
### 后果
- 插件可以返回前端从未支持的字段和路由;
- 前端需要在运行时猜测 Payload 结构;
- `navigate``refresh` 可能越过宿主允许的目标;
- OpenAPI 无法表达不同 Effect 的必填字段;
- 无效 Effect 往往要到页面执行时才暴露。
### 解决思路
Effect 是宿主能力协议,不是插件任意消息。每种 Effect 都应是独立、封闭、可判别的 Contract,并在进入 HTTP 响应前完成验证。
### 解决方案
- 后端建立 `notification``navigate``refresh``job``none` 五类模型;
- 使用 `type` 作为 Pydantic 判别字段;
- 限制通知级别、消息长度、路由白名单、刷新 Scope 和 Job ID
- TypeScript 同步为精确的判别联合;
- OpenAPI `PluginCommandResult.effect` 生成 `oneOf` 和 discriminator
- 保留可序列化性和 64 KiB 总大小限制作为第二层保护。
## 12. D-10:必填普通设置没有阻止启用和执行
### 原因
初始 Runtime 会合并已保存值和默认值,却没有检查 `required` 且没有默认值的普通字段是否仍为空。Secret 已有独立缺失检查,因此测试容易只覆盖 Secret,忽略普通 Settings。
### 后果
- 配置不完整的 Plugin 仍可启动 MCP Host
- Command 到插件内部才因缺少字段失败;
- 用户只能看到模糊执行错误,不知道应先补配置;
- 插件启用后删除必填值,后续执行没有再次校验。
### 解决思路
必填设置既是启用前置条件,也是每次执行的运行时不变量。不能只在保存表单时校验,因为磁盘内容可能变化,启用后的配置也可能被更新。
### 解决方案
- `runtime_values()` 返回完整有效普通 Settings
- 缺少必填且无默认值的字段时抛出 `PLUGIN_SETTINGS_REQUIRED`
- Plugin Enable 前执行一次检查,不启动无效 Host;
- 每次 Command Execute 前重新检查;
- 返回 409 和缺失字段上下文,便于前端引导用户进入设置页;
- 增加“补齐设置后可启用”的完整回归测试。
## 13. D-11MCP 工具 Schema 被发现后丢弃,真实信封未校验
### 原因
MCP 初始化阶段能够取得工具名称和 `inputSchema`,但 Runtime 记录只保留了工具名。Command 执行时直接发送宿主信封,没有用目标工具的完整 Schema 校验实际数据。
这意味着插件只要暴露同名工具就可能通过启用检查,即使它根本不接受 NotesAgent Command 协议。
### 后果
- 不兼容目标在启用阶段被注册为可执行 Command;
- 错误推迟到远程 MCP Server,返回信息不稳定;
- Context、Settings 或 Secret 结构变化时无法在宿主边界发现漂移;
- 前端看到可用命令,执行后才得到 502;
- 禁用或重启后若 Schema 缓存不清理,还可能使用过期契约。
### 解决思路
发现阶段保留完整目标 Schema;启用阶段只检查最低协议标记;执行阶段再用真实数据验证全部约束。Schema 生命周期必须和 MCP 工具生命周期一致。
### 解决方案
- Plugin 运行记录增加 MCP Command Schema 映射;
- 禁用、回滚、重启和 Host 不可用时同步清理 Schema
- 启用时要求目标 Schema 顶层直接声明 `properties._notesagent`,且类型为 `object`
- 执行前构造完整固定信封;
- 使用官方 Draft 2020-12 Validator 校验真实信封;
- 不匹配时返回 `PLUGIN_COMMAND_TARGET_SCHEMA_MISMATCH`,不调用 MCP Server。
## 14. D-12:启用探测和回归测试存在假阳性或假阴性
### 原因
审阅期间先后暴露了三类测试方法问题:
1. 启用阶段曾用空 arguments、Context、Settings 和 Secret 伪造信封,以判断目标 Schema 是否兼容。合法 Schema 如果要求真实业务字段,会被错误拒绝;
2. 为避免空数据误判,曾尝试加入自定义 JSON Schema 可满足性求解,但该近似实现无法正确覆盖 `not``oneOf` 等完整 Draft 2020-12 语义;
3. MCP Secret Fixture 即使没有收到 `api_key` 也会返回成功,测试只验证了命令成功,没有证明 Secret 真正到达服务端。
最后还发现空 Echo 消息会构造 `notification`,但新的通知 Contract 要求消息非空,导致合法空输入被包装为 502。
### 后果
- 合法插件可能在启用阶段被拒绝,形成假阴性;
- 不兼容 Schema 可能被自定义求解器放过,形成假阳性;
- Secret 传递链路回归后测试仍显示通过;
- Contract 收紧后,旧 Fixture 的边界值会产生新的运行时错误;
- 测试数量增加,却没有真正覆盖需要证明的安全事实。
### 解决思路
启用阶段只做稳定且明确的协议结构检查,完整 Schema 语义交给官方 Validator 和真实执行数据。测试必须让目标事实缺失时明确失败,而不是通过返回值间接猜测。
### 解决方案
- 取消空业务数据 Probe
- 将启用门槛缩小为直接 `_notesagent: { type: object }` 协议标记;
- 允许 `$ref``$dynamicRef``allOf``anyOf``oneOf``not` 等约束出现在 `_notesagent` 内部;
- 完全移除自定义 Schema 可满足性求解器;
- 实际执行统一交给官方 Draft 2020-12 Validator
- MCP Fixture 未收到声明的 Secret 时主动返回 MCP 错误,但永不返回明文;
- 空 Echo 返回 `none` Effect,非空 Echo 返回 `notification`
- 为协议标记、真实信封、Secret 到达、空 Echo 和恶意 Effect 分别增加回归测试。
## 15. 验证方法与结果
本分支最终执行以下验证:
```powershell
cd backend
uv lock --check
uv run pytest
cd ../frontend
pnpm test -- --run
pnpm type-check
pnpm build
cd ..
git diff --check
```
结果:
```text
backend: 136 passed
frontend: 29 passed
TypeScript type-check passed
frontend production build passed
uv lock --check passed
git diff --check passed
```
后端测试在 Windows 下仍有既有 `.pytest_cache` 权限警告,不影响测试结果。前端生产构建仍有既有大 Chunk 提示,不影响本次功能正确性和合并结论。
新增或强化的关键测试包括:
- Plugin Secret 公共 API、Provider Resolver 和 Command Resolver 三层隔离;
- 清单空值、重复项、无效权限、非有限边界和非法 Schema;
- MCP Command 与 Agent Tool 隔离;
- 固定信封中的 Context、Settings 和声明式 Secret
- 外部 Schema 引用拒绝和嵌套 `$id` 资源作用域;
- Secret 定长引用、篡改阻断、删除回滚和卸载原子性;
- 五类 Effect 的合法 Payload 和恶意 Payload 拒绝;
- 必填普通设置对 Enable 和 Execute 的双重门禁;
- MCP 实际信封校验、Secret 到达证明和空 Echo 行为。
## 16. 预防措施
- Plugin 包、MCP Schema 和 MCP 返回值一律按不可信输入处理;
- Secret 安全检查必须覆盖写入、读取、删除、解析、传输和审计全链路;
- 保留命名空间需要在公共 API 和内部 Resolver 两侧同时阻断;
- 多存储更新必须设计原子提交或补偿回滚,并测试中途失败;
- 不自行实现通用 JSON Schema 求解器,标准语义交给官方 Validator;
- 启用阶段只检查静态协议能力,不使用伪业务数据推导可执行性;
- Agent Tool 和用户触发的 Plugin Command 必须保持独立注册和权限边界;
- Pydantic Contract、OpenAPI、TypeScript DTO 和测试 Fixture 在同一提交中同步;
- 回归测试应直接证明目标事实,例如“Secret 确实到达且未落盘”,不能只证明接口返回成功;
- 每次收紧 Contract 后,重新检查空值、默认值、最大值和旧 Fixture 等边界输入。
## 17. 当前边界与后续事项
本次合并完成的是阶段 D 的宿主协议和开发期运行边界,不等于第三方插件已经具备生产级操作系统隔离。
当前仍保留以下后续事项:
- 阶段 C.5 按规划放在第二阶段功能与测试完成后、第三阶段桌面集成正式构建 Tauri/Rust 沙箱之前;
- 生产环境继续通过配置门禁拒绝未沙箱化的 MCP Host;
- 桌面端将 Plugin Secret 从开发期 Fernet 文件迁移到 Stronghold 或系统 Keychain,保持现有引用和 HTTP Contract
- 前端后续实现命令面板、上下文菜单和动态 Settings 表单,继续复用现有 Service;
- Command 审计当前是 500 条有界内存队列,长期审计持久化需在后续阶段单独设计;
- 前端大 Chunk 应通过路由和 Markdown 依赖拆包处理,不与本次 Extension Contract 修改混合。
## 18. 复盘结论
本次最重要的经验是:插件系统的正确性不能只按“命令是否执行成功”判断。真正需要审阅的是数据从清单进入注册表、从 Settings 进入运行时、从 Secret Store 进入执行器、从宿主信封进入 MCP,以及从 MCP Effect 返回前端的每一道边界。
连续审阅避免了跨命名空间 Secret 访问、非事务删除、外部 Schema I/O、MCP 伪兼容和任意 Effect 等问题进入 `main`。最终实现把每个边界落到明确 Contract、稳定错误码和可失败的回归测试上,为下一阶段前端集成和桌面安全沙箱提供了可复用基础。
@@ -4,7 +4,7 @@
> 涉及提交:`f9efc4f`,合并提交 `c6c28e4` > 涉及提交:`f9efc4f`,合并提交 `c6c28e4`
> 文档用途:记录前端分支合并后暴露的问题域、形成原因、实际后果、修复思路和落地方案,供后续技术文档、比赛材料与博客写作使用。 > 文档用途:记录前端分支合并后暴露的问题域、形成原因、实际后果、修复思路和落地方案,供后续技术文档、比赛材料与博客写作使用。
> 2026-08-30 状态补充:在本文轮修复之后,项目又完成 Milkdown 写作工具栏、文件切换二次竞态修复、Shiki 只读高亮、Provider 预设/模型发现/加密 API Key 输入,以及智能体页面汉化。当前前端回归基线为 14 项测试和生产构建通过。 > 2026-09-02 状态补充:在本文轮修复之后,项目又完成 Milkdown 写作工具栏、文件切换二次竞态修复、Shiki 只读高亮、Provider 预设/模型发现/加密 API Key 输入智能体页面汉化,以及 Plugin Command/Settings Service。当前前端回归基线为 29 项测试TypeScript 类型检查和生产构建通过。
## 1. 结论 ## 1. 结论
@@ -281,4 +281,4 @@ git diff --check passed
第三轮交互完善继续处理了文件切换、Markdown 选区格式、代码块默认状态、亮暗主题对比度和浮动工具栏失效问题。Provider 设置页增加 OpenAI、DeepSeek、Ollama 预设与模型自动发现,API Key 改为提交给后端加密保存,不进入 Pinia 或 Local Storage。智能体页面的运行状态、事件、工具、权限及导航文案已完成中文化,同时保留技术 ID 便于排障。 第三轮交互完善继续处理了文件切换、Markdown 选区格式、代码块默认状态、亮暗主题对比度和浮动工具栏失效问题。Provider 设置页增加 OpenAI、DeepSeek、Ollama 预设与模型自动发现,API Key 改为提交给后端加密保存,不进入 Pinia 或 Local Storage。智能体页面的运行状态、事件、工具、权限及导航文案已完成中文化,同时保留技术 ID 便于排障。
该轮新增 Store、Workspace、文件树、编辑器和中文标签回归测试;当前结果为前端 14 项、后端 71 项测试通过,生产构建通过。 该轮新增 Store、Workspace、文件树、编辑器和中文标签回归测试;该轮当时结果为前端 14 项、后端 71 项测试通过,生产构建通过。最新全仓基线见本文开头的状态补充。
@@ -4,7 +4,7 @@
> 审阅范围:FastAPI、Knowledge / Retrieval Core、Agent Core、Extension Core、Provider Adapter、公共接口和后端开发文档。 > 审阅范围:FastAPI、Knowledge / Retrieval Core、Agent Core、Extension Core、Provider Adapter、公共接口和后端开发文档。
> 文档用途:记录问题形成原因、实际影响、修复判断和落地方案,供后续开发文档、比赛材料与技术博客使用。 > 文档用途:记录问题形成原因、实际影响、修复判断和落地方案,供后续开发文档、比赛材料与技术博客使用。
> 2026-09-02 状态补充:本文记录的缺陷均保持修复。此后又加入 Provider 预设、模型发现、DeepSeek/OpenAI 凭据解析、Fernet 加密存储、Agent Trace 持久化、stdio MCP Plugin Host 和 Plugin Command/Settings,当前完整后端回归基线为 126 项测试通过。 > 2026-09-02 状态补充:本文记录的缺陷均保持修复。此后又加入 Provider 预设、模型发现、DeepSeek/OpenAI 凭据解析、Fernet 加密存储、Agent Trace 持久化、stdio MCP Plugin Host 和 Plugin Command/Settings,当前完整后端回归基线为 136 项测试通过。
## 1. 审阅结论 ## 1. 审阅结论