@lobehub/chat 1.128.2 → 1.128.3
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/i18n.mdc +97 -95
- package/CHANGELOG.md +25 -0
- package/changelog/v1.json +9 -0
- package/package.json +2 -2
- package/packages/const/src/auth.ts +1 -1
- package/packages/database/package.json +4 -2
- package/packages/database/src/index.ts +1 -0
- package/packages/database/src/repositories/dataExporter/index.test.ts +3 -3
- package/src/app/(backend)/_deprecated/createBizOpenAI/createAzureOpenai.ts +1 -1
- package/src/app/(backend)/_deprecated/createBizOpenAI/createOpenai.ts +1 -1
- package/src/app/(backend)/api/webhooks/casdoor/route.ts +1 -1
- package/src/app/(backend)/api/webhooks/casdoor/validateRequest.ts +1 -1
- package/src/app/(backend)/api/webhooks/clerk/route.ts +1 -1
- package/src/app/(backend)/api/webhooks/logto/route.ts +1 -1
- package/src/app/(backend)/api/webhooks/logto/validateRequest.ts +1 -1
- package/src/{config → envs}/__tests__/analytics.test.ts +1 -1
- package/src/{config → envs}/__tests__/app.test.ts +1 -1
- package/src/{config → envs}/__tests__/client.test.ts +1 -1
- package/src/layout/AuthProvider/index.tsx +1 -1
- package/src/libs/next-auth/auth.config.ts +1 -1
- package/src/libs/next-auth/sso-providers/auth0.ts +1 -1
- package/src/libs/next-auth/sso-providers/authelia.ts +1 -1
- package/src/libs/next-auth/sso-providers/authentik.ts +1 -1
- package/src/libs/next-auth/sso-providers/azure-ad.ts +1 -1
- package/src/libs/next-auth/sso-providers/cloudflare-zero-trust.ts +1 -1
- package/src/libs/next-auth/sso-providers/generic-oidc.ts +1 -1
- package/src/libs/next-auth/sso-providers/github.ts +1 -1
- package/src/libs/next-auth/sso-providers/logto.ts +1 -1
- package/src/libs/next-auth/sso-providers/microsoft-entra-id-helper.ts +1 -1
- package/src/libs/next-auth/sso-providers/zitadel.ts +1 -1
- package/src/libs/oidc-provider/adapter.ts +4 -5
- package/src/libs/oidc-provider/provider.ts +1 -1
- package/src/libs/trpc/async/asyncAuth.ts +1 -1
- package/src/libs/trpc/async/context.ts +1 -1
- package/src/middleware.ts +1 -1
- package/src/server/globalConfig/_deprecated.test.ts +1 -1
- package/src/server/globalConfig/_deprecated.ts +1 -1
- package/src/server/globalConfig/genServerAiProviderConfig.test.ts +2 -2
- package/src/server/globalConfig/genServerAiProviderConfig.ts +1 -1
- package/src/server/globalConfig/index.ts +2 -2
- package/src/server/modules/ModelRuntime/apiKeyManager.ts +1 -1
- package/src/server/modules/ModelRuntime/index.test.ts +1 -1
- package/src/server/modules/ModelRuntime/index.ts +1 -1
- package/src/server/modules/S3/index.ts +1 -1
- package/src/server/routers/async/file.ts +1 -1
- package/src/server/services/agent/index.ts +2 -1
- package/src/server/services/aiChat/index.test.ts +1 -1
- package/src/server/services/aiChat/index.ts +2 -1
- package/src/server/services/chunk/index.ts +1 -1
- package/src/server/services/document/index.ts +1 -1
- package/src/server/services/file/impls/s3.test.ts +13 -13
- package/src/server/services/file/impls/s3.ts +1 -1
- package/src/server/services/file/index.ts +1 -1
- package/src/server/services/generation/index.ts +1 -1
- package/src/server/services/nextAuthUser/index.ts +1 -1
- package/src/server/services/user/index.test.ts +1 -1
- package/src/server/services/user/index.ts +1 -1
- package/src/services/__tests__/upload.test.ts +1 -1
- package/src/services/file/_deprecated.test.ts +1 -1
- package/src/services/upload.ts +1 -1
- /package/src/{config → envs}/__tests__/auth.test.ts +0 -0
- /package/src/{config → envs}/auth.ts +0 -0
- /package/src/{config → envs}/file.ts +0 -0
- /package/src/{config → envs}/llm.ts +0 -0
package/.cursor/rules/i18n.mdc
CHANGED
|
@@ -2,117 +2,115 @@
|
|
|
2
2
|
globs: *.tsx
|
|
3
3
|
alwaysApply: false
|
|
4
4
|
---
|
|
5
|
-
# LobeChat
|
|
5
|
+
# LobeChat Internationalization Guide
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Key Points
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
- Default language: Chinese (zh-CN) as the source language
|
|
10
|
+
- Supported languages: 18 languages including English, Japanese, Korean, Arabic, etc.
|
|
11
|
+
- Framework: react-i18next with Next.js app router
|
|
12
|
+
- Translation automation: @lobehub/i18n-cli for automatic translation, config file: .i18nrc.js
|
|
13
|
+
- Never manually modify any json file. You can only modify files in `default` folder
|
|
10
14
|
|
|
11
|
-
|
|
12
|
-
- 支持语言:18 种语言,包括英语、日语、韩语、阿拉伯语等
|
|
13
|
-
- 框架:react-i18next 配合 Next.js app router
|
|
14
|
-
- 翻译自动化:@lobehub/i18n-cli 用于自动翻译,配置文件:.i18nrc.js
|
|
15
|
-
|
|
16
|
-
## 目录结构
|
|
15
|
+
## Directory Structure
|
|
17
16
|
|
|
18
17
|
```
|
|
19
18
|
src/locales/
|
|
20
|
-
├── default/ #
|
|
21
|
-
│ ├── index.ts #
|
|
22
|
-
│ ├── common.ts #
|
|
23
|
-
│ ├── chat.ts #
|
|
24
|
-
│ ├── setting.ts #
|
|
25
|
-
│ └── ... #
|
|
26
|
-
└── resources.ts #
|
|
27
|
-
|
|
28
|
-
locales/ #
|
|
29
|
-
├── en-US/ #
|
|
30
|
-
│ ├── common.json #
|
|
31
|
-
│ ├── chat.json #
|
|
32
|
-
│ ├── setting.json #
|
|
33
|
-
│ └── ... #
|
|
34
|
-
├── ja-JP/ #
|
|
19
|
+
├── default/ # Source language files (zh-CN)
|
|
20
|
+
│ ├── index.ts # Namespace exports
|
|
21
|
+
│ ├── common.ts # Common translations
|
|
22
|
+
│ ├── chat.ts # Chat-related translations
|
|
23
|
+
│ ├── setting.ts # Settings translations
|
|
24
|
+
│ └── ... # Other namespace files
|
|
25
|
+
└── resources.ts # Type definitions and language configuration
|
|
26
|
+
|
|
27
|
+
locales/ # Translation files
|
|
28
|
+
├── en-US/ # English translations
|
|
29
|
+
│ ├── common.json # Common translations
|
|
30
|
+
│ ├── chat.json # Chat translations
|
|
31
|
+
│ ├── setting.json # Settings translations
|
|
32
|
+
│ └── ... # Other namespace JSON files
|
|
33
|
+
├── ja-JP/ # Japanese translations
|
|
35
34
|
│ ├── common.json
|
|
36
35
|
│ ├── chat.json
|
|
37
36
|
│ └── ...
|
|
38
|
-
└── ... #
|
|
37
|
+
└── ... # Other language folders
|
|
39
38
|
```
|
|
40
39
|
|
|
41
|
-
##
|
|
40
|
+
## Workflow for Adding New Translations
|
|
42
41
|
|
|
43
|
-
### 1.
|
|
42
|
+
### 1. Adding New Translation Keys
|
|
44
43
|
|
|
45
|
-
|
|
44
|
+
Step 1: Add translation keys in the corresponding namespace files under src/locales/default directory
|
|
46
45
|
|
|
47
46
|
```typescript
|
|
48
|
-
//
|
|
47
|
+
// Example: src/locales/default/common.ts
|
|
49
48
|
export default {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
49
|
+
// ... existing keys
|
|
50
|
+
newFeature: {
|
|
51
|
+
title: '新功能标题',
|
|
52
|
+
description: '功能描述文案',
|
|
53
|
+
button: '操作按钮',
|
|
54
|
+
},
|
|
56
55
|
};
|
|
57
56
|
```
|
|
58
57
|
|
|
59
|
-
|
|
58
|
+
Step 2: If creating a new namespace, export it in src/locales/default/index.ts
|
|
60
59
|
|
|
61
60
|
```typescript
|
|
62
|
-
import newNamespace from
|
|
61
|
+
import newNamespace from './newNamespace';
|
|
63
62
|
|
|
64
63
|
const resources = {
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
// ... existing namespaces
|
|
65
|
+
newNamespace,
|
|
67
66
|
} as const;
|
|
68
67
|
```
|
|
69
68
|
|
|
70
|
-
### 2.
|
|
69
|
+
### 2. Translation Process
|
|
71
70
|
|
|
72
|
-
|
|
71
|
+
Development mode:
|
|
73
72
|
|
|
74
|
-
|
|
75
|
-
但是为了立马能看到效果,还是需要先翻译 `locales/zh-CN/namespace.json`,不需要翻译其它语言。
|
|
73
|
+
Generally, you don't need to help me run the automatic translation tool as it takes a long time. I'll run it myself when needed. However, to see immediate results, you still need to translate `locales/zh-CN/namespace.json` first, no need to translate other languages.
|
|
76
74
|
|
|
77
|
-
|
|
75
|
+
Production mode:
|
|
78
76
|
|
|
79
77
|
```bash
|
|
80
|
-
#
|
|
78
|
+
# Generate translations for all languages
|
|
81
79
|
npm run i18n
|
|
82
80
|
```
|
|
83
81
|
|
|
84
|
-
##
|
|
82
|
+
## Usage in Components
|
|
85
83
|
|
|
86
|
-
###
|
|
84
|
+
### Basic Usage
|
|
87
85
|
|
|
88
86
|
```tsx
|
|
89
|
-
import { useTranslation } from
|
|
87
|
+
import { useTranslation } from 'react-i18next';
|
|
90
88
|
|
|
91
89
|
const MyComponent = () => {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
90
|
+
const { t } = useTranslation('common');
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<div>
|
|
94
|
+
<h1>{t('newFeature.title')}</h1>
|
|
95
|
+
<p>{t('newFeature.description')}</p>
|
|
96
|
+
<button>{t('newFeature.button')}</button>
|
|
97
|
+
</div>
|
|
98
|
+
);
|
|
101
99
|
};
|
|
102
100
|
```
|
|
103
101
|
|
|
104
|
-
###
|
|
102
|
+
### Usage with Parameters
|
|
105
103
|
|
|
106
104
|
```tsx
|
|
107
|
-
const { t } = useTranslation(
|
|
105
|
+
const { t } = useTranslation('common');
|
|
108
106
|
|
|
109
|
-
<p>{t(
|
|
107
|
+
<p>{t('welcome.message', { name: 'John' })}</p>;
|
|
110
108
|
|
|
111
|
-
//
|
|
112
|
-
// welcome: { message: '
|
|
109
|
+
// Corresponding language file:
|
|
110
|
+
// welcome: { message: 'Welcome {{name}}!' }
|
|
113
111
|
```
|
|
114
112
|
|
|
115
|
-
###
|
|
113
|
+
### Multiple Namespaces
|
|
116
114
|
|
|
117
115
|
```tsx
|
|
118
116
|
const { t } = useTranslation(['common', 'chat']);
|
|
@@ -121,59 +119,63 @@ const { t } = useTranslation(['common', 'chat']);
|
|
|
121
119
|
<span>{t('chat:typing')}</span>
|
|
122
120
|
```
|
|
123
121
|
|
|
124
|
-
##
|
|
122
|
+
## Type Safety
|
|
125
123
|
|
|
126
|
-
|
|
124
|
+
The project uses TypeScript to implement type-safe translations, with types automatically generated from src/locales/resources.ts:
|
|
127
125
|
|
|
128
126
|
```typescript
|
|
129
|
-
import type { DefaultResources,
|
|
127
|
+
import type { DefaultResources, Locales, NS } from '@/locales/resources';
|
|
130
128
|
|
|
131
|
-
//
|
|
132
|
-
// - NS:
|
|
133
|
-
// - Locales:
|
|
129
|
+
// Available types:
|
|
130
|
+
// - NS: Available namespace keys ('common' | 'chat' | 'setting' | ...)
|
|
131
|
+
// - Locales: Supported language codes ('en-US' | 'zh-CN' | 'ja-JP' | ...)
|
|
134
132
|
|
|
135
|
-
const namespace: NS =
|
|
136
|
-
const locale: Locales =
|
|
133
|
+
const namespace: NS = 'common';
|
|
134
|
+
const locale: Locales = 'en-US';
|
|
137
135
|
```
|
|
138
136
|
|
|
139
|
-
##
|
|
137
|
+
## Best Practices
|
|
140
138
|
|
|
141
|
-
### 1.
|
|
139
|
+
### 1. Namespace Organization
|
|
142
140
|
|
|
143
|
-
- common:
|
|
144
|
-
- chat:
|
|
145
|
-
- setting:
|
|
146
|
-
- error:
|
|
147
|
-
- [feature]:
|
|
148
|
-
- components:
|
|
141
|
+
- common: Shared UI elements (buttons, labels, actions)
|
|
142
|
+
- chat: Chat-specific functionality
|
|
143
|
+
- setting: Configuration and settings
|
|
144
|
+
- error: Error messages and handling
|
|
145
|
+
- [feature]: Feature-specific or page-specific namespaces
|
|
146
|
+
- components: Reusable component text
|
|
149
147
|
|
|
150
|
-
### 2.
|
|
148
|
+
### 2. Key Naming Conventions
|
|
151
149
|
|
|
152
150
|
```typescript
|
|
153
|
-
// ✅
|
|
151
|
+
// ✅ Good: Hierarchical structure
|
|
154
152
|
export default {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
},
|
|
153
|
+
modal: {
|
|
154
|
+
confirm: {
|
|
155
|
+
title: '确认操作',
|
|
156
|
+
message: '确定要执行此操作吗?',
|
|
157
|
+
actions: {
|
|
158
|
+
confirm: '确认',
|
|
159
|
+
cancel: '取消',
|
|
160
|
+
},
|
|
164
161
|
},
|
|
162
|
+
},
|
|
165
163
|
};
|
|
166
164
|
|
|
167
|
-
// ❌
|
|
165
|
+
// ❌ Avoid: Flat structure
|
|
168
166
|
export default {
|
|
169
|
-
|
|
170
|
-
|
|
167
|
+
modalConfirmTitle: '确认操作',
|
|
168
|
+
modalConfirmMessage: '确定要执行此操作吗?',
|
|
171
169
|
};
|
|
172
170
|
```
|
|
173
171
|
|
|
174
|
-
##
|
|
172
|
+
## Troubleshooting
|
|
173
|
+
|
|
174
|
+
### Missing Translation Keys
|
|
175
175
|
|
|
176
|
-
|
|
176
|
+
- Check if the key exists in src/locales/default/namespace.ts
|
|
177
|
+
- Ensure the namespace is correctly imported in the component
|
|
178
|
+
- Ensure new namespaces are exported in src/locales/default/index.ts
|
|
177
179
|
|
|
178
180
|
- 检查键是否存在于 src/locales/default/namespace.ts 中
|
|
179
181
|
- 确保在组件中正确导入命名空间
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
### [Version 1.128.3](https://github.com/lobehub/lobe-chat/compare/v1.128.2...v1.128.3)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2025-09-13**</sup>
|
|
8
|
+
|
|
9
|
+
#### 🐛 Bug Fixes
|
|
10
|
+
|
|
11
|
+
- **misc**: Fix open chat page with float link modal.
|
|
12
|
+
|
|
13
|
+
<br/>
|
|
14
|
+
|
|
15
|
+
<details>
|
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
17
|
+
|
|
18
|
+
#### What's fixed
|
|
19
|
+
|
|
20
|
+
- **misc**: Fix open chat page with float link modal, closes [#9235](https://github.com/lobehub/lobe-chat/issues/9235) ([2c677e5](https://github.com/lobehub/lobe-chat/commit/2c677e5))
|
|
21
|
+
|
|
22
|
+
</details>
|
|
23
|
+
|
|
24
|
+
<div align="right">
|
|
25
|
+
|
|
26
|
+
[](#readme-top)
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
5
30
|
### [Version 1.128.2](https://github.com/lobehub/lobe-chat/compare/v1.128.1...v1.128.2)
|
|
6
31
|
|
|
7
32
|
<sup>Released on **2025-09-13**</sup>
|
package/changelog/v1.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/chat",
|
|
3
|
-
"version": "1.128.
|
|
3
|
+
"version": "1.128.3",
|
|
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",
|
|
@@ -157,7 +157,7 @@
|
|
|
157
157
|
"@lobehub/charts": "^2.1.2",
|
|
158
158
|
"@lobehub/chat-plugin-sdk": "^1.32.4",
|
|
159
159
|
"@lobehub/chat-plugins-gateway": "^1.9.0",
|
|
160
|
-
"@lobehub/editor": "^1.8.
|
|
160
|
+
"@lobehub/editor": "^1.8.5",
|
|
161
161
|
"@lobehub/icons": "^2.32.2",
|
|
162
162
|
"@lobehub/market-sdk": "^0.22.7",
|
|
163
163
|
"@lobehub/tts": "^2.0.1",
|
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
"name": "@lobechat/database",
|
|
3
3
|
"version": "1.0.0",
|
|
4
4
|
"private": true,
|
|
5
|
-
"
|
|
6
|
-
|
|
5
|
+
"exports": {
|
|
6
|
+
".": "./src/index.ts",
|
|
7
|
+
"./schemas": "./src/schemas/index.ts"
|
|
8
|
+
},
|
|
7
9
|
"scripts": {
|
|
8
10
|
"test": "npm run test:client-db && npm run test:server-db",
|
|
9
11
|
"test:client-db": "vitest run",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './type';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
2
|
|
|
3
3
|
import { clientDB, initializeDB } from '@/database/client/db';
|
|
4
|
+
|
|
4
5
|
import {
|
|
5
6
|
agents,
|
|
6
7
|
agentsKnowledgeBases,
|
|
@@ -16,9 +17,8 @@ import {
|
|
|
16
17
|
topics,
|
|
17
18
|
userSettings,
|
|
18
19
|
users,
|
|
19
|
-
} from '
|
|
20
|
-
import { LobeChatDatabase } from '
|
|
21
|
-
|
|
20
|
+
} from '../../schemas';
|
|
21
|
+
import { LobeChatDatabase } from '../../type';
|
|
22
22
|
import { DATA_EXPORT_CONFIG, DataExporterRepos } from './index';
|
|
23
23
|
|
|
24
24
|
let db = clientDB as LobeChatDatabase;
|
|
@@ -2,7 +2,7 @@ import { ChatErrorType } from '@lobechat/types';
|
|
|
2
2
|
import OpenAI, { ClientOptions } from 'openai';
|
|
3
3
|
import urlJoin from 'url-join';
|
|
4
4
|
|
|
5
|
-
import { getLLMConfig } from '@/
|
|
5
|
+
import { getLLMConfig } from '@/envs/llm';
|
|
6
6
|
|
|
7
7
|
// create Azure OpenAI Instance
|
|
8
8
|
export const createAzureOpenai = (params: {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ChatErrorType } from '@lobechat/types';
|
|
2
2
|
import OpenAI from 'openai';
|
|
3
3
|
|
|
4
|
-
import { getLLMConfig } from '@/
|
|
4
|
+
import { getLLMConfig } from '@/envs/llm';
|
|
5
5
|
|
|
6
6
|
// create OpenAI instance
|
|
7
7
|
export const createOpenai = (userApiKey: string | null, endpoint?: string | null) => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server';
|
|
2
2
|
|
|
3
|
-
import { authEnv } from '@/config/auth';
|
|
4
3
|
import { serverDB } from '@/database/server';
|
|
4
|
+
import { authEnv } from '@/envs/auth';
|
|
5
5
|
import { pino } from '@/libs/logger';
|
|
6
6
|
import { NextAuthUserService } from '@/server/services/nextAuthUser';
|
|
7
7
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server';
|
|
2
2
|
|
|
3
|
-
import { authEnv } from '@/config/auth';
|
|
4
3
|
import { isServerMode } from '@/const/version';
|
|
5
4
|
import { serverDB } from '@/database/server';
|
|
5
|
+
import { authEnv } from '@/envs/auth';
|
|
6
6
|
import { pino } from '@/libs/logger';
|
|
7
7
|
import { UserService } from '@/server/services/user';
|
|
8
8
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server';
|
|
2
2
|
|
|
3
|
-
import { authEnv } from '@/config/auth';
|
|
4
3
|
import { serverDB } from '@/database/server';
|
|
4
|
+
import { authEnv } from '@/envs/auth';
|
|
5
5
|
import { pino } from '@/libs/logger';
|
|
6
6
|
import { NextAuthUserService } from '@/server/services/nextAuthUser';
|
|
7
7
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @vitest-environment node
|
|
2
2
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
3
|
|
|
4
|
-
import { analyticsEnv, getAnalyticsConfig } from '
|
|
4
|
+
import { analyticsEnv, getAnalyticsConfig } from '../analytics';
|
|
5
5
|
|
|
6
6
|
beforeEach(() => {
|
|
7
7
|
// 在每个测试用例之前,清除所有的 console.warn mock
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @vitest-environment node
|
|
2
2
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
3
|
|
|
4
|
-
import { getAppConfig } from '
|
|
4
|
+
import { getAppConfig } from '../app';
|
|
5
5
|
|
|
6
6
|
// Stub the global process object to safely mock environment variables
|
|
7
7
|
vi.stubGlobal('process', {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { NextAuthConfig } from 'next-auth';
|
|
2
2
|
|
|
3
|
-
import { getAuthConfig } from '@/config/auth';
|
|
4
3
|
import { getServerDBConfig } from '@/config/db';
|
|
4
|
+
import { getAuthConfig } from '@/envs/auth';
|
|
5
5
|
|
|
6
6
|
import { LobeNextAuthDbAdapter } from './adapter';
|
|
7
7
|
import { ssoProviders } from './sso-providers';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import AzureAD from 'next-auth/providers/azure-ad';
|
|
2
2
|
|
|
3
|
-
import { authEnv } from '@/
|
|
3
|
+
import { authEnv } from '@/envs/auth';
|
|
4
4
|
|
|
5
5
|
import { getMicrosoftEntraIdIssuer } from './microsoft-entra-id-helper';
|
|
6
6
|
import { CommonProviderConfig } from './sso.config';
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { eq, sql } from 'drizzle-orm';
|
|
3
|
-
|
|
1
|
+
import { LobeChatDatabase } from '@lobechat/database';
|
|
4
2
|
import {
|
|
5
3
|
oidcAccessTokens,
|
|
6
4
|
oidcAuthorizationCodes,
|
|
@@ -10,8 +8,9 @@ import {
|
|
|
10
8
|
oidcInteractions,
|
|
11
9
|
oidcRefreshTokens,
|
|
12
10
|
oidcSessions,
|
|
13
|
-
} from '
|
|
14
|
-
import
|
|
11
|
+
} from '@lobechat/database/schemas';
|
|
12
|
+
import debug from 'debug';
|
|
13
|
+
import { eq, sql } from 'drizzle-orm';
|
|
15
14
|
|
|
16
15
|
// 创建 adapter 日志命名空间
|
|
17
16
|
const log = debug('lobe-oidc:adapter');
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import { LobeChatDatabase } from '@lobechat/database';
|
|
1
2
|
import debug from 'debug';
|
|
2
3
|
import Provider, { Configuration, KoaContextWithOIDC, errors } from 'oidc-provider';
|
|
3
4
|
import urlJoin from 'url-join';
|
|
4
5
|
|
|
5
6
|
import { serverDBEnv } from '@/config/db';
|
|
6
7
|
import { UserModel } from '@/database/models/user';
|
|
7
|
-
import { LobeChatDatabase } from '@/database/type';
|
|
8
8
|
import { appEnv } from '@/envs/app';
|
|
9
9
|
import { getJWKS } from '@/libs/oidc-provider/jwt';
|
|
10
10
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { LobeChatDatabase } from '@lobechat/database';
|
|
1
2
|
import { TRPCError } from '@trpc/server';
|
|
2
3
|
import debug from 'debug';
|
|
3
4
|
|
|
4
5
|
import { serverDBEnv } from '@/config/db';
|
|
5
6
|
import { UserModel } from '@/database/models/user';
|
|
6
|
-
import { LobeChatDatabase } from '@/database/type';
|
|
7
7
|
|
|
8
8
|
import { asyncTrpc } from './init';
|
|
9
9
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { LobeChatDatabase } from '@lobechat/database';
|
|
1
2
|
import { ClientSecretPayload } from '@lobechat/types';
|
|
2
3
|
import debug from 'debug';
|
|
3
4
|
import { NextRequest } from 'next/server';
|
|
4
5
|
|
|
5
6
|
import { LOBE_CHAT_AUTH_HEADER } from '@/const/auth';
|
|
6
|
-
import { LobeChatDatabase } from '@/database/type';
|
|
7
7
|
import { KeyVaultsGateKeeper } from '@/server/modules/KeyVaultsEncrypt';
|
|
8
8
|
|
|
9
9
|
const log = debug('lobe-async:context');
|
package/src/middleware.ts
CHANGED
|
@@ -5,11 +5,11 @@ import { NextRequest, NextResponse } from 'next/server';
|
|
|
5
5
|
import { UAParser } from 'ua-parser-js';
|
|
6
6
|
import urlJoin from 'url-join';
|
|
7
7
|
|
|
8
|
-
import { authEnv } from '@/config/auth';
|
|
9
8
|
import { OAUTH_AUTHORIZED } from '@/const/auth';
|
|
10
9
|
import { LOBE_LOCALE_COOKIE } from '@/const/locale';
|
|
11
10
|
import { LOBE_THEME_APPEARANCE } from '@/const/theme';
|
|
12
11
|
import { appEnv } from '@/envs/app';
|
|
12
|
+
import { authEnv } from '@/envs/auth';
|
|
13
13
|
import NextAuth from '@/libs/next-auth';
|
|
14
14
|
import { Locales } from '@/locales/resources';
|
|
15
15
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ModelProvider } from '@lobechat/model-runtime';
|
|
2
2
|
|
|
3
|
-
import { getLLMConfig } from '@/config/llm';
|
|
4
3
|
import * as ProviderCards from '@/config/modelProviders';
|
|
4
|
+
import { getLLMConfig } from '@/envs/llm';
|
|
5
5
|
import { ModelProviderCard } from '@/types/llm';
|
|
6
6
|
import { extractEnabledModels, transformToChatModelCards } from '@/utils/_deprecated/parseModels';
|
|
7
7
|
|
|
@@ -11,7 +11,7 @@ vi.mock('model-bank', async (importOriginal) => {
|
|
|
11
11
|
};
|
|
12
12
|
});
|
|
13
13
|
|
|
14
|
-
vi.mock('@/
|
|
14
|
+
vi.mock('@/envs/llm', () => ({
|
|
15
15
|
getLLMConfig: vi.fn(() => ({
|
|
16
16
|
ENABLED_OPENAI: true,
|
|
17
17
|
ENABLED_ANTHROPIC: false,
|
|
@@ -83,7 +83,7 @@ describe('genServerAiProvidersConfig', () => {
|
|
|
83
83
|
};
|
|
84
84
|
|
|
85
85
|
// Mock the LLM config to include our custom key
|
|
86
|
-
const { getLLMConfig } = vi.mocked(await import('@/
|
|
86
|
+
const { getLLMConfig } = vi.mocked(await import('@/envs/llm'));
|
|
87
87
|
getLLMConfig.mockReturnValue({
|
|
88
88
|
ENABLED_OPENAI: true,
|
|
89
89
|
ENABLED_ANTHROPIC: false,
|
|
@@ -4,7 +4,7 @@ import { extractEnabledModels, transformToAiModelList } from '@lobechat/utils';
|
|
|
4
4
|
import * as AiModels from 'model-bank';
|
|
5
5
|
import { AiFullModelCard } from 'model-bank';
|
|
6
6
|
|
|
7
|
-
import { getLLMConfig } from '@/
|
|
7
|
+
import { getLLMConfig } from '@/envs/llm';
|
|
8
8
|
|
|
9
9
|
interface ProviderSpecificConfig {
|
|
10
10
|
enabled?: boolean;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { authEnv } from '@/config/auth';
|
|
2
|
-
import { fileEnv } from '@/config/file';
|
|
3
1
|
import { enableNextAuth } from '@/const/auth';
|
|
4
2
|
import { isDesktop } from '@/const/version';
|
|
5
3
|
import { appEnv, getAppConfig } from '@/envs/app';
|
|
4
|
+
import { authEnv } from '@/envs/auth';
|
|
5
|
+
import { fileEnv } from '@/envs/file';
|
|
6
6
|
import { knowledgeEnv } from '@/envs/knowledge';
|
|
7
7
|
import { langfuseEnv } from '@/envs/langfuse';
|
|
8
8
|
import { parseSystemAgent } from '@/server/globalConfig/parseSystemAgent';
|
|
@@ -27,7 +27,7 @@ import { describe, expect, it, vi } from 'vitest';
|
|
|
27
27
|
import { initModelRuntimeWithUserPayload } from './index';
|
|
28
28
|
|
|
29
29
|
// 模拟依赖项
|
|
30
|
-
vi.mock('@/
|
|
30
|
+
vi.mock('@/envs/llm', () => ({
|
|
31
31
|
getLLMConfig: vi.fn(() => ({
|
|
32
32
|
// 确保为每个provider提供必要的配置信息
|
|
33
33
|
OPENAI_API_KEY: 'test-openai-key',
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ModelProvider, ModelRuntime } from '@lobechat/model-runtime';
|
|
2
2
|
import { ClientSecretPayload } from '@lobechat/types';
|
|
3
3
|
|
|
4
|
-
import { getLLMConfig } from '@/
|
|
4
|
+
import { getLLMConfig } from '@/envs/llm';
|
|
5
5
|
|
|
6
6
|
import apiKeyManager from './apiKeyManager';
|
|
7
7
|
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
|
|
9
9
|
import { z } from 'zod';
|
|
10
10
|
|
|
11
|
-
import { fileEnv } from '@/
|
|
11
|
+
import { fileEnv } from '@/envs/file';
|
|
12
12
|
import { YEAR } from '@/utils/units';
|
|
13
13
|
import { inferContentTypeFromImageUrl } from '@/utils/url';
|
|
14
14
|
|
|
@@ -4,13 +4,13 @@ import pMap from 'p-map';
|
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
|
|
6
6
|
import { serverDBEnv } from '@/config/db';
|
|
7
|
-
import { fileEnv } from '@/config/file';
|
|
8
7
|
import { DEFAULT_FILE_EMBEDDING_MODEL_ITEM } from '@/const/settings/knowledge';
|
|
9
8
|
import { ASYNC_TASK_TIMEOUT, AsyncTaskModel } from '@/database/models/asyncTask';
|
|
10
9
|
import { ChunkModel } from '@/database/models/chunk';
|
|
11
10
|
import { EmbeddingModel } from '@/database/models/embedding';
|
|
12
11
|
import { FileModel } from '@/database/models/file';
|
|
13
12
|
import { NewChunkItem, NewEmbeddingsItem } from '@/database/schemas';
|
|
13
|
+
import { fileEnv } from '@/envs/file';
|
|
14
14
|
import { asyncAuthedProcedure, asyncRouter as router } from '@/libs/trpc/async';
|
|
15
15
|
import { getServerDefaultFilesConfig } from '@/server/globalConfig';
|
|
16
16
|
import { initModelRuntimeWithUserPayload } from '@/server/modules/ModelRuntime';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { LobeChatDatabase } from '@lobechat/database';
|
|
2
|
+
|
|
1
3
|
import { SessionModel } from '@/database/models/session';
|
|
2
|
-
import { LobeChatDatabase } from '@/database/type';
|
|
3
4
|
import { getServerDefaultAgentConfig } from '@/server/globalConfig';
|
|
4
5
|
|
|
5
6
|
export class AgentService {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { LobeChatDatabase } from '@lobechat/database';
|
|
1
2
|
import { describe, expect, it, vi } from 'vitest';
|
|
2
3
|
|
|
3
4
|
import { MessageModel } from '@/database/models/message';
|
|
4
5
|
import { TopicModel } from '@/database/models/topic';
|
|
5
|
-
import { LobeChatDatabase } from '@/database/type';
|
|
6
6
|
import { FileService } from '@/server/services/file';
|
|
7
7
|
|
|
8
8
|
import { AiChatService } from '.';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { LobeChatDatabase } from '@lobechat/database';
|
|
2
|
+
|
|
1
3
|
import { MessageModel } from '@/database/models/message';
|
|
2
4
|
import { TopicModel } from '@/database/models/topic';
|
|
3
|
-
import { LobeChatDatabase } from '@/database/type';
|
|
4
5
|
import { FileService } from '@/server/services/file';
|
|
5
6
|
|
|
6
7
|
export class AiChatService {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { LobeChatDatabase } from '@lobechat/database';
|
|
1
2
|
import { ClientSecretPayload } from '@lobechat/types';
|
|
2
3
|
|
|
3
4
|
import { AsyncTaskModel } from '@/database/models/asyncTask';
|
|
4
5
|
import { FileModel } from '@/database/models/file';
|
|
5
|
-
import { LobeChatDatabase } from '@/database/type';
|
|
6
6
|
import { ChunkContentParams, ContentChunk } from '@/server/modules/ContentChunk';
|
|
7
7
|
import { createAsyncCaller } from '@/server/routers/async';
|
|
8
8
|
import {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { LobeChatDatabase } from '@lobechat/database';
|
|
1
2
|
import { loadFile } from '@lobechat/file-loaders';
|
|
2
3
|
import debug from 'debug';
|
|
3
4
|
|
|
4
5
|
import { DocumentModel } from '@/database/models/document';
|
|
5
6
|
import { FileModel } from '@/database/models/file';
|
|
6
|
-
import { LobeChatDatabase } from '@/database/type';
|
|
7
7
|
import { LobeDocument } from '@/types/document';
|
|
8
8
|
|
|
9
9
|
import { FileService } from '../file';
|
|
@@ -10,7 +10,7 @@ const config = {
|
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
// 模拟 fileEnv
|
|
13
|
-
vi.mock('@/
|
|
13
|
+
vi.mock('@/envs/file', () => ({
|
|
14
14
|
get fileEnv() {
|
|
15
15
|
return config;
|
|
16
16
|
},
|
|
@@ -71,12 +71,12 @@ describe('S3StaticFileImpl', () => {
|
|
|
71
71
|
it('should handle full URL input by extracting key (S3_SET_ACL=false)', async () => {
|
|
72
72
|
config.S3_SET_ACL = false;
|
|
73
73
|
const fullUrl = 'https://s3.example.com/bucket/path/to/file.jpg?X-Amz-Signature=expired';
|
|
74
|
-
|
|
74
|
+
|
|
75
75
|
// Mock getKeyFromFullUrl to return the extracted key
|
|
76
76
|
vi.spyOn(fileService, 'getKeyFromFullUrl').mockReturnValue('path/to/file.jpg');
|
|
77
|
-
|
|
77
|
+
|
|
78
78
|
const result = await fileService.getFullFileUrl(fullUrl);
|
|
79
|
-
|
|
79
|
+
|
|
80
80
|
expect(fileService.getKeyFromFullUrl).toHaveBeenCalledWith(fullUrl);
|
|
81
81
|
expect(result).toBe('https://presigned.example.com/test.jpg');
|
|
82
82
|
config.S3_SET_ACL = true;
|
|
@@ -84,33 +84,33 @@ describe('S3StaticFileImpl', () => {
|
|
|
84
84
|
|
|
85
85
|
it('should handle full URL input by extracting key (S3_SET_ACL=true)', async () => {
|
|
86
86
|
const fullUrl = 'https://s3.example.com/bucket/path/to/file.jpg';
|
|
87
|
-
|
|
87
|
+
|
|
88
88
|
vi.spyOn(fileService, 'getKeyFromFullUrl').mockReturnValue('path/to/file.jpg');
|
|
89
|
-
|
|
89
|
+
|
|
90
90
|
const result = await fileService.getFullFileUrl(fullUrl);
|
|
91
|
-
|
|
91
|
+
|
|
92
92
|
expect(fileService.getKeyFromFullUrl).toHaveBeenCalledWith(fullUrl);
|
|
93
93
|
expect(result).toBe('https://example.com/path/to/file.jpg');
|
|
94
94
|
});
|
|
95
95
|
|
|
96
96
|
it('should handle normal key input without extraction', async () => {
|
|
97
97
|
const key = 'path/to/file.jpg';
|
|
98
|
-
|
|
98
|
+
|
|
99
99
|
const spy = vi.spyOn(fileService, 'getKeyFromFullUrl');
|
|
100
|
-
|
|
100
|
+
|
|
101
101
|
const result = await fileService.getFullFileUrl(key);
|
|
102
|
-
|
|
102
|
+
|
|
103
103
|
expect(spy).not.toHaveBeenCalled();
|
|
104
104
|
expect(result).toBe('https://example.com/path/to/file.jpg');
|
|
105
105
|
});
|
|
106
106
|
|
|
107
107
|
it('should handle http:// URLs for legacy compatibility', async () => {
|
|
108
108
|
const httpUrl = 'http://s3.example.com/bucket/path/to/file.jpg';
|
|
109
|
-
|
|
109
|
+
|
|
110
110
|
vi.spyOn(fileService, 'getKeyFromFullUrl').mockReturnValue('path/to/file.jpg');
|
|
111
|
-
|
|
111
|
+
|
|
112
112
|
const result = await fileService.getFullFileUrl(httpUrl);
|
|
113
|
-
|
|
113
|
+
|
|
114
114
|
expect(fileService.getKeyFromFullUrl).toHaveBeenCalledWith(httpUrl);
|
|
115
115
|
expect(result).toBe('https://example.com/path/to/file.jpg');
|
|
116
116
|
});
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { LobeChatDatabase } from '@lobechat/database';
|
|
1
2
|
import { TRPCError } from '@trpc/server';
|
|
2
3
|
|
|
3
4
|
import { serverDBEnv } from '@/config/db';
|
|
4
5
|
import { FileModel } from '@/database/models/file';
|
|
5
6
|
import { FileItem } from '@/database/schemas';
|
|
6
|
-
import { LobeChatDatabase } from '@/database/type';
|
|
7
7
|
import { TempFileManager } from '@/server/utils/tempFileManager';
|
|
8
8
|
import { nanoid } from '@/utils/uuid';
|
|
9
9
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { LobeChatDatabase } from '@lobechat/database';
|
|
1
2
|
import { parseDataUri } from '@lobechat/model-runtime';
|
|
2
3
|
import debug from 'debug';
|
|
3
4
|
import { sha256 } from 'js-sha256';
|
|
@@ -6,7 +7,6 @@ import { IMAGE_GENERATION_CONFIG } from 'model-bank';
|
|
|
6
7
|
import { nanoid } from 'nanoid';
|
|
7
8
|
import sharp from 'sharp';
|
|
8
9
|
|
|
9
|
-
import { LobeChatDatabase } from '@/database/type';
|
|
10
10
|
import { FileService } from '@/server/services/file';
|
|
11
11
|
import { calculateThumbnailDimensions } from '@/utils/number';
|
|
12
12
|
import { getYYYYmmddHHMMss } from '@/utils/time';
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { LobeChatDatabase } from '@lobechat/database';
|
|
1
2
|
import { and, eq } from 'drizzle-orm';
|
|
2
3
|
import { Adapter, AdapterAccount } from 'next-auth/adapters';
|
|
3
4
|
import { NextResponse } from 'next/server';
|
|
@@ -11,7 +12,6 @@ import {
|
|
|
11
12
|
nextauthVerificationTokens,
|
|
12
13
|
users,
|
|
13
14
|
} from '@/database/schemas';
|
|
14
|
-
import { LobeChatDatabase } from '@/database/type';
|
|
15
15
|
import { pino } from '@/libs/logger';
|
|
16
16
|
import { merge } from '@/utils/merge';
|
|
17
17
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { UserJSON } from '@clerk/backend';
|
|
2
|
+
import { LobeChatDatabase } from '@lobechat/database';
|
|
2
3
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
4
|
|
|
4
5
|
import { UserModel } from '@/database/models/user';
|
|
5
6
|
import { UserItem } from '@/database/schemas';
|
|
6
|
-
import { LobeChatDatabase } from '@/database/type';
|
|
7
7
|
import { pino } from '@/libs/logger';
|
|
8
8
|
import { AgentService } from '@/server/services/agent';
|
|
9
9
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { UserJSON } from '@clerk/backend';
|
|
2
|
+
import { LobeChatDatabase } from '@lobechat/database';
|
|
2
3
|
|
|
3
4
|
import { UserModel } from '@/database/models/user';
|
|
4
|
-
import { LobeChatDatabase } from '@/database/type';
|
|
5
5
|
import { initializeServerAnalytics } from '@/libs/analytics';
|
|
6
6
|
import { pino } from '@/libs/logger';
|
|
7
7
|
import { KeyVaultsGateKeeper } from '@/server/modules/KeyVaultsEncrypt';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
2
|
|
|
3
|
-
import { fileEnv } from '@/
|
|
3
|
+
import { fileEnv } from '@/envs/file';
|
|
4
4
|
import { edgeClient } from '@/libs/trpc/client';
|
|
5
5
|
import { API_ENDPOINTS } from '@/services/_url';
|
|
6
6
|
import { clientS3Storage } from '@/services/file/ClientS3';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Mock, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
2
|
|
|
3
|
-
import { fileEnv } from '@/config/file';
|
|
4
3
|
import { FileModel } from '@/database/_deprecated/models/file';
|
|
5
4
|
import { DB_File } from '@/database/_deprecated/schemas/files';
|
|
5
|
+
import { fileEnv } from '@/envs/file';
|
|
6
6
|
import { clientS3Storage } from '@/services/file/ClientS3';
|
|
7
7
|
import { serverConfigSelectors } from '@/store/serverConfig/selectors';
|
|
8
8
|
import { createServerConfigStore } from '@/store/serverConfig/store';
|
package/src/services/upload.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { uuid } from '@lobechat/utils';
|
|
|
4
4
|
import dayjs from 'dayjs';
|
|
5
5
|
import { sha256 } from 'js-sha256';
|
|
6
6
|
|
|
7
|
-
import { fileEnv } from '@/
|
|
7
|
+
import { fileEnv } from '@/envs/file';
|
|
8
8
|
import { edgeClient } from '@/libs/trpc/client';
|
|
9
9
|
import { API_ENDPOINTS } from '@/services/_url';
|
|
10
10
|
import { clientS3Storage } from '@/services/file/ClientS3';
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|