@lobehub/chat 1.88.13 → 1.88.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursor/rules/backend-architecture.mdc +94 -0
- package/.cursor/rules/cursor-ux-optimize.mdc +27 -0
- package/.cursor/rules/define-database-model.mdc +8 -0
- package/.cursor/rules/drizzle-schema-style-guide.mdc +202 -0
- package/.cursor/rules/i18n/i18n-auto-attached.mdc +6 -0
- package/.cursor/rules/i18n/i18n.mdc +183 -0
- package/.cursor/rules/packages/lobe-ui.mdc +72 -0
- package/.cursor/rules/packages/react-layout-kit.mdc +126 -0
- package/.cursor/rules/project-introduce.mdc +46 -0
- package/.cursor/rules/react-component.mdc +68 -0
- package/.cursorindexingignore +6 -0
- package/CHANGELOG.md +50 -0
- package/apps/desktop/src/main/controllers/AuthCtr.ts +5 -2
- package/changelog/v1.json +18 -0
- package/package.json +1 -1
- package/src/config/aiModels/deepseek.ts +1 -0
@@ -0,0 +1,94 @@
|
|
1
|
+
---
|
2
|
+
description:
|
3
|
+
globs: src/services/**/*,src/database/**/*,src/server/**/*
|
4
|
+
alwaysApply: false
|
5
|
+
---
|
6
|
+
# LobeChat 后端技术架构指南
|
7
|
+
|
8
|
+
本指南旨在阐述 LobeChat 项目的后端分层架构,重点介绍各核心目录的职责以及它们之间的协作方式。
|
9
|
+
|
10
|
+
## 目录结构映射
|
11
|
+
|
12
|
+
```
|
13
|
+
src/
|
14
|
+
├── server/
|
15
|
+
│ ├── routers/ # tRPC API 路由定义
|
16
|
+
│ └── services/ # 业务逻辑服务层
|
17
|
+
│ └── */impls/ # 平台特定实现
|
18
|
+
├── database/
|
19
|
+
│ ├── models/ # 数据模型 (单表 CRUD)
|
20
|
+
│ ├── repositories/ # 仓库层 (复杂查询/聚合)
|
21
|
+
│ └── schemas/ # Drizzle ORM 表定义
|
22
|
+
└── services/ # 客户端服务 (调用 tRPC 或直接访问 Model)
|
23
|
+
```
|
24
|
+
|
25
|
+
## 核心架构分层
|
26
|
+
|
27
|
+
LobeChat 的后端设计注重模块化、可测试性和灵活性,以适应不同的运行环境(如浏览器端 PGLite、服务端远程 PostgreSQL 以及 Electron 桌面应用)。
|
28
|
+
|
29
|
+
其主要分层如下:
|
30
|
+
|
31
|
+
1. **客户端服务层 (`src/services`)**:
|
32
|
+
* 位于 [src/services/](mdc:src/services)。
|
33
|
+
* 这是客户端业务逻辑的核心层,负责封装各种业务操作和数据处理逻辑。
|
34
|
+
* **环境适配**: 根据不同的运行环境,服务层会选择合适的数据访问方式:
|
35
|
+
* **本地数据库模式**: 直接调用 `Model` 层进行数据操作,适用于浏览器 PGLite 和本地 Electron 应用。
|
36
|
+
* **远程数据库模式**: 通过 `tRPC` 客户端调用服务端 API,适用于需要云同步的场景。
|
37
|
+
* **类型转换**: 对于简单的数据类型转换,直接在此层进行类型断言,如 `this.pluginModel.query() as Promise<LobeTool[]>`(参见 [src/services/plugin/client.ts](mdc:src/services/plugin/client.ts))。
|
38
|
+
* 每个服务模块通常包含 `client.ts`(本地模式)、`server.ts`(远程模式)和 `type.ts`(接口定义)文件。
|
39
|
+
|
40
|
+
2. **API 接口层 (`TRPC`)**:
|
41
|
+
* 位于 [src/server/routers/](mdc:src/server/routers)。
|
42
|
+
* 使用 `tRPC` 构建类型安全的 API。Router 根据运行时环境(如 Edge Functions, Node.js Lambda)进行组织。
|
43
|
+
* 负责接收客户端请求,并将其路由到相应的 `Service` 层进行处理。
|
44
|
+
|
45
|
+
3. **服务端服务层 (`server/services`)**:
|
46
|
+
* 位于 [src/server/services/](mdc:src/server/services)。
|
47
|
+
* 核心职责是封装独立的、可复用的业务逻辑单元。这些服务应易于测试。
|
48
|
+
* **平台差异抽象**: 一个关键特性是通过其内部的 `impls` 子目录(例如 [src/server/services/file/impls/](mdc:src/server/services/file/impls) 包含 `s3.ts` 和 `local.ts`)来抹平不同运行环境带来的差异(例如云端使用 S3 存储,桌面版使用本地文件系统)。这使得上层(如 `tRPC` routers)无需关心底层具体实现。
|
49
|
+
* 目标是使 `tRPC` router 层的逻辑尽可能纯粹,专注于请求处理和业务流程编排。
|
50
|
+
* 服务会调用 `Repository` 层或直接调用 `Model` 层进行数据持久化和检索,也可能调用其他服务。
|
51
|
+
|
52
|
+
4. **仓库层 (`Repositories`)**:
|
53
|
+
* 位于 [src/database/repositories/](mdc:src/database/repositories)。
|
54
|
+
* 主要处理**复杂的跨表查询和数据聚合**逻辑,特别是当需要从**多个 `Model`** 获取数据并进行组合时。
|
55
|
+
* 与 `Model` 层不同,`Repository` 层专注于复杂的业务查询场景,而不涉及简单的领域模型转换。
|
56
|
+
* 当业务逻辑涉及多表关联、复杂的数据统计或需要事务处理时,会使用 `Repository` 层。
|
57
|
+
* 如果数据操作简单(仅涉及单个 `Model`),则通常直接在 `src/services` 层调用 `Model` 并进行简单的类型断言。
|
58
|
+
|
59
|
+
5. **模型层 (`Models`)**:
|
60
|
+
* 位于 [src/database/models/](mdc:src/database/models) (例如 [src/database/models/plugin.ts](mdc:src/database/models/plugin.ts) 和 [src/database/models/document.ts](mdc:src/database/models/document.ts))。
|
61
|
+
* 提供对数据库中各个表(由 [src/database/schemas/](mdc:src/database/schemas) 中的 Drizzle ORM schema 定义)的基本 CRUD (创建、读取、更新、删除) 操作和简单的查询能力。
|
62
|
+
* `Model` 类专注于单个数据表的直接操作,**不涉及复杂的领域模型转换**,这些转换通常在上层的 `src/services` 中通过类型断言完成。
|
63
|
+
|
64
|
+
6. **数据库 (`Database`)**:
|
65
|
+
* **客户端模式 (浏览器/PWA)**: 使用 PGLite (基于 WASM 的 PostgreSQL),数据存储在用户浏览器本地。
|
66
|
+
* **服务端模式 (云部署)**: 使用远程 PostgreSQL 数据库。
|
67
|
+
* **Electron 桌面应用**:
|
68
|
+
* Electron 客户端会启动一个本地 Node.js 服务。
|
69
|
+
* 本地服务通过 `tRPC` 与 Electron 的渲染进程通信。
|
70
|
+
* 数据库选择依赖于是否开启**云同步**功能:
|
71
|
+
* **云同步开启**: 连接到远程 PostgreSQL 数据库。
|
72
|
+
* **云同步关闭**: 使用 PGLite (通过 Node.js 的 WASM 实现) 在本地存储数据。
|
73
|
+
|
74
|
+
## 数据流向说明
|
75
|
+
|
76
|
+
### 浏览器/PWA 模式
|
77
|
+
```
|
78
|
+
UI (React) → Zustand State → Model Layer → PGLite (本地数据库)
|
79
|
+
```
|
80
|
+
|
81
|
+
### 服务端模式
|
82
|
+
```
|
83
|
+
UI (React) → Zustand State → tRPC Client → tRPC Routers → Services → Repositories/Models → Remote PostgreSQL
|
84
|
+
```
|
85
|
+
|
86
|
+
### Electron 桌面应用模式
|
87
|
+
```
|
88
|
+
UI (Electron Renderer) → Zustand State → tRPC Client → 本地 Node.js 服务 → tRPC Routers → Services → Repositories/Models → PGLite/Remote PostgreSQL (取决于云同步设置)
|
89
|
+
```
|
90
|
+
|
91
|
+
|
92
|
+
|
93
|
+
|
94
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
---
|
2
|
+
description:
|
3
|
+
globs:
|
4
|
+
alwaysApply: false
|
5
|
+
---
|
6
|
+
## Formatting Response
|
7
|
+
|
8
|
+
This is about how you should format your responses.
|
9
|
+
|
10
|
+
### Render Markdown Table
|
11
|
+
|
12
|
+
- Be aware that the cursor chat you are in can't render markdown table correctly.
|
13
|
+
- IMPORTANT: Tables need to be rendered in plain text and not markdown
|
14
|
+
|
15
|
+
When rendering tables, do not use markdown table syntax or plain text alone. Instead, place the entire table inside a code/text block (using triple backticks). This ensures the table formatting is preserved and readable in the chat interface.
|
16
|
+
|
17
|
+
Example:
|
18
|
+
|
19
|
+
```plaintext
|
20
|
+
+----+---------+-----------+
|
21
|
+
| ID | Name | Role |
|
22
|
+
+----+---------+-----------+
|
23
|
+
| 1 | Alice | Admin |
|
24
|
+
| 2 | Bob | User |
|
25
|
+
| 3 | Charlie | Moderator |
|
26
|
+
+----+---------+-----------+
|
27
|
+
```
|
@@ -0,0 +1,8 @@
|
|
1
|
+
---
|
2
|
+
description:
|
3
|
+
globs: src/database/models/**/*
|
4
|
+
alwaysApply: false
|
5
|
+
---
|
6
|
+
1. first read [lobe-chat-backend-architecture.mdc](mdc:.cursor/rules/lobe-chat-backend-architecture.mdc)
|
7
|
+
2. refer to the [_template.ts](mdc:src/database/models/_template.ts) to create new model
|
8
|
+
3. if an operation involves multiple models or complex queries, consider defining it in the `repositories` layer under `src/database/repositories/`
|
@@ -0,0 +1,202 @@
|
|
1
|
+
---
|
2
|
+
description:
|
3
|
+
globs: src/database/schemas/*
|
4
|
+
alwaysApply: false
|
5
|
+
---
|
6
|
+
# Drizzle ORM Schema Style Guide for lobe-chat
|
7
|
+
|
8
|
+
This document outlines the conventions and best practices for defining PostgreSQL Drizzle ORM schemas within the lobe-chat project.
|
9
|
+
|
10
|
+
## Configuration
|
11
|
+
|
12
|
+
- Drizzle configuration is managed in [drizzle.config.ts](mdc:drizzle.config.ts)
|
13
|
+
- Schema files are located in the src/database/schemas/ directory
|
14
|
+
- Migration files are output to `src/database/migrations/`
|
15
|
+
- The project uses `postgresql` dialect with `strict: true`
|
16
|
+
|
17
|
+
## Helper Functions
|
18
|
+
|
19
|
+
Commonly used column definitions, especially for timestamps, are centralized in [src/database/schemas/_helpers.ts](mdc:src/database/schemas/_helpers.ts):
|
20
|
+
- `timestamptz(name: string)`: Creates a timestamp column with timezone
|
21
|
+
- `createdAt()`, `updatedAt()`, `accessedAt()`: Helper functions for standard timestamp columns
|
22
|
+
- `timestamps`: An object `{ createdAt, updatedAt, accessedAt }` for easy inclusion in table definitions
|
23
|
+
|
24
|
+
## Naming Conventions
|
25
|
+
|
26
|
+
- **Table Names**: Use plural snake_case (e.g., `users`, `agents`, `session_groups`)
|
27
|
+
- **Column Names**: Use snake_case (e.g., `user_id`, `created_at`, `background_color`)
|
28
|
+
|
29
|
+
## Column Definitions
|
30
|
+
|
31
|
+
### Primary Keys (PKs)
|
32
|
+
- Typically `text('id')` (or `varchar('id')` for some OIDC tables)
|
33
|
+
- Often use `.$defaultFn(() => idGenerator('table_name'))` for automatic ID generation with meaningful prefixes
|
34
|
+
- **ID Prefix Purpose**: Makes it easy for users and developers to distinguish different entity types at a glance
|
35
|
+
- For internal/system tables that users don't need to see, can use `uuid` or auto-increment keys
|
36
|
+
- Composite PKs are defined using `primaryKey({ columns: [t.colA, t.colB] })`
|
37
|
+
|
38
|
+
### Foreign Keys (FKs)
|
39
|
+
- Defined using `.references(() => otherTable.id, { onDelete: 'cascade' | 'set null' | 'no action' })`
|
40
|
+
- FK columns are usually named `related_table_singular_name_id` (e.g., `user_id` references `users.id`)
|
41
|
+
- Most tables include a `user_id` column referencing `users.id` with `onDelete: 'cascade'`
|
42
|
+
|
43
|
+
### Timestamps
|
44
|
+
- Consistently use the `...timestamps` spread from [_helpers.ts](mdc:src/database/schemas/_helpers.ts) for `created_at`, `updated_at`, and `accessed_at` columns
|
45
|
+
|
46
|
+
### Default Values
|
47
|
+
- `.$defaultFn(() => expression)` for dynamic defaults (e.g., `idGenerator()`, `randomSlug()`)
|
48
|
+
- `.default(staticValue)` for static defaults (e.g., `boolean('enabled').default(true)`)
|
49
|
+
|
50
|
+
### Indexes
|
51
|
+
- Defined in the table's second argument: `pgTable('name', {...columns}, (t) => ({ indexName: indexType().on(...) }))`
|
52
|
+
- Use `uniqueIndex()` for unique constraints and `index()` for non-unique indexes
|
53
|
+
- Naming pattern: `table_name_column(s)_idx` or `table_name_column(s)_unique`
|
54
|
+
- Many tables feature a `clientId: text('client_id')` column, often part of a composite unique index with `user_id`
|
55
|
+
|
56
|
+
### Data Types
|
57
|
+
- Common types: `text`, `varchar`, `jsonb`, `boolean`, `integer`, `uuid`, `pgTable`
|
58
|
+
- For `jsonb` fields, specify the TypeScript type using `.$type<MyType>()` for better type safety
|
59
|
+
|
60
|
+
## Zod Schemas & Type Inference
|
61
|
+
|
62
|
+
- Utilize `drizzle-zod` to generate Zod schemas for validation:
|
63
|
+
- `createInsertSchema(tableName)`
|
64
|
+
- `createSelectSchema(tableName)` (less common)
|
65
|
+
- Export inferred types: `export type NewEntity = typeof tableName.$inferInsert;` and `export type EntityItem = typeof tableName.$inferSelect;`
|
66
|
+
|
67
|
+
## Relations
|
68
|
+
|
69
|
+
- Table relationships are defined centrally in [src/database/schemas/relations.ts](mdc:src/database/schemas/relations.ts) using the `relations()` utility from `drizzle-orm`
|
70
|
+
|
71
|
+
## Code Style & Structure
|
72
|
+
|
73
|
+
- **File Organization**: Each main database entity typically has its own schema file (e.g., [user.ts](mdc:src/database/schemas/user.ts), [agent.ts](mdc:src/database/schemas/agent.ts))
|
74
|
+
- All schemas are re-exported from [src/database/schemas/index.ts](mdc:src/database/schemas/index.ts)
|
75
|
+
- **ESLint**: Files often start with `/* eslint-disable sort-keys-fix/sort-keys-fix */`
|
76
|
+
- **Comments**: Use JSDoc-style comments to explain the purpose of tables and complex columns, fields that are self-explanatory do not require jsdoc explanations, such as id, user_id, etc.
|
77
|
+
|
78
|
+
## Example Pattern
|
79
|
+
|
80
|
+
```typescript
|
81
|
+
// From src/database/schemas/agent.ts
|
82
|
+
export const agents = pgTable(
|
83
|
+
'agents',
|
84
|
+
{
|
85
|
+
id: text('id')
|
86
|
+
.primaryKey()
|
87
|
+
.$defaultFn(() => idGenerator('agents'))
|
88
|
+
.notNull(),
|
89
|
+
slug: varchar('slug', { length: 100 })
|
90
|
+
.$defaultFn(() => randomSlug(4))
|
91
|
+
.unique(),
|
92
|
+
userId: text('user_id')
|
93
|
+
.references(() => users.id, { onDelete: 'cascade' })
|
94
|
+
.notNull(),
|
95
|
+
clientId: text('client_id'),
|
96
|
+
chatConfig: jsonb('chat_config').$type<LobeAgentChatConfig>(),
|
97
|
+
...timestamps,
|
98
|
+
},
|
99
|
+
// return array instead of object, the object style is deprecated
|
100
|
+
(t) => [
|
101
|
+
uniqueIndex('client_id_user_id_unique').on(t.clientId, t.userId),
|
102
|
+
],
|
103
|
+
);
|
104
|
+
|
105
|
+
export const insertAgentSchema = createInsertSchema(agents);
|
106
|
+
export type NewAgent = typeof agents.$inferInsert;
|
107
|
+
export type AgentItem = typeof agents.$inferSelect;
|
108
|
+
```
|
109
|
+
|
110
|
+
## Common Patterns
|
111
|
+
|
112
|
+
### 1. userId + clientId Pattern (Legacy)
|
113
|
+
Some existing tables include both fields for different purposes:
|
114
|
+
|
115
|
+
```typescript
|
116
|
+
// Example from agents table (legacy pattern)
|
117
|
+
userId: text('user_id')
|
118
|
+
.references(() => users.id, { onDelete: 'cascade' })
|
119
|
+
.notNull(),
|
120
|
+
clientId: text('client_id'),
|
121
|
+
|
122
|
+
// Usually with a composite unique index
|
123
|
+
clientIdUnique: uniqueIndex('agents_client_id_user_id_unique').on(t.clientId, t.userId),
|
124
|
+
```
|
125
|
+
|
126
|
+
- **`userId`**: Server-side user association, ensures data belongs to specific user
|
127
|
+
- **`clientId`**: Unique key for import/export operations, supports data migration between instances
|
128
|
+
- **Current Status**: New tables should NOT include `clientId` unless specifically needed for import/export functionality
|
129
|
+
- **Note**: This pattern is being phased out for new features to simplify the schema
|
130
|
+
|
131
|
+
### 2. Junction Tables (Many-to-Many Relationships)
|
132
|
+
Use composite primary keys for relationship tables:
|
133
|
+
|
134
|
+
```typescript
|
135
|
+
// Example: agents_knowledge_bases (from agent.ts)
|
136
|
+
export const agentsKnowledgeBases = pgTable(
|
137
|
+
'agents_knowledge_bases',
|
138
|
+
{
|
139
|
+
agentId: text('agent_id').references(() => agents.id, { onDelete: 'cascade' }).notNull(),
|
140
|
+
knowledgeBaseId: text('knowledge_base_id').references(() => knowledgeBases.id, { onDelete: 'cascade' }).notNull(),
|
141
|
+
userId: text('user_id').references(() => users.id, { onDelete: 'cascade' }).notNull(),
|
142
|
+
enabled: boolean('enabled').default(true),
|
143
|
+
...timestamps,
|
144
|
+
},
|
145
|
+
(t) => [
|
146
|
+
primaryKey({ columns: [t.agentId, t.knowledgeBaseId] }),
|
147
|
+
],
|
148
|
+
);
|
149
|
+
```
|
150
|
+
|
151
|
+
**Pattern**: `{entity1}Id` + `{entity2}Id` as composite PK, plus `userId` for ownership
|
152
|
+
|
153
|
+
### 3. OIDC Tables Special Patterns
|
154
|
+
OIDC tables use `varchar` IDs instead of `text` with custom generators:
|
155
|
+
|
156
|
+
```typescript
|
157
|
+
// Example from oidc.ts
|
158
|
+
export const oidcAuthorizationCodes = pgTable('oidc_authorization_codes', {
|
159
|
+
id: varchar('id', { length: 255 }).primaryKey(), // varchar not text
|
160
|
+
data: jsonb('data').notNull(),
|
161
|
+
expiresAt: timestamptz('expires_at').notNull(),
|
162
|
+
// ... other fields
|
163
|
+
});
|
164
|
+
```
|
165
|
+
|
166
|
+
**Reason**: OIDC standards expect specific ID formats and lengths
|
167
|
+
|
168
|
+
### 4. File Processing with Async Tasks
|
169
|
+
File-related tables reference async task IDs for background processing:
|
170
|
+
|
171
|
+
```typescript
|
172
|
+
// Example from files table
|
173
|
+
export const files = pgTable('files', {
|
174
|
+
// ... other fields
|
175
|
+
chunkTaskId: uuid('chunk_task_id').references(() => asyncTasks.id, { onDelete: 'set null' }),
|
176
|
+
embeddingTaskId: uuid('embedding_task_id').references(() => asyncTasks.id, { onDelete: 'set null' }),
|
177
|
+
// ...
|
178
|
+
});
|
179
|
+
```
|
180
|
+
|
181
|
+
**Purpose**:
|
182
|
+
- Track file chunking progress (breaking files into smaller pieces)
|
183
|
+
- Track embedding generation progress (converting text to vectors)
|
184
|
+
- Allow querying task status and handling failures
|
185
|
+
|
186
|
+
### 5. Slug Pattern (Legacy)
|
187
|
+
Some entities include auto-generated slugs - this is legacy code:
|
188
|
+
|
189
|
+
```typescript
|
190
|
+
slug: varchar('slug', { length: 100 })
|
191
|
+
.$defaultFn(() => randomSlug(4))
|
192
|
+
.unique(),
|
193
|
+
|
194
|
+
// Often with composite unique constraint
|
195
|
+
slugUserIdUnique: uniqueIndex('slug_user_id_unique').on(t.slug, t.userId),
|
196
|
+
```
|
197
|
+
|
198
|
+
**Current usage**: Only used to identify default agents/sessions (legacy pattern)
|
199
|
+
**Future refactor**: Will likely be replaced with `isDefault: boolean()` field
|
200
|
+
**Note**: Avoid using slugs for new features - prefer explicit boolean flags for status tracking
|
201
|
+
|
202
|
+
By following these guidelines, maintain consistency, type safety, and maintainability across database schema definitions.
|
@@ -0,0 +1,183 @@
|
|
1
|
+
---
|
2
|
+
description: i18n workflow and troubleshooting
|
3
|
+
globs:
|
4
|
+
alwaysApply: false
|
5
|
+
---
|
6
|
+
# LobeChat Internationalization (i18n) Guide
|
7
|
+
|
8
|
+
## Architecture Overview
|
9
|
+
|
10
|
+
LobeChat uses **react-i18next** for internationalization with a well-structured namespace approach:
|
11
|
+
|
12
|
+
- **Default language**: Chinese (zh-CN) - serves as the source language
|
13
|
+
- **Supported locales**: 18 languages including English, Japanese, Korean, Arabic, etc.
|
14
|
+
- **Framework**: react-i18next with Next.js app router
|
15
|
+
- **Translation automation**: [@lobehub/i18n-cli](mdc:package.json) for automated translations, config file: .i18nrc.js
|
16
|
+
|
17
|
+
## Directory Structure
|
18
|
+
|
19
|
+
```
|
20
|
+
src/locales/
|
21
|
+
├── default/ # Source language files (zh-CN)
|
22
|
+
│ ├── index.ts # Namespace exports
|
23
|
+
│ ├── common.ts # Common translations
|
24
|
+
│ ├── chat.ts # Chat-related translations
|
25
|
+
│ ├── setting.ts # Settings translations
|
26
|
+
│ └── ... # Other namespace files
|
27
|
+
└── resources.ts # Type definitions and locale config
|
28
|
+
|
29
|
+
locales/ # Translated files
|
30
|
+
├── en-US/ # English translations
|
31
|
+
│ ├── common.json # Common translations
|
32
|
+
│ ├── chat.json # Chat translations
|
33
|
+
│ ├── setting.json # Settings translations
|
34
|
+
│ └── ... # Other namespace JSON files
|
35
|
+
├── ja-JP/ # Japanese translations
|
36
|
+
│ ├── common.json
|
37
|
+
│ ├── chat.json
|
38
|
+
│ └── ...
|
39
|
+
└── ... # Other language folders
|
40
|
+
```
|
41
|
+
|
42
|
+
## Workflow for Adding New Translations
|
43
|
+
|
44
|
+
### 1. Add New Translation Keys
|
45
|
+
|
46
|
+
**Step 1**: Add translation key to the appropriate namespace file in [src/locales/default/](mdc:src/locales/default)
|
47
|
+
|
48
|
+
```typescript
|
49
|
+
// Example: src/locales/default/common.ts
|
50
|
+
export default {
|
51
|
+
// ... existing keys
|
52
|
+
newFeature: {
|
53
|
+
title: "新功能标题",
|
54
|
+
description: "功能描述文案",
|
55
|
+
button: "操作按钮",
|
56
|
+
},
|
57
|
+
};
|
58
|
+
```
|
59
|
+
|
60
|
+
**Step 2**: If creating a new namespace, export it in [src/locales/default/index.ts](mdc:src/locales/default/index.ts)
|
61
|
+
|
62
|
+
```typescript
|
63
|
+
import newNamespace from "./newNamespace";
|
64
|
+
|
65
|
+
const resources = {
|
66
|
+
// ... existing namespaces
|
67
|
+
newNamespace,
|
68
|
+
} as const;
|
69
|
+
```
|
70
|
+
|
71
|
+
### 2. Translation Process
|
72
|
+
|
73
|
+
**Development Mode** (Recommended):
|
74
|
+
|
75
|
+
- Manually add Chinese translations to corresponding JSON files in `locales/zh-CN/namespace.json`, this avoids running slow automation during development
|
76
|
+
- Don't auto add translations for other language like English etc, most of developer is Chinese,
|
77
|
+
|
78
|
+
**Production Mode**:
|
79
|
+
|
80
|
+
```bash
|
81
|
+
# Generate translations for all languages
|
82
|
+
npm run i18n
|
83
|
+
```
|
84
|
+
|
85
|
+
## Usage in Components
|
86
|
+
|
87
|
+
### Basic Usage with Hooks
|
88
|
+
|
89
|
+
```tsx
|
90
|
+
import { useTranslation } from "react-i18next";
|
91
|
+
|
92
|
+
const MyComponent = () => {
|
93
|
+
const { t } = useTranslation("common"); // namespace
|
94
|
+
|
95
|
+
return (
|
96
|
+
<div>
|
97
|
+
<h1>{t("newFeature.title")}</h1>
|
98
|
+
<p>{t("newFeature.description")}</p>
|
99
|
+
<button>{t("newFeature.button")}</button>
|
100
|
+
</div>
|
101
|
+
);
|
102
|
+
};
|
103
|
+
```
|
104
|
+
|
105
|
+
### With Parameters
|
106
|
+
|
107
|
+
```tsx
|
108
|
+
const { t } = useTranslation("common");
|
109
|
+
|
110
|
+
// Translation key with interpolation
|
111
|
+
<p>{t("welcome.message", { name: "John" })}</p>;
|
112
|
+
|
113
|
+
// Corresponding locale file:
|
114
|
+
// welcome: { message: '欢迎 {{name}} 使用!' }
|
115
|
+
```
|
116
|
+
|
117
|
+
### Multiple Namespaces
|
118
|
+
|
119
|
+
```tsx
|
120
|
+
const { t } = useTranslation(['common', 'chat']);
|
121
|
+
|
122
|
+
// Access different namespaces
|
123
|
+
<button>{t('common:save')}</button>
|
124
|
+
<span>{t('chat:typing')}</span>
|
125
|
+
```
|
126
|
+
|
127
|
+
## Type Safety
|
128
|
+
|
129
|
+
The project uses TypeScript for type-safe translations with auto-generated types from [src/locales/resources.ts](mdc:src/locales/resources.ts):
|
130
|
+
|
131
|
+
```typescript
|
132
|
+
import type { DefaultResources, NS, Locales } from "@/locales/resources";
|
133
|
+
|
134
|
+
// Available types:
|
135
|
+
// - NS: Available namespace keys ('common' | 'chat' | 'setting' | ...)
|
136
|
+
// - Locales: Supported locale codes ('en-US' | 'zh-CN' | 'ja-JP' | ...)
|
137
|
+
|
138
|
+
// Type-safe namespace usage
|
139
|
+
const namespace: NS = "common"; // ✅ Valid
|
140
|
+
const locale: Locales = "en-US"; // ✅ Valid
|
141
|
+
```
|
142
|
+
|
143
|
+
## Best Practices
|
144
|
+
|
145
|
+
### 1. Namespace Organization
|
146
|
+
|
147
|
+
- **common**: Shared UI elements (buttons, labels, actions)
|
148
|
+
- **chat**: Chat-specific features
|
149
|
+
- **setting**: Configuration and settings
|
150
|
+
- **error**: Error messages and handling
|
151
|
+
- **[feature]**: Feature-specific or page specific namespaces
|
152
|
+
|
153
|
+
### 2. Key Naming Conventions
|
154
|
+
|
155
|
+
```typescript
|
156
|
+
// ✅ Good: Hierarchical structure
|
157
|
+
export default {
|
158
|
+
modal: {
|
159
|
+
confirm: {
|
160
|
+
title: "确认操作",
|
161
|
+
message: "确定要执行此操作吗?",
|
162
|
+
actions: {
|
163
|
+
confirm: "确认",
|
164
|
+
cancel: "取消",
|
165
|
+
},
|
166
|
+
},
|
167
|
+
},
|
168
|
+
};
|
169
|
+
|
170
|
+
// ❌ Avoid: Flat structure
|
171
|
+
export default {
|
172
|
+
modalConfirmTitle: "确认操作",
|
173
|
+
modalConfirmMessage: "确定要执行此操作吗?",
|
174
|
+
};
|
175
|
+
```
|
176
|
+
|
177
|
+
## Troubleshooting
|
178
|
+
|
179
|
+
### Missing Translation Keys
|
180
|
+
|
181
|
+
- Check if the key exists in src/locales/default/namespace.ts
|
182
|
+
- Ensure proper namespace import in component
|
183
|
+
- Ensure new namespaces are exported in [src/locales/default/index.ts](mdc:src/locales/default/index.ts)
|
@@ -0,0 +1,72 @@
|
|
1
|
+
---
|
2
|
+
description: @lobehub/ui components list
|
3
|
+
globs:
|
4
|
+
alwaysApply: false
|
5
|
+
---
|
6
|
+
## @lobehub/ui Components
|
7
|
+
|
8
|
+
- General
|
9
|
+
ActionIcon
|
10
|
+
ActionIconGroup
|
11
|
+
Block
|
12
|
+
Button
|
13
|
+
Icon
|
14
|
+
- Data Display
|
15
|
+
Avatar
|
16
|
+
Collapse
|
17
|
+
FileTypeIcon
|
18
|
+
FluentEmoji
|
19
|
+
GuideCard
|
20
|
+
Highlighter
|
21
|
+
Hotkey
|
22
|
+
Image
|
23
|
+
List
|
24
|
+
Markdown
|
25
|
+
MaterialFileTypeIcon
|
26
|
+
Mermaid
|
27
|
+
Segmented
|
28
|
+
Snippet
|
29
|
+
SortableList
|
30
|
+
Tag
|
31
|
+
Tooltip
|
32
|
+
Video
|
33
|
+
- Data Entry
|
34
|
+
AutoComplete
|
35
|
+
CodeEditor
|
36
|
+
ColorSwatches
|
37
|
+
CopyButton
|
38
|
+
DatePicker
|
39
|
+
EditableText
|
40
|
+
EmojiPicker
|
41
|
+
Form
|
42
|
+
FormModal
|
43
|
+
HotkeyInput
|
44
|
+
ImageSelect
|
45
|
+
Input
|
46
|
+
SearchBar
|
47
|
+
Select
|
48
|
+
SliderWithInput
|
49
|
+
ThemeSwitch
|
50
|
+
- Feedback
|
51
|
+
Alert
|
52
|
+
Drawer
|
53
|
+
Modal
|
54
|
+
- Layout
|
55
|
+
DraggablePanel
|
56
|
+
Footer
|
57
|
+
Grid
|
58
|
+
Header
|
59
|
+
Layout
|
60
|
+
MaskShadow
|
61
|
+
ScrollShadow
|
62
|
+
- Navigation
|
63
|
+
Burger
|
64
|
+
Dropdown
|
65
|
+
Menu
|
66
|
+
SideNav
|
67
|
+
Tabs
|
68
|
+
Toc
|
69
|
+
- Theme
|
70
|
+
ConfigProvider
|
71
|
+
FontLoader
|
72
|
+
ThemeProvider
|
@@ -0,0 +1,126 @@
|
|
1
|
+
---
|
2
|
+
description: react flex layout package `react-layout-kit` usage
|
3
|
+
globs:
|
4
|
+
alwaysApply: false
|
5
|
+
---
|
6
|
+
# React Layout Kit 使用指南
|
7
|
+
|
8
|
+
`react-layout-kit` 是一个功能丰富的 React flex 布局组件库,在 lobe-chat 项目中被广泛使用。以下是重点组件的使用方法:
|
9
|
+
|
10
|
+
## Flexbox 组件
|
11
|
+
|
12
|
+
Flexbox 是最常用的布局组件,用于创建弹性布局,类似于 CSS 的 `display: flex`。
|
13
|
+
|
14
|
+
### 基本用法
|
15
|
+
|
16
|
+
```jsx
|
17
|
+
import { Flexbox } from 'react-layout-kit';
|
18
|
+
|
19
|
+
// 默认垂直布局
|
20
|
+
<Flexbox>
|
21
|
+
<div>子元素1</div>
|
22
|
+
<div>子元素2</div>
|
23
|
+
</Flexbox>
|
24
|
+
|
25
|
+
// 水平布局
|
26
|
+
<Flexbox horizontal>
|
27
|
+
<div>左侧元素</div>
|
28
|
+
<div>右侧元素</div>
|
29
|
+
</Flexbox>
|
30
|
+
```
|
31
|
+
|
32
|
+
### 常用属性
|
33
|
+
|
34
|
+
- `horizontal`: 布尔值,设置为水平方向布局
|
35
|
+
- `flex`: 数值或字符串,控制 flex 属性
|
36
|
+
- `gap`: 数值,设置子元素之间的间距
|
37
|
+
- `align`: 对齐方式,如 'center', 'flex-start' 等
|
38
|
+
- `justify`: 主轴对齐方式,如 'space-between', 'center' 等
|
39
|
+
- `padding`: 内边距值
|
40
|
+
- `paddingInline`: 水平内边距值
|
41
|
+
- `paddingBlock`: 垂直内边距值
|
42
|
+
- `width/height`: 设置宽高,通常用 `'100%'` 或具体像素值
|
43
|
+
- `style`: 自定义样式对象
|
44
|
+
|
45
|
+
### 实际应用示例
|
46
|
+
|
47
|
+
```jsx
|
48
|
+
// 经典三栏布局
|
49
|
+
<Flexbox horizontal height={'100%'} width={'100%'}>
|
50
|
+
{/* 左侧边栏 */}
|
51
|
+
<Flexbox
|
52
|
+
width={260}
|
53
|
+
style={{
|
54
|
+
borderRight: `1px solid ${theme.colorBorderSecondary}`,
|
55
|
+
height: '100%',
|
56
|
+
overflowY: 'auto',
|
57
|
+
}}
|
58
|
+
>
|
59
|
+
<SidebarContent />
|
60
|
+
</Flexbox>
|
61
|
+
|
62
|
+
{/* 中间内容区 */}
|
63
|
+
<Flexbox
|
64
|
+
flex={1}
|
65
|
+
style={{
|
66
|
+
height: '100%',
|
67
|
+
}}
|
68
|
+
>
|
69
|
+
{/* 主要内容 */}
|
70
|
+
<Flexbox flex={1} padding={24} style={{ overflowY: 'auto' }}>
|
71
|
+
<MainContent />
|
72
|
+
</Flexbox>
|
73
|
+
|
74
|
+
{/* 底部区域 */}
|
75
|
+
<Flexbox
|
76
|
+
style={{
|
77
|
+
borderTop: `1px solid ${theme.colorBorderSecondary}`,
|
78
|
+
padding: '16px 24px',
|
79
|
+
}}
|
80
|
+
>
|
81
|
+
<Footer />
|
82
|
+
</Flexbox>
|
83
|
+
</Flexbox>
|
84
|
+
</Flexbox>
|
85
|
+
```
|
86
|
+
|
87
|
+
## Center 组件
|
88
|
+
|
89
|
+
Center 是对 Flexbox 的封装,使子元素水平和垂直居中。
|
90
|
+
|
91
|
+
### 基本用法
|
92
|
+
|
93
|
+
```jsx
|
94
|
+
import { Center } from 'react-layout-kit';
|
95
|
+
|
96
|
+
<Center width={'100%'} height={'100%'}>
|
97
|
+
<Content />
|
98
|
+
</Center>
|
99
|
+
```
|
100
|
+
|
101
|
+
Center 组件继承了 Flexbox 的所有属性,同时默认设置了居中对齐。主要用于快速创建居中布局。
|
102
|
+
|
103
|
+
### 实际应用示例
|
104
|
+
|
105
|
+
```jsx
|
106
|
+
// 登录页面居中布局
|
107
|
+
<Flexbox height={'100%'} width={'100%'}>
|
108
|
+
<Center height={'100%'} width={'100%'}>
|
109
|
+
<LoginForm />
|
110
|
+
</Center>
|
111
|
+
</Flexbox>
|
112
|
+
|
113
|
+
// 图标居中显示
|
114
|
+
<Center className={styles.icon} flex={'none'} height={40} width={40}>
|
115
|
+
<Icon icon={icon} size={24} />
|
116
|
+
</Center>
|
117
|
+
```
|
118
|
+
|
119
|
+
## 最佳实践
|
120
|
+
|
121
|
+
1. 使用 `flex={1}` 让组件填充可用空间
|
122
|
+
2. 使用 `gap` 代替传统的 margin 设置元素间距
|
123
|
+
3. 嵌套 Flexbox 创建复杂布局
|
124
|
+
4. 设置 `overflow: 'auto'` 使内容可滚动
|
125
|
+
5. 使用 `horizontal` 创建水平布局,默认为垂直布局
|
126
|
+
6. 与 `antd-style` 的 `useTheme` hook 配合使用创建主题响应式的布局
|
@@ -0,0 +1,46 @@
|
|
1
|
+
---
|
2
|
+
description:
|
3
|
+
globs:
|
4
|
+
alwaysApply: true
|
5
|
+
---
|
6
|
+
## Project Description
|
7
|
+
|
8
|
+
You are developing an open-source, modern-design AI chat framework: lobe chat.
|
9
|
+
|
10
|
+
Emoji logo: 🤯
|
11
|
+
|
12
|
+
|
13
|
+
## Project Technologies Stack
|
14
|
+
|
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.
|
17
|
+
|
18
|
+
The project uses the following technologies:
|
19
|
+
|
20
|
+
- pnpm as package manager
|
21
|
+
- Next.js 15 for frontend and backend, using app router instead of pages router
|
22
|
+
- react 19, using hooks, functional components, react server components
|
23
|
+
- TypeScript programming language
|
24
|
+
- antd, @lobehub/ui for component framework
|
25
|
+
- antd-style for css-in-js framework
|
26
|
+
- react-layout-kit for flex layout
|
27
|
+
- react-i18next for i18n
|
28
|
+
- lucide-react, @ant-design/icons for icons
|
29
|
+
- @lobehub/icons for AI provider/model logo icon
|
30
|
+
- @formkit/auto-animate for react list animation
|
31
|
+
- zustand for global state management
|
32
|
+
- nuqs for type-safe search params state manager
|
33
|
+
- SWR for react data fetch
|
34
|
+
- aHooks for react hooks library
|
35
|
+
- dayjs for date and time library
|
36
|
+
- lodash-es for utility library
|
37
|
+
- zod for data validation
|
38
|
+
- TRPC for type safe backend
|
39
|
+
- PGLite for client DB and PostgreSQL for backend DB
|
40
|
+
- Drizzle ORM
|
41
|
+
- Vitest for testing, testing-library for react component test
|
42
|
+
- Prettier for code formatting
|
43
|
+
- ESLint for code linting
|
44
|
+
- Cursor AI for code editing and AI coding assistance
|
45
|
+
|
46
|
+
Note: All tools and libraries used are the latest versions. The application only needs to be compatible with the latest browsers;
|
@@ -0,0 +1,68 @@
|
|
1
|
+
---
|
2
|
+
description:
|
3
|
+
globs: *.tsx
|
4
|
+
alwaysApply: false
|
5
|
+
---
|
6
|
+
# react component 编写指南
|
7
|
+
|
8
|
+
- 如果要写复杂样式的话用 antd-style ,简单的话可以用 style 属性直接写内联样式
|
9
|
+
- 如果需要 flex 布局或者居中布局应该使用 react-layout-kit
|
10
|
+
- 选择组件库中的组件时优先使用 [lobe-ui.mdc](mdc:.cursor/rules/package-usage/lobe-ui.mdc) 有的,然后才是 antd 的,不知道 @lobehub/ui 的组件怎么用,有哪些属性,就自己搜下这个项目其它地方怎么用的,不要瞎猜
|
11
|
+
|
12
|
+
## 访问 theme 的两种方式
|
13
|
+
|
14
|
+
### 使用 antd-style 的 useTheme hook
|
15
|
+
|
16
|
+
```tsx
|
17
|
+
import { useTheme } from 'antd-style';
|
18
|
+
|
19
|
+
const MyComponent = () => {
|
20
|
+
const theme = useTheme();
|
21
|
+
|
22
|
+
return (
|
23
|
+
<div style={{
|
24
|
+
color: theme.colorPrimary,
|
25
|
+
backgroundColor: theme.colorBgContainer,
|
26
|
+
padding: theme.padding,
|
27
|
+
borderRadius: theme.borderRadius
|
28
|
+
}}>
|
29
|
+
使用主题 token 的组件
|
30
|
+
</div>
|
31
|
+
);
|
32
|
+
}
|
33
|
+
```
|
34
|
+
|
35
|
+
### 使用 antd-style 的 createStyles
|
36
|
+
|
37
|
+
```tsx
|
38
|
+
const useStyles = createStyles(({ css, token }) => {
|
39
|
+
return {
|
40
|
+
container: css`
|
41
|
+
background-color: ${token.colorBgContainer};
|
42
|
+
border-radius: ${token.borderRadius}px;
|
43
|
+
padding: ${token.padding}px;
|
44
|
+
color: ${token.colorText};
|
45
|
+
`,
|
46
|
+
title: css`
|
47
|
+
font-size: ${token.fontSizeLG}px;
|
48
|
+
font-weight: ${token.fontWeightStrong};
|
49
|
+
margin-bottom: ${token.marginSM}px;
|
50
|
+
`,
|
51
|
+
content: css`
|
52
|
+
font-size: ${token.fontSize}px;
|
53
|
+
line-height: ${token.lineHeight};
|
54
|
+
`
|
55
|
+
};
|
56
|
+
});
|
57
|
+
|
58
|
+
const Card: FC<CardProps> = ({ title, content }) => {
|
59
|
+
const { styles } = useStyles();
|
60
|
+
|
61
|
+
return (
|
62
|
+
<Flexbox className={styles.container}>
|
63
|
+
<div className={styles.title}>{title}</div>
|
64
|
+
<div className={styles.content}>{content}</div>
|
65
|
+
</Flexbox>
|
66
|
+
);
|
67
|
+
};
|
68
|
+
```
|
package/CHANGELOG.md
CHANGED
@@ -2,6 +2,56 @@
|
|
2
2
|
|
3
3
|
# Changelog
|
4
4
|
|
5
|
+
### [Version 1.88.15](https://github.com/lobehub/lobe-chat/compare/v1.88.14...v1.88.15)
|
6
|
+
|
7
|
+
<sup>Released on **2025-05-29**</sup>
|
8
|
+
|
9
|
+
#### 💄 Styles
|
10
|
+
|
11
|
+
- **misc**: Add fc ability to deepseek-reasoner model.
|
12
|
+
|
13
|
+
<br/>
|
14
|
+
|
15
|
+
<details>
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
17
|
+
|
18
|
+
#### Styles
|
19
|
+
|
20
|
+
- **misc**: Add fc ability to deepseek-reasoner model, closes [#8006](https://github.com/lobehub/lobe-chat/issues/8006) ([1511c75](https://github.com/lobehub/lobe-chat/commit/1511c75))
|
21
|
+
|
22
|
+
</details>
|
23
|
+
|
24
|
+
<div align="right">
|
25
|
+
|
26
|
+
[](#readme-top)
|
27
|
+
|
28
|
+
</div>
|
29
|
+
|
30
|
+
### [Version 1.88.14](https://github.com/lobehub/lobe-chat/compare/v1.88.13...v1.88.14)
|
31
|
+
|
32
|
+
<sup>Released on **2025-05-28**</sup>
|
33
|
+
|
34
|
+
#### 🐛 Bug Fixes
|
35
|
+
|
36
|
+
- **misc**: Cant invoke the application after OIDC authorization in Windows 11.
|
37
|
+
|
38
|
+
<br/>
|
39
|
+
|
40
|
+
<details>
|
41
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
42
|
+
|
43
|
+
#### What's fixed
|
44
|
+
|
45
|
+
- **misc**: Cant invoke the application after OIDC authorization in Windows 11, closes [#7900](https://github.com/lobehub/lobe-chat/issues/7900) ([585e386](https://github.com/lobehub/lobe-chat/commit/585e386))
|
46
|
+
|
47
|
+
</details>
|
48
|
+
|
49
|
+
<div align="right">
|
50
|
+
|
51
|
+
[](#readme-top)
|
52
|
+
|
53
|
+
</div>
|
54
|
+
|
5
55
|
### [Version 1.88.13](https://github.com/lobehub/lobe-chat/compare/v1.88.12...v1.88.13)
|
6
56
|
|
7
57
|
<sup>Released on **2025-05-27**</sup>
|
@@ -217,12 +217,15 @@ export default class AuthCtr extends ControllerModule {
|
|
217
217
|
} else {
|
218
218
|
// Handle protocol callback via second-instance event on Windows and Linux
|
219
219
|
logger.debug('Registering second-instance event handler for Windows/Linux');
|
220
|
-
app.on('second-instance', (event, commandLine) => {
|
220
|
+
app.on('second-instance', async (event, commandLine) => {
|
221
221
|
// Find the URL from command line arguments
|
222
222
|
const url = commandLine.find((arg) => arg.startsWith(`${protocolPrefix}://`));
|
223
223
|
if (url) {
|
224
224
|
logger.info(`Found URL from second-instance command line arguments: ${url}`);
|
225
|
-
this.handleAuthCallback(url);
|
225
|
+
const { success } = await this.handleAuthCallback(url);
|
226
|
+
if (success) {
|
227
|
+
this.app.browserManager.getMainWindow().show();
|
228
|
+
}
|
226
229
|
} else {
|
227
230
|
logger.warn('Protocol URL not found in second-instance command line arguments');
|
228
231
|
}
|
package/changelog/v1.json
CHANGED
@@ -1,4 +1,22 @@
|
|
1
1
|
[
|
2
|
+
{
|
3
|
+
"children": {
|
4
|
+
"improvements": [
|
5
|
+
"Add fc ability to deepseek-reasoner model."
|
6
|
+
]
|
7
|
+
},
|
8
|
+
"date": "2025-05-29",
|
9
|
+
"version": "1.88.15"
|
10
|
+
},
|
11
|
+
{
|
12
|
+
"children": {
|
13
|
+
"fixes": [
|
14
|
+
"Cant invoke the application after OIDC authorization in Windows 11."
|
15
|
+
]
|
16
|
+
},
|
17
|
+
"date": "2025-05-28",
|
18
|
+
"version": "1.88.14"
|
19
|
+
},
|
2
20
|
{
|
3
21
|
"children": {},
|
4
22
|
"date": "2025-05-27",
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@lobehub/chat",
|
3
|
-
"version": "1.88.
|
3
|
+
"version": "1.88.15",
|
4
4
|
"description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
|
5
5
|
"keywords": [
|
6
6
|
"framework",
|