Skip to content

Commit 095de57

Browse files
✨ feat: support AI Image (#8312)
Co-authored-by: canisminor1990 <i@canisminor.cc>
1 parent c98860e commit 095de57

File tree

402 files changed

+29173
-510
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

402 files changed

+29173
-510
lines changed

.cursor/rules/backend-architecture.mdc

Lines changed: 93 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
---
2-
description:
2+
description:
33
globs: src/services/**/*,src/database/**/*,src/server/**/*
44
alwaysApply: false
55
---
6+
67
# LobeChat 后端技术架构指南
78

89
本指南旨在阐述 LobeChat 项目的后端分层架构,重点介绍各核心目录的职责以及它们之间的协作方式。
@@ -29,32 +30,28 @@ LobeChat 的后端设计注重模块化、可测试性和灵活性,以适应
2930
其主要分层如下:
3031

3132
1. 客户端服务层 (`src/services`):
32-
3333
- 位于 src/services/。
3434
- 这是客户端业务逻辑的核心层,负责封装各种业务操作和数据处理逻辑。
3535
- 环境适配: 根据不同的运行环境,服务层会选择合适的数据访问方式:
36-
- 本地数据库模式: 直接调用 `Model` 层进行数据操作,适用于浏览器 PGLite 和本地 Electron 应用。
37-
- 远程数据库模式: 通过 `tRPC` 客户端调用服务端 API,适用于需要云同步的场景。
36+
- 本地数据库模式: 直接调用 `Model` 层进行数据操作,适用于浏览器 PGLite 和本地 Electron 应用。
37+
- 远程数据库模式: 通过 `tRPC` 客户端调用服务端 API,适用于需要云同步的场景。
3838
- 类型转换: 对于简单的数据类型转换,直接在此层进行类型断言,如 `this.pluginModel.query() as Promise<LobeTool[]>`
3939
- 每个服务模块通常包含 `client.ts`(本地模式)、`server.ts`(远程模式)和 `type.ts`(接口定义)文件,在实现时应该确保本地模式和远程模式业务逻辑实现一致,只是数据库不同。
4040

4141
2. API 接口层 (`TRPC`):
42-
4342
- 位于 src/server/routers/
4443
- 使用 `tRPC` 构建类型安全的 API。Router 根据运行时环境(如 Edge Functions, Node.js Lambda)进行组织。
4544
- 负责接收客户端请求,并将其路由到相应的 `Service` 层进行处理。
4645
- 新建 lambda 端点时可以参考 src/server/routers/lambda/\_template.ts
4746

4847
3. 仓库层 (`Repositories`):
49-
5048
- 位于 src/database/repositories/。
5149
- 主要处理复杂的跨表查询和数据聚合逻辑,特别是当需要从多个 `Model` 获取数据并进行组合时。
5250
- 与 `Model` 层不同,`Repository` 层专注于复杂的业务查询场景,而不涉及简单的领域模型转换。
5351
- 当业务逻辑涉及多表关联、复杂的数据统计或需要事务处理时,会使用 `Repository` 层。
5452
- 如果数据操作简单(仅涉及单个 `Model`),则通常直接在 `src/services` 层调用 `Model` 并进行简单的类型断言。
5553

5654
4. 模型层 (`Models`):
57-
5855
- 位于 src/database/models/ (例如 src/database/models/plugin.ts 和 src/database/models/document.ts)。
5956
- 提供对数据库中各个表(由 src/database/schemas/ 中的 Drizzle ORM schema 定义)的基本 CRUD (创建、读取、更新、删除) 操作和简单的查询能力。
6057
- `Model` 类专注于单个数据表的直接操作,不涉及复杂的领域模型转换,这些转换通常在上层的 `src/services` 中通过类型断言完成。
@@ -65,11 +62,11 @@ LobeChat 的后端设计注重模块化、可测试性和灵活性,以适应
6562
- 客户端模式 (浏览器/PWA): 使用 PGLite (基于 WASM 的 PostgreSQL),数据存储在用户浏览器本地。
6663
- 服务端模式 (云部署): 使用远程 PostgreSQL 数据库。
6764
- Electron 桌面应用:
68-
- Electron 客户端会启动一个本地 Node.js 服务。
69-
- 本地服务通过 `tRPC` 与 Electron 的渲染进程通信。
70-
- 数据库选择依赖于是否开启云同步功能:
71-
- 云同步开启: 连接到远程 PostgreSQL 数据库。
72-
- 云同步关闭: 使用 PGLite (通过 Node.js 的 WASM 实现) 在本地存储数据。
65+
- Electron 客户端会启动一个本地 Node.js 服务。
66+
- 本地服务通过 `tRPC` 与 Electron 的渲染进程通信。
67+
- 数据库选择依赖于是否开启云同步功能:
68+
- 云同步开启: 连接到远程 PostgreSQL 数据库。
69+
- 云同步关闭: 使用 PGLite (通过 Node.js 的 WASM 实现) 在本地存储数据。
7370

7471
## 数据流向说明
7572

@@ -93,8 +90,87 @@ UI (Electron Renderer) → Zustand action → Client Service -> TRPC Client →
9390

9491
## 服务层 (Server Services)
9592

96-
- 位于 src/server/services/。
97-
- 核心职责是封装独立的、可复用的业务逻辑单元。这些服务应易于测试。
98-
- 平台差异抽象: 一个关键特性是通过其内部的 `impls` 子目录(例如 src/server/services/file/impls 包含 s3.ts 和 local.ts)来抹平不同运行环境带来的差异(例如云端使用 S3 存储,桌面版使用本地文件系统)。这使得上层(如 `tRPC` routers)无需关心底层具体实现。
99-
- 目标是使 `tRPC` router 层的逻辑尽可能纯粹,专注于请求处理和业务流程编排。
100-
- 服务可能会调用 `Repository` 层或直接调用 `Model` 层进行数据持久化和检索,也可能调用其他服务。
93+
- 位于 src/server/services/。
94+
- 核心职责是封装独立的、可复用的业务逻辑单元。这些服务应易于测试。
95+
- 平台差异抽象: 一个关键特性是通过其内部的 `impls` 子目录(例如 src/server/services/file/impls 包含 s3.ts 和 local.ts)来抹平不同运行环境带来的差异(例如云端使用 S3 存储,桌面版使用本地文件系统)。这使得上层(如 `tRPC` routers)无需关心底层具体实现。
96+
- 目标是使 `tRPC` router 层的逻辑尽可能纯粹,专注于请求处理和业务流程编排。
97+
- 服务可能会调用 `Repository` 层或直接调用 `Model` 层进行数据持久化和检索,也可能调用其他服务。
98+
99+
## 最佳实践 (Best Practices)
100+
101+
### 数据库操作封装原则
102+
103+
**连续的数据库操作应该封装到 Model 层**
104+
105+
当业务逻辑涉及多个相关的数据库操作时,建议将这些操作封装到 Model 层中,而不是在上层(Service 或 Router 层)中进行多次数据库调用。
106+
107+
**优势:**
108+
109+
- **代码复用**: Client DB 环境的 service 实现和 Server DB 的 lambda 层实现可以复用相同的 Model 方法
110+
- **事务一致性**: 相关的数据库操作可以在同一个方法中管理,便于维护数据一致性
111+
- **性能优化**: 减少数据库连接次数,提高查询效率
112+
- **职责清晰**: Model 层专注数据访问,上层专注业务协调
113+
114+
**示例:**
115+
116+
```typescript
117+
// ✅ 推荐:在 Model 层封装连续的数据库操作
118+
class GenerationBatchModel {
119+
async delete(id: string): Promise<{ deletedBatch: BatchItem; thumbnailUrls: string[] }> {
120+
// 1. 查询相关数据
121+
const batchWithGenerations = await this.db.query.generationBatches.findFirst({...});
122+
123+
// 2. 收集需要处理的数据
124+
const thumbnailUrls = [...];
125+
126+
// 3. 执行删除操作
127+
const [deletedBatch] = await this.db.delete(generationBatches)...;
128+
129+
return { deletedBatch, thumbnailUrls };
130+
}
131+
}
132+
133+
// ✅ 上层使用简洁
134+
const { thumbnailUrls } = await model.delete(id);
135+
await fileService.deleteFiles(thumbnailUrls);
136+
```
137+
138+
### 文件操作与数据库操作的执行顺序
139+
140+
**删除操作原则:数据库删除在前,文件删除在后**
141+
142+
当业务逻辑同时涉及数据库记录和文件系统操作时,应该遵循"数据库优先"的原则。
143+
144+
**原因:**
145+
146+
- **用户体验优先**: 如果先删除文件再删除数据库记录,可能出现文件已删除但数据库记录仍存在的情况,用户访问时会遇到文件不存在的错误
147+
- **影响程度较小**: 如果先删除数据库记录再删除文件,即使文件删除失败,用户也看不到这个记录,只是造成一些存储空间浪费,对用户体验影响更小
148+
- **数据一致性**: 数据库记录是业务逻辑的核心,应该优先保证其一致性
149+
150+
**示例:**
151+
152+
```typescript
153+
// ✅ 推荐:先删除数据库记录,再删除文件
154+
async deleteGeneration(id: string) {
155+
// 1. 先删除数据库记录
156+
const deletedGeneration = await generationModel.delete(id);
157+
158+
// 2. 再删除相关文件
159+
if (deletedGeneration.asset?.thumbnailUrl) {
160+
await fileService.deleteFile(deletedGeneration.asset.thumbnailUrl);
161+
}
162+
}
163+
164+
// ❌ 不推荐:先删除文件
165+
async deleteGeneration(id: string) {
166+
const generation = await generationModel.findById(id);
167+
168+
// 如果这里删除成功,但后面数据库删除失败,用户会遇到访问错误
169+
await fileService.deleteFile(generation.asset.thumbnailUrl);
170+
await generationModel.delete(id); // 可能失败
171+
}
172+
```
173+
174+
**创建操作原则:数据库创建在前,文件操作在后**
175+
176+
创建操作同样应该优先处理数据库记录,确保数据的一致性和完整性。

.cursor/rules/cursor-ux.mdc

Lines changed: 45 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,35 @@
11
---
2-
description:
3-
globs:
2+
description:
3+
globs:
44
alwaysApply: true
55
---
6+
67
# Guide to Optimize Output(Response) Rendering
78

89
## File Path and Code Symbol Rendering
910

1011
- When rendering file paths, use backtick wrapping instead of markdown links so they can be parsed as clickable links in Cursor IDE.
12+
- Good: `src/components/Button.tsx`
13+
- Bad: [src/components/Button.tsx](src/components/Button.tsx)
1114

12-
- Good: `src/components/Button.tsx`
13-
- Bad: [src/components/Button.tsx](mdc:src/components/Button.tsx)
15+
- Don't use line and column number in file path, this will make file path not clickable in Cursor IDE.
16+
- Good: `src/components/Button.tsx` `10:20` (add a space between the file path and the line and column number)
17+
- Bad: `src/components/Button.tsx:10:20`
1418

1519
- When rendering functions, variables, or other code symbols, use backtick wrapping so they can be parsed as navigable links in Cursor IDE
16-
- Good: The `useState` hook in `MyComponent`
17-
- Bad: The useState hook in MyComponent
18-
20+
- Good: The `useState` hook in `MyComponent`
21+
- Bad: The useState hook in MyComponent
22+
1923
## Markdown Render
2024

2125
- don't use br tag to wrap in table cell
2226

2327
## Terminal Command Output
2428

2529
- If terminal commands don't produce output, it's likely due to paging issues. Try piping the command to `cat` to ensure full output is displayed.
26-
- Good: `git show commit_hash -- file.txt | cat`
27-
- Good: `git log --oneline | cat`
28-
- Reason: Some git commands use pagers by default, which may prevent output from being captured properly
30+
- Good: `git show commit_hash -- file.txt | cat`
31+
- Good: `git log --oneline | cat`
32+
- Reason: Some git commands use pagers by default, which may prevent output from being captured properly
2933

3034
## Mermaid Diagram Generation: Strict Syntax Validation Checklist
3135

@@ -44,50 +48,56 @@ Before producing any Mermaid diagram, you **must** compare your final code line-
4448

4549
### Checklist Details
4650

47-
#### Rule 1: Edge Labels – Must Be Plain Text Only
51+
#### Rule 1: Edge Labels – Must Be Plain Text Only
52+
4853
> **Essence:** Anything inside `|...|` must contain pure, unformatted text. Absolutely NO Markdown, list markers, or parentheses/brackets allowed—these often cause rendering failures.
4954

50-
- **✅ Do:** `A -->|Process plain text data| B`
51-
- **❌ Don't:** `A -->|1. Ordered list item| B` (No numbered lists)
52-
- **❌ Don't:** `CC --"1. fetch('/api/...')"--> API` (No square brackets)
53-
- **❌ Don't:** `A -->|- Unordered list item| B` (No hyphen lists)
54-
- **❌ Don't:** `A -->|Transform (important)| B` (No parentheses)
55-
- **❌ Don't:** `A -->|Transform [important]| B` (No square brackets)
55+
- **✅ Do:** `A -->|Process plain text data| B`
56+
- **❌ Don't:** `A -->|1. Ordered list item| B` (No numbered lists)
57+
- **❌ Don't:** `CC --"1. fetch('/api/...')"--> API` (No square brackets)
58+
- **❌ Don't:** `A -->|- Unordered list item| B` (No hyphen lists)
59+
- **❌ Don't:** `A -->|Transform (important)| B` (No parentheses)
60+
- **❌ Don't:** `A -->|Transform [important]| B` (No square brackets)
61+
62+
#### Rule 2: Node Definition – Handle Special Characters with Care
5663

57-
#### Rule 2: Node Definition – Handle Special Characters with Care
5864
> **Essence:** When node text or subgraph titles contain special characters like `()` or `[]`, wrap the text in quotes to avoid conflicts with Mermaid shape syntax.
5965

60-
- **When your node text includes parentheses (e.g., 'React (JSX)'):**
61-
- **✅ Do:** `I_REACT["<b>React component (JSX)</b>"]` (Quotes wrap all text)
62-
- **❌ Don't:** `I_REACT(<b>React component (JSX)</b>)` (Wrong, Mermaid parses this as a shape)
63-
- **❌ Don't:** `subgraph Plugin Features (Plugins)` (Wrong, subgraph titles with parentheses must also be wrapped in quotes)
66+
- **When your node text includes parentheses (e.g., 'React (JSX)'):**
67+
- **✅ Do:** `I_REACT["<b>React component (JSX)</b>"]` (Quotes wrap all text)
68+
- **❌ Don't:** `I_REACT(<b>React component (JSX)</b>)` (Wrong, Mermaid parses this as a shape)
69+
- **❌ Don't:** `subgraph Plugin Features (Plugins)` (Wrong, subgraph titles with parentheses must also be wrapped in quotes)
70+
71+
#### Rule 3: Double Quotes in Text – Must Be Escaped
6472

65-
#### Rule 3: Double Quotes in Text – Must Be Escaped
6673
> **Essence:** Use `&quot;` for double quotes **inside node text**.
6774

68-
- **✅ Do:** `A[This node contains &quot;quotes&quot;]`
69-
- **❌ Don't:** `A[This node contains "quotes"]`
75+
- **✅ Do:** `A[This node contains &quot;quotes&quot;]`
76+
- **❌ Don't:** `A[This node contains "quotes"]`
77+
78+
#### Rule 4: All Formatting Must Use HTML Tags (NOT Markdown!)
7079

71-
#### Rule 4: All Formatting Must Use HTML Tags (NOT Markdown!)
7280
> **Essence:** For newlines, bold, and other text formatting in nodes, use HTML tags only. Markdown is not supported.
7381

74-
- **✅ Do (robust):** `A["<b>Bold</b> and <code>code</code><br>This is a new line"]`
75-
- **❌ Don't (not rendered):** `C["# This is a heading"]`
76-
- **❌ Don't (not rendered):** ``C["`const` means constant"]``
77-
- **⚠️ Warning (unreliable):** `B["Markdown **bold** might sometimes work but DON'T rely on it"]`
82+
- **✅ Do (robust):** `A["<b>Bold</b> and <code>code</code><br>This is a new line"]`
83+
- **❌ Don't (not rendered):** `C["# This is a heading"]`
84+
- **❌ Don't (not rendered):** ``C["`const` means constant"]``
85+
- **⚠️ Warning (unreliable):** `B["Markdown **bold** might sometimes work but DON'T rely on it"]`
86+
87+
#### Rule 5: No HTML Tags for Participants and Message Labels (Sequence Diagrams)
7888

79-
#### Rule 5: No HTML Tags for Participants and Message Labels (Sequence Diagrams)
8089
> **Important Addition:**
8190
> In Mermaid sequence diagrams, you MUST NOT use any HTML tags (such as `<b>`, `<code>`, etc.) in:
91+
>
8292
> - `participant` display names (`as` part)
8393
> - Message labels (the text after `:` in diagram flows)
8494
>
8595
> These tags are generally not rendered—they may appear as-is or cause compatibility issues.
8696

87-
- **✅ Do:** `participant A as Client`
88-
- **❌ Don't:** `participant A as <b>Client</b>`
89-
- **✅ Do:** `A->>B: 1. Establish connection`
90-
- **❌ Don't:** `A->>B: 1. <code>Establish connection</code>`
97+
- **✅ Do:** `participant A as Client`
98+
- **❌ Don't:** `participant A as <b>Client</b>`
99+
- **✅ Do:** `A->>B: 1. Establish connection`
100+
- **❌ Don't:** `A->>B: 1. <code>Establish connection</code>`
91101

92102
---
93103

File renamed without changes.

.cursor/rules/i18n/i18n-auto-attached.mdc

Lines changed: 0 additions & 6 deletions
This file was deleted.

.cursor/rules/project-introduce.mdc

Lines changed: 72 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,71 @@
11
---
2-
description:
3-
globs:
42
alwaysApply: true
53
---
4+
65
## Project Description
76

8-
You are developing an open-source, modern-design AI chat framework: lobe chat.
7+
You are developing an open-source, modern-design AI chat framework: lobe chat.
8+
9+
Emoji logo: 🤯
10+
11+
## Project Technologies Stack
12+
13+
read [package.json](mdc:package.json) to know all npm packages you can use. read [folder-structure.mdx](mdc:docs/development/basic/folder-structure.mdx) to learn project structure.
14+
15+
The project uses the following technologies:
16+
17+
- pnpm as package manager
18+
- Next.js 15 for frontend and backend, using app router instead of pages router
19+
- react 19, using hooks, functional components, react server components
20+
- TypeScript programming language
21+
- antd, @lobehub/ui for component framework
22+
- antd-style for css-in-js framework
23+
- react-layout-kit for flex layout
24+
- react-i18next for i18n
25+
- lucide-react, @ant-design/icons for icons
26+
- @lobehub/icons for AI provider/model logo icon
27+
- @formkit/auto-animate for react list animation
28+
- zustand for global state management
29+
- nuqs for type-safe search params state manager
30+
- SWR for react data fetch
31+
- aHooks for react hooks library
32+
- dayjs for date and time library
33+
- lodash-es for utility library
34+
- fast-deep-equal for deep comparison of JavaScript objects
35+
- zod for data validation
36+
- TRPC for type safe backend
37+
- PGLite for client DB and PostgreSQL for backend DB
38+
- Drizzle ORM
39+
- Vitest for testing, testing-library for react component test
40+
- Prettier for code formatting
41+
- ESLint for code linting
42+
- Cursor AI for code editing and AI coding assistance
43+
44+
Note: All tools and libraries used are the latest versions. The application only needs to be compatible with the latest browsers;
45+
46+
## Often used npm scripts
47+
48+
```bash
49+
# type check
50+
bun type-check
51+
52+
# install dependencies
53+
pnpm install
54+
55+
# !: don't any build script to check weather code can work after modify
56+
```
57+
58+
check [testing guide](./testing-guide.mdc) to learn test scripts.
59+
60+
## Project Description
961

10-
Emoji logo: 🤯
62+
You are developing an open-source, modern-design AI chat framework: lobe chat.
1163

64+
Emoji logo: 🤯
1265

1366
## Project Technologies Stack
1467

15-
read [package.json](mdc:package.json) to know all npm packages you can use.
16-
read [folder-structure.mdx](mdc:docs/development/basic/folder-structure.mdx) to learn project structure.
68+
read [package.json](mdc:package.json) to know all npm packages you can use. read [folder-structure.mdx](mdc:docs/development/basic/folder-structure.mdx) to learn project structure.
1769

1870
The project uses the following technologies:
1971

@@ -45,3 +97,17 @@ The project uses the following technologies:
4597
- Cursor AI for code editing and AI coding assistance
4698

4799
Note: All tools and libraries used are the latest versions. The application only needs to be compatible with the latest browsers;
100+
101+
## Often used npm scripts
102+
103+
```bash
104+
# type check
105+
bun type-check
106+
107+
# install dependencies
108+
pnpm install
109+
110+
# !: don't any build script to check weather code can work after modify
111+
```
112+
113+
check [testing guide](./testing-guide.mdc) to learn test scripts.

0 commit comments

Comments
 (0)