feat(provider): 完成阶段E协议适配、国内预设与模型路由

This commit is contained in:
2026-09-04 06:19:32 +08:00
parent 9b8b10cdb1
commit 1fe75e3fd2
57 changed files with 4208 additions and 592 deletions
@@ -180,7 +180,7 @@ RunCancelled
- 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,以及 Ollama JSONL Streaming
- 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,供浏览器编辑器直接定位。
@@ -718,6 +718,8 @@ stdio 命令始终以 executable 与 args 数组通过 `shell=False` 启动;
## 8. Provider Adapter 扩展
> 阶段 E 实施更新(2026-09-04):OpenAI Responses、Anthropic Messages、Chat Completions 与 Ollama Adapter 已接入;国内提供商 logo 预设、独立凭据输入、配置恢复、Embedding / 转写 / 声纹 API 路由已实现。真实本地语音模型仍属于阶段 F。实现细节见 [模型提供商与模型发现开发说明](../development/模型提供商与模型发现开发说明.md)。
第二阶段不新增平行 Provider CRUD,继续使用第一阶段接口:
```text
@@ -734,7 +736,7 @@ POST /api/chat
### 8.1 ModelInfo 扩展
`GET /api/providers/{provider_id}/models` item 增加可选字段
以下为后续计划的可选字段;阶段 E 的 `GET /api/providers/{provider_id}/models` 实际 item 仍只包含 `model``display_name``capabilities`
```json
{
@@ -774,6 +776,8 @@ Done
- 浏览器取消 Fetch 或 SSE 后,服务端必须取消上游 Provider 请求。
- 不支持 reasoning 的 Provider 不发送伪造 ThinkingDelta。
阶段 E 补充:取消或关闭迭代器直接关闭上游连接并传播取消,不向已断开的客户端继续发送 Done。内部带点号、长名称的工具映射为合法的 64 字符以内名称,响应恢复原命名空间,映射在请求内隔离。实际流中断错误码为 `PROVIDER_STREAM_TRUNCATED``PROVIDER_INVALID_RESPONSE` 用于无效结构/参数。上面的 `Done.data.status` 适用于真实 HTTP Adapter;开发 Mock 保留原有测试事件。
### 8.3 Provider 一致性测试 Contract
每个 Adapter 使用相同 Case 描述:
@@ -811,6 +815,25 @@ MODEL_CONTEXT_LENGTH_EXCEEDED
---
### 8.5 阶段 E 模型路由接口(已实现)
| 方法 | 路径 | 契约 |
| --- | --- | --- |
| GET | `/api/model-routing` | `{config, local_backends}` |
| PUT | `/api/model-routing` | 提交 ModelRoutingConfig,返回递增版本配置 |
| POST | `/api/models/embeddings` | `{texts: string[]}``{vectors, source, model_id, dimensions, fallback_reason}` |
| POST | `/api/media/speaker-matches` | `{attachment_id, reference_attachment_id}``{score, source, fallback_reason}` |
`ModelRoutingConfig` 包含 `version``embedding``transcription``speaker_matching`。每个能力为 null 或 `{provider_id, model, endpoint, dimensions?}`。dimensions 仅 Embedding 使用,范围 116384endpoint 是选定 Provider 下不带查询的路径,不能传第二个 URL。PUT 不提交 GET 返回的 local_backends;版本冲突返回 409 `MODEL_ROUTING_VERSION_CONFLICT`。删除仍被引用的 Provider 返回 409 `PROVIDER_IN_USE`
本阶段远程能力仅接受 OpenAI Chat / Compatible HTTP 配置,默认路径分别是 `/embeddings``/audio/transcriptions``/audio/speaker-matches`。最后一个是本项目自定义 multipart 接口,**不是公共 OpenAI 标准协议**:请求 model、file、reference_file,响应有限 01 的 score。转写采用 multipart model、file、可选 language,必须返回非空 text。文件来自受控附件目录,限制 25 MiB。
`TranscriptionJob` 新增可选 `source: api|local|sidecar``fallback_reason`。保留已有转写 Job 路径;`diarization=true` 返回失败 Job,错误为 `DIARIZATION_NOT_IMPLEMENTED`,不能静默忽略。
无配置时调用本地接口;有配置时 API 优先,网络/鉴权/限流/结果无效时回退。本地 Embedding 当前为 hash 占位;本地 ASR / 声纹后端尚未安装时返回 `LOCAL_MODEL_NOT_INSTALLED`,而非伪成功。远程 Embedding 独立索引并检查完整覆盖,模型变化后需重建;不与本地向量混算。
Provider PATCH 支持 provider_type;普通配置持久化到 SQLite,凭据继续独立加密。预设新增 logo_id、description、capabilities,前端图标随应用打包。
## 9. RAG / Agent Benchmark
Benchmark Service 同时提供 Python 调用接口和本地 HTTP 接口。CLI、测试和前端报告页调用同一 Service,不各自实现指标。