9.3 KiB
后端开发
开发规范见 开发规范文档。
共享工具
src/server/helpers/:
response.ts:createApiError(error, status)、createHeaders(mode, init)、createMetaResponse(version)、formatDuration(ms)、jsonResponse(body, options)url.ts:parseIdFromUrl(url)list-params.ts:parseListParams(url, mode, options?)— 统一校验分页/排序参数,替代 validatePaginationpagination.ts:paginateQuery()— Drizzle 分页查询封装
src/server/middleware/:
validate.ts:validateIdParam(idStr, mode)— 校验 ID 格式(字母数字 +_-);validatePagination(pageParam, pageSizeParam, mode)— page≥1, pageSize≤200;validateTimeRange(from, to, mode)error-handler.ts:AppError— 业务异常类(含 statusCode);withErrorHandler(fn, mode, logger?)— 包裹 handler 捕获异常
数据库
SQLite + bun:sqlite + Drizzle ORM。
src/server/db/schema.ts:Drizzle 表结构,列名 snake_case,TS 类型 camelCase。所有业务表通过helpers.ts的baseColumns获取 id/created_at/updated_at/deleted_at。src/server/db/helpers.ts:baseColumns常量(id、createdAt、updatedAt、deletedAt)+ Drizzle 构建器再导出。src/server/db/内禁止直接从drizzle-orm/sqlite-core导入sqliteTable(ESLint 强制)。src/server/db/connection.ts:createDatabase(dataDir, logger)打开alfred.db,PRAGMA:foreign_keys=ON、journal_mode=WAL、busy_timeout=5000。wrap(db)转 Drizzle 实例(DrizzleDB类型)。工具函数:timestamp()、notDeleted(table)、softDeleteRecord(db, table, id)、paginateQuery()(支持softDelete参数自动过滤已删除行)。- Migration:开发期
drizzle-kit generate产出到drizzle/;生产期嵌入可执行文件,启动时自动应用。备份到<dataDir>/backups/,事务中执行(迁移期间临时关闭外键检查),失败回滚。
软删除
所有业务表(projects、providers、models、conversations、materials、messages)使用 deleted_at 列实现软删除,不暴露给 API 层。DAO 查询通过 notDeleted(table) 或 paginateQuery({ softDelete }) 自动过滤已删除行。唯一性校验在应用层完成(同名 + deleted_at IS NULL),无数据库级 UNIQUE 约束。级联软删除:删除项目 → 级联软删除会话(→ 消息)+ 素材;删除会话 → 级联软删除消息;删除供应商 → 需无未删除模型。
数据访问函数
| 文件 | 函数 |
|---|---|
projects.ts |
createProject、getProject、listProjects、updateProject、deleteProject、archiveProject、restoreProject |
providers.ts |
createProvider、getProvider、listProviders、listProviderOptions、updateProvider、deleteProvider |
models.ts |
createModel、getModel、listModels、getModelWithProvider、getModelsByProviderId、updateModel、deleteModel |
conversations.ts |
createConversation、getConversation、listConversations、updateConversation、updateConversationTimestamp、deleteConversation、createMessage、createMessages、listMessages |
materials.ts |
createMaterial、getMaterial、listMaterials、deleteMaterial、approveMaterial、discardMaterial、retryMaterial |
输入输出类型来自 src/shared/api.ts。
AI 服务层
src/server/ai/types.ts:AIProviderConfig(name、type、baseUrl、apiKey)、AIModelConfig(providerId、modelId、capabilities)。注:AI 层modelId对应 DB 层Model.externalId。src/server/ai/registry.ts:buildProviderRegistry(db)— 从 DB 查询供应商构建 AI SDK Provider Registry,每次调用重建,不缓存。通过registry.languageModel('providerId:modelId')获取模型实例。testProviderConnection(config, logger)— 测试 Base URL 可达性 +/models接口testModelConnection(config, logger)— 测试模型连通性(需传入含 modelId 的合并配置)
src/server/ai/agents/alfred-agent.ts:createAlfredAgent(model)— ToolLoopAgent +stepCountIs(20)+getCurrentTime工具。src/server/ai/tools/:AI 工具定义。
供应商类型
| type | AI SDK factory |
|---|---|
openai |
createOpenAI({ apiKey, baseURL }) |
anthropic |
createAnthropic({ apiKey, baseURL }) |
openai-compatible |
createOpenAICompatible({ name, apiKey, baseURL }) |
连通性测试
POST /api/providers/test— 用未保存配置测试,不写入 DB,不阻止保存。Base URL 不可达或 API Key 无效返回ok: false;/models不支持返回ok: true+ 提示。POST /api/models/test— 用模型关联供应商 + externalId 测试。
素材 API
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/projects/:id/materials |
列出项目下素材(分页+状态筛选) |
| POST | /api/projects/:id/materials |
创建素材 |
| GET | /api/projects/:id/materials/:mid |
获取素材详情 |
| DELETE | /api/projects/:id/materials/:mid |
删除素材(软删除) |
| POST | /api/projects/:id/materials/:mid/approve |
审核通过(需 review 状态) |
| POST | /api/projects/:id/materials/:mid/discard |
审核放弃(需 review 状态) |
| POST | /api/projects/:id/materials/:mid/retry |
重试处理(需 failed 状态) |
素材状态流转:pending → processing → review → approved/discarded,失败分支 processing → failed,用户重试 failed → pending。共 6 种状态:pending、processing、review、approved、discarded、failed。
素材类型:general(通用)和 meeting(会议),创建时可选,默认 general。
校验:description 必填非空,associatedDate 必填 YYYY-MM-DD,项目须存在且 active 且未删除,素材归属校验不匹配返回 403。processing 状态禁止删除(409)。approve/discard 仅限 review 状态(409),retry 仅限 failed 状态(409)。
素材处理引擎
src/server/processing/:
processor.ts:MaterialProcessor类 — 后台定时扫描 pending 素材,按 FIFO 顺序处理(每 5 秒扫描一次),每次处理最多重试 3 次,成功后 status=review 并设置 processedContent,全部失败后 status=failed。启动时自动恢复所有 processing 状态的素材为 pending(recoverStuckMaterials)。templates/:处理模板目录 —general.ts(通用模板)和meeting.ts(会议模板),当前为占位实现(原样回显 description)。index.ts导出ProcessingTemplate类型和getTemplate(type)映射函数。index.ts:startMaterialProcessor(db, logger)— 工厂函数,创建并启动处理器实例。
处理器在 bootstrap.ts 中启动,shutdown 时先停止处理器再关闭数据库。
聊天 API
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/projects/:id/conversations |
列出项目下所有会话 |
| POST | /api/projects/:id/conversations |
创建新会话 |
| GET | /api/projects/:id/conversations/:cid |
获取会话详情 |
| PATCH | /api/projects/:id/conversations/:cid |
更新会话 |
| DELETE | /api/projects/:id/conversations/:cid |
删除会话及消息 |
| GET | /api/projects/:id/conversations/:cid/messages |
获取消息列表 |
| POST | /api/projects/:id/chat |
发送消息,SSE 回复 |
send.ts:验证会话归属 → 保存用户消息 → createAlfredAgent → createAgentUIStreamResponse → onFinish 持久化 AI 回复。
日志
| 实现 | 用途 |
|---|---|
| PinoLoggerWrapper | 生产运行时 |
| ConsoleFallbackLogger | 配置加载前降级 |
| NoopLogger | 静默丢弃 |
| MemoryLogger | 测试替身 |
版本管理
唯一来源:package.json。开发模式从 package.json 运行时读取;生产模式构建时烘焙为字面量。
更新触发条件
修改后端模块 API、共享工具、数据库 schema、AI 服务层、聊天 API 或列表查询参数解析时,必须更新本文档。管理页面 CRUD 通用模式的详细约定见 crud.md。