- 修复 registry 测试 ai mock 缺失 createProviderRegistry 导出 - 新增 POST /api/providers/test 支持未保存供应商配置连通性测试 - 供应商表单新增测试连接按钮,新建默认 openai-compatible - 连通性测试按 ok 展示成功/失败,不再统一 success 样式 - 模型表单新建时也可测试供应商连接 - 模型页使用独立 provider 列表避免分页/搜索影响 - 移除模型管理组件内联 style - 新增 ProviderTestResultResponse 共享响应类型 - 新增 bun run format:check 脚本 - 补充关键测试覆盖(删除关联、连通性、默认类型、表单测试) - 更新 docs/user/usage.md、docs/development/*、design.md、tasks.md - 归档 change 至 openspec/changes/archive/2026-05-29-add-model-management
7.4 KiB
后端开发
本文档说明 alfred 后端的 API、配置加载、日志、版本管理和后端测试开发约定。
适用场景:修改 src/server/、src/shared/api.ts、后端测试、配置契约、API 响应或日志模块。
库使用优先级
| 优先级 | 来源 | 典型用途 |
|---|---|---|
| 1 | Bun 内置 API | Bun.serve、Bun.file、Bun.YAML、Bun.spawn、bun:sqlite |
| 2 | es-toolkit | 类型判断、深度比较、并发控制 |
| 3 | 标准 Web API | Headers、fetch、AbortController |
| 4 | 主流三方库 | pino、@sinclair/typebox、ajv、drizzle-orm |
| 5 | 自行实现 | 仅在以上都无法满足时 |
新增依赖前必须先检查上述每一层是否已有可用方案。
API 路由开发
路由文件位于 src/server/routes/,每个端点一个文件。路由通过 server.ts 的 Bun.serve({ routes }) 声明式注册。
新增路由步骤:
- 在 src/server/routes/ 下创建 .ts
- 实现 handler 函数并 export
- 在 server.ts 的 routes 对象中注册路径和 method handler
- 在 tests/server/ 中添加对应测试
共享工具
helpers.ts 提供跨路由共用的响应工具:
- createApiError(error, status) — 构造 API 错误体
- createHeaders(mode, init) — 创建响应 Headers
- jsonResponse(body, options) — JSON 响应构造
middleware.ts 提供 API 参数校验函数:
- validateIdParam(idStr, mode) — 校验 ID 参数格式
- validatePagination(pageParam, pageSizeParam, mode) — 校验分页参数
- validateTimeRange(from, to, mode) — 校验时间范围参数
数据库
项目使用 SQLite 作为存储后端,通过 bun:sqlite + Drizzle ORM 实现类型安全的数据访问。
schema 定义
src/server/db/schema.ts 使用 Drizzle ORM 定义表结构,列名使用 snake_case,TypeScript 类型使用 camelCase,Drizzle schema 负责映射。
数据库连接
src/server/db/connection.ts 的 createDatabase(dataDir, logger) 打开 <dataDir>/alfred.db,设置 PRAGMA(foreign_keys=ON、journal_mode=WAL、busy_timeout=5000)。
migration 机制
- 开发期:使用
drizzle-kit generate从 TS schema 生成 SQL migration 文件到drizzle/目录 - 生产期:构建时将
drizzle/*.sql嵌入可执行文件,启动时自动应用 pending migrations - 每次 migration 前自动备份现有 DB 到
<dataDir>/backups/alfred-<timestamp>.db - migration 在事务中执行,失败则回滚并停止启动
数据访问
src/server/db/projects.ts 提供项目数据访问函数,src/server/db/providers.ts 提供供应商数据访问函数,src/server/db/models.ts 提供模型数据访问函数。输入输出使用 src/shared/api.ts 的类型。函数内部使用 Drizzle query builder 包装 bun:sqlite Database。
AI 服务层
src/server/ai/ 提供 AI Provider Registry 构建与连接测试能力。
类型定义
src/server/ai/types.ts 定义 AI 配置类型:
AIProviderConfig— 供应商配置(name、type、baseUrl、apiKey)AIModelConfig— 模型配置(providerId、modelId、capabilities)AIRegistryConfig— Registry 构建配置(providers、models),供后续 AI 调用层组合使用
Registry 构建
src/server/ai/registry.ts 提供:
buildProviderRegistry(db)— 从 DB 查询启用的供应商,构建 Vercel AI SDK Provider RegistrytestProviderConnection(config)— 使用 generateText 测试供应商连接
每次 AI 调用时从 DB 查询 enabled providers,构建 registry 后通过 registry.languageModel('providerId:modelId') 获取模型实例。不使用缓存层。模型是否存在、是否启用以及业务能力标签由调用方基于 models 表先行校验,registry 只负责将 providerId/modelId 映射到 AI SDK 模型实例。
供应商连通性测试
供应商连通性测试返回 { providerTestResponse: { ok, message } },前端根据 ok 展示成功或失败提示。
POST /api/providers/:id/test— 使用已保存供应商配置测试连接POST /api/providers/test— 使用表单中尚未保存的供应商配置测试连接
支持的供应商类型
| type | AI SDK factory |
|---|---|
openai |
createOpenAI({ apiKey, baseURL }) |
anthropic |
createAnthropic({ apiKey, baseURL }) |
openai-compatible |
createOpenAICompatible({ name, apiKey, baseURL }) |
类型规范
- 共享类型以 src/shared/api.ts 为唯一源头
- 应用常量以 src/shared/app.ts 为唯一源头
- 版本号以 package.json.version 为唯一源头
- 前端不得 import src/server/ 下的任何文件
- 严格联合类型优先于宽类型
配置契约
配置加载流程固定为:unknown -> AuthoringConfig -> NormalizedConfig -> ValidatedConfig -> ServerConfig。
Ajv 保持严格拒绝模式:allErrors: true、不启用类型强制转换、不注入默认值、不自动删除未知字段。
新增或修改配置字段时必须同步更新 TypeBox schema fragments、config.schema.json、测试和对应用户文档。
日志模块
后端运行时代码统一通过 Logger 接口输出日志,禁止直接使用 console.*。
| 实现 | 用途 |
|---|---|
| PinoLoggerWrapper | 生产运行时 |
| ConsoleFallbackLogger | 配置加载失败前的降级日志 |
| NoopLogger | 静默丢弃日志 |
| MemoryLogger | 测试替身 |
敏感信息会自动 redact authorization、cookie、password 等字段。
版本管理
项目使用 package.json.version 作为版本号唯一来源。
版本获取方式:
- 开发模式:src/server/version.ts 运行时从 package.json 读取
- 生产模式:scripts/build.ts 在构建时将版本号烘焙为字面量注入
版本升迁命令:
bun run version:patch # 升迁 patch 版本
bun run version:minor # 升迁 minor 版本
bun run version:major # 升迁 major 版本
bun run version:set # 显式设置版本号
后端测试
| 变更类型 | 测试重点 |
|---|---|
| API 路由 | tests/server/app.test.ts 集成行为 |
| 配置 schema | schema 导出、合法/非法配置 |
| helpers/middleware | 单元测试 |
后端测试约定:
- API 路由集成测试必须通过真实
startServer覆盖路由注册、HTTP method、fallback、响应 header 和核心错误路径。 - SQLite 相关测试必须复用
tests/helpers.ts中的测试数据库 helper,不要在测试文件内分散实现临时目录清理或直接裸用rmSync(dir, { recursive: true })。 - DAO 和路由边界测试应优先使用真实 migration 初始化测试库,只有 migration 执行器单测可以使用最小 fake migration。
- logger/bootstrap 中预期的 fallback 输出必须在测试中捕获并断言,正常通过的测试不应污染 stdout/stderr。
更新触发条件
修改后端 API、共享类型、配置契约、日志模块、版本管理或后端测试规范时,必须更新本文档。