- 新增 materials 表(id/projectId/description/associatedDate/status/createdAt/updatedAt) - 新增 4 个后端 API 路由(list/create/get/delete)+ 13 个测试 - 新增 use-materials hooks(TanStack Query) - 收集箱页面重构为三层架构(InboxPage + MaterialSidebar + MaterialDetailPanel) - MaterialCard: Popconfirm 删除确认 + 粗粒度时间格式 - MaterialContent: 展示状态标签 + createdAt - 更新开发文档 backend.md / frontend.md
101 lines
6.2 KiB
Markdown
101 lines
6.2 KiB
Markdown
# 后端开发
|
||
|
||
开发规范见 [开发规范文档](README.md)。
|
||
|
||
## 共享工具
|
||
|
||
`src/server/helpers/`:
|
||
|
||
- `response.ts`:`createApiError(error, status)`、`createHeaders(mode, init)`、`createMetaResponse(version)`、`formatDuration(ms)`、`jsonResponse(body, options)`
|
||
- `url.ts`:`parseIdFromUrl(url)`
|
||
|
||
`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。
|
||
- `src/server/db/connection.ts`:`createDatabase(dataDir, logger)` 打开 `alfred.db`,PRAGMA:foreign_keys=ON、journal_mode=WAL、busy_timeout=5000。`wrap(db)` 转为 Drizzle 实例。`paginateQuery()` 分页工具。
|
||
- Migration:开发期 `drizzle-kit generate` 产出到 `drizzle/`;生产期嵌入可执行文件,启动时自动应用。备份到 `<dataDir>/backups/`,事务中执行,失败回滚。
|
||
|
||
### 数据访问函数
|
||
|
||
| 文件 | 函数 |
|
||
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||
| `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 |
|
||
|
||
输入输出类型来自 `src/shared/api.ts`。
|
||
|
||
## AI 服务层
|
||
|
||
- `src/server/ai/types.ts`:`AIProviderConfig`(name、type、baseUrl、apiKey)、`AIModelConfig`(providerId、modelId、capabilities)。
|
||
- `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` — 用模型关联供应商 + modelId 测试。
|
||
|
||
## 素材 API
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
| ------ | ---------------------------------- | ---------------------- |
|
||
| GET | `/api/projects/:id/materials` | 列出项目下素材(分页) |
|
||
| POST | `/api/projects/:id/materials` | 创建素材 |
|
||
| GET | `/api/projects/:id/materials/:mid` | 获取素材详情 |
|
||
| DELETE | `/api/projects/:id/materials/:mid` | 删除素材(硬删除) |
|
||
|
||
校验:description 必填非空,associatedDate 必填 YYYY-MM-DD,项目须存在且 active,素材归属校验不匹配返回 403。
|
||
|
||
## 聊天 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 时,必须更新本文档。
|