Files
NotesAgentic/docs/contracts/后端接口契约-开发版.md

227 lines
13 KiB
Markdown
Raw Permalink 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.
# 后端接口契约(开发版)
> 更新日期:2026-09-02。本文档记录当前前后端联调使用的已实现接口;机器可读字段、校验规则和响应模型以 FastAPI 运行时生成的 OpenAPI 为准。第二阶段尚未实现的规划接口见 `第二阶段接口契约-开发版.md`,不要将规划路径视为当前服务能力。
## 契约入口
- Swagger UI`GET /docs`
- OpenAPI`GET /openapi.json`
- 所有普通接口使用 JSON。
- Chat 和 Agent 实时事件使用 `text/event-stream`SSE)。
- 内部时间统一使用 UTC ISO 8601。
- ID 使用稳定业务 ID,不使用文件路径代替 ID。
## 接口清单
### System
| 方法 | 路径 | 用途 |
| --- | --- | --- |
| GET | `/health` | Sidecar 健康检查 |
| GET | `/api/status` | 获取服务名称、版本和环境 |
### Notes 与 Search
| 方法 | 路径 | 用途 |
| --- | --- | --- |
| GET | `/api/notes` | 获取笔记列表 |
| POST | `/api/notes` | 创建笔记 |
| GET | `/api/notes/{note_id}` | 获取笔记及 Block |
| PATCH | `/api/notes/{note_id}` | 更新笔记 |
| DELETE | `/api/notes/{note_id}` | 删除笔记 |
| POST | `/api/notes/{note_id}/move` | 移动笔记 |
| POST | `/api/notes/{note_id}/rename` | 重命名笔记文件并保留 Note/Block 身份 |
| POST | `/api/search` | FTS、Vector 或 Hybrid 检索 |
| GET | `/api/search/history` | 读取当前应用数据库最近 10 条去重搜索记录 |
| DELETE | `/api/search/history` | 清空当前应用数据库的搜索记录 |
### Workspace
Web 联调阶段只暴露后端通过 `APP_VAULT_PATH` 配置的单一 Vault,不接受浏览器传入任意本地目录。桌面多 Vault 与目录选择仍由后续 Tauri Host 提供。
| 方法 | 路径 | 用途 |
| --- | --- | --- |
| GET | `/api/workspace` | 获取当前 Vault、文件数和索引同步状态 |
| POST | `/api/workspace/open` | 打开配置的 Vault;路径集变化时先登记文件与 FTS,再调度后台向量更新 |
| GET | `/api/workspace/tree` | 获取真实 Markdown 文件和目录树 |
| POST | `/api/workspace/folders` | 新建目录 |
| POST | `/api/workspace/folders/rename` | 重命名目录并同步 Note 路径 |
| POST | `/api/workspace/folders/delete` | 删除目录及其 Note、Block、FTS 和向量记录 |
### Chat、Agent 与 Tool
| 方法 | 路径 | 用途 |
| --- | --- | --- |
| POST | `/api/chat` | 发起聊天并返回 ModelEvent SSE |
| GET | `/api/agent/runs` | 获取 Agent Run 列表 |
| POST | `/api/agent/runs` | 创建 Agent Run |
| GET | `/api/agent/runs/{run_id}` | 获取 Agent Run 状态与 Trace 摘要 |
| POST | `/api/agent/runs/{run_id}/cancel` | 取消 Agent Run |
| GET | `/api/agent/runs/{run_id}/events` | 订阅 AgentEvent SSE,支持 `Last-Event-ID` / `after_sequence` 恢复 |
| GET | `/api/agent/runs/{run_id}/trace` | 分页读取持久化 Trace、摘要和运行配置快照 |
| POST | `/api/agent/runs/{run_id}/permissions/{request_id}` | 响应 Tool 权限确认 |
| GET | `/api/tools` | 获取已注册 Tool Definition |
### Skill 与 Plugin
| 方法 | 路径 | 用途 |
| --- | --- | --- |
| GET | `/api/skills` | 获取 Skill 列表及状态 |
| POST | `/api/skills/install` | 安装 Skill |
| GET | `/api/skills/{skill_id}` | 获取 Skill Manifest 与状态 |
| POST | `/api/skills/{skill_id}/enable` | 启用 Skill |
| POST | `/api/skills/{skill_id}/disable` | 停用 Skill |
| DELETE | `/api/skills/{skill_id}` | 卸载 Skill |
| GET | `/api/user-skills` | 列出当前 Vault 的用户 Skill 逻辑记录 |
| POST | `/api/user-skills` | 新建用户 Skill;支持 UUID Idempotency-Key |
| GET | `/api/user-skills/{skill_id}` | 读取用户 Skill 与内容 revision |
| PUT | `/api/user-skills/{skill_id}` | 以内容 revision CAS 更新用户 Skill |
| DELETE | `/api/user-skills/{skill_id}?revision=...` | 以内容 revision CAS 删除用户 Skill |
| GET | `/api/plugins` | 获取 Plugin 列表及状态 |
| POST | `/api/plugins/install` | 安装 Plugin |
| GET | `/api/plugins/{plugin_id}` | 获取 Plugin Manifest 与状态 |
| POST | `/api/plugins/{plugin_id}/enable` | 启用 Plugin |
| POST | `/api/plugins/{plugin_id}/disable` | 停用 Plugin |
| PUT | `/api/plugins/{plugin_id}/permissions` | 设置 Plugin 已授权权限 |
| GET | `/api/plugins/{plugin_id}/host` | 获取隔离 MCP Host 状态、工具数和协商信息 |
| POST | `/api/plugins/{plugin_id}/host/restart` | 重启 MCP Host 并重新发现、校验和注册 Tool |
| DELETE | `/api/plugins/{plugin_id}` | 卸载 Plugin |
### Provider
| 方法 | 路径 | 用途 |
| --- | --- | --- |
| GET | `/api/providers` | 获取 Provider 配置列表 |
| GET | `/api/providers/presets` | 获取 OpenAI、DeepSeek 与 Ollama 配置预设 |
| POST | `/api/providers` | 新建 Provider 配置 |
| GET | `/api/providers/{provider_id}` | 获取 Provider 配置 |
| PATCH | `/api/providers/{provider_id}` | 更新 Provider 配置 |
| DELETE | `/api/providers/{provider_id}` | 删除 Provider 配置 |
| GET | `/api/providers/{provider_id}/models` | 获取模型及 Capability 列表 |
| POST | `/api/providers/test` | 测试 Provider 连接 |
| GET | `/api/credentials/{credential_id}` | 查询凭据是否已配置,不返回明文 |
| PUT | `/api/credentials/{credential_id}` | 加密保存开发阶段 API Key |
| DELETE | `/api/credentials/{credential_id}` | 删除已保存凭据 |
Provider Contract 只传递 `credential_id` 或临时 `credential_context_id`。当前前后端开发阶段通过独立的 `PUT /api/credentials/{credential_id}` 接收 API Key,并立即加密落盘;该接口只返回配置状态,不返回密钥。Provider CRUD、模型列表和测试接口均不携带明文 API Key。Tauri 集成后由 Stronghold 接管存储实现。
### Tasks、Media 与 Index
| 方法 | 路径 | 用途 |
| --- | --- | --- |
| GET | `/api/tasks` | 获取任务列表 |
| POST | `/api/tasks` | 创建任务 |
| GET | `/api/tasks/{task_id}` | 获取任务 |
| PATCH | `/api/tasks/{task_id}` | 更新任务 |
| DELETE | `/api/tasks/{task_id}` | 删除任务 |
| POST | `/api/media/transcriptions` | 创建音频转写任务 |
| GET | `/api/media/transcriptions/{job_id}` | 获取转写任务状态 |
| GET | `/api/index/status` | 获取索引服务状态 |
| POST | `/api/index/rebuild` | 创建索引重建任务 |
| GET | `/api/index/jobs/{job_id}` | 获取索引任务状态 |
## 统一错误
所有普通 HTTP 错误统一返回:
```json
{
"error": {
"code": "RESOURCE_NOT_FOUND",
"message": "Resource was not found.",
"details": {}
}
}
```
当前接口主要返回:
- `422 VALIDATION_ERROR`:请求字段不符合 Pydantic Contract
- `404 RESOURCE_NOT_FOUND`:路由或资源不存在。
- `409`:资源冲突、依赖缺失或扩展尚未获得权限;
- `429 AGENT_CAPACITY_EXCEEDED`:活动 Agent Run 达到上限。
前端只根据 `error.code` 判断业务错误,不解析第三方 SDK 的原始异常文本。
## SSE 约定
每条 SSE 包含事件名和对应 JSON Contract
```text
event: TextDelta
data: {"event":"TextDelta","sequence":1,"data":{"text":"..."},"timestamp":"..."}
```
ModelEvent 类型:
```text
TextDelta
ThinkingDelta
ToolCallStart
ToolCallDelta
ToolCallEnd
Usage
Error
Done
```
AgentEvent 类型:
```text
RunStarted
TextDelta
ThinkingDelta
ToolCall
ToolResult
PermissionRequired
Usage
Citation
RunCompleted
RunFailed
RunCancelled
```
## 当前实现状态
更新至 2026-09-02:后端 136 项回归测试通过;第二阶段 Plugin Command 与 Plugin Settings/Secret 接口已实现,详细 DTO 和边界见《第二阶段接口契约-开发版》第 7 节。
- Chat、Agent Run、Agent Events、Tool 列表、Provider 配置生命周期、模型列表和连接测试已经接入 AI Core。
- Agent Run/Event 已持久化到 SQLiteSSE 帧携带 sequence `id`,断线后可以回放缺失事件。Trace API 与 Benchmark 共用同一事件事实,并在入库前执行 Secret 脱敏和结果限长。
- Provider Adapter 当前包含 Mock、增量 SSE 的 OpenAI-Compatible Chat Completions、OpenAI Responses、Anthropic Messages,以及 Ollama JSONL Streaming。阶段 E 增加 `/api/model-routing``/api/models/embeddings``/api/media/speaker-matches`;具体请求和阶段边界见第二阶段契约 §8.5。
- Notes、Search、Index、Skills、Plugins、Tasks 和 Provider 生命周期均已接入业务服务。
- Workspace 已接入后端配置的真实 Vault;文件树、笔记读写、文件/目录新建、重命名和删除不再使用前端 Mock Fallback。
- Note Move 保留 `note_id`;Citation 的字符偏移统一使用 UTF-16 code unit,供浏览器编辑器直接定位。
- Plugin 启用前必须通过权限接口记录授权,未知权限默认拒绝。
- 本地 stdio MCP Server 已通过独立子进程接入 Plugin RuntimeAgent 只消费内部 Tool Contract。Host 支持 initialize、分页发现、调用、超时取消、状态查询、重启和异常退出后的 Tool 注销。
- Attachment Tool 读取 Host 管理的 `attachments` 目录;音频接口读取 Host 生成的转写文本,真实本地语音模型在第二阶段接入。
- 接入业务模块时保持当前路径和 Contract,不在 Router 中直接实现数据库、Provider 或 Agent 逻辑。
第二阶段开发保持本文件中已有路径兼容,并按 `第二阶段接口契约-开发版.md` 增加子资源、可选字段和事件。接口完成后先更新 OpenAPI 与本文件,再将第二阶段文档中的状态改为已实现。
### 前端真实状态补充(2026-09-04
- `GET /api/index/status` 额外返回 `total_notes: int``total_blocks: int`,来自当前 SQLite 索引;未建立内容索引时为 0。
- `GET /api/permissions/policy` 返回 `Record<string, "allow" | "confirm" | "deny">`,值取自后端当前生效的 PermissionPolicy。此接口只读,不提供全局修改能力,运行时权限确认仍使用既有 Agent permission endpoint。
## 2026-09-06:后台索引补充
- `POST /api/workspace/open` 返回可使用的 WorkspaceSnapshot,不等待向量推理。
- 外部新增文件登记后按笔记持久化后台向量任务,不再因此设置全库重建标记;已存在的全库待处理标记仍继续执行。模型空间与维度的持久化 sqlite-vec 索引从已有向量转换,接口响应结构不变。实现与性能验证见 [模型隔离向量索引与增量登记](../development/模型隔离向量索引与增量登记.md)。
- `PATCH /api/notes/{note_id}` 成功代表正文、元数据和 FTS 已保存;后台向量失败不撤销这次保存。
- `GET /api/index/status` 新增 `vector_refresh_required: boolean`,表示工作区或笔记存在向量待处理标记。该字段不是进度百分比;任务失败时也可为 true。
- `pending_jobs` 返回真实未完成索引任务数(包含运行中),不再固定为 0。全库待重建或运行中的全量重建计一个任务;逐笔记刷新按待处理标记计数。`running_jobs` 返回当前运行数。失败后保留的待重建标记仍计入未完成数。
- `active_searches``completed_searches``failed_searches``cancelled_searches` 分别表示向量/混合检索的进行中、完成、失败、取消次数,覆盖搜索、对话和 Agent 经统一检索引擎发起的调用,排除纯 FTS;混合检索回退 FTS 后成功仍计完成。计数仅保存在当前服务进程内,重启归零,与索引队列互相独立。
- 设置与搜索页每秒轮询状态,其他页面空闲时每 5 秒轮询;不是事件推送。短检索可能无法观察到进行中状态,但完成/失败计数会保留。设置页与底部状态栏复用状态标签,未知字段显示“未获取”。
- `POST /api/index/rebuild` 仍仅支持全量重建,并等待结果;不要将上述异步语义推广到所有索引 API。
状态、恢复限制与验证见 [工作区后台索引与保存开发说明](../development/工作区后台索引与保存开发说明.md)。
## 2026-09-06:统一运行日志
`GET /api/logs` 返回独立持久化的后台操作日志,无需打开 Vault。参数:`limit` 默认 50、最大 200`before` 为上一页 next_cursor`level` 为 INFO/WARNING/ERROR/CRITICAL 或空;`source` 按模块精确匹配;`q` 在事件名和脱敏元数据中做字面搜索。
返回 `items: [{id,timestamp,level,source,event,details}]``next_cursor`(无后续页时 null)、`sources``pending``dropped``write_failures``retention`。日志按 ID 倒序,保留最近 20,000 条。响应头 `X-Request-ID` 与后台日志关联。不得依赖日志记录笔记正文、工具参数、凭据或原始异常消息。
队列、错误处理、字段白名单和验证方法见 [后台运行日志与压力问题修复](../development/后台运行日志与压力问题修复.md)。